root/scripts/genksyms/genksyms.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. partial_crc32_one
  2. partial_crc32
  3. crc32
  4. map_to_ns
  5. find_symbol
  6. is_unknown_symbol
  7. __add_symbol
  8. add_symbol
  9. add_reference_symbol
  10. free_node
  11. free_list
  12. mk_node
  13. concat_list
  14. copy_node
  15. copy_list_range
  16. equal_list
  17. read_node
  18. read_reference
  19. print_node
  20. print_list
  21. expand_and_crc_sym
  22. export_symbol
  23. print_location
  24. print_type_name
  25. error_with_pos
  26. genksyms_usage
  27. main

   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 }

/* [<][>][^][v][top][bottom][index][help] */