[12/13] Document "no debug info debugging" improvements

Message ID 1499912370-1842-14-git-send-email-palves@redhat.com
State New, archived
Headers

Commit Message

Pedro Alves July 13, 2017, 2:19 a.m. UTC
  Here's the documentation bits for all the improvements.  The original
"weak alias functions" paragraph ends up disappearing, because this
other patch, which I'm considering kind of part of this series, makes the
alias case Just Work:
  https://sourceware.org/ml/gdb-patches/2017-07/msg00018.html

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* NEWS (Safer support for debugging with no debug info): New.

gdb/doc/ChangeLog:
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* gdb.texinfo (Variables): Document inspecting no-debug-info
	variables.
	(Symbols): Document inspecting no-debug-info types.
	(Calling): Document calling no-debug-info functions.
---
 gdb/doc/gdb.texinfo | 90 +++++++++++++++++++++++++++++++++++++++++++++++------
 gdb/NEWS            | 24 ++++++++++++++
 2 files changed, 104 insertions(+), 10 deletions(-)
  

Comments

Pedro Alves July 13, 2017, 11:09 a.m. UTC | #1
On 07/13/2017 03:19 AM, Pedro Alves wrote:

> +Sometimes, a function you wish to call is missing debug information.
> +In such case, @value{GDBN} does not know the type of the function,
> +including the types of the function's parameters.  To avoid calling
> +the inferior function incorrectly, which could result in the called
> +function functioning erroneously and even crash, @value{GDBN} refuses
> +to call the function unless you tell it at least the return type of
> +the function, with a cast.  For example:
> +
> +@smallexample
> +  (@value{GDBP}) p getenv ("PATH")
> +  'getenv' has unknown return type; cast the call to its declared return type
> +  (@value{GDBP}) p (char *) getenv ("PATH")
> +  $1 = 0x7fffffffe7ba "/usr/local/bin:/"...
> +@end smallexample
> +
> +Casting the return type of the function is equivalent to casting the
> +function to a pointer to an unprototyped function, and calling that:
> +
> +@smallexample
> +  (@value{GDBP}) p ((char * (*) ()) getenv) ("PATH")
> +  $2 = 0x7fffffffe7ba "/usr/local/bin:/"...
> +@end smallexample

I woke up thinking that mapping to unprototyped is the wrong
equivalence -- that it'd be better to assume the function is
prototyped, since that's how most C functions are written as
nowadays.  Also, there's no such thing as an unprototyped
function in C++.

Assuming prototyped would allow this, for example:

    float mult (float v1, float v2) { return v1 * v2; }

    (gdb) p (float) mult (2.0f, 3.0f)
    $1 = 6
    (gdb) p (float) mult ((float) 2, (float) 3)
    $2 = 6
    (gdb) p ((float (*) (float, float)) mult) (2, 3)
    $3 = 6

    (gdb) ptype 2.0f
    type = float
    (gdb) ptype 2.0
    type = double

If the function really is unprototyped, then you'd still be
able to call it correctly via the function pointer cast syntax:

    float mult_noproto (v1, v2)
       float v1, v2;
    { return v1 * v2; }

    (gdb) p ((float (*) ()) mult_noproto) (2.0f, 3.0f)
    $1 = 6
    (gdb) p ((float (*) ()) mult_noproto) (2.0, 3.0)
    $2 = 6
    (gdb) p ((float (*) ()) mult_noproto) ((float) 2, (float) 3)
    $3 = 6

I'll give this a try, and add those as tests to gdb.base/nodebug.exp.

> +
> +If the function you wish to call is declared as prototyped and has
> +floating point parameters or integer parameters narrower than int, you
> +may need to cast the function to a function pointer of the same type
> +as the function and call that, to avoid @value{GDBN} coercing
> +arguments to integer/double, as would be required if calling an
> +unprototyped function.  @xref{ABI, float promotion}.  For example,
> +given this prototyped (i.e.@: ANSI/ISO style) function:

