xref: /openbmc/linux/scripts/genksyms/genksyms.c (revision d0b73b48)
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 
39 static struct symbol *symtab[HASH_BUCKETS];
40 static FILE *debugfile;
41 
42 int cur_line = 1;
43 char *cur_filename, *source_file;
44 int in_source_file;
45 
46 static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types,
47 	   flag_preserve, flag_warnings;
48 static const char *arch = "";
49 static const char *mod_prefix = "";
50 
51 static int errors;
52 static int nsyms;
53 
54 static struct symbol *expansion_trail;
55 static struct symbol *visited_symbols;
56 
57 static 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 
69 static int equal_list(struct string_list *a, struct string_list *b);
70 static void print_list(FILE * f, struct string_list *list);
71 static struct string_list *concat_list(struct string_list *start, ...);
72 static struct string_list *mk_node(const char *string);
73 static void print_location(void);
74 static void print_type_name(enum symbol_type type, const char *name);
75 
76 /*----------------------------------------------------------------------*/
77 
78 static 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 
133 static unsigned long partial_crc32_one(unsigned char c, unsigned long crc)
134 {
135 	return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
136 }
137 
138 static 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 
145 static unsigned long crc32(const char *s)
146 {
147 	return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
148 }
149 
150 /*----------------------------------------------------------------------*/
151 
152 static 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 
167 struct 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 
183 static 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 
198 static 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 
322 struct 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 
328 static 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 
336 void free_node(struct string_list *node)
337 {
338 	free(node->string);
339 	free(node);
340 }
341 
342 void 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 
351 static 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 
363 static 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 
380 struct 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 
391 struct 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 
407 static 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 
421 static 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 
467 static 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 
503 static 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 
512 static 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 
541 static 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 
645 void 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 
701 static void print_location(void)
702 {
703 	fprintf(stderr, "%s:%d: ", cur_filename ? : "<stdin>", cur_line);
704 }
705 
706 static 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 
714 void 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 
730 static 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 
759 int 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