I've created an extremely useful tool for kernel developers
Posted: Fri Dec 07, 2018 7:27 am
Hello
I'm writing my own kernel, and after month of hitting the wall with my head I've found a way to
a) boot 64bit kernels from GRUB without assembly files
b) eliminate global offset table
I hope it will be useful for you.
My goal was to write 32bit code which deals with GRUB, creates page tables, GDT and other stuff in C++. Linker refuses to link 32bit and 64bit object files, but feels ok if you translate 32bit sources to assembly(with gcc -S), and them compile them as 64bit object files. The tool detects "#define MULTIBOOT_INTERFACE" line in source files and builds them with -m32 -S flags, then postprocesses assembly code and compiles the result into 64bit object files. Another problem is GOT with I don't want to see in my binary. This problem is solved during postprocessing stage.
During postprocessing stage I insert dummy section in file header:
Also I remove .file directive because I dislike it, and #APP / #NOAPP lines - gcc wraps my inline assembly with them.
Then each GOT address calculation is modified:
Then each reference to GOT is replaced with address of label relative to .Ltext_offset:
Upd: there is an unfixed problem with static variables:
Please move all such variables into a static structure and get a pointer to this structure:
There are still problems with instructions like movzbl, I'll fix them soon.
Regards,
Dmitry
I'm writing my own kernel, and after month of hitting the wall with my head I've found a way to
a) boot 64bit kernels from GRUB without assembly files
b) eliminate global offset table
I hope it will be useful for you.
My goal was to write 32bit code which deals with GRUB, creates page tables, GDT and other stuff in C++. Linker refuses to link 32bit and 64bit object files, but feels ok if you translate 32bit sources to assembly(with gcc -S), and them compile them as 64bit object files. The tool detects "#define MULTIBOOT_INTERFACE" line in source files and builds them with -m32 -S flags, then postprocesses assembly code and compiles the result into 64bit object files. Another problem is GOT with I don't want to see in my binary. This problem is solved during postprocessing stage.
During postprocessing stage I insert dummy section in file header:
Code: Select all
.text
.Ltext_offset:
Then each GOT address calculation is modified:
Code: Select all
call __x86.get_pc_thunk.bx
// addl $_GLOBAL_OFFSET_TABLE_, %ebx
addl $(.Ltext_offset - .), %ebx
Code: Select all
// leal .LC0@GOTOFF(%ebx), %eax
movl $(.LC0-.Ltext_offset), %eax
addl %ebx, %eax
Code: Select all
int foo;
void bar() {
m = foo;
...
foo = n;
}
Code: Select all
struct fb_parameters {
uint64 address = 0xB8000;
uint32 width = 80;
uint32 height = 24;
uint32 pitch = 0;
uint32 bpp = 0;
uint32 color = 0;
uint32 x = 0, w = 0;
static void (*putchar)(int);
};
static fb_parameters fb;
void print32 (const char *format, ...) {
auto f = &::fb;
...
}
Regards,
Dmitry