mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Implement Makefile for building, running and debugging the kernel
The makefile provides the following targets: - kernel - iso - run - gdb It sniffs the OS type and when running on non-linux hosts it uses vagrant ssh and runs make with the above targets inside the vagrant box. The kernel build process consists of the following steps: 1) Compile arch-specific (only x86 for now) assembly files. 2) Run go build -n to obtain the build commands for our kernel. The makefile sets the build target to 386/linux so that our current rt0 implementation does not need to switch to long-mode. 3) The build commands are then patched to: - use build/ as the output directory - force the go linker to use external link mode and to place its output files (--tmpdir) to the build folder. By forcing external link mode, the go linker will emit a single go.o file which can be used by ld. 4) We run our own link step and use ld to link the rt0 .o files with the go.o file and provide a custom linker script to ensure that our multiboot record is located at the top of the kernel image so that grub can find it. The ISO build process sets up a minimal folder structure for building a bootable ISO (basically the kernel image plus a grub configuration) and runs grub-mkrescue to produce the ISO file. Both the run and the gdb targets assume that qemu is installed. The gdb target starts qemu, attaches the debugger and sets a breakpoint to the rt0 entrypoint.
This commit is contained in:
parent
865f46c467
commit
95569d2982
99
Makefile
Normal file
99
Makefile
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
OS = $(shell uname -s)
|
||||||
|
ARCH := x86
|
||||||
|
BUILD_DIR := build
|
||||||
|
BUILD_ABS_DIR := $(CURDIR)/$(BUILD_DIR)
|
||||||
|
|
||||||
|
kernel_target :=$(BUILD_DIR)/kernel-$(ARCH).bin
|
||||||
|
iso_target := $(BUILD_DIR)/kernel-$(ARCH).iso
|
||||||
|
|
||||||
|
ifeq ($(OS), Linux)
|
||||||
|
export SHELL := /bin/bash
|
||||||
|
|
||||||
|
LD := ld
|
||||||
|
AS := nasm
|
||||||
|
|
||||||
|
GOOS := linux
|
||||||
|
GOARCH := 386
|
||||||
|
|
||||||
|
LD_FLAGS := -n -melf_i386 -T arch/$(ARCH)/script/linker.ld -static --no-ld-generated-unwind-info
|
||||||
|
AS_FLAGS := -g -f elf32 -F dwarf -I arch/$(ARCH)/asm/
|
||||||
|
|
||||||
|
asm_src_files := $(wildcard arch/$(ARCH)/asm/*.s)
|
||||||
|
asm_obj_files := $(patsubst arch/$(ARCH)/asm/%.s, $(BUILD_DIR)/arch/$(ARCH)/asm/%.o, $(asm_src_files))
|
||||||
|
|
||||||
|
.PHONY: kernel iso clean
|
||||||
|
|
||||||
|
kernel: $(kernel_target)
|
||||||
|
|
||||||
|
$(kernel_target): $(asm_obj_files) go.o
|
||||||
|
@echo "[$(LD)] linking kernel-$(ARCH).bin"
|
||||||
|
@$(LD) $(LD_FLAGS) -o $(kernel_target) $(asm_obj_files) $(BUILD_DIR)/go.o
|
||||||
|
|
||||||
|
go.o:
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
@echo "[go] compiling go sources into a standalone .o file"
|
||||||
|
@GOARCH=386 GOOS=linux go build -n 2>&1 | sed \
|
||||||
|
-e "1s|^|set -e\n|" \
|
||||||
|
-e "1s|^|export GOOS=linux\n|" \
|
||||||
|
-e "1s|^|export GOARCH=386\n|" \
|
||||||
|
-e "1s|^|WORK='$(BUILD_ABS_DIR)'\n|" \
|
||||||
|
-e "1s|^|alias pack='go tool pack'\n|" \
|
||||||
|
-e "/^mv/d" \
|
||||||
|
-e "s|-extld|-tmpdir='$(BUILD_ABS_DIR)' -linkmode=external -extldflags='-nostdlib' -extld|g" \
|
||||||
|
| sh 2>&1 | sed -e "s/^/ | /g"
|
||||||
|
|
||||||
|
@# build/go.o is a elf32 object file but all go symbols are unexported. Our
|
||||||
|
@# asm entrypoint code needs to know the address to 'main.main' so we use
|
||||||
|
@# objcopy to make that symbol exportable
|
||||||
|
@echo "[objcopy] export 'main.main' symbol in go.o"
|
||||||
|
@objcopy --globalize-symbol='main.main' $(BUILD_DIR)/go.o $(BUILD_DIR)/go.o
|
||||||
|
|
||||||
|
$(BUILD_DIR)/arch/$(ARCH)/asm/%.o: arch/$(ARCH)/asm/%.s
|
||||||
|
@mkdir -p $(shell dirname $@)
|
||||||
|
@echo "[$(AS)] $<"
|
||||||
|
@$(AS) $(AS_FLAGS) $< -o $@
|
||||||
|
|
||||||
|
iso: $(iso_target)
|
||||||
|
|
||||||
|
$(iso_target): $(kernel_target)
|
||||||
|
@echo "[grub] building ISO kernel-$(ARCH).iso"
|
||||||
|
|
||||||
|
@mkdir -p $(BUILD_DIR)/isofiles/boot/grub
|
||||||
|
@cp $(kernel_target) $(BUILD_DIR)/isofiles/boot/kernel.bin
|
||||||
|
@cp arch/$(ARCH)/script/grub.cfg $(BUILD_DIR)/isofiles/boot/grub
|
||||||
|
@grub-mkrescue -o $(iso_target) $(BUILD_DIR)/isofiles 2>&1 | sed -e "s/^/ | /g"
|
||||||
|
@rm -r $(BUILD_DIR)/isofiles
|
||||||
|
|
||||||
|
else
|
||||||
|
VAGRANT_SRC_FOLDER = /home/vagrant/workspace/src/github.com/achilleasa/gopher-os
|
||||||
|
|
||||||
|
.PHONY: kernel iso vagrant-up vagrant-down vagrant-ssh run gdb clean
|
||||||
|
|
||||||
|
kernel:
|
||||||
|
vagrant ssh -c 'cd $(VAGRANT_SRC_FOLDER); make kernel'
|
||||||
|
|
||||||
|
iso:
|
||||||
|
vagrant ssh -c 'cd $(VAGRANT_SRC_FOLDER); make iso'
|
||||||
|
|
||||||
|
run: iso
|
||||||
|
qemu-system-i386 -cdrom $(iso_target)
|
||||||
|
|
||||||
|
gdb: iso
|
||||||
|
qemu-system-i386 -s -S -cdrom $(iso_target) &
|
||||||
|
sleep 1
|
||||||
|
gdb \
|
||||||
|
-ex "add-auto-load-safe-path $(pwd)" \
|
||||||
|
-ex "file $(kernel_target)" \
|
||||||
|
-ex "set disassembly-flavor intel" \
|
||||||
|
-ex 'set arch i386:intel' \
|
||||||
|
-ex 'target remote localhost:1234' \
|
||||||
|
-ex 'layout asm' \
|
||||||
|
-ex 'b _rt0_entry' \
|
||||||
|
-ex 'continue' \
|
||||||
|
-ex 'disass'
|
||||||
|
@killall qemu-system-i386 || true
|
||||||
|
endif
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@test -d $(BUILD_DIR) && rm -rf $(BUILD_DIR) || true
|
7
arch/x86/script/grub.cfg
Normal file
7
arch/x86/script/grub.cfg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
set timeout=0
|
||||||
|
set default=0
|
||||||
|
|
||||||
|
menuentry "gopheros" {
|
||||||
|
multiboot2 /boot/kernel.bin
|
||||||
|
boot
|
||||||
|
}
|
35
arch/x86/script/linker.ld
Normal file
35
arch/x86/script/linker.ld
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
ENTRY(_rt0_entry)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
/* Kernel starts at 1M */
|
||||||
|
. = 1M;
|
||||||
|
|
||||||
|
/* ensure that the multiboot header is at the beginning */
|
||||||
|
.multiboot :
|
||||||
|
{
|
||||||
|
*(.multiboot_header)
|
||||||
|
}
|
||||||
|
|
||||||
|
.text BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-only data. */
|
||||||
|
.rodata BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read-write data (initialized) */
|
||||||
|
.data BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss BLOCK(4K) : ALIGN(4K)
|
||||||
|
{
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user