环境是 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 中 dlopen 生成的 .so
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 + object
)。并且约定是在一个函数的开头计算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
关于c - 如何引用动态链接库中的全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/814823/