ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / scripts / kallsyms.c
1 /* Generate assembler source containing symbol information
2  *
3  * Copyright 2002       by Kai Germaschewski
4  *
5  * This software may be used and distributed according to the terms
6  * of the GNU General Public License, incorporated herein by reference.
7  *
8  * Usage: nm -n vmlinux | scripts/kallsyms > symbols.S
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 struct sym_entry {
16         unsigned long long addr;
17         char type;
18         char *sym;
19 };
20
21
22 static struct sym_entry *table;
23 static int size, cnt;
24 static unsigned long long _stext, _etext, _sinittext, _einittext;
25
26 static void
27 usage(void)
28 {
29         fprintf(stderr, "Usage: kallsyms < in.map > out.S\n");
30         exit(1);
31 }
32
33 static int
34 read_symbol(FILE *in, struct sym_entry *s)
35 {
36         char str[500];
37         int rc;
38
39         rc = fscanf(in, "%llx %c %499s\n", &s->addr, &s->type, str);
40         if (rc != 3) {
41                 if (rc != EOF) {
42                         /* skip line */
43                         fgets(str, 500, in);
44                 }
45                 return -1;
46         }
47         s->sym = strdup(str);
48         return 0;
49 }
50
51 static int
52 symbol_valid(struct sym_entry *s)
53 {
54         if ((s->addr < _stext || s->addr > _etext)
55             && (s->addr < _sinittext || s->addr > _einittext))
56                 return 0;
57
58         if (strstr(s->sym, "_compiled."))
59                 return 0;
60
61         return 1;
62 }
63
64 static void
65 read_map(FILE *in)
66 {
67         int i;
68
69         while (!feof(in)) {
70                 if (cnt >= size) {
71                         size += 10000;
72                         table = realloc(table, sizeof(*table) * size);
73                         if (!table) {
74                                 fprintf(stderr, "out of memory\n");
75                                 exit (1);
76                         }
77                 }
78                 if (read_symbol(in, &table[cnt]) == 0)
79                         cnt++;
80         }
81         for (i = 0; i < cnt; i++) {
82                 if (strcmp(table[i].sym, "_stext") == 0)
83                         _stext = table[i].addr;
84                 if (strcmp(table[i].sym, "_etext") == 0)
85                         _etext = table[i].addr;
86                 if (strcmp(table[i].sym, "_sinittext") == 0)
87                         _sinittext = table[i].addr;
88                 if (strcmp(table[i].sym, "_einittext") == 0)
89                         _einittext = table[i].addr;
90         }
91 }
92
93 static void
94 write_src(void)
95 {
96         unsigned long long last_addr;
97         int i, valid = 0;
98         char *prev;
99
100         printf("#include <asm/types.h>\n");
101         printf("#if BITS_PER_LONG == 64\n");
102         printf("#define PTR .quad\n");
103         printf("#define ALGN .align 8\n");
104         printf("#else\n");
105         printf("#define PTR .long\n");
106         printf("#define ALGN .align 4\n");
107         printf("#endif\n");
108
109         printf(".data\n");
110
111         printf(".globl kallsyms_addresses\n");
112         printf("\tALGN\n");
113         printf("kallsyms_addresses:\n");
114         for (i = 0, last_addr = 0; i < cnt; i++) {
115                 if (!symbol_valid(&table[i]))
116                         continue;
117                 
118                 if (table[i].addr == last_addr)
119                         continue;
120
121                 printf("\tPTR\t%#llx\n", table[i].addr);
122                 valid++;
123                 last_addr = table[i].addr;
124         }
125         printf("\n");
126
127         printf(".globl kallsyms_num_syms\n");
128         printf("\tALGN\n");
129         printf("kallsyms_num_syms:\n");
130         printf("\tPTR\t%d\n", valid);
131         printf("\n");
132
133         printf(".globl kallsyms_names\n");
134         printf("\tALGN\n");
135         printf("kallsyms_names:\n");
136         prev = ""; 
137         for (i = 0, last_addr = 0; i < cnt; i++) {
138                 int k;
139
140                 if (!symbol_valid(&table[i]))
141                         continue;
142                 
143                 if (table[i].addr == last_addr)
144                         continue;
145
146                 for (k = 0; table[i].sym[k] && table[i].sym[k] == prev[k]; ++k)
147                         ; 
148
149                 printf("\t.byte 0x%02x\n\t.asciz\t\"%s\"\n", k, table[i].sym + k);
150                 last_addr = table[i].addr;
151                 prev = table[i].sym;
152         }
153         printf("\n");
154 }
155
156 int
157 main(int argc, char **argv)
158 {
159         if (argc != 1)
160                 usage();
161
162         read_map(stdin);
163         write_src();
164
165         return 0;
166 }
167