blob: 23eff234184f381323ff0eb7dc93d0c4d4913e56 [file] [log] [blame]
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/* 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
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +020011 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
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>
Sam Ravnborg78c041532006-03-12 22:59:36 +010021#endif /* __GNU_LIBRARY__ */
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
23#include "genksyms.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024/*----------------------------------------------------------------------*/
25
26#define HASH_BUCKETS 4096
27
28static struct symbol *symtab[HASH_BUCKETS];
Sam Ravnborgce560682006-03-12 23:26:29 +010029static FILE *debugfile;
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
31int cur_line = 1;
Michal Marek2c5925d2011-10-08 01:18:35 +020032char *cur_filename, *source_file;
33int in_source_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -080035static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
Ard Biesheuvel56067812017-02-03 09:54:05 +000036 flag_preserve, flag_warnings, flag_rel_crcs;
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
38static int errors;
39static int nsyms;
40
41static struct symbol *expansion_trail;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +020042static struct symbol *visited_symbols;
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Michal Marek7ec8eda2011-01-18 16:28:06 +010044static 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"},
Michal Mareke37ddb82011-02-03 23:57:09 +010053 [SYM_ENUM_CONST] = {'E', "enum constant"},
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
Sam Ravnborgce560682006-03-12 23:26:29 +010056static int equal_list(struct string_list *a, struct string_list *b);
57static void print_list(FILE * f, struct string_list *list);
Michal Marek68eb8562011-02-02 23:52:13 +010058static struct string_list *concat_list(struct string_list *start, ...);
59static struct string_list *mk_node(const char *string);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -080060static void print_location(void);
61static void print_type_name(enum symbol_type type, const char *name);
Sam Ravnborgce560682006-03-12 23:26:29 +010062
Linus Torvalds1da177e2005-04-16 15:20:36 -070063/*----------------------------------------------------------------------*/
64
Sam Ravnborg78c041532006-03-12 22:59:36 +010065static 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118};
119
Sam Ravnborgce560682006-03-12 23:26:29 +0100120static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100122 return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123}
124
Sam Ravnborgce560682006-03-12 23:26:29 +0100125static unsigned long partial_crc32(const char *s, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100127 while (*s)
128 crc = partial_crc32_one(*s++, crc);
129 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130}
131
Sam Ravnborgce560682006-03-12 23:26:29 +0100132static unsigned long crc32(const char *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100134 return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135}
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137/*----------------------------------------------------------------------*/
138
Sam Ravnborgce560682006-03-12 23:26:29 +0100139static enum symbol_type map_to_ns(enum symbol_type t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140{
Michal Mareke37ddb82011-02-03 23:57:09 +0100141 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 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100151 return t;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152}
153
Michal Marek01762c42011-02-15 15:11:36 +0100154struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100156 unsigned long h = crc32(name) % HASH_BUCKETS;
157 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Sam Ravnborg78c041532006-03-12 22:59:36 +0100159 for (sym = symtab[h]; sym; sym = sym->hash_next)
Sam Ravnborgce560682006-03-12 23:26:29 +0100160 if (map_to_ns(sym->type) == map_to_ns(ns) &&
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800161 strcmp(name, sym->name) == 0 &&
162 sym->is_declared)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100163 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Michal Marek01762c42011-02-15 15:11:36 +0100165 if (exact && sym && sym->type != ns)
166 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 return sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168}
169
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800170static 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
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700185static struct symbol *__add_symbol(const char *name, enum symbol_type type,
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800186 struct string_list *defn, int is_extern,
187 int is_reference)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100188{
Michal Mareke37ddb82011-02-03 23:57:09 +0100189 unsigned long h;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100190 struct symbol *sym;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800191 enum symbol_status status = STATUS_UNCHANGED;
Michal Mareke37ddb82011-02-03 23:57:09 +0100192 /* 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;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100198
Michal Mareke37ddb82011-02-03 23:57:09 +0100199 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;
Sam Ravnborgce560682006-03-12 23:26:29 +0100230 for (sym = symtab[h]; sym; sym = sym->hash_next) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800231 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)) {
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800237 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 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800243 sym->is_declared = 1;
244 return sym;
245 } else if (!sym->is_declared) {
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800246 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 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800257 } else {
Sam Ravnborg78c041532006-03-12 22:59:36 +0100258 error_with_pos("redefinition of %s", name);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800259 return sym;
260 }
261 break;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100262 }
Sam Ravnborgce560682006-03-12 23:26:29 +0100263 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100264
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800265 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
Sam Ravnborg78c041532006-03-12 22:59:36 +0100277 sym = xmalloc(sizeof(*sym));
278 sym->name = name;
279 sym->type = type;
280 sym->defn = defn;
281 sym->expansion_trail = NULL;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200282 sym->visited = NULL;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100283 sym->is_extern = is_extern;
284
285 sym->hash_next = symtab[h];
286 symtab[h] = sym;
287
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800288 sym->is_declared = !is_reference;
289 sym->status = status;
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800290 sym->is_override = 0;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800291
Sam Ravnborg78c041532006-03-12 22:59:36 +0100292 if (flag_debug) {
Michal Marek7ec8eda2011-01-18 16:28:06 +0100293 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);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100299 if (is_extern)
300 fputs("extern ", debugfile);
301 print_list(debugfile, defn);
302 fputs(">\n", debugfile);
303 }
304
305 ++nsyms;
306 return sym;
307}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800309struct 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
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700315static struct symbol *add_reference_symbol(const char *name, enum symbol_type type,
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800316 struct string_list *defn, int is_extern)
317{
318 return __add_symbol(name, type, defn, is_extern, 1);
319}
320
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321/*----------------------------------------------------------------------*/
322
Sam Ravnborgce560682006-03-12 23:26:29 +0100323void free_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100325 free(node->string);
326 free(node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327}
328
Sam Ravnborg78c041532006-03-12 22:59:36 +0100329void free_list(struct string_list *s, struct string_list *e)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100331 while (s != e) {
332 struct string_list *next = s->next;
333 free_node(s);
334 s = next;
335 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336}
337
Michal Marek68eb8562011-02-02 23:52:13 +0100338static 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
350static 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
Sam Ravnborgce560682006-03-12 23:26:29 +0100367struct string_list *copy_node(struct string_list *node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100369 struct string_list *newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Sam Ravnborg78c041532006-03-12 22:59:36 +0100371 newnode = xmalloc(sizeof(*newnode));
372 newnode->string = xstrdup(node->string);
373 newnode->tag = node->tag;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Sam Ravnborg78c041532006-03-12 22:59:36 +0100375 return newnode;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376}
377
Michal Mareke37ddb82011-02-03 23:57:09 +0100378struct 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
Sam Ravnborgce560682006-03-12 23:26:29 +0100394static int equal_list(struct string_list *a, struct string_list *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100396 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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Sam Ravnborg78c041532006-03-12 22:59:36 +0100403 return !a && !b;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404}
405
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800406#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
407
Ladinu Chandrasingheb7ed6982009-09-22 16:43:42 -0700408static struct string_list *read_node(FILE *f)
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800409{
410 char buffer[256];
411 struct string_list node = {
412 .string = buffer,
413 .tag = SYM_NORMAL };
Michal Mareka78f70e2015-12-09 15:08:21 +0100414 int c, in_string = 0;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800415
416 while ((c = fgetc(f)) != EOF) {
Michal Mareka78f70e2015-12-09 15:08:21 +0100417 if (!in_string && c == ' ') {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800418 if (node.string == buffer)
419 continue;
420 break;
Michal Mareka78f70e2015-12-09 15:08:21 +0100421 } else if (c == '"') {
422 in_string = !in_string;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800423 } 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] == '#') {
Jesper Juhl1ae14702011-07-12 00:32:04 +0200441 size_t n;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800442
Michal Marek7ec8eda2011-01-18 16:28:06 +0100443 for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
444 if (node.string[0] == symbol_types[n].n) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800445 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
456static void read_reference(FILE *f)
457{
458 while (!feof(f)) {
459 struct string_list *defn = NULL;
460 struct string_list *sym, *def;
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800461 int is_extern = 0, is_override = 0;
462 struct symbol *subsym;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800463
464 sym = read_node(f);
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800465 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 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800471 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 }
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800485 subsym = add_reference_symbol(xstrdup(sym->string), sym->tag,
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800486 defn, is_extern);
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800487 subsym->is_override = is_override;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800488 free_node(sym);
489 }
490}
491
Sam Ravnborgce560682006-03-12 23:26:29 +0100492static void print_node(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493{
Michal Marek7ec8eda2011-01-18 16:28:06 +0100494 if (symbol_types[list->tag].n) {
495 putc(symbol_types[list->tag].n, f);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100496 putc('#', f);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100497 }
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200498 fputs(list->string, f);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499}
500
Sam Ravnborgce560682006-03-12 23:26:29 +0100501static void print_list(FILE * f, struct string_list *list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100503 struct string_list **e, **b;
504 struct string_list *tmp, **tmp2;
505 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Sam Ravnborg78c041532006-03-12 22:59:36 +0100507 if (list == NULL) {
508 fputs("(nil)", f);
509 return;
510 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Sam Ravnborg78c041532006-03-12 22:59:36 +0100512 tmp = list;
513 while ((tmp = tmp->next) != NULL)
514 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Sam Ravnborg78c041532006-03-12 22:59:36 +0100516 b = alloca(elem * sizeof(*e));
517 e = b + elem;
518 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519
Sam Ravnborg78c041532006-03-12 22:59:36 +0100520 (*tmp2--) = list;
521 while ((list = list->next) != NULL)
522 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Sam Ravnborg78c041532006-03-12 22:59:36 +0100524 while (b != e) {
525 print_node(f, *b++);
526 putc(' ', f);
527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528}
529
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200530static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200532 struct string_list *list = sym->defn;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100533 struct string_list **e, **b;
534 struct string_list *tmp, **tmp2;
535 int elem = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Sam Ravnborg78c041532006-03-12 22:59:36 +0100537 if (!list)
538 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
Sam Ravnborg78c041532006-03-12 22:59:36 +0100540 tmp = list;
541 while ((tmp = tmp->next) != NULL)
542 elem++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Sam Ravnborg78c041532006-03-12 22:59:36 +0100544 b = alloca(elem * sizeof(*e));
545 e = b + elem;
546 tmp2 = e - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Sam Ravnborg78c041532006-03-12 22:59:36 +0100548 *(tmp2--) = list;
549 while ((list = list->next) != NULL)
550 *(tmp2--) = list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Sam Ravnborg78c041532006-03-12 22:59:36 +0100552 while (b != e) {
553 struct string_list *cur;
554 struct symbol *subsym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Sam Ravnborg78c041532006-03-12 22:59:36 +0100556 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Michal Mareke37ddb82011-02-03 23:57:09 +0100565 case SYM_ENUM_CONST:
Sam Ravnborg78c041532006-03-12 22:59:36 +0100566 case SYM_TYPEDEF:
Michal Marek01762c42011-02-15 15:11:36 +0100567 subsym = find_symbol(cur->string, cur->tag, 0);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800568 /* FIXME: Bad reference files can segfault here. */
Sam Ravnborg78c041532006-03-12 22:59:36 +0100569 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;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200577 crc = expand_and_crc_sym(subsym, crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100578 }
579 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Sam Ravnborg78c041532006-03-12 22:59:36 +0100581 case SYM_STRUCT:
582 case SYM_UNION:
583 case SYM_ENUM:
Michal Marek01762c42011-02-15 15:11:36 +0100584 subsym = find_symbol(cur->string, cur->tag, 0);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100585 if (!subsym) {
Michal Marek68eb8562011-02-02 23:52:13 +0100586 struct string_list *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Sam Ravnborg78c041532006-03-12 22:59:36 +0100588 error_with_pos("expand undefined %s %s",
Michal Marek7ec8eda2011-01-18 16:28:06 +0100589 symbol_types[cur->tag].name,
Sam Ravnborg78c041532006-03-12 22:59:36 +0100590 cur->string);
Michal Marek68eb8562011-02-02 23:52:13 +0100591 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);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100597 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 ",
Michal Marek7ec8eda2011-01-18 16:28:06 +0100603 symbol_types[cur->tag].name,
Sam Ravnborg78c041532006-03-12 22:59:36 +0100604 cur->string);
605 }
606
Michal Marek7ec8eda2011-01-18 16:28:06 +0100607 crc = partial_crc32(symbol_types[cur->tag].name,
Sam Ravnborgce560682006-03-12 23:26:29 +0100608 crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100609 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;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200615 crc = expand_and_crc_sym(subsym, crc);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100616 }
617 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200621 {
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
Sam Ravnborg78c041532006-03-12 22:59:36 +0100631 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632}
633
Sam Ravnborg78c041532006-03-12 22:59:36 +0100634void export_symbol(const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100636 struct symbol *sym;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Michal Marek01762c42011-02-15 15:11:36 +0100638 sym = find_symbol(name, SYM_NORMAL, 0);
Sam Ravnborg78c041532006-03-12 22:59:36 +0100639 if (!sym)
640 error_with_pos("export undefined symbol %s", name);
641 else {
642 unsigned long crc;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800643 int has_changed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Sam Ravnborg78c041532006-03-12 22:59:36 +0100645 if (flag_dump_defs)
646 fprintf(debugfile, "Export %s == <", name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Sam Ravnborg78c041532006-03-12 22:59:36 +0100648 expansion_trail = (struct symbol *)-1L;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800650 sym->expansion_trail = expansion_trail;
651 expansion_trail = sym;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200652 crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Sam Ravnborg78c041532006-03-12 22:59:36 +0100654 sym = expansion_trail;
655 while (sym != (struct symbol *)-1L) {
656 struct symbol *n = sym->expansion_trail;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800657
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 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100674 sym->expansion_trail = 0;
675 sym = n;
676 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800677 if (has_changed)
678 fprintf(stderr, "\n");
Sam Ravnborg78c041532006-03-12 22:59:36 +0100679
680 if (flag_dump_defs)
681 fputs(">\n", debugfile);
682
Sam Ravnborg2ea03892009-01-14 21:38:20 +0100683 /* Used as a linker script. */
Masahiro Yamada74d93172018-05-09 16:23:46 +0900684 printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" :
Ard Biesheuvel56067812017-02-03 09:54:05 +0000685 "SECTIONS { .rodata : ALIGN(4) { "
Masahiro Yamada74d93172018-05-09 16:23:46 +0900686 "__crc_%s = .; LONG(0x%08lx); } }\n",
687 name, crc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689}
690
691/*----------------------------------------------------------------------*/
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800692
693static void print_location(void)
694{
695 fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
696}
697
698static void print_type_name(enum symbol_type type, const char *name)
699{
Michal Marek7ec8eda2011-01-18 16:28:06 +0100700 if (symbol_types[type].name)
701 fprintf(stderr, "%s %s", symbol_types[type].name, name);
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800702 else
703 fprintf(stderr, "%s", name);
704}
705
Sam Ravnborg78c041532006-03-12 22:59:36 +0100706void error_with_pos(const char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
Sam Ravnborg78c041532006-03-12 22:59:36 +0100708 va_list args;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Sam Ravnborg78c041532006-03-12 22:59:36 +0100710 if (flag_warnings) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800711 print_location();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
Sam Ravnborg78c041532006-03-12 22:59:36 +0100713 va_start(args, fmt);
714 vfprintf(stderr, fmt, args);
715 va_end(args);
716 putc('\n', stderr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Sam Ravnborg78c041532006-03-12 22:59:36 +0100718 errors++;
719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720}
721
Sam Ravnborgce560682006-03-12 23:26:29 +0100722static void genksyms_usage(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
Ard Biesheuvel56067812017-02-03 09:54:05 +0000724 fputs("Usage:\n" "genksyms [-adDTwqhVR] > /path/to/.tmp_obj.ver\n" "\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725#ifdef __GNU_LIBRARY__
James Hogand70f82a2013-03-18 19:38:56 +1030726 " -s, --symbol-prefix Select symbol prefix\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 " -d, --debug Increment the debug level (repeatable)\n"
728 " -D, --dump Dump expanded symbol defs (for debugging only)\n"
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800729 " -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"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 " -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"
Ard Biesheuvel56067812017-02-03 09:54:05 +0000736 " -R, --relative-crc Emit section relative symbol CRCs\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100737#else /* __GNU_LIBRARY__ */
James Hogand70f82a2013-03-18 19:38:56 +1030738 " -s Select symbol prefix\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100739 " -d Increment the debug level (repeatable)\n"
740 " -D Dump expanded symbol defs (for debugging only)\n"
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800741 " -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"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100744 " -w Enable warnings\n"
745 " -q Disable warnings (default)\n"
746 " -h Print this message\n"
747 " -V Print the release version\n"
Ard Biesheuvel56067812017-02-03 09:54:05 +0000748 " -R Emit section relative symbol CRCs\n"
Sam Ravnborg78c041532006-03-12 22:59:36 +0100749#endif /* __GNU_LIBRARY__ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750 , stderr);
751}
752
Sam Ravnborg78c041532006-03-12 22:59:36 +0100753int main(int argc, char **argv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754{
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800755 FILE *dumpfile = NULL, *ref_file = NULL;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100756 int o;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
758#ifdef __GNU_LIBRARY__
Sam Ravnborg78c041532006-03-12 22:59:36 +0100759 struct option long_opts[] = {
Sam Ravnborg78c041532006-03-12 22:59:36 +0100760 {"debug", 0, 0, 'd'},
761 {"warnings", 0, 0, 'w'},
762 {"quiet", 0, 0, 'q'},
763 {"dump", 0, 0, 'D'},
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800764 {"reference", 1, 0, 'r'},
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200765 {"dump-types", 1, 0, 'T'},
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800766 {"preserve", 0, 0, 'p'},
Sam Ravnborg78c041532006-03-12 22:59:36 +0100767 {"version", 0, 0, 'V'},
768 {"help", 0, 0, 'h'},
Ard Biesheuvel56067812017-02-03 09:54:05 +0000769 {"relative-crc", 0, 0, 'R'},
Sam Ravnborg78c041532006-03-12 22:59:36 +0100770 {0, 0, 0, 0}
771 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Ard Biesheuvel56067812017-02-03 09:54:05 +0000773 while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR",
Sam Ravnborg78c041532006-03-12 22:59:36 +0100774 &long_opts[0], NULL)) != EOF)
775#else /* __GNU_LIBRARY__ */
Ard Biesheuvel56067812017-02-03 09:54:05 +0000776 while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF)
Sam Ravnborg78c041532006-03-12 22:59:36 +0100777#endif /* __GNU_LIBRARY__ */
778 switch (o) {
Sam Ravnborg78c041532006-03-12 22:59:36 +0100779 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;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800794 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;
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200802 case 'T':
803 flag_dump_types = 1;
804 dumpfile = fopen(optarg, "w");
805 if (!dumpfile) {
806 perror(optarg);
807 return 1;
808 }
809 break;
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800810 case 'p':
811 flag_preserve = 1;
812 break;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100813 case 'h':
814 genksyms_usage();
815 return 0;
Ard Biesheuvel56067812017-02-03 09:54:05 +0000816 case 'R':
817 flag_rel_crcs = 1;
818 break;
Sam Ravnborg78c041532006-03-12 22:59:36 +0100819 default:
820 genksyms_usage();
821 return 1;
822 }
Sam Ravnborg78c041532006-03-12 22:59:36 +0100823 {
824 extern int yydebug;
825 extern int yy_flex_debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
Sam Ravnborg78c041532006-03-12 22:59:36 +0100827 yydebug = (flag_debug > 1);
828 yy_flex_debug = (flag_debug > 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
Sam Ravnborg78c041532006-03-12 22:59:36 +0100830 debugfile = stderr;
831 /* setlinebuf(debugfile); */
832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
Alexander Beregalovc64152b2010-01-07 05:22:41 +0300834 if (flag_reference) {
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800835 read_reference(ref_file);
Alexander Beregalovc64152b2010-01-07 05:22:41 +0300836 fclose(ref_file);
837 }
Andreas Gruenbacher64e6c1e2008-12-01 14:21:01 -0800838
Sam Ravnborg78c041532006-03-12 22:59:36 +0100839 yyparse();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200841 if (flag_dump_types && visited_symbols) {
842 while (visited_symbols != (struct symbol *)-1L) {
843 struct symbol *sym = visited_symbols;
844
Andreas Gruenbacher5dae9a52008-12-01 14:21:03 -0800845 if (sym->is_override)
846 fputs("override ", dumpfile);
Michal Marek7ec8eda2011-01-18 16:28:06 +0100847 if (symbol_types[sym->type].n) {
848 putc(symbol_types[sym->type].n, dumpfile);
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200849 putc('#', dumpfile);
850 }
851 fputs(sym->name, dumpfile);
852 putc(' ', dumpfile);
Andreas Gruenbacher3b40d382008-07-21 04:28:25 +0200853 if (sym->is_extern)
854 fputs("extern ", dumpfile);
Andreas Gruenbacher15fde672006-05-09 20:37:30 +0200855 print_list(dumpfile, sym->defn);
856 putc('\n', dumpfile);
857
858 visited_symbols = sym->visited;
859 sym->visited = NULL;
860 }
861 }
862
Sam Ravnborg78c041532006-03-12 22:59:36 +0100863 if (flag_debug) {
864 fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
865 nsyms, HASH_BUCKETS,
866 (double)nsyms / (double)HASH_BUCKETS);
867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868
Maxim Zhukov4deaaa42016-04-12 23:54:59 +0300869 if (dumpfile)
870 fclose(dumpfile);
871
Sam Ravnborg78c041532006-03-12 22:59:36 +0100872 return errors != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873}