.. | .. |
---|
18 | 18 | * |
---|
19 | 19 | */ |
---|
20 | 20 | |
---|
| 21 | +#include <stdbool.h> |
---|
21 | 22 | #include <stdio.h> |
---|
22 | 23 | #include <stdlib.h> |
---|
23 | 24 | #include <string.h> |
---|
24 | 25 | #include <ctype.h> |
---|
25 | 26 | #include <limits.h> |
---|
26 | 27 | |
---|
27 | | -#ifndef ARRAY_SIZE |
---|
28 | 28 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) |
---|
29 | | -#endif |
---|
30 | 29 | |
---|
31 | 30 | #define KSYM_NAME_LEN 128 |
---|
32 | 31 | |
---|
.. | .. |
---|
34 | 33 | unsigned long long addr; |
---|
35 | 34 | unsigned int len; |
---|
36 | 35 | unsigned int start_pos; |
---|
37 | | - unsigned char *sym; |
---|
38 | 36 | unsigned int percpu_absolute; |
---|
| 37 | + unsigned char sym[]; |
---|
39 | 38 | }; |
---|
40 | 39 | |
---|
41 | 40 | struct addr_range { |
---|
.. | .. |
---|
48 | 47 | static struct addr_range text_ranges[] = { |
---|
49 | 48 | { "_stext", "_etext" }, |
---|
50 | 49 | { "_sinittext", "_einittext" }, |
---|
51 | | - { "_stext_l1", "_etext_l1" }, /* Blackfin on-chip L1 inst SRAM */ |
---|
52 | | - { "_stext_l2", "_etext_l2" }, /* Blackfin on-chip L2 SRAM */ |
---|
53 | 50 | }; |
---|
54 | 51 | #define text_range_text (&text_ranges[0]) |
---|
55 | 52 | #define text_range_inittext (&text_ranges[1]) |
---|
.. | .. |
---|
58 | 55 | "__per_cpu_start", "__per_cpu_end", -1ULL, 0 |
---|
59 | 56 | }; |
---|
60 | 57 | |
---|
61 | | -static struct sym_entry *table; |
---|
| 58 | +static struct sym_entry **table; |
---|
62 | 59 | static unsigned int table_size, table_cnt; |
---|
63 | | -static int all_symbols = 0; |
---|
64 | | -static int absolute_percpu = 0; |
---|
65 | | -static int base_relative = 0; |
---|
| 60 | +static int all_symbols; |
---|
| 61 | +static int absolute_percpu; |
---|
| 62 | +static int base_relative; |
---|
66 | 63 | |
---|
67 | | -int token_profit[0x10000]; |
---|
| 64 | +static int token_profit[0x10000]; |
---|
68 | 65 | |
---|
69 | 66 | /* the table that holds the result of the compression */ |
---|
70 | | -unsigned char best_table[256][2]; |
---|
71 | | -unsigned char best_table_len[256]; |
---|
| 67 | +static unsigned char best_table[256][2]; |
---|
| 68 | +static unsigned char best_table_len[256]; |
---|
72 | 69 | |
---|
73 | 70 | |
---|
74 | 71 | static void usage(void) |
---|
.. | .. |
---|
78 | 75 | exit(1); |
---|
79 | 76 | } |
---|
80 | 77 | |
---|
81 | | -/* |
---|
82 | | - * This ignores the intensely annoying "mapping symbols" found |
---|
83 | | - * in ARM ELF files: $a, $t and $d. |
---|
84 | | - */ |
---|
85 | | -static inline int is_arm_mapping_symbol(const char *str) |
---|
| 78 | +static char *sym_name(const struct sym_entry *s) |
---|
86 | 79 | { |
---|
87 | | - return str[0] == '$' && strchr("axtd", str[1]) |
---|
88 | | - && (str[2] == '\0' || str[2] == '.'); |
---|
| 80 | + return (char *)s->sym + 1; |
---|
89 | 81 | } |
---|
90 | 82 | |
---|
91 | | -static int check_symbol_range(const char *sym, unsigned long long addr, |
---|
92 | | - struct addr_range *ranges, int entries) |
---|
| 83 | +static bool is_ignored_symbol(const char *name, char type) |
---|
| 84 | +{ |
---|
| 85 | + /* Symbol names that exactly match to the following are ignored.*/ |
---|
| 86 | + static const char * const ignored_symbols[] = { |
---|
| 87 | + /* |
---|
| 88 | + * Symbols which vary between passes. Passes 1 and 2 must have |
---|
| 89 | + * identical symbol lists. The kallsyms_* symbols below are |
---|
| 90 | + * only added after pass 1, they would be included in pass 2 |
---|
| 91 | + * when --all-symbols is specified so exclude them to get a |
---|
| 92 | + * stable symbol list. |
---|
| 93 | + */ |
---|
| 94 | + "kallsyms_addresses", |
---|
| 95 | + "kallsyms_offsets", |
---|
| 96 | + "kallsyms_relative_base", |
---|
| 97 | + "kallsyms_num_syms", |
---|
| 98 | + "kallsyms_names", |
---|
| 99 | + "kallsyms_markers", |
---|
| 100 | + "kallsyms_token_table", |
---|
| 101 | + "kallsyms_token_index", |
---|
| 102 | + /* Exclude linker generated symbols which vary between passes */ |
---|
| 103 | + "_SDA_BASE_", /* ppc */ |
---|
| 104 | + "_SDA2_BASE_", /* ppc */ |
---|
| 105 | + NULL |
---|
| 106 | + }; |
---|
| 107 | + |
---|
| 108 | + /* Symbol names that begin with the following are ignored.*/ |
---|
| 109 | + static const char * const ignored_prefixes[] = { |
---|
| 110 | + "$", /* local symbols for ARM, MIPS, etc. */ |
---|
| 111 | + ".LASANPC", /* s390 kasan local symbols */ |
---|
| 112 | + "__crc_", /* modversions */ |
---|
| 113 | + "__efistub_", /* arm64 EFI stub namespace */ |
---|
| 114 | + "__kvm_nvhe_", /* arm64 non-VHE KVM namespace */ |
---|
| 115 | + "__AArch64ADRPThunk_", /* arm64 lld */ |
---|
| 116 | + "__ARMV5PILongThunk_", /* arm lld */ |
---|
| 117 | + "__ARMV7PILongThunk_", |
---|
| 118 | + "__ThumbV7PILongThunk_", |
---|
| 119 | + "__LA25Thunk_", /* mips lld */ |
---|
| 120 | + "__microLA25Thunk_", |
---|
| 121 | + NULL |
---|
| 122 | + }; |
---|
| 123 | + |
---|
| 124 | + /* Symbol names that end with the following are ignored.*/ |
---|
| 125 | + static const char * const ignored_suffixes[] = { |
---|
| 126 | + "_from_arm", /* arm */ |
---|
| 127 | + "_from_thumb", /* arm */ |
---|
| 128 | + "_veneer", /* arm */ |
---|
| 129 | + NULL |
---|
| 130 | + }; |
---|
| 131 | + |
---|
| 132 | + /* Symbol names that contain the following are ignored.*/ |
---|
| 133 | + static const char * const ignored_matches[] = { |
---|
| 134 | + ".long_branch.", /* ppc stub */ |
---|
| 135 | + ".plt_branch.", /* ppc stub */ |
---|
| 136 | + NULL |
---|
| 137 | + }; |
---|
| 138 | + |
---|
| 139 | + const char * const *p; |
---|
| 140 | + |
---|
| 141 | + for (p = ignored_symbols; *p; p++) |
---|
| 142 | + if (!strcmp(name, *p)) |
---|
| 143 | + return true; |
---|
| 144 | + |
---|
| 145 | + for (p = ignored_prefixes; *p; p++) |
---|
| 146 | + if (!strncmp(name, *p, strlen(*p))) |
---|
| 147 | + return true; |
---|
| 148 | + |
---|
| 149 | + for (p = ignored_suffixes; *p; p++) { |
---|
| 150 | + int l = strlen(name) - strlen(*p); |
---|
| 151 | + |
---|
| 152 | + if (l >= 0 && !strcmp(name + l, *p)) |
---|
| 153 | + return true; |
---|
| 154 | + } |
---|
| 155 | + |
---|
| 156 | + for (p = ignored_matches; *p; p++) { |
---|
| 157 | + if (strstr(name, *p)) |
---|
| 158 | + return true; |
---|
| 159 | + } |
---|
| 160 | + |
---|
| 161 | + if (type == 'U' || type == 'u') |
---|
| 162 | + return true; |
---|
| 163 | + /* exclude debugging symbols */ |
---|
| 164 | + if (type == 'N' || type == 'n') |
---|
| 165 | + return true; |
---|
| 166 | + |
---|
| 167 | + if (toupper(type) == 'A') { |
---|
| 168 | + /* Keep these useful absolute symbols */ |
---|
| 169 | + if (strcmp(name, "__kernel_syscall_via_break") && |
---|
| 170 | + strcmp(name, "__kernel_syscall_via_epc") && |
---|
| 171 | + strcmp(name, "__kernel_sigtramp") && |
---|
| 172 | + strcmp(name, "__gp")) |
---|
| 173 | + return true; |
---|
| 174 | + } |
---|
| 175 | + |
---|
| 176 | + return false; |
---|
| 177 | +} |
---|
| 178 | + |
---|
| 179 | +static void check_symbol_range(const char *sym, unsigned long long addr, |
---|
| 180 | + struct addr_range *ranges, int entries) |
---|
93 | 181 | { |
---|
94 | 182 | size_t i; |
---|
95 | 183 | struct addr_range *ar; |
---|
.. | .. |
---|
99 | 187 | |
---|
100 | 188 | if (strcmp(sym, ar->start_sym) == 0) { |
---|
101 | 189 | ar->start = addr; |
---|
102 | | - return 0; |
---|
| 190 | + return; |
---|
103 | 191 | } else if (strcmp(sym, ar->end_sym) == 0) { |
---|
104 | 192 | ar->end = addr; |
---|
105 | | - return 0; |
---|
| 193 | + return; |
---|
106 | 194 | } |
---|
107 | 195 | } |
---|
108 | | - |
---|
109 | | - return 1; |
---|
110 | 196 | } |
---|
111 | 197 | |
---|
112 | | -static int read_symbol(FILE *in, struct sym_entry *s) |
---|
| 198 | +static struct sym_entry *read_symbol(FILE *in) |
---|
113 | 199 | { |
---|
114 | | - char sym[500], stype; |
---|
| 200 | + char name[500], type; |
---|
| 201 | + unsigned long long addr; |
---|
| 202 | + unsigned int len; |
---|
| 203 | + struct sym_entry *sym; |
---|
115 | 204 | int rc; |
---|
116 | 205 | |
---|
117 | | - rc = fscanf(in, "%llx %c %499s\n", &s->addr, &stype, sym); |
---|
| 206 | + rc = fscanf(in, "%llx %c %499s\n", &addr, &type, name); |
---|
118 | 207 | if (rc != 3) { |
---|
119 | | - if (rc != EOF && fgets(sym, 500, in) == NULL) |
---|
| 208 | + if (rc != EOF && fgets(name, 500, in) == NULL) |
---|
120 | 209 | fprintf(stderr, "Read error or end of file.\n"); |
---|
121 | | - return -1; |
---|
| 210 | + return NULL; |
---|
122 | 211 | } |
---|
123 | | - if (strlen(sym) >= KSYM_NAME_LEN) { |
---|
| 212 | + if (strlen(name) >= KSYM_NAME_LEN) { |
---|
124 | 213 | fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n" |
---|
125 | 214 | "Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n", |
---|
126 | | - sym, strlen(sym), KSYM_NAME_LEN); |
---|
127 | | - return -1; |
---|
| 215 | + name, strlen(name), KSYM_NAME_LEN); |
---|
| 216 | + return NULL; |
---|
128 | 217 | } |
---|
| 218 | + |
---|
| 219 | + if (strcmp(name, "_text") == 0) |
---|
| 220 | + _text = addr; |
---|
129 | 221 | |
---|
130 | 222 | /* Ignore most absolute/undefined (?) symbols. */ |
---|
131 | | - if (strcmp(sym, "_text") == 0) |
---|
132 | | - _text = s->addr; |
---|
133 | | - else if (check_symbol_range(sym, s->addr, text_ranges, |
---|
134 | | - ARRAY_SIZE(text_ranges)) == 0) |
---|
135 | | - /* nothing to do */; |
---|
136 | | - else if (toupper(stype) == 'A') |
---|
137 | | - { |
---|
138 | | - /* Keep these useful absolute symbols */ |
---|
139 | | - if (strcmp(sym, "__kernel_syscall_via_break") && |
---|
140 | | - strcmp(sym, "__kernel_syscall_via_epc") && |
---|
141 | | - strcmp(sym, "__kernel_sigtramp") && |
---|
142 | | - strcmp(sym, "__gp")) |
---|
143 | | - return -1; |
---|
| 223 | + if (is_ignored_symbol(name, type)) |
---|
| 224 | + return NULL; |
---|
144 | 225 | |
---|
145 | | - } |
---|
146 | | - else if (toupper(stype) == 'U' || |
---|
147 | | - is_arm_mapping_symbol(sym)) |
---|
148 | | - return -1; |
---|
149 | | - /* exclude also MIPS ELF local symbols ($L123 instead of .L123) */ |
---|
150 | | - else if (sym[0] == '$') |
---|
151 | | - return -1; |
---|
152 | | - /* exclude debugging symbols */ |
---|
153 | | - else if (stype == 'N' || stype == 'n') |
---|
154 | | - return -1; |
---|
155 | | - /* exclude s390 kasan local symbols */ |
---|
156 | | - else if (!strncmp(sym, ".LASANPC", 8)) |
---|
157 | | - return -1; |
---|
| 226 | + check_symbol_range(name, addr, text_ranges, ARRAY_SIZE(text_ranges)); |
---|
| 227 | + check_symbol_range(name, addr, &percpu_range, 1); |
---|
158 | 228 | |
---|
159 | 229 | /* include the type field in the symbol name, so that it gets |
---|
160 | 230 | * compressed together */ |
---|
161 | | - s->len = strlen(sym) + 1; |
---|
162 | | - s->sym = malloc(s->len + 1); |
---|
163 | | - if (!s->sym) { |
---|
| 231 | + |
---|
| 232 | + len = strlen(name) + 1; |
---|
| 233 | + |
---|
| 234 | + sym = malloc(sizeof(*sym) + len + 1); |
---|
| 235 | + if (!sym) { |
---|
164 | 236 | fprintf(stderr, "kallsyms failure: " |
---|
165 | 237 | "unable to allocate required amount of memory\n"); |
---|
166 | 238 | exit(EXIT_FAILURE); |
---|
167 | 239 | } |
---|
168 | | - strcpy((char *)s->sym + 1, sym); |
---|
169 | | - s->sym[0] = stype; |
---|
| 240 | + sym->addr = addr; |
---|
| 241 | + sym->len = len; |
---|
| 242 | + sym->sym[0] = type; |
---|
| 243 | + strcpy(sym_name(sym), name); |
---|
| 244 | + sym->percpu_absolute = 0; |
---|
170 | 245 | |
---|
171 | | - s->percpu_absolute = 0; |
---|
172 | | - |
---|
173 | | - /* Record if we've found __per_cpu_start/end. */ |
---|
174 | | - check_symbol_range(sym, s->addr, &percpu_range, 1); |
---|
175 | | - |
---|
176 | | - return 0; |
---|
| 246 | + return sym; |
---|
177 | 247 | } |
---|
178 | 248 | |
---|
179 | | -static int symbol_in_range(struct sym_entry *s, struct addr_range *ranges, |
---|
180 | | - int entries) |
---|
| 249 | +static int symbol_in_range(const struct sym_entry *s, |
---|
| 250 | + const struct addr_range *ranges, int entries) |
---|
181 | 251 | { |
---|
182 | 252 | size_t i; |
---|
183 | | - struct addr_range *ar; |
---|
| 253 | + const struct addr_range *ar; |
---|
184 | 254 | |
---|
185 | 255 | for (i = 0; i < entries; ++i) { |
---|
186 | 256 | ar = &ranges[i]; |
---|
.. | .. |
---|
192 | 262 | return 0; |
---|
193 | 263 | } |
---|
194 | 264 | |
---|
195 | | -static int symbol_valid(struct sym_entry *s) |
---|
| 265 | +static int symbol_valid(const struct sym_entry *s) |
---|
196 | 266 | { |
---|
197 | | - /* Symbols which vary between passes. Passes 1 and 2 must have |
---|
198 | | - * identical symbol lists. The kallsyms_* symbols below are only added |
---|
199 | | - * after pass 1, they would be included in pass 2 when --all-symbols is |
---|
200 | | - * specified so exclude them to get a stable symbol list. |
---|
201 | | - */ |
---|
202 | | - static char *special_symbols[] = { |
---|
203 | | - "kallsyms_addresses", |
---|
204 | | - "kallsyms_offsets", |
---|
205 | | - "kallsyms_relative_base", |
---|
206 | | - "kallsyms_num_syms", |
---|
207 | | - "kallsyms_names", |
---|
208 | | - "kallsyms_markers", |
---|
209 | | - "kallsyms_token_table", |
---|
210 | | - "kallsyms_token_index", |
---|
211 | | - |
---|
212 | | - /* Exclude linker generated symbols which vary between passes */ |
---|
213 | | - "_SDA_BASE_", /* ppc */ |
---|
214 | | - "_SDA2_BASE_", /* ppc */ |
---|
215 | | - NULL }; |
---|
216 | | - |
---|
217 | | - static char *special_prefixes[] = { |
---|
218 | | - "__crc_", /* modversions */ |
---|
219 | | - "__efistub_", /* arm64 EFI stub namespace */ |
---|
220 | | - NULL }; |
---|
221 | | - |
---|
222 | | - static char *special_suffixes[] = { |
---|
223 | | - "_veneer", /* arm */ |
---|
224 | | - "_from_arm", /* arm */ |
---|
225 | | - "_from_thumb", /* arm */ |
---|
226 | | - NULL }; |
---|
227 | | - |
---|
228 | | - int i; |
---|
229 | | - char *sym_name = (char *)s->sym + 1; |
---|
| 267 | + const char *name = sym_name(s); |
---|
230 | 268 | |
---|
231 | 269 | /* if --all-symbols is not specified, then symbols outside the text |
---|
232 | 270 | * and inittext sections are discarded */ |
---|
.. | .. |
---|
241 | 279 | * rules. |
---|
242 | 280 | */ |
---|
243 | 281 | if ((s->addr == text_range_text->end && |
---|
244 | | - strcmp(sym_name, |
---|
245 | | - text_range_text->end_sym)) || |
---|
| 282 | + strcmp(name, text_range_text->end_sym)) || |
---|
246 | 283 | (s->addr == text_range_inittext->end && |
---|
247 | | - strcmp(sym_name, |
---|
248 | | - text_range_inittext->end_sym))) |
---|
249 | | - return 0; |
---|
250 | | - } |
---|
251 | | - |
---|
252 | | - /* Exclude symbols which vary between passes. */ |
---|
253 | | - for (i = 0; special_symbols[i]; i++) |
---|
254 | | - if (strcmp(sym_name, special_symbols[i]) == 0) |
---|
255 | | - return 0; |
---|
256 | | - |
---|
257 | | - for (i = 0; special_prefixes[i]; i++) { |
---|
258 | | - int l = strlen(special_prefixes[i]); |
---|
259 | | - |
---|
260 | | - if (l <= strlen(sym_name) && |
---|
261 | | - strncmp(sym_name, special_prefixes[i], l) == 0) |
---|
262 | | - return 0; |
---|
263 | | - } |
---|
264 | | - |
---|
265 | | - for (i = 0; special_suffixes[i]; i++) { |
---|
266 | | - int l = strlen(sym_name) - strlen(special_suffixes[i]); |
---|
267 | | - |
---|
268 | | - if (l >= 0 && strcmp(sym_name + l, special_suffixes[i]) == 0) |
---|
| 284 | + strcmp(name, text_range_inittext->end_sym))) |
---|
269 | 285 | return 0; |
---|
270 | 286 | } |
---|
271 | 287 | |
---|
272 | 288 | return 1; |
---|
273 | 289 | } |
---|
274 | 290 | |
---|
| 291 | +/* remove all the invalid symbols from the table */ |
---|
| 292 | +static void shrink_table(void) |
---|
| 293 | +{ |
---|
| 294 | + unsigned int i, pos; |
---|
| 295 | + |
---|
| 296 | + pos = 0; |
---|
| 297 | + for (i = 0; i < table_cnt; i++) { |
---|
| 298 | + if (symbol_valid(table[i])) { |
---|
| 299 | + if (pos != i) |
---|
| 300 | + table[pos] = table[i]; |
---|
| 301 | + pos++; |
---|
| 302 | + } else { |
---|
| 303 | + free(table[i]); |
---|
| 304 | + } |
---|
| 305 | + } |
---|
| 306 | + table_cnt = pos; |
---|
| 307 | + |
---|
| 308 | + /* When valid symbol is not registered, exit to error */ |
---|
| 309 | + if (!table_cnt) { |
---|
| 310 | + fprintf(stderr, "No valid symbol.\n"); |
---|
| 311 | + exit(1); |
---|
| 312 | + } |
---|
| 313 | +} |
---|
| 314 | + |
---|
275 | 315 | static void read_map(FILE *in) |
---|
276 | 316 | { |
---|
| 317 | + struct sym_entry *sym; |
---|
| 318 | + |
---|
277 | 319 | while (!feof(in)) { |
---|
| 320 | + sym = read_symbol(in); |
---|
| 321 | + if (!sym) |
---|
| 322 | + continue; |
---|
| 323 | + |
---|
| 324 | + sym->start_pos = table_cnt; |
---|
| 325 | + |
---|
278 | 326 | if (table_cnt >= table_size) { |
---|
279 | 327 | table_size += 10000; |
---|
280 | 328 | table = realloc(table, sizeof(*table) * table_size); |
---|
.. | .. |
---|
283 | 331 | exit (1); |
---|
284 | 332 | } |
---|
285 | 333 | } |
---|
286 | | - if (read_symbol(in, &table[table_cnt]) == 0) { |
---|
287 | | - table[table_cnt].start_pos = table_cnt; |
---|
288 | | - table_cnt++; |
---|
289 | | - } |
---|
| 334 | + |
---|
| 335 | + table[table_cnt++] = sym; |
---|
290 | 336 | } |
---|
291 | 337 | } |
---|
292 | 338 | |
---|
293 | | -static void output_label(char *label) |
---|
| 339 | +static void output_label(const char *label) |
---|
294 | 340 | { |
---|
295 | 341 | printf(".globl %s\n", label); |
---|
296 | 342 | printf("\tALGN\n"); |
---|
297 | 343 | printf("%s:\n", label); |
---|
298 | 344 | } |
---|
299 | 345 | |
---|
| 346 | +/* Provide proper symbols relocatability by their '_text' relativeness. */ |
---|
| 347 | +static void output_address(unsigned long long addr) |
---|
| 348 | +{ |
---|
| 349 | + if (_text <= addr) |
---|
| 350 | + printf("\tPTR\t_text + %#llx\n", addr - _text); |
---|
| 351 | + else |
---|
| 352 | + printf("\tPTR\t_text - %#llx\n", _text - addr); |
---|
| 353 | +} |
---|
| 354 | + |
---|
300 | 355 | /* uncompress a compressed symbol. When this function is called, the best table |
---|
301 | 356 | * might still be compressed itself, so the function needs to be recursive */ |
---|
302 | | -static int expand_symbol(unsigned char *data, int len, char *result) |
---|
| 357 | +static int expand_symbol(const unsigned char *data, int len, char *result) |
---|
303 | 358 | { |
---|
304 | 359 | int c, rlen, total=0; |
---|
305 | 360 | |
---|
.. | .. |
---|
324 | 379 | return total; |
---|
325 | 380 | } |
---|
326 | 381 | |
---|
327 | | -static int symbol_absolute(struct sym_entry *s) |
---|
| 382 | +static int symbol_absolute(const struct sym_entry *s) |
---|
328 | 383 | { |
---|
329 | 384 | return s->percpu_absolute; |
---|
330 | 385 | } |
---|
.. | .. |
---|
336 | 391 | unsigned int *markers; |
---|
337 | 392 | char buf[KSYM_NAME_LEN]; |
---|
338 | 393 | |
---|
339 | | - printf("#include <asm/types.h>\n"); |
---|
| 394 | + printf("#include <asm/bitsperlong.h>\n"); |
---|
340 | 395 | printf("#if BITS_PER_LONG == 64\n"); |
---|
341 | 396 | printf("#define PTR .quad\n"); |
---|
342 | | - printf("#define ALGN .align 8\n"); |
---|
| 397 | + printf("#define ALGN .balign 8\n"); |
---|
343 | 398 | printf("#else\n"); |
---|
344 | 399 | printf("#define PTR .long\n"); |
---|
345 | | - printf("#define ALGN .align 4\n"); |
---|
| 400 | + printf("#define ALGN .balign 4\n"); |
---|
346 | 401 | printf("#endif\n"); |
---|
347 | 402 | |
---|
348 | 403 | printf("\t.section .rodata, \"a\"\n"); |
---|
349 | 404 | |
---|
350 | | - /* Provide proper symbols relocatability by their relativeness |
---|
351 | | - * to a fixed anchor point in the runtime image, either '_text' |
---|
352 | | - * for absolute address tables, in which case the linker will |
---|
353 | | - * emit the final addresses at build time. Otherwise, use the |
---|
354 | | - * offset relative to the lowest value encountered of all relative |
---|
355 | | - * symbols, and emit non-relocatable fixed offsets that will be fixed |
---|
356 | | - * up at runtime. |
---|
357 | | - * |
---|
358 | | - * The symbol names cannot be used to construct normal symbol |
---|
359 | | - * references as the list of symbols contains symbols that are |
---|
360 | | - * declared static and are private to their .o files. This prevents |
---|
361 | | - * .tmp_kallsyms.o or any other object from referencing them. |
---|
362 | | - */ |
---|
363 | 405 | if (!base_relative) |
---|
364 | 406 | output_label("kallsyms_addresses"); |
---|
365 | 407 | else |
---|
.. | .. |
---|
367 | 409 | |
---|
368 | 410 | for (i = 0; i < table_cnt; i++) { |
---|
369 | 411 | if (base_relative) { |
---|
| 412 | + /* |
---|
| 413 | + * Use the offset relative to the lowest value |
---|
| 414 | + * encountered of all relative symbols, and emit |
---|
| 415 | + * non-relocatable fixed offsets that will be fixed |
---|
| 416 | + * up at runtime. |
---|
| 417 | + */ |
---|
| 418 | + |
---|
370 | 419 | long long offset; |
---|
371 | 420 | int overflow; |
---|
372 | 421 | |
---|
373 | 422 | if (!absolute_percpu) { |
---|
374 | | - offset = table[i].addr - relative_base; |
---|
| 423 | + offset = table[i]->addr - relative_base; |
---|
375 | 424 | overflow = (offset < 0 || offset > UINT_MAX); |
---|
376 | | - } else if (symbol_absolute(&table[i])) { |
---|
377 | | - offset = table[i].addr; |
---|
| 425 | + } else if (symbol_absolute(table[i])) { |
---|
| 426 | + offset = table[i]->addr; |
---|
378 | 427 | overflow = (offset < 0 || offset > INT_MAX); |
---|
379 | 428 | } else { |
---|
380 | | - offset = relative_base - table[i].addr - 1; |
---|
| 429 | + offset = relative_base - table[i]->addr - 1; |
---|
381 | 430 | overflow = (offset < INT_MIN || offset >= 0); |
---|
382 | 431 | } |
---|
383 | 432 | if (overflow) { |
---|
384 | 433 | fprintf(stderr, "kallsyms failure: " |
---|
385 | 434 | "%s symbol value %#llx out of range in relative mode\n", |
---|
386 | | - symbol_absolute(&table[i]) ? "absolute" : "relative", |
---|
387 | | - table[i].addr); |
---|
| 435 | + symbol_absolute(table[i]) ? "absolute" : "relative", |
---|
| 436 | + table[i]->addr); |
---|
388 | 437 | exit(EXIT_FAILURE); |
---|
389 | 438 | } |
---|
390 | 439 | printf("\t.long\t%#x\n", (int)offset); |
---|
391 | | - } else if (!symbol_absolute(&table[i])) { |
---|
392 | | - if (_text <= table[i].addr) |
---|
393 | | - printf("\tPTR\t_text + %#llx\n", |
---|
394 | | - table[i].addr - _text); |
---|
395 | | - else |
---|
396 | | - printf("\tPTR\t_text - %#llx\n", |
---|
397 | | - _text - table[i].addr); |
---|
| 440 | + } else if (!symbol_absolute(table[i])) { |
---|
| 441 | + output_address(table[i]->addr); |
---|
398 | 442 | } else { |
---|
399 | | - printf("\tPTR\t%#llx\n", table[i].addr); |
---|
| 443 | + printf("\tPTR\t%#llx\n", table[i]->addr); |
---|
400 | 444 | } |
---|
401 | 445 | } |
---|
402 | 446 | printf("\n"); |
---|
403 | 447 | |
---|
404 | 448 | if (base_relative) { |
---|
405 | 449 | output_label("kallsyms_relative_base"); |
---|
406 | | - printf("\tPTR\t_text - %#llx\n", _text - relative_base); |
---|
| 450 | + output_address(relative_base); |
---|
407 | 451 | printf("\n"); |
---|
408 | 452 | } |
---|
409 | 453 | |
---|
410 | 454 | output_label("kallsyms_num_syms"); |
---|
411 | | - printf("\tPTR\t%u\n", table_cnt); |
---|
| 455 | + printf("\t.long\t%u\n", table_cnt); |
---|
412 | 456 | printf("\n"); |
---|
413 | 457 | |
---|
414 | 458 | /* table of offset markers, that give the offset in the compressed stream |
---|
.. | .. |
---|
426 | 470 | if ((i & 0xFF) == 0) |
---|
427 | 471 | markers[i >> 8] = off; |
---|
428 | 472 | |
---|
429 | | - printf("\t.byte 0x%02x", table[i].len); |
---|
430 | | - for (k = 0; k < table[i].len; k++) |
---|
431 | | - printf(", 0x%02x", table[i].sym[k]); |
---|
| 473 | + printf("\t.byte 0x%02x", table[i]->len); |
---|
| 474 | + for (k = 0; k < table[i]->len; k++) |
---|
| 475 | + printf(", 0x%02x", table[i]->sym[k]); |
---|
432 | 476 | printf("\n"); |
---|
433 | 477 | |
---|
434 | | - off += table[i].len + 1; |
---|
| 478 | + off += table[i]->len + 1; |
---|
435 | 479 | } |
---|
436 | 480 | printf("\n"); |
---|
437 | 481 | |
---|
438 | 482 | output_label("kallsyms_markers"); |
---|
439 | 483 | for (i = 0; i < ((table_cnt + 255) >> 8); i++) |
---|
440 | | - printf("\tPTR\t%d\n", markers[i]); |
---|
| 484 | + printf("\t.long\t%u\n", markers[i]); |
---|
441 | 485 | printf("\n"); |
---|
442 | 486 | |
---|
443 | 487 | free(markers); |
---|
.. | .. |
---|
462 | 506 | /* table lookup compression functions */ |
---|
463 | 507 | |
---|
464 | 508 | /* count all the possible tokens in a symbol */ |
---|
465 | | -static void learn_symbol(unsigned char *symbol, int len) |
---|
| 509 | +static void learn_symbol(const unsigned char *symbol, int len) |
---|
466 | 510 | { |
---|
467 | 511 | int i; |
---|
468 | 512 | |
---|
.. | .. |
---|
471 | 515 | } |
---|
472 | 516 | |
---|
473 | 517 | /* decrease the count for all the possible tokens in a symbol */ |
---|
474 | | -static void forget_symbol(unsigned char *symbol, int len) |
---|
| 518 | +static void forget_symbol(const unsigned char *symbol, int len) |
---|
475 | 519 | { |
---|
476 | 520 | int i; |
---|
477 | 521 | |
---|
.. | .. |
---|
479 | 523 | token_profit[ symbol[i] + (symbol[i + 1] << 8) ]--; |
---|
480 | 524 | } |
---|
481 | 525 | |
---|
482 | | -/* remove all the invalid symbols from the table and do the initial token count */ |
---|
| 526 | +/* do the initial token count */ |
---|
483 | 527 | static void build_initial_tok_table(void) |
---|
484 | 528 | { |
---|
485 | | - unsigned int i, pos; |
---|
| 529 | + unsigned int i; |
---|
486 | 530 | |
---|
487 | | - pos = 0; |
---|
488 | | - for (i = 0; i < table_cnt; i++) { |
---|
489 | | - if ( symbol_valid(&table[i]) ) { |
---|
490 | | - if (pos != i) |
---|
491 | | - table[pos] = table[i]; |
---|
492 | | - learn_symbol(table[pos].sym, table[pos].len); |
---|
493 | | - pos++; |
---|
494 | | - } else { |
---|
495 | | - free(table[i].sym); |
---|
496 | | - } |
---|
497 | | - } |
---|
498 | | - table_cnt = pos; |
---|
| 531 | + for (i = 0; i < table_cnt; i++) |
---|
| 532 | + learn_symbol(table[i]->sym, table[i]->len); |
---|
499 | 533 | } |
---|
500 | 534 | |
---|
501 | | -static void *find_token(unsigned char *str, int len, unsigned char *token) |
---|
| 535 | +static unsigned char *find_token(unsigned char *str, int len, |
---|
| 536 | + const unsigned char *token) |
---|
502 | 537 | { |
---|
503 | 538 | int i; |
---|
504 | 539 | |
---|
.. | .. |
---|
511 | 546 | |
---|
512 | 547 | /* replace a given token in all the valid symbols. Use the sampled symbols |
---|
513 | 548 | * to update the counts */ |
---|
514 | | -static void compress_symbols(unsigned char *str, int idx) |
---|
| 549 | +static void compress_symbols(const unsigned char *str, int idx) |
---|
515 | 550 | { |
---|
516 | 551 | unsigned int i, len, size; |
---|
517 | 552 | unsigned char *p1, *p2; |
---|
518 | 553 | |
---|
519 | 554 | for (i = 0; i < table_cnt; i++) { |
---|
520 | 555 | |
---|
521 | | - len = table[i].len; |
---|
522 | | - p1 = table[i].sym; |
---|
| 556 | + len = table[i]->len; |
---|
| 557 | + p1 = table[i]->sym; |
---|
523 | 558 | |
---|
524 | 559 | /* find the token on the symbol */ |
---|
525 | 560 | p2 = find_token(p1, len, str); |
---|
526 | 561 | if (!p2) continue; |
---|
527 | 562 | |
---|
528 | 563 | /* decrease the counts for this symbol's tokens */ |
---|
529 | | - forget_symbol(table[i].sym, len); |
---|
| 564 | + forget_symbol(table[i]->sym, len); |
---|
530 | 565 | |
---|
531 | 566 | size = len; |
---|
532 | 567 | |
---|
.. | .. |
---|
545 | 580 | |
---|
546 | 581 | } while (p2); |
---|
547 | 582 | |
---|
548 | | - table[i].len = len; |
---|
| 583 | + table[i]->len = len; |
---|
549 | 584 | |
---|
550 | 585 | /* increase the counts for this symbol's new tokens */ |
---|
551 | | - learn_symbol(table[i].sym, len); |
---|
| 586 | + learn_symbol(table[i]->sym, len); |
---|
552 | 587 | } |
---|
553 | 588 | } |
---|
554 | 589 | |
---|
.. | .. |
---|
603 | 638 | { |
---|
604 | 639 | unsigned int i, j, c; |
---|
605 | 640 | |
---|
606 | | - memset(best_table, 0, sizeof(best_table)); |
---|
607 | | - memset(best_table_len, 0, sizeof(best_table_len)); |
---|
608 | | - |
---|
609 | 641 | for (i = 0; i < table_cnt; i++) { |
---|
610 | | - for (j = 0; j < table[i].len; j++) { |
---|
611 | | - c = table[i].sym[j]; |
---|
| 642 | + for (j = 0; j < table[i]->len; j++) { |
---|
| 643 | + c = table[i]->sym[j]; |
---|
612 | 644 | best_table[c][0]=c; |
---|
613 | 645 | best_table_len[c]=1; |
---|
614 | 646 | } |
---|
.. | .. |
---|
621 | 653 | |
---|
622 | 654 | insert_real_symbols_in_table(); |
---|
623 | 655 | |
---|
624 | | - /* When valid symbol is not registered, exit to error */ |
---|
625 | | - if (!table_cnt) { |
---|
626 | | - fprintf(stderr, "No valid symbol.\n"); |
---|
627 | | - exit(1); |
---|
628 | | - } |
---|
629 | | - |
---|
630 | 656 | optimize_result(); |
---|
631 | 657 | } |
---|
632 | 658 | |
---|
633 | 659 | /* guess for "linker script provide" symbol */ |
---|
634 | 660 | static int may_be_linker_script_provide_symbol(const struct sym_entry *se) |
---|
635 | 661 | { |
---|
636 | | - const char *symbol = (char *)se->sym + 1; |
---|
| 662 | + const char *symbol = sym_name(se); |
---|
637 | 663 | int len = se->len - 1; |
---|
638 | 664 | |
---|
639 | 665 | if (len < 8) |
---|
.. | .. |
---|
665 | 691 | return 0; |
---|
666 | 692 | } |
---|
667 | 693 | |
---|
668 | | -static int prefix_underscores_count(const char *str) |
---|
669 | | -{ |
---|
670 | | - const char *tail = str; |
---|
671 | | - |
---|
672 | | - while (*tail == '_') |
---|
673 | | - tail++; |
---|
674 | | - |
---|
675 | | - return tail - str; |
---|
676 | | -} |
---|
677 | | - |
---|
678 | 694 | static int compare_symbols(const void *a, const void *b) |
---|
679 | 695 | { |
---|
680 | | - const struct sym_entry *sa; |
---|
681 | | - const struct sym_entry *sb; |
---|
| 696 | + const struct sym_entry *sa = *(const struct sym_entry **)a; |
---|
| 697 | + const struct sym_entry *sb = *(const struct sym_entry **)b; |
---|
682 | 698 | int wa, wb; |
---|
683 | | - |
---|
684 | | - sa = a; |
---|
685 | | - sb = b; |
---|
686 | 699 | |
---|
687 | 700 | /* sort by address first */ |
---|
688 | 701 | if (sa->addr > sb->addr) |
---|
.. | .. |
---|
703 | 716 | return wa - wb; |
---|
704 | 717 | |
---|
705 | 718 | /* sort by the number of prefix underscores */ |
---|
706 | | - wa = prefix_underscores_count((const char *)sa->sym + 1); |
---|
707 | | - wb = prefix_underscores_count((const char *)sb->sym + 1); |
---|
| 719 | + wa = strspn(sym_name(sa), "_"); |
---|
| 720 | + wb = strspn(sym_name(sb), "_"); |
---|
708 | 721 | if (wa != wb) |
---|
709 | 722 | return wa - wb; |
---|
710 | 723 | |
---|
.. | .. |
---|
714 | 727 | |
---|
715 | 728 | static void sort_symbols(void) |
---|
716 | 729 | { |
---|
717 | | - qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols); |
---|
| 730 | + qsort(table, table_cnt, sizeof(table[0]), compare_symbols); |
---|
718 | 731 | } |
---|
719 | 732 | |
---|
720 | 733 | static void make_percpus_absolute(void) |
---|
.. | .. |
---|
722 | 735 | unsigned int i; |
---|
723 | 736 | |
---|
724 | 737 | for (i = 0; i < table_cnt; i++) |
---|
725 | | - if (symbol_in_range(&table[i], &percpu_range, 1)) { |
---|
| 738 | + if (symbol_in_range(table[i], &percpu_range, 1)) { |
---|
726 | 739 | /* |
---|
727 | 740 | * Keep the 'A' override for percpu symbols to |
---|
728 | 741 | * ensure consistent behavior compared to older |
---|
729 | 742 | * versions of this tool. |
---|
730 | 743 | */ |
---|
731 | | - table[i].sym[0] = 'A'; |
---|
732 | | - table[i].percpu_absolute = 1; |
---|
| 744 | + table[i]->sym[0] = 'A'; |
---|
| 745 | + table[i]->percpu_absolute = 1; |
---|
733 | 746 | } |
---|
734 | 747 | } |
---|
735 | 748 | |
---|
.. | .. |
---|
738 | 751 | { |
---|
739 | 752 | unsigned int i; |
---|
740 | 753 | |
---|
741 | | - relative_base = -1ULL; |
---|
742 | 754 | for (i = 0; i < table_cnt; i++) |
---|
743 | | - if (!symbol_absolute(&table[i]) && |
---|
744 | | - table[i].addr < relative_base) |
---|
745 | | - relative_base = table[i].addr; |
---|
| 755 | + if (!symbol_absolute(table[i])) { |
---|
| 756 | + /* |
---|
| 757 | + * The table is sorted by address. |
---|
| 758 | + * Take the first non-absolute symbol value. |
---|
| 759 | + */ |
---|
| 760 | + relative_base = table[i]->addr; |
---|
| 761 | + return; |
---|
| 762 | + } |
---|
746 | 763 | } |
---|
747 | 764 | |
---|
748 | 765 | int main(int argc, char **argv) |
---|
.. | .. |
---|
763 | 780 | usage(); |
---|
764 | 781 | |
---|
765 | 782 | read_map(stdin); |
---|
| 783 | + shrink_table(); |
---|
766 | 784 | if (absolute_percpu) |
---|
767 | 785 | make_percpus_absolute(); |
---|
| 786 | + sort_symbols(); |
---|
768 | 787 | if (base_relative) |
---|
769 | 788 | record_relative_base(); |
---|
770 | | - sort_symbols(); |
---|
771 | 789 | optimize_token_table(); |
---|
772 | 790 | write_src(); |
---|
773 | 791 | |
---|