2012-08-10 138 views
0

1)。直接打印功能地址:dlsym()返回符号的奇怪地址

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

2)。对dlsym版本:

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

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

3)。其他:

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

我怎样才能使用strerror_r=0x8049e20dlsym()

我已经打印出strerror_r的地址,然后调用dlsym()。

strerror_r = 0xb76544e0是错误的地址,我用这个地址调用strerror_r只是什么都不做。

+0

我想可能'strerror'实际上是在某处调用的,因此已经解决了,而'strerror_r'没有被调用,'dlsym'给了你一个蹦床函数的地址。尝试调用它们(只是一次),看看是否有任何变化。 – Useless 2012-08-10 10:31:28

+0

很难说..也许喂它到'readelf'可以给一些提示 – 2012-08-10 10:46:21

+0

你可以看看调试器中的地址。我猜想其中一个除了跳转到真正的功能外没有其他任何东西。 – 2012-08-10 10:51:21

回答

1

如果你看看strerror_r/usr/include/string.h声明:

/*重入版本strerror'. There are 2 flavors of strerror_r”,GNU它返回字符串 和可能或不使用所提供的临时缓冲和POSIX一个 的将字符串填充到缓冲区中。 要使用POSIX版本,需要-D_XOPEN_SOURCE = 600或-D_POSIX_C_SOURCE = 200112L 而不需要-D_GNU_SOURCE,否则首选的是GNU版本 。 */
[然后颇有些迷惑声明]

编译示例程序与gcc -save-temps和默认配置,我得到以下预编译声明:

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

所以它看起来像strerror_r功能改为链接到代码__xpg_strerror_r

事实上,生成的二进制objdump -t a.out | grep strerror的检查:

00000000  DF *UND* 00000000 GLIBC_2.3.4 __xpg_strerror_r 

所以,问你的问题,只是做dlsym(rtldDefault, "__xpg_strerror_r")

+0

感谢您的亲切解释。但为什么dlsym(rtldDefault,“strerror_r”); ==> strerror_r = 0xb76544e0 – 2012-08-10 11:10:27

+0

@DavidChyi:你什么意思?为什么它比另一个更高的地址?或者为什么它不同于__xpg_strerror_r?它们不同,因为它们是不同的功能,或者更确切地说,不同的_symbols_。这可能要高得多,因为正如无用在他的评论中所说的那样,这个功能从来没有被调用过。 – rodrigo 2012-08-10 11:17:59