Building libgcc for mcmodel=kernel: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Rod (talk | contribs)
improvements. also address mcmodel=large.
m Bot: Replace deprecated source tag with syntaxhighlight
 
(5 intermediate revisions by 5 users not shown)
Line 1:
{{Rating|2}}
In [[X86-64|x86_64]], if you link (e.g. through a linker script) your kernel directly to the higher half of the virtual memory, you might want to build the kernel with <tt>-mcmodel=kernel</tt> or <tt>-mcmodel=large</tt>.
 
Also, if you link with <tt>libgcc</tt> and use <tt>crtbegin.o</tt> and <tt>crtend.o</tt> (see [[Calling_Global_Constructors|Calling Global Constructors]]), you might wand to build <tt>libgcc</tt> with <tt>-mcmodel=kernel</tt> or <tt>-mcmodel-large</tt>.
 
Otherwise, you may get errors when linking, either from <tt>crtstuff.c</tt> or from kernel code, like:
 
<sourcesyntaxhighlight lang="text">
.../crtbegin.o: In function `deregister_tm_clones':
crtstuff.c:(.text+0x2): relocation truncated to fit: R_X86_64_32 against symbol `__TMC_END__' defined in .dtors section in ...
Line 23 ⟶ 24:
crtstuff.c:(.text+0x13): relocation truncated to fit: R_X86_64_32 against `.ctors'
collect2: error: ld returned 1 exit status
</syntaxhighlight>
</source>
 
One solution is to build a specific cross compiler, used only for kernel compilation (different from the one used for the userland), with <tt>libgcc</tt> (where <tt>crtbegin.o</tt> and <tt>crtend.o</tt> are generated, from <tt>crtstuff.c</tt>) compiled, like the kernel, with <tt>-mcmodel=kernel</tt> or <tt>-mcmodel=large</tt>. As far as we can tell, you could even mix the two modes, e.g.: compile the kernel with <tt>-mcmodel=kernel</tt> and <tt>libgcc</tt> with <tt>-mcmodel=large</tt> or the other way around.
 
In this case we also use <tt>-mno-red-zone</tt> to compile <tt>libgcc</tt> because it may be needed for the kernel (see [[Libgcc_without_red_zone|Libgcc without red zone]]).
 
Afterwards, you can compile and link your kernel with the generated cross compiler using <tt>-mcmodel=kernel</tt> or <tt>-mcmodel=large</tt>, and <tt>-mno-red-zone</tt>, and link with <tt>crtbegin.o</tt> and <tt>crtend.o</tt>.
 
These recipes were tested and work at least for GCC 6.3, 7 and GCC 7.18.
 
Starting from the [[GCC_Cross-Compiler|GCC Cross-Compiler]] recipe, and using <tt>TARGET=x86_64-elf</tt>, we can proceed as in the next sections.
 
== Compiling libgcc with -mcmodel=kernel ==
Line 39 ⟶ 40:
This may require a workaround. First compile <tt>binutils</tt> as usual, then add the binaries to the <tt>PATH</tt>, and start to compile <tt>gcc</tt>. When compiling <tt>libgcc</tt> with <tt>-mcmodel=kernel</tt>, it will fail. Then patch the <tt>Makefile</tt> to disable <tt>PIC</tt>, repeat and continue:
 
<sourcesyntaxhighlight lang='"bash'">
# (...)
mkdir build
Line 51 ⟶ 52:
make install-gcc
make install-target-libgcc
</syntaxhighlight>
</source>
 
== Compiling libgcc with -mcmodel=large ==
Line 57 ⟶ 58:
First compile <tt>binutils</tt> as usual, then add the binaries to the <tt>PATH</tt>, and start to compile <tt>gcc</tt>. Then compile <tt>libgcc</tt> with <tt>-mcmodel=large</tt>:
 
<sourcesyntaxhighlight lang='"bash'">
# (...)
mkdir build
Line 66 ⟶ 67:
make install-gcc
make install-target-libgcc
</syntaxhighlight>
</source>
 
== See Also ==
=== Articles ===
* [[GCC_Cross-Compiler|GCC Cross-Compiler]]
* [[Libgcc]]
* [[Libgcc_without_red_zoneLibgcc|libgcc]]
* [[Libgcc_without_red_zone|libgcc without red zone]]
* [[Calling_Global_Constructors|Calling Global Constructors]]
 
[[Category:Compilers]]