This paragraph will need adjustment.

Thanks,
Pedro Alves
  
Pedro Alves July 13, 2017, 1:51 p.m. UTC | #2
On 07/13/2017 12:09 PM, Pedro Alves wrote:

> I woke up thinking that mapping to unprototyped is the wrong
> equivalence -- that it'd be better to assume the function is
> prototyped, since that's how most C functions are written as
> nowadays.  Also, there's no such thing as an unprototyped
> function in C++.
> 
> Assuming prototyped would allow this, for example:
> 
>     float mult (float v1, float v2) { return v1 * v2; }
> 
>     (gdb) p (float) mult (2.0f, 3.0f)
>     $1 = 6
>     (gdb) p (float) mult ((float) 2, (float) 3)
>     $2 = 6
>     (gdb) p ((float (*) (float, float)) mult) (2, 3)
>     $3 = 6
> 
>     (gdb) ptype 2.0f
>     type = float
>     (gdb) ptype 2.0
>     type = double
> 
> If the function really is unprototyped, then you'd still be
> able to call it correctly via the function pointer cast syntax:
> 
>     float mult_noproto (v1, v2)
>        float v1, v2;
>     { return v1 * v2; }
> 
>     (gdb) p ((float (*) ()) mult_noproto) (2.0f, 3.0f)
>     $1 = 6
>     (gdb) p ((float (*) ()) mult_noproto) (2.0, 3.0)
>     $2 = 6
>     (gdb) p ((float (*) ()) mult_noproto) ((float) 2, (float) 3)
>     $3 = 6
> 
> I'll give this a try, and add those as tests to gdb.base/nodebug.exp.

This worked nicely, see below.

I'll tweak the docs, and send an updated patch.

Thanks,
Pedro Alves
  
Eli Zaretskii July 13, 2017, 3:47 p.m. UTC | #3
> From: Pedro Alves <palves@redhat.com>
> Date: Thu, 13 Jul 2017 03:19:30 +0100
> 
> Here's the documentation bits for all the improvements.  The original
> "weak alias functions" paragraph ends up disappearing, because this
> other patch, which I'm considering kind of part of this series, makes the
> alias case Just Work:
>   https://sourceware.org/ml/gdb-patches/2017-07/msg00018.html
> 
> gdb/ChangeLog:
> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
> 
> 	* NEWS (Safer support for debugging with no debug info): New.
> 
> gdb/doc/ChangeLog:
> yyyy-mm-dd  Pedro Alves  <palves@redhat.com>
> 
> 	* gdb.texinfo (Variables): Document inspecting no-debug-info
> 	variables.
> 	(Symbols): Document inspecting no-debug-info types.
> 	(Calling): Document calling no-debug-info functions.

Thanks, this is okay with a minor comment:

> +includes no debug information, @value{GDBN} says @w{@samp{'var' has
> +unknown type; cast it to its declared type}}.  @xref{Symbols, unknown
> +type}, for more about unknown types.  If you cast the variable to its
> +declared type, @value{GDBN} gets the variable's value using the
> +cast-to type as the variable's type.  For example, in a C program:
> +
> +@smallexample
> +  (@value{GDBP}) p var
> +  'var' has unknown type; cast it to its declared type
> +  (@value{GDBP}) p (float) var
> +  $1 = 3.14
> +@end smallexample

Since you have an example showing the error message, repeating that in
the text is redundant.  Moreover, it will almost certainly cause an
overfull hbox.  Instead, I would just say

  If you try to inspect the type of a (global) variable for which
  @value{GDBN} has no type information, @value{GDBN} displays an error
  message.

