Commit 6802d702 authored by Kai Germaschewski's avatar Kai Germaschewski

kbuild: Speed up kallsyms generation

This patch basically just replaces the scripts/kallsyms script by
a scripts/kallsyms.c C program, which does the same thing much faster.

It also removes duplicates and entries which are not between _stext and
_etext, as they would not get used anyway. This saves about 290KB in
vmlinux with my .config, more than 50% of the kallsyms bloat ;)
parent a596e9e8
...@@ -352,12 +352,12 @@ ifdef CONFIG_KALLSYMS ...@@ -352,12 +352,12 @@ ifdef CONFIG_KALLSYMS
kallsyms.o := .tmp_kallsyms2.o kallsyms.o := .tmp_kallsyms2.o
quiet_cmd_kallsyms = KSYM $@ quiet_cmd_kallsyms = KSYM $@
cmd_kallsyms = sh $(KALLSYMS) $< $@ cmd_kallsyms = $(NM) -n $< | scripts/kallsyms > $@
.tmp_kallsyms1.o: .tmp_vmlinux1 .tmp_kallsyms1.o .tmp_kallsyms2.o: %.o: %.S scripts FORCE
$(call cmd,kallsyms) $(call if_changed_dep,as_o_S)
.tmp_kallsyms2.o: .tmp_vmlinux2 .tmp_kallsyms%.S: .tmp_vmlinux%
$(call cmd,kallsyms) $(call cmd,kallsyms)
.tmp_vmlinux1: $(vmlinux-objs) arch/$(ARCH)/vmlinux.lds.s FORCE .tmp_vmlinux1: $(vmlinux-objs) arch/$(ARCH)/vmlinux.lds.s FORCE
...@@ -842,6 +842,9 @@ a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(NOSTDINC_FLAGS) \ ...@@ -842,6 +842,9 @@ a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(NOSTDINC_FLAGS) \
quiet_cmd_as_s_S = CPP $@ quiet_cmd_as_s_S = CPP $@
cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< cmd_as_s_S = $(CPP) $(a_flags) -o $@ $<
quiet_cmd_as_o_S = AS $@
cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
# read all saved command lines # read all saved command lines
targets := $(wildcard $(sort $(targets))) targets := $(wildcard $(sort $(targets)))
......
...@@ -45,14 +45,11 @@ const char *kallsyms_lookup(unsigned long addr, ...@@ -45,14 +45,11 @@ const char *kallsyms_lookup(unsigned long addr,
for (i = 0; i < best; i++) for (i = 0; i < best; i++)
name += strlen(name)+1; name += strlen(name)+1;
/* Base symbol size on next symbol, but beware aliases. */ /* Base symbol size on next symbol. */
if (best + 1 < kallsyms_num_syms)
symbol_end = kallsyms_addresses[best + 1];
else
symbol_end = (unsigned long)_etext; symbol_end = (unsigned long)_etext;
for (i = best+1; i < kallsyms_num_syms; i++) {
if (kallsyms_addresses[i] != kallsyms_addresses[best]){
symbol_end = kallsyms_addresses[i];
break;
}
}
*symbolsize = symbol_end - kallsyms_addresses[best]; *symbolsize = symbol_end - kallsyms_addresses[best];
*modname = NULL; *modname = NULL;
......
...@@ -8,12 +8,11 @@ ...@@ -8,12 +8,11 @@
# docproc: Preprocess .tmpl file in order to generate .sgml documentation # docproc: Preprocess .tmpl file in order to generate .sgml documentation
# conmakehash: Create arrays for initializing the kernel console tables # conmakehash: Create arrays for initializing the kernel console tables
host-progs := fixdep split-include conmakehash docproc host-progs := fixdep split-include conmakehash docproc kallsyms
build-targets := $(host-progs) build-targets := $(host-progs)
# Let clean descend into subdirs # Let clean descend into subdirs
subdir- := lxdialog kconfig subdir- := lxdialog kconfig
# fixdep is needed to compile other host programs # fixdep is needed to compile other host programs
$(obj)/split-include $(obj)/docproc \ $(obj)/split-include $(obj)/docproc $(obj)/conmakehash: $(obj)/fixdep
$(obj)/conmakehash: $(obj)/fixdep
#! /bin/sh
# Written by Rusty Russell <rusty@rustcorp.com.au> 2002.
if [ $# -ne 2 ]; then
echo Usage: kallsyms vmlinux objfile >&2
echo Adds a .kallsyms section containing symbol info.
exit 1
fi
set -e
# Clean up on exit.
trap "rm -f kallsyms.map kallsyms.c $2" 0
# Takes nm output from $1, produces a .c file on standard output.
encode_symbols()
{
# First take addresses.
echo "unsigned long kallsyms_addresses[] = {"
sed 's/^[ ]*\([A-Fa-f0-9]*\).*/0x\1UL,/' < $1
echo "};"
# Now output size.
echo "unsigned long kallsyms_num_syms = `wc -l < $1`;"
# Now output names.
echo "char kallsyms_names[] = ";
sed 's/^[ ]*[A-Fa-f0-9]*[ ]*.[ ]\(.*\)/"\1\\0"/' < $1
echo ";"
}
# FIXME: Use System.map as input, and regenerate each time in Makefile.
$NM -n $1 | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > kallsyms.map
encode_symbols kallsyms.map > kallsyms.c
$CC $CFLAGS -c -o $2 kallsyms.c
trap "rm -f kallsyms.map kallsyms.c" 0
exit 0
/* Generate assembler source containing symbol information
*
* Copyright 2002 by Kai Germaschewski
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Usage: nm -n vmlinux | scripts/kallsyms > symbols.S
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct sym_entry {
unsigned long long addr;
char type;
char *sym;
};
static struct sym_entry *table;
static int size, cnt;
static unsigned long long _stext, _etext;
static void
usage(void)
{
fprintf(stderr, "Usage: kallsyms < in.map > out.S\n");
exit(1);
}
static int
read_symbol(FILE *in, struct sym_entry *s)
{
char str[500];
int rc;
rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str);
if (rc != 3) {
if (rc != EOF) {
/* skip line */
fgets(str, 500, in);
}
return -1;
}
s->sym = strdup(str);
return 0;
}
static int
symbol_valid(struct sym_entry *s)
{
if (s->addr < _stext)
return 0;
if (s->addr > _etext)
return 0;
if (strstr(s->sym, "_compiled."))
return 0;
return 1;
}
static void
read_map(FILE *in)
{
int i;
while (!feof(in)) {
if (cnt >= size) {
size += 10000;
table = realloc(table, sizeof(*table) * size);
if (!table) {
fprintf(stderr, "out of memory\n");
exit (1);
}
}
if (read_symbol(in, &table[cnt]) == 0)
cnt++;
}
for (i = 0; i < cnt; i++) {
if (strcmp(table[i].sym, "_stext") == 0)
_stext = table[i].addr;
if (strcmp(table[i].sym, "_etext") == 0)
_etext = table[i].addr;
}
}
static void
write_src(void)
{
unsigned long long last_addr;
int i, valid = 0;
printf(".data\n");
printf(".globl kallsyms_addresses\n");
printf("\t.align 8\n");
printf("kallsyms_addresses:\n");
for (i = 0, last_addr = 0; i < cnt; i++) {
if (!symbol_valid(&table[i]))
continue;
if (table[i].addr == last_addr)
continue;
printf("\t.long\t%#llx\n", table[i].addr);
valid++;
last_addr = table[i].addr;
}
printf("\n");
printf(".globl kallsyms_num_syms\n");
printf("\t.align 8\n");
printf("\t.long\t%d\n", valid);
printf("\n");
printf(".globl kallsyms_names\n");
printf(".data\n");
printf("\t.align 8\n");
printf("kallsyms_names:\n");
for (i = 0, last_addr = 0; i < cnt; i++) {
if (!symbol_valid(&table[i]))
continue;
if (table[i].addr == last_addr)
continue;
printf("\t.string\t\"%s\"\n", table[i].sym);
last_addr = table[i].addr;
}
printf("\n");
}
int
main(int argc, char **argv)
{
if (argc != 1)
usage();
read_map(stdin);
write_src();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment