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