Discussion:
[Bug gdb/19487] New: Result of call to __errno_location() is truncated to 32 bit on amd64
b7.10110111 at gmail dot com
2016-01-18 11:38:34 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

Bug ID: 19487
Summary: Result of call to __errno_location() is truncated to
32 bit on amd64
Product: gdb
Version: 7.10
Status: NEW
Severity: normal
Priority: P2
Component: gdb
Assignee: unassigned at sourceware dot org
Reporter: b7.10110111 at gmail dot com
Target Milestone: ---

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.
--
You are receiving this mail because:
You are on the CC list for the bug.
b7.10110111 at gmail dot com
2016-01-18 11:39:58 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #1 from Ruslan <b7.10110111 at gmail dot com> ---
*** Bug 19488 has been marked as a duplicate of this bug. ***
--
You are receiving this mail because:
You are on the CC list for the bug.
palves at redhat dot com
2016-01-18 15:32:04 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

Pedro Alves <palves at redhat dot com> changed:

What |Removed |Added
----------------------------------------------------------------------------
CC| |palves at redhat dot com

--- Comment #2 from Pedro Alves <palves at redhat dot com> ---
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 *").
--
You are receiving this mail because:
You are on the CC list for the bug.
b7.10110111 at gmail dot com
2016-01-18 15:39:10 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #3 from Ruslan <b7.10110111 at gmail dot com> ---
(In reply to Pedro Alves from comment #2)
Post by palves at redhat dot com
(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.
--
You are receiving this mail because:
You are on the CC list for the bug.
palves at redhat dot com
2016-01-18 15:42:30 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #4 from Pedro Alves <palves at redhat dot com> ---
Post by b7.10110111 at gmail dot com
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.
--
You are receiving this mail because:
You are on the CC list for the bug.
b7.10110111 at gmail dot com
2016-01-18 18:23:59 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #5 from Ruslan <b7.10110111 at gmail dot com> ---
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)
--
You are receiving this mail because:
You are on the CC list for the bug.
fweimer at redhat dot com
2016-02-09 18:39:50 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

Florian Weimer <fweimer at redhat dot com> changed:

What |Removed |Added
----------------------------------------------------------------------------
CC| |fweimer at redhat dot com
--
You are receiving this mail because:
You are on the CC list for the bug.
cvs-commit at gcc dot gnu.org
2017-08-21 10:37:12 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #6 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Pedro Alves <***@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bf223d3e808e6fec9ee165d3d48beb74837796de

commit bf223d3e808e6fec9ee165d3d48beb74837796de
Author: Pedro Alves <***@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 <***@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 <***@redhat.com>

PR gdb/19487
* gdb.base/symbol-alias.c: New.
* gdb.base/symbol-alias2.c: New.
* gdb.base/symbol-alias.exp: New.
--
You are receiving this mail because:
You are on the CC list for the bug.
palves at redhat dot com
2017-08-21 11:02:17 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #7 from Pedro Alves <palves at redhat dot com> ---
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
--
You are receiving this mail because:
You are on the CC list for the bug.
cvs-commit at gcc dot gnu.org
2018-04-26 12:16:32 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

--- Comment #8 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Pedro Alves <***@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a376e11d84ba7ea8cc7333c77043e20c7b0cfc91

commit a376e11d84ba7ea8cc7333c77043e20c7b0cfc91
Author: Pedro Alves <***@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 <***@redhat.com>

* c-exp.y (variable production): Skip finding an alias for ifunc
symbols.
--
You are receiving this mail because:
You are on the CC list for the bug.
palves at redhat dot com
2018-04-26 14:11:50 UTC
Permalink
https://sourceware.org/bugzilla/show_bug.cgi?id=19487

Pedro Alves <palves at redhat dot com> changed:

What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |RESOLVED
Resolution|--- |FIXED

--- Comment #9 from Pedro Alves <palves at redhat dot com> ---
I think we can close this one now, the series pointed at by comment 7 above has
been merged a while ago.
--
You are receiving this mail because:
You are on the CC list for the bug.
Loading...