~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/kallsyms.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/kallsyms.c (Version linux-6.12-rc7) and /scripts/kallsyms.c (Version linux-6.4.16)


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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php