public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* compile: objfiles lifetime UI
@ 2015-04-29 13:57 Jan Kratochvil
  2015-04-30 10:31 ` Phil Muldoon
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2015-04-29 13:57 UTC (permalink / raw)
  To: gdb; +Cc: Phil Muldoon

Hi,

posting first for an approval CLI UI for managing objfiles currently in
inferior for the 'compile' command.

With each injected code is associated:
 * infcall dummy frame - deleted when the code returns or when user interrupts
   the code and 'return's from it in CLI.
 * objfile - deleted when the dummy frame is deleted
 * inferior mmap()ped memory - currently leaked in inferior forever
   - prepared in a local patchset: deleted when the objfile is deleted
 * inferior malloc()ed memory - only from the posted 'compile print' command
   - in the posted 'compile print' command: deleted when the objfile is deleted

The mmap leak was intentional so that one can do for example:
inferior:
	char *str = "foo";
GDB:
	(gdb) compile code str = "bar";

Now there should be a way to delete everything by default (so that a loop with
'compile print' command will not run the inferior out of memory) but to have
a way to keep the memory alive (so that for example strings can be set) or
even to keep the objfile alive (so that for example a callback function can be
set which may crash so that we want to keep DWARF loaded for the callback
function).

What CLI should be there for it?

(gdB) info compile-files
Num Address Range                           Frame Name
1   0x00007ffff7ff3000 - 0x00007ffff7ff5000 -     file test.c
2   0x00007ffff7ff9000 - 0x00007ffff7ffb000 #0    code puts("hello wor...
(gdb) delete compile-file 1
(gdb) delete compile-file 2
compile-file #2 dummy frame is still valid, use 'return' command to delete it.
(gdb) bt
#0  0x00007ffff7ff9021 in _gdb_expr (__regs=0x7ffff7ff7000) at gdb command line:1
#1  <function called from gdb>
#2  main () at ./gdb.compile/compile-print.c:31
(gdB) info compile-files
Num Address Range                           Frame Name
2   0x0000003834603da0 - 0x0000003834603dc0 #0    code puts("hello wor...


Jan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: compile: objfiles lifetime UI
  2015-04-29 13:57 compile: objfiles lifetime UI Jan Kratochvil
@ 2015-04-30 10:31 ` Phil Muldoon
  2015-04-30 10:53   ` Jan Kratochvil
  0 siblings, 1 reply; 6+ messages in thread
From: Phil Muldoon @ 2015-04-30 10:31 UTC (permalink / raw)
  To: Jan Kratochvil, gdb

On 29/04/15 14:57, Jan Kratochvil wrote:
> Hi,
>
> posting first for an approval CLI UI for managing objfiles currently in
> inferior for the 'compile' command.
>
> With each injected code is associated:
>  * infcall dummy frame - deleted when the code returns or when user interrupts
>    the code and 'return's from it in CLI.
>  * objfile - deleted when the dummy frame is deleted
>  * inferior mmap()ped memory - currently leaked in inferior forever
>    - prepared in a local patchset: deleted when the objfile is deleted
>  * inferior malloc()ed memory - only from the posted 'compile print' command
>    - in the posted 'compile print' command: deleted when the objfile is deleted
>
> The mmap leak was intentional so that one can do for example:
> inferior:
>     char *str = "foo";
> GDB:
>     (gdb) compile code str = "bar";
>
> Now there should be a way to delete everything by default (so that a loop with
> 'compile print' command will not run the inferior out of memory) but to have
> a way to keep the memory alive (so that for example strings can be set) or
> even to keep the objfile alive (so that for example a callback function can be
> set which may crash so that we want to keep DWARF loaded for the callback
> function).
>

I'm not sure we need a UI at all? I suppose I am trying to think of a
reason why the user would want to manage an object's life-cycle, and
not let GDB dispose of it according to the following rules:

    * Object files involved in an expression should be discarded after
      the expression evaluation;

    * Object files created by the "compile code" command should be
      discarded after the execution of the injected code;

    * Object files created by "fast" breakpoints (where the evaluation
      of whether the inferior should be stopped is determined by the
      return value of an injected piece of code) should be deleted
      when the breakpoint is deleted.

Of the three examples above, only the last requires the object file to
be held for an indefinite time. Note I am not against a user interface,
I just want to envision when a user would need to use it.

Cheers

Phil

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: compile: objfiles lifetime UI
  2015-04-30 10:31 ` Phil Muldoon
