From 7a49f672c5b901b1082c693c22f87b0ea494b05e Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 28 Sep 2007 20:29:52 +0200 Subject: add kallsyms from linux kernel --- Makefile | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++--- common/kallsyms.c | 69 ++++++++++++++++++++++++++++++++++++++ include/kallsyms.h | 7 ++++ 3 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 common/kallsyms.c create mode 100644 include/kallsyms.h diff --git a/Makefile b/Makefile index f7d9428e5b..be9e870013 100644 --- a/Makefile +++ b/Makefile @@ -163,8 +163,8 @@ export srctree objtree VPATH # Alternatively CROSS_COMPILE can be set in the environment. # Default value for CROSS_COMPILE is not to prefix executables -ARCH := sandbox -CROSS_COMPILE := +ARCH ?= sandbox +CROSS_COMPILE ?= # Architecture as present in compile.h UTS_MACHINE := $(ARCH) @@ -250,6 +250,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump AWK = awk GENKSYMS = scripts/genksyms/genksyms DEPMOD = /sbin/depmod +KALLSYMS = scripts/kallsyms PERL = perl CHECK = sparse @@ -449,6 +450,8 @@ common-y := $(patsubst %/, %/built-in.o, $(common-y)) # in the kernel tree, others are specified in arch/$(ARCH)Makefile. # Ordering when linking is important, and $(uboot-init) must be first. # +# FIXME: This picture is wrong for U-Boot. We have no init, driver, mm +# # uboot # ^ # | @@ -456,9 +459,11 @@ common-y := $(patsubst %/, %/built-in.o, $(common-y)) # | +--< init/version.o + more # | # +--< $(uboot-main) -# +--< driver/built-in.o mm/built-in.o + more +# | +--< driver/built-in.o mm/built-in.o + more +# | +# +-< kallsyms.o (see description in CONFIG_KALLSYMS section) # -# uboot version (uname -v) cannot be updated during normal +# uboot version cannot be updated during normal # descending-into-subdirs phase since we do not yet know if we need to # update uboot. # @@ -512,12 +517,94 @@ define rule_uboot__ fi; endef +ifdef CONFIG_KALLSYMS +# Generate section listing all symbols and add it into uboot $(kallsyms.o) +# It's a three stage process: +# o .tmp_uboot1 has all symbols and sections, but __kallsyms is +# empty +# Running kallsyms on that gives us .tmp_kallsyms1.o with +# the right size - uboot version is updated during this step +# o .tmp_uboot2 now has a __kallsyms section of the right size, +# but due to the added section, some addresses have shifted. +# From here, we generate a correct .tmp_kallsyms2.o +# o The correct .tmp_kallsyms2.o is linked into the final uboot. +# o Verify that the System.map from uboot matches the map from +# .tmp_uboot2, just in case we did not generate kallsyms correctly. +# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using +# .tmp_uboot3 and .tmp_kallsyms3.o. This is only meant as a +# temporary bypass to allow the kernel to be built while the +# maintainers work out what went wrong with kallsyms. + +ifdef CONFIG_KALLSYMS_EXTRA_PASS +last_kallsyms := 3 +else +last_kallsyms := 2 +endif + +kallsyms.o := .tmp_kallsyms$(last_kallsyms).o + +define verify_kallsyms + $(Q)$(if $($(quiet)cmd_sysmap), \ + echo ' $($(quiet)cmd_sysmap) .tmp_System.map' &&) \ + $(cmd_sysmap) .tmp_uboot$(last_kallsyms) .tmp_System.map + $(Q)cmp -s System.map .tmp_System.map || \ + (echo Inconsistent kallsyms data; \ + echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \ + rm .tmp_kallsyms* ; /bin/false ) +endef + +# Update uboot version before link +# Use + in front of this rule to silent warning about make -j1 +# First command is ':' to allow us to use + in front of this rule +cmd_ksym_ld = $(cmd_uboot__) +define rule_ksym_ld + : + +$(call cmd,uboot_version) + $(call cmd,uboot__) + $(Q)echo 'cmd_$@ := $(cmd_uboot__)' > $(@D)/.$(@F).cmd +endef + +# Generate .S file with all kernel symbols +quiet_cmd_kallsyms = KSYM $@ + cmd_kallsyms = $(NM) -g -n $< | $(KALLSYMS) > $@ + +.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE + $(call if_changed_dep,as_o_S) + +.tmp_kallsyms%.S: .tmp_uboot% $(KALLSYMS) + $(call cmd,kallsyms) + +# .tmp_uboot1 must be complete except kallsyms, so update uboot version +.tmp_uboot1: $(uboot-lds) $(uboot-all) FORCE + $(call if_changed_rule,ksym_ld) + +.tmp_uboot2: $(uboot-lds) $(uboot-all) .tmp_kallsyms1.o FORCE + $(call if_changed,uboot__) + +.tmp_uboot3: $(uboot-lds) $(uboot-all) .tmp_kallsyms2.o FORCE + $(call if_changed,uboot__) + +# Needs to visit scripts/ before $(KALLSYMS) can be used. +$(KALLSYMS): scripts ; + +# Generate some data for debugging strange kallsyms problems +debug_kallsyms: .tmp_map$(last_kallsyms) + +.tmp_map%: .tmp_uboot% FORCE + ($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@ + +.tmp_map3: .tmp_map2 + +.tmp_map2: .tmp_map1 + +endif # ifdef CONFIG_KALLSYMS + uboot.bin: uboot $(Q)$(OBJCOPY) -O binary uboot uboot.bin $(Q)$(OBJDUMP) -d uboot > uboot.S # uboot image -uboot: $(uboot-lds) $(uboot-head) $(uboot-common) FORCE +uboot: $(uboot-lds) $(uboot-head) $(uboot-common) $(kallsyms.o) FORCE $(call if_changed_rule,uboot__) $(Q)rm -f .old_version diff --git a/common/kallsyms.c b/common/kallsyms.c new file mode 100644 index 0000000000..4069f4b701 --- /dev/null +++ b/common/kallsyms.c @@ -0,0 +1,69 @@ +#include +#include +#include + +/* These will be re-linked against their real values during the second link stage */ +extern const unsigned long kallsyms_addresses[] __attribute__((weak)); +extern const unsigned long kallsyms_num_syms __attribute__((weak)); +extern const u8 kallsyms_names[] __attribute__((weak)); + +extern const u8 kallsyms_token_table[] __attribute__((weak)); +extern const u16 kallsyms_token_index[] __attribute__((weak)); + +extern const unsigned long kallsyms_markers[] __attribute__((weak)); + +/* expand a compressed symbol data into the resulting uncompressed string, + given the offset to where the symbol is in the compressed stream */ +static unsigned int kallsyms_expand_symbol(unsigned int off, char *result) +{ + int len, skipped_first = 0; + const u8 *tptr, *data; + + /* get the compressed symbol length from the first symbol byte */ + data = &kallsyms_names[off]; + len = *data; + data++; + + /* update the offset to return the offset for the next symbol on + * the compressed stream */ + off += len + 1; + + /* for every byte on the compressed symbol data, copy the table + entry for that byte */ + while(len) { + tptr = &kallsyms_token_table[ kallsyms_token_index[*data] ]; + data++; + len--; + + while (*tptr) { + if(skipped_first) { + *result = *tptr; + result++; + } else + skipped_first = 1; + tptr++; + } + } + + *result = '\0'; + + /* return to offset to the next symbol */ + return off; +} + +/* Lookup the address for this symbol. Returns 0 if not found. */ +unsigned long kallsyms_lookup_name(const char *name) +{ + char namebuf[KSYM_NAME_LEN]; + unsigned long i; + unsigned int off; + + for (i = 0, off = 0; i < kallsyms_num_syms; i++) { + off = kallsyms_expand_symbol(off, namebuf); + + if (strcmp(namebuf, name) == 0) + return kallsyms_addresses[i]; + } +// return module_kallsyms_lookup_name(name); + return 0; +} diff --git a/include/kallsyms.h b/include/kallsyms.h new file mode 100644 index 0000000000..5117be2272 --- /dev/null +++ b/include/kallsyms.h @@ -0,0 +1,7 @@ +#ifndef __KALLSYMS_H +#define __KALLSYMS_H + +#define KSYM_NAME_LEN 128 +unsigned long kallsyms_lookup_name(const char *name); + +#endif /* __KALLSYMS_H */ -- cgit v1.2.3