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