我无法找到足够的信息来使用as和ld在程序集中创建共享对象。
我想创建一个共享库,其中包含一些带有变量的函数(.data节)。但是当我的代码中有一个.data段时,ld将不接受-shared选项。 (在创建共享库时,不能将R_X86_64_32S相对于'.data'的重定位;使用-fPIC重新编译)。当然可以在共享对象代码中使用局部变量,但是如果不使用-fPIC选项编译C代码,我将找不到有关如何执行此操作的信息。
my_lib.s:
.globl print_info
.data
output:
.ascii "The processor vendor ID is 'xxxxxxxxxxxx'\n"
.bss
.text
print_info:
xor %eax, %eax
cpuid
movq $output, %rdi
movl %ebx, 28(%rdi)
movl %edx, 32(%rdi)
movl %ecx, 36(%rdi)
movl $1, %eax
movl $1, %edi
movq $output, %rsi
movl $42, %edx
ret
caller.s:
.globl _start
.data
.bss
.text
_start:
# some code to load shared library
# with open() and mmap() syscalls
subq $8, %rsp # align stack
call print_info
addq $8, %rsp
# some code here
movl $60, %eax # exit program
xor %edi, %edi
syscall
as my_lib.s -omy_lib.o
as caller.s -ocaller.o
不产生任何错误。但是
ld -shared my_lib.o
礼物:
ld: my_lib.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
ld: final link failed: nonrepresentable section on output
我已经找到的关于该主题的所有信息,都使用C代码和gcc进行编译和链接。任何人都可以演示如何在不使用C进行编码和使用gcc的情况下进行操作吗?
答案 0 :(得分:0)
您的程序集与位置无关。特别是:
movq $output, %rdi
应该成为
movq $output(%rip), %rdi
一般来讲,我建议使用C语言(用-fPIC
编译等效代码,然后检查生成的asm以获取必要的语法。
答案 1 :(得分:0)
如上所述,必须使用与位置无关的代码编写共享库。使用libdl.so从库中动态加载函数[使用open()和mmap()系统调用必须在以后出现],我可以全部使用:
lib.s:
.globl print_info
.data
output:
.ascii "The processor vendor ID is 'xxxxxxxxxxxx'\n"
.bss
.text
print_info:
xor %eax, %eax
cpuid
leaq output(%rip), %rdi
movl %ebx, 28(%rdi)
movl %edx, 32(%rdi)
movl %ecx, 36(%rdi)
movl $1, %eax
movl $1, %edi
leaq output(%rip), %rsi
movl $42, %edx
syscall
ret
assemble and link with:
as -olib.o lib.s
ld -shared -olib.so lib.o
rm lib.o
caller.s:
.globl _start
.data
so_name:
.asciz "./lib.so"
func_name:
.asciz "print_info"
.bss
.lcomm handle, 8
.lcomm func, 8
.text
_start:
movq $so_name, %rdi
movl $1, %esi # RTLD_LAZY == 1
call dlopen
movq %rax, handle
movq %rax, %rdi
movq $func_name, %rsi
call dlsym
movq %rax, func # Not really necessary here, as func is used
# immediately and just this once
call *%rax
movq handle, %rdi
call dlclose
movl $60, %eax
xorl %edi, %edi
syscall
assemble and link with:
as -ocaller.o caller.s
ld -dynamic-linker /usr/lib64/ld-linux-x86-64.so.2 -ocaller caller.o -ldl
rm caller.o
现在,您可以使用以下命令运行呼叫者:
./caller
使用_start作为条目时,堆栈似乎已正确对齐(与使用main相对,这显然会在调用main =您的程序之前通过按%rbp引起初始未对齐),因此无需进行调整
subq $8, %rsp
通话前和
addq $8, %rsp
之后。至少看起来是这样,但在这一点上我可能是错的。