Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/Makefile.common	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -250,5 +250,5 @@
 
 COMPONENTS = \
-	$(KERNEL_PATH)/kernel.bin \
+	$(KERNEL_PATH)/kernel.elf \
 	$(INIT_TASKS) \
 	$(INITRD).img
Index: boot/Makefile.grub
===================================================================
--- boot/Makefile.grub	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/Makefile.grub	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -85,5 +85,5 @@
 	for module in $(MODULES) ; do \
 		echo "	echo 'Loading $$module'" >> $(BOOT_CONFIG) ; \
-		if [ "$$module" = "kernel.bin" ] ; then \
+		if [ "$$module" = "kernel.elf" ] ; then \
 			echo "	$(MULTIBOOT_CMD) /boot/$$module" >> $(BOOT_CONFIG) ; \
 		else \
Index: boot/arch/arm32/Makefile.inc
===================================================================
--- boot/arch/arm32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/arm32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -107,3 +107,4 @@
 	generic/src/gzip.c \
 	generic/src/tar.c \
+	generic/src/kernel.c \
 	generic/src/payload.c
Index: boot/arch/arm32/src/main.c
===================================================================
--- boot/arch/arm32/src/main.c	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/arm32/src/main.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -50,4 +50,5 @@
 #include <arch/cp15.h>
 #include <payload.h>
+#include <kernel.h>
 
 static void clean_dcache_poc(void *address, size_t size)
@@ -104,6 +105,8 @@
 	clean_dcache_poc(boot_pt, PTL0_ENTRIES * PTL0_ENTRY_SIZE);
 
+	uintptr_t entry = check_kernel((void *) PA2KA(BOOT_OFFSET));
+
 	printf("Booting the kernel...\n");
-	jump_to_kernel((void *) PA2KA(BOOT_OFFSET), &bootinfo);
+	jump_to_kernel((void *) entry, &bootinfo);
 }
 
Index: boot/arch/ia64/Makefile.inc
===================================================================
--- boot/arch/ia64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ia64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -61,4 +61,5 @@
 	generic/src/tar.c \
 	generic/src/gzip.c \
+	generic/src/kernel.c \
 	generic/src/payload.c
 
Index: boot/arch/ia64/include/arch/arch.h
===================================================================
--- boot/arch/ia64/include/arch/arch.h	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ia64/include/arch/arch.h	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -36,4 +36,5 @@
 #define LOADER_ADDRESS  0x4400000
 #define KERNEL_ADDRESS  0x4800000
+#define KERNEL_VADDRESS 0xe000000004800000
 
 #define STACK_SIZE                   8192
Index: boot/arch/ia64/src/main.c
===================================================================
--- boot/arch/ia64/src/main.c	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ia64/src/main.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -44,4 +44,5 @@
 #include <errno.h>
 #include <payload.h>
+#include <kernel.h>
 
 #define DEFAULT_MEMORY_BASE		0x4000000ULL
@@ -182,5 +183,11 @@
 	    (uintptr_t) kernel_start, NULL);
 
-	printf("Booting the kernel ...\n");
-	jump_to_kernel(&bootinfo, kernel_start);
+	uintptr_t entry = check_kernel(kernel_start);
+
+	// FIXME: kernel's entry point is linked at a different address than
+	//        where it is run from.
+	entry = entry - KERNEL_VADDRESS + KERNEL_ADDRESS;
+
+	printf("Booting the kernel at %p...\n", (void *) entry);
+	jump_to_kernel(&bootinfo, (void *) entry);
 }
Index: boot/arch/mips32/Makefile.inc
===================================================================
--- boot/arch/mips32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/mips32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -88,3 +88,4 @@
 	generic/src/gzip.c \
 	generic/src/tar.c \
+	generic/src/kernel.c \
 	generic/src/payload.c
Index: boot/arch/mips32/src/main.c
===================================================================
--- boot/arch/mips32/src/main.c	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/mips32/src/main.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -40,4 +40,5 @@
 #include <errno.h>
 #include <payload.h>
+#include <kernel.h>
 
 static bootinfo_t *bootinfo = (bootinfo_t *) PA2KA(BOOTINFO_OFFSET);
@@ -78,5 +79,7 @@
 	}
 
