本文介绍了NASM:在运行时从RIP(指令指针)获取重新定位的二进制的偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个适用于x86_64的兼容Multiboot2的ELF文件,其中开始符号在start.asm中定义,这是一个NASM程序集文件。Multiboot2标头包含relocatable标记。

由于GRUB不支持Multiboot2+a可重定位ELF(至少在2021年7月[3]),我希望自己解决一些重定位问题以解决此问题,并只加载静态ELF。

为此,我需要在运行时在我的第一个条目符号(在ELF头中指定)中获取偏移量,以便手动解析位置。对于偏移量,我指的是GRUB在内存中定位二进制文件的位置与ELF文件中符号的静态地址之间的差异。

在我的条目符号中,我处于64位长模式。无法在NASM语法中直接访问rip,因此我需要某种解决方法。

像[1][2]这样的解决方案不起作用,因为rip关键字/寄存器在NASM中不可用。因此我不能使用

lea    rax,[rip+0x1020304]
; rax contains offset
sub    rax,0x1020304

我如何解决此问题?

推荐答案

访问rip中的rip的唯一方法是通过rel-关键字[1]。如果没有一个奇怪的解决办法,它不能立即接受,而只能接受一个符号。要使用符号来求解它,可以使用以下代码:

; the function we want to jump to. We need to calculate the runtime
; address manually, because the ELF file is not relocatable, therefore static.
EXTERN entry_64_bit

; start symbol must be globally available (linker must find it, don't discard it)
; Referenced in ELF-Header.
GLOBAL start

SECTION .text

; always produce x-bit x86 code (even if this would be compiled to an ELF-32 file)
[BITS 64]

    ; very first entry point; this is the address where GRUB loads the binary
    start:
        ; save values provided by multiboot2 bootloader (removed here)
        ; ...

        ; Set stack top (removed here)
        ; ...

        ; rbx: static link address
        mov     rbx, .eff_addr_magic_end

        ; rax: runtime address (relative to instruction pointer)
        lea     rax, [rel + .eff_addr_magic_end]
    
    .eff_addr_magic_end:
        ; subtract address difference => offset
        sub     rax, rbx
        ; rax: address of Rust entry point (static link address + runtime offset)
        add     rax, entry_64_bit
        jmp     rax

请注意,这真的很棘手,需要几个低级别主题的深厚专业知识。请谨慎使用。

这篇关于NASM:在运行时从RIP(指令指针)获取重新定位的二进制的偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 22:52