在位置独立代码中访问.data部分

时间:2016-03-25 15:47:06

标签: linux assembly nasm x86-64 elf

我正在使用NASM构建一个共享库。在该库中,在某些函数中,我需要在C中称为静态变量。基本上,我认为它是.data部分中的一些空格:

    SECTION .data
last_tok:       dq 0 ; Define a QWORD

当我尝试在我的函数中访问 last_tok 时出现问题。

我阅读了解释问题的NASM Manual: 8.2 Writing Linux/ELF Shared Libraries并给出了解决方案。

    SECTION .data
last_tok:              dq 0     ; Define a QWORD

    SECTION .text
    EXTERN _GLOBAL_OFFSET_TABLE_
    GLOBAL strtok:function
strtok:
    enter    0, 0
    push     rbx
    call     .get_GOT
.get_GOT:
    pop      rbx
    add      rbx, _GLOBAL_OFFSET_TABLE_ + $$ - .get_GOT wrt ..gotpc

    mov      [rbx + last_tok wrt ..gotoff], rdi ; Store the contents of RDI at last_tok

    mov      rbx, [rbp - 8]
    leave
    ret

它可以与ELF32一起使用,但是对于ELF64,我收到以下错误:

nasm -f elf64  -o strtok.o strtok.s
strtok:15: error: ELF64 requires ..gotoff references to be qword
<builtin>: recipe for target 'strtok.o' failed
make: *** [strtok.o] Error 1

我做错了什么?

1 个答案:

答案 0 :(得分:4)

有效地址格式仅允许32位位移,符号扩展为64位。根据错误消息,您需要完整的64位。您可以通过寄存器添加它,例如:

mov      rax,  last_tok wrt ..gotoff
mov      [rbx + rax], rdi 

此外,call .get_GOT是32位解决方案,在64位模式下,您可以使用rip相对寻址。虽然上面可能会编译,但我不确定它是否会起作用。幸运的是,简单的解决方案是使用提到的rip相对寻址来访问您的变量:

    SECTION .data
    GLOBAL last_tok
last_tok:              dq 0     ; Define a QWORD

    SECTION .text
    GLOBAL strtok:function
strtok:
    mov      [rel last_tok wrt ..gotpc], rdi ; Store the contents of RDI at last_tok
    ret

请注意,对于私有(静态)变量,您只需使用[rel last_tok],而不必弄乱它。