11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /* Generate kernel symbol version hashes.
31da177e4SLinus Torvalds Copyright 1996, 1997 Linux International.
41da177e4SLinus Torvalds
51da177e4SLinus Torvalds New implementation contributed by Richard Henderson <rth@tamu.edu>
61da177e4SLinus Torvalds Based on original work by Bjorn Ekwall <bj0rn@blox.se>
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds This file was part of the Linux modutils 2.4.22: moved back into the
91da177e4SLinus Torvalds kernel sources by Rusty Russell/Kai Germaschewski.
101da177e4SLinus Torvalds
111a59d1b8SThomas Gleixner */
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #include <stdio.h>
141da177e4SLinus Torvalds #include <string.h>
151da177e4SLinus Torvalds #include <stdlib.h>
161da177e4SLinus Torvalds #include <unistd.h>
171da177e4SLinus Torvalds #include <assert.h>
181da177e4SLinus Torvalds #include <stdarg.h>
191da177e4SLinus Torvalds #ifdef __GNU_LIBRARY__
201da177e4SLinus Torvalds #include <getopt.h>
211da177e4SLinus Torvalds #endif /* __GNU_LIBRARY__ */
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds #include "genksyms.h"
241da177e4SLinus Torvalds /*----------------------------------------------------------------------*/
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds #define HASH_BUCKETS 4096
271da177e4SLinus Torvalds
281da177e4SLinus Torvalds static struct symbol *symtab[HASH_BUCKETS];
29ce560686SSam Ravnborg static FILE *debugfile;
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds int cur_line = 1;
32ab37d5a4SMasahiro Yamada char *cur_filename;
332c5925d6SMichal Marek int in_source_file;
341da177e4SLinus Torvalds
3564e6c1e1SAndreas Gruenbacher static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
367b453719SMasahiro Yamada flag_preserve, flag_warnings;
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds static int errors;
391da177e4SLinus Torvalds static int nsyms;
401da177e4SLinus Torvalds
411da177e4SLinus Torvalds static struct symbol *expansion_trail;
4215fde675SAndreas Gruenbacher static struct symbol *visited_symbols;
431da177e4SLinus Torvalds
447ec8eda1SMichal Marek static const struct {
457ec8eda1SMichal Marek int n;
467ec8eda1SMichal Marek const char *name;
477ec8eda1SMichal Marek } symbol_types[] = {
487ec8eda1SMichal Marek [SYM_NORMAL] = { 0, NULL},
497ec8eda1SMichal Marek [SYM_TYPEDEF] = {'t', "typedef"},
507ec8eda1SMichal Marek [SYM_ENUM] = {'e', "enum"},
517ec8eda1SMichal Marek [SYM_STRUCT] = {'s', "struct"},
527ec8eda1SMichal Marek [SYM_UNION] = {'u', "union"},
53e37ddb82SMichal Marek [SYM_ENUM_CONST] = {'E', "enum constant"},
541da177e4SLinus Torvalds };
551da177e4SLinus Torvalds
56ce560686SSam Ravnborg static int equal_list(struct string_list *a, struct string_list *b);
57ce560686SSam Ravnborg static void print_list(FILE * f, struct string_list *list);
5868eb8563SMichal Marek static struct string_list *concat_list(struct string_list *start, ...);
5968eb8563SMichal Marek static struct string_list *mk_node(const char *string);
6064e6c1e1SAndreas Gruenbacher static void print_location(void);
6164e6c1e1SAndreas Gruenbacher static void print_type_name(enum symbol_type type, const char *name);
62ce560686SSam Ravnborg
631da177e4SLinus Torvalds /*----------------------------------------------------------------------*/
641da177e4SLinus Torvalds
6578c04153SSam Ravnborg static const unsigned int crctab32[] = {
661da177e4SLinus Torvalds 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
671da177e4SLinus Torvalds 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
681da177e4SLinus Torvalds 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
691da177e4SLinus Torvalds 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
701da177e4SLinus Torvalds 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
711da177e4SLinus Torvalds 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
721da177e4SLinus Torvalds 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
731da177e4SLinus Torvalds 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
741da177e4SLinus Torvalds 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
751da177e4SLinus Torvalds 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
761da177e4SLinus Torvalds 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
771da177e4SLinus Torvalds 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
781da177e4SLinus Torvalds 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
791da177e4SLinus Torvalds 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
801da177e4SLinus Torvalds 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
811da177e4SLinus Torvalds 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
821da177e4SLinus Torvalds 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
831da177e4SLinus Torvalds 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
841da177e4SLinus Torvalds 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
851da177e4SLinus Torvalds 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
861da177e4SLinus Torvalds 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
871da177e4SLinus Torvalds 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
881da177e4SLinus Torvalds 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
891da177e4SLinus Torvalds 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
901da177e4SLinus Torvalds 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
911da177e4SLinus Torvalds 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
921da177e4SLinus Torvalds 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
931da177e4SLinus Torvalds 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
941da177e4SLinus Torvalds 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
951da177e4SLinus Torvalds 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
961da177e4SLinus Torvalds 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
971da177e4SLinus Torvalds 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
981da177e4SLinus Torvalds 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
991da177e4SLinus Torvalds 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
1001da177e4SLinus Torvalds 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
1011da177e4SLinus Torvalds 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
1021da177e4SLinus Torvalds 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
1031da177e4SLinus Torvalds 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
1041da177e4SLinus Torvalds 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
1051da177e4SLinus Torvalds 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
1061da177e4SLinus Torvalds 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
1071da177e4SLinus Torvalds 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
1081da177e4SLinus Torvalds 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
1091da177e4SLinus Torvalds 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
1101da177e4SLinus Torvalds 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
1111da177e4SLinus Torvalds 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
1121da177e4SLinus Torvalds 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
1131da177e4SLinus Torvalds 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
1141da177e4SLinus Torvalds 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
1151da177e4SLinus Torvalds 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
1161da177e4SLinus Torvalds 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
1171da177e4SLinus Torvalds 0x2d02ef8dU
1181da177e4SLinus Torvalds };
1191da177e4SLinus Torvalds
partial_crc32_one(unsigned char c,unsigned long crc)120ce560686SSam Ravnborg static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
1211da177e4SLinus Torvalds {
1221da177e4SLinus Torvalds return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds
partial_crc32(const char * s,unsigned long crc)125ce560686SSam Ravnborg static unsigned long partial_crc32(const char *s, unsigned long crc)
1261da177e4SLinus Torvalds {
1271da177e4SLinus Torvalds while (*s)
1281da177e4SLinus Torvalds crc = partial_crc32_one(*s++, crc);
1291da177e4SLinus Torvalds return crc;
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds
crc32(const char * s)132ce560686SSam Ravnborg static unsigned long crc32(const char *s)
1331da177e4SLinus Torvalds {
1341da177e4SLinus Torvalds return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
1351da177e4SLinus Torvalds }
1361da177e4SLinus Torvalds
1371da177e4SLinus Torvalds /*----------------------------------------------------------------------*/
1381da177e4SLinus Torvalds
map_to_ns(enum symbol_type t)139ce560686SSam Ravnborg static enum symbol_type map_to_ns(enum symbol_type t)
1401da177e4SLinus Torvalds {
141e37ddb82SMichal Marek switch (t) {
142e37ddb82SMichal Marek case SYM_ENUM_CONST:
143e37ddb82SMichal Marek case SYM_NORMAL:
144e37ddb82SMichal Marek case SYM_TYPEDEF:
145e37ddb82SMichal Marek return SYM_NORMAL;
146e37ddb82SMichal Marek case SYM_ENUM:
147e37ddb82SMichal Marek case SYM_STRUCT:
148e37ddb82SMichal Marek case SYM_UNION:
149e37ddb82SMichal Marek return SYM_STRUCT;
150e37ddb82SMichal Marek }
1511da177e4SLinus Torvalds return t;
1521da177e4SLinus Torvalds }
1531da177e4SLinus Torvalds
find_symbol(const char * name,enum symbol_type ns,int exact)15401762c4eSMichal Marek struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
1551da177e4SLinus Torvalds {
1561da177e4SLinus Torvalds unsigned long h = crc32(name) % HASH_BUCKETS;
1571da177e4SLinus Torvalds struct symbol *sym;
1581da177e4SLinus Torvalds
1591da177e4SLinus Torvalds for (sym = symtab[h]; sym; sym = sym->hash_next)
160ce560686SSam Ravnborg if (map_to_ns(sym->type) == map_to_ns(ns) &&
16164e6c1e1SAndreas Gruenbacher strcmp(name, sym->name) == 0 &&
16264e6c1e1SAndreas Gruenbacher sym->is_declared)
1631da177e4SLinus Torvalds break;
1641da177e4SLinus Torvalds
16501762c4eSMichal Marek if (exact && sym && sym->type != ns)
16601762c4eSMichal Marek return NULL;
1671da177e4SLinus Torvalds return sym;
1681da177e4SLinus Torvalds }
1691da177e4SLinus Torvalds
is_unknown_symbol(struct symbol * sym)17064e6c1e1SAndreas Gruenbacher static int is_unknown_symbol(struct symbol *sym)
17164e6c1e1SAndreas Gruenbacher {
17264e6c1e1SAndreas Gruenbacher struct string_list *defn;
17364e6c1e1SAndreas Gruenbacher
17464e6c1e1SAndreas Gruenbacher return ((sym->type == SYM_STRUCT ||
17564e6c1e1SAndreas Gruenbacher sym->type == SYM_UNION ||
17664e6c1e1SAndreas Gruenbacher sym->type == SYM_ENUM) &&
17764e6c1e1SAndreas Gruenbacher (defn = sym->defn) && defn->tag == SYM_NORMAL &&
17864e6c1e1SAndreas Gruenbacher strcmp(defn->string, "}") == 0 &&
17964e6c1e1SAndreas Gruenbacher (defn = defn->next) && defn->tag == SYM_NORMAL &&
18064e6c1e1SAndreas Gruenbacher strcmp(defn->string, "UNKNOWN") == 0 &&
18164e6c1e1SAndreas Gruenbacher (defn = defn->next) && defn->tag == SYM_NORMAL &&
18264e6c1e1SAndreas Gruenbacher strcmp(defn->string, "{") == 0);
18364e6c1e1SAndreas Gruenbacher }
18464e6c1e1SAndreas Gruenbacher
__add_symbol(const char * name,enum symbol_type type,struct string_list * defn,int is_extern,int is_reference)185b7ed698cSLadinu Chandrasinghe static struct symbol *__add_symbol(const char *name, enum symbol_type type,
18664e6c1e1SAndreas Gruenbacher struct string_list *defn, int is_extern,
18764e6c1e1SAndreas Gruenbacher int is_reference)
1881da177e4SLinus Torvalds {
189e37ddb82SMichal Marek unsigned long h;
1901da177e4SLinus Torvalds struct symbol *sym;
19164e6c1e1SAndreas Gruenbacher enum symbol_status status = STATUS_UNCHANGED;
192e37ddb82SMichal Marek /* The parser adds symbols in the order their declaration completes,
193e37ddb82SMichal Marek * so it is safe to store the value of the previous enum constant in
194e37ddb82SMichal Marek * a static variable.
195e37ddb82SMichal Marek */
196e37ddb82SMichal Marek static int enum_counter;
197e37ddb82SMichal Marek static struct string_list *last_enum_expr;
1981da177e4SLinus Torvalds
199e37ddb82SMichal Marek if (type == SYM_ENUM_CONST) {
200e37ddb82SMichal Marek if (defn) {
201e37ddb82SMichal Marek free_list(last_enum_expr, NULL);
202e37ddb82SMichal Marek last_enum_expr = copy_list_range(defn, NULL);
203e37ddb82SMichal Marek enum_counter = 1;
204e37ddb82SMichal Marek } else {
205e37ddb82SMichal Marek struct string_list *expr;
206e37ddb82SMichal Marek char buf[20];
207e37ddb82SMichal Marek
208e37ddb82SMichal Marek snprintf(buf, sizeof(buf), "%d", enum_counter++);
209e37ddb82SMichal Marek if (last_enum_expr) {
210e37ddb82SMichal Marek expr = copy_list_range(last_enum_expr, NULL);
211e37ddb82SMichal Marek defn = concat_list(mk_node("("),
212e37ddb82SMichal Marek expr,
213e37ddb82SMichal Marek mk_node(")"),
214e37ddb82SMichal Marek mk_node("+"),
215e37ddb82SMichal Marek mk_node(buf), NULL);
216e37ddb82SMichal Marek } else {
217e37ddb82SMichal Marek defn = mk_node(buf);
218e37ddb82SMichal Marek }
219e37ddb82SMichal Marek }
220e37ddb82SMichal Marek } else if (type == SYM_ENUM) {
221e37ddb82SMichal Marek free_list(last_enum_expr, NULL);
222e37ddb82SMichal Marek last_enum_expr = NULL;
223e37ddb82SMichal Marek enum_counter = 0;
224e37ddb82SMichal Marek if (!name)
225e37ddb82SMichal Marek /* Anonymous enum definition, nothing more to do */
226e37ddb82SMichal Marek return NULL;
227e37ddb82SMichal Marek }
228e37ddb82SMichal Marek
229e37ddb82SMichal Marek h = crc32(name) % HASH_BUCKETS;
230ce560686SSam Ravnborg for (sym = symtab[h]; sym; sym = sym->hash_next) {
23164e6c1e1SAndreas Gruenbacher if (map_to_ns(sym->type) == map_to_ns(type) &&
23264e6c1e1SAndreas Gruenbacher strcmp(name, sym->name) == 0) {
23364e6c1e1SAndreas Gruenbacher if (is_reference)
23464e6c1e1SAndreas Gruenbacher /* fall through */ ;
23564e6c1e1SAndreas Gruenbacher else if (sym->type == type &&
23664e6c1e1SAndreas Gruenbacher equal_list(sym->defn, defn)) {
2375dae9a55SAndreas Gruenbacher if (!sym->is_declared && sym->is_override) {
2385dae9a55SAndreas Gruenbacher print_location();
2395dae9a55SAndreas Gruenbacher print_type_name(type, name);
2405dae9a55SAndreas Gruenbacher fprintf(stderr, " modversion is "
2415dae9a55SAndreas Gruenbacher "unchanged\n");
2425dae9a55SAndreas Gruenbacher }
24364e6c1e1SAndreas Gruenbacher sym->is_declared = 1;
2449dc841e8SMasahiro Yamada free_list(defn, NULL);
24564e6c1e1SAndreas Gruenbacher return sym;
24664e6c1e1SAndreas Gruenbacher } else if (!sym->is_declared) {
2475dae9a55SAndreas Gruenbacher if (sym->is_override && flag_preserve) {
2485dae9a55SAndreas Gruenbacher print_location();
2495dae9a55SAndreas Gruenbacher fprintf(stderr, "ignoring ");
2505dae9a55SAndreas Gruenbacher print_type_name(type, name);
2515dae9a55SAndreas Gruenbacher fprintf(stderr, " modversion change\n");
2525dae9a55SAndreas Gruenbacher sym->is_declared = 1;
2539dc841e8SMasahiro Yamada free_list(defn, NULL);
2545dae9a55SAndreas Gruenbacher return sym;
2555dae9a55SAndreas Gruenbacher } else {
25664e6c1e1SAndreas Gruenbacher status = is_unknown_symbol(sym) ?
25764e6c1e1SAndreas Gruenbacher STATUS_DEFINED : STATUS_MODIFIED;
2585dae9a55SAndreas Gruenbacher }
25964e6c1e1SAndreas Gruenbacher } else {
2601da177e4SLinus Torvalds error_with_pos("redefinition of %s", name);
2619dc841e8SMasahiro Yamada free_list(defn, NULL);
2621da177e4SLinus Torvalds return sym;
2631da177e4SLinus Torvalds }
26464e6c1e1SAndreas Gruenbacher break;
26564e6c1e1SAndreas Gruenbacher }
26664e6c1e1SAndreas Gruenbacher }
26764e6c1e1SAndreas Gruenbacher
26864e6c1e1SAndreas Gruenbacher if (sym) {
26964e6c1e1SAndreas Gruenbacher struct symbol **psym;
27064e6c1e1SAndreas Gruenbacher
27164e6c1e1SAndreas Gruenbacher for (psym = &symtab[h]; *psym; psym = &(*psym)->hash_next) {
27264e6c1e1SAndreas Gruenbacher if (*psym == sym) {
27364e6c1e1SAndreas Gruenbacher *psym = sym->hash_next;
27464e6c1e1SAndreas Gruenbacher break;
27564e6c1e1SAndreas Gruenbacher }
27664e6c1e1SAndreas Gruenbacher }
277*4517f37bSMasahiro Yamada
278*4517f37bSMasahiro Yamada free_list(sym->defn, NULL);
279*4517f37bSMasahiro Yamada free(sym->name);
280*4517f37bSMasahiro Yamada free(sym);
28164e6c1e1SAndreas Gruenbacher --nsyms;
282ce560686SSam Ravnborg }
2831da177e4SLinus Torvalds
2841da177e4SLinus Torvalds sym = xmalloc(sizeof(*sym));
285*4517f37bSMasahiro Yamada sym->name = xstrdup(name);
2861da177e4SLinus Torvalds sym->type = type;
2871da177e4SLinus Torvalds sym->defn = defn;
2881da177e4SLinus Torvalds sym->expansion_trail = NULL;
28915fde675SAndreas Gruenbacher sym->visited = NULL;
2901da177e4SLinus Torvalds sym->is_extern = is_extern;
2911da177e4SLinus Torvalds
2921da177e4SLinus Torvalds sym->hash_next = symtab[h];
2931da177e4SLinus Torvalds symtab[h] = sym;
2941da177e4SLinus Torvalds
29564e6c1e1SAndreas Gruenbacher sym->is_declared = !is_reference;
29664e6c1e1SAndreas Gruenbacher sym->status = status;
2975dae9a55SAndreas Gruenbacher sym->is_override = 0;
29864e6c1e1SAndreas Gruenbacher
29978c04153SSam Ravnborg if (flag_debug) {
3007ec8eda1SMichal Marek if (symbol_types[type].name)
30178c04153SSam Ravnborg fprintf(debugfile, "Defn for %s %s == <",
3027ec8eda1SMichal Marek symbol_types[type].name, name);
3037ec8eda1SMichal Marek else
3047ec8eda1SMichal Marek fprintf(debugfile, "Defn for type%d %s == <",
3057ec8eda1SMichal Marek type, name);
3061da177e4SLinus Torvalds if (is_extern)
3071da177e4SLinus Torvalds fputs("extern ", debugfile);
3081da177e4SLinus Torvalds print_list(debugfile, defn);
3091da177e4SLinus Torvalds fputs(">\n", debugfile);
3101da177e4SLinus Torvalds }
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds ++nsyms;
3131da177e4SLinus Torvalds return sym;
3141da177e4SLinus Torvalds }
3151da177e4SLinus Torvalds
add_symbol(const char * name,enum symbol_type type,struct string_list * defn,int is_extern)31664e6c1e1SAndreas Gruenbacher struct symbol *add_symbol(const char *name, enum symbol_type type,
31764e6c1e1SAndreas Gruenbacher struct string_list *defn, int is_extern)
31864e6c1e1SAndreas Gruenbacher {
31964e6c1e1SAndreas Gruenbacher return __add_symbol(name, type, defn, is_extern, 0);
32064e6c1e1SAndreas Gruenbacher }
32164e6c1e1SAndreas Gruenbacher
add_reference_symbol(const char * name,enum symbol_type type,struct string_list * defn,int is_extern)322b7ed698cSLadinu Chandrasinghe static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
32364e6c1e1SAndreas Gruenbacher struct string_list *defn, int is_extern)
32464e6c1e1SAndreas Gruenbacher {
32564e6c1e1SAndreas Gruenbacher return __add_symbol(name, type, defn, is_extern, 1);
32664e6c1e1SAndreas Gruenbacher }
32764e6c1e1SAndreas Gruenbacher
3281da177e4SLinus Torvalds /*----------------------------------------------------------------------*/
3291da177e4SLinus Torvalds
free_node(struct string_list * node)330ce560686SSam Ravnborg void free_node(struct string_list *node)
3311da177e4SLinus Torvalds {
3321da177e4SLinus Torvalds free(node->string);
3331da177e4SLinus Torvalds free(node);
3341da177e4SLinus Torvalds }
3351da177e4SLinus Torvalds
free_list(struct string_list * s,struct string_list * e)33678c04153SSam Ravnborg void free_list(struct string_list *s, struct string_list *e)
3371da177e4SLinus Torvalds {
33878c04153SSam Ravnborg while (s != e) {
3391da177e4SLinus Torvalds struct string_list *next = s->next;
3401da177e4SLinus Torvalds free_node(s);
3411da177e4SLinus Torvalds s = next;
3421da177e4SLinus Torvalds }
3431da177e4SLinus Torvalds }
3441da177e4SLinus Torvalds
mk_node(const char * string)34568eb8563SMichal Marek static struct string_list *mk_node(const char *string)
34668eb8563SMichal Marek {
34768eb8563SMichal Marek struct string_list *newnode;
34868eb8563SMichal Marek
34968eb8563SMichal Marek newnode = xmalloc(sizeof(*newnode));
35068eb8563SMichal Marek newnode->string = xstrdup(string);
35168eb8563SMichal Marek newnode->tag = SYM_NORMAL;
35268eb8563SMichal Marek newnode->next = NULL;
35368eb8563SMichal Marek
35468eb8563SMichal Marek return newnode;
35568eb8563SMichal Marek }
35668eb8563SMichal Marek
concat_list(struct string_list * start,...)35768eb8563SMichal Marek static struct string_list *concat_list(struct string_list *start, ...)
35868eb8563SMichal Marek {
35968eb8563SMichal Marek va_list ap;
36068eb8563SMichal Marek struct string_list *n, *n2;
36168eb8563SMichal Marek
36268eb8563SMichal Marek if (!start)
36368eb8563SMichal Marek return NULL;
36468eb8563SMichal Marek for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
36568eb8563SMichal Marek for (n2 = n; n2->next; n2 = n2->next)
36668eb8563SMichal Marek ;
36768eb8563SMichal Marek n2->next = start;
36868eb8563SMichal Marek start = n;
36968eb8563SMichal Marek }
37068eb8563SMichal Marek va_end(ap);
37168eb8563SMichal Marek return start;
37268eb8563SMichal Marek }
37368eb8563SMichal Marek
copy_node(struct string_list * node)374ce560686SSam Ravnborg struct string_list *copy_node(struct string_list *node)
3751da177e4SLinus Torvalds {
3761da177e4SLinus Torvalds struct string_list *newnode;
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds newnode = xmalloc(sizeof(*newnode));
3791da177e4SLinus Torvalds newnode->string = xstrdup(node->string);
3801da177e4SLinus Torvalds newnode->tag = node->tag;
3811da177e4SLinus Torvalds
3821da177e4SLinus Torvalds return newnode;
3831da177e4SLinus Torvalds }
3841da177e4SLinus Torvalds
copy_list_range(struct string_list * start,struct string_list * end)385e37ddb82SMichal Marek struct string_list *copy_list_range(struct string_list *start,
386e37ddb82SMichal Marek struct string_list *end)
387e37ddb82SMichal Marek {
388e37ddb82SMichal Marek struct string_list *res, *n;
389e37ddb82SMichal Marek
390e37ddb82SMichal Marek if (start == end)
391e37ddb82SMichal Marek return NULL;
392e37ddb82SMichal Marek n = res = copy_node(start);
393e37ddb82SMichal Marek for (start = start->next; start != end; start = start->next) {
394e37ddb82SMichal Marek n->next = copy_node(start);
395e37ddb82SMichal Marek n = n->next;
396e37ddb82SMichal Marek }
397e37ddb82SMichal Marek n->next = NULL;
398e37ddb82SMichal Marek return res;
399e37ddb82SMichal Marek }
400e37ddb82SMichal Marek
equal_list(struct string_list * a,struct string_list * b)401ce560686SSam Ravnborg static int equal_list(struct string_list *a, struct string_list *b)
4021da177e4SLinus Torvalds {
40378c04153SSam Ravnborg while (a && b) {
4041da177e4SLinus Torvalds if (a->tag != b->tag || strcmp(a->string, b->string))
4051da177e4SLinus Torvalds return 0;
4061da177e4SLinus Torvalds a = a->next;
4071da177e4SLinus Torvalds b = b->next;
4081da177e4SLinus Torvalds }
4091da177e4SLinus Torvalds
4101da177e4SLinus Torvalds return !a && !b;
4111da177e4SLinus Torvalds }
4121da177e4SLinus Torvalds
41364e6c1e1SAndreas Gruenbacher #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
41464e6c1e1SAndreas Gruenbacher
read_node(FILE * f)415b7ed698cSLadinu Chandrasinghe static struct string_list *read_node(FILE *f)
41664e6c1e1SAndreas Gruenbacher {
41764e6c1e1SAndreas Gruenbacher char buffer[256];
41864e6c1e1SAndreas Gruenbacher struct string_list node = {
41964e6c1e1SAndreas Gruenbacher .string = buffer,
42064e6c1e1SAndreas Gruenbacher .tag = SYM_NORMAL };
421a78f70e8SMichal Marek int c, in_string = 0;
42264e6c1e1SAndreas Gruenbacher
42364e6c1e1SAndreas Gruenbacher while ((c = fgetc(f)) != EOF) {
424a78f70e8SMichal Marek if (!in_string && c == ' ') {
42564e6c1e1SAndreas Gruenbacher if (node.string == buffer)
42664e6c1e1SAndreas Gruenbacher continue;
42764e6c1e1SAndreas Gruenbacher break;
428a78f70e8SMichal Marek } else if (c == '"') {
429a78f70e8SMichal Marek in_string = !in_string;
43064e6c1e1SAndreas Gruenbacher } else if (c == '\n') {
43164e6c1e1SAndreas Gruenbacher if (node.string == buffer)
43264e6c1e1SAndreas Gruenbacher return NULL;
43364e6c1e1SAndreas Gruenbacher ungetc(c, f);
43464e6c1e1SAndreas Gruenbacher break;
43564e6c1e1SAndreas Gruenbacher }
43664e6c1e1SAndreas Gruenbacher if (node.string >= buffer + sizeof(buffer) - 1) {
43764e6c1e1SAndreas Gruenbacher fprintf(stderr, "Token too long\n");
43864e6c1e1SAndreas Gruenbacher exit(1);
43964e6c1e1SAndreas Gruenbacher }
44064e6c1e1SAndreas Gruenbacher *node.string++ = c;
44164e6c1e1SAndreas Gruenbacher }
44264e6c1e1SAndreas Gruenbacher if (node.string == buffer)
44364e6c1e1SAndreas Gruenbacher return NULL;
44464e6c1e1SAndreas Gruenbacher *node.string = 0;
44564e6c1e1SAndreas Gruenbacher node.string = buffer;
44664e6c1e1SAndreas Gruenbacher
44764e6c1e1SAndreas Gruenbacher if (node.string[1] == '#') {
4481ae14703SJesper Juhl size_t n;
44964e6c1e1SAndreas Gruenbacher
4507ec8eda1SMichal Marek for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
4517ec8eda1SMichal Marek if (node.string[0] == symbol_types[n].n) {
45264e6c1e1SAndreas Gruenbacher node.tag = n;
45364e6c1e1SAndreas Gruenbacher node.string += 2;
45464e6c1e1SAndreas Gruenbacher return copy_node(&node);
45564e6c1e1SAndreas Gruenbacher }
45664e6c1e1SAndreas Gruenbacher }
45764e6c1e1SAndreas Gruenbacher fprintf(stderr, "Unknown type %c\n", node.string[0]);
45864e6c1e1SAndreas Gruenbacher exit(1);
45964e6c1e1SAndreas Gruenbacher }
46064e6c1e1SAndreas Gruenbacher return copy_node(&node);
46164e6c1e1SAndreas Gruenbacher }
46264e6c1e1SAndreas Gruenbacher
read_reference(FILE * f)46364e6c1e1SAndreas Gruenbacher static void read_reference(FILE *f)
46464e6c1e1SAndreas Gruenbacher {
46564e6c1e1SAndreas Gruenbacher while (!feof(f)) {
46664e6c1e1SAndreas Gruenbacher struct string_list *defn = NULL;
46764e6c1e1SAndreas Gruenbacher struct string_list *sym, *def;
4685dae9a55SAndreas Gruenbacher int is_extern = 0, is_override = 0;
4695dae9a55SAndreas Gruenbacher struct symbol *subsym;
47064e6c1e1SAndreas Gruenbacher
47164e6c1e1SAndreas Gruenbacher sym = read_node(f);
4725dae9a55SAndreas Gruenbacher if (sym && sym->tag == SYM_NORMAL &&
4735dae9a55SAndreas Gruenbacher !strcmp(sym->string, "override")) {
4745dae9a55SAndreas Gruenbacher is_override = 1;
4755dae9a55SAndreas Gruenbacher free_node(sym);
4765dae9a55SAndreas Gruenbacher sym = read_node(f);
4775dae9a55SAndreas Gruenbacher }
47864e6c1e1SAndreas Gruenbacher if (!sym)
47964e6c1e1SAndreas Gruenbacher continue;
48064e6c1e1SAndreas Gruenbacher def = read_node(f);
48164e6c1e1SAndreas Gruenbacher if (def && def->tag == SYM_NORMAL &&
48264e6c1e1SAndreas Gruenbacher !strcmp(def->string, "extern")) {
48364e6c1e1SAndreas Gruenbacher is_extern = 1;
48464e6c1e1SAndreas Gruenbacher free_node(def);
48564e6c1e1SAndreas Gruenbacher def = read_node(f);
48664e6c1e1SAndreas Gruenbacher }
48764e6c1e1SAndreas Gruenbacher while (def) {
48864e6c1e1SAndreas Gruenbacher def->next = defn;
48964e6c1e1SAndreas Gruenbacher defn = def;
49064e6c1e1SAndreas Gruenbacher def = read_node(f);
49164e6c1e1SAndreas Gruenbacher }
492*4517f37bSMasahiro Yamada subsym = add_reference_symbol(sym->string, sym->tag,
49364e6c1e1SAndreas Gruenbacher defn, is_extern);
4945dae9a55SAndreas Gruenbacher subsym->is_override = is_override;
49564e6c1e1SAndreas Gruenbacher free_node(sym);
49664e6c1e1SAndreas Gruenbacher }
49764e6c1e1SAndreas Gruenbacher }
49864e6c1e1SAndreas Gruenbacher
print_node(FILE * f,struct string_list * list)499ce560686SSam Ravnborg static void print_node(FILE * f, struct string_list *list)
5001da177e4SLinus Torvalds {
5017ec8eda1SMichal Marek if (symbol_types[list->tag].n) {
5027ec8eda1SMichal Marek putc(symbol_types[list->tag].n, f);
5031da177e4SLinus Torvalds putc('#', f);
5041da177e4SLinus Torvalds }
50515fde675SAndreas Gruenbacher fputs(list->string, f);
5061da177e4SLinus Torvalds }
5071da177e4SLinus Torvalds
print_list(FILE * f,struct string_list * list)508ce560686SSam Ravnborg static void print_list(FILE * f, struct string_list *list)
5091da177e4SLinus Torvalds {
5101da177e4SLinus Torvalds struct string_list **e, **b;
5111da177e4SLinus Torvalds struct string_list *tmp, **tmp2;
5121da177e4SLinus Torvalds int elem = 1;
5131da177e4SLinus Torvalds
51478c04153SSam Ravnborg if (list == NULL) {
5151da177e4SLinus Torvalds fputs("(nil)", f);
5161da177e4SLinus Torvalds return;
5171da177e4SLinus Torvalds }
5181da177e4SLinus Torvalds
5191da177e4SLinus Torvalds tmp = list;
5201da177e4SLinus Torvalds while ((tmp = tmp->next) != NULL)
5211da177e4SLinus Torvalds elem++;
5221da177e4SLinus Torvalds
5231da177e4SLinus Torvalds b = alloca(elem * sizeof(*e));
5241da177e4SLinus Torvalds e = b + elem;
5251da177e4SLinus Torvalds tmp2 = e - 1;
5261da177e4SLinus Torvalds
5271da177e4SLinus Torvalds (*tmp2--) = list;
5281da177e4SLinus Torvalds while ((list = list->next) != NULL)
5291da177e4SLinus Torvalds *(tmp2--) = list;
5301da177e4SLinus Torvalds
53178c04153SSam Ravnborg while (b != e) {
5321da177e4SLinus Torvalds print_node(f, *b++);
5331da177e4SLinus Torvalds putc(' ', f);
5341da177e4SLinus Torvalds }
5351da177e4SLinus Torvalds }
5361da177e4SLinus Torvalds
expand_and_crc_sym(struct symbol * sym,unsigned long crc)53715fde675SAndreas Gruenbacher static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
5381da177e4SLinus Torvalds {
53915fde675SAndreas Gruenbacher struct string_list *list = sym->defn;
5401da177e4SLinus Torvalds struct string_list **e, **b;
5411da177e4SLinus Torvalds struct string_list *tmp, **tmp2;
5421da177e4SLinus Torvalds int elem = 1;
5431da177e4SLinus Torvalds
5441da177e4SLinus Torvalds if (!list)
5451da177e4SLinus Torvalds return crc;
5461da177e4SLinus Torvalds
5471da177e4SLinus Torvalds tmp = list;
5481da177e4SLinus Torvalds while ((tmp = tmp->next) != NULL)
5491da177e4SLinus Torvalds elem++;
5501da177e4SLinus Torvalds
5511da177e4SLinus Torvalds b = alloca(elem * sizeof(*e));
5521da177e4SLinus Torvalds e = b + elem;
5531da177e4SLinus Torvalds tmp2 = e - 1;
5541da177e4SLinus Torvalds
5551da177e4SLinus Torvalds *(tmp2--) = list;
5561da177e4SLinus Torvalds while ((list = list->next) != NULL)
5571da177e4SLinus Torvalds *(tmp2--) = list;
5581da177e4SLinus Torvalds
55978c04153SSam Ravnborg while (b != e) {
5601da177e4SLinus Torvalds struct string_list *cur;
5611da177e4SLinus Torvalds struct symbol *subsym;
5621da177e4SLinus Torvalds
5631da177e4SLinus Torvalds cur = *(b++);
56478c04153SSam Ravnborg switch (cur->tag) {
5651da177e4SLinus Torvalds case SYM_NORMAL:
5661da177e4SLinus Torvalds if (flag_dump_defs)
5671da177e4SLinus Torvalds fprintf(debugfile, "%s ", cur->string);
5681da177e4SLinus Torvalds crc = partial_crc32(cur->string, crc);
5691da177e4SLinus Torvalds crc = partial_crc32_one(' ', crc);
5701da177e4SLinus Torvalds break;
5711da177e4SLinus Torvalds
572e37ddb82SMichal Marek case SYM_ENUM_CONST:
5731da177e4SLinus Torvalds case SYM_TYPEDEF:
57401762c4eSMichal Marek subsym = find_symbol(cur->string, cur->tag, 0);
57564e6c1e1SAndreas Gruenbacher /* FIXME: Bad reference files can segfault here. */
57678c04153SSam Ravnborg if (subsym->expansion_trail) {
5771da177e4SLinus Torvalds if (flag_dump_defs)
5781da177e4SLinus Torvalds fprintf(debugfile, "%s ", cur->string);
5791da177e4SLinus Torvalds crc = partial_crc32(cur->string, crc);
5801da177e4SLinus Torvalds crc = partial_crc32_one(' ', crc);
58178c04153SSam Ravnborg } else {
5821da177e4SLinus Torvalds subsym->expansion_trail = expansion_trail;
5831da177e4SLinus Torvalds expansion_trail = subsym;
58415fde675SAndreas Gruenbacher crc = expand_and_crc_sym(subsym, crc);
5851da177e4SLinus Torvalds }
5861da177e4SLinus Torvalds break;
5871da177e4SLinus Torvalds
5881da177e4SLinus Torvalds case SYM_STRUCT:
5891da177e4SLinus Torvalds case SYM_UNION:
5901da177e4SLinus Torvalds case SYM_ENUM:
59101762c4eSMichal Marek subsym = find_symbol(cur->string, cur->tag, 0);
59278c04153SSam Ravnborg if (!subsym) {
59368eb8563SMichal Marek struct string_list *n;
5941da177e4SLinus Torvalds
5951da177e4SLinus Torvalds error_with_pos("expand undefined %s %s",
5967ec8eda1SMichal Marek symbol_types[cur->tag].name,
59778c04153SSam Ravnborg cur->string);
59868eb8563SMichal Marek n = concat_list(mk_node
59968eb8563SMichal Marek (symbol_types[cur->tag].name),
60068eb8563SMichal Marek mk_node(cur->string),
60168eb8563SMichal Marek mk_node("{"),
60268eb8563SMichal Marek mk_node("UNKNOWN"),
60368eb8563SMichal Marek mk_node("}"), NULL);
60478c04153SSam Ravnborg subsym =
60578c04153SSam Ravnborg add_symbol(cur->string, cur->tag, n, 0);
6061da177e4SLinus Torvalds }
60778c04153SSam Ravnborg if (subsym->expansion_trail) {
60878c04153SSam Ravnborg if (flag_dump_defs) {
60978c04153SSam Ravnborg fprintf(debugfile, "%s %s ",
6107ec8eda1SMichal Marek symbol_types[cur->tag].name,
6111da177e4SLinus Torvalds cur->string);
6121da177e4SLinus Torvalds }
6131da177e4SLinus Torvalds
6147ec8eda1SMichal Marek crc = partial_crc32(symbol_types[cur->tag].name,
61578c04153SSam Ravnborg crc);
6161da177e4SLinus Torvalds crc = partial_crc32_one(' ', crc);
6171da177e4SLinus Torvalds crc = partial_crc32(cur->string, crc);
6181da177e4SLinus Torvalds crc = partial_crc32_one(' ', crc);
61978c04153SSam Ravnborg } else {
6201da177e4SLinus Torvalds subsym->expansion_trail = expansion_trail;
6211da177e4SLinus Torvalds expansion_trail = subsym;
62215fde675SAndreas Gruenbacher crc = expand_and_crc_sym(subsym, crc);
6231da177e4SLinus Torvalds }
6241da177e4SLinus Torvalds break;
6251da177e4SLinus Torvalds }
6261da177e4SLinus Torvalds }
6271da177e4SLinus Torvalds
62815fde675SAndreas Gruenbacher {
62915fde675SAndreas Gruenbacher static struct symbol **end = &visited_symbols;
63015fde675SAndreas Gruenbacher
63115fde675SAndreas Gruenbacher if (!sym->visited) {
63215fde675SAndreas Gruenbacher *end = sym;
63315fde675SAndreas Gruenbacher end = &sym->visited;
63415fde675SAndreas Gruenbacher sym->visited = (struct symbol *)-1L;
63515fde675SAndreas Gruenbacher }
63615fde675SAndreas Gruenbacher }
63715fde675SAndreas Gruenbacher
6381da177e4SLinus Torvalds return crc;
6391da177e4SLinus Torvalds }
6401da177e4SLinus Torvalds
export_symbol(const char * name)64178c04153SSam Ravnborg void export_symbol(const char *name)
6421da177e4SLinus Torvalds {
6431da177e4SLinus Torvalds struct symbol *sym;
6441da177e4SLinus Torvalds
64501762c4eSMichal Marek sym = find_symbol(name, SYM_NORMAL, 0);
6461da177e4SLinus Torvalds if (!sym)
6471da177e4SLinus Torvalds error_with_pos("export undefined symbol %s", name);
64878c04153SSam Ravnborg else {
6491da177e4SLinus Torvalds unsigned long crc;
65064e6c1e1SAndreas Gruenbacher int has_changed = 0;
6511da177e4SLinus Torvalds
6521da177e4SLinus Torvalds if (flag_dump_defs)
6531da177e4SLinus Torvalds fprintf(debugfile, "Export %s == <", name);
6541da177e4SLinus Torvalds
6551da177e4SLinus Torvalds expansion_trail = (struct symbol *)-1L;
6561da177e4SLinus Torvalds
65764e6c1e1SAndreas Gruenbacher sym->expansion_trail = expansion_trail;
65864e6c1e1SAndreas Gruenbacher expansion_trail = sym;
65915fde675SAndreas Gruenbacher crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
6601da177e4SLinus Torvalds
6611da177e4SLinus Torvalds sym = expansion_trail;
66278c04153SSam Ravnborg while (sym != (struct symbol *)-1L) {
6631da177e4SLinus Torvalds struct symbol *n = sym->expansion_trail;
66464e6c1e1SAndreas Gruenbacher
66564e6c1e1SAndreas Gruenbacher if (sym->status != STATUS_UNCHANGED) {
66664e6c1e1SAndreas Gruenbacher if (!has_changed) {
66764e6c1e1SAndreas Gruenbacher print_location();
66864e6c1e1SAndreas Gruenbacher fprintf(stderr, "%s: %s: modversion "
66964e6c1e1SAndreas Gruenbacher "changed because of changes "
67064e6c1e1SAndreas Gruenbacher "in ", flag_preserve ? "error" :
67164e6c1e1SAndreas Gruenbacher "warning", name);
67264e6c1e1SAndreas Gruenbacher } else
67364e6c1e1SAndreas Gruenbacher fprintf(stderr, ", ");
67464e6c1e1SAndreas Gruenbacher print_type_name(sym->type, sym->name);
67564e6c1e1SAndreas Gruenbacher if (sym->status == STATUS_DEFINED)
67664e6c1e1SAndreas Gruenbacher fprintf(stderr, " (became defined)");
67764e6c1e1SAndreas Gruenbacher has_changed = 1;
67864e6c1e1SAndreas Gruenbacher if (flag_preserve)
67964e6c1e1SAndreas Gruenbacher errors++;
68064e6c1e1SAndreas Gruenbacher }
6811da177e4SLinus Torvalds sym->expansion_trail = 0;
6821da177e4SLinus Torvalds sym = n;
6831da177e4SLinus Torvalds }
68464e6c1e1SAndreas Gruenbacher if (has_changed)
68564e6c1e1SAndreas Gruenbacher fprintf(stderr, "\n");
6861da177e4SLinus Torvalds
6871da177e4SLinus Torvalds if (flag_dump_defs)
6881da177e4SLinus Torvalds fputs(">\n", debugfile);
6891da177e4SLinus Torvalds
6905ce2176bSMasahiro Yamada printf("#SYMVER %s 0x%08lx\n", name, crc);
6911da177e4SLinus Torvalds }
6921da177e4SLinus Torvalds }
6931da177e4SLinus Torvalds
6941da177e4SLinus Torvalds /*----------------------------------------------------------------------*/
69564e6c1e1SAndreas Gruenbacher
print_location(void)69664e6c1e1SAndreas Gruenbacher static void print_location(void)
69764e6c1e1SAndreas Gruenbacher {
69864e6c1e1SAndreas Gruenbacher fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
69964e6c1e1SAndreas Gruenbacher }
70064e6c1e1SAndreas Gruenbacher
print_type_name(enum symbol_type type,const char * name)70164e6c1e1SAndreas Gruenbacher static void print_type_name(enum symbol_type type, const char *name)
70264e6c1e1SAndreas Gruenbacher {
7037ec8eda1SMichal Marek if (symbol_types[type].name)
7047ec8eda1SMichal Marek fprintf(stderr, "%s %s", symbol_types[type].name, name);
70564e6c1e1SAndreas Gruenbacher else
70664e6c1e1SAndreas Gruenbacher fprintf(stderr, "%s", name);
70764e6c1e1SAndreas Gruenbacher }
70864e6c1e1SAndreas Gruenbacher
error_with_pos(const char * fmt,...)70978c04153SSam Ravnborg void error_with_pos(const char *fmt, ...)
7101da177e4SLinus Torvalds {
7111da177e4SLinus Torvalds va_list args;
7121da177e4SLinus Torvalds
71378c04153SSam Ravnborg if (flag_warnings) {
71464e6c1e1SAndreas Gruenbacher print_location();
7151da177e4SLinus Torvalds
7161da177e4SLinus Torvalds va_start(args, fmt);
7171da177e4SLinus Torvalds vfprintf(stderr, fmt, args);
7181da177e4SLinus Torvalds va_end(args);
7191da177e4SLinus Torvalds putc('\n', stderr);
7201da177e4SLinus Torvalds
7211da177e4SLinus Torvalds errors++;
7221da177e4SLinus Torvalds }
7231da177e4SLinus Torvalds }
7241da177e4SLinus Torvalds
genksyms_usage(void)725ce560686SSam Ravnborg static void genksyms_usage(void)
7261da177e4SLinus Torvalds {
72756067812SArd Biesheuvel fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
7281da177e4SLinus Torvalds #ifdef __GNU_LIBRARY__
729d70f82acSJames Hogan " -s, --symbol-prefix Select symbol prefix\n"
7301da177e4SLinus Torvalds " -d, --debug Increment the debug level (repeatable)\n"
7311da177e4SLinus Torvalds " -D, --dump Dump expanded symbol defs (for debugging only)\n"
73264e6c1e1SAndreas Gruenbacher " -r, --reference file Read reference symbols from a file\n"
73364e6c1e1SAndreas Gruenbacher " -T, --dump-types file Dump expanded types into file\n"
73464e6c1e1SAndreas Gruenbacher " -p, --preserve Preserve reference modversions or fail\n"
7351da177e4SLinus Torvalds " -w, --warnings Enable warnings\n"
7361da177e4SLinus Torvalds " -q, --quiet Disable warnings (default)\n"
7371da177e4SLinus Torvalds " -h, --help Print this message\n"
7381da177e4SLinus Torvalds " -V, --version Print the release version\n"
7391da177e4SLinus Torvalds #else /* __GNU_LIBRARY__ */
740d70f82acSJames Hogan " -s Select symbol prefix\n"
7411da177e4SLinus Torvalds " -d Increment the debug level (repeatable)\n"
7421da177e4SLinus Torvalds " -D Dump expanded symbol defs (for debugging only)\n"
74364e6c1e1SAndreas Gruenbacher " -r file Read reference symbols from a file\n"
74464e6c1e1SAndreas Gruenbacher " -T file Dump expanded types into file\n"
74564e6c1e1SAndreas Gruenbacher " -p Preserve reference modversions or fail\n"
7461da177e4SLinus Torvalds " -w Enable warnings\n"
7471da177e4SLinus Torvalds " -q Disable warnings (default)\n"
7481da177e4SLinus Torvalds " -h Print this message\n"
7491da177e4SLinus Torvalds " -V Print the release version\n"
7501da177e4SLinus Torvalds #endif /* __GNU_LIBRARY__ */
7511da177e4SLinus Torvalds , stderr);
7521da177e4SLinus Torvalds }
7531da177e4SLinus Torvalds
main(int argc,char ** argv)75478c04153SSam Ravnborg int main(int argc, char **argv)
7551da177e4SLinus Torvalds {
75664e6c1e1SAndreas Gruenbacher FILE *dumpfile = NULL, *ref_file = NULL;
7571da177e4SLinus Torvalds int o;
7581da177e4SLinus Torvalds
7591da177e4SLinus Torvalds #ifdef __GNU_LIBRARY__
7601da177e4SLinus Torvalds struct option long_opts[] = {
7611da177e4SLinus Torvalds {"debug", 0, 0, 'd'},
7621da177e4SLinus Torvalds {"warnings", 0, 0, 'w'},
7631da177e4SLinus Torvalds {"quiet", 0, 0, 'q'},
7641da177e4SLinus Torvalds {"dump", 0, 0, 'D'},
76564e6c1e1SAndreas Gruenbacher {"reference", 1, 0, 'r'},
76615fde675SAndreas Gruenbacher {"dump-types", 1, 0, 'T'},
76764e6c1e1SAndreas Gruenbacher {"preserve", 0, 0, 'p'},
7681da177e4SLinus Torvalds {"version", 0, 0, 'V'},
7691da177e4SLinus Torvalds {"help", 0, 0, 'h'},
7701da177e4SLinus Torvalds {0, 0, 0, 0}
7711da177e4SLinus Torvalds };
7721da177e4SLinus Torvalds
7737b453719SMasahiro Yamada while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph",
7741da177e4SLinus Torvalds &long_opts[0], NULL)) != EOF)
7751da177e4SLinus Torvalds #else /* __GNU_LIBRARY__ */
7767b453719SMasahiro Yamada while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF)
7771da177e4SLinus Torvalds #endif /* __GNU_LIBRARY__ */
77878c04153SSam Ravnborg switch (o) {
7791da177e4SLinus Torvalds case 'd':
7801da177e4SLinus Torvalds flag_debug++;
7811da177e4SLinus Torvalds break;
7821da177e4SLinus Torvalds case 'w':
7831da177e4SLinus Torvalds flag_warnings = 1;
7841da177e4SLinus Torvalds break;
7851da177e4SLinus Torvalds case 'q':
7861da177e4SLinus Torvalds flag_warnings = 0;
7871da177e4SLinus Torvalds break;
7881da177e4SLinus Torvalds case 'V':
7891da177e4SLinus Torvalds fputs("genksyms version 2.5.60\n", stderr);
7901da177e4SLinus Torvalds break;
7911da177e4SLinus Torvalds case 'D':
7921da177e4SLinus Torvalds flag_dump_defs = 1;
7931da177e4SLinus Torvalds break;
79464e6c1e1SAndreas Gruenbacher case 'r':
79564e6c1e1SAndreas Gruenbacher flag_reference = 1;
79664e6c1e1SAndreas Gruenbacher ref_file = fopen(optarg, "r");
79764e6c1e1SAndreas Gruenbacher if (!ref_file) {
79864e6c1e1SAndreas Gruenbacher perror(optarg);
79964e6c1e1SAndreas Gruenbacher return 1;
80064e6c1e1SAndreas Gruenbacher }
80164e6c1e1SAndreas Gruenbacher break;
80215fde675SAndreas Gruenbacher case 'T':
80315fde675SAndreas Gruenbacher flag_dump_types = 1;
80415fde675SAndreas Gruenbacher dumpfile = fopen(optarg, "w");
80515fde675SAndreas Gruenbacher if (!dumpfile) {
80615fde675SAndreas Gruenbacher perror(optarg);
80715fde675SAndreas Gruenbacher return 1;
80815fde675SAndreas Gruenbacher }
80915fde675SAndreas Gruenbacher break;
81064e6c1e1SAndreas Gruenbacher case 'p':
81164e6c1e1SAndreas Gruenbacher flag_preserve = 1;
81264e6c1e1SAndreas Gruenbacher break;
8131da177e4SLinus Torvalds case 'h':
8141da177e4SLinus Torvalds genksyms_usage();
8151da177e4SLinus Torvalds return 0;
8161da177e4SLinus Torvalds default:
8171da177e4SLinus Torvalds genksyms_usage();
8181da177e4SLinus Torvalds return 1;
8191da177e4SLinus Torvalds }
8201da177e4SLinus Torvalds {
8211da177e4SLinus Torvalds extern int yydebug;
8221da177e4SLinus Torvalds extern int yy_flex_debug;
8231da177e4SLinus Torvalds
8241da177e4SLinus Torvalds yydebug = (flag_debug > 1);
8251da177e4SLinus Torvalds yy_flex_debug = (flag_debug > 2);
8261da177e4SLinus Torvalds
8271da177e4SLinus Torvalds debugfile = stderr;
8281da177e4SLinus Torvalds /* setlinebuf(debugfile); */
8291da177e4SLinus Torvalds }
8301da177e4SLinus Torvalds
831c64152bfSAlexander Beregalov if (flag_reference) {
83264e6c1e1SAndreas Gruenbacher read_reference(ref_file);
833c64152bfSAlexander Beregalov fclose(ref_file);
834c64152bfSAlexander Beregalov }
83564e6c1e1SAndreas Gruenbacher
8361da177e4SLinus Torvalds yyparse();
8371da177e4SLinus Torvalds
83815fde675SAndreas Gruenbacher if (flag_dump_types && visited_symbols) {
83915fde675SAndreas Gruenbacher while (visited_symbols != (struct symbol *)-1L) {
84015fde675SAndreas Gruenbacher struct symbol *sym = visited_symbols;
84115fde675SAndreas Gruenbacher
8425dae9a55SAndreas Gruenbacher if (sym->is_override)
8435dae9a55SAndreas Gruenbacher fputs("override ", dumpfile);
8447ec8eda1SMichal Marek if (symbol_types[sym->type].n) {
8457ec8eda1SMichal Marek putc(symbol_types[sym->type].n, dumpfile);
84615fde675SAndreas Gruenbacher putc('#', dumpfile);
84715fde675SAndreas Gruenbacher }
84815fde675SAndreas Gruenbacher fputs(sym->name, dumpfile);
84915fde675SAndreas Gruenbacher putc(' ', dumpfile);
8503b40d381SAndreas Gruenbacher if (sym->is_extern)
8513b40d381SAndreas Gruenbacher fputs("extern ", dumpfile);
85215fde675SAndreas Gruenbacher print_list(dumpfile, sym->defn);
85315fde675SAndreas Gruenbacher putc('\n', dumpfile);
85415fde675SAndreas Gruenbacher
85515fde675SAndreas Gruenbacher visited_symbols = sym->visited;
85615fde675SAndreas Gruenbacher sym->visited = NULL;
85715fde675SAndreas Gruenbacher }
85815fde675SAndreas Gruenbacher }
85915fde675SAndreas Gruenbacher
86078c04153SSam Ravnborg if (flag_debug) {
8611da177e4SLinus Torvalds fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
86278c04153SSam Ravnborg nsyms, HASH_BUCKETS,
86378c04153SSam Ravnborg (double)nsyms / (double)HASH_BUCKETS);
8641da177e4SLinus Torvalds }
8651da177e4SLinus Torvalds
8664deaaa4dSMaxim Zhukov if (dumpfile)
8674deaaa4dSMaxim Zhukov fclose(dumpfile);
8684deaaa4dSMaxim Zhukov
8691da177e4SLinus Torvalds return errors != 0;
8701da177e4SLinus Torvalds }
871