Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
I'm writing an x86_64 kernel in C++ with a g++ 4.9.1 cross-compiler (target is x86_64-elf). I've just written the crt{i,n}.o stubs and linked them into my kernel, along with the cross-compiler's crtbegin.o and crtend.o but I'm still getting relocation errors:
[...]/lib/gcc/x86_64-elf/4.9.1/crtbegin.o: In function `deregister_tm_clones':
crtstuff.c:(.text+0x1): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .jcr section in [...]/kernel-x86_64-elf.0.1
crtstuff.c:(.text+0x21): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
[...]/lib/gcc/x86_64-elf/4.9.1/crtbegin.o: In function `register_tm_clones':
crtstuff.c:(.text+0x41): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .jcr section in [...]/kernel-x86_64-elf.0.1
crtstuff.c:(.text+0x6f): relocation truncated to fit: R_X86_64_32 against `.tm_clone_table'
[...]/lib/gcc/x86_64-elf/4.9.1/crtbegin.o: In function `__do_global_dtors_aux':
crtstuff.c:(.text+0x8f): relocation truncated to fit: R_X86_64_32 against symbol `__DTOR_END__' defined in .dtors section in [...]/lib/gcc/x86_64-elf/4.9.1/crtend.o
crtstuff.c:(.text+0xe6): relocation truncated to fit: R_X86_64_32 against `.eh_frame'
[...]/lib/gcc/x86_64-elf/4.9.1/crtbegin.o: In function `frame_dummy':
crtstuff.c:(.text+0x10f): relocation truncated to fit: R_X86_64_32 against `.bss'
crtstuff.c:(.text+0x114): relocation truncated to fit: R_X86_64_32 against `.eh_frame'
crtstuff.c:(.text+0x11e): relocation truncated to fit: R_X86_64_32 against `.jcr'
[...]//lib/gcc/x86_64-elf/4.9.1/crtend.o: In function `__do_global_ctors_aux':
crtstuff.c:(.text+0x6): relocation truncated to fit: R_X86_64_32 against `.ctors'
abi/cxa_guard.o:(.debug_info+0x6): additional relocation overflows omitted from the output
'
These relocation errors seem to be in the cross-compilers code and not mine (I had some relocation problems but I solved them; partly by discarding stabs stuff). Does that mean I need to recompile something? I couldn't find anything on the net about these particular relocation errors, and I couldn't fix it by myself based on the errors I've had before.
Edit:
I have tried using -mcmodel=large, -fPIC (together and separately) and -m64 but I got the same errors
I don't think its possible to have crtbegin/crtend linked anywhere outside of the first 4 GiB of address space. The issue is that libgcc/crtstuff.c generates lots of code of the form mov eax, label (as imm32). The use of this form, rather than mov rax, label (as imm32), means that the label is not sign-extended to 64-bits by the CPU and so negative values cannot be used. Thus R_X86_64_32 references are used in the crtbegin/end.o files, instead of R_X86_64_32S ones, and the linker rightly complains. I'd imagine this behaviour is due to Linux running user space programs at a low address (and so this isn't an issue for them) and them not using C++ in the kernel.
All I can suggest is either linking crtbegin/end to a low address, or somehow changing the arguments used to build crtbegin/end in the first place (and add -mcmodel=kernel/large to it).
jnc100 wrote:I don't think its possible to have crtbegin/crtend linked anywhere outside of the first 4 GiB of address space. The issue is that libgcc/crtstuff.c generates lots of code of the form mov eax, label (as imm32). The use of this form, rather than mov rax, label (as imm32), means that the label is not sign-extended to 64-bits by the CPU and so negative values cannot be used. Thus R_X86_64_32 references are used in the crtbegin/end.o files, instead of R_X86_64_32S ones, and the linker rightly complains. I'd imagine this behaviour is due to Linux running user space programs at a low address (and so this isn't an issue for them) and them not using C++ in the kernel.
All I can suggest is either linking crtbegin/end to a low address, or somehow changing the arguments used to build crtbegin/end in the first place (and add -mcmodel=kernel/large to it).
Regards,
John.
Thanks for the info. I will try linking them into my bootstrap code which is at physical address 0x100000. I already have initialize() and finalize() functions which call _init/_fini instead of calling them directly, so in those functions I can subtract the kernel's virtual address 0xFFFFFFFF80000000 to call them. I think. I'll post back here if I get it working or not. I'm currently recompiling my cross-compilers. It looks like there are new files/directories in my cross-compiler directory so I think I did something wrong last time.
[edit] I got it to work by rebuilding my cross-compiler as x86_64-none-elf, building all-gcc as normal, but doing a find-and-replace from "-fPIC" to "-mcmodel=kernel" in {build-dir}/x86_64-none-elf/libgcc/Makefile. Readelf still says the relocations are 32-bit but it links now.
Synon wrote:I got it to work by rebuilding my cross-compiler as x86_64-none-elf, building all-gcc as normal, but doing a find-and-replace from "-fPIC" to "-mcmodel=kernel" in {build-dir}/x86_64-none-elf/libgcc/Makefile. Readelf still says the relocations are 32-bit but it links now.
Good work, however bear in mind that you probably want a libgcc linked without mcmodel=kernel for usermode applications, otherwise they could not be linked above +2 GiB. This may of course not be a problem for you. I'd imagine your new 32-bit relocations are signed ones rather than unsigned?