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