diff options
author | Pedro Alves <palves@redhat.com> | 2017-08-21 11:34:32 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2017-08-21 11:34:32 +0100 |
commit | bf223d3e808e6fec9ee165d3d48beb74837796de (patch) | |
tree | e416f6364d2ff65dfde7465d28bc0bf692b4540f /gdb/c-exp.y | |
parent | c973d0aa4a2c737ab527ae44a617f1c357e07364 (diff) | |
download | gdb-bf223d3e808e6fec9ee165d3d48beb74837796de.zip gdb-bf223d3e808e6fec9ee165d3d48beb74837796de.tar.gz gdb-bf223d3e808e6fec9ee165d3d48beb74837796de.tar.bz2 |
Handle function aliases better (PR gdb/19487, errno printing)
(Ref: https://sourceware.org/ml/gdb/2017-06/msg00048.html)
This patch improves GDB support for function aliases defined with
__attribute__ alias. For example, in the test added by this commit,
there is no reference to "func_alias" in the debug info at all, only
to "func"'s definition:
$ nm ./testsuite/outputs/gdb.base/symbol-alias/symbol-alias | grep " func"
00000000004005ae t func
00000000004005ae T func_alias
$ readelf -w ./testsuite/outputs/gdb.base/symbol-alias/symbol-alias | grep func -B 1 -A 8
<1><db>: Abbrev Number: 5 (DW_TAG_subprogram)
<dc> DW_AT_name : (indirect string, offset: 0x111): func
<e0> DW_AT_decl_file : 1
<e1> DW_AT_decl_line : 27
<e2> DW_AT_prototyped : 1
<e2> DW_AT_type : <0xf8>
<e6> DW_AT_low_pc : 0x4005ae
<ee> DW_AT_high_pc : 0xb
<f6> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<f8> DW_AT_GNU_all_call_sites: 1
So all GDB knows about "func_alias" is from the minsym (elf symbol):
(gdb) p func_alias
$1 = {<text variable, no debug info>} 0x4005ae <func>
(gdb) ptype func_alias
type = int ()
(gdb) p func
$2 = {struct S *(void)} 0x4005ae <func>
(gdb) ptype func
type = struct S {
int field1;
int field2;
} *(void)
The result is that calling func_alias from the command line produces
incorrect results.
This is similar (though not exactly the same) to the glibc
errno/__errno_location/__GI___errno_location situation. On glibc,
errno is defined like this:
extern int *__errno_location (void);
#define errno (*__errno_location ())
with __GI___errno_location being an internal alias for
__errno_location. On my system's libc (F23), I do see debug info for
__errno_location, in the form of name vs linkage name:
<1><95a5>: Abbrev Number: 18 (DW_TAG_subprogram)
<95a6> DW_AT_external : 1
<95a6> DW_AT_name : (indirect string, offset: 0x2c26): __errno_location
<95aa> DW_AT_decl_file : 1
<95ab> DW_AT_decl_line : 24
<95ac> DW_AT_linkage_name: (indirect string, offset: 0x2c21): __GI___errno_location
<95b0> DW_AT_prototyped : 1
<95b0> DW_AT_type : <0x9206>
<95b4> DW_AT_low_pc : 0x20f40
<95bc> DW_AT_high_pc : 0x11
<95c4> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa)
<95c6> DW_AT_GNU_all_call_sites: 1
however that doesn't matter in practice, because GDB doesn't record
demangled names anyway, and so we end up with the exact same situation
covered by the testcase.
So the fix is to make the expression parser find a debug symbol for
the same address as the just-found minsym, when a lookup by name
didn't find a debug symbol by name. We now get:
(gdb) p func_alias
$1 = {struct S *(void)} 0x4005ae <func>
(gdb) p __errno_location
$2 = {int *(void)} 0x7ffff6e92830 <__errno_location>
I've made the test exercise variable aliases too, for completeness.
Those already work correctly, because unlike for function aliases, GCC
emits debug information for variable aliases.
Tested on GNU/Linux.
gdb/ChangeLog:
2017-08-21 Pedro Alves <palves@redhat.com>
PR gdb/19487
* c-exp.y (variable production): Handle function aliases.
* minsyms.c (msymbol_is_text): New function.
* minsyms.h (msymbol_is_text): Declare.
* symtab.c (find_function_alias_target): New function.
* symtab.h (find_function_alias_target): Declare.
gdb/testsuite/ChangeLog:
2017-08-21 Pedro Alves <palves@redhat.com>
PR gdb/19487
* gdb.base/symbol-alias.c: New.
* gdb.base/symbol-alias2.c: New.
* gdb.base/symbol-alias.exp: New.
Diffstat (limited to 'gdb/c-exp.y')
-rw-r--r-- | gdb/c-exp.y | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 24a2fbd..a1f9fee 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -1038,18 +1038,38 @@ variable: name_not_typename } else { - struct bound_minimal_symbol msymbol; char *arg = copy_name ($1.stoken); - msymbol = - lookup_bound_minimal_symbol (arg); - if (msymbol.minsym != NULL) - write_exp_msymbol (pstate, msymbol); - else if (!have_full_symbols () && !have_partial_symbols ()) - error (_("No symbol table is loaded. Use the \"file\" command.")); + bound_minimal_symbol msymbol + = lookup_bound_minimal_symbol (arg); + if (msymbol.minsym == NULL) + { + if (!have_full_symbols () && !have_partial_symbols ()) + error (_("No symbol table is loaded. Use the \"file\" command.")); + else + error (_("No symbol \"%s\" in current context."), + copy_name ($1.stoken)); + } + + /* This minsym might be an alias for + another function. See if we can find + the debug symbol for the target, and + if so, use it instead, since it has + return type / prototype info. This + is important for example for "p + *__errno_location()". */ + symbol *alias_target + = find_function_alias_target (msymbol); + if (alias_target != NULL) + { + write_exp_elt_opcode (pstate, OP_VAR_VALUE); + write_exp_elt_block + (pstate, SYMBOL_BLOCK_VALUE (alias_target)); + write_exp_elt_sym (pstate, alias_target); + write_exp_elt_opcode (pstate, OP_VAR_VALUE); + } else - error (_("No symbol \"%s\" in current context."), - copy_name ($1.stoken)); + write_exp_msymbol (pstate, msymbol); } } ; |