Как отметил выше yugr, разделяемый объект должен быть написан с независимым от позиции кодом. Используя libdl.so для динамической загрузки функции из lib [системные вызовы 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, что, по-видимому, вызывает начальное смещение при нажатии% rbp перед вызовом main = вашей программы), поэтому нет необходимости настраивать с помощью
subq $8, %rsp
до звонка и
addq $8, %rsp
после. По крайней мере, так кажется, но я могу ошибаться в этом вопросе.