> +@cindex unknown type
> +Othertimes, information about a variable's type is completely absent
> +from the debug information included in the program.  This most often
> +happens when the program or library where the variable is defined
> +includes no debug information at all.  @value{GDBN} knows the variable
> +exists from inspecting the linker/loader symbol table (e.g., the ELF
> +dynamic symbol table), but such symbols do not contain type
> +information.  If you try to inspect the type of a (global) variable
> +for which @value{GDBN} has no type information, @value{GDBN} says
> +@w{@samp{<data variable, no debug info>}}.  For example:

Same here.
  
Pedro Alves July 13, 2017, 4:14 p.m. UTC | #4
On 07/13/2017 04:47 PM, Eli Zaretskii wrote:

> Thanks, this is okay with a minor comment:
> 
>> +includes no debug information, @value{GDBN} says @w{@samp{'var' has
>> +unknown type; cast it to its declared type}}.  @xref{Symbols, unknown
>> +type}, for more about unknown types.  If you cast the variable to its
>> +declared type, @value{GDBN} gets the variable's value using the
>> +cast-to type as the variable's type.  For example, in a C program:
>> +
>> +@smallexample
>> +  (@value{GDBP}) p var
>> +  'var' has unknown type; cast it to its declared type
>> +  (@value{GDBP}) p (float) var
>> +  $1 = 3.14
>> +@end smallexample
> 
> Since you have an example showing the error message, repeating that in
> the text is redundant.  Moreover, it will almost certainly cause an
> overfull hbox.  Instead, I would just say
> 
>   If you try to inspect the type of a (global) variable for which
>   @value{GDBN} has no type information, @value{GDBN} displays an error
>   message.
> 

...

> Same here.

Thanks, good idea.  Meanwhile, the v2 of the docs are a bit
different in the "calling functions" part since they describe different
behavior.  I'll apply that change to the v2 version, and resend it.

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c167a86..5ac072e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9114,6 +9114,22 @@  If you ask to print an object whose contents are unknown to
 by the debug information, @value{GDBN} will say @samp{<incomplete
 type>}.  @xref{Symbols, incomplete type}, for more about this.
 
+@cindex no debug info variables
+If you try to examine or use the value of a (global) variable for
+which @value{GDBN} has no type information, e.g., because the program
+includes no debug information, @value{GDBN} says @w{@samp{'var' has
+unknown type; cast it to its declared type}}.  @xref{Symbols, unknown
+type}, for more about unknown types.  If you cast the variable to its
+declared type, @value{GDBN} gets the variable's value using the
+cast-to type as the variable's type.  For example, in a C program:
+
+@smallexample
+  (@value{GDBP}) p var
+  'var' has unknown type; cast it to its declared type
+  (@value{GDBP}) p (float) var
+  $1 = 3.14
+@end smallexample
+
 If you append @kbd{@@entry} string to a function parameter name you get its
 value at the time the function got called.  If the value is not available an
 error message is printed.  Entry values are available only with some compilers.
@@ -17083,6 +17099,25 @@  but no definition for @code{struct foo} itself, @value{GDBN} will say:
 ``Incomplete type'' is C terminology for data types that are not
 completely specified.
 
+@cindex unknown type
+Othertimes, information about a variable's type is completely absent
+from the debug information included in the program.  This most often
+happens when the program or library where the variable is defined
+includes no debug information at all.  @value{GDBN} knows the variable
+exists from inspecting the linker/loader symbol table (e.g., the ELF
+dynamic symbol table), but such symbols do not contain type
+information.  If you try to inspect the type of a (global) variable
+for which @value{GDBN} has no type information, @value{GDBN} says
+@w{@samp{<data variable, no debug info>}}.  For example:
+
+@smallexample
+  (@value{GDBP}) ptype var
+  type = <data variable, no debug info>
+@end smallexample
+
+@xref{Variables, no debug info variables}, for how to print the values
+of such variables.
+
 @kindex info types
 @item info types @var{regexp}
 @itemx info types
@@ -17798,14 +17833,49 @@  Show the current setting of stack unwinding in the functions called by
 
 @end table
 
-@cindex weak alias functions
-Sometimes, a function you wish to call is actually a @dfn{weak alias}
-for another function.  In such case, @value{GDBN} might not pick up
-the type information, including the types of the function arguments,
-which causes @value{GDBN} to call the inferior function incorrectly.
-As a result, the called function will function erroneously and may
-even crash.  A solution to that is to use the name of the aliased
-function instead.
+@cindex no debug info functions
+Sometimes, a function you wish to call is missing debug information.
+In such case, @value{GDBN} does not know the type of the function,
+including the types of the function's parameters.  To avoid calling
+the inferior function incorrectly, which could result in the called
+function functioning erroneously and even crash, @value{GDBN} refuses
+to call the function unless you tell it at least the return type of
+the function, with a cast.  For example:
+
+@smallexample
+  (@value{GDBP}) p getenv ("PATH")
+  'getenv' has unknown return type; cast the call to its declared return type
+  (@value{GDBP}) p (char *) getenv ("PATH")
+  $1 = 0x7fffffffe7ba "/usr/local/bin:/"...
+@end smallexample
+
+Casting the return type of the function is equivalent to casting the
+function to a pointer to an unprototyped function, and calling that:
+
+@smallexample
+  (@value{GDBP}) p ((char * (*) ()) getenv) ("PATH")
+  $2 = 0x7fffffffe7ba "/usr/local/bin:/"...
+@end smallexample
+
+If the function you wish to call is declared as prototyped and has
+floating point parameters or integer parameters narrower than int, you
+may need to cast the function to a function pointer of the same type
+as the function and call that, to avoid @value{GDBN} coercing
+arguments to integer/double, as would be required if calling an
+unprototyped function.  @xref{ABI, float promotion}.  For example,
+given this prototyped (i.e.@: ANSI/ISO style) function:
+
+@smallexample
+    float multiply (float v1, float v2) @{ return v1 * v2; @}
+@end smallexample
+
+@noindent
+call it like this:
+
+@smallexample
+  (@value{GDBP}) p ((float (*) (float, float)) multiply) (2, 3.5)
+  $1 = 7
+@end smallexample
 
 @node Patching
 @section Patching Programs
@@ -21792,12 +21862,12 @@  problem:
 
 @smallexample
 (@value{GDBP}) print 'cygwin1!__argv'
-$1 = 268572168
+'cygwin1!__argv' has unknown type; cast it to its declared type
 @end smallexample
 
 @smallexample
 (@value{GDBP}) x 'cygwin1!__argv'
-0x10021610:      "\230y\""
+'cygwin1!__argv' has unknown type; cast it to its declared type
 @end smallexample
 
 And two possible solutions:
diff --git a/gdb/NEWS b/gdb/NEWS
index 7c8a8f6..ce71ec0 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -23,6 +23,30 @@  set debug separate-debug-file
 show debug separate-debug-file
   Control the display of debug output about separate debug file search.
 
+* Safer support for debugging with no debug info
+
+  GDB no longer assumes functions with no debug information
+  information return 'int'.
+
+  This means that GDB now refuses the call such functions unless you
+  tell it the function's type, with a cast:
+
+    (gdb) p getenv ("PATH")
+    'getenv' has unknown return type; cast the call to its declared return type
+    (gdb) p (char *) getenv ("PATH")
+    $1 = 0x7fffffffe "/usr/local/bin:/"...
+    (gdb) p ((char * (*) (const char *)) getenv) ("PATH")
+    $2 = 0x7fffffffe "/usr/local/bin:/"...
+
+  Similarly, GDB no longer assumes that global variables with no debug
+  info have type 'int', and refuses to print the variable's value
+  unless you tell it the variable's type:
+
+    (gdb) p var
+    'var' has unknown type; cast it to its declared type
+    (gdb) p (float) var
+    $3 = 3.14
+
 *** Changes in GDB 8.0
 
 * GDB now supports access to the PKU register on GNU/Linux. The register is