Почему линкер дает такую ошибку?

Я пытаюсь инициализировать IDT, для использования прерывания клавиатуры. Действую по одному туториалу, изменяя его под себя. Вот мой код инициализации:

lib.cpp
#include <stdint.h>
extern "C" void mainCpp(); // для доступа из C, не важно
extern "C" void Work(); //функция проверки прерывания, не важно
extern "C" void outb(int, int);
struct IDT64
{
    uint16_t offset_low;
    uint16_t selector;
    uint8_t ist;
    uint8_t types_attr;
    uint16_t offset_mid;
    uint32_t offset_high;
    uint32_t zero;
};

extern IDT64 _idt[256];
extern uint64_t isrl;
extern "C" void LoadIDT();

void InitializeIDT() {
    for (uint64_t t = 0; t < 256; t++) {
        _idt[t].zero = 0;
        _idt[t].offset_low = (uint16_t)(((uint64_t)&isrl & 0x000000000000ffff));
        _idt[t].offset_mid = (uint16_t)(((uint64_t)&isrl & 0x00000000ffff0000) >> 16);
        _idt[t].offset_high = (uint32_t)(((uint64_t)&isrl & 0xfffffff00000000) >> 32);
        _idt[t].ist = 0;
        _idt[t].selector = 0x08;
        _idt[t].types_attr = 0x8e;
    }

    outb(0x21, 0xfd);
    outb(0xa1, 0xff);
    LoadIDT();
}

extern "C" void isrl_handler() {
    Work(); //не важно, любая функция при прерывании
    outb(0x20, 0x20);
    outb(0xa0, 0x20);
}

void mainCpp() 
{   
    InitializeIDT();
}


lib.asm
[bits 64]
global outb
global isrl
global LoadIDT

SECTION .text

[extern _idt]
idtDescriptor:
	dw 4095
	dq _idt

	%macro PUSHALL 0
		push rax
		push rcx
		push rdx
		push r8
		push r9
		push r10
		push r11
	%endmacro

	%macro POPALL 0
		pop r11
		pop r10
		pop r9
		pop r8
		pop rdx
		pop rcx
		pop rax
	%endmacro


[extern isrl_handler]

isrl:
	PUSHALL
	call isrl_handler
	POPALL
	iretq
	

LoadIDT:
	lidt[idtDescriptor]
	sti
	ret
	
outb: 
	mov   rdx, [rsp + 4]
	mov   al, [rsp + 4 + 4]
	out   dx, al
	ret


Компилирую я все это так:
nasm -felf64 -o lib.o lib.asm
clang++ -fno-stack-protector -fpic -fshort-wchar -mno-red-zone -DHAVE_USE_MS_ABI -c -o temporaryFiles/libCpp.o lib.cpp

И потом связываю (присутствуют остальные файлы, не обращайте на них внимания):
ld -nostdlib -znocombreloc -T /usr/lib/elf_x86_64_efi.lds -shared -Bsymbolic -L /usr/lib /usr/lib/crt0-efi-x86_64.o temporaryFiles/main.o temporaryFiles/libCpp.o  lib.o -o bootx64.so -lefi -lgnuefi

После выполнения команды выше я получаю
ld: lib.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
ld: failed to set dynamic section sizes: bad value

У кого нибудь есть идеи, что делать?
  • Вопрос задан
  • 71 просмотр
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
http://dilbert.com/strip/1998-08-24
relocation R_X86_64_32S against `.text' can not be used when making a shared object
что делать?

Переписать код так, чтобы избавиться от этой релокации.
Для этого посмотреть где она: objdump -dr lib.o

27:   0f 01 1c 25 00 00 00    lidt   0x0
2e:   00 
                        2b: R_X86_64_32S        .text


и переписать загрузку idt без использования константного адреса, например так (используя адресацию относительно pc):
lea rax, [rel idtDescriptor]
lidt [rax]


Однако, я подозреваю, что этого будет недостаточно, потому что
dq _idt
-- это ещё одна релокация в текстовом сегменте. Я не вижу как от неё можно избавиться кроме перемещения этой переменной в сегмент .data или .bss и инициализации этой переменной в процессе выполнения программы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы