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 <hashtable.h> 22 23 #include "genksyms.h" 24 /*----------------------------------------------------------------------*/ 25 26 static HASHTABLE_DEFINE(symbol_hashtable, 1U << 12); 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 struct symbol *sym; 155 156 hash_for_each_possible(symbol_hashtable, sym, hnode, crc32(name)) { 157 if (map_to_ns(sym->type) == map_to_ns(ns) && 158 strcmp(name, sym->name) == 0 && 159 sym->is_declared) 160 break; 161 } 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); 228 hash_for_each_possible(symbol_hashtable, sym, hnode, h) { 229 if (map_to_ns(sym->type) != map_to_ns(type) || 230 strcmp(name, sym->name)) 231 continue; 232 233 if (is_reference) { 234 break; 235 } else if (sym->type == type && equal_list(sym->defn, defn)) { 236 if (!sym->is_declared && sym->is_override) { 237 print_location(); 238 print_type_name(type, name); 239 fprintf(stderr, " modversion is unchanged\n"); 240 } 241 sym->is_declared = 1; 242 } else if (sym->is_declared) { 243 error_with_pos("redefinition of %s", name); 244 } else if (sym->is_override && flag_preserve) { 245 print_location(); 246 fprintf(stderr, "ignoring "); 247 print_type_name(type, name); 248 fprintf(stderr, " modversion change\n"); 249 sym->is_declared = 1; 250 } else { 251 status = is_unknown_symbol(sym) ? 252 STATUS_DEFINED : STATUS_MODIFIED; 253 break; 254 } 255 free_list(defn, NULL); 256 return sym; 257 } 258 259 if (sym) { 260 hash_del(&sym->hnode); 261 262 free_list(sym->defn, NULL); 263 free(sym->name); 264 free(sym); 265 --nsyms; 266 } 267 268 sym = xmalloc(sizeof(*sym)); 269 sym->name = xstrdup(name); 270 sym->type = type; 271 sym->defn = defn; 272 sym->expansion_trail = NULL; 273 sym->visited = NULL; 274 sym->is_extern = is_extern; 275 276 hash_add(symbol_hashtable, &sym->hnode, h); 277 278 sym->is_declared = !is_reference; 279 sym->status = status; 280 sym->is_override = 0; 281 282 if (flag_debug) { 283 if (symbol_types[type].name) 284 fprintf(debugfile, "Defn for %s %s == <", 285 symbol_types[type].name, name); 286 else 287 fprintf(debugfile, "Defn for type%d %s == <", 288 type, name); 289 if (is_extern) 290 fputs("extern ", debugfile); 291 print_list(debugfile, defn); 292 fputs(">\n", debugfile); 293 } 294 295 ++nsyms; 296 return sym; 297 } 298 299 struct symbol *add_symbol(const char *name, enum symbol_type type, 300 struct string_list *defn, int is_extern) 301 { 302 return __add_symbol(name, type, defn, is_extern, 0); 303 } 304 305 static struct symbol *add_reference_symbol(const char *name, enum symbol_type type, 306 struct string_list *defn, int is_extern) 307 { 308 return __add_symbol(name, type, defn, is_extern, 1); 309 } 310 311 /*----------------------------------------------------------------------*/ 312 313 void free_node(struct string_list *node) 314 { 315 free(node->string); 316 free(node); 317 } 318 319 void free_list(struct string_list *s, struct string_list *e) 320 { 321 while (s != e) { 322 struct string_list *next = s->next; 323 free_node(s); 324 s = next; 325 } 326 } 327 328 static struct string_list *mk_node(const char *string) 329 { 330 struct string_list *newnode; 331 332 newnode = xmalloc(sizeof(*newnode)); 333 newnode->string = xstrdup(string); 334 newnode->tag = SYM_NORMAL; 335 newnode->next = NULL; 336 337 return newnode; 338 } 339 340 static struct string_list *concat_list(struct string_list *start, ...) 341 { 342 va_list ap; 343 struct string_list *n, *n2; 344 345 if (!start) 346 return NULL; 347 for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) { 348 for (n2 = n; n2->next; n2 = n2->next) 349 ; 350 n2->next = start; 351 start = n; 352 } 353 va_end(ap); 354 return start; 355 } 356 357 struct string_list *copy_node(struct string_list *node) 358 { 359 struct string_list *newnode; 360 361 newnode = xmalloc(sizeof(*newnode)); 362 newnode->string = xstrdup(node->string); 363 newnode->tag = node->tag; 364 365 return newnode; 366 } 367 368 struct string_list *copy_list_range(struct string_list *start, 369 struct string_list *end) 370 { 371 struct string_list *res, *n; 372 373 if (start == end) 374 return NULL; 375 n = res = copy_node(start); 376 for (start = start->next; start != end; start = start->next) { 377 n->next = copy_node(start); 378 n = n->next; 379 } 380 n->next = NULL; 381 return res; 382 } 383 384 static int equal_list(struct string_list *a, struct string_list *b) 385 { 386 while (a && b) { 387 if (a->tag != b->tag || strcmp(a->string, b->string)) 388 return 0; 389 a = a->next; 390 b = b->next; 391 } 392 393 return !a && !b; 394 } 395 396 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 397 398 static struct string_list *read_node(FILE *f) 399 { 400 char buffer[256]; 401 struct string_list node = { 402 .string = buffer, 403 .tag = SYM_NORMAL }; 404 int c, in_string = 0; 405 406 while ((c = fgetc(f)) != EOF) { 407 if (!in_string && c == ' ') { 408 if (node.string == buffer) 409 continue; 410 break; 411 } else if (c == '"') { 412 in_string = !in_string; 413 } else if (c == '\n') { 414 if (node.string == buffer) 415 return NULL; 416 ungetc(c, f); 417 break; 418 } 419 if (node.string >= buffer + sizeof(buffer) - 1) { 420 fprintf(stderr, "Token too long\n"); 421 exit(1); 422 } 423 *node.string++ = c; 424 } 425 if (node.string == buffer) 426 return NULL; 427 *node.string = 0; 428 node.string = buffer; 429 430 if (node.string[1] == '#') { 431 size_t n; 432 433 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) { 434 if (node.string[0] == symbol_types[n].n) { 435 node.tag = n; 436 node.string += 2; 437 return copy_node(&node); 438 } 439 } 440 fprintf(stderr, "Unknown type %c\n", node.string[0]); 441 exit(1); 442 } 443 return copy_node(&node); 444 } 445 446 static void read_reference(FILE *f) 447 { 448 while (!feof(f)) { 449 struct string_list *defn = NULL; 450 struct string_list *sym, *def; 451 int is_extern = 0, is_override = 0; 452 struct symbol *subsym; 453 454 sym = read_node(f); 455 if (sym && sym->tag == SYM_NORMAL && 456 !strcmp(sym->string, "override")) { 457 is_override = 1; 458 free_node(sym); 459 sym = read_node(f); 460 } 461 if (!sym) 462 continue; 463 def = read_node(f); 464 if (def && def->tag == SYM_NORMAL && 465 !strcmp(def->string, "extern")) { 466 is_extern = 1; 467 free_node(def); 468 def = read_node(f); 469 } 470 while (def) { 471 def->next = defn; 472 defn = def; 473 def = read_node(f); 474 } 475 subsym = add_reference_symbol(sym->string, sym->tag, 476 defn, is_extern); 477 subsym->is_override = is_override; 478 free_node(sym); 479 } 480 } 481 482 static void print_node(FILE * f, struct string_list *list) 483 { 484 if (symbol_types[list->tag].n) { 485 putc(symbol_types[list->tag].n, f); 486 putc('#', f); 487 } 488 fputs(list->string, f); 489 } 490 491 static void print_list(FILE * f, struct string_list *list) 492 { 493 struct string_list **e, **b; 494 struct string_list *tmp, **tmp2; 495 int elem = 1; 496 497 if (list == NULL) { 498 fputs("(nil)", f); 499 return; 500 } 501 502 tmp = list; 503 while ((tmp = tmp->next) != NULL) 504 elem++; 505 506 b = alloca(elem * sizeof(*e)); 507 e = b + elem; 508 tmp2 = e - 1; 509 510 (*tmp2--) = list; 511 while ((list = list->next) != NULL) 512 *(tmp2--) = list; 513 514 while (b != e) { 515 print_node(f, *b++); 516 putc(' ', f); 517 } 518 } 519 520 static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) 521 { 522 struct string_list *list = sym->defn; 523 struct string_list **e, **b; 524 struct string_list *tmp, **tmp2; 525 int elem = 1; 526 527 if (!list) 528 return crc; 529 530 tmp = list; 531 while ((tmp = tmp->next) != NULL) 532 elem++; 533 534 b = alloca(elem * sizeof(*e)); 535 e = b + elem; 536 tmp2 = e - 1; 537 538 *(tmp2--) = list; 539 while ((list = list->next) != NULL) 540 *(tmp2--) = list; 541 542 while (b != e) { 543 struct string_list *cur; 544 struct symbol *subsym; 545 546 cur = *(b++); 547 switch (cur->tag) { 548 case SYM_NORMAL: 549 if (flag_dump_defs) 550 fprintf(debugfile, "%s ", cur->string); 551 crc = partial_crc32(cur->string, crc); 552 crc = partial_crc32_one(' ', crc); 553 break; 554 555 case SYM_ENUM_CONST: 556 case SYM_TYPEDEF: 557 subsym = find_symbol(cur->string, cur->tag, 0); 558 /* FIXME: Bad reference files can segfault here. */ 559 if (subsym->expansion_trail) { 560 if (flag_dump_defs) 561 fprintf(debugfile, "%s ", cur->string); 562 crc = partial_crc32(cur->string, crc); 563 crc = partial_crc32_one(' ', crc); 564 } else { 565 subsym->expansion_trail = expansion_trail; 566 expansion_trail = subsym; 567 crc = expand_and_crc_sym(subsym, crc); 568 } 569 break; 570 571 case SYM_STRUCT: 572 case SYM_UNION: 573 case SYM_ENUM: 574 subsym = find_symbol(cur->string, cur->tag, 0); 575 if (!subsym) { 576 struct string_list *n; 577 578 error_with_pos("expand undefined %s %s", 579 symbol_types[cur->tag].name, 580 cur->string); 581 n = concat_list(mk_node 582 (symbol_types[cur->tag].name), 583 mk_node(cur->string), 584 mk_node("{"), 585 mk_node("UNKNOWN"), 586 mk_node("}"), NULL); 587 subsym = 588 add_symbol(cur->string, cur->tag, n, 0); 589 } 590 if (subsym->expansion_trail) { 591 if (flag_dump_defs) { 592 fprintf(debugfile, "%s %s ", 593 symbol_types[cur->tag].name, 594 cur->string); 595 } 596 597 crc = partial_crc32(symbol_types[cur->tag].name, 598 crc); 599 crc = partial_crc32_one(' ', crc); 600 crc = partial_crc32(cur->string, crc); 601 crc = partial_crc32_one(' ', crc); 602 } else { 603 subsym->expansion_trail = expansion_trail; 604 expansion_trail = subsym; 605 crc = expand_and_crc_sym(subsym, crc); 606 } 607 break; 608 } 609 } 610 611 { 612 static struct symbol **end = &visited_symbols; 613 614 if (!sym->visited) { 615 *end = sym; 616 end = &sym->visited; 617 sym->visited = (struct symbol *)-1L; 618 } 619 } 620 621 return crc; 622 } 623 624 void export_symbol(const char *name) 625 { 626 struct symbol *sym; 627 unsigned long crc; 628 int has_changed = 0; 629 630 sym = find_symbol(name, SYM_NORMAL, 0); 631 if (!sym) { 632 error_with_pos("export undefined symbol %s", name); 633 return; 634 } 635 636 if (flag_dump_defs) 637 fprintf(debugfile, "Export %s == <", name); 638 639 expansion_trail = (struct symbol *)-1L; 640 641 sym->expansion_trail = expansion_trail; 642 expansion_trail = sym; 643 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff; 644 645 sym = expansion_trail; 646 while (sym != (struct symbol *)-1L) { 647 struct symbol *n = sym->expansion_trail; 648 649 if (sym->status != STATUS_UNCHANGED) { 650 if (!has_changed) { 651 print_location(); 652 fprintf(stderr, 653 "%s: %s: modversion changed because of changes in ", 654 flag_preserve ? "error" : "warning", 655 name); 656 } else { 657 fprintf(stderr, ", "); 658 } 659 print_type_name(sym->type, sym->name); 660 if (sym->status == STATUS_DEFINED) 661 fprintf(stderr, " (became defined)"); 662 has_changed = 1; 663 if (flag_preserve) 664 errors++; 665 } 666 sym->expansion_trail = 0; 667 sym = n; 668 } 669 if (has_changed) 670 fprintf(stderr, "\n"); 671 672 if (flag_dump_defs) 673 fputs(">\n", debugfile); 674 675 printf("#SYMVER %s 0x%08lx\n", name, crc); 676 } 677 678 /*----------------------------------------------------------------------*/ 679 680 static void print_location(void) 681 { 682 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line); 683 } 684 685 static void print_type_name(enum symbol_type type, const char *name) 686 { 687 if (symbol_types[type].name) 688 fprintf(stderr, "%s %s", symbol_types[type].name, name); 689 else 690 fprintf(stderr, "%s", name); 691 } 692 693 void error_with_pos(const char *fmt, ...) 694 { 695 va_list args; 696 697 if (flag_warnings) { 698 print_location(); 699 700 va_start(args, fmt); 701 vfprintf(stderr, fmt, args); 702 va_end(args); 703 putc('\n', stderr); 704 705 errors++; 706 } 707 } 708 709 static void genksyms_usage(void) 710 { 711 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n" 712 " -d, --debug Increment the debug level (repeatable)\n" 713 " -D, --dump Dump expanded symbol defs (for debugging only)\n" 714 " -r, --reference file Read reference symbols from a file\n" 715 " -T, --dump-types file Dump expanded types into file\n" 716 " -p, --preserve Preserve reference modversions or fail\n" 717 " -w, --warnings Enable warnings\n" 718 " -q, --quiet Disable warnings (default)\n" 719 " -h, --help Print this message\n" 720 " -V, --version Print the release version\n" 721 , stderr); 722 } 723 724 int main(int argc, char **argv) 725 { 726 FILE *dumpfile = NULL, *ref_file = NULL; 727 int o; 728 729 struct option long_opts[] = { 730 {"debug", 0, 0, 'd'}, 731 {"warnings", 0, 0, 'w'}, 732 {"quiet", 0, 0, 'q'}, 733 {"dump", 0, 0, 'D'}, 734 {"reference", 1, 0, 'r'}, 735 {"dump-types", 1, 0, 'T'}, 736 {"preserve", 0, 0, 'p'}, 737 {"version", 0, 0, 'V'}, 738 {"help", 0, 0, 'h'}, 739 {0, 0, 0, 0} 740 }; 741 742 while ((o = getopt_long(argc, argv, "dwqVDr:T:ph", 743 &long_opts[0], NULL)) != EOF) 744 switch (o) { 745 case 'd': 746 flag_debug++; 747 break; 748 case 'w': 749 flag_warnings = 1; 750 break; 751 case 'q': 752 flag_warnings = 0; 753 break; 754 case 'V': 755 fputs("genksyms version 2.5.60\n", stderr); 756 break; 757 case 'D': 758 flag_dump_defs = 1; 759 break; 760 case 'r': 761 flag_reference = 1; 762 ref_file = fopen(optarg, "r"); 763 if (!ref_file) { 764 perror(optarg); 765 return 1; 766 } 767 break; 768 case 'T': 769 flag_dump_types = 1; 770 dumpfile = fopen(optarg, "w"); 771 if (!dumpfile) { 772 perror(optarg); 773 return 1; 774 } 775 break; 776 case 'p': 777 flag_preserve = 1; 778 break; 779 case 'h': 780 genksyms_usage(); 781 return 0; 782 default: 783 genksyms_usage(); 784 return 1; 785 } 786 { 787 extern int yydebug; 788 extern int yy_flex_debug; 789 790 yydebug = (flag_debug > 1); 791 yy_flex_debug = (flag_debug > 2); 792 793 debugfile = stderr; 794 /* setlinebuf(debugfile); */ 795 } 796 797 if (flag_reference) { 798 read_reference(ref_file); 799 fclose(ref_file); 800 } 801 802 yyparse(); 803 804 if (flag_dump_types && visited_symbols) { 805 while (visited_symbols != (struct symbol *)-1L) { 806 struct symbol *sym = visited_symbols; 807 808 if (sym->is_override) 809 fputs("override ", dumpfile); 810 if (symbol_types[sym->type].n) { 811 putc(symbol_types[sym->type].n, dumpfile); 812 putc('#', dumpfile); 813 } 814 fputs(sym->name, dumpfile); 815 putc(' ', dumpfile); 816 if (sym->is_extern) 817 fputs("extern ", dumpfile); 818 print_list(dumpfile, sym->defn); 819 putc('\n', dumpfile); 820 821 visited_symbols = sym->visited; 822 sym->visited = NULL; 823 } 824 } 825 826 if (flag_debug) { 827 fprintf(debugfile, "Hash table occupancy %d/%zd = %g\n", 828 nsyms, HASH_SIZE(symbol_hashtable), 829 (double)nsyms / HASH_SIZE(symbol_hashtable)); 830 } 831 832 if (dumpfile) 833 fclose(dumpfile); 834 835 return errors != 0; 836 } 837