patch-2_6_7-vs1_9_1_12
[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 [--all-symbols] > symbols.S
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <ctype.h>
15
16 struct sym_entry {
17         unsigned long long addr;
18         char type;
19         char *sym;
20 };
21
22
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;
27
28 static void
29 usage(void)
30 {
31         fprintf(stderr, "Usage: kallsyms [--all-symbols] < in.map > out.S\n");
32         exit(1);
33 }
34
35 static int
36 read_symbol(FILE *in, struct sym_entry *s)
37 {
38         char str[500];
39         int rc;
40
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);
46                 }
47                 return -1;
48         }
49
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;
61
62         s->sym = strdup(str);
63         return 0;
64 }
65
66 static int
67 symbol_valid(struct sym_entry *s)
68 {
69         if (!all_symbols) {
70                 if ((s->addr < _stext || s->addr > _etext)
71                     && (s->addr < _sinittext || s->addr > _einittext))
72                         return 0;
73         }
74
75         if (strstr(s->sym, "_compiled."))
76                 return 0;
77
78         return 1;
79 }
80
81 static void
82 read_map(FILE *in)
83 {
84         while (!feof(in)) {
85                 if (cnt >= size) {
86                         size += 10000;
87                         table = realloc(table, sizeof(*table) * size);
88                         if (!table) {
89                                 fprintf(stderr, "out of memory\n");
90                                 exit (1);
91                         }
92                 }
93                 if (read_symbol(in, &table[cnt]) == 0)
94                         cnt++;
95         }
96 }
97
98 static void
99 write_src(void)
100 {
101         int i, valid = 0;
102         char *prev;
103
104         printf("#include <asm/types.h>\n");
105         printf("#if BITS_PER_LONG == 64\n");
106         printf("#define PTR .quad\n");
107         printf("#define ALGN .align 8\n");
108         printf("#else\n");
109         printf("#define PTR .long\n");
110         printf("#define ALGN .align 4\n");
111         printf("#endif\n");
112
113         printf(".data\n");
114
115         printf(".globl kallsyms_addresses\n");
116         printf("\tALGN\n");
117         printf("kallsyms_addresses:\n");
118         for (i = 0; i < cnt; i++) {
119                 if (!symbol_valid(&table[i]))
120                         continue;
121
122                 printf("\tPTR\t%#llx\n", table[i].addr);
123                 valid++;
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; i < cnt; i++) {
138                 int k;
139
140                 if (!symbol_valid(&table[i]))
141                         continue;
142
143                 for (k = 0; table[i].sym[k] && table[i].sym[k] == prev[k]; ++k)
144                         ; 
145
146                 printf("\t.byte 0x%02x\n\t.asciz\t\"%s\"\n", k, table[i].sym + k);
147                 prev = table[i].sym;
148         }
149         printf("\n");
150 }
151
152 int
153 main(int argc, char **argv)
154 {
155         if (argc == 2 && strcmp(argv[1], "--all-symbols") == 0)
156                 all_symbols = 1;
157         else if (argc != 1)
158                 usage();
159
160         read_map(stdin);
161         write_src();
162
163         return 0;
164 }
165