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