如何在动态链接库中引用全局变量?

环境是32位SPARC上的Solaris,但我认为这是动态链接和/或位置无关代码的更普遍的问题.

我有一个汇编程序,我编译为位置无关代码,并从C程序动态链接到它.它工作正常,除了我不能从汇编程序引用汇编程序保留的任何内存.在装配程序中跳转工作正常.

我只想在汇编程序中读取和写入内存,但是每次尝试都会出现分段错误.

我写了这个测试程序来调试这个问题

  .section ".data"
  .global foo
foo: .word 1
  .section ".text"
  .global testprog
testprog:
  save %sp, -(92+4), %sp
  sethi %hi(foo), %o0 ! set foo, %o0
  or %o0, %lo(foo), %o0 
  call print_int
  nop
  ret
  restore

我把它编译成了

as -K PIC -b

并在C中将所得到的.so dlopen

dlhandle = dlopen(obj_file, RTLD_NOW)
dl_testprog = dlsym(dlhandle, "testprog")

当我调用dl_testprog()时,它会打印“4”.如果我尝试打印testprog或print_int的地址,它也会打印“4”.跳到标签,其他一切工作正常.看看反汇编,foo被替换为0x0,就像它应该的那样.

我是否必须通过_GLOBAL_OFFSET_TABLE_或其他东西,才能在汇编程序中写入我自己的内存?如果是这样,我该怎么做?我尝试过的所有内容都导致了一个段错误,我找不到一个非常好的指南如何做到这一点(这让我相信你不应该这样做.这不是链接器问题吗?) .

最佳答案
通过查看C编译器为PIC输出的代码来解决这个问题,这是我应该从一开始就做的,而不是阅读手册和随机网页.

也许这是显而易见的,但事实上PIC中的对象(至少在32b SPARC上)的实际地址是(_GLOBAL_OFFSET_TABLE_ PC对象).惯例是在函数开始时将GOT地址计算为%l7.细节是here,除了如何实际计算%l7.

addpc:
  add %o7, %l7, %l7 ! %o7 == addr of call == PC
  retl
   nop
testprog:
  sethi %hi(_GLOBAL_OFFSET_TABLE_-8), %l7 ! -8 = distance from call addpc
  add %l7, %lo(_GLOBAL_OFFSET_TABLE_-4), %l7 
  call addpc ! add PC to %l7
   nop

转载注明原文:如何在动态链接库中引用全局变量? - 代码日志