@ 2015-04-30 10:53   ` Jan Kratochvil
  2015-05-06 12:26     ` Jan Kratochvil
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2015-04-30 10:53 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: gdb

On Thu, 30 Apr 2015 12:30:59 +0200, Phil Muldoon wrote:
> I'm not sure we need a UI at all? I suppose I am trying to think of a
> reason why the user would want to manage an object's life-cycle, and
> not let GDB dispose of it according to the following rules:
> 
>     * Object files involved in an expression should be discarded after
>       the expression evaluation;
> 
>     * Object files created by the "compile code" command should be
>       discarded after the execution of the injected code;
> 
>     * Object files created by "fast" breakpoints (where the evaluation
>       of whether the inferior should be stopped is determined by the
>       return value of an injected piece of code) should be deleted
>       when the breakpoint is deleted.
> 
> Of the three examples above, only the last requires the object file to
> be held for an indefinite time. Note I am not against a user interface,
> I just want to envision when a user would need to use it.

What about that 2nd case example of:
	(gdb) compile code str = "bar";
That can be also typed as the 1st case:
	(gdb) compile print str = "bar"
Obviously "bar" remains the GDB-mmap()ed memory.  For C++ one will be able to
similarly assign whole new objects residing in the GDB-mmap()ed memory.

This is all a light variant of the possible far future feature "fix&continue",
that one tries to modify the inferior's behavior some way and continue its
execution.


Jan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: compile: objfiles lifetime UI
  2015-04-30 10:53   ` Jan Kratochvil
@ 2015-05-06 12:26     ` Jan Kratochvil
  2015-05-07  2:53       ` Alexandre Oliva
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2015-05-06 12:26 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: gdb, Alexandre Oliva

On Thu, 30 Apr 2015 12:53:49 +0200, Jan Kratochvil wrote:
> What about that 2nd case example of:
> 	(gdb) compile code str = "bar";
> That can be also typed as the 1st case:
> 	(gdb) compile print str = "bar"
> Obviously "bar" remains the GDB-mmap()ed memory.

Maybe it would be best if GCC can report whether the compiled code exposes
address to its internal object outside - such as by such an assignment or by
passing such a pointer to some external function.  I expect some scan of the
IR (intermediate representation - RTL/GIMPLE?) would be sufficient.

IMO for 99% of such compiled code it will not happen and therefore GDB can
quietly and safely discard such injected objfile from the inferior.

It is questionable how many false positives would such a scan-for-address-of
make.


Jan

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: compile: objfiles lifetime UI
  2015-05-06 12:26     ` Jan Kratochvil
@ 2015-05-07  2:53       ` Alexandre Oliva
  2015-05-07 17:06         ` Jan Kratochvil
  0 siblings, 1 reply; 6+ messages in thread
From: Alexandre Oliva @ 2015-05-07  2:53 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Phil Muldoon, gdb

On May  6, 2015, Jan Kratochvil <jan.kratochvil@redhat.com> wrote:

> On Thu, 30 Apr 2015 12:53:49 +0200, Jan Kratochvil wrote:
>> What about that 2nd case example of:
>> (gdb) compile code str = "bar";
>> That can be also typed as the 1st case:
>> (gdb) compile print str = "bar"
>> Obviously "bar" remains the GDB-mmap()ed memory.

> Maybe it would be best if GCC can report whether the compiled code exposes
> address to its internal object outside - such as by such an assignment or by
> passing such a pointer to some external function.  I expect some scan of the
> IR (intermediate representation - RTL/GIMPLE?) would be sufficient.

There is some pointer escaping analysis that could be repurposed to that
end in GCC.  -Wreturn-local-addr is surely not enough to cover assigning
gdb-compile pointers to inferior variables, but a new warning to cover
more general pointer escaping to automatic variables might could be
useful on its own, with a small extension for user expressions for it to
apply to strings as well.

However, it's not clear where to draw the line when a (pointer to a)
string (literal) is passed to some inferior function.  Technically, it
is an escaping pointer, but printf won't save it, whereas add_to_list
will.  So we don't want it to be an error, at most a warning.

