无法从与共享库

时间:2017-10-18 12:23:22

标签: c linux assembly shared-libraries

在我的系统中,我有静态库文件(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中的一些帖子建议创建符号链接以正确链接正确版本的共享库以解决上述错误/警告消息。

但在我的情况下,虽然存在符号链接,

libcrypto.so -> libcrypto.so.0.9.8

我仍然在使用符号链接获得相同的警告消息和相同的分段错误。

我在Debian OS中使用gcc。

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

** EDIT-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

我仍然遇到分段错误。

1 个答案:

答案 0 :(得分:2)

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

您无法尝试通过共享对象的绝对值引用const AppDrawer = DrawerNavigator({ Home: { screen: StackNavigator({ Home: { screen: WelcomeContainer, navigationOptions: { title: "Welcome" } } }) }, Category: { screen: StackNavigator({ Category: { screen: CategoryContainer, navigationOptions: { title: "Category" } } }) } }) 区域数据。在某些平台上它不起作用,在其他平台上它没有链接。例如,在X86_64上:

.text

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

我建议的解决方案是使用/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 编译静态版本。像这样更改代码:

-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不适用于动态链接,但还应注意AES_Td_ptr = &AES_Td方法不适用于静态链接。如果你想同时支持两者,你需要两者。

已添加

如果您可以更改要链接的库,并且您要查找的符号实际上不是代码,那么将其移动到dlsym部分而不是.rodata将使用相同的代码用于静态和动态链接。如果这不是你的库,或者符号实际上包含代码,那么我担心我写的是你能想到的最好的。