0

1). print function address directly:

printf("strerror=%p, strerror_r=%p\n", strerror, strerror_r);
strerror=0x8049ec0, strerror_r=0x8049e20

2). dlsym version:

rtldDefault= dlopen(0, RTLD_NOW | RTLD_GLOBAL);
dlsym(rtldDefault, "strerror_r"); ==> strerror_r=0xb76544e0

but

dlsym(rtldDefault, "strerror"); ==> strerror=0x8049ec0

3). others:

dlsym((void*)0, "strerror_r") ==> strerror_r=0xb76544e0
dlsym((void*)-1, "strerror_r") ==> strerror_r=0xb76544e0

How can I get strerror_r=0x8049e20 using dlsym()?

I have already print the address of strerror_r first, then call dlsym().

strerror_r=0xb76544e0 is wrong address, my call strerror_r with this address just do nothing.

David Chyi
  • 159
  • 1
  • 9
  • I suppose it's possible that `strerror` is actually called somewhere and therefore already resolved, whereas `strerror_r` hasn't been called and `dlsym` is giving you the address of a trampoline function. Try calling them both (just once) and seeing if anything changes. – Useless Aug 10 '12 at 10:31
  • Hard to say.. Perhaps feeding it to `readelf` could give some hints – Roman Saveljev Aug 10 '12 at 10:46
  • You can just look at the addresses in a debugger. I'd guess that one of them contains nothing but a jump to the real function. – Niklas B. Aug 10 '12 at 10:51

1 Answers1

1

If you look at the declaration of strerror_r in /usr/include/string.h:

/* Reentrant version of strerror'. There are 2 flavors ofstrerror_r', GNU which returns the string and may or may not use the supplied temporary buffer and POSIX one which fills the string into the buffer. To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L without -D_GNU_SOURCE is needed, otherwise the GNU version is preferred. */
[and then some quite confusing declarations]

Compiling a sample program with gcc -save-temps and default configuration, I get the following precompiled declaration:

extern int strerror_r (int __errnum, char *__buf, size_t __buflen) 
    __asm__ ("" "__xpg_strerror_r") __attribute__ ((__nothrow__ , __leaf__))
    __attribute__ ((__nonnull__ (2)));

So it looks like the strerror_r function is linked to the symbol __xpg_strerror_r instead.

Indeed, a check of the generated binary objdump -t a.out | grep strerror:

00000000      DF *UND*  00000000  GLIBC_2.3.4 __xpg_strerror_r

So, asking your question, just do dlsym(rtldDefault, "__xpg_strerror_r").

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • Thanks for your kindly explaination. But why dlsym(rtldDefault, "strerror_r"); ==> strerror_r=0xb76544e0 – David Chyi Aug 10 '12 at 11:10
  • @DavidChyi: What do you mean? Why is it a much higher address than the other? Or why is it different than __xpg_strerror_r? They are different because they are different functions, or more exactly, different _symbols_. It is much higher maybe because, as Useless said in his comment, this function has never been called. – rodrigo Aug 10 '12 at 11:17