-	printf("Booting the kernel ... \n");
-	jump_to_kernel((void *) PA2KA(BOOT_OFFSET), bootinfo);
+	uintptr_t entry = check_kernel(kernel_start);
+
+	printf("Booting the kernel...\n");
+	jump_to_kernel((void *) entry, bootinfo);
 }
Index: boot/arch/ppc32/Makefile.inc
===================================================================
--- boot/arch/ppc32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ppc32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -76,3 +76,4 @@
 	generic/src/gzip.c \
 	generic/src/tar.c \
+	generic/src/kernel.c \
 	generic/src/payload.c
Index: boot/arch/ppc32/_link.ld.in
===================================================================
--- boot/arch/ppc32/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ppc32/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -6,5 +6,4 @@
 		loader_start = .;
 		*(BOOTSTRAP);
-		*(REALMODE);
 		*(.text);
 	}
Index: boot/arch/ppc32/src/asm.S
===================================================================
--- boot/arch/ppc32/src/asm.S	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ppc32/src/asm.S	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -152,7 +152,4 @@
 FUNCTION_END(jump_to_kernel)
 
-.section REALMODE, "ax"
-
-.align PAGE_WIDTH
 SYMBOL(real_mode)
 
Index: boot/arch/ppc32/src/main.c
===================================================================
--- boot/arch/ppc32/src/main.c	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/ppc32/src/main.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -42,4 +42,5 @@
 #include <errno.h>
 #include <payload.h>
+#include <kernel.h>
 
 #define BALLOC_MAX_SIZE  131072
@@ -68,6 +69,4 @@
 	printf(" %p|%p: real mode trampoline\n", &real_mode, real_mode_pa);
 	printf(" %p|%p: boot info structure\n", &bootinfo, bootinfo_pa);
-	printf(" %p|%p: kernel entry point\n",
-	    (void *) PA2KA(BOOT_OFFSET), (void *) BOOT_OFFSET);
 	printf(" %p|%p: loader entry point\n",
 	    (void *) LOADER_ADDRESS, loader_address_pa);
@@ -144,6 +143,7 @@
 	}
 
+	uintptr_t entry = check_kernel_translated(inflate_base, 0);
+
 	printf("Booting the kernel...\n");
-	jump_to_kernel(bootinfo_pa, transtable_pa, pages, real_mode_pa,
-	    PA2KA(BOOT_OFFSET));
+	jump_to_kernel(bootinfo_pa, transtable_pa, pages, real_mode_pa, entry);
 }
Index: boot/arch/riscv64/Makefile.inc
===================================================================
--- boot/arch/riscv64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/riscv64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -30,5 +30,4 @@
 BFD_OUTPUT = $(BFD_NAME)
 BFD_ARCH = riscv
-BFD = binary
 
 BITS = 64
@@ -51,3 +50,4 @@
 	generic/src/gzip.c \
 	generic/src/tar.c \
+	generic/src/kernel.c \
 	generic/src/payload.c
Index: boot/arch/riscv64/include/arch/asm.h
===================================================================
--- boot/arch/riscv64/include/arch/asm.h	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/riscv64/include/arch/asm.h	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -36,5 +36,5 @@
 extern char pt_page[];
 
-extern _Noreturn void jump_to_kernel(uintptr_t);
+extern _Noreturn void jump_to_kernel(uintptr_t, uintptr_t);
 
 #endif
Index: boot/arch/riscv64/src/asm.S
===================================================================
--- boot/arch/riscv64/src/asm.S	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/riscv64/src/asm.S	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -125,5 +125,6 @@
 	csrw mstatus, t0
 
-	li ra, PA2KA(BOOT_OFFSET)
+	/* Entry point address is in a1. */
+	mv ra, a1
 	csrw mepc, ra
 
Index: boot/arch/riscv64/src/main.c
===================================================================
--- boot/arch/riscv64/src/main.c	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/riscv64/src/main.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -42,4 +42,5 @@
 #include <halt.h>
 #include <payload.h>
+#include <kernel.h>
 
 static bootinfo_t bootinfo;
@@ -88,5 +89,7 @@
 	extract_payload(&bootinfo.taskmap, load_addr, end, kernel_addr, NULL);
 