But then, wouldn't we be better served by teaching users to use strdup
in gdb-compile snippets when they wish to get strings preserved (and
permanently leaked) in the inferior?  Since we can't tell when it's ok
for a pointer to escape in relatively common and harmless cases (the
printf example above, any C++ function that takes a reference argument,
C++ non-static member functions), I think even a warning would quickly
become annoying due to the number of false positives.

Using memory allocation primitives of the inferior might be cumbersome,
but it will likely be learned fast, given how the failure to use them
would break the inferior.

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: compile: objfiles lifetime UI
  2015-05-07  2:53       ` Alexandre Oliva
@ 2015-05-07 17:06         ` Jan Kratochvil
  0 siblings, 0 replies; 6+ messages in thread
From: Jan Kratochvil @ 2015-05-07 17:06 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: Phil Muldoon, gdb

On Thu, 07 May 2015 04:53:37 +0200, Alexandre Oliva wrote:
> However, it's not clear where to draw the line when a (pointer to a)
> string (literal) is passed to some inferior function.  Technically, it
> is an escaping pointer, but printf won't save it, whereas add_to_list
> will.  So we don't want it to be an error, at most a warning.

OK, you are right that printf() would be the most common false positive.
printf() could be excepted but that is not much foolproof solution.


> But then, wouldn't we be better served by teaching users to use strdup
> in gdb-compile snippets when they wish to get strings preserved (and
> permanently leaked) in the inferior?

If GDB wants to at least catch up with LLDB then no.  In LLDB it just works.
And personally I do not think "teaching users" works anymore, if it does not
work out of the box the user will just use a better tool.

------------------------------------------------------------------------------
The most simple case in LLDB just works:
   1   	#include <stdio.h>
   2   	char *a;
   3   	int main(void) {
-> 4   	  puts(a);
   5   	return 0; }
(lldb) p a="foo"
(char *) $0 = 0x00007ffff7ff5000 "foo"
(lldb) c
Process 13050 resuming
foo
Process 13050 exited with status = 0 (0x00000000) 
------------------------------------------------------------------------------

This is because LLDB always keeps the last 'injected code' mapped.  But it is
only the last 'injected code' so a more complicated case no longer works:

------------------------------------------------------------------------------
   1   	#include <stdio.h>
   2   	char *a,*b;
   3   	int main(void) {
-> 4   	  puts(a); puts(b);
   5   	return 0; }
(lldb) p a="foo"
(char *) $0 = 0x00007ffff7ff5000 "foo"
(lldb) p b="bar"
(char *) $1 = 0x00007ffff7ff5000 "bar"
(lldb) c
Process 13135 resuming
bar
bar
Process 13135 exited with status = 0 (0x00000000) 
------------------------------------------------------------------------------

For that case one already needs to read 'help print' where LLDB has:
    User defined variables:
	You can define your own variables for convenience or to be used in
	subsequent expressions.  You define them the same way you would define
	variables in C.  If the first character of your user defined variable
	is a $, then the variable's value will be available in future
	expressions, otherwise it will just be available in the current
	expression.

So in LLDB one can do:

------------------------------------------------------------------------------
   1   	#include <stdio.h>
   2   	char *a,*b;
   3   	int main(void) {
-> 4   	  puts(a); puts(b);
   5   	return 0; }
(lldb) p char $a[]="foo";a=$a
(char *) $0 = 0x00007ffff7ff5030 "foo"
(lldb) p char $b[]="bar";b=$b
(char *) $1 = 0x00007ffff7ff5040 "bar"
(lldb) c
Process 13260 resuming
foo
bar
Process 13260 exited with status = 0 (0x00000000) 
------------------------------------------------------------------------------

Originally I wanted to make it even more automatic than the LLDB's $-variables
but that looks as not really possible by that IR analysis. So personally
I think GDB/GCC should do the same as LLDB so that the users are not forked
from how they are already used to LLDB.

Technically GCC could put the $ variables into some new section?


Jan

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-05-07 17:06 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-29 13:57 compile: objfiles lifetime UI Jan Kratochvil
2015-04-30 10:31 ` Phil Muldoon
2015-04-30 10:53   ` Jan Kratochvil
2015-05-06 12:26     ` Jan Kratochvil
2015-05-07  2:53       ` Alexandre Oliva
2015-05-07 17:06         ` Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).