x86-32, relocs: Whitelist more symbols for ld bug workaround
[pandora-kernel.git] / arch / x86 / tools / relocs.c
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <stdlib.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <unistd.h>
8 #include <elf.h>
9 #include <byteswap.h>
10 #define USE_BSD
11 #include <endian.h>
12 #include <regex.h>
13
14 static void die(char *fmt, ...);
15
16 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
17 static Elf32_Ehdr ehdr;
18 static unsigned long reloc_count, reloc_idx;
19 static unsigned long *relocs;
20 static unsigned long reloc16_count, reloc16_idx;
21 static unsigned long *relocs16;
22
23 struct section {
24         Elf32_Shdr     shdr;
25         struct section *link;
26         Elf32_Sym      *symtab;
27         Elf32_Rel      *reltab;
28         char           *strtab;
29 };
30 static struct section *secs;
31
32 enum symtype {
33         S_ABS,
34         S_REL,
35         S_SEG,
36         S_LIN,
37         S_NSYMTYPES
38 };
39
40 static const char * const sym_regex_kernel[S_NSYMTYPES] = {
41 /*
42  * Following symbols have been audited. There values are constant and do
43  * not change if bzImage is loaded at a different physical address than
44  * the address for which it has been compiled. Don't warn user about
45  * absolute relocations present w.r.t these symbols.
46  */
47         [S_ABS] =
48         "^(xen_irq_disable_direct_reloc$|"
49         "xen_save_fl_direct_reloc$|"
50         "VDSO|"
51         "__crc_)",
52
53 /*
54  * These symbols are known to be relative, even if the linker marks them
55  * as absolute (typically defined outside any section in the linker script.)
56  */
57         [S_REL] =
58         "^(__init_(begin|end)|"
59         "__x86_cpu_dev_(start|end)|"
60         "(__parainstructions|__alt_instructions)(|_end)|"
61         "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|"
62         "__(start|end)_pci_.*|"
63         "__(start|end)_builtin_fw|"
64         "__(start|stop)___ksymtab(|_gpl|_unused|_unused_gpl|_gpl_future)|"
65         "__(start|stop)___kcrctab(|_gpl|_unused|_unused_gpl|_gpl_future)|"
66         "__(start|stop)___param|"
67         "__(start|stop)___modver|"
68         "__(start|stop)___bug_table|"
69         "__tracedata_(start|end)|"
70         "__(start|stop)_notes|"
71         "__end_rodata|"
72         "__initramfs_start|"
73         "_end)$"
74 };
75
76
77 static const char * const sym_regex_realmode[S_NSYMTYPES] = {
78 /*
79  * These are 16-bit segment symbols when compiling 16-bit code.
80  */
81         [S_SEG] =
82         "^real_mode_seg$",
83
84 /*
85  * These are offsets belonging to segments, as opposed to linear addresses,
86  * when compiling 16-bit code.
87  */
88         [S_LIN] =
89         "^pa_",
90 };
91
92 static const char * const *sym_regex;
93
94 static regex_t sym_regex_c[S_NSYMTYPES];
95 static int is_reloc(enum symtype type, const char *sym_name)
96 {
97         return sym_regex[type] &&
98                 !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0);
99 }
100
101 static void regex_init(int use_real_mode)
102 {
103         char errbuf[128];
104         int err;
105         int i;
106
107         if (use_real_mode)
108                 sym_regex = sym_regex_realmode;
109         else
110                 sym_regex = sym_regex_kernel;
111
112         for (i = 0; i < S_NSYMTYPES; i++) {
113                 if (!sym_regex[i])
114                         continue;
115
116                 err = regcomp(&sym_regex_c[i], sym_regex[i],
117                               REG_EXTENDED|REG_NOSUB);
118
119                 if (err) {
120                         regerror(err, &sym_regex_c[i], errbuf, sizeof errbuf);
121                         die("%s", errbuf);
122                 }
123         }
124 }
125
126 static void die(char *fmt, ...)
127 {
128         va_list ap;
129         va_start(ap, fmt);
130         vfprintf(stderr, fmt, ap);
131         va_end(ap);
132         exit(1);
133 }
134
135 static const char *sym_type(unsigned type)
136 {
137         static const char *type_name[] = {
138 #define SYM_TYPE(X) [X] = #X
139                 SYM_TYPE(STT_NOTYPE),
140                 SYM_TYPE(STT_OBJECT),
141                 SYM_TYPE(STT_FUNC),
142                 SYM_TYPE(STT_SECTION),
143                 SYM_TYPE(STT_FILE),
144                 SYM_TYPE(STT_COMMON),
145                 SYM_TYPE(STT_TLS),
146 #undef SYM_TYPE
147         };
148         const char *name = "unknown sym type name";
149         if (type < ARRAY_SIZE(type_name)) {
150                 name = type_name[type];
151         }
152         return name;
153 }
154
155 static const char *sym_bind(unsigned bind)
156 {
157         static const char *bind_name[] = {
158 #define SYM_BIND(X) [X] = #X
159                 SYM_BIND(STB_LOCAL),
160                 SYM_BIND(STB_GLOBAL),
161                 SYM_BIND(STB_WEAK),
162 #undef SYM_BIND
163         };
164         const char *name = "unknown sym bind name";
165         if (bind < ARRAY_SIZE(bind_name)) {
166                 name = bind_name[bind];
167         }
168         return name;
169 }
170
171 static const char *sym_visibility(unsigned visibility)
172 {
173         static const char *visibility_name[] = {
174 #define SYM_VISIBILITY(X) [X] = #X
175                 SYM_VISIBILITY(STV_DEFAULT),
176                 SYM_VISIBILITY(STV_INTERNAL),
177                 SYM_VISIBILITY(STV_HIDDEN),
178                 SYM_VISIBILITY(STV_PROTECTED),
179 #undef SYM_VISIBILITY
180         };
181         const char *name = "unknown sym visibility name";
182         if (visibility < ARRAY_SIZE(visibility_name)) {
183                 name = visibility_name[visibility];
184         }
185         return name;
186 }
187
188 static const char *rel_type(unsigned type)
189 {
190         static const char *type_name[] = {
191 #define REL_TYPE(X) [X] = #X
192                 REL_TYPE(R_386_NONE),
193                 REL_TYPE(R_386_32),
194                 REL_TYPE(R_386_PC32),
195                 REL_TYPE(R_386_GOT32),
196                 REL_TYPE(R_386_PLT32),
197                 REL_TYPE(R_386_COPY),
198                 REL_TYPE(R_386_GLOB_DAT),
199                 REL_TYPE(R_386_JMP_SLOT),
200                 REL_TYPE(R_386_RELATIVE),
201                 REL_TYPE(R_386_GOTOFF),
202                 REL_TYPE(R_386_GOTPC),
203                 REL_TYPE(R_386_8),
204                 REL_TYPE(R_386_PC8),
205                 REL_TYPE(R_386_16),
206                 REL_TYPE(R_386_PC16),
207 #undef REL_TYPE
208         };
209         const char *name = "unknown type rel type name";
210         if (type < ARRAY_SIZE(type_name) && type_name[type]) {
211                 name = type_name[type];
212         }
213         return name;
214 }
215
216 static const char *sec_name(unsigned shndx)
217 {
218         const char *sec_strtab;
219         const char *name;
220         sec_strtab = secs[ehdr.e_shstrndx].strtab;
221         name = "<noname>";
222         if (shndx < ehdr.e_shnum) {
223                 name = sec_strtab + secs[shndx].shdr.sh_name;
224         }
225         else if (shndx == SHN_ABS) {
226                 name = "ABSOLUTE";
227         }
228         else if (shndx == SHN_COMMON) {
229                 name = "COMMON";
230         }
231         return name;
232 }
233
234 static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
235 {
236         const char *name;
237         name = "<noname>";
238         if (sym->st_name) {
239                 name = sym_strtab + sym->st_name;
240         }
241         else {
242                 name = sec_name(sym->st_shndx);
243         }
244         return name;
245 }
246
247
248
249 #if BYTE_ORDER == LITTLE_ENDIAN
250 #define le16_to_cpu(val) (val)
251 #define le32_to_cpu(val) (val)
252 #endif
253 #if BYTE_ORDER == BIG_ENDIAN
254 #define le16_to_cpu(val) bswap_16(val)
255 #define le32_to_cpu(val) bswap_32(val)
256 #endif
257
258 static uint16_t elf16_to_cpu(uint16_t val)
259 {
260         return le16_to_cpu(val);
261 }
262
263 static uint32_t elf32_to_cpu(uint32_t val)
264 {
265         return le32_to_cpu(val);
266 }
267
268 static void read_ehdr(FILE *fp)
269 {
270         if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
271                 die("Cannot read ELF header: %s\n",
272                         strerror(errno));
273         }
274         if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
275                 die("No ELF magic\n");
276         }
277         if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
278                 die("Not a 32 bit executable\n");
279         }
280         if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
281                 die("Not a LSB ELF executable\n");
282         }
283         if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
284                 die("Unknown ELF version\n");
285         }
286         /* Convert the fields to native endian */
287         ehdr.e_type      = elf16_to_cpu(ehdr.e_type);
288         ehdr.e_machine   = elf16_to_cpu(ehdr.e_machine);
289         ehdr.e_version   = elf32_to_cpu(ehdr.e_version);
290         ehdr.e_entry     = elf32_to_cpu(ehdr.e_entry);
291         ehdr.e_phoff     = elf32_to_cpu(ehdr.e_phoff);
292         ehdr.e_shoff     = elf32_to_cpu(ehdr.e_shoff);
293         ehdr.e_flags     = elf32_to_cpu(ehdr.e_flags);
294         ehdr.e_ehsize    = elf16_to_cpu(ehdr.e_ehsize);
295         ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
296         ehdr.e_phnum     = elf16_to_cpu(ehdr.e_phnum);
297         ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
298         ehdr.e_shnum     = elf16_to_cpu(ehdr.e_shnum);
299         ehdr.e_shstrndx  = elf16_to_cpu(ehdr.e_shstrndx);
300
301         if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
302                 die("Unsupported ELF header type\n");
303         }
304         if (ehdr.e_machine != EM_386) {
305                 die("Not for x86\n");
306         }
307         if (ehdr.e_version != EV_CURRENT) {
308                 die("Unknown ELF version\n");
309         }
310         if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
311                 die("Bad Elf header size\n");
312         }
313         if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
314                 die("Bad program header entry\n");
315         }
316         if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
317                 die("Bad section header entry\n");
318         }
319         if (ehdr.e_shstrndx >= ehdr.e_shnum) {
320                 die("String table index out of bounds\n");
321         }
322 }
323
324 static void read_shdrs(FILE *fp)
325 {
326         int i;
327         Elf32_Shdr shdr;
328
329         secs = calloc(ehdr.e_shnum, sizeof(struct section));
330         if (!secs) {
331                 die("Unable to allocate %d section headers\n",
332                     ehdr.e_shnum);
333         }
334         if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
335                 die("Seek to %d failed: %s\n",
336                         ehdr.e_shoff, strerror(errno));
337         }
338         for (i = 0; i < ehdr.e_shnum; i++) {
339                 struct section *sec = &secs[i];
340                 if (fread(&shdr, sizeof shdr, 1, fp) != 1)
341                         die("Cannot read ELF section headers %d/%d: %s\n",
342                             i, ehdr.e_shnum, strerror(errno));
343                 sec->shdr.sh_name      = elf32_to_cpu(shdr.sh_name);
344                 sec->shdr.sh_type      = elf32_to_cpu(shdr.sh_type);
345                 sec->shdr.sh_flags     = elf32_to_cpu(shdr.sh_flags);
346                 sec->shdr.sh_addr      = elf32_to_cpu(shdr.sh_addr);
347                 sec->shdr.sh_offset    = elf32_to_cpu(shdr.sh_offset);
348                 sec->shdr.sh_size      = elf32_to_cpu(shdr.sh_size);
349                 sec->shdr.sh_link      = elf32_to_cpu(shdr.sh_link);
350                 sec->shdr.sh_info      = elf32_to_cpu(shdr.sh_info);
351                 sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
352                 sec->shdr.sh_entsize   = elf32_to_cpu(shdr.sh_entsize);
353                 if (sec->shdr.sh_link < ehdr.e_shnum)
354                         sec->link = &secs[sec->shdr.sh_link];
355         }
356
357 }
358
359 static void read_strtabs(FILE *fp)
360 {
361         int i;
362         for (i = 0; i < ehdr.e_shnum; i++) {
363                 struct section *sec = &secs[i];
364                 if (sec->shdr.sh_type != SHT_STRTAB) {
365                         continue;
366                 }
367                 sec->strtab = malloc(sec->shdr.sh_size);
368                 if (!sec->strtab) {
369                         die("malloc of %d bytes for strtab failed\n",
370                                 sec->shdr.sh_size);
371                 }
372                 if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
373                         die("Seek to %d failed: %s\n",
374                                 sec->shdr.sh_offset, strerror(errno));
375                 }
376                 if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
377                     != sec->shdr.sh_size) {
378                         die("Cannot read symbol table: %s\n",
379                                 strerror(errno));
380                 }
381         }
382 }
383
384 static void read_symtabs(FILE *fp)
385 {
386         int i,j;
387         for (i = 0; i < ehdr.e_shnum; i++) {
388                 struct section *sec = &secs[i];
389                 if (sec->shdr.sh_type != SHT_SYMTAB) {
390                         continue;
391                 }
392                 sec->symtab = malloc(sec->shdr.sh_size);
393                 if (!sec->symtab) {
394                         die("malloc of %d bytes for symtab failed\n",
395                                 sec->shdr.sh_size);
396                 }
397                 if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
398                         die("Seek to %d failed: %s\n",
399                                 sec->shdr.sh_offset, strerror(errno));
400                 }
401                 if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
402                     != sec->shdr.sh_size) {
403                         die("Cannot read symbol table: %s\n",
404                                 strerror(errno));
405                 }
406                 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
407                         Elf32_Sym *sym = &sec->symtab[j];
408                         sym->st_name  = elf32_to_cpu(sym->st_name);
409                         sym->st_value = elf32_to_cpu(sym->st_value);
410                         sym->st_size  = elf32_to_cpu(sym->st_size);
411                         sym->st_shndx = elf16_to_cpu(sym->st_shndx);
412                 }
413         }
414 }
415
416
417 static void read_relocs(FILE *fp)
418 {
419         int i,j;
420         for (i = 0; i < ehdr.e_shnum; i++) {
421                 struct section *sec = &secs[i];
422                 if (sec->shdr.sh_type != SHT_REL) {
423                         continue;
424                 }
425                 sec->reltab = malloc(sec->shdr.sh_size);
426                 if (!sec->reltab) {
427                         die("malloc of %d bytes for relocs failed\n",
428                                 sec->shdr.sh_size);
429                 }
430                 if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
431                         die("Seek to %d failed: %s\n",
432                                 sec->shdr.sh_offset, strerror(errno));
433                 }
434                 if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
435                     != sec->shdr.sh_size) {
436                         die("Cannot read symbol table: %s\n",
437                                 strerror(errno));
438                 }
439                 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
440                         Elf32_Rel *rel = &sec->reltab[j];
441                         rel->r_offset = elf32_to_cpu(rel->r_offset);
442                         rel->r_info   = elf32_to_cpu(rel->r_info);
443                 }
444         }
445 }
446
447
448 static void print_absolute_symbols(void)
449 {
450         int i;
451         printf("Absolute symbols\n");
452         printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
453         for (i = 0; i < ehdr.e_shnum; i++) {
454                 struct section *sec = &secs[i];
455                 char *sym_strtab;
456                 int j;
457
458                 if (sec->shdr.sh_type != SHT_SYMTAB) {
459                         continue;
460                 }
461                 sym_strtab = sec->link->strtab;
462                 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
463                         Elf32_Sym *sym;
464                         const char *name;
465                         sym = &sec->symtab[j];
466                         name = sym_name(sym_strtab, sym);
467                         if (sym->st_shndx != SHN_ABS) {
468                                 continue;
469                         }
470                         printf("%5d %08x %5d %10s %10s %12s %s\n",
471                                 j, sym->st_value, sym->st_size,
472                                 sym_type(ELF32_ST_TYPE(sym->st_info)),
473                                 sym_bind(ELF32_ST_BIND(sym->st_info)),
474                                 sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
475                                 name);
476                 }
477         }
478         printf("\n");
479 }
480
481 static void print_absolute_relocs(void)
482 {
483         int i, printed = 0;
484
485         for (i = 0; i < ehdr.e_shnum; i++) {
486                 struct section *sec = &secs[i];
487                 struct section *sec_applies, *sec_symtab;
488                 char *sym_strtab;
489                 Elf32_Sym *sh_symtab;
490                 int j;
491                 if (sec->shdr.sh_type != SHT_REL) {
492                         continue;
493                 }
494                 sec_symtab  = sec->link;
495                 sec_applies = &secs[sec->shdr.sh_info];
496                 if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
497                         continue;
498                 }
499                 sh_symtab  = sec_symtab->symtab;
500                 sym_strtab = sec_symtab->link->strtab;
501                 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
502                         Elf32_Rel *rel;
503                         Elf32_Sym *sym;
504                         const char *name;
505                         rel = &sec->reltab[j];
506                         sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
507                         name = sym_name(sym_strtab, sym);
508                         if (sym->st_shndx != SHN_ABS) {
509                                 continue;
510                         }
511
512                         /* Absolute symbols are not relocated if bzImage is
513                          * loaded at a non-compiled address. Display a warning
514                          * to user at compile time about the absolute
515                          * relocations present.
516                          *
517                          * User need to audit the code to make sure
518                          * some symbols which should have been section
519                          * relative have not become absolute because of some
520                          * linker optimization or wrong programming usage.
521                          *
522                          * Before warning check if this absolute symbol
523                          * relocation is harmless.
524                          */
525                         if (is_reloc(S_ABS, name) || is_reloc(S_REL, name))
526                                 continue;
527
528                         if (!printed) {
529                                 printf("WARNING: Absolute relocations"
530                                         " present\n");
531                                 printf("Offset     Info     Type     Sym.Value "
532                                         "Sym.Name\n");
533                                 printed = 1;
534                         }
535
536                         printf("%08x %08x %10s %08x  %s\n",
537                                 rel->r_offset,
538                                 rel->r_info,
539                                 rel_type(ELF32_R_TYPE(rel->r_info)),
540                                 sym->st_value,
541                                 name);
542                 }
543         }
544
545         if (printed)
546                 printf("\n");
547 }
548
549 static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym),
550                         int use_real_mode)
551 {
552         int i;
553         /* Walk through the relocations */
554         for (i = 0; i < ehdr.e_shnum; i++) {
555                 char *sym_strtab;
556                 Elf32_Sym *sh_symtab;
557                 struct section *sec_applies, *sec_symtab;
558                 int j;
559                 struct section *sec = &secs[i];
560
561                 if (sec->shdr.sh_type != SHT_REL) {
562                         continue;
563                 }
564                 sec_symtab  = sec->link;
565                 sec_applies = &secs[sec->shdr.sh_info];
566                 if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
567                         continue;
568                 }
569                 sh_symtab = sec_symtab->symtab;
570                 sym_strtab = sec_symtab->link->strtab;
571                 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
572                         Elf32_Rel *rel;
573                         Elf32_Sym *sym;
574                         unsigned r_type;
575                         const char *symname;
576                         int shn_abs;
577
578                         rel = &sec->reltab[j];
579                         sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
580                         r_type = ELF32_R_TYPE(rel->r_info);
581
582                         shn_abs = sym->st_shndx == SHN_ABS;
583
584                         switch (r_type) {
585                         case R_386_NONE:
586                         case R_386_PC32:
587                         case R_386_PC16:
588                         case R_386_PC8:
589                                 /*
590                                  * NONE can be ignored and and PC relative
591                                  * relocations don't need to be adjusted.
592                                  */
593                                 break;
594
595                         case R_386_16:
596                                 symname = sym_name(sym_strtab, sym);
597                                 if (!use_real_mode)
598                                         goto bad;
599                                 if (shn_abs) {
600                                         if (is_reloc(S_ABS, symname))
601                                                 break;
602                                         else if (!is_reloc(S_SEG, symname))
603                                                 goto bad;
604                                 } else {
605                                         if (is_reloc(S_LIN, symname))
606                                                 goto bad;
607                                         else
608                                                 break;
609                                 }
610                                 visit(rel, sym);
611                                 break;
612
613                         case R_386_32:
614                                 symname = sym_name(sym_strtab, sym);
615                                 if (shn_abs) {
616                                         if (is_reloc(S_ABS, symname))
617                                                 break;
618                                         else if (!is_reloc(S_REL, symname))
619                                                 goto bad;
620                                 } else {
621                                         if (use_real_mode &&
622                                             !is_reloc(S_LIN, symname))
623                                                 break;
624                                 }
625                                 visit(rel, sym);
626                                 break;
627                         default:
628                                 die("Unsupported relocation type: %s (%d)\n",
629                                     rel_type(r_type), r_type);
630                                 break;
631                         bad:
632                                 symname = sym_name(sym_strtab, sym);
633                                 die("Invalid %s %s relocation: %s\n",
634                                     shn_abs ? "absolute" : "relative",
635                                     rel_type(r_type), symname);
636                         }
637                 }
638         }
639 }
640
641 static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
642 {
643         if (ELF32_R_TYPE(rel->r_info) == R_386_16)
644                 reloc16_count++;
645         else
646                 reloc_count++;
647 }
648
649 static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
650 {
651         /* Remember the address that needs to be adjusted. */
652         if (ELF32_R_TYPE(rel->r_info) == R_386_16)
653                 relocs16[reloc16_idx++] = rel->r_offset;
654         else
655                 relocs[reloc_idx++] = rel->r_offset;
656 }
657
658 static int cmp_relocs(const void *va, const void *vb)
659 {
660         const unsigned long *a, *b;
661         a = va; b = vb;
662         return (*a == *b)? 0 : (*a > *b)? 1 : -1;
663 }
664
665 static int write32(unsigned int v, FILE *f)
666 {
667         unsigned char buf[4];
668
669         buf[0] = (v >>  0) & 0xff;
670         buf[1] = (v >>  8) & 0xff;
671         buf[2] = (v >> 16) & 0xff;
672         buf[3] = (v >> 24) & 0xff;
673         return fwrite(buf, 1, 4, f) == 4 ? 0 : -1;
674 }
675
676 static void emit_relocs(int as_text, int use_real_mode)
677 {
678         int i;
679         /* Count how many relocations I have and allocate space for them. */
680         reloc_count = 0;
681         walk_relocs(count_reloc, use_real_mode);
682         relocs = malloc(reloc_count * sizeof(relocs[0]));
683         if (!relocs) {
684                 die("malloc of %d entries for relocs failed\n",
685                         reloc_count);
686         }
687
688         relocs16 = malloc(reloc16_count * sizeof(relocs[0]));
689         if (!relocs16) {
690                 die("malloc of %d entries for relocs16 failed\n",
691                         reloc16_count);
692         }
693         /* Collect up the relocations */
694         reloc_idx = 0;
695         walk_relocs(collect_reloc, use_real_mode);
696
697         if (reloc16_count && !use_real_mode)
698                 die("Segment relocations found but --realmode not specified\n");
699
700         /* Order the relocations for more efficient processing */
701         qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
702         qsort(relocs16, reloc16_count, sizeof(relocs16[0]), cmp_relocs);
703
704         /* Print the relocations */
705         if (as_text) {
706                 /* Print the relocations in a form suitable that
707                  * gas will like.
708                  */
709                 printf(".section \".data.reloc\",\"a\"\n");
710                 printf(".balign 4\n");
711                 if (use_real_mode) {
712                         printf("\t.long %lu\n", reloc16_count);
713                         for (i = 0; i < reloc16_count; i++)
714                                 printf("\t.long 0x%08lx\n", relocs16[i]);
715                         printf("\t.long %lu\n", reloc_count);
716                         for (i = 0; i < reloc_count; i++) {
717                                 printf("\t.long 0x%08lx\n", relocs[i]);
718                         }
719                 } else {
720                         /* Print a stop */
721                         printf("\t.long 0x%08lx\n", (unsigned long)0);
722                         for (i = 0; i < reloc_count; i++) {
723                                 printf("\t.long 0x%08lx\n", relocs[i]);
724                         }
725                 }
726
727                 printf("\n");
728         }
729         else {
730                 if (use_real_mode) {
731                         write32(reloc16_count, stdout);
732                         for (i = 0; i < reloc16_count; i++)
733                                 write32(relocs16[i], stdout);
734                         write32(reloc_count, stdout);
735
736                         /* Now print each relocation */
737                         for (i = 0; i < reloc_count; i++)
738                                 write32(relocs[i], stdout);
739                 } else {
740                         /* Print a stop */
741                         write32(0, stdout);
742
743                         /* Now print each relocation */
744                         for (i = 0; i < reloc_count; i++) {
745                                 write32(relocs[i], stdout);
746                         }
747                 }
748         }
749 }
750
751 static void usage(void)
752 {
753         die("relocs [--abs-syms|--abs-relocs|--text|--realmode] vmlinux\n");
754 }
755
756 int main(int argc, char **argv)
757 {
758         int show_absolute_syms, show_absolute_relocs;
759         int as_text, use_real_mode;
760         const char *fname;
761         FILE *fp;
762         int i;
763
764         show_absolute_syms = 0;
765         show_absolute_relocs = 0;
766         as_text = 0;
767         use_real_mode = 0;
768         fname = NULL;
769         for (i = 1; i < argc; i++) {
770                 char *arg = argv[i];
771                 if (*arg == '-') {
772                         if (strcmp(arg, "--abs-syms") == 0) {
773                                 show_absolute_syms = 1;
774                                 continue;
775                         }
776                         if (strcmp(arg, "--abs-relocs") == 0) {
777                                 show_absolute_relocs = 1;
778                                 continue;
779                         }
780                         if (strcmp(arg, "--text") == 0) {
781                                 as_text = 1;
782                                 continue;
783                         }
784                         if (strcmp(arg, "--realmode") == 0) {
785                                 use_real_mode = 1;
786                                 continue;
787                         }
788                 }
789                 else if (!fname) {
790                         fname = arg;
791                         continue;
792                 }
793                 usage();
794         }
795         if (!fname) {
796                 usage();
797         }
798         regex_init(use_real_mode);
799         fp = fopen(fname, "r");
800         if (!fp) {
801                 die("Cannot open %s: %s\n",
802                         fname, strerror(errno));
803         }
804         read_ehdr(fp);
805         read_shdrs(fp);
806         read_strtabs(fp);
807         read_symtabs(fp);
808         read_relocs(fp);
809         if (show_absolute_syms) {
810                 print_absolute_symbols();
811                 return 0;
812         }
813         if (show_absolute_relocs) {
814                 print_absolute_relocs();
815                 return 0;
816         }
817         emit_relocs(as_text, use_real_mode);
818         return 0;
819 }