Example:
Code: Select all
IDT_set_gate(0, ISR0, ...)
Code: Select all
mov -0x...(%rip), %rsi
Code: Select all
lea -0x...(%rip), %rsi
Code: Select all
IDT_set_gate(0, IDT_initialize, ...)
What is causing this and how can I fix this?
Code: Select all
IDT_set_gate(0, ISR0, ...)
Code: Select all
mov -0x...(%rip), %rsi
Code: Select all
lea -0x...(%rip), %rsi
Code: Select all
IDT_set_gate(0, IDT_initialize, ...)
Code: Select all
extern const char ISR0[];
Code: Select all
extern unsigned long ISR0;
Code: Select all
void ISR0();
Code: Select all
void ISR0();
void ISR1();
void ISR2();
void ISR3();
void ISR4();
...
void ISR_initialize()
{
IDT_set_gate(0, ISR_initialize, GDT_KCS, 0, 0xf); // "Works"
// -> lea -0x1e(%rip), %rsi
IDT_set_gate(0, ISR0, GDT_KCS, 0, 0xf); // Does not work
// -> mov -0x33a(%rip), %rsi
IDT_set_gate(1, ISR1, GDT_KCS, 0, 0xf);
IDT_set_gate(2, ISR2, GDT_KCS, 0, 0xf);
IDT_set_gate(3, ISR3, GDT_KCS, 0, 0xf);
IDT_set_gate(4, ISR4, GDT_KCS, 0, 0xf);
...
}
Code: Select all
void IDT_set_gate(int interrupt, void (*base)(), uint16_t segment, int privilege, int type)
{
if(interrupt > 255)return;
idt[interrupt].base_low = ((uintptr_t)base) & 0xffff;
idt[interrupt].base_mid = (((uintptr_t)base) >> 16) & 0xffff;
idt[interrupt].base_high = ((uintptr_t)base) >> 32;
idt[interrupt].segment = segment;
idt[interrupt].flags = (privilege << 13) | ((type & 0xf) << 8);
idt[interrupt].flags |= IDT_ENABLE_FLAG;
}
Code: Select all
void (*isrs[])() = {
ISR0, ISR1, ISR2, ISR3,
ISR4, ISR5, ISR6, ISR7,
ISR8, ISR9, ISR10, ISR11,
ISR12, ISR13, ISR14, ISR15,
ISR16, ISR17, ISR18, ISR19,
ISR20, ISR21, ISR22, ISR23,
ISR24, ISR25, ISR26, ISR27,
ISR28, ISR29, ISR30, ISR31,
ISR32, ISR33, ISR34, ISR35,
ISR36, ISR37, ISR38, ISR39,
ISR40, ISR41, ISR42, ISR43,
ISR44, ISR45, ISR46, ISR47,
};
Code: Select all
IDT_set_gate(0, isrs[0], GDT_KCS, 0, 0xf);
Code: Select all
KERNEL_PM = 0x100000
KERNEL_VM = 0xffff800000100000
KERNEL_VM_OFFSET = KERNEL_VM - KERNEL_PM
ENTRY(k32_entry)
OUTPUT_FORMAT("binary")
SECTIONS
{
. = KERNEL_PM;
... k32 stuff
. = ALIGN(4096);
. += KERNEL_VM_OFFSET;
.text : AT(ADDR(.text) - KERNEL_VM_OFFSET) {...}
+ other sections
+ discards
}
You should use a cross-compiler. Since you're not using a cross-compiler, you get whatever default options the package maintainers decided to use when they built your copy of GCC, and I'd guess they decided to enable PIC by default. I'm not sure why your resulting binary isn't statically linked correctly, but disabling PIC (-fno-pic) will fix that. If you disable PIC you'll also need to specify the code model according to the address where your kernel is linked. The current address you're using requires the large code model (-mcmodel=large), but if you change it to 0xFFFFFFFF80000000 or higher, you can use the kernel code model (-mcmodel=kernel).SomePerson wrote: ↑Sun Sep 15, 2024 3:33 pmgcc -Wall -Wextra -O3 -ffreestanding -nostdlib -c $< -o $@
Code: Select all
lea 0x0(%rip),%rax
vs
mov 0x0(%rip),%rax
Code: Select all
lea -0x16(%rip),%rax
vs
mov $0x40103b,%rax
Code: Select all
lea -0x16(%rip),%rax
vs
mov 0xb(%rip),%rax
Code: Select all
#include <stdint.h>
void take_func(uint64_t offset) {
}
int c_func() {
return 0x101010;
}
extern int extern_func();
void _start() {
take_func((uint64_t)&c_func);
take_func((uint64_t)&extern_func);
}
Code: Select all
int extern_func() {
return 0x111111;
}
Code: Select all
x86_64-linux-gnu-gcc -c c_code.c -o c_code.o
x86_64-linux-gnu-gcc -c extern_code.c -o extern_code.o
x86_64-linux-gnu-ld --oformat=binary *.o -o linked.bin
x86_64-linux-gnu-ld --oformat=elf64-x86-64 *.o -o linked.elf
Code: Select all
000000000000000b <c_func>:
b: 55 push %rbp
c: 48 89 e5 mov %rsp,%rbp
f: b8 10 10 10 00 mov $0x101010,%eax
14: 5d pop %rbp
15: c3 ret
0000000000000016 <_start>:
16: 55 push %rbp
17: 48 89 e5 mov %rsp,%rbp
1a: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 21 <_start+0xb>
21: 48 89 c7 mov %rax,%rdi
24: e8 00 00 00 00 call 29 <_start+0x13>
29: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 30 <_start+0x1a>
30: 48 89 c7 mov %rax,%rdi
33: e8 00 00 00 00 call 38 <_start+0x22>
38: 90 nop
39: 5d pop %rbp
3a: c3 ret
Code: Select all
b: 55 push %rbp
c: 48 89 e5 mov %rsp,%rbp
f: b8 10 10 10 00 mov $0x101010,%eax
14: 5d pop %rbp
15: c3 ret
16: 55 push %rbp
17: 48 89 e5 mov %rsp,%rbp
1a: 48 8d 05 ea ff ff ff lea -0x16(%rip),%rax # 0xb
21: 48 89 c7 mov %rax,%rdi
24: e8 d7 ff ff ff call 0x0
29: 48 8b 05 0b 00 00 00 mov 0xb(%rip),%rax # 0x3b
30: 48 89 c7 mov %rax,%rdi
33: e8 c8 ff ff ff call 0x0
38: 90 nop
39: 5d pop %rbp
3a: c3 ret
3b: 55 push %rbp
3c: 48 89 e5 mov %rsp,%rbp
3f: b8 11 11 11 00 mov $0x111111,%eax
44: 5d pop %rbp
45: c3 ret
Code: Select all
000000000040100b <c_func>:
40100b: 55 push %rbp
40100c: 48 89 e5 mov %rsp,%rbp
40100f: b8 10 10 10 00 mov $0x101010,%eax
401014: 5d pop %rbp
401015: c3 ret
0000000000401016 <_start>:
401016: 55 push %rbp
401017: 48 89 e5 mov %rsp,%rbp
40101a: 48 8d 05 ea ff ff ff lea -0x16(%rip),%rax # 40100b <c_func>
401021: 48 89 c7 mov %rax,%rdi
401024: e8 d7 ff ff ff call 401000 <take_func>
401029: 48 c7 c0 3b 10 40 00 mov $0x40103b,%rax
401030: 48 89 c7 mov %rax,%rdi
401033: e8 c8 ff ff ff call 401000 <take_func>
401038: 90 nop
401039: 5d pop %rbp
40103a: c3 ret
000000000040103b <extern_func>:
40103b: 55 push %rbp
40103c: 48 89 e5 mov %rsp,%rbp
40103f: b8 11 11 11 00 mov $0x111111,%eax
401044: 5d pop %rbp
401045: c3 ret
I wouldn't be surprised if those optimizations only work on ELF output. But why are you compiling position-independent code in the first place?