Libgcc without red zone: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Solved a writing fault in a Link)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(8 intermediate revisions by 6 users not shown)
Line 1:
{{Main | Libgcc}}
 
This article discuses how to build [[libgcc]] without the need to support a <tt>red-zone</tt> in your kernel.
If you're not targeting [[X86-64|x86-64]] you don't need this as i*86 has no such requirements.
 
== What is the 'red-zone'? ==
The <tt>red-zone</tt> is a feature described in the [[X86System V ABI#x86-64|x86-64]] ABI]].
 
It is a 128 byte long region located directly below the stack pointer. This region is free-for-use for the compiler without the requirement to notify the application / the os or any running interrupt handler.
Line 14:
 
To get around this the <tt>red-zone</tt> can be disabled by passing <tt>-mno-red-zone</tt> to [[GCC]].
<sourcesyntaxhighlight lang="bash">x86_64-elf-gcc $CFLAGS -mno-red-zone ...</sourcesyntaxhighlight>
 
== Why modify libgcc? ==
If you link against [[libgcc]] (as you should) there is one problem: <u>[[libgcc]] is build with <tt>red-zone</tt> <u>enabled</u>.
 
So while your kernel works just fine the methods in [[libgcc]] may mess things up by accident.
Line 28:
 
Create the following file and save it as <tt>t-x86_64-elf</tt> inside <i><tt>gcc/config/i386/</tt></i> under your [[GCC]] sources.
<sourcesyntaxhighlight lang="Make">
# Add libgcc multilib variant without red-zone requirement
 
MULTILIB_OPTIONS += mno-red-zone
MULTILIB_DIRNAMES += no-red-zone
</syntaxhighlight>
</source>
 
By default this new configuration will not be used by [[GCC]] unless it's explicitly told to.
Open <tt>gcc/config.ccgcc</tt> in your favorite editor and search for case block like this:
<sourcesyntaxhighlight lang="bash">
x86_64-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h"
;;
</syntaxhighlight>
</source>
 
This is the target configuration used when creating a [[GCC Cross-Compiler]] for x86_64-elf.
Modify it to include the new [[multilib]] configuration:
<sourcesyntaxhighlight lang="bash">
x86_64-*-elf*)
tmake_file="${tmake_file} i386/t-x86_64-elf" # include the new multilib configuration
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h"
;;
</syntaxhighlight>
</source>
 
== Building libgcc ==
Line 56:
Run configure and then invoke the <tt>all-target-libgcc</tt> and <tt>install-target-libgcc</tt> as usual and [[GCC]] will build [[libgcc]] in two versions - one with <tt>red-zone</tt> enabled and one without.
You can check the successful build by checking the installed <tt>libgcc.a</tt> archives:
<sourcesyntaxhighlight lang="bash">
find $TOOLCHAIN_PREFIX/lib -name 'libgcc.a'
</syntaxhighlight>
</source>
 
If all went well you should see an additional [[libgcc]] installed in the <tt>no-red-zone</tt> multilib directory:
<sourcesyntaxhighlight lang="text">
./gcc/x86_64-pc-elf/4.9.1/libgcc.a
./gcc/x86_64-pc-elf/4.9.1/no-red-zone/libgcc.a
</syntaxhighlight>
</source>
 
== Linking against the correct multilib version ==
Assuming you're using [[GCC]] to link your kernel you're probably fine. All that's needed is to make sure <tt>-mno-red-zone</tt> is in your <tt>LDFLAGS</tt> when doing the final linker call.
<sourcesyntaxhighlight lang="bash">
x86_64-elf-gcc $LDFLAGS -mno-red-zone -o kernel $SOURCES
</syntaxhighlight>
</source>
 
If you're unsure which [[libgcc]] version is going to be used you can check by passing <tt>-mno-red-zone</tt> and <tt>-print-libgcc-file-name</tt> to [[GCC]]:
<sourcesyntaxhighlight lang="bash">
x86_64-elf-gcc -mno-red-zone -print-libgcc-file-name
lib/gcc/x86_64-pc-elf/4.9.1/no-red-zone/libgcc.a
</syntaxhighlight>
</source>
 
==See Also==