+	uintptr_t entry = check_kernel(load_addr);
+
 	printf("Booting the kernel...\n");
-	jump_to_kernel(PA2KA(&bootinfo));
+	jump_to_kernel(PA2KA(&bootinfo), entry);
 }
Index: boot/arch/sparc64/Makefile.inc
===================================================================
--- boot/arch/sparc64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/sparc64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -72,3 +72,4 @@
 	generic/src/gzip.c \
 	generic/src/tar.c \
+	generic/src/kernel.c \
 	generic/src/payload.c
Index: boot/arch/sparc64/src/main.c
===================================================================
--- boot/arch/sparc64/src/main.c	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ boot/arch/sparc64/src/main.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -43,4 +43,5 @@
 #include <errno.h>
 #include <payload.h>
+#include <kernel.h>
 
 /* The lowest ID (read from the VER register) of some US3 CPU model */
@@ -257,6 +258,8 @@
 		sun4u_smp();
 
+	uintptr_t entry = check_kernel((void *) KERNEL_ADDRESS);
+
 	printf("Booting the kernel ...\n");
-	jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo, subarch,
-	    (void *) KERNEL_ADDRESS);
-}
+	jump_to_kernel(bootinfo.physmem_start | BSP_PROCESSOR, &bootinfo,
+	    subarch, (void *) entry);
+}
Index: boot/generic/include/kernel.h
===================================================================
--- boot/generic/include/kernel.h	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
+++ boot/generic/include/kernel.h	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018 Jiří Zárevúcky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BOOT_ELF_H_
+#define BOOT_ELF_H_
+
+#include <stdint.h>
+
+uintptr_t check_kernel_translated(void *, uintptr_t);
+uintptr_t check_kernel(void *);
+
+#endif
Index: boot/generic/src/kernel.c
===================================================================
--- boot/generic/src/kernel.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
+++ boot/generic/src/kernel.c	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018 Jiří Zárevúcky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <abi/elf.h>
+#include <halt.h>
+#include <printf.h>
+#include <kernel.h>
+#include <stdbool.h>
+
+// FIXME: elf_is_valid is a duplicate of the same-named libc function.
+
+// TODO: better kernel ELF loading
+//
+// Currently the boot loader is very primitive. It loads the ELF file as
+// a contiguous span starting at a predefined offset, and then checks load
+// segments in it to make sure they are correctly positioned. Ideally, this
+// should change to a more flexible loader that actually loads based on the
+// kernel's ELF segments. There would still be some restrictions however.
+// ELF vaddr and paddr fields offer some flexibility in their interpretation,
+// so I propose the following scheme, to correctly express everything various
+// architectures require:
+//
+//     - in vaddr and paddr fields, addresses numerically in the lower half are
+//       interpreted as physical addresses, addresses in the upper half are
+//       interpreted as virtual addresses.
+//
+//     - If vaddr is a virtual address, the segment is mapped into the kernel's
+//       virtual address space at vaddr.
+//
+//     - If vaddr is a physical address, it must be the same as paddr.
+//       Loader loads the segment at the given physical address, but does not
+//       map it into the kernel's virtual address space. Symbols defined in this
+//       segment are only accessible with paging disabled.
+//
+//     - If paddr is a physical address, the loader must load the segment at
+//       physical address paddr, or die trying.
+//
+//     - If paddr is a virtual address, it must be the same as vaddr.
+//       Loader may allocate the physical location arbitrarily.
+//
+//     - If the kernel is a Position Independent Executable, all this is
+//       irrelevant, paddr must be the same as vaddr, vaddr is always the
+//       virtual address offset, and loader can choose the virtual address
+//       base arbitrarily within some predefined constraints. We might want
+//       to support PIE kernel on architectures that need some code at fixed
+//       physical address. In that case, the "real mode" code should probably
+//       be in a separate ELF file from the rest of kernel.
+//
+
+/**
+ * Checks that the ELF header is valid for the running system.
+ */
+static bool elf_is_valid(const elf_header_t *header)
+{
+	// TODO: check more things
+	// TODO: debug output
+
+	if (header->e_ident[EI_MAG0] != ELFMAG0 ||
+	    header->e_ident[EI_MAG1] != ELFMAG1 ||
+	    header->e_ident[EI_MAG2] != ELFMAG2 ||
+	    header->e_ident[EI_MAG3] != ELFMAG3) {
+		return false;
+	}
+
+	if (header->e_ident[EI_DATA] != ELF_DATA_ENCODING ||
+	    header->e_machine != ELF_MACHINE ||
+	    header->e_ident[EI_VERSION] != EV_CURRENT ||
+	    header->e_version != EV_CURRENT ||
+	    header->e_ident[EI_CLASS] != ELF_CLASS) {
+		return false;
+	}
+
+	if (header->e_phentsize != sizeof(elf_segment_header_t)) {
+		return false;
+	}
+
+	if (header->e_type != ET_EXEC && header->e_type != ET_DYN) {
+		return false;
+	}
+
+	if (header->e_phoff == 0) {
+		return false;
+	}
+
+	return true;
+}
+
+uintptr_t check_kernel(void *start)
+{
+	return check_kernel_translated(start, (uintptr_t) start);
+}
+
+/**
+ * Checks that the kernel ELF image is valid, and returns the entry point
+ * address. We check that the image's load addresses match the actual location.
+ *
+ * @param start  Pointer to the start of the ELF file in memory.
+ * @param actual_addr  Start address where the kernel is moved after the check
+ *                     but before it is executed.
+ *
+ * @return  Entry point address in *kernel's* address space.
+ */
+uintptr_t check_kernel_translated(void *start, uintptr_t actual_addr)
+{
+	elf_header_t *header = (elf_header_t *) start;
+
+	if (!elf_is_valid(header)) {
+		printf("Kernel is not a valid ELF image.\n");
+		halt();
+	}
+
+	elf_segment_header_t *phdr =
+	    (elf_segment_header_t *) ((uintptr_t) start + header->e_phoff);
+
+	/* Walk through PT_LOAD headers, to find out the size of the module. */
+	for (int i = 0; i < header->e_phnum; i++) {
+		if (phdr[i].p_type != PT_LOAD)
+			continue;
+
+		uintptr_t expected = actual_addr + phdr[i].p_offset;
+		uintptr_t got = phdr[i].p_paddr;
+		if (expected != got) {
+			printf("Incorrect kernel load address. "
+			    "Expected: %p, got %p\n",
+			    (void *) expected, (void *) got);
+			halt();
+		}
+
+		if (phdr[i].p_filesz != phdr[i].p_memsz) {
+			printf("Kernel's memory size is greater than its file"
+			    " size. We don't currently support that.\n");
+			halt();
+		}
+	}
+
+	return (uintptr_t) header->e_entry;
+}
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/Makefile	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -49,6 +49,5 @@
 
 AUTOCHECK = $(realpath $(ROOT_PATH)/tools/autocheck.awk)
