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.
If you look at the declaration of strerror_r
in /usr/include/string.h
:
/* Reentrant version of
strerror'. There are 2 flavors of
strerror_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")
.