185 lines
6.5 KiB
Markdown
185 lines
6.5 KiB
Markdown
layout: post
|
|
title: "New Environment"
|
|
subtitle: "A bit more and less modern tools"
|
|
tags: [osdev]
|
|
|
|
Two summers ago, I didn't always have access to my build computer, so I
|
|
came up with a convoluted development setup which could be run over an
|
|
ssh connection.
|
|
|
|
I would edit files locally using some graphical text editor. Then I
|
|
would save my files and wait for them to propagate to the build computer
|
|
through Dropbox.
|
|
Next I would run the build commands through ssh and then test the
|
|
results in bochs terminal mode.
|
|
|
|
Last summer I started using vim to edit the source directly on the build
|
|
computer, which meant I didn't have to wait for Dropbox.
|
|
Around the same time I started to find some awesome tools which have
|
|
been around for ages.
|
|
|
|
Those are, for example [tmux](http://tmux.sourceforge.net/) which is a
|
|
terminal multiplexer which runs circles around gnu screen in terms of
|
|
usability and features.
|
|
|
|
LLVM
|
|
----
|
|
|
|
I also started looking at the [llvm](http://llvm.org) compiler suite.
|
|
The main reason I've been using a cross compiler is that I'm building
|
|
under OSX. OSX has its own executable format (Mach-O something or other),
|
|
but I'd like to use gnu elf, because it's well documented and there's
|
|
lots of example code about. The gcc bundled with OSX only compiles for
|
|
OSX, obviously, but OSX recently started shipping with llvm and clang
|
|
instead.
|
|
|
|
Clang can apparently be used as a cross compiler whatever way it was
|
|
built, though the available documentation is a bit unclear on how
|
|
exactly to do this. Come to think of it, the available documentation is
|
|
a lot unclear on just about everything. Funny for a compiler which
|
|
boasts expressive error messages as a feature...
|
|
|
|
Anyway with clang version 3.1 you can compile i386-elf object files through
|
|
|
|
:::bash
|
|
$ clang -ccc-host-triple i386-pc-linux -c source.c -o object.o
|
|
|
|
`-ccc-host-triple` isn't mentioned even once in the documentation of
|
|
clang nor are the possible choices. `i386-elf` which is somewhat of a
|
|
standard does not work...
|
|
|
|
Since clang version 3.2 `-ccc-host-triple` has apparently been replaced
|
|
by `-target`. This change is, of course, not mentioned in the release
|
|
notes.
|
|
|
|
In short, the llvm project - though I appreciate the thought - is an
|
|
excellent example of why you should document your code, kids.
|
|
|
|
This being said. If you know of some secret stash of llvm or clang
|
|
documentation, please - PLEASE - let me know!
|
|
|
|
I still use clang for compiling my kernel, though. Mostly because of the
|
|
aforementioned expressive error messages. They really are a nice change
|
|
to gcc and in pretty colors too.
|
|
|
|
If you run OSX clang 3.1 is installed with the
|
|
current version of Xcode. Version 3.2 is installed by
|
|
[Homebrew](http://mxcl.github.com/homebrew/).
|
|
|
|
:::bash
|
|
$ homebrew install llvm
|
|
|
|
Binutils
|
|
--------
|
|
|
|
The linker supplied with llvm doesn't read linker scripts - and I didn't
|
|
even get it to link my kernel objects together at all anyway - so I
|
|
still use gnu binutils cross compiled for i386-elf.
|
|
|
|
However, I don't use the compiling process described in an earlier post.
|
|
Instead, again, I use Homebrew.
|
|
|
|
First of all, to get a working cross target binutils, the brew formula
|
|
will have to be changed a bit
|
|
|
|
:::bash
|
|
$ brew edit binutils
|
|
|
|
Change the last configure flag (` --enable-targets=x86_64-elf,arm-none-eabi,m32r`)
|
|
to `--target=i386-elf`. I also changed the `--program-prefix` to `i386-elf-`. Save the file and run
|
|
|
|
:::bash
|
|
$ brew install binutils
|
|
|
|
and you're good to go.
|
|
|
|
As a bonus, binutils also contains usefull tools like objdump and readelf.
|
|
|
|
Qemu
|
|
----
|
|
|
|
Up until a few days ago, after compiling my kernel, I mounted an ext2
|
|
image using mac-fuse, copied the kernel binary into it, unmounted the
|
|
image and tested it using bochs.
|
|
Bochs has a really nice text based interface which works well as long as
|
|
the OS is only text based anyway, also a great debugger. Unfortunately,
|
|
you can't use both at once, but most of the time you don't need an
|
|
actual debugger to find the problems anyway.
|
|
|
|
The whole process can be streamlined through some shell scripting and I
|
|
had the overhead reduced to almost nothing, I thought...
|
|
|
|
Then I decided to take a look at [qemu](http://wiki.qemu.org/Main_Page)
|
|
again. I used it once before, but stopped due to the lack of a debugger
|
|
and text mode if I recall correctly. I knew back then that it could be
|
|
debugged with [gdb](http://www.gnu.org/software/gdb/), but I was on a
|
|
windows machine in those days, and... well... don't really want to talk
|
|
about it...
|
|
|
|
Anyway, I started having some problems with mac-fuse, so I thought
|
|
I should take a look at qemu again, since it has built in emulation
|
|
of a boot loader and can run a lone kernel binary passed to it as an
|
|
argument. So I started to look it up and it turned out to actually have
|
|
a text mode (curses mode).
|
|
|
|
So I went out on a whim and tried
|
|
|
|
:::bash
|
|
$ brew info qemu
|
|
|
|
By now you should know pretty much what I think of Homebrew, so the
|
|
results of that command pretty much sealed the deal.
|
|
|
|
Now I run my kernel in qemu through
|
|
|
|
:::bash
|
|
$ qemu-system-i386 -kernel kernel/kernel -curses
|
|
|
|
Qemu also turned out to have a monitor mode which contains some of the
|
|
functions I used most often in the bochs debugger, such as printing the
|
|
memory map. Further, this could be accessed using telnet from a
|
|
different tmux pane.
|
|
|
|
:::bash
|
|
#!/bin/bash
|
|
tmux split-window -h 'qemu-system-i386 -kernel kernel/kernel -curses -monitor telnet:localhost:4444,server'
|
|
tmux select-pane -L
|
|
telnet localhost 4444
|
|
|
|
Finally, I also installed an i386-elf targeted version of gdb - using Homebrew, obviously, with the same trick as for binutils. Gdb is found in a different tap of homebrew, so that will have to be installed first
|
|
|
|
:::bash
|
|
$ brew tap homebrew/dupes
|
|
$ brew edit gdb
|
|
|
|
Add the flag `--target=i386-elf` to the configure flags, save and
|
|
|
|
:::bash
|
|
$ brew install gdb
|
|
|
|
This will link to `ì386-elf-gdb` and can be run in yet another tmux window.
|
|
|
|
:::bash
|
|
#!/bin/bash
|
|
tmux split-window -h 'qemu-system-i386 -kernel kernel/kernel -curses -monitor telnet:localhost:4444,server -s -S'
|
|
tmux select-pane -L
|
|
tmux slit-window -v 'i386-elf-gdb'
|
|
tmux select-pane -U
|
|
telnet localhost 4444
|
|
|
|
Upon start, gdb will look for a file called `.gdbinit` which in my case contains
|
|
|
|
file kernel/kernel
|
|
target remote localhost:1234
|
|
|
|
Results
|
|
-------
|
|
|
|
[](/media/img/osdev_build_env_full.png)
|
|
|
|
Now that's neat!
|
|
|
|
The results can also be seen in git commit [0699c20381](https://github.com/thomasloven/os5/tree/0699c203818ec1d018c93b0192fba48ccb6879d8).
|
|
|
|
|