-RAW = kernel.raw
-BIN = kernel.bin
+KERNEL = kernel.elf
 MAP = kernel.map
 JOB = kernel.job
@@ -75,8 +74,8 @@
 .DELETE_ON_ERROR:
 
-all: $(VERSION_DEF) $(COMMON_MAKEFILE) $(COMMON_HEADER) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) $(BIN) $(DISASM)
+all: $(VERSION_DEF) $(COMMON_MAKEFILE) $(COMMON_HEADER) $(CONFIG_MAKEFILE) $(CONFIG_HEADER) $(KERNEL) $(DISASM)
 
 clean: autogen_clean
-	rm -f $(RAW) $(BIN) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* arch/*/_link.ld arch/*/include/arch/common.h
+	rm -f $(KERNEL) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* arch/*/_link.ld arch/*/include/arch/common.h
 	find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm '{}' \;
 	find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.d' -follow -exec rm '{}' \;
@@ -370,8 +369,5 @@
 endif
 
-$(BIN): $(RAW)
-	$(OBJCOPY) -O $(BFD) $< $@
-
-$(DISASM): $(RAW)
+$(DISASM): $(KERNEL)
 ifeq ($(CONFIG_LINE_DEBUG),y)
 	$(OBJDUMP) -d -S $< > $@
@@ -380,5 +376,5 @@
 endif
 
