locking/atomic: Correct (cmp)xchg() instrumentation
[linux-block.git] / scripts / kallsyms.c
1 /* Generate assembler source containing symbol information
2  *
3  * Copyright 2002       by Kai Germaschewski
4  *
5  * This software may be used and distributed according to the terms
6  * of the GNU General Public License, incorporated herein by reference.
7  *
8  * Usage: kallsyms [--all-symbols] [--absolute-percpu]
9  *                         [--base-relative] in.map > out.S
10  *
11  *      Table compression uses all the unused char codes on the symbols and
12  *  maps these to the most used substrings (tokens). For instance, it might
13  *  map char code 0xF7 to represent "write_" and then in every symbol where
14  *  "write_" appears it can be replaced by 0xF7, saving 5 bytes.
15  *      The used codes themselves are also placed in the table so that the
16  *  decompresion can work without "special cases".
17  *      Applied to kernel symbols, this usually produces a compression ratio
18  *  of about 50%.
19  *
20  */
21
22 #include <getopt.h>
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <limits.h>
29
30 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
31
32 #define _stringify_1(x) #x
33 #define _stringify(x)   _stringify_1(x)
34
35 #define KSYM_NAME_LEN           512
36
37 /*
38  * A substantially bigger size than the current maximum.
39  *
40  * It cannot be defined as an expression because it gets stringified
41  * for the fscanf() format string. Therefore, a _Static_assert() is
42  * used instead to maintain the relationship with KSYM_NAME_LEN.
43  */
44 #define KSYM_NAME_LEN_BUFFER    2048
45 _Static_assert(
46         KSYM_NAME_LEN_BUFFER == KSYM_NAME_LEN * 4,
47         "Please keep KSYM_NAME_LEN_BUFFER in sync with KSYM_NAME_LEN"
48 );
49
50 struct sym_entry {
51         unsigned long long addr;
52         unsigned int len;
53         unsigned int seq;
54         unsigned int start_pos;
55         unsigned int percpu_absolute;
56         unsigned char sym[];
57 };
58
59 struct addr_range {
60         const char *start_sym, *end_sym;
61         unsigned long long start, end;
62 };
63
64 static unsigned long long _text;
65 static unsigned long long relative_base;
66 static struct addr_range text_ranges[] = {
67         { "_stext",     "_etext"     },
68         { "_sinittext", "_einittext" },
69 };
70 #define text_range_text     (&text_ranges[0])
71 #define text_range_inittext (&text_ranges[1])
72
73 static struct addr_range percpu_range = {
74         "__per_cpu_start", "__per_cpu_end", -1ULL, 0
75 };
76
77 static struct sym_entry **table;
78 static unsigned int table_size, table_cnt;
79 static int all_symbols;
80 static int absolute_percpu;
81 static int base_relative;
82 static int lto_clang;
83
84 static int token_profit[0x10000];
85
86 /* the table that holds the result of the compression */
87 static unsigned char best_table[256][2];
88 static unsigned char best_table_len[256];
89
90
91 static void usage(void)
92 {
93         fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] "
94                         "[--base-relative] [--lto-clang] in.map > out.S\n");
95         exit(1);
96 }
97
98 static char *sym_name(const struct sym_entry *s)
99 {
100         return (char *)s->sym + 1;
101 }
102
103 static bool is_ignored_symbol(const char *name, char type)
104 {
105         /* Symbol names that exactly match to the following are ignored.*/
106         static const char * const ignored_symbols[] = {
107                 /*
108                  * Symbols which vary between passes. Passes 1 and 2 must have
109                  * identical symbol lists. The kallsyms_* symbols below are
110                  * only added after pass 1, they would be included in pass 2
111                  * when --all-symbols is specified so exclude them to get a
112                  * stable symbol list.
113                  */
114                 "kallsyms_addresses",
115                 "kallsyms_offsets",
116                 "kallsyms_relative_base",
117                 "kallsyms_num_syms",
118                 "kallsyms_names",
119                 "kallsyms_markers",
120                 "kallsyms_token_table",
121                 "kallsyms_token_index",
122                 /* Exclude linker generated symbols which vary between passes */
123                 "_SDA_BASE_",           /* ppc */
124                 "_SDA2_BASE_",          /* ppc */
125                 NULL
126         };
127
128         /* Symbol names that begin with the following are ignored.*/
129         static const char * const ignored_prefixes[] = {
130                 "__efistub_",           /* arm64 EFI stub namespace */
131                 "__kvm_nvhe_$",         /* arm64 local symbols in non-VHE KVM namespace */
132                 "__kvm_nvhe_.L",        /* arm64 local symbols in non-VHE KVM namespace */
133                 "__AArch64ADRPThunk_",  /* arm64 lld */
134                 "__ARMV5PILongThunk_",  /* arm lld */
135                 "__ARMV7PILongThunk_",
136                 "__ThumbV7PILongThunk_",
137                 "__LA25Thunk_",         /* mips lld */
138                 "__microLA25Thunk_",
139                 "__kcfi_typeid_",       /* CFI type identifiers */
140                 NULL
141         };
142
143         /* Symbol names that end with the following are ignored.*/
144         static const char * const ignored_suffixes[] = {
145                 "_from_arm",            /* arm */
146                 "_from_thumb",          /* arm */
147                 "_veneer",              /* arm */
148                 NULL
149         };
150
151         /* Symbol names that contain the following are ignored.*/
152         static const char * const ignored_matches[] = {
153                 ".long_branch.",        /* ppc stub */
154                 ".plt_branch.",         /* ppc stub */
155                 NULL
156         };
157
158         const char * const *p;
159
160         for (p = ignored_symbols; *p; p++)
161                 if (!strcmp(name, *p))
162                         return true;
163
164         for (p = ignored_prefixes; *p; p++)
165                 if (!strncmp(name, *p, strlen(*p)))
166                         return true;
167
168         for (p = ignored_suffixes; *p; p++) {
169                 int l = strlen(name) - strlen(*p);
170
171                 if (l >= 0 && !strcmp(name + l, *p))
172                         return true;
173         }
174
175         for (p = ignored_matches; *p; p++) {
176                 if (strstr(name, *p))
177                         return true;
178         }
179
180         if (type == 'U' || type == 'u')
181                 return true;
182         /* exclude debugging symbols */
183         if (type == 'N' || type == 'n')
184                 return true;
185
186         if (toupper(type) == 'A') {
187                 /* Keep these useful absolute symbols */
188                 if (strcmp(name, "__kernel_syscall_via_break") &&
189                     strcmp(name, "__kernel_syscall_via_epc") &&
190                     strcmp(name, "__kernel_sigtramp") &&
191                     strcmp(name, "__gp"))
192                         return true;
193         }
194
195         return false;
196 }
197
198 static void check_symbol_range(const char *sym, unsigned long long addr,
199                                struct addr_range *ranges, int entries)
200 {
201         size_t i;
202         struct addr_range *ar;
203
204         for (i = 0; i < entries; ++i) {
205                 ar = &ranges[i];
206
207                 if (strcmp(sym, ar->start_sym) == 0) {
208                         ar->start = addr;
209                         return;
210                 } else if (strcmp(sym, ar->end_sym) == 0) {
211                         ar->end = addr;
212                         return;
213                 }
214         }
215 }
216
217 static struct sym_entry *read_symbol(FILE *in)
218 {
219         char name[KSYM_NAME_LEN_BUFFER+1], type;
220         unsigned long long addr;
221         unsigned int len;
222         struct sym_entry *sym;
223         int rc;
224
225         rc = fscanf(in, "%llx %c %" _stringify(KSYM_NAME_LEN_BUFFER) "s\n", &addr, &type, name);
226         if (rc != 3) {
227                 if (rc != EOF && fgets(name, ARRAY_SIZE(name), in) == NULL)
228                         fprintf(stderr, "Read error or end of file.\n");
229                 return NULL;
230         }
231         if (strlen(name) >= KSYM_NAME_LEN) {
232                 fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n"
233                                 "Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n",
234                         name, strlen(name), KSYM_NAME_LEN);
235                 return NULL;
236         }
237
238         if (strcmp(name, "_text") == 0)
239                 _text = addr;
240
241         /* Ignore most absolute/undefined (?) symbols. */
242         if (is_ignored_symbol(name, type))
243                 return NULL;
244
245         check_symbol_range(name, addr, text_ranges, ARRAY_SIZE(text_ranges));
246         check_symbol_range(name, addr, &percpu_range, 1);
247
248         /* include the type field in the symbol name, so that it gets
249          * compressed together */
250
251         len = strlen(name) + 1;
252
253         sym = malloc(sizeof(*sym) + len + 1);
254         if (!sym) {
255                 fprintf(stderr, "kallsyms failure: "
256                         "unable to allocate required amount of memory\n");
257                 exit(EXIT_FAILURE);
258         }
259         sym->addr = addr;
260         sym->len = len;
261         sym->sym[0] = type;
262         strcpy(sym_name(sym), name);
263         sym->percpu_absolute = 0;
264
265         return sym;
266 }
267
268 static int symbol_in_range(const struct sym_entry *s,
269                            const struct addr_range *ranges, int entries)
270 {
271         size_t i;
272         const struct addr_range *ar;
273
274         for (i = 0; i < entries; ++i) {
275                 ar = &ranges[i];
276
277                 if (s->addr >= ar->start && s->addr <= ar->end)
278                         return 1;
279         }
280
281         return 0;
282 }
283
284 static int symbol_valid(const struct sym_entry *s)
285 {
286         const char *name = sym_name(s);
287
288         /* if --all-symbols is not specified, then symbols outside the text
289          * and inittext sections are discarded */
290         if (!all_symbols) {
291                 if (symbol_in_range(s, text_ranges,
292                                     ARRAY_SIZE(text_ranges)) == 0)
293                         return 0;
294                 /* Corner case.  Discard any symbols with the same value as
295                  * _etext _einittext; they can move between pass 1 and 2 when
296                  * the kallsyms data are added.  If these symbols move then
297                  * they may get dropped in pass 2, which breaks the kallsyms
298                  * rules.
299                  */
300                 if ((s->addr == text_range_text->end &&
301                      strcmp(name, text_range_text->end_sym)) ||
302                     (s->addr == text_range_inittext->end &&
303                      strcmp(name, text_range_inittext->end_sym)))
304                         return 0;
305         }
306
307         return 1;
308 }
309
310 /* remove all the invalid symbols from the table */
311 static void shrink_table(void)
312 {
313         unsigned int i, pos;
314
315         pos = 0;
316         for (i = 0; i < table_cnt; i++) {
317                 if (symbol_valid(table[i])) {
318                         if (pos != i)
319                                 table[pos] = table[i];
320                         pos++;
321                 } else {
322                         free(table[i]);
323                 }
324         }
325         table_cnt = pos;
326
327         /* When valid symbol is not registered, exit to error */
328         if (!table_cnt) {
329                 fprintf(stderr, "No valid symbol.\n");
330                 exit(1);
331         }
332 }
333
334 static void read_map(const char *in)
335 {
336         FILE *fp;
337         struct sym_entry *sym;
338
339         fp = fopen(in, "r");
340         if (!fp) {
341                 perror(in);
342                 exit(1);
343         }
344
345         while (!feof(fp)) {
346                 sym = read_symbol(fp);
347                 if (!sym)
348                         continue;
349
350                 sym->start_pos = table_cnt;
351
352                 if (table_cnt >= table_size) {
353                         table_size += 10000;
354                         table = realloc(table, sizeof(*table) * table_size);
355                         if (!table) {
356                                 fprintf(stderr, "out of memory\n");
357                                 fclose(fp);
358                                 exit (1);
359                         }
360                 }
361
362                 table[table_cnt++] = sym;
363         }
364
365         fclose(fp);
366 }
367
368 static void output_label(const char *label)
369 {
370         printf(".globl %s\n", label);
371         printf("\tALGN\n");
372         printf("%s:\n", label);
373 }
374
375 /* Provide proper symbols relocatability by their '_text' relativeness. */
376 static void output_address(unsigned long long addr)
377 {
378         if (_text <= addr)
379                 printf("\tPTR\t_text + %#llx\n", addr - _text);
380         else
381                 printf("\tPTR\t_text - %#llx\n", _text - addr);
382 }
383
384 /* uncompress a compressed symbol. When this function is called, the best table
385  * might still be compressed itself, so the function needs to be recursive */
386 static int expand_symbol(const unsigned char *data, int len, char *result)
387 {
388         int c, rlen, total=0;
389
390         while (len) {
391                 c = *data;
392                 /* if the table holds a single char that is the same as the one
393                  * we are looking for, then end the search */
394                 if (best_table[c][0]==c && best_table_len[c]==1) {
395                         *result++ = c;
396                         total++;
397                 } else {
398                         /* if not, recurse and expand */
399                         rlen = expand_symbol(best_table[c], best_table_len[c], result);
400                         total += rlen;
401                         result += rlen;
402                 }
403                 data++;
404                 len--;
405         }
406         *result=0;
407
408         return total;
409 }
410
411 static int symbol_absolute(const struct sym_entry *s)
412 {
413         return s->percpu_absolute;
414 }
415
416 static char * s_name(char *buf)
417 {
418         /* Skip the symbol type */
419         return buf + 1;
420 }
421
422 static void cleanup_symbol_name(char *s)
423 {
424         char *p;
425
426         if (!lto_clang)
427                 return;
428
429         /*
430          * ASCII[.]   = 2e
431          * ASCII[0-9] = 30,39
432          * ASCII[A-Z] = 41,5a
433          * ASCII[_]   = 5f
434          * ASCII[a-z] = 61,7a
435          *
436          * As above, replacing '.' with '\0' does not affect the main sorting,
437          * but it helps us with subsorting.
438          */
439         p = strchr(s, '.');
440         if (p)
441                 *p = '\0';
442 }
443
444 static int compare_names(const void *a, const void *b)
445 {
446         int ret;
447         char sa_namebuf[KSYM_NAME_LEN];
448         char sb_namebuf[KSYM_NAME_LEN];
449         const struct sym_entry *sa = *(const struct sym_entry **)a;
450         const struct sym_entry *sb = *(const struct sym_entry **)b;
451
452         expand_symbol(sa->sym, sa->len, sa_namebuf);
453         expand_symbol(sb->sym, sb->len, sb_namebuf);
454         cleanup_symbol_name(s_name(sa_namebuf));
455         cleanup_symbol_name(s_name(sb_namebuf));
456         ret = strcmp(s_name(sa_namebuf), s_name(sb_namebuf));
457         if (!ret) {
458                 if (sa->addr > sb->addr)
459                         return 1;
460                 else if (sa->addr < sb->addr)
461                         return -1;
462
463                 /* keep old order */
464                 return (int)(sa->seq - sb->seq);
465         }
466
467         return ret;
468 }
469
470 static void sort_symbols_by_name(void)
471 {
472         qsort(table, table_cnt, sizeof(table[0]), compare_names);
473 }
474
475 static void write_src(void)
476 {
477         unsigned int i, k, off;
478         unsigned int best_idx[256];
479         unsigned int *markers;
480         char buf[KSYM_NAME_LEN];
481
482         printf("#include <asm/bitsperlong.h>\n");
483         printf("#if BITS_PER_LONG == 64\n");
484         printf("#define PTR .quad\n");
485         printf("#define ALGN .balign 8\n");
486         printf("#else\n");
487         printf("#define PTR .long\n");
488         printf("#define ALGN .balign 4\n");
489         printf("#endif\n");
490
491         printf("\t.section .rodata, \"a\"\n");
492
493         if (!base_relative)
494                 output_label("kallsyms_addresses");
495         else
496                 output_label("kallsyms_offsets");
497
498         for (i = 0; i < table_cnt; i++) {
499                 if (base_relative) {
500                         /*
501                          * Use the offset relative to the lowest value
502                          * encountered of all relative symbols, and emit
503                          * non-relocatable fixed offsets that will be fixed
504                          * up at runtime.
505                          */
506
507                         long long offset;
508                         int overflow;
509
510                         if (!absolute_percpu) {
511                                 offset = table[i]->addr - relative_base;
512                                 overflow = (offset < 0 || offset > UINT_MAX);
513                         } else if (symbol_absolute(table[i])) {
514                                 offset = table[i]->addr;
515                                 overflow = (offset < 0 || offset > INT_MAX);
516                         } else {
517                                 offset = relative_base - table[i]->addr - 1;
518                                 overflow = (offset < INT_MIN || offset >= 0);
519                         }
520                         if (overflow) {
521                                 fprintf(stderr, "kallsyms failure: "
522                                         "%s symbol value %#llx out of range in relative mode\n",
523                                         symbol_absolute(table[i]) ? "absolute" : "relative",
524                                         table[i]->addr);
525                                 exit(EXIT_FAILURE);
526                         }
527                         printf("\t.long\t%#x\n", (int)offset);
528                 } else if (!symbol_absolute(table[i])) {
529                         output_address(table[i]->addr);
530                 } else {
531                         printf("\tPTR\t%#llx\n", table[i]->addr);
532                 }
533         }
534         printf("\n");
535
536         if (base_relative) {
537                 output_label("kallsyms_relative_base");
538                 output_address(relative_base);
539                 printf("\n");
540         }
541
542         output_label("kallsyms_num_syms");
543         printf("\t.long\t%u\n", table_cnt);
544         printf("\n");
545
546         /* table of offset markers, that give the offset in the compressed stream
547          * every 256 symbols */
548         markers = malloc(sizeof(unsigned int) * ((table_cnt + 255) / 256));
549         if (!markers) {
550                 fprintf(stderr, "kallsyms failure: "
551                         "unable to allocate required memory\n");
552                 exit(EXIT_FAILURE);
553         }
554
555         output_label("kallsyms_names");
556         off = 0;
557         for (i = 0; i < table_cnt; i++) {
558                 if ((i & 0xFF) == 0)
559                         markers[i >> 8] = off;
560                 table[i]->seq = i;
561
562                 /* There cannot be any symbol of length zero. */
563                 if (table[i]->len == 0) {
564                         fprintf(stderr, "kallsyms failure: "
565                                 "unexpected zero symbol length\n");
566                         exit(EXIT_FAILURE);
567                 }
568
569                 /* Only lengths that fit in up-to-two-byte ULEB128 are supported. */
570                 if (table[i]->len > 0x3FFF) {
571                         fprintf(stderr, "kallsyms failure: "
572                                 "unexpected huge symbol length\n");
573                         exit(EXIT_FAILURE);
574                 }
575
576                 /* Encode length with ULEB128. */
577                 if (table[i]->len <= 0x7F) {
578                         /* Most symbols use a single byte for the length. */
579                         printf("\t.byte 0x%02x", table[i]->len);
580                         off += table[i]->len + 1;
581                 } else {
582                         /* "Big" symbols use two bytes. */
583                         printf("\t.byte 0x%02x, 0x%02x",
584                                 (table[i]->len & 0x7F) | 0x80,
585                                 (table[i]->len >> 7) & 0x7F);
586                         off += table[i]->len + 2;
587                 }
588                 for (k = 0; k < table[i]->len; k++)
589                         printf(", 0x%02x", table[i]->sym[k]);
590                 printf("\n");
591         }
592         printf("\n");
593
594         output_label("kallsyms_markers");
595         for (i = 0; i < ((table_cnt + 255) >> 8); i++)
596                 printf("\t.long\t%u\n", markers[i]);
597         printf("\n");
598
599         free(markers);
600
601         sort_symbols_by_name();
602         output_label("kallsyms_seqs_of_names");
603         for (i = 0; i < table_cnt; i++)
604                 printf("\t.byte 0x%02x, 0x%02x, 0x%02x\n",
605                         (unsigned char)(table[i]->seq >> 16),
606                         (unsigned char)(table[i]->seq >> 8),
607                         (unsigned char)(table[i]->seq >> 0));
608         printf("\n");
609
610         output_label("kallsyms_token_table");
611         off = 0;
612         for (i = 0; i < 256; i++) {
613                 best_idx[i] = off;
614                 expand_symbol(best_table[i], best_table_len[i], buf);
615                 printf("\t.asciz\t\"%s\"\n", buf);
616                 off += strlen(buf) + 1;
617         }
618         printf("\n");
619
620         output_label("kallsyms_token_index");
621         for (i = 0; i < 256; i++)
622                 printf("\t.short\t%d\n", best_idx[i]);
623         printf("\n");
624 }
625
626
627 /* table lookup compression functions */
628
629 /* count all the possible tokens in a symbol */
630 static void learn_symbol(const unsigned char *symbol, int len)
631 {
632         int i;
633
634         for (i = 0; i < len - 1; i++)
635                 token_profit[ symbol[i] + (symbol[i + 1] << 8) ]++;
636 }
637
638 /* decrease the count for all the possible tokens in a symbol */
639 static void forget_symbol(const unsigned char *symbol, int len)
640 {
641         int i;
642
643         for (i = 0; i < len - 1; i++)
644                 token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--;
645 }
646
647 /* do the initial token count */
648 static void build_initial_token_table(void)
649 {
650         unsigned int i;
651
652         for (i = 0; i < table_cnt; i++)
653                 learn_symbol(table[i]->sym, table[i]->len);
654 }
655
656 static unsigned char *find_token(unsigned char *str, int len,
657                                  const unsigned char *token)
658 {
659         int i;
660
661         for (i = 0; i < len - 1; i++) {
662                 if (str[i] == token[0] && str[i+1] == token[1])
663                         return &str[i];
664         }
665         return NULL;
666 }
667
668 /* replace a given token in all the valid symbols. Use the sampled symbols
669  * to update the counts */
670 static void compress_symbols(const unsigned char *str, int idx)
671 {
672         unsigned int i, len, size;
673         unsigned char *p1, *p2;
674
675         for (i = 0; i < table_cnt; i++) {
676
677                 len = table[i]->len;
678                 p1 = table[i]->sym;
679
680                 /* find the token on the symbol */
681                 p2 = find_token(p1, len, str);
682                 if (!p2) continue;
683
684                 /* decrease the counts for this symbol's tokens */
685                 forget_symbol(table[i]->sym, len);
686
687                 size = len;
688
689                 do {
690                         *p2 = idx;
691                         p2++;
692                         size -= (p2 - p1);
693                         memmove(p2, p2 + 1, size);
694                         p1 = p2;
695                         len--;
696
697                         if (size < 2) break;
698
699                         /* find the token on the symbol */
700                         p2 = find_token(p1, size, str);
701
702                 } while (p2);
703
704                 table[i]->len = len;
705
706                 /* increase the counts for this symbol's new tokens */
707                 learn_symbol(table[i]->sym, len);
708         }
709 }
710
711 /* search the token with the maximum profit */
712 static int find_best_token(void)
713 {
714         int i, best, bestprofit;
715
716         bestprofit=-10000;
717         best = 0;
718
719         for (i = 0; i < 0x10000; i++) {
720                 if (token_profit[i] > bestprofit) {
721                         best = i;
722                         bestprofit = token_profit[i];
723                 }
724         }
725         return best;
726 }
727
728 /* this is the core of the algorithm: calculate the "best" table */
729 static void optimize_result(void)
730 {
731         int i, best;
732
733         /* using the '\0' symbol last allows compress_symbols to use standard
734          * fast string functions */
735         for (i = 255; i >= 0; i--) {
736
737                 /* if this table slot is empty (it is not used by an actual
738                  * original char code */
739                 if (!best_table_len[i]) {
740
741                         /* find the token with the best profit value */
742                         best = find_best_token();
743                         if (token_profit[best] == 0)
744                                 break;
745
746                         /* place it in the "best" table */
747                         best_table_len[i] = 2;
748                         best_table[i][0] = best & 0xFF;
749                         best_table[i][1] = (best >> 8) & 0xFF;
750
751                         /* replace this token in all the valid symbols */
752                         compress_symbols(best_table[i], i);
753                 }
754         }
755 }
756
757 /* start by placing the symbols that are actually used on the table */
758 static void insert_real_symbols_in_table(void)
759 {
760         unsigned int i, j, c;
761
762         for (i = 0; i < table_cnt; i++) {
763                 for (j = 0; j < table[i]->len; j++) {
764                         c = table[i]->sym[j];
765                         best_table[c][0]=c;
766                         best_table_len[c]=1;
767                 }
768         }
769 }
770
771 static void optimize_token_table(void)
772 {
773         build_initial_token_table();
774
775         insert_real_symbols_in_table();
776
777         optimize_result();
778 }
779
780 /* guess for "linker script provide" symbol */
781 static int may_be_linker_script_provide_symbol(const struct sym_entry *se)
782 {
783         const char *symbol = sym_name(se);
784         int len = se->len - 1;
785
786         if (len < 8)
787                 return 0;
788
789         if (symbol[0] != '_' || symbol[1] != '_')
790                 return 0;
791
792         /* __start_XXXXX */
793         if (!memcmp(symbol + 2, "start_", 6))
794                 return 1;
795
796         /* __stop_XXXXX */
797         if (!memcmp(symbol + 2, "stop_", 5))
798                 return 1;
799
800         /* __end_XXXXX */
801         if (!memcmp(symbol + 2, "end_", 4))
802                 return 1;
803
804         /* __XXXXX_start */
805         if (!memcmp(symbol + len - 6, "_start", 6))
806                 return 1;
807
808         /* __XXXXX_end */
809         if (!memcmp(symbol + len - 4, "_end", 4))
810                 return 1;
811
812         return 0;
813 }
814
815 static int compare_symbols(const void *a, const void *b)
816 {
817         const struct sym_entry *sa = *(const struct sym_entry **)a;
818         const struct sym_entry *sb = *(const struct sym_entry **)b;
819         int wa, wb;
820
821         /* sort by address first */
822         if (sa->addr > sb->addr)
823                 return 1;
824         if (sa->addr < sb->addr)
825                 return -1;
826
827         /* sort by "weakness" type */
828         wa = (sa->sym[0] == 'w') || (sa->sym[0] == 'W');
829         wb = (sb->sym[0] == 'w') || (sb->sym[0] == 'W');
830         if (wa != wb)
831                 return wa - wb;
832
833         /* sort by "linker script provide" type */
834         wa = may_be_linker_script_provide_symbol(sa);
835         wb = may_be_linker_script_provide_symbol(sb);
836         if (wa != wb)
837                 return wa - wb;
838
839         /* sort by the number of prefix underscores */
840         wa = strspn(sym_name(sa), "_");
841         wb = strspn(sym_name(sb), "_");
842         if (wa != wb)
843                 return wa - wb;
844
845         /* sort by initial order, so that other symbols are left undisturbed */
846         return sa->start_pos - sb->start_pos;
847 }
848
849 static void sort_symbols(void)
850 {
851         qsort(table, table_cnt, sizeof(table[0]), compare_symbols);
852 }
853
854 static void make_percpus_absolute(void)
855 {
856         unsigned int i;
857
858         for (i = 0; i < table_cnt; i++)
859                 if (symbol_in_range(table[i], &percpu_range, 1)) {
860                         /*
861                          * Keep the 'A' override for percpu symbols to
862                          * ensure consistent behavior compared to older
863                          * versions of this tool.
864                          */
865                         table[i]->sym[0] = 'A';
866                         table[i]->percpu_absolute = 1;
867                 }
868 }
869
870 /* find the minimum non-absolute symbol address */
871 static void record_relative_base(void)
872 {
873         unsigned int i;
874
875         for (i = 0; i < table_cnt; i++)
876                 if (!symbol_absolute(table[i])) {
877                         /*
878                          * The table is sorted by address.
879                          * Take the first non-absolute symbol value.
880                          */
881                         relative_base = table[i]->addr;
882                         return;
883                 }
884 }
885
886 int main(int argc, char **argv)
887 {
888         while (1) {
889                 static struct option long_options[] = {
890                         {"all-symbols",     no_argument, &all_symbols,     1},
891                         {"absolute-percpu", no_argument, &absolute_percpu, 1},
892                         {"base-relative",   no_argument, &base_relative,   1},
893                         {"lto-clang",       no_argument, &lto_clang,       1},
894                         {},
895                 };
896
897                 int c = getopt_long(argc, argv, "", long_options, NULL);
898
899                 if (c == -1)
900                         break;
901                 if (c != 0)
902                         usage();
903         }
904
905         if (optind >= argc)
906                 usage();
907
908         read_map(argv[optind]);
909         shrink_table();
910         if (absolute_percpu)
911                 make_percpus_absolute();
912         sort_symbols();
913         if (base_relative)
914                 record_relative_base();
915         optimize_token_table();
916         write_src();
917
918         return 0;
919 }