Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
genksyms.c
Go to the documentation of this file.
1 /* Generate kernel symbol version hashes.
2  Copyright 1996, 1997 Linux International.
3 
4  New implementation contributed by Richard Henderson <[email protected]>
5  Based on original work by Bjorn Ekwall <[email protected]>
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;
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;
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) ?
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 
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 
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 
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 {
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 
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 }