module: fix symbol versioning with symbol prefixes
[deliverable/linux.git] / scripts / genksyms / genksyms.c
CommitLineData
1da177e4
LT
1/* Generate kernel symbol version hashes.
2 Copyright 1996, 1997 Linux International.
3
4 New implementation contributed by Richard Henderson <rth@tamu.edu>
5 Based on original work by Bjorn Ekwall <bj0rn@blox.se>
6
7 This file was part of the Linux modutils 2.4.22: moved back into the
8 kernel sources by Rusty Russell/Kai Germaschewski.
9
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2 of the License, or (at your
13 option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24#include <stdio.h>
25#include <string.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <assert.h>
29#include <stdarg.h>
30#ifdef __GNU_LIBRARY__
31#include <getopt.h>
78c04153 32#endif /* __GNU_LIBRARY__ */
1da177e4
LT
33
34#include "genksyms.h"
1da177e4
LT
35/*----------------------------------------------------------------------*/
36
37#define HASH_BUCKETS 4096
38
39static struct symbol *symtab[HASH_BUCKETS];
ce560686 40static FILE *debugfile;
1da177e4
LT
41
42int cur_line = 1;
2c5925d6
MM
43char *cur_filename, *source_file;
44int in_source_file;
1da177e4 45
64e6c1e1 46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
2ea03891 47 flag_preserve, flag_warnings;
ce560686
SR
48static const char *arch = "";
49static const char *mod_prefix = "";
1da177e4
LT
50
51static int errors;
52static int nsyms;
53
54static struct symbol *expansion_trail;
15fde675 55static struct symbol *visited_symbols;
1da177e4 56
7ec8eda1
MM
57static const struct {
58 int n;
59 const char *name;
60} symbol_types[] = {
61 [SYM_NORMAL] = { 0, NULL},
62 [SYM_TYPEDEF] = {'t', "typedef"},
63 [SYM_ENUM] = {'e', "enum"},
64 [SYM_STRUCT] = {'s', "struct"},
65 [SYM_UNION] = {'u', "union"},
e37ddb82 66 [SYM_ENUM_CONST] = {'E', "enum constant"},
1da177e4
LT
67};
68
ce560686
SR
69static int equal_list(struct string_list *a, struct string_list *b);
70static void print_list(FILE * f, struct string_list *list);
68eb8563
MM
71static struct string_list *concat_list(struct string_list *start, ...);
72static struct string_list *mk_node(const char *string);
64e6c1e1
AG
73static void print_location(void);
74static void print_type_name(enum symbol_type type, const char *name);
ce560686 75
1da177e4
LT
76/*----------------------------------------------------------------------*/
77
78c04153
SR
78static const unsigned int crctab32[] = {
79 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
80 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
81 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
82 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
83 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
84 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
85 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
86 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
87 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
88 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
89 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
90 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
91 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
92 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
93 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
94 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
95 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
96 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
97 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
98 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
99 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
100 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
101 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
102 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
103 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
104 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
105 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
106 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
107 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
108 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
109 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
110 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
111 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
112 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
113 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
114 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
115 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
116 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
117 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
118 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
119 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
120 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
121 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
122 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
123 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
124 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
125 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
126 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
127 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
128 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
129 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
130 0x2d02ef8dU
1da177e4
LT
131};
132
ce560686 133static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
1da177e4 134{
78c04153 135 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
1da177e4
LT
136}
137
ce560686 138static unsigned long partial_crc32(const char *s, unsigned long crc)
1da177e4 139{
78c04153
SR
140 while (*s)
141 crc = partial_crc32_one(*s++, crc);
142 return crc;
1da177e4
LT
143}
144
ce560686 145static unsigned long crc32(const char *s)
1da177e4 146{
78c04153 147 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
1da177e4
LT
148}
149
1da177e4
LT
150/*----------------------------------------------------------------------*/
151
ce560686 152static enum symbol_type map_to_ns(enum symbol_type t)
1da177e4 153{
e37ddb82
MM
154 switch (t) {
155 case SYM_ENUM_CONST:
156 case SYM_NORMAL:
157 case SYM_TYPEDEF:
158 return SYM_NORMAL;
159 case SYM_ENUM:
160 case SYM_STRUCT:
161 case SYM_UNION:
162 return SYM_STRUCT;
163 }
78c04153 164 return t;
1da177e4
LT
165}
166
01762c4e 167struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
1da177e4 168{
78c04153
SR
169 unsigned long h = crc32(name) % HASH_BUCKETS;
170 struct symbol *sym;
1da177e4 171
78c04153 172 for (sym = symtab[h]; sym; sym = sym->hash_next)
ce560686 173 if (map_to_ns(sym->type) == map_to_ns(ns) &&
64e6c1e1
AG
174 strcmp(name, sym->name) == 0 &&
175 sym->is_declared)
78c04153 176 break;
1da177e4 177
01762c4e
MM
178 if (exact && sym && sym->type != ns)
179 return NULL;
78c04153 180 return sym;
1da177e4
LT
181}
182
64e6c1e1
AG
183static int is_unknown_symbol(struct symbol *sym)
184{
185 struct string_list *defn;
186
187 return ((sym->type == SYM_STRUCT ||
188 sym->type == SYM_UNION ||
189 sym->type == SYM_ENUM) &&
190 (defn = sym->defn) && defn->tag == SYM_NORMAL &&
191 strcmp(defn->string, "}") == 0 &&
192 (defn = defn->next) && defn->tag == SYM_NORMAL &&
193 strcmp(defn->string, "UNKNOWN") == 0 &&
194 (defn = defn->next) && defn->tag == SYM_NORMAL &&
195 strcmp(defn->string, "{") == 0);
196}
197
b7ed698c 198static struct symbol *__add_symbol(const char *name, enum symbol_type type,
64e6c1e1
AG
199 struct string_list *defn, int is_extern,
200 int is_reference)
1da177e4 201{
e37ddb82 202 unsigned long h;
78c04153 203 struct symbol *sym;
64e6c1e1 204 enum symbol_status status = STATUS_UNCHANGED;
e37ddb82
MM
205 /* The parser adds symbols in the order their declaration completes,
206 * so it is safe to store the value of the previous enum constant in
207 * a static variable.
208 */
209 static int enum_counter;
210 static struct string_list *last_enum_expr;
211
212 if (type == SYM_ENUM_CONST) {
213 if (defn) {
214 free_list(last_enum_expr, NULL);
215 last_enum_expr = copy_list_range(defn, NULL);
216 enum_counter = 1;
217 } else {
218 struct string_list *expr;
219 char buf[20];
220
221 snprintf(buf, sizeof(buf), "%d", enum_counter++);
222 if (last_enum_expr) {
223 expr = copy_list_range(last_enum_expr, NULL);
224 defn = concat_list(mk_node("("),
225 expr,
226 mk_node(")"),
227 mk_node("+"),
228 mk_node(buf), NULL);
229 } else {
230 defn = mk_node(buf);
231 }
232 }
233 } else if (type == SYM_ENUM) {
234 free_list(last_enum_expr, NULL);
235 last_enum_expr = NULL;
236 enum_counter = 0;
237 if (!name)
238 /* Anonymous enum definition, nothing more to do */
239 return NULL;
240 }
78c04153 241
e37ddb82 242 h = crc32(name) % HASH_BUCKETS;
ce560686 243 for (sym = symtab[h]; sym; sym = sym->hash_next) {
64e6c1e1
AG
244 if (map_to_ns(sym->type) == map_to_ns(type) &&
245 strcmp(name, sym->name) == 0) {
246 if (is_reference)
247 /* fall through */ ;
248 else if (sym->type == type &&
249 equal_list(sym->defn, defn)) {
5dae9a55
AG
250 if (!sym->is_declared && sym->is_override) {
251 print_location();
252 print_type_name(type, name);
253 fprintf(stderr, " modversion is "
254 "unchanged\n");
255 }
64e6c1e1
AG
256 sym->is_declared = 1;
257 return sym;
258 } else if (!sym->is_declared) {
5dae9a55
AG
259 if (sym->is_override && flag_preserve) {
260 print_location();
261 fprintf(stderr, "ignoring ");
262 print_type_name(type, name);
263 fprintf(stderr, " modversion change\n");
264 sym->is_declared = 1;
265 return sym;
266 } else {
267 status = is_unknown_symbol(sym) ?
268 STATUS_DEFINED : STATUS_MODIFIED;
269 }
64e6c1e1 270 } else {
78c04153 271 error_with_pos("redefinition of %s", name);
64e6c1e1
AG
272 return sym;
273 }
274 break;
78c04153 275 }
ce560686 276 }
78c04153 277
64e6c1e1
AG
278 if (sym) {
279 struct symbol **psym;
280
281 for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
282 if (*psym == sym) {
283 *psym = sym->hash_next;
284 break;
285 }
286 }
287 --nsyms;
288 }
289
78c04153
SR
290 sym = xmalloc(sizeof(*sym));
291 sym->name = name;
292 sym->type = type;
293 sym->defn = defn;
294 sym->expansion_trail = NULL;
15fde675 295 sym->visited = NULL;
78c04153
SR
296 sym->is_extern = is_extern;
297
298 sym->hash_next = symtab[h];
299 symtab[h] = sym;
300
64e6c1e1
AG
301 sym->is_declared = !is_reference;
302 sym->status = status;
5dae9a55 303 sym->is_override = 0;
64e6c1e1 304
78c04153 305 if (flag_debug) {
7ec8eda1
MM
306 if (symbol_types[type].name)
307 fprintf(debugfile, "Defn for %s %s == <",
308 symbol_types[type].name, name);
309 else
310 fprintf(debugfile, "Defn for type%d %s == <",
311 type, name);
78c04153
SR
312 if (is_extern)
313 fputs("extern ", debugfile);
314 print_list(debugfile, defn);
315 fputs(">\n", debugfile);
316 }
317
318 ++nsyms;
1da177e4 319 return sym;
1da177e4
LT
320}
321
64e6c1e1
AG
322struct symbol *add_symbol(const char *name, enum symbol_type type,
323 struct string_list *defn, int is_extern)
324{
325 return __add_symbol(name, type, defn, is_extern, 0);
326}
327
b7ed698c 328static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
64e6c1e1
AG
329 struct string_list *defn, int is_extern)
330{
331 return __add_symbol(name, type, defn, is_extern, 1);
332}
333
1da177e4
LT
334/*----------------------------------------------------------------------*/
335
ce560686 336void free_node(struct string_list *node)
1da177e4 337{
78c04153
SR
338 free(node->string);
339 free(node);
1da177e4
LT
340}
341
78c04153 342void free_list(struct string_list *s, struct string_list *e)
1da177e4 343{
78c04153
SR
344 while (s != e) {
345 struct string_list *next = s->next;
346 free_node(s);
347 s = next;
348 }
1da177e4
LT
349}
350
68eb8563
MM
351static struct string_list *mk_node(const char *string)
352{
353 struct string_list *newnode;
354
355 newnode = xmalloc(sizeof(*newnode));
356 newnode->string = xstrdup(string);
357 newnode->tag = SYM_NORMAL;
358 newnode->next = NULL;
359
360 return newnode;
361}
362
363static struct string_list *concat_list(struct string_list *start, ...)
364{
365 va_list ap;
366 struct string_list *n, *n2;
367
368 if (!start)
369 return NULL;
370 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
371 for (n2 = n; n2->next; n2 = n2->next)
372 ;
373 n2->next = start;
374 start = n;
375 }
376 va_end(ap);
377 return start;
378}
379
ce560686 380struct string_list *copy_node(struct string_list *node)
1da177e4 381{
78c04153 382 struct string_list *newnode;
1da177e4 383
78c04153
SR
384 newnode = xmalloc(sizeof(*newnode));
385 newnode->string = xstrdup(node->string);
386 newnode->tag = node->tag;
1da177e4 387
78c04153 388 return newnode;
1da177e4
LT
389}
390
e37ddb82
MM
391struct string_list *copy_list_range(struct string_list *start,
392 struct string_list *end)
393{
394 struct string_list *res, *n;
395
396 if (start == end)
397 return NULL;
398 n = res = copy_node(start);
399 for (start = start->next; start != end; start = start->next) {
400 n->next = copy_node(start);
401 n = n->next;
402 }
403 n->next = NULL;
404 return res;
405}
406
ce560686 407static int equal_list(struct string_list *a, struct string_list *b)
1da177e4 408{
78c04153
SR
409 while (a && b) {
410 if (a->tag != b->tag || strcmp(a->string, b->string))
411 return 0;
412 a = a->next;
413 b = b->next;
414 }
1da177e4 415
78c04153 416 return !a && !b;
1da177e4
LT
417}
418
64e6c1e1
AG
419#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
420
b7ed698c 421static struct string_list *read_node(FILE *f)
64e6c1e1
AG
422{
423 char buffer[256];
424 struct string_list node = {
425 .string = buffer,
426 .tag = SYM_NORMAL };
427 int c;
428
429 while ((c = fgetc(f)) != EOF) {
430 if (c == ' ') {
431 if (node.string == buffer)
432 continue;
433 break;
434 } else if (c == '\n') {
435 if (node.string == buffer)
436 return NULL;
437 ungetc(c, f);
438 break;
439 }
440 if (node.string >= buffer + sizeof(buffer) - 1) {
441 fprintf(stderr, "Token too long\n");
442 exit(1);
443 }
444 *node.string++ = c;
445 }
446 if (node.string == buffer)
447 return NULL;
448 *node.string = 0;
449 node.string = buffer;
450
451 if (node.string[1] == '#') {
1ae14703 452 size_t n;
64e6c1e1 453
7ec8eda1
MM
454 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
455 if (node.string[0] == symbol_types[n].n) {
64e6c1e1
AG
456 node.tag = n;
457 node.string += 2;
458 return copy_node(&node);
459 }
460 }
461 fprintf(stderr, "Unknown type %c\n", node.string[0]);
462 exit(1);
463 }
464 return copy_node(&node);
465}
466
467static void read_reference(FILE *f)
468{
469 while (!feof(f)) {
470 struct string_list *defn = NULL;
471 struct string_list *sym, *def;
5dae9a55
AG
472 int is_extern = 0, is_override = 0;
473 struct symbol *subsym;
64e6c1e1
AG
474
475 sym = read_node(f);
5dae9a55
AG
476 if (sym && sym->tag == SYM_NORMAL &&
477 !strcmp(sym->string, "override")) {
478 is_override = 1;
479 free_node(sym);
480 sym = read_node(f);
481 }
64e6c1e1
AG
482 if (!sym)
483 continue;
484 def = read_node(f);
485 if (def && def->tag == SYM_NORMAL &&
486 !strcmp(def->string, "extern")) {
487 is_extern = 1;
488 free_node(def);
489 def = read_node(f);
490 }
491 while (def) {
492 def->next = defn;
493 defn = def;
494 def = read_node(f);
495 }
5dae9a55 496 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
64e6c1e1 497 defn, is_extern);
5dae9a55 498 subsym->is_override = is_override;
64e6c1e1
AG
499 free_node(sym);
500 }
501}
502
ce560686 503static void print_node(FILE * f, struct string_list *list)
1da177e4 504{
7ec8eda1
MM
505 if (symbol_types[list->tag].n) {
506 putc(symbol_types[list->tag].n, f);
78c04153 507 putc('#', f);
78c04153 508 }
15fde675 509 fputs(list->string, f);
1da177e4
LT
510}
511
ce560686 512static void print_list(FILE * f, struct string_list *list)
1da177e4 513{
78c04153
SR
514 struct string_list **e, **b;
515 struct string_list *tmp, **tmp2;
516 int elem = 1;
1da177e4 517
78c04153
SR
518 if (list == NULL) {
519 fputs("(nil)", f);
520 return;
521 }
1da177e4 522
78c04153
SR
523 tmp = list;
524 while ((tmp = tmp->next) != NULL)
525 elem++;
1da177e4 526
78c04153
SR
527 b = alloca(elem * sizeof(*e));
528 e = b + elem;
529 tmp2 = e - 1;
1da177e4 530
78c04153
SR
531 (*tmp2--) = list;
532 while ((list = list->next) != NULL)
533 *(tmp2--) = list;
1da177e4 534
78c04153
SR
535 while (b != e) {
536 print_node(f, *b++);
537 putc(' ', f);
538 }
539}
1da177e4 540
15fde675 541static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
78c04153 542{
15fde675 543 struct string_list *list = sym->defn;
78c04153
SR
544 struct string_list **e, **b;
545 struct string_list *tmp, **tmp2;
546 int elem = 1;
547
548 if (!list)
549 return crc;
550
551 tmp = list;
552 while ((tmp = tmp->next) != NULL)
553 elem++;
554
555 b = alloca(elem * sizeof(*e));
556 e = b + elem;
557 tmp2 = e - 1;
558
559 *(tmp2--) = list;
560 while ((list = list->next) != NULL)
561 *(tmp2--) = list;
562
563 while (b != e) {
564 struct string_list *cur;
565 struct symbol *subsym;
566
567 cur = *(b++);
568 switch (cur->tag) {
569 case SYM_NORMAL:
570 if (flag_dump_defs)
571 fprintf(debugfile, "%s ", cur->string);
572 crc = partial_crc32(cur->string, crc);
573 crc = partial_crc32_one(' ', crc);
574 break;
575
e37ddb82 576 case SYM_ENUM_CONST:
78c04153 577 case SYM_TYPEDEF:
01762c4e 578 subsym = find_symbol(cur->string, cur->tag, 0);
64e6c1e1 579 /* FIXME: Bad reference files can segfault here. */
78c04153
SR
580 if (subsym->expansion_trail) {
581 if (flag_dump_defs)
582 fprintf(debugfile, "%s ", cur->string);
583 crc = partial_crc32(cur->string, crc);
584 crc = partial_crc32_one(' ', crc);
585 } else {
586 subsym->expansion_trail = expansion_trail;
587 expansion_trail = subsym;
15fde675 588 crc = expand_and_crc_sym(subsym, crc);
78c04153
SR
589 }
590 break;
591
592 case SYM_STRUCT:
593 case SYM_UNION:
594 case SYM_ENUM:
01762c4e 595 subsym = find_symbol(cur->string, cur->tag, 0);
78c04153 596 if (!subsym) {
68eb8563 597 struct string_list *n;
78c04153
SR
598
599 error_with_pos("expand undefined %s %s",
7ec8eda1 600 symbol_types[cur->tag].name,
78c04153 601 cur->string);
68eb8563
MM
602 n = concat_list(mk_node
603 (symbol_types[cur->tag].name),
604 mk_node(cur->string),
605 mk_node("{"),
606 mk_node("UNKNOWN"),
607 mk_node("}"), NULL);
78c04153
SR
608 subsym =
609 add_symbol(cur->string, cur->tag, n, 0);
610 }
611 if (subsym->expansion_trail) {
612 if (flag_dump_defs) {
613 fprintf(debugfile, "%s %s ",
7ec8eda1 614 symbol_types[cur->tag].name,
78c04153
SR
615 cur->string);
616 }
617
7ec8eda1 618 crc = partial_crc32(symbol_types[cur->tag].name,
ce560686 619 crc);
78c04153
SR
620 crc = partial_crc32_one(' ', crc);
621 crc = partial_crc32(cur->string, crc);
622 crc = partial_crc32_one(' ', crc);
623 } else {
624 subsym->expansion_trail = expansion_trail;
625 expansion_trail = subsym;
15fde675 626 crc = expand_and_crc_sym(subsym, crc);
78c04153
SR
627 }
628 break;
1da177e4 629 }
1da177e4 630 }
1da177e4 631
15fde675
AG
632 {
633 static struct symbol **end = &visited_symbols;
634
635 if (!sym->visited) {
636 *end = sym;
637 end = &sym->visited;
638 sym->visited = (struct symbol *)-1L;
639 }
640 }
641
78c04153 642 return crc;
1da177e4
LT
643}
644
78c04153 645void export_symbol(const char *name)
1da177e4 646{
78c04153 647 struct symbol *sym;
1da177e4 648
01762c4e 649 sym = find_symbol(name, SYM_NORMAL, 0);
78c04153
SR
650 if (!sym)
651 error_with_pos("export undefined symbol %s", name);
652 else {
653 unsigned long crc;
64e6c1e1 654 int has_changed = 0;
1da177e4 655
78c04153
SR
656 if (flag_dump_defs)
657 fprintf(debugfile, "Export %s == <", name);
1da177e4 658
78c04153 659 expansion_trail = (struct symbol *)-1L;
1da177e4 660
64e6c1e1
AG
661 sym->expansion_trail = expansion_trail;
662 expansion_trail = sym;
15fde675 663 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
1da177e4 664
78c04153
SR
665 sym = expansion_trail;
666 while (sym != (struct symbol *)-1L) {
667 struct symbol *n = sym->expansion_trail;
64e6c1e1
AG
668
669 if (sym->status != STATUS_UNCHANGED) {
670 if (!has_changed) {
671 print_location();
672 fprintf(stderr, "%s: %s: modversion "
673 "changed because of changes "
674 "in ", flag_preserve ? "error" :
675 "warning", name);
676 } else
677 fprintf(stderr, ", ");
678 print_type_name(sym->type, sym->name);
679 if (sym->status == STATUS_DEFINED)
680 fprintf(stderr, " (became defined)");
681 has_changed = 1;
682 if (flag_preserve)
683 errors++;
684 }
78c04153
SR
685 sym->expansion_trail = 0;
686 sym = n;
687 }
64e6c1e1
AG
688 if (has_changed)
689 fprintf(stderr, "\n");
1da177e4 690
78c04153
SR
691 if (flag_dump_defs)
692 fputs(">\n", debugfile);
1da177e4 693
2ea03891
SR
694 /* Used as a linker script. */
695 printf("%s__crc_%s = 0x%08lx ;\n", mod_prefix, name, crc);
78c04153 696 }
1da177e4
LT
697}
698
699/*----------------------------------------------------------------------*/
64e6c1e1
AG
700
701static void print_location(void)
702{
703 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
704}
705
706static void print_type_name(enum symbol_type type, const char *name)
707{
7ec8eda1
MM
708 if (symbol_types[type].name)
709 fprintf(stderr, "%s %s", symbol_types[type].name, name);
64e6c1e1
AG
710 else
711 fprintf(stderr, "%s", name);
712}
713
78c04153 714void error_with_pos(const char *fmt, ...)
1da177e4 715{
78c04153 716 va_list args;
1da177e4 717
78c04153 718 if (flag_warnings) {
64e6c1e1 719 print_location();
1da177e4 720
78c04153
SR
721 va_start(args, fmt);
722 vfprintf(stderr, fmt, args);
723 va_end(args);
724 putc('\n', stderr);
1da177e4 725
78c04153
SR
726 errors++;
727 }
1da177e4
LT
728}
729
ce560686 730static void genksyms_usage(void)
1da177e4 731{
2ea03891 732 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n"
1da177e4 733#ifdef __GNU_LIBRARY__
36091fd3 734 " -a, --arch Select architecture\n"
1da177e4
LT
735 " -d, --debug Increment the debug level (repeatable)\n"
736 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
64e6c1e1
AG
737 " -r, --reference file Read reference symbols from a file\n"
738 " -T, --dump-types file Dump expanded types into file\n"
739 " -p, --preserve Preserve reference modversions or fail\n"
1da177e4
LT
740 " -w, --warnings Enable warnings\n"
741 " -q, --quiet Disable warnings (default)\n"
742 " -h, --help Print this message\n"
743 " -V, --version Print the release version\n"
78c04153 744#else /* __GNU_LIBRARY__ */
36091fd3 745 " -a Select architecture\n"
78c04153
SR
746 " -d Increment the debug level (repeatable)\n"
747 " -D Dump expanded symbol defs (for debugging only)\n"
64e6c1e1
AG
748 " -r file Read reference symbols from a file\n"
749 " -T file Dump expanded types into file\n"
750 " -p Preserve reference modversions or fail\n"
78c04153
SR
751 " -w Enable warnings\n"
752 " -q Disable warnings (default)\n"
753 " -h Print this message\n"
754 " -V Print the release version\n"
755#endif /* __GNU_LIBRARY__ */
1da177e4
LT
756 , stderr);
757}
758
78c04153 759int main(int argc, char **argv)
1da177e4 760{
64e6c1e1 761 FILE *dumpfile = NULL, *ref_file = NULL;
78c04153 762 int o;
1da177e4
LT
763
764#ifdef __GNU_LIBRARY__
78c04153
SR
765 struct option long_opts[] = {
766 {"arch", 1, 0, 'a'},
767 {"debug", 0, 0, 'd'},
768 {"warnings", 0, 0, 'w'},
769 {"quiet", 0, 0, 'q'},
770 {"dump", 0, 0, 'D'},
64e6c1e1 771 {"reference", 1, 0, 'r'},
15fde675 772 {"dump-types", 1, 0, 'T'},
64e6c1e1 773 {"preserve", 0, 0, 'p'},
78c04153
SR
774 {"version", 0, 0, 'V'},
775 {"help", 0, 0, 'h'},
776 {0, 0, 0, 0}
777 };
778
2ea03891 779 while ((o = getopt_long(argc, argv, "a:dwqVDr:T:ph",
78c04153
SR
780 &long_opts[0], NULL)) != EOF)
781#else /* __GNU_LIBRARY__ */
2ea03891 782 while ((o = getopt(argc, argv, "a:dwqVDr:T:ph")) != EOF)
78c04153
SR
783#endif /* __GNU_LIBRARY__ */
784 switch (o) {
785 case 'a':
786 arch = optarg;
787 break;
788 case 'd':
789 flag_debug++;
790 break;
791 case 'w':
792 flag_warnings = 1;
793 break;
794 case 'q':
795 flag_warnings = 0;
796 break;
797 case 'V':
798 fputs("genksyms version 2.5.60\n", stderr);
799 break;
800 case 'D':
801 flag_dump_defs = 1;
802 break;
64e6c1e1
AG
803 case 'r':
804 flag_reference = 1;
805 ref_file = fopen(optarg, "r");
806 if (!ref_file) {
807 perror(optarg);
808 return 1;
809 }
810 break;
15fde675
AG
811 case 'T':
812 flag_dump_types = 1;
813 dumpfile = fopen(optarg, "w");
814 if (!dumpfile) {
815 perror(optarg);
816 return 1;
817 }
818 break;
64e6c1e1
AG
819 case 'p':
820 flag_preserve = 1;
821 break;
78c04153
SR
822 case 'h':
823 genksyms_usage();
824 return 0;
825 default:
826 genksyms_usage();
827 return 1;
828 }
97c3ec63
JH
829 if ((strcmp(arch, "h8300") == 0) || (strcmp(arch, "blackfin") == 0) ||
830 (strcmp(arch, "metag") == 0))
78c04153
SR
831 mod_prefix = "_";
832 {
833 extern int yydebug;
834 extern int yy_flex_debug;
835
836 yydebug = (flag_debug > 1);
837 yy_flex_debug = (flag_debug > 2);
838
839 debugfile = stderr;
840 /* setlinebuf(debugfile); */
841 }
842
c64152bf 843 if (flag_reference) {
64e6c1e1 844 read_reference(ref_file);
c64152bf
AB
845 fclose(ref_file);
846 }
64e6c1e1 847
78c04153
SR
848 yyparse();
849
15fde675
AG
850 if (flag_dump_types && visited_symbols) {
851 while (visited_symbols != (struct symbol *)-1L) {
852 struct symbol *sym = visited_symbols;
853
5dae9a55
AG
854 if (sym->is_override)
855 fputs("override ", dumpfile);
7ec8eda1
MM
856 if (symbol_types[sym->type].n) {
857 putc(symbol_types[sym->type].n, dumpfile);
15fde675
AG
858 putc('#', dumpfile);
859 }
860 fputs(sym->name, dumpfile);
861 putc(' ', dumpfile);
3b40d381
AG
862 if (sym->is_extern)
863 fputs("extern ", dumpfile);
15fde675
AG
864 print_list(dumpfile, sym->defn);
865 putc('\n', dumpfile);
866
867 visited_symbols = sym->visited;
868 sym->visited = NULL;
869 }
870 }
871
78c04153
SR
872 if (flag_debug) {
873 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
874 nsyms, HASH_BUCKETS,
875 (double)nsyms / (double)HASH_BUCKETS);
876 }
877
878 return errors != 0;
1da177e4 879}
This page took 0.71946 seconds and 5 git commands to generate.