-$(RAW): $(LINK) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(SYMTAB_OBJECTS)
+$(KERNEL): $(LINK) $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(SYMTAB_OBJECTS)
 	$(CC) $(DEFS) $(CFLAGS) $(LDFLAGS) -Wl,-Map,$(MAP) -o $@ $(ARCH_OBJECTS) $(GENARCH_OBJECTS) $(GENERIC_OBJECTS) $(EXTRA_OBJECTS) $(SYMTAB_OBJECTS)
 
Index: kernel/arch/abs32le/Makefile.inc
===================================================================
--- kernel/arch/abs32le/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/abs32le/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,5 +27,4 @@
 #
 
-BFD = binary
 
 ifeq ($(COMPILER),gcc_cross)
Index: kernel/arch/amd64/Makefile.inc
===================================================================
--- kernel/arch/amd64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/amd64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,7 +27,4 @@
 #
 
-BFD_NAME = elf64-x86-64
-BFD_ARCH = i386:x86-64
-BFD = binary
 
 FPU_NO_CFLAGS = -mno-sse -mno-sse2
Index: kernel/arch/amd64/_link.ld.in
===================================================================
--- kernel/arch/amd64/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/amd64/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -33,9 +33,10 @@
 		*(COMMON);      /* global variables */
 
+		/* XXX: bss can't be omitted from the ELF image. */
+		*(.bss);        /* uninitialized static variables */
+
 		. = ALIGN(8);
 		symbol_table = .;
 		*(symtab.*);    /* Symbol table, must be LAST symbol!*/
-
-		*(.bss);        /* uninitialized static variables */
 
 		kdata_end = .;
Index: kernel/arch/arm32/Makefile.inc
===================================================================
--- kernel/arch/arm32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/arm32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,7 +27,4 @@
 #
 
-BFD_NAME = elf32-littlearm
-BFD_ARCH = arm
-BFD = binary
 
 ATSIGN = %
Index: kernel/arch/arm32/_link.ld.in
===================================================================
--- kernel/arch/arm32/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/arm32/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -25,4 +25,5 @@
 	. = KERNEL_LOAD_ADDRESS;
 	kernel_load_address = .;
+	. = . + SIZEOF_HEADERS;
 	.text : {
 		ktext_start = .;
Index: kernel/arch/ia32/Makefile.inc
===================================================================
--- kernel/arch/ia32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ia32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,7 +27,4 @@
 #
 
-BFD_NAME = elf32-i386
-BFD_ARCH = i386
-BFD = binary
 
 BITS = 32
Index: kernel/arch/ia32/_link.ld.in
===================================================================
--- kernel/arch/ia32/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ia32/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -31,8 +31,11 @@
 		*(.rodata .rodata.*);   /* string literals */
 		*(COMMON);              /* global variables */
+
+		/* XXX: bss can't be omitted from the ELF image. */
+		*(.bss);                /* uninitialized static variables */
+
 		. = ALIGN(8);
 		symbol_table = .;
 		*(symtab.*);            /* Symbol table, must be LAST symbol! */
-		*(.bss);                /* uninitialized static variables */
 		kdata_end = .;
 	}
Index: kernel/arch/ia64/Makefile.inc
===================================================================
--- kernel/arch/ia64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ia64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,6 +27,4 @@
 #
 
-BFD_NAME = elf64-little
-BFD_ARCH = ia64-elf64
 
 COMMON_CFLAGS += -mconstant-gp -fno-unwind-tables -mfixed-range=f32-f127
@@ -65,10 +63,8 @@
 ifeq ($(MACHINE),ski)
 	ARCH_SOURCES += arch/$(KARCH)/src/drivers/ski.c
-	BFD = binary
 endif
 
 ifeq ($(MACHINE),i460GX)
 	DEFS += -DI460GX
-	BFD = binary
 endif
 
Index: kernel/arch/ia64/_link.ld.in
===================================================================
--- kernel/arch/ia64/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ia64/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -15,5 +15,6 @@
 	kernel_load_address = LOAD_ADDRESS_V;
 
