summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kconfig19
-rw-r--r--Makefile51
-rw-r--r--arch/x86/machine/boot.c2
-rw-r--r--arch/x86/machine/strace.c212
-rw-r--r--arch/x86/machine/strace.h25
-rw-r--r--arch/x86/x15.lds.S17
-rw-r--r--kern/Makefile1
-rw-r--r--kern/macros.h4
-rw-r--r--kern/panic.c3
-rw-r--r--kern/symbol.c49
-rw-r--r--kern/symbol.h45
-rwxr-xr-xtools/gen_symtab.py30
12 files changed, 227 insertions, 231 deletions
diff --git a/Kconfig b/Kconfig
index cf42e9f2..479ab45a 100644
--- a/Kconfig
+++ b/Kconfig
@@ -26,13 +26,16 @@ config CFLAGS
menu "Build options"
-config CC_EXE
+config COMPILER
string "Compiler executable"
default CC
---help---
Name of the compiler executable
-config CC_OPTIONS
+ This includes any toolchain prefix, and must be a file name,
+ not a path.
+
+config COMPILER_OPTIONS
string "Compilation options"
default CFLAGS
---help---
@@ -44,6 +47,18 @@ config ASSERT
---help---
Enable assert() code generation.
+config SYMTAB
+ bool "Build symbol table"
+ default y
+ ---help---
+ Build and embed a symbol table in the kernel.
+
+ This option allows the kernel to perform symbolic address
+ resolutions which are very convenient for debugging, at the
+ cost of additional data memory.
+
+ If unsure, enable.
+
endmenu
source "arch/$ARCH/Kconfig"
diff --git a/Makefile b/Makefile
index 3084d56e..a5402992 100644
--- a/Makefile
+++ b/Makefile
@@ -85,9 +85,19 @@ define xbuild_link
$(COMPILE) -o $@ $(1) $(XBUILD_LDFLAGS)
endef
+XBUILD_GEN_SYMTAB = $(SRCDIR)/tools/gen_symtab.py
+XBUILD_GEN_SYMTAB_DEPS = $(XBUILD_GEN_SYMTAB)
+
+# $(call xbuild_gen_symtab)
+define xbuild_gen_symtab
+ $(call xbuild_action,GEN,$@) \
+ $(NM) -S -n $< | $(XBUILD_GEN_SYMTAB) > $@
+endef
+
define xbuild_clean
- $(Q)rm -f x15 \
+ $(Q)rm -f x15 $(x15_NO_SYMTAB) \
$(x15_OBJDEPS) $(x15_OBJECTS) \
+ $(x15_SYMTAB_C) $(x15_SYMTAB_D) $(x15_SYMTAB_O) \
$(x15_LDS_D) $(x15_LDS)
endef
@@ -207,17 +217,24 @@ include/generated/autoconf.h: .config $(ALL_MAKEFILES)
-include .config
-ifdef CONFIG_CC_EXE
+ifdef CONFIG_COMPILER
# Use printf to remove quotes
-CC := $(shell printf -- $(CONFIG_CC_EXE))
+CC := $(shell printf -- $(CONFIG_COMPILER))
else
CC := gcc
endif
-# Export to CONFIG_CC
+# The CC variable is used by Kconfig to set the value of CONFIG_COMPILER.
export CC
-CPP = $(CC) -E
+TOOLCHAIN_NAME = $(shell printf "%s" $(CC) | rev | cut -s -d - -f 2- | rev)
+
+ifneq ($(TOOLCHAIN_NAME),)
+TOOLCHAIN_PREFIX = $(TOOLCHAIN_NAME)-
+endif
+
+CPP := $(CC) -E
+NM := $(TOOLCHAIN_PREFIX)nm
CFLAGS ?= -O2 -g
@@ -281,18 +298,22 @@ include $(MAKEFILE_INCLUDES)
# Must be defined by the architecture-specific Makefile.
export KCONFIG_DEFCONFIG
-ifdef CONFIG_CC_OPTIONS
+ifdef CONFIG_COMPILER_OPTIONS
# Use printf to remove quotes
-XBUILD_CFLAGS += $(shell printf -- $(CONFIG_CC_OPTIONS))
+XBUILD_CFLAGS += $(shell printf -- $(CONFIG_COMPILER_OPTIONS))
endif
COMPILE := $(CC) $(XBUILD_CPPFLAGS) $(XBUILD_CFLAGS)
# Don't change preprocessor and compiler flags from this point
+x15_NO_SYMTAB := .x15.no_symtab
x15_SOURCES := $(x15_SOURCES-y)
x15_OBJDEPS := $(call xbuild_replace_source_suffix,d,$(x15_SOURCES))
x15_OBJECTS := $(call xbuild_replace_source_suffix,o,$(x15_SOURCES))
+x15_SYMTAB_C := .symtab.c
+x15_SYMTAB_D := $(call xbuild_replace_source_suffix,d,$(x15_SYMTAB_C))
+x15_SYMTAB_O := $(call xbuild_replace_source_suffix,o,$(x15_SYMTAB_C))
x15_LDS := $(basename $(x15_LDS_S))
x15_LDS_D := $(x15_LDS).d
@@ -324,9 +345,23 @@ x15_DEPS := $(x15_LDS) .x15.sorted_init_ops
%.lds: %.lds.S include/generated/autoconf.h
$(xbuild_gen_linker_script)
-x15: $(x15_OBJECTS) $(x15_DEPS)
+ifeq ($(CONFIG_SYMTAB),y)
+x15_FIRST_PASS := $(x15_NO_SYMTAB)
+else
+x15_FIRST_PASS := x15
+endif
+
+$(x15_FIRST_PASS): $(x15_OBJECTS) $(x15_DEPS)
$(call xbuild_link,$(x15_OBJECTS))
+ifeq ($(CONFIG_SYMTAB),y)
+$(x15_SYMTAB_C): $(x15_FIRST_PASS) $(XBUILD_GEN_SYMTAB_DEPS)
+ $(call xbuild_gen_symtab)
+
+x15: $(x15_NO_SYMTAB) $(x15_SYMTAB_O)
+ $(call xbuild_link,$(x15_OBJECTS) $(x15_SYMTAB_O))
+endif
+
.PHONY: install-x15
install-x15:
install -D -m 644 x15 $(DESTDIR)/boot/x15
diff --git a/arch/x86/machine/boot.c b/arch/x86/machine/boot.c
index d540d8d8..c1970f5d 100644
--- a/arch/x86/machine/boot.c
+++ b/arch/x86/machine/boot.c
@@ -70,7 +70,6 @@
#include <machine/pmap.h>
#include <machine/pmu_amd.h>
#include <machine/pmu_intel.h>
-#include <machine/strace.h>
#include <machine/uart.h>
#include <vm/vm_kmem.h>
@@ -495,7 +494,6 @@ void __init
boot_main(void)
{
arg_set_cmdline(boot_tmp_cmdline);
- strace_set_mbi(&boot_raw_mbi);
kernel_main();
/* Never reached */
diff --git a/arch/x86/machine/strace.c b/arch/x86/machine/strace.c
index cfb237e1..3031e544 100644
--- a/arch/x86/machine/strace.c
+++ b/arch/x86/machine/strace.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012-2014 Richard Braun.
+ * Copyright (c) 2018 Agustina Arzille.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,15 +17,10 @@
*/
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
-#include <string.h>
-#include <kern/init.h>
-#include <kern/kmem.h>
-#include <kern/log.h>
-#include <kern/macros.h>
-#include <machine/elf.h>
-#include <machine/multiboot.h>
+#include <kern/symbol.h>
#include <machine/pmap.h>
#include <machine/strace.h>
#include <machine/types.h>
@@ -36,56 +32,26 @@
#define STRACE_ADDR_FORMAT "%#010lx"
#endif /* __LP64__ */
-static const struct multiboot_raw_info *strace_mbi __initdata;
-
-static struct elf_sym *strace_symtab __read_mostly;
-static struct elf_sym *strace_symtab_end __read_mostly;
-static char *strace_strtab __read_mostly;
-
-static const char *
-strace_lookup(uintptr_t addr, uintptr_t *offset, uintptr_t *size)
-{
- struct elf_sym *sym;
-
- for (sym = strace_symtab; sym < strace_symtab_end; sym++) {
- if ((sym->size != 0)
- && (addr >= sym->value)
- && (addr <= (sym->value + sym->size))) {
- break;
- }
- }
-
- if (sym >= strace_symtab_end) {
- return NULL;
- }
-
- if (sym->name == 0) {
- return NULL;
- }
-
- *offset = addr - sym->value;
- *size = sym->size;
- return &strace_strtab[sym->name];
-}
-
static void
-strace_show_one(unsigned int index, unsigned long ip)
+strace_show_one(unsigned int index, uintptr_t ip)
{
- uintptr_t offset, size;
- const char *name;
+ const struct symbol *symbol;
+ uintptr_t offset;
- name = strace_lookup(ip, &offset, &size);
+ symbol = symbol_lookup(ip);
- if (name == NULL) {
- printf("#%u [" STRACE_ADDR_FORMAT "]\n", index, ip);
+ if (!symbol) {
+ printf("#%u [" STRACE_ADDR_FORMAT "]\n", index, (unsigned long)ip);
} else {
+ offset = ip - symbol->addr;
printf("#%u [" STRACE_ADDR_FORMAT "] %s+%#lx/%#lx\n",
- index, ip, name, (unsigned long)offset, (unsigned long)size);
+ index, (unsigned long)ip, symbol->name,
+ (unsigned long)offset, (unsigned long)symbol->size);
}
}
void
-strace_show(unsigned long ip, unsigned long bp)
+strace_show(uintptr_t ip, uintptr_t bp)
{
phys_addr_t pa;
void **frame;
@@ -109,7 +75,7 @@ strace_show(unsigned long ip, unsigned long bp)
break;
}
- strace_show_one(i, (unsigned long)frame[1]);
+ strace_show_one(i, (uintptr_t)frame[1]);
error = pmap_kextract((uintptr_t)frame, &pa);
if (error) {
@@ -121,153 +87,3 @@ strace_show(unsigned long ip, unsigned long bp)
frame = frame[0];
}
}
-
-static void * __init
-strace_copy_section(const struct elf_shdr *shdr)
-{
- uintptr_t map_addr;
- size_t map_size;
- const void *src;
- void *copy;
-
- src = vm_kmem_map_pa(shdr->addr, shdr->size, &map_addr, &map_size);
-
- if (src == NULL) {
- log_err("strace: unable to map section");
- goto error_map;
- }
-
- copy = kmem_alloc(shdr->size);
-
- if (copy == NULL) {
- log_err("strace: unable to allocate section copy");
- goto error_copy;
- }
-
- memcpy(copy, src, shdr->size);
- vm_kmem_unmap_pa(map_addr, map_size);
- return copy;
-
-error_copy:
- vm_kmem_unmap_pa(map_addr, map_size);
-error_map:
- return NULL;
-}
-
-static const struct elf_shdr * __init
-strace_lookup_section(const struct multiboot_raw_info *mbi, const void *table,
- const char *shstrtab, const char *name)
-{
- const struct elf_shdr *shdr;
- unsigned int i;
- const char *shdr_name;
-
- for (i = 0; i < mbi->shdr_num; i++) {
- shdr = table + (i * mbi->shdr_size);
- shdr_name = &shstrtab[shdr->name];
-
- if (strcmp(shdr_name, name) == 0) {
- return shdr;
- }
- }
-
- return NULL;
-}
-
-void __init
-strace_set_mbi(const struct multiboot_raw_info *mbi)
-{
- strace_mbi = mbi;
-}
-
-static int __init
-strace_setup(void)
-{
- const struct elf_shdr *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
- const struct multiboot_raw_info *mbi;
- uintptr_t map_addr, shstrtab_map_addr;
- size_t size, map_size, shstrtab_map_size;
- const char *shstrtab;
- const void *table;
-
- mbi = strace_mbi;
-
- if (!(mbi->flags & MULTIBOOT_LOADER_SHDR) || (mbi->shdr_num == 0)) {
- goto no_syms;
- }
-
- size = mbi->shdr_num * mbi->shdr_size;
- table = vm_kmem_map_pa(mbi->shdr_addr, size, &map_addr, &map_size);
-
- if (table == NULL) {
- log_err("strace: unable to map section headers table");
- goto no_syms;
- }
-
- if (mbi->shdr_strndx >= mbi->shdr_num) {
- log_err("strace: invalid section names index");
- goto error_shstrndx;
- }
-
- shstrtab_hdr = table + (mbi->shdr_strndx * mbi->shdr_size);
- shstrtab = vm_kmem_map_pa(shstrtab_hdr->addr, shstrtab_hdr->size,
- &shstrtab_map_addr, &shstrtab_map_size);
-
- if (shstrtab == NULL) {
- log_err("strace: unable to map section names");
- goto error_shstrtab;
- }
-
- symtab_hdr = strace_lookup_section(mbi, table, shstrtab, ".symtab");
-
- if (symtab_hdr == NULL) {
- log_err("strace: unable to find symbol table");
- goto error_symtab_lookup;
- }
-
- strtab_hdr = strace_lookup_section(mbi, table, shstrtab, ".strtab");
-
- if (strtab_hdr == NULL) {
- log_err("strace: unable to find symbol string table");
- goto error_strtab_lookup;
- }
-
- strace_symtab = strace_copy_section(symtab_hdr);
-
- if (strace_symtab == NULL) {
- goto error_symtab;
- }
-
- strace_symtab_end = (void *)strace_symtab + symtab_hdr->size;
- strace_strtab = strace_copy_section(strtab_hdr);
-
- if (strace_strtab == NULL) {
- goto error_strtab;
- }
-
- vm_kmem_unmap_pa(shstrtab_map_addr, shstrtab_map_size);
- vm_kmem_unmap_pa(map_addr, map_size);
- return 0;
-
-error_strtab:
- kmem_free(strace_symtab, symtab_hdr->size);
-error_symtab:
-error_strtab_lookup:
-error_symtab_lookup:
- vm_kmem_unmap_pa(shstrtab_map_addr, shstrtab_map_size);
-error_shstrtab:
-error_shstrndx:
- vm_kmem_unmap_pa(map_addr, map_size);
-no_syms:
- strace_symtab = NULL;
- strace_symtab_end = NULL;
- strace_strtab = NULL;
- return 0;
-}
-
-INIT_OP_DEFINE(strace_setup,
- INIT_OP_DEP(kmem_setup, true),
- INIT_OP_DEP(log_setup, true),
- INIT_OP_DEP(pmap_bootstrap, true),
- INIT_OP_DEP(printf_setup, true),
- INIT_OP_DEP(vm_kmem_setup, true));
diff --git a/arch/x86/machine/strace.h b/arch/x86/machine/strace.h
index 482768b9..a5de664f 100644
--- a/arch/x86/machine/strace.h
+++ b/arch/x86/machine/strace.h
@@ -23,9 +23,9 @@
#ifndef X86_STRACE_H
#define X86_STRACE_H
-#include <kern/init.h>
+#include <stdint.h>
+
#include <kern/macros.h>
-#include <machine/multiboot.h>
/*
* Display a call trace.
@@ -33,7 +33,7 @@
* Attempt to resolve the given instruction pointer, then walk the calling
* chain from the given frame pointer.
*/
-void strace_show(unsigned long ip, unsigned long bp);
+void strace_show(uintptr_t ip, uintptr_t bp);
/*
* Display the current call trace.
@@ -41,24 +41,11 @@ void strace_show(unsigned long ip, unsigned long bp);
static __always_inline void
strace_dump(void)
{
- unsigned long ip;
+ uintptr_t ip, bp;
asm volatile("1: mov $1b, %0" : "=r" (ip));
- strace_show(ip, (unsigned long)__builtin_frame_address(0));
+ bp = (uintptr_t)__builtin_frame_address(0);
+ strace_show(ip, bp);
}
-/*
- * Pass the multiboot information structure.
- *
- * If available, the symbol table is extracted from the boot data, when
- * the strace module is initialized.
- */
-void strace_set_mbi(const struct multiboot_raw_info *mbi);
-
-/*
- * This init operation provides :
- * - module fully initialized
- */
-INIT_OP_DECLARE(strace_setup);
-
#endif /* X86_STRACE_H */
diff --git a/arch/x86/x15.lds.S b/arch/x86/x15.lds.S
index b896a5d6..260d230c 100644
--- a/arch/x86/x15.lds.S
+++ b/arch/x86/x15.lds.S
@@ -23,6 +23,10 @@ PHDRS
text PT_LOAD FLAGS(5);
rodata PT_LOAD FLAGS(4);
data PT_LOAD FLAGS(6);
+
+#ifdef CONFIG_SYMTAB
+ symbol PT_LOAD FLAGS(6);
+#endif
}
SECTIONS
@@ -91,6 +95,19 @@ SECTIONS
*(.bss*)
} : data
+#ifdef CONFIG_SYMTAB
+ /*
+ * Including the embedded symbol table last should reliably prevent
+ * the second link from changing the addresses of the kernel symbols.
+ *
+ * In addition, use a program header different from data to make
+ * sure the linker doesn't include the .bss section in the output file.
+ */
+ .symbol ALIGN(PAGE_SIZE) : AT(BOOT_VTOP(ADDR(.symbol))) {
+ *(.symbol*)
+ } : symbol
+#endif /* CONFIG_SYMTAB */
+
. = ALIGN(PAGE_SIZE);
_end = .;
diff --git a/kern/Makefile b/kern/Makefile
index 5b04fcb3..ea7e3bff 100644
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -29,6 +29,7 @@ x15_SOURCES-y += \
kern/spinlock.c \
kern/sref.c \
kern/string.c \
+ kern/symbol.c \
kern/syscnt.c \
kern/task.c \
kern/thread.c \
diff --git a/kern/macros.h b/kern/macros.h
index 6d136e3e..ddd9e587 100644
--- a/kern/macros.h
+++ b/kern/macros.h
@@ -105,6 +105,10 @@
#define __used __attribute__((used))
#endif
+#ifndef __weak
+#define __weak __attribute__((weak))
+#endif
+
#ifndef __fallthrough
#if __GNUC__ >= 7
#define __fallthrough __attribute__((fallthrough))
diff --git a/kern/panic.c b/kern/panic.c
index c610e3fa..bd1f6658 100644
--- a/kern/panic.c
+++ b/kern/panic.c
@@ -64,5 +64,4 @@ panic_setup(void)
INIT_OP_DEFINE(panic_setup,
INIT_OP_DEP(cpu_setup, true),
- INIT_OP_DEP(printf_setup, true),
- INIT_OP_DEP(strace_setup, true));
+ INIT_OP_DEP(printf_setup, true));
diff --git a/kern/symbol.c b/kern/symbol.c
new file mode 100644
index 00000000..30df091e
--- /dev/null
+++ b/kern/symbol.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 Agustina Arzille.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <kern/macros.h>
+#include <kern/symbol.h>
+
+const size_t symbol_table_size __weak;
+const struct symbol *symbol_table_ptr __weak;
+
+const struct symbol *
+symbol_lookup(uintptr_t addr)
+{
+ const struct symbol *symbol;
+ uintptr_t start, end;
+
+ for (size_t i = 0; i < symbol_table_size; i++) {
+ symbol = &symbol_table_ptr[i];
+
+ if (!symbol->name || (symbol->size == 0)) {
+ continue;
+ }
+
+ start = symbol->addr;
+ end = symbol->addr + symbol->size;
+
+ if ((addr >= start) && (addr < end)) {
+ return symbol;
+ }
+ }
+
+ return NULL;
+}
diff --git a/kern/symbol.h b/kern/symbol.h
new file mode 100644
index 00000000..61fbf3f0
--- /dev/null
+++ b/kern/symbol.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018 Agustina Arzille.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERN_SYMBOL_H
+#define KERN_SYMBOL_H
+
+#include <stdint.h>
+
+#include <kern/macros.h>
+
+#define __symbol_table __section(".symbol")
+
+/*
+ * Symbol structure.
+ *
+ * This structure is public.
+ */
+struct symbol {
+ uintptr_t addr;
+ uintptr_t size;
+ const char *name;
+};
+
+/*
+ * Look up a symbol from an address.
+ *
+ * NULL is returned if no symbol was found for the given address.
+ */
+const struct symbol * symbol_lookup(uintptr_t addr);
+
+#endif /* KERN_SYMBOL_H */
diff --git a/tools/gen_symtab.py b/tools/gen_symtab.py
new file mode 100755
index 00000000..b691da12
--- /dev/null
+++ b/tools/gen_symtab.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+'''
+Embedded symbol table generator.
+'''
+
+import sys
+
+symtab_size = 0
+symtab = []
+
+for line in sys.stdin:
+ line = line.strip()
+ parts = line.split(' ')
+ del parts[2]
+
+ if len(parts) != 3 or parts[2].startswith("__func__."):
+ continue
+
+ symtab.append("{ 0x%s, 0x%s, \"%s\" }" % tuple(parts))
+ symtab_size += 1
+
+print("#include <kern/symbol.h>")
+print("const struct symbol symbol_table[] __symbol_table = {")
+
+for elem in symtab:
+ print(" " + elem + ",",)
+
+print("};")
+print("const size_t symbol_table_size = %d;" % symtab_size)
+print("const struct symbol *symbol_table_ptr = symbol_table;")