Consider the following C program: #include <stdio.h> #include <errno.h> int main() { printf("%p\n",&errno); } If I run it in gdb, I get wrong results of attempt to print errno and even just its location. Here's the debugging session log: ------------------------------------------------- $ gdb -q ./gdb-bug -ex 'b main' -ex r Reading symbols from ./gdb-bug...(no debugging symbols found)...done. Breakpoint 1 at 0x40059a Starting program: /tmp/gdb-bug Breakpoint 1, 0x000000000040059a in main () (gdb) p/x __errno_location() $1 = 0xf7fbf6a0 (gdb) p *__errno_location() Cannot access memory at address 0xfffffffff7fbf6a0 (gdb) c Continuing. 0x7ffff7fbf6a0 [Inferior 1 (process 869) exited normally] ---------------------------------------------------- See that "p/x" truncates the value to 32 bits, then "p *..." sign-extends the result of truncation, while on "c" we get actual value printed by the program itself, which is neither of the former two.
*** Bug 19488 has been marked as a duplicate of this bug. ***
What does: (gdb) ptype __errno_location say? I think you'll get this if you don't have debug info for __errno_location, and then gdb assumes the function return "int" (not "int *").
(In reply to Pedro Alves from comment #2) > What does: > > (gdb) ptype __errno_location > > say? I think you'll get this if you don't have debug info for > __errno_location, and then gdb assumes the function return "int" (not "int > *"). It says `type = int ()`, both with debug info ("gcc -g") and without.
> both with debug info ("gcc -g") and without. That sounds like debug info for your program. __errno_location lives in glibc, so check if you have debug info for that.
Tracing into __errno_location reveals that actual implementation is in __GI___errno_location, into which the _dl_runtime_resolve RETs. For __GI___errno_location I do have line numbers and file name showed. Still, for __errno_location the result is as it was, unlike for __GI___errno_location: (gdb) ptype __errno_location type = int () (gdb) ptype __GI___errno_location type = int *(void)
The master branch has been updated by Pedro Alves <palves@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bf223d3e808e6fec9ee165d3d48beb74837796de commit bf223d3e808e6fec9ee165d3d48beb74837796de Author: Pedro Alves <palves@redhat.com> Date: Mon Aug 21 11:34:32 2017 +0100 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.
The original issue should be fixed, provided you have glibc debug info installed. There's a follow up series pending that will improve things further, by stopping GDB from silently assuming that functions without debug info have type "int ()": https://sourceware.org/ml/gdb-patches/2017-07/msg00137.html
The master branch has been updated by Pedro Alves <palves@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a376e11d84ba7ea8cc7333c77043e20c7b0cfc91 commit a376e11d84ba7ea8cc7333c77043e20c7b0cfc91 Author: Pedro Alves <palves@redhat.com> Date: Thu Apr 26 13:01:26 2018 +0100 Fix calling ifunc functions when resolver has debug info and different name Currently, on Fedora 27 (glibc 2.26), if you try to call strlen in the inferior you get: (gdb) p strlen ("hello") $1 = (size_t (*)(const char *)) 0x7ffff554aac0 <__strlen_avx2> strlen is an ifunc function, and what we see above is the result of calling the ifunc resolver in the inferior. That returns a pointer to the actual target function that implements strlen on my machine. GDB should have turned around and called the resolver automatically without the user noticing. This is was caused by commit: commit bf223d3e808e6fec9ee165d3d48beb74837796de Date: Mon Aug 21 11:34:32 2017 +0100 Handle function aliases better (PR gdb/19487, errno printing) which added the find_function_alias_target call to c-exp.y, to try to find an alias with debug info for a minsym. For ifunc symbols, that finds the ifunc's resolver if it has debug info (in the example it's called "strlen_ifunc"), with the result that GDB calls that as a regular function. After this commit, we get now get: (top-gdb) p strlen ("hello") '__strlen_avx2' has unknown return type; cast the call to its declared return type Which is correct, because __strlen_avx2 is written in assembly. That'll be improved in a following patch, though. gdb/ChangeLog: 2018-04-26 Pedro Alves <palves@redhat.com> * c-exp.y (variable production): Skip finding an alias for ifunc symbols.
I think we can close this one now, the series pointed at by comment 7 above has been merged a while ago.