Why is a cross compiler "needed"?

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.
Post Reply
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Why is a cross compiler "needed"?

Post by proxy »

So this is going to come off like a silly question, but bear with me. I've dabbled with my hobby OS for something like 15 years now.

Basically, I compile with `-mcmodel=kernel -ffreestanding -nostdinc` plus a boat load of other flags and use a custom linker script. I've written my own "libc" and my own "libstdc++" and provide their include paths and link to them when building. I also link to `-lgcc` just in case the compiler decides to use a builtin that requires its support library.

This works! It's kinda always worked, and AFAIK, is basically what the linux folks do too right?

So how come (at least in the past few years), the primary advice I see in this forum, the wiki, and even on r/osdev, is that people should **definitely** be using a cross compiler? What am I missing? Is it just to make certain things simpler instead of manually providing all the libraries and paths, the triplet will make the compiler just "know" what you prefer?

I've read: https://wiki.osdev.org/GCC_Cross-Compil ... _necessary

And it just basically just says "unless a lot of problematic options are passed to it, which will create a lot of problems in the future" which is kinda vague. Like I said, I've had the same build process for like 15 years and haven't run into any issues (that I know of), so what am I missing?
nullplan
Member
Member
Posts: 1789
Joined: Wed Aug 30, 2017 8:24 am

Re: Why is a cross compiler "needed"?

Post by nullplan »

It is very easy this way to end up with a setup that seems to work, but doesn't actually. Worse, it is possible for this to blow up only in a rarely used error branch. So the time bomb lurks in your code, waiting to spring on you in the worst moment.

A bit less dramatically, using a Linux compiler makes the compiler assume the code will be compiled to run on Linux. Depending on architecture, this can have dramatic effects:
  • On ARM32, if compiling for armv4, GCC will implement its builtin compare-and-swap routine (I forget what it was called) by calling the Linux kuser helper at 0xffff0fc0. Bad news if you don't have that helper in your OS.
  • On ARM32 (again), if compiling for a CPU level that doesn't have a hardware divider, the software division algorithm in libgcc would call raise(SIGFPE) in earlier versions of gcc if the divisor was zero. This, too, is bad news if you are compiling a kernel.
  • On x86 and x86_64, gcc will presume the thread pointer to be available under %gs:0 and %fs:0 respectively. It will presume the stack canary to be there at the specific offsets glibc has for -fstack-protector, and it will presume to be able to use those registers to look up TLS offsets in the local-exec TLS model, which it will use by default if compiling a static executable.
  • On PowerPC and PowerPC64, the thread pointer thing comes back, only now it is in r2 and r13 respectively. Again this comes into play for TLS and -fstack-protector.
And these are just the things I could think of off the top of my head. A lot of this can be mitigated with the correct options, but using a cross compiler reduces the amount of options needed to rid the compiler of its Linux assumptions.

Linux itself uses no cross compiler (normally), but it also has a giant workforce of competent individuals, that know exactly what options to pass to the compiler to make it generate the code that will work for Linux kernel mode. They also know which parts of the userland they need to emulate. For example, they go have a thread pointer at %gs:0, it's just a CPU pointer instead.
Carpe diem!
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: Why is a cross compiler "needed"?

Post by proxy »

@nullplan:

Thanks for the response. Your answer makes sense and is in line with the idea "yeah, you can do it without a cross compiler, but it can be made easier with one".

I actually do have `-fno-stack-protector` in my flags too and do explicitly avoid using TLS specifically because I don't want the compiler to generate code for those things. So I guess I've just been (unbeknownst to me) just working around these gotchas (and probably other too) you mentioned.

Appreciate the info!
Post Reply