MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / scripts / kallsyms.c
blobe21a5d1a255aea317d0e72e91435c7d68b28ea7c
1 /* Generate assembler source containing symbol information
3 * Copyright 2002 by Kai Germaschewski
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
8 * Usage: nm -n vmlinux | scripts/kallsyms [--all-symbols] > symbols.S
9 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
16 struct sym_entry {
17 unsigned long long addr;
18 char type;
19 char *sym;
23 static struct sym_entry *table;
24 static int size, cnt;
25 static unsigned long long _stext, _etext, _sinittext, _einittext;
26 static int all_symbols = 0;
28 static void
29 usage(void)
31 fprintf(stderr, "Usage: kallsyms [--all-symbols] < in.map > out.S\n");
32 exit(1);
35 static int
36 read_symbol(FILE *in, struct sym_entry *s)
38 char str[500];
39 int rc;
41 rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str);
42 if (rc != 3) {
43 if (rc != EOF) {
44 /* skip line */
45 fgets(str, 500, in);
47 return -1;
50 /* Ignore most absolute/undefined (?) symbols. */
51 if (strcmp(str, "_stext") == 0)
52 _stext = s->addr;
53 else if (strcmp(str, "_etext") == 0)
54 _etext = s->addr;
55 else if (strcmp(str, "_sinittext") == 0)
56 _sinittext = s->addr;
57 else if (strcmp(str, "_einittext") == 0)
58 _einittext = s->addr;
59 else if (toupper(s->type) == 'A' || toupper(s->type) == 'U')
60 return -1;
62 s->sym = strdup(str);
63 return 0;
66 static int
67 symbol_valid(struct sym_entry *s)
69 if (!all_symbols) {
70 if ((s->addr < _stext || s->addr > _etext)
71 && (s->addr < _sinittext || s->addr > _einittext))
72 return 0;
75 /* Exclude symbols which vary between passes. Passes 1 and 2 must have
76 * identical symbol lists. The kallsyms_* symbols below are only added
77 * after pass 1, they would be included in pass 2 when --all-symbols is
78 * specified so exclude them to get a stable symbol list.
80 if (strstr(s->sym, "_compiled.") ||
81 strcmp(s->sym, "kallsyms_addresses") == 0 ||
82 strcmp(s->sym, "kallsyms_num_syms") == 0 ||
83 strcmp(s->sym, "kallsyms_names") == 0)
84 return 0;
86 /* Exclude linker generated symbols which vary between passes */
87 if (strcmp(s->sym, "_SDA_BASE_") == 0 || /* ppc */
88 strcmp(s->sym, "_SDA2_BASE_") == 0) /* ppc */
89 return 0;
91 return 1;
94 static void
95 read_map(FILE *in)
97 while (!feof(in)) {
98 if (cnt >= size) {
99 size += 10000;
100 table = realloc(table, sizeof(*table) * size);
101 if (!table) {
102 fprintf(stderr, "out of memory\n");
103 exit (1);
106 if (read_symbol(in, &table[cnt]) == 0)
107 cnt++;
111 static void
112 write_src(void)
114 int i, valid = 0;
115 char *prev;
117 printf("#include <asm/types.h>\n");
118 printf("#if BITS_PER_LONG == 64\n");
119 printf("#define PTR .quad\n");
120 printf("#define ALGN .align 8\n");
121 printf("#else\n");
122 printf("#define PTR .long\n");
123 printf("#define ALGN .align 4\n");
124 printf("#endif\n");
126 printf(".data\n");
128 printf(".globl kallsyms_addresses\n");
129 printf("\tALGN\n");
130 printf("kallsyms_addresses:\n");
131 for (i = 0; i < cnt; i++) {
132 if (!symbol_valid(&table[i]))
133 continue;
135 printf("\tPTR\t%#llx\n", table[i].addr);
136 valid++;
138 printf("\n");
140 printf(".globl kallsyms_num_syms\n");
141 printf("\tALGN\n");
142 printf("kallsyms_num_syms:\n");
143 printf("\tPTR\t%d\n", valid);
144 printf("\n");
146 printf(".globl kallsyms_names\n");
147 printf("\tALGN\n");
148 printf("kallsyms_names:\n");
149 prev = "";
150 for (i = 0; i < cnt; i++) {
151 int k;
153 if (!symbol_valid(&table[i]))
154 continue;
156 for (k = 0; table[i].sym[k] && table[i].sym[k] == prev[k]; ++k)
159 printf("\t.byte 0x%02x\n\t.asciz\t\"%s\"\n", k, table[i].sym + k);
160 prev = table[i].sym;
162 printf("\n");
166 main(int argc, char **argv)
168 if (argc == 2 && strcmp(argv[1], "--all-symbols") == 0)
169 all_symbols = 1;
170 else if (argc != 1)
171 usage();
173 read_map(stdin);
174 write_src();
176 return 0;