Bug 539590 - gdb can't call some functions
gdb can't call some functions
Status: CLOSED CURRENTRELEASE
Product: Fedora
Classification: Fedora
Component: gdb (Show other bugs)
12
All Linux
low Severity medium
: ---
: ---
Assigned To: Jan Kratochvil
Fedora Extras Quality Assurance
: Triaged
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2009-11-20 12:03 EST by Tom Horsley
Modified: 2010-07-20 14:07 EDT (History)
2 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2010-04-04 04:50:22 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
ifunc implementation #1. (14.36 KB, patch)
2009-11-23 16:39 EST, Jan Kratochvil
no flags Details | Diff

  None (edit)
Description Tom Horsley 2009-11-20 12:03:52 EST
Description of problem:

The fedora 12 x86_64 gdb experience:

# gdb ./fact
GNU gdb (GDB) Fedora (7.0-3.fc12)
...yadda, yadda, yadda...
(gdb) b main
Breakpoint 1 at 0x400593: file fact.c, line 19.
(gdb) r 7
Starting program: fact 7

Breakpoint 1, main (argc=2, argv=0x7fffffffe708)
    at fact.c:19
19         for (i = 1; i < argc; ++i) {
(gdb) p strlen("xyzzy")
$1 = -509088576
(gdb) 

I'm pretty sure the string "xyzzy" is not -509,088,576
bytes long :-).

The fedora 11 x86_64 gdb experience:

zooty> gdb ./fact
GNU gdb (GDB) Fedora (6.8.50.20090302-39.fc11)
...yadda, yadda, yadda...
(gdb) b main
Breakpoint 1 at 0x400593: file fact.c, line 19.
(gdb) r 7
Starting program: fact 7

Breakpoint 1, main (argc=2, argv=0x7fffffffe2b8)
    at fact.c:19
19         for (i = 1; i < argc; ++i) {
(gdb) p strlen("xyzzy")
$1 = 5
(gdb) 

I was right! It is actually 5 bytes long.

P.S. The program "fact" is unimportant, any old hello world sort
of app dynamically linked with libc will do.

Version-Release number of selected component (if applicable):
gdb-7.0-3.fc12.x86_64
glibc-2.11-2.x86_64

How reproducible:
Oh, it is gonna happen every time, for strlen and several other
similar functions (strcpy, etc).

Steps to Reproduce:
1.see above
2.
3.
  
Actual results:
ridiculous nonsense

Expected results:
actual length of string

Additional info:
I know exactly what is happening here, but why should I spare
the gdb maintainers the thrill of the discovery of the true
horror the latest glibc "improvements" have foisted on long
suffering debugger maintainers? :-).
Comment 1 Phil Muldoon 2009-11-20 16:39:28 EST
This might be cross-pollination of a cause involving conditional breakpoints involving an inferior function call smashing the breakpoint struct. I've been looking a little at this today, and the value returned from inferior function call is bogus. 

https://bugzilla.redhat.com/show_bug.cgi?id=538626

If you have a theory the the cause, please by all means expound on it! It's all good ;)
Comment 2 Tom Horsley 2009-11-20 17:35:04 EST
Nope, this has nothing to do with conditional breakpoints. If you
do an 'nm' on libc.so, you will see the functions that gdb cannot
call have an 'i' printed in front of the symbol.

If you disassemble the code at &strlen, you find no code that
could possibly take an argument and return a string length.

If you follow these clues around for several hours of google
searching, you will find the STT_GNU_IFUNC symbol type and
the assembler directive .type @gnu_indirect_function in various
patches applied to the glibc code.

In those patches, you will also find that glibc now has
47,621 different versions of strlen, each optimized for a
different architecture variation, because, after all, it
is vital to provide a 1 nanosecond speed improvement in routines
that typical programs spend 0.001% of their time in at the cost
of complicating the maintenance of glibc and debuggers
by a factor of at least 100.

Anyway, it seems like the dynamic linker checks for these
indirect function entries when it is looking up symbols
to resolve .plt entries, and when it finds one, rather than
stashing the symbol value as the address of the function,
it *calls* the funtion, which returns a pointer to the best
version of of the 47,621 alternate strlens to use on the
current architecture.

So the symbol named "strlen" is indeed a function, but it is
a function of no arguments which returns a pointer to another
function (the one you really want).

God help us all when the security boys get wind of this
dynamic linker feature - then they can randomly pick different
implementations of all the glibc functions at runtime :-).
Comment 3 Jan Kratochvil 2009-11-23 16:39:46 EST
Created attachment 373246 [details]
ifunc implementation #1.
Comment 4 Fedora Update System 2009-11-25 05:53:27 EST
gdb-7.0-7.fc12 has been submitted as an update for Fedora 12.
http://admin.fedoraproject.org/updates/gdb-7.0-7.fc12
Comment 5 Fedora Update System 2009-11-27 16:59:06 EST
gdb-7.0-7.fc12 has been pushed to the Fedora 12 stable repository.  If problems still persist, please make note of it in this bug report.
Comment 6 Fedora Update System 2010-01-21 16:49:15 EST
gdb-7.0.1-28.fc12 has been submitted as an update for Fedora 12.
http://admin.fedoraproject.org/updates/gdb-7.0.1-28.fc12
Comment 7 Fedora Update System 2010-07-20 14:07:36 EDT
gdb-7.0.1-49.fc12 has been submitted as an update for Fedora 12.
http://admin.fedoraproject.org/updates/gdb-7.0.1-49.fc12

Note You need to log in before you can comment on or make changes to this bug.