gpt4 book ai didi

c - 无法从与共享库链接的 C 程序访问全局程序集标签数​​据

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:05:53 24 4
gpt4 key购买 nike

在我的系统中,我同时拥有静态库文件 (libcrypto.a) 和共享库 (libcrypto.so.0.9.8)。

我正在尝试使用静态库和共享库从 C 程序内部访问汇编文件的全局标签 AES_Td。

   //assembly code
.globl AES_Td
.text
.align 64
AES_Td:
.long 1353184337,1353184337
.long 1399144830,1399144830
.long 3282310938,3282310938
.long 2522752826,2522752826
.....
.....

// test_glob.c
#include <stdio.h>
extern void* AES_Td ;

int main()
{
long *p;
int i;
p=(long *)(&AES_Td);
printf("%p %lu\n",p,*p);
}

成功使用静态库

在尝试链接静态库时,我能够访问全局标签。

gcc -L. test_glob.c -lcrypto

共享库的段错误

我在尝试链接共享库时收到以下警告消息。

/usr/bin/ld:警告:动态符号“AES_Td”的类型和大小未定义

var=`pwd` 
gcc -g -L$var -O0 -Wall -o dynamic test_glob.c -lcrypto
/usr/bin/ld: warning: type and size of dynamic symbol `AES_Td' are not defined

LD_LIBRARY_PATH=$var:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$var:$LD_LIBRARY_PATH


./dynamic
segmentation fault

SO 中的一些帖子建议创建符号链接(symbolic link)以正确链接到共享库的正确版本以解决上述错误/警告消息。

但是在我的例子中,虽然存在符号链接(symbolic link),

libcrypto.so -> libcrypto.so.0.9.8

我仍然收到相同的警告消息和相同的符号链接(symbolic link)段错误。

我在 Debian 操作系统中使用 gcc。

任何解决段错误或使用共享库访问全局标签的帮助/链接都将受到高度赞赏。

**编辑-1:**

根据Shachar Shemesh的建议,我重新编译了加密库如下

./config -fPIC -shared -DSTATIC_CRYPTO
make

然后将 libcrypto.a 、 libcrypto.so 和 libtomcrypto.so.0.9.8 复制到本地文件夹中。

然后我对c代码做了如下修改,

// test_glob_modified.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#ifdef STATIC_CRYPTO
extern void* AES_TD;
void** AES_Td_ptr= &AES_Td;
#else
void** AES_Td_ptr;
#endif

int main()
{

#ifndef STATIC_CRYPTO
AES_Td_ptr=dlsym(RTLD_NEXT,"AES_Td");
#endif

long *p;
int i;
p=(long *)(AES_Td_ptr);

printf(" %p %lu\n", p,*p);

return 0;

}



#Compile and run the source code as follows
var=`pwd`
gcc -g -L$var -Wall -o dynamic test_glob_modified.c -lcrypto -ldl

LD_LIBRARY_PATH=$var:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$var:$LD_LIBRARY_PATH
./dynamic

我仍然遇到段错误。

最佳答案

您尝试做的事情以您尝试做的方式是不可能的。

您不能尝试通过共享库中的绝对值来引用 .text 区域数据。在某些平台上它不起作用,在其他平台上它无法链接。例如,在 X86_64 上:

/usr/bin/ld: warning: type and size of dynamic symbol `AES_Td' are not defined
/usr/bin/ld: /tmp/cc4xpr2u.o: relocation R_X86_64_PC32 against symbol `AES_Td' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

原因是文本段代码是通过 stub 加载的,该 stub 在首次使用时解析实际地址。您直接使用该符号会绕过此机制。

我建议的解决方案是使用-DSTATIC_CRYPTO 编译静态版本。像这样更改代码:

#ifdef STATIC_CRYPTO
extern void* AES_Td;
void** AES_Td_ptr = &AES_Td;
#else
void** AES_Td_ptr;
#endif

...

// Somewhere near the start of the program
#ifndef STATIC_CRYPTO
AES_Td_ptr = dlsym(RTLD_NEXT, "AES_Td");
#endif

通过 AES_Td_ptr 指针访问实际代码(它只是替换示例程序中的 p)。本质上,您是在手动编写链接器作为 stub 放置的相同代码以进行常规函数访问。

另请注意,这两种方法是互斥的。虽然 AES_Td_ptr = &AES_Td 不适用于动态链接,但还应注意 dlsym 方法不适用于静态链接。如果您想同时支持两者,则两者都需要。

编辑添加

如果您可以更改链接的库,并且您要查找的符号实际上不是代码,则将其移动到 .rodata 部分而不是 .text 将使用相同的代码进行静态和动态链接。如果这不是您的库,或者该符号实际上包含代码,那么恐怕我写的是您所能期望的最好的。

关于c - 无法从与共享库链接的 C 程序访问全局程序集标签数​​据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46810114/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com