Age | Commit message (Collapse) | Author | Files | Lines |
|
An earlier commit made GDB no longer assume no-debug-info functions
return int. This commit gives the same treatment to variables.
Currently, you can end misled by GDB over output like this:
(gdb) p var
$1 = -1
(gdb) p /x var
$2 = 0xffffffff
until you realize that GDB is assuming that the variable is an "int",
because:
(gdb) ptype var
type = <data variable, no debug info>
You may try to fix it by casting, but that doesn't really help:
(gdb) p /x (unsigned long long) var
$3 = 0xffffffffffffffff # incorrect
^^
That's incorrect output, because the variable was defined like this:
uint64_t var = 0x7fffffffffffffff;
^^
What happened is that with the cast, GDB did an int -> 'unsigned long
long' conversion instead of reinterpreting the variable as the cast-to
type. To get at the variable properly you have to reinterpret the
variable's address manually instead, with either:
(gdb) p /x *(unsigned long long *) &var
$4 = 0x7fffffffffffffff
(gdb) p /x {unsigned long long} &var
$5 = 0x7fffffffffffffff
After this commit GDB does it for you. This is what you'll get
instead:
(gdb) p var
'var' has unknown type; cast it to its declared type
(gdb) p /x (unsigned long long) var
$1 = 0x7fffffffffffffff
As in the functions patch, the "compile" machinery doesn't currently
have the cast-to type handy, so it continues assuming no-debug
variables have int type, though now at least it warns.
The change to gdb.cp/m-static.exp deserves an explanation:
- gdb_test "print 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \
+ gdb_test "print (int) 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \
That's printing the "sintvar" function local static of the
"gnu_obj_1::method()" method.
The problem with that test is that that "'S::method()::static_var'"
syntax doesn't really work in C++ as you'd expect. The way to make it
work correctly currently is to quote the method part, not the whole
expression, like:
(gdb) print 'gnu_obj_1::method()'::sintvar
If you wrap the whole expression in quotes, like in m-static.exp, what
really happens is that the parser considers the whole string as a
symbol name, but there's no debug symbol with that name. However,
local statics have linkage and are given a mangled name that demangles
to the same string as the full expression, so that's what GDB prints.
After this commit, and without the cast, the print in m-static.exp
would error out saying that the variable has unknown type:
(gdb) p 'gnu_obj_1::method()::sintvar'
'gnu_obj_1::method()::sintvar' has unknown type; cast it to its declared type
TBC, if currently (even before this series) you try to print any
function local static variable of type other than int, you'll get
bogus results. You can see that with m-static.cc as is, even.
Printing the "svar" local, which is a boolean (1 byte) still prints as
"int" (4 bytes):
(gdb) p 'gnu_obj_1::method()::svar'
$1 = 1
(gdb) ptype 'gnu_obj_1::method()::svar'
type = <data variable, no debug info>
This probably prints some random bogus value on big endian machines.
If 'svar' was of some aggregate type (etc.) we'd still print it as
int, so the problem would have been more obvious... After this
commit, you'll get instead:
(gdb) p 'gnu_obj_1::method()::svar'
'gnu_obj_1::method()::svar' has unknown type; cast it to its declared type
... so at least GDB is no longer misleading. Making GDB find the real
local static debug symbol is the subject of the following patches. In
the end, it'll all "Just Work".
gdb/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* ax-gdb.c: Include "typeprint.h".
(gen_expr_for_cast): New function.
(gen_expr) <OP_CAST, OP_CAST_TYPE>: Use it.
<OP_VAR_VALUE, OP_MSYM_VAR_VALUE>: Error out if the variable's
type is unknown.
* dwarf2read.c (new_symbol_full): Fallback to int instead of
nodebug_data_symbol.
* eval.c: Include "typeprint.h".
(evaluate_subexp_standard) <OP_VAR_VALUE, OP_VAR_MSYM_VALUE>:
Error out if symbol has unknown type.
<UNOP_CAST, UNOP_CAST_TYPE>: Common bits factored out to
evaluate_subexp_for_cast.
(evaluate_subexp_for_address, evaluate_subexp_for_sizeof): Handle
OP_VAR_MSYM_VALUE.
(evaluate_subexp_for_cast): New function.
* gdbtypes.c (init_nodebug_var_type): New function.
(objfile_type): Use it to initialize types of variables with no
debug info.
* typeprint.c (error_unknown_type): New.
* typeprint.h (error_unknown_type): New declaration.
* compile/compile-c-types.c (convert_type_basic): Handle
TYPE_CODE_ERROR; warn and fallback to int for variables with
unknown type.
gdb/testsuite/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* gdb.asm/asm-source.exp: Add casts to int.
* gdb.base/nodebug.c (dataglobal8, dataglobal32_1, dataglobal32_2)
(dataglobal64_1, dataglobal64_2): New globals.
* gdb.base/nodebug.exp: Test different expressions involving the
new globals, with print, whatis and ptype. Add casts to int.
* gdb.base/solib-display.exp: Add casts to int.
* gdb.compile/compile-ifunc.exp: Expect warning. Add cast to int.
* gdb.cp/m-static.exp: Add cast to int.
* gdb.dwarf2/dw2-skip-prologue.exp: Add cast to int.
* gdb.threads/tls-nodebug.exp: Check that gdb errors out printing
tls variable with no debug info without a cast. Test with a cast
to int too.
* gdb.trace/entry-values.exp: Add casts.
|
|
The fact that GDB defaults to assuming that functions return int, when
it has no debug info for the function has been a recurring source of
user confusion. Recently this came up on the errno pretty printer
discussions. Shortly after, it came up again on IRC, with someone
wondering why does getenv() in GDB return a negative int:
(gdb) p getenv("PATH")
$1 = -6185
This question (with s/getenv/random-other-C-runtime-function) is a FAQ
on IRC.
The reason for the above is:
(gdb) p getenv
$2 = {<text variable, no debug info>} 0x7ffff7751d80 <getenv>
(gdb) ptype getenv
type = int ()
... which means that GDB truncated the 64-bit pointer that is actually
returned from getent to 32-bit, and then sign-extended it:
(gdb) p /x -6185
$6 = 0xffffe7d7
The workaround is to cast the function to the right type, like:
(gdb) p ((char *(*) (const char *)) getenv) ("PATH")
$3 = 0x7fffffffe7d7 "/usr/local/bin:/"...
IMO, we should do better than this.
I see the "assume-int" issue the same way I see printing bogus values
for optimized-out variables instead of "<optimized out>" -- I'd much
rather that the debugger tells me "I don't know" and tells me how to
fix it than showing me bogus misleading results, making me go around
tilting at windmills.
If GDB prints a signed integer when you're expecting a pointer or
aggregate, you at least have some sense that something is off, but
consider the case of the function actually returning a 64-bit integer.
For example, compile this without debug info:
unsigned long long
function ()
{
return 0x7fffffffffffffff;
}
Currently, with pristine GDB, you get:
(gdb) p function ()
$1 = -1 # incorrect
(gdb) p /x function ()
$2 = 0xffffffff # incorrect
maybe after spending a few hours debugging you suspect something is
wrong with that -1, and do:
(gdb) ptype function
type = int ()
and maybe, just maybe, you realize that the function actually returns
unsigned long long. And you try to fix it with:
(gdb) p /x (unsigned long long) function ()
$3 = 0xffffffffffffffff # incorrect
... which still produces the wrong result, because GDB simply applied
int to unsigned long long conversion. Meaning, it sign-extended the
integer that it extracted from the return of the function, to 64-bits.
and then maybe, after asking around on IRC, you realize you have to
cast the function to a pointer of the right type, and call that. It
won't be easy, but after a few missteps, you'll get to it:
..... (gdb) p /x ((unsigned long long(*) ()) function) ()
$666 = 0x7fffffffffffffff # finally! :-)
So to improve on the user experience, this patch does the following
(interrelated) things:
- makes no-debug-info functions no longer default to "int" as return
type. Instead, they're left with NULL/"<unknown return type>"
return type.
(gdb) ptype getenv
type = <unknown return type> ()
- makes calling a function with unknown return type an error.
(gdb) p getenv ("PATH")
'getenv' has unknown return type; cast the call to its declared return type
- and then to make it easier to call the function, makes it possible
to _only_ cast the return of the function to the right type,
instead of having to cast the function to a function pointer:
(gdb) p (char *) getenv ("PATH") # now Just Works
$3 = 0x7fffffffe7d7 "/usr/local/bin:/"...
(gdb) p ((char *(*) (const char *)) getenv) ("PATH") # continues working
$4 = 0x7fffffffe7d7 "/usr/local/bin:/"...
I.e., it makes GDB default the function's return type to the type
of the cast, and the function's parameters to the type of the
arguments passed down.
After this patch, here's what you'll get for the "unsigned long long"
example above:
(gdb) p function ()
'function' has unknown return type; cast the call to its declared return type
(gdb) p /x (unsigned long long) function ()
$4 = 0x7fffffffffffffff # correct!
Note that while with "print" GDB shows the name of the function that
has the problem:
(gdb) p getenv ("PATH")
'getenv' has unknown return type; cast the call to its declared return type
which can by handy in more complicated expressions, "ptype" does not:
(gdb) ptype getenv ("PATH")
function has unknown return type; cast the call to its declared return type
This will be fixed in the next patch.
gdb/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_evaluate_subexp) <TYPE_CODE_FUNC>: Don't handle
TYPE_GNU_IFUNC specially here. Throw error if return type is
unknown.
* ada-typeprint.c (print_func_type): Handle functions with unknown
return type.
* c-typeprint.c (c_type_print_base): Handle functions and methods
with unknown return type.
* compile/compile-c-symbols.c (convert_symbol_bmsym)
<mst_text_gnu_ifunc>: Use nodebug_text_gnu_ifunc_symbol.
* compile/compile-c-types.c: Include "objfiles.h".
(convert_func): For functions with unknown return type, warn and
default to int.
* compile/compile-object-run.c (compile_object_run): Adjust call
to call_function_by_hand_dummy.
* elfread.c (elf_gnu_ifunc_resolve_addr): Adjust call to
call_function_by_hand.
* eval.c (evaluate_subexp_standard): Adjust calls to
call_function_by_hand. Handle functions and methods with unknown
return type. Pass expect_type to call_function_by_hand.
* f-typeprint.c (f_type_print_base): Handle functions with unknown
return type.
* gcore.c (call_target_sbrk): Adjust call to
call_function_by_hand.
* gdbtypes.c (objfile_type): Leave nodebug text symbol with NULL
return type instead of int. Make nodebug_text_gnu_ifunc_symbol be
an integer address type instead of nodebug.
* guile/scm-value.c (gdbscm_value_call): Adjust call to
call_function_by_hand.
* infcall.c (error_call_unknown_return_type): New function.
(call_function_by_hand): New "default_return_type" parameter.
Pass it down.
(call_function_by_hand_dummy): New "default_return_type"
parameter. Use it instead of defaulting to int. If there's no
default and the return type is unknown, throw an error. If
there's a default return type, and the called function has no
debug info, then assume the function is prototyped.
* infcall.h (call_function_by_hand, call_function_by_hand_dummy):
New "default_return_type" parameter.
(error_call_unknown_return_type): New declaration.
* linux-fork.c (call_lseek): Cast return type of lseek.
(inferior_call_waitpid, checkpoint_command): Adjust calls to
call_function_by_hand.
* linux-tdep.c (linux_infcall_mmap, linux_infcall_munmap): Adjust
calls to call_function_by_hand.
* m2-typeprint.c (m2_procedure): Handle functions with unknown
return type.
* objc-lang.c (lookup_objc_class, lookup_child_selector)
(value_nsstring, print_object_command): Adjust calls to
call_function_by_hand.
* p-typeprint.c (pascal_type_print_varspec_prefix): Handle
functions with unknown return type.
(pascal_type_print_func_varspec_suffix): New function.
(pascal_type_print_varspec_suffix) <TYPE_CODE_FUNC,
TYPE_CODE_METHOD>: Use it.
* python/py-value.c (valpy_call): Adjust call to
call_function_by_hand.
* rust-lang.c (rust_evaluate_funcall): Adjust call to
call_function_by_hand.
* valarith.c (value_x_binop, value_x_unop): Adjust calls to
call_function_by_hand.
* valops.c (value_allocate_space_in_inferior): Adjust call to
call_function_by_hand.
* typeprint.c (type_print_unknown_return_type): New function.
* typeprint.h (type_print_unknown_return_type): New declaration.
gdb/testsuite/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* gdb.base/break-main-file-remove-fail.exp (test_remove_bp): Cast
return type of munmap in infcall.
* gdb.base/break-probes.exp: Cast return type of foo in infcall.
* gdb.base/checkpoint.exp: Simplify using for loop. Cast return
type of ftell in infcall.
* gdb.base/dprintf-detach.exp (dprintf_detach_test): Cast return
type of getpid in infcall.
* gdb.base/infcall-exec.exp: Cast return type of execlp in
infcall.
* gdb.base/info-os.exp: Cast return type of getpid in infcall.
Bail on failure to extract the pid.
* gdb.base/nodebug.c: #include <stdint.h>.
(multf, multf_noproto, mult, mult_noproto, add8, add8_noproto):
New functions.
* gdb.base/nodebug.exp (test_call_promotion): New procedure.
Change expected output of print/whatis/ptype with functions with
no debug info. Test all supported languages. Call
test_call_promotion.
* gdb.compile/compile.exp: Adjust expected output to expect
warning.
* gdb.threads/siginfo-threads.exp: Likewise.
|
|
Remove many old-style function header variants in C source files of
the GDB test suite, using the 'unifdef' tool with '-DPROTOTYPES=1'.
gdb/testsuite/ChangeLog:
* gdb.base/annota1.c: Remove #ifdef PROTOTYPES, keep prototyped
variant.
* gdb.base/annota3.c: Likewise.
* gdb.base/async.c: Likewise.
* gdb.base/average.c: Likewise.
* gdb.base/call-ar-st.c: Likewise.
* gdb.base/call-rt-st.c: Likewise.
* gdb.base/call-sc.c: Likewise.
* gdb.base/call-strs.c: Likewise.
* gdb.base/ending-run.c: Likewise.
* gdb.base/execd-prog.c: Likewise.
* gdb.base/exprs.c: Likewise.
* gdb.base/foll-exec.c: Likewise.
* gdb.base/foll-fork.c: Likewise.
* gdb.base/foll-vfork.c: Likewise.
* gdb.base/funcargs.c: Likewise.
* gdb.base/gcore.c: Likewise.
* gdb.base/jump.c: Likewise.
* gdb.base/langs0.c: Likewise.
* gdb.base/langs1.c: Likewise.
* gdb.base/langs2.c: Likewise.
* gdb.base/mips_pro.c: Likewise.
* gdb.base/nodebug.c: Likewise.
* gdb.base/opaque0.c: Likewise.
* gdb.base/opaque1.c: Likewise.
* gdb.base/recurse.c: Likewise.
* gdb.base/run.c: Likewise.
* gdb.base/scope0.c: Likewise.
* gdb.base/scope1.c: Likewise.
* gdb.base/setshow.c: Likewise.
* gdb.base/setvar.c: Likewise.
* gdb.base/shmain.c: Likewise.
* gdb.base/shr1.c: Likewise.
* gdb.base/shr2.c: Likewise.
* gdb.base/sigall.c: Likewise.
* gdb.base/signals.c: Likewise.
* gdb.base/so-indr-cl.c: Likewise.
* gdb.base/solib2.c: Likewise.
* gdb.base/structs.c: Likewise.
* gdb.base/sum.c: Likewise.
* gdb.base/vforked-prog.c: Likewise.
* gdb.base/watchpoint.c: Likewise.
* gdb.reverse/shr2.c: Likewise.
* gdb.reverse/until-reverse.c: Likewise.
* gdb.reverse/ur1.c: Likewise.
* gdb.reverse/watch-reverse.c: Likewise.
|
|
2011-12-13 Pedro Alves <pedro@codesourcery.com>
* gdb.texinfo (Implementing a Remote Stub): Explain that you
should transfer control to the stub in the startup code instead of
in main. Mention the need to get past the initial breakpoint.
gdb/testsuite/
2011-12-13 Pedro Alves <pedro@codesourcery.com>
Doug Evans <dje@google.com>
* lib/gdb.exp (gdb_run_cmd, runto_main, gdb_compile)
(clean_restart): Remove references to the gdb_stub target board
variable.
(gdb_step_for_stub): Delete.
* gdb.base/annota1.exp: Remove all references to [target_info
exists gdb_stub], gdb_step_for_stub and usestubs.
* gdb.base/annota3.exp: Ditto.
* gdb.base/async.exp: Ditto.
* gdb.base/break.exp: Ditto.
* gdb.base/code-expr.exp: Ditto.
* gdb.base/commands.exp: Ditto.
* gdb.base/completion.exp: Ditto.
* gdb.base/condbreak.exp: Ditto.
* gdb.base/consecutive.exp: Ditto.
* gdb.base/cvexpr.exp: Ditto.
* gdb.base/define.exp: Ditto.
* gdb.base/display.exp: Ditto.
* gdb.base/ena-dis-br.exp: Ditto.
* gdb.base/environ.exp: Ditto.
* gdb.base/gnu-ifunc.exp: Ditto.
* gdb.base/maint.exp: Ditto.
* gdb.base/pending.exp: Ditto.
* gdb.base/sect-cmd.exp: Ditto.
* gdb.base/sepdebug.exp: Ditto.
* gdb.base/unload.exp: Ditto.
* gdb.base/watchpoint-solib.exp: Ditto.
* gdb.cp/annota2.exp: Ditto.
* gdb.cp/annota3.exp: Ditto.
* gdb.dwarf2/dw2-inline-param.exp: Ditto.
* gdb.hp/gdb.compat/xdb1.exp: Ditto.
* gdb.mi/mi-pending.exp: Ditto.
* gdb.trace/circ.exp: Ditto.
* gdb.cp/ovldbreak.exp: Ditto. Adjust expected line numbers.
* gdb.base/list.exp: Ditto.
* gdb.base/all-types.c: Remove all calls to set_debug_traps and
breakpoint function and all references to the usestubs macro.
* gdb.base/exprs.c: Ditto.
* gdb.base/freebpcmd.c: Ditto.
* gdb.base/bitfields.c: Ditto.
* gdb.base/bitfields2.c: Ditto.
* gdb.base/break.c: Ditto.
* gdb.base/call-sc.c: Ditto.
* gdb.base/call-signals.c: Ditto.
* gdb.base/callfuncs.c: Ditto.
* gdb.base/charset.c: Ditto.
* gdb.base/consecutive.c: Ditto.
* gdb.base/constvars.c: Ditto.
* gdb.base/funcargs.c: Ditto.
* gdb.base/int-type.c: Ditto.
* gdb.base/interrupt.c: Ditto.
* gdb.base/langs0.c: Ditto.
* gdb.base/list0.c: Ditto.
* gdb.base/mips_pro.c: Ditto.
* gdb.base/miscexprs.c: Ditto.
* gdb.base/nodebug.c: Ditto.
* gdb.base/opaque0.c: Ditto.
* gdb.base/pointers.c: Ditto.
* gdb.base/printcmds.c: Ditto.
* gdb.base/ptype.c: Ditto.
* gdb.base/recurse.c: Ditto.
* gdb.base/reread1.c: Ditto.
* gdb.base/reread2.c: Ditto.
* gdb.base/restore.c: Ditto.
* gdb.base/return.c: Ditto.
* gdb.base/run.c: Ditto.
* gdb.base/scope0.c: Ditto.
* gdb.base/sepdebug.c: Ditto.
* gdb.base/setshow.c: Ditto.
* gdb.base/setvar.c: Ditto.
* gdb.base/sigall.c: Ditto.
* gdb.base/signals.c: Ditto.
* gdb.base/structs.c: Ditto.
* gdb.base/structs2.c: Ditto.
* gdb.base/testenv.c: Ditto.
* gdb.base/twice.c: Ditto.
* gdb.base/unwindonsignal.c: Ditto.
* gdb.base/watchpoint.c: Ditto.
* gdb.base/watchpoints.c: Ditto.
* gdb.base/whatis.c: Ditto.
* gdb.cp/classes.cc: Ditto.
* gdb.cp/cplusfuncs.cc: Ditto.
* gdb.cp/derivation.cc: Ditto.
* gdb.cp/formatted-ref.cc: Ditto.
* gdb.cp/misc.cc: Ditto.
* gdb.cp/overload.cc: Ditto.
* gdb.cp/ovldbreak.cc: Ditto.
* gdb.cp/ref-params.cc: Ditto.
* gdb.cp/ref-types.cc: Ditto.
* gdb.cp/templates.cc: Ditto.
* gdb.cp/virtfunc.cc: Ditto.
* gdb.hp/gdb.aCC/run.c: Ditto.
* gdb.hp/gdb.base-hp/callfwmall.c: Ditto.
* gdb.hp/gdb.compat/xdb0.c: Ditto.
* gdb.reverse/consecutive-reverse.c: Ditto.
* gdb.reverse/sigall-reverse.c: Ditto.
* gdb.reverse/until-reverse.c: Ditto.
* gdb.reverse/watch-reverse.c: Ditto.
* gdb.trace/actions.c: Ditto.
* gdb.trace/circ.c: Ditto.
* gdb.trace/collection.c: Ditto.
|
|
|
|
|
|
|
|
|