为什么我收到错误 ld: failed to conversion GOTPCREL relocation;将 C++ 与使用 nasm 或 as 组装的目标文件链接时,使用 --no-relax 重新链接?

2024-01-05

我正在编写一个小型 x86-64 内核。我正在设置 IDT 并遇到了一个我不太明白的奇怪错误。这是一个最小的例子:

entry.s

extern InterruptHandler
global isr0
align 4

isr0:
jmp sharedisr

sharedisr:
push rax
push rbx
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
cld

call InterruptHandler

pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
pop rbx
pop rax
iretq

idt.cpp

#include "idt.h"

struct IDTEntry{
    unsigned short offset0;     //bits 0-15
    unsigned short selector;    //0x08 = 1000b code selector
    unsigned char ist;      //0
    unsigned char attrib;       //
    unsigned short offset1;     //bits 16-31
    unsigned int offset2;   //bits 31-63
    unsigned int zero;      //0
}__attribute__((packed));

struct IDTR{
    unsigned short size;
    unsigned long address;
}__attribute__((packed));

unsigned long isrAddresses[1];
IDTEntry idt[1];

extern "C" void InterruptHandler(){
    
}

void SetupIDT(){
    isrAddresses[0] = {
        (unsigned long)&isr0
    };
    
    IDTEntry entry;
    for (unsigned int i = 0; i < 1; i++){
        entry.offset0 = (unsigned short)isrAddresses[i];
        entry.selector = 0x08;
        entry.ist = 0;
        entry.attrib = 0x8e;
        entry.offset1 = (unsigned short)(isrAddresses[i] >> 16);
        entry.offset2 = (unsigned int)(isrAddresses[i] >> 32);
        entry.zero = 0;
        idt[i] = entry;
    }
    
    unsigned long idtAddr = (unsigned long)idt;
    IDTR idtr = { 4096, idtAddr };
    unsigned long idtrAddr = (unsigned long)&idtr;
    asm volatile("lidt (%0)" : : "r"(idtrAddr));
}

idt.h

#ifndef IDTH
#define IDTH

extern "C" void isr0(void);
void SetupIDT();

#endif

main.cpp

#include "idt.h"

void main(){
    SetupIDT();
    asm volatile("hlt");
}

我用这个 bash 脚本编译并链接:

nasm entry.s -felf64 -oentry.o
g++ -static -ffreestanding -nostdlib -mgeneral-regs-only -mno-red-zone -c -m64 main.cpp -omain.o
g++ -static -ffreestanding -nostdlib -mgeneral-regs-only -mno-red-zone -c -m64 idt.cpp -oidt.o
ld -entry main --oformat elf64-x86-64 --no-dynamic-linker -static -nostdlib -Ttext-segment=ffff800001000000 entry.o main.o idt.o  -okernel.elf

我收到错误ld: failed to convert GOTPCREL relocation; relink with --no-relax。如果我添加--no-relaxld 的选项它有效并且代码实际上有效。我可以在 InterruptHandler 函数中打印一些内容并返回到触发异常的先前代码(我测试了它在故意引发的除以零的情况下工作)。

从错误中我猜想这与链接松弛有关,但我不知道它是什么。有人可以简要解释一下它是什么以及为什么我会收到错误吗?另外,任何人都可以就建立适当的 ISR 提供​​任何进一步的建议吗?例如,我应该推送 RBP 然后将 RSP 放入 RBP 中,就像 gcc 在使用时所做的那样__attribute__((interrupt))? ISR 末尾是否还应该有一个leaveq? ETC...

谢谢您的任何提示!


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我收到错误 ld: failed to conversion GOTPCREL relocation;将 C++ 与使用 nasm 或 as 组装的目标文件链接时,使用 --no-relax 重新链接? 的相关文章

随机推荐