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