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> 32#endif /* __GNU_LIBRARY__ */ 33 34#include "genksyms.h" 35/*----------------------------------------------------------------------*/ 36 37#define HASH_BUCKETS 4096 38 39static struct symbol *symtab[HASH_BUCKETS]; 40static FILE *debugfile; 41 42int cur_line = 1; 43char *cur_filename, *source_file; 44int in_source_file; 45 46static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, 47 flag_preserve, flag_warnings; 48static const char *mod_prefix = ""; 49 50static int errors; 51static int nsyms; 52 53static struct symbol *expansion_trail; 54static struct symbol *visited_symbols; 55 56static 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 68static int equal_list(struct string_list *a, struct string_list *b); 69static void print_list(FILE * f, struct string_list *list); 70static struct string_list *concat_list(struct string_list *start, ...); 71static struct string_list *mk_node(const char *string); 72static void print_location(void); 73static void print_type_name(enum symbol_type type, const char *name); 74 75/*----------------------------------------------------------------------*/ 76 77static 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 132static unsigned long partial_crc32_one(unsigned char c, unsigned long crc) 133{ 134 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); 135} 136 137static 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 144static unsigned long crc32(const char *s) 145{ 146 return partial_crc32(s, 0xffffffff) ^ 0xffffffff; 147} 148 149/*----------------------------------------------------------------------*/ 150 151static 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 166struct 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 182static 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 197static 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 321struct 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 327static 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 335void free_node(struct string_list *node) 336{ 337 free(node->string); 338 free(node); 339} 340 341void 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 350static 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 362static 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 379struct 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 390struct 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 406static 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 420static 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 size_t 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 466static 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 502static 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 511static 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 540static 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 644void 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 700static void print_location(void) 701{ 702 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line); 703} 704 705static 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 713void 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 729static void genksyms_usage(void) 730{ 731 fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n" 732#ifdef __GNU_LIBRARY__ 733 " -s, --symbol-prefix Select symbol prefix\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 " -s Select symbol prefix\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 758int 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 {"symbol-prefix", 1, 0, 's'}, 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, "s:dwqVDr:T:ph", 779 &long_opts[0], NULL)) != EOF) 780#else /* __GNU_LIBRARY__ */ 781 while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF) 782#endif /* __GNU_LIBRARY__ */ 783 switch (o) { 784 case 's': 785 mod_prefix = 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 { 829 extern int yydebug; 830 extern int yy_flex_debug; 831 832 yydebug = (flag_debug > 1); 833 yy_flex_debug = (flag_debug > 2); 834 835 debugfile = stderr; 836 /* setlinebuf(debugfile); */ 837 } 838 839 if (flag_reference) { 840 read_reference(ref_file); 841 fclose(ref_file); 842 } 843 844 yyparse(); 845 846 if (flag_dump_types && visited_symbols) { 847 while (visited_symbols != (struct symbol *)-1L) { 848 struct symbol *sym = visited_symbols; 849 850 if (sym->is_override) 851 fputs("override ", dumpfile); 852 if (symbol_types[sym->type].n) { 853 putc(symbol_types[sym->type].n, dumpfile); 854 putc('#', dumpfile); 855 } 856 fputs(sym->name, dumpfile); 857 putc(' ', dumpfile); 858 if (sym->is_extern) 859 fputs("extern ", dumpfile); 860 print_list(dumpfile, sym->defn); 861 putc('\n', dumpfile); 862 863 visited_symbols = sym->visited; 864 sym->visited = NULL; 865 } 866 } 867 868 if (flag_debug) { 869 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", 870 nsyms, HASH_BUCKETS, 871 (double)nsyms / (double)HASH_BUCKETS); 872 } 873 874 return errors != 0; 875} 876