-	.image LOAD_ADDRESS_V: AT (LOAD_ADDRESS_P) {
+	.image (LOAD_ADDRESS_V + SIZEOF_HEADERS): AT (LOAD_ADDRESS_P + SIZEOF_HEADERS) {
+		. = ALIGN(16);
 		ktext_start = .;
 		*(K_TEXT_START);
Index: kernel/arch/mips32/Makefile.inc
===================================================================
--- kernel/arch/mips32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/mips32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,6 +27,4 @@
 #
 
-BFD_ARCH = mips
-BFD = binary
 COMMON_CFLAGS += -msoft-float -mno-abicalls -G 0 -fno-zero-initialized-in-bss -mabi=32
 AS_PROLOG = .module softfloat;
@@ -38,15 +36,12 @@
 
 ifeq ($(MACHINE),msim)
-	BFD_NAME = elf32-tradlittlemips
 	ENDIANESS = LE
 	COMMON_CFLAGS += -march=r4000
 endif
 ifeq ($(MACHINE),bmalta)
-	BFD_NAME = elf32-tradbigmips
 	ENDIANESS = BE
 	COMMON_CFLAGS += -D__BE__ -march=4kc
 endif
 ifeq ($(MACHINE),lmalta)
-	BFD_NAME = elf32-tradlittlemips
 	ENDIANESS = LE
 	COMMON_CFLAGS += -march=4kc
Index: kernel/arch/mips32/_link.ld.in
===================================================================
--- kernel/arch/mips32/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/mips32/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -24,4 +24,5 @@
 	. = KERNEL_LOAD_ADDRESS;
 	kernel_load_address = .;
+	. = . + SIZEOF_HEADERS;
 
 	.text : {
Index: kernel/arch/ppc32/Makefile.inc
===================================================================
--- kernel/arch/ppc32/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ppc32/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,7 +27,4 @@
 #
 
-BFD_NAME = elf32-powerpc
-BFD_ARCH = powerpc:common
-BFD = binary
 
 COMMON_CFLAGS += -mcpu=powerpc -msoft-float -m32
Index: kernel/arch/ppc32/_link.ld.in
===================================================================
--- kernel/arch/ppc32/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ppc32/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -20,5 +20,6 @@
 	kernel_load_address = PA2KA(0);
 
-	.unmapped 0: AT (0) {
+	.unmapped (SIZEOF_HEADERS): AT (SIZEOF_HEADERS) {
+		. = ALIGN(0x100);
 		*(K_UNMAPPED_TEXT_START);
 	}
@@ -46,3 +47,7 @@
 		kdata_end = .;
 	}
+
+	/DISCARD/ : {
+		*(*);
+	}
 }
Index: kernel/arch/ppc32/src/exception.S
===================================================================
--- kernel/arch/ppc32/src/exception.S	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/ppc32/src/exception.S	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -126,5 +126,9 @@
 .endm
 
-.org 0x100
+// XXX: K_UNMAPPED_TEXT_START section starts at 0x100,
+// so all the following .org directives are relative to that.
+#define ABSOLUTE(x) ((x) - 0x100)
+
+.org ABSOLUTE(0x100)
 SYMBOL(exc_system_reset)
 	CONTEXT_STORE
@@ -133,5 +137,5 @@
 	b jump_to_kernel
 
-.org 0x200
+.org ABSOLUTE(0x200)
 SYMBOL(exc_machine_check)
 	CONTEXT_STORE
@@ -140,5 +144,5 @@
 	b jump_to_kernel
 
-.org 0x300
+.org ABSOLUTE(0x300)
 SYMBOL(exc_data_storage)
 	CONTEXT_STORE
@@ -147,5 +151,5 @@
 	b jump_to_kernel
 
-.org 0x400
+.org ABSOLUTE(0x400)
 SYMBOL(exc_instruction_storage)
 	CONTEXT_STORE
@@ -154,5 +158,5 @@
 	b jump_to_kernel
 
-.org 0x500
+.org ABSOLUTE(0x500)
 SYMBOL(exc_external)
 	CONTEXT_STORE
@@ -161,5 +165,5 @@
 	b jump_to_kernel
 
-.org 0x600
+.org ABSOLUTE(0x600)
 SYMBOL(exc_alignment)
 	CONTEXT_STORE
@@ -168,5 +172,5 @@
 	b jump_to_kernel
 
-.org 0x700
+.org ABSOLUTE(0x700)
 SYMBOL(exc_program)
 	CONTEXT_STORE
@@ -175,5 +179,5 @@
 	b jump_to_kernel
 
-.org 0x800
+.org ABSOLUTE(0x800)
 SYMBOL(exc_fp_unavailable)
 	CONTEXT_STORE
@@ -182,5 +186,5 @@
 	b jump_to_kernel
 
-.org 0x900
+.org ABSOLUTE(0x900)
 SYMBOL(exc_decrementer)
 	CONTEXT_STORE
@@ -189,5 +193,5 @@
 	b jump_to_kernel
 
-.org 0xa00
+.org ABSOLUTE(0xa00)
 SYMBOL(exc_reserved0)
 	CONTEXT_STORE
@@ -196,5 +200,5 @@
 	b jump_to_kernel
 
-.org 0xb00
+.org ABSOLUTE(0xb00)
 SYMBOL(exc_reserved1)
 	CONTEXT_STORE
@@ -203,5 +207,5 @@
 	b jump_to_kernel
 
-.org 0xc00
+.org ABSOLUTE(0xc00)
 SYMBOL(exc_syscall)
 	CONTEXT_STORE
@@ -209,5 +213,5 @@
 	b jump_to_kernel_syscall
 
-.org 0xd00
+.org ABSOLUTE(0xd00)
 SYMBOL(exc_trace)
 	CONTEXT_STORE
@@ -216,5 +220,5 @@
 	b jump_to_kernel
 
-.org 0x1000
+.org ABSOLUTE(0x1000)
 SYMBOL(exc_itlb_miss)
 	CONTEXT_STORE
@@ -223,5 +227,5 @@
 	b jump_to_kernel
 
-.org 0x1100
+.org ABSOLUTE(0x1100)
 SYMBOL(exc_dtlb_miss_load)
 	CONTEXT_STORE
@@ -230,5 +234,5 @@
 	b jump_to_kernel
 
-.org 0x1200
+.org ABSOLUTE(0x1200)
 SYMBOL(exc_dtlb_miss_store)
 	CONTEXT_STORE
@@ -237,5 +241,5 @@
 	b jump_to_kernel
 
-.org 0x4000
+.org ABSOLUTE(0x4000)
 jump_to_kernel:
 	mfsrr1 r5
@@ -289,2 +293,6 @@
 	addis sp, sp, 0x8000
 	rfi
+
+/* Rest is for stack. */
+
+.org ABSOLUTE(0x8000)
Index: kernel/arch/riscv64/Makefile.inc
===================================================================
--- kernel/arch/riscv64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/riscv64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,7 +27,4 @@
 #
 
-BFD_NAME = elf64-littleriscv
-BFD_ARCH = riscv
-BFD = binary
 
 COMMON_CFLAGS += -mcmodel=medany
Index: kernel/arch/riscv64/_link.ld.in
===================================================================
--- kernel/arch/riscv64/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/riscv64/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -16,5 +16,5 @@
 	kernel_load_address = PA2KA(BOOT_OFFSET);
 
-	.image (PA2KA(BOOT_OFFSET)) : AT (0) {
+	.image (PA2KA(BOOT_OFFSET) + SIZEOF_HEADERS) : AT (SIZEOF_HEADERS) {
 		ktext_start = .;
 		*(K_TEXT_START);
Index: kernel/arch/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/sparc64/Makefile.inc	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -27,7 +27,4 @@
 #
 
-BFD_NAME = elf64-sparc
-BFD_ARCH = sparc
-BFD = binary
 
 COMMON_CFLAGS += -m64 -mcpu=ultrasparc -mcmodel=medlow -mno-fpu
Index: kernel/arch/sparc64/_link.ld.in
===================================================================
--- kernel/arch/sparc64/_link.ld.in	(revision d59718e246e2f30ad97e0364fac7e75455fcb7d1)
+++ kernel/arch/sparc64/_link.ld.in	(revision cfdeedc55a55b7c1fc8de8b3faea55104ff3f641)
@@ -12,7 +12,7 @@
 
 SECTIONS {
-	.image VMA: AT (LMA) {
-		kernel_load_address = .;
+	kernel_load_address = VMA;
 
+	.image (VMA + SIZEOF_HEADERS): AT (LMA + SIZEOF_HEADERS) {
 		ktext_start = .;
 		*(K_TEXT_START)
