~ [ 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 (Architecture i386) and /scripts/kallsyms.c (Architecture mips)


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

~ [ 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