Search code examples
macoslinkerld

GNU Linker equivalent command in OS X


I'm reading the following book about operating systems. In Page 43, they use the following command to convert annotated machine code into a raw machine code file:

$ ld -o basic.bin -Ttext 0x0 --oformat binary basic.o

When running that command in my MacBook Pro (running Mavericks), I get:

ld: unknown option: -Ttext

I've did some research and found out that OS X's linker doesn't allow using a script file as the linker script.

Some other posts on the internet recommend using the following "correct" format:

$ ld -T text 0x0 --o format binary -o basic.bin basic.o

Although it didn't work for me neither.

I also tried installing binutils via homebrew, but it doesn't seems to ship with GNU linker.

The command correctly runs in Ubuntu 14.04, but I'd like to continue developing in OS X if possible.

Is there a way to obtain the same results with OS X's linker, potentially with different flags?

UPDATE:

I was able to generate a bin with the following command, using gobjcopy from binutils:

$ gobjcopy -j .text -O binary basic.o basic.bin

However I couldn't find a way to offset label addresses in the code, as I could with GNU ld with -Ttext 0x1000 for example.

I tried with --set-start <hex> without any luck:

$ gobjcopy -j .text --set-start 0x1000 -O binary basic.o basic.bin

Solution

  • I am following the same os-dev.pdf guide and encountered the same problem as you.

    The bottom of the issue is that we need to compile a cross-compiled gcc anyway, so the solution is just to do so.

    There is a good guide at OSDev but if you're running a recent version of OSX I prepared a specific guide for this on Github

    Here are the commands, though please test them before pasting the whole wall of text on your computer! At the Github link you will find the full explanations, but since Stack Overflow seems to like the solution embedded on the answer, here it is.

    Also, if you encounter any error, please report it back to me (here or with a Github issue) so that I can fix it for other people.

    brew install gmp
    brew install mpfr
    brew install libmpc
    brew install gcc
    
    export CC=/usr/local/bin/gcc-4.9
    export LD=/usr/local/bin/gcc-4.9
    
    export PREFIX="/usr/local/i386elfgcc"
    export TARGET=i386-elf
    export PATH="$PREFIX/bin:$PATH"
    
    mkdir /tmp/src
    cd /tmp/src
    curl -O http://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.gz # If the link 404's, look for a more recent version
    tar xf binutils-2.24.tar.gz
    mkdir binutils-build
    cd binutils-build
    ../binutils-2.24/configure --target=$TARGET --enable-interwork --enable-multilib --disable-nls --disable-werror --prefix=$PREFIX 2>&1 | tee configure.log
    make all install 2>&1 | tee make.log
    
    cd /tmp/src
    curl -O http://mirror.bbln.org/gcc/releases/gcc-4.9.1/gcc-4.9.1.tar.bz2
    tar xf gcc-4.9.1.tar.bz2
    mkdir gcc-build
    cd gcc-build
    ../gcc-4.9.1/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers
    make all-gcc 
    make all-target-libgcc 
    make install-gcc 
    make install-target-libgcc 
    

    You will find GNU's binutils and your cross-compiled gcc at /usr/local/i386elfgcc/bin