M3 Operating System Development

A chronicle of the development of the M3 operating system

Posts Tagged ‘OS X

Tutorial – Building an i386-elf cross-compiler and binutils on OS X

with 2 comments

As I mentioned in my previous post, I managed to build a cross-compiler and binutils toolchain targeting i386-elf executables on OS X. While the process isn’t too difficult, there are a couple of gotchas that you should be aware of.

Before I start, I’d like to reference this tutorial for building an ARM cross-compiler on OS X. It provided a pretty good roadmap for me as I set out on my task.

OK – the first thing that you need to do is get the source code for both gcc and binutils. To do this, we’ll use a handy tool called wget. Unfortunately, OS X does not come with wget as one of its pre-installed apps, so we’ll have to install it. You can grab a copy of wget compiled for OS X here. Follow the instructions in the README to install it into the proper directories and add the proper folders to your PATH.

If you don’t want to install wget, OS X comes with a similar utility called curl. If you are comfortable using that tool, then adjust the wget commands below accordingly.

Now, drop to a command prompt and issue the following commands to download and extract the source code for binutils and gcc:

$ mkdir ~/crossgcc && cd ~/crossgcc
$ wget ftp://sourceware.org/pub/binutils/snapshots/binutils-2.18.50.tar.bz2
$ tar jxf binutils-2.18.50.tar.bz2
$ wget http://ftp.gnu.org/pub/gnu/gcc/gcc-4.2.3/gcc-4.2.3.tar.bz2
$ tar jxf gcc-4.2.3.tar.bz2

I've chosen a target directory of  /usr/local/i386elfgcc

We’ll have to create that directory and make it world writable for now:

$ sudo mkdir /usr/local/i386elfgcc
$ sudo chmod 777 /usr/local/i386elfgcc

First we build the binutils:

$ mkdir build-binutils && cd build-binutils
$ ../binutils-2.18.50/configure --target=i386-elf 
--prefix=/usr/local/i386elfgcc/ 2>&1 | tee configure.log
$ make all install 2>&1 | tee make.log

The compiler will do its thing for a few minutes. When it’s done, your cross-compiled binutils will be installed in the bin folder of the target folder.

Now we'll build the gcc compiler with C support. This is someplace that we need to specialize the configuration for OS X. Be sure to include the parameter --disable-libssp when you are running configure for gcc. Otherwise, your build will blow up with errors about libssp.

$ cd ../gcc-4.2.3
$ cd ..
$ mkdir build-gcc && cd build-gcc
$ ../gcc-4.2.3/configure --target=i386-elf 
--with-gnu-as --with-gnu-ld --disable-libssp --enable-languages=c 2>&1 | tee configure.log
$ make all install 2>&1 | tee make.log

The compiler will again do its thing for a few minutes. When it is done, your cross-compiled gcc will be installed in the bin folder of the target folder.

All the cross-compiled tools in our dev toolchain are now installed into


Because they are cross-compiled versions, they have different names from the standard tools, to avoid naming conflicts. For example, our cross-compiled gcc is called i386-elf-gcc. Basically, all the tools have the prefix i386-gcc.

If you’d like these tools to be generally accessible, you can add the target path to your PATH, in .bash_profile or a similar shell configuration file.

You’ve now got a complete cross-compiled development toolchain for targeting the IA-32 platform on OS X. Pat yourself on the back, and if you’re feeling especially amazed and encouraged by the many excellent free development tools available with source, show your support by donating to the Free Software Foundation.


Written by m3os

March 29, 2009 at 1:57 pm

Booting a C kernel on OS X – a bit of a snag

leave a comment »

Things were cruising along smoothly for a little while with the boot loader, but now I’ve run into a bit of a snag. Right now, the M3 boot loader will load up my simple “kernel” stub written in assembly just fine, but the goal for the M3 kernel is to have the entire thing written in C. So the next logical step in my development process is to figure out how to get my boot loader to load and hand over control to a simple C “kernel”, which is really just a stub that will print a line of text on the screen or something equally simple.

For this purpose, I’ve borrowed a simple C “kernel” from this article about mixing C and assembly. I was able to compile the code just fine, but my problems started when it came time to link everything together. I was getting errors about invalid command line parameters and the like. Particularly, it didn’t like the -T option, which indicates to the linker where the text section of the code should be loaded in memory. On OS X, the ld command has no such option.

After digging a bit deeper, I learned that the OS X tools don’t support the same binary file types as those on Linux or Windows. Notably absent is the ELF binary type – OS X dev tools simply don’t support the creation of such files, because OS X doesn’t support that format. Instead, OS X uses what’s called the Mach-O binary format.

I found what I think to be the command line equivalent of -T for ld on OS X. The option is -segaddr. I got everything linked together, but when I tried to run my code on Q(emu) it just hung.

At this point, I have two choices. The first is that I could dig around through some OS X documentation and try to figure out how to output a flat binary file instead of Mach-O. The second is that I take out the Eee PC and move my development over to that box, since it’s Linux.

I’m not giving up on OS X just yet, so for now I’m going to do a bit of research into the OS X dev tools and try to figure out how to get the linker to do my bidding. If that proves to be a no-go, then I’ll move over to Linux. Gotta keep the momentum going.

Written by m3os

March 14, 2009 at 9:03 am

Posted in Status Update

Tagged with , , ,