Question

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.

Was it helpful?

Solution

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").

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top