linux/arch/x86/boot/compressed/relocs.c
<<
>>
Prefs
   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
  13#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  14static Elf32_Ehdr ehdr;
  15static unsigned long reloc_count, reloc_idx;
  16static unsigned long *relocs;
  17
  18struct section {
  19        Elf32_Shdr     shdr;
  20        struct section *link;
  21        Elf32_Sym      *symtab;
  22        Elf32_Rel      *reltab;
  23        char           *strtab;
  24};
  25static struct section *secs;
  26
  27/*
  28 * Following symbols have been audited. There values are constant and do
  29 * not change if bzImage is loaded at a different physical address than
  30 * the address for which it has been compiled. Don't warn user about
  31 * absolute relocations present w.r.t these symbols.
  32 */
  33static const char* safe_abs_relocs[] = {
  34                "xen_irq_disable_direct_reloc",
  35                "xen_save_fl_direct_reloc",
  36};
  37
  38static int is_safe_abs_reloc(const char* sym_name)
  39{
  40        int i;
  41
  42        for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
  43                if (!strcmp(sym_name, safe_abs_relocs[i]))
  44                        /* Match found */
  45                        return 1;
  46        }
  47        if (strncmp(sym_name, "VDSO", 4) == 0)
  48                return 1;
  49        if (strncmp(sym_name, "__crc_", 6) == 0)
  50                return 1;
  51        return 0;
  52}
  53
  54static void die(char *fmt, ...)
  55{
  56        va_list ap;
  57        va_start(ap, fmt);
  58        vfprintf(stderr, fmt, ap);
  59        va_end(ap);
  60        exit(1);
  61}
  62
  63static const char *sym_type(unsigned type)
  64{
  65        static const char *type_name[] = {
  66#define SYM_TYPE(X) [X] = #X
  67                SYM_TYPE(STT_NOTYPE),
  68                SYM_TYPE(STT_OBJECT),
  69                SYM_TYPE(STT_FUNC),
  70                SYM_TYPE(STT_SECTION),
  71                SYM_TYPE(STT_FILE),
  72                SYM_TYPE(STT_COMMON),
  73                SYM_TYPE(STT_TLS),
  74#undef SYM_TYPE
  75        };
  76        const char *name = "unknown sym type name";
  77        if (type < ARRAY_SIZE(type_name)) {
  78                name = type_name[type];
  79        }
  80        return name;
  81}
  82
  83static const char *sym_bind(unsigned bind)
  84{
  85        static const char *bind_name[] = {
  86#define SYM_BIND(X) [X] = #X
  87                SYM_BIND(STB_LOCAL),
  88                SYM_BIND(STB_GLOBAL),
  89                SYM_BIND(STB_WEAK),
  90#undef SYM_BIND
  91        };
  92        const char *name = "unknown sym bind name";
  93        if (bind < ARRAY_SIZE(bind_name)) {
  94                name = bind_name[bind];
  95        }
  96        return name;
  97}
  98
  99static const char *sym_visibility(unsigned visibility)
 100{
 101        static const char *visibility_name[] = {
 102#define SYM_VISIBILITY(X) [X] = #X
 103                SYM_VISIBILITY(STV_DEFAULT),
 104                SYM_VISIBILITY(STV_INTERNAL),
 105                SYM_VISIBILITY(STV_HIDDEN),
 106                SYM_VISIBILITY(STV_PROTECTED),
 107#undef SYM_VISIBILITY
 108        };
 109        const char *name = "unknown sym visibility name";
 110        if (visibility < ARRAY_SIZE(visibility_name)) {
 111                name = visibility_name[visibility];
 112        }
 113        return name;
 114}
 115
 116static const char *rel_type(unsigned type)
 117{
 118        static const char *type_name[] = {
 119#define REL_TYPE(X) [X] = #X
 120                REL_TYPE(R_386_NONE),
 121                REL_TYPE(R_386_32),
 122                REL_TYPE(R_386_PC32),
 123                REL_TYPE(R_386_GOT32),
 124                REL_TYPE(R_386_PLT32),
 125                REL_TYPE(R_386_COPY),
 126                REL_TYPE(R_386_GLOB_DAT),
 127                REL_TYPE(R_386_JMP_SLOT),
 128                REL_TYPE(R_386_RELATIVE),
 129                REL_TYPE(R_386_GOTOFF),
 130                REL_TYPE(R_386_GOTPC),
 131#undef REL_TYPE
 132        };
 133        const char *name = "unknown type rel type name";
 134        if (type < ARRAY_SIZE(type_name)) {
 135                name = type_name[type];
 136        }
 137        return name;
 138}
 139
 140static const char *sec_name(unsigned shndx)
 141{
 142        const char *sec_strtab;
 143        const char *name;
 144        sec_strtab = secs[ehdr.e_shstrndx].strtab;
 145        name = "<noname>";
 146        if (shndx < ehdr.e_shnum) {
 147                name = sec_strtab + secs[shndx].shdr.sh_name;
 148        }
 149        else if (shndx == SHN_ABS) {
 150                name = "ABSOLUTE";
 151        }
 152        else if (shndx == SHN_COMMON) {
 153                name = "COMMON";
 154        }
 155        return name;
 156}
 157
 158static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
 159{
 160        const char *name;
 161        name = "<noname>";
 162        if (sym->st_name) {
 163                name = sym_strtab + sym->st_name;
 164        }
 165        else {
 166                name = sec_name(secs[sym->st_shndx].shdr.sh_name);
 167        }
 168        return name;
 169}
 170
 171
 172
 173#if BYTE_ORDER == LITTLE_ENDIAN
 174#define le16_to_cpu(val) (val)
 175#define le32_to_cpu(val) (val)
 176#endif
 177#if BYTE_ORDER == BIG_ENDIAN
 178#define le16_to_cpu(val) bswap_16(val)
 179#define le32_to_cpu(val) bswap_32(val)
 180#endif
 181
 182static uint16_t elf16_to_cpu(uint16_t val)
 183{
 184        return le16_to_cpu(val);
 185}
 186
 187static uint32_t elf32_to_cpu(uint32_t val)
 188{
 189        return le32_to_cpu(val);
 190}
 191
 192static void read_ehdr(FILE *fp)
 193{
 194        if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
 195                die("Cannot read ELF header: %s\n",
 196                        strerror(errno));
 197        }
 198        if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
 199                die("No ELF magic\n");
 200        }
 201        if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
 202                die("Not a 32 bit executable\n");
 203        }
 204        if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
 205                die("Not a LSB ELF executable\n");
 206        }
 207        if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
 208                die("Unknown ELF version\n");
 209        }
 210        /* Convert the fields to native endian */
 211        ehdr.e_type      = elf16_to_cpu(ehdr.e_type);
 212        ehdr.e_machine   = elf16_to_cpu(ehdr.e_machine);
 213        ehdr.e_version   = elf32_to_cpu(ehdr.e_version);
 214        ehdr.e_entry     = elf32_to_cpu(ehdr.e_entry);
 215        ehdr.e_phoff     = elf32_to_cpu(ehdr.e_phoff);
 216        ehdr.e_shoff     = elf32_to_cpu(ehdr.e_shoff);
 217        ehdr.e_flags     = elf32_to_cpu(ehdr.e_flags);
 218        ehdr.e_ehsize    = elf16_to_cpu(ehdr.e_ehsize);
 219        ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
 220        ehdr.e_phnum     = elf16_to_cpu(ehdr.e_phnum);
 221        ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
 222        ehdr.e_shnum     = elf16_to_cpu(ehdr.e_shnum);
 223        ehdr.e_shstrndx  = elf16_to_cpu(ehdr.e_shstrndx);
 224
 225        if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
 226                die("Unsupported ELF header type\n");
 227        }
 228        if (ehdr.e_machine != EM_386) {
 229                die("Not for x86\n");
 230        }
 231        if (ehdr.e_version != EV_CURRENT) {
 232                die("Unknown ELF version\n");
 233        }
 234        if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
 235                die("Bad Elf header size\n");
 236        }
 237        if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
 238                die("Bad program header entry\n");
 239        }
 240        if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
 241                die("Bad section header entry\n");
 242        }
 243        if (ehdr.e_shstrndx >= ehdr.e_shnum) {
 244                die("String table index out of bounds\n");
 245        }
 246}
 247
 248static void read_shdrs(FILE *fp)
 249{
 250        int i;
 251        Elf32_Shdr shdr;
 252
 253        secs = calloc(ehdr.e_shnum, sizeof(struct section));
 254        if (!secs) {
 255                die("Unable to allocate %d section headers\n",
 256                    ehdr.e_shnum);
 257        }
 258        if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
 259                die("Seek to %d failed: %s\n",
 260                        ehdr.e_shoff, strerror(errno));
 261        }
 262        for (i = 0; i < ehdr.e_shnum; i++) {
 263                struct section *sec = &secs[i];
 264                if (fread(&shdr, sizeof shdr, 1, fp) != 1)
 265                        die("Cannot read ELF section headers %d/%d: %s\n",
 266                            i, ehdr.e_shnum, strerror(errno));
 267                sec->shdr.sh_name      = elf32_to_cpu(shdr.sh_name);
 268                sec->shdr.sh_type      = elf32_to_cpu(shdr.sh_type);
 269                sec->shdr.sh_flags     = elf32_to_cpu(shdr.sh_flags);
 270                sec->shdr.sh_addr      = elf32_to_cpu(shdr.sh_addr);
 271                sec->shdr.sh_offset    = elf32_to_cpu(shdr.sh_offset);
 272                sec->shdr.sh_size      = elf32_to_cpu(shdr.sh_size);
 273                sec->shdr.sh_link      = elf32_to_cpu(shdr.sh_link);
 274                sec->shdr.sh_info      = elf32_to_cpu(shdr.sh_info);
 275                sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
 276                sec->shdr.sh_entsize   = elf32_to_cpu(shdr.sh_entsize);
 277                if (sec->shdr.sh_link < ehdr.e_shnum)
 278                        sec->link = &secs[sec->shdr.sh_link];
 279        }
 280
 281}
 282
 283static void read_strtabs(FILE *fp)
 284{
 285        int i;
 286        for (i = 0; i < ehdr.e_shnum; i++) {
 287                struct section *sec = &secs[i];
 288                if (sec->shdr.sh_type != SHT_STRTAB) {
 289                        continue;
 290                }
 291                sec->strtab = malloc(sec->shdr.sh_size);
 292                if (!sec->strtab) {
 293                        die("malloc of %d bytes for strtab failed\n",
 294                                sec->shdr.sh_size);
 295                }
 296                if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
 297                        die("Seek to %d failed: %s\n",
 298                                sec->shdr.sh_offset, strerror(errno));
 299                }
 300                if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
 301                    != sec->shdr.sh_size) {
 302                        die("Cannot read symbol table: %s\n",
 303                                strerror(errno));
 304                }
 305        }
 306}
 307
 308static void read_symtabs(FILE *fp)
 309{
 310        int i,j;
 311        for (i = 0; i < ehdr.e_shnum; i++) {
 312                struct section *sec = &secs[i];
 313                if (sec->shdr.sh_type != SHT_SYMTAB) {
 314                        continue;
 315                }
 316                sec->symtab = malloc(sec->shdr.sh_size);
 317                if (!sec->symtab) {
 318                        die("malloc of %d bytes for symtab failed\n",
 319                                sec->shdr.sh_size);
 320                }
 321                if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
 322                        die("Seek to %d failed: %s\n",
 323                                sec->shdr.sh_offset, strerror(errno));
 324                }
 325                if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
 326                    != sec->shdr.sh_size) {
 327                        die("Cannot read symbol table: %s\n",
 328                                strerror(errno));
 329                }
 330                for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
 331                        Elf32_Sym *sym = &sec->symtab[j];
 332                        sym->st_name  = elf32_to_cpu(sym->st_name);
 333                        sym->st_value = elf32_to_cpu(sym->st_value);
 334                        sym->st_size  = elf32_to_cpu(sym->st_size);
 335                        sym->st_shndx = elf16_to_cpu(sym->st_shndx);
 336                }
 337        }
 338}
 339
 340
 341static void read_relocs(FILE *fp)
 342{
 343        int i,j;
 344        for (i = 0; i < ehdr.e_shnum; i++) {
 345                struct section *sec = &secs[i];
 346                if (sec->shdr.sh_type != SHT_REL) {
 347                        continue;
 348                }
 349                sec->reltab = malloc(sec->shdr.sh_size);
 350                if (!sec->reltab) {
 351                        die("malloc of %d bytes for relocs failed\n",
 352                                sec->shdr.sh_size);
 353                }
 354                if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
 355                        die("Seek to %d failed: %s\n",
 356                                sec->shdr.sh_offset, strerror(errno));
 357                }
 358                if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
 359                    != sec->shdr.sh_size) {
 360                        die("Cannot read symbol table: %s\n",
 361                                strerror(errno));
 362                }
 363                for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
 364                        Elf32_Rel *rel = &sec->reltab[j];
 365                        rel->r_offset = elf32_to_cpu(rel->r_offset);
 366                        rel->r_info   = elf32_to_cpu(rel->r_info);
 367                }
 368        }
 369}
 370
 371
 372static void print_absolute_symbols(void)
 373{
 374        int i;
 375        printf("Absolute symbols\n");
 376        printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
 377        for (i = 0; i < ehdr.e_shnum; i++) {
 378                struct section *sec = &secs[i];
 379                char *sym_strtab;
 380                Elf32_Sym *sh_symtab;
 381                int j;
 382
 383                if (sec->shdr.sh_type != SHT_SYMTAB) {
 384                        continue;
 385                }
 386                sh_symtab = sec->symtab;
 387                sym_strtab = sec->link->strtab;
 388                for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
 389                        Elf32_Sym *sym;
 390                        const char *name;
 391                        sym = &sec->symtab[j];
 392                        name = sym_name(sym_strtab, sym);
 393                        if (sym->st_shndx != SHN_ABS) {
 394                                continue;
 395                        }
 396                        printf("%5d %08x %5d %10s %10s %12s %s\n",
 397                                j, sym->st_value, sym->st_size,
 398                                sym_type(ELF32_ST_TYPE(sym->st_info)),
 399                                sym_bind(ELF32_ST_BIND(sym->st_info)),
 400                                sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
 401                                name);
 402                }
 403        }
 404        printf("\n");
 405}
 406
 407static void print_absolute_relocs(void)
 408{
 409        int i, printed = 0;
 410
 411        for (i = 0; i < ehdr.e_shnum; i++) {
 412                struct section *sec = &secs[i];
 413                struct section *sec_applies, *sec_symtab;
 414                char *sym_strtab;
 415                Elf32_Sym *sh_symtab;
 416                int j;
 417                if (sec->shdr.sh_type != SHT_REL) {
 418                        continue;
 419                }
 420                sec_symtab  = sec->link;
 421                sec_applies = &secs[sec->shdr.sh_info];
 422                if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
 423                        continue;
 424                }
 425                sh_symtab  = sec_symtab->symtab;
 426                sym_strtab = sec_symtab->link->strtab;
 427                for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
 428                        Elf32_Rel *rel;
 429                        Elf32_Sym *sym;
 430                        const char *name;
 431                        rel = &sec->reltab[j];
 432                        sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 433                        name = sym_name(sym_strtab, sym);
 434                        if (sym->st_shndx != SHN_ABS) {
 435                                continue;
 436                        }
 437
 438                        /* Absolute symbols are not relocated if bzImage is
 439                         * loaded at a non-compiled address. Display a warning
 440                         * to user at compile time about the absolute
 441                         * relocations present.
 442                         *
 443                         * User need to audit the code to make sure
 444                         * some symbols which should have been section
 445                         * relative have not become absolute because of some
 446                         * linker optimization or wrong programming usage.
 447                         *
 448                         * Before warning check if this absolute symbol
 449                         * relocation is harmless.
 450                         */
 451                        if (is_safe_abs_reloc(name))
 452                                continue;
 453
 454                        if (!printed) {
 455                                printf("WARNING: Absolute relocations"
 456                                        " present\n");
 457                                printf("Offset     Info     Type     Sym.Value "
 458                                        "Sym.Name\n");
 459                                printed = 1;
 460                        }
 461
 462                        printf("%08x %08x %10s %08x  %s\n",
 463                                rel->r_offset,
 464                                rel->r_info,
 465                                rel_type(ELF32_R_TYPE(rel->r_info)),
 466                                sym->st_value,
 467                                name);
 468                }
 469        }
 470
 471        if (printed)
 472                printf("\n");
 473}
 474
 475static void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
 476{
 477        int i;
 478        /* Walk through the relocations */
 479        for (i = 0; i < ehdr.e_shnum; i++) {
 480                char *sym_strtab;
 481                Elf32_Sym *sh_symtab;
 482                struct section *sec_applies, *sec_symtab;
 483                int j;
 484                struct section *sec = &secs[i];
 485
 486                if (sec->shdr.sh_type != SHT_REL) {
 487                        continue;
 488                }
 489                sec_symtab  = sec->link;
 490                sec_applies = &secs[sec->shdr.sh_info];
 491                if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
 492                        continue;
 493                }
 494                sh_symtab = sec_symtab->symtab;
 495                sym_strtab = sec_symtab->link->strtab;
 496                for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
 497                        Elf32_Rel *rel;
 498                        Elf32_Sym *sym;
 499                        unsigned r_type;
 500                        rel = &sec->reltab[j];
 501                        sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
 502                        r_type = ELF32_R_TYPE(rel->r_info);
 503                        /* Don't visit relocations to absolute symbols */
 504                        if (sym->st_shndx == SHN_ABS) {
 505                                continue;
 506                        }
 507                        if (r_type == R_386_NONE || r_type == R_386_PC32) {
 508                                /*
 509                                 * NONE can be ignored and and PC relative
 510                                 * relocations don't need to be adjusted.
 511                                 */
 512                        }
 513                        else if (r_type == R_386_32) {
 514                                /* Visit relocations that need to be adjusted */
 515                                visit(rel, sym);
 516                        }
 517                        else {
 518                                die("Unsupported relocation type: %d\n", r_type);
 519                        }
 520                }
 521        }
 522}
 523
 524static void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
 525{
 526        reloc_count += 1;
 527}
 528
 529static void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
 530{
 531        /* Remember the address that needs to be adjusted. */
 532        relocs[reloc_idx++] = rel->r_offset;
 533}
 534
 535static int cmp_relocs(const void *va, const void *vb)
 536{
 537        const unsigned long *a, *b;
 538        a = va; b = vb;
 539        return (*a == *b)? 0 : (*a > *b)? 1 : -1;
 540}
 541
 542static void emit_relocs(int as_text)
 543{
 544        int i;
 545        /* Count how many relocations I have and allocate space for them. */
 546        reloc_count = 0;
 547        walk_relocs(count_reloc);
 548        relocs = malloc(reloc_count * sizeof(relocs[0]));
 549        if (!relocs) {
 550                die("malloc of %d entries for relocs failed\n",
 551                        reloc_count);
 552        }
 553        /* Collect up the relocations */
 554        reloc_idx = 0;
 555        walk_relocs(collect_reloc);
 556
 557        /* Order the relocations for more efficient processing */
 558        qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
 559
 560        /* Print the relocations */
 561        if (as_text) {
 562                /* Print the relocations in a form suitable that
 563                 * gas will like.
 564                 */
 565                printf(".section \".data.reloc\",\"a\"\n");
 566                printf(".balign 4\n");
 567                for (i = 0; i < reloc_count; i++) {
 568                        printf("\t .long 0x%08lx\n", relocs[i]);
 569                }
 570                printf("\n");
 571        }
 572        else {
 573                unsigned char buf[4];
 574                buf[0] = buf[1] = buf[2] = buf[3] = 0;
 575                /* Print a stop */
 576                printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
 577                /* Now print each relocation */
 578                for (i = 0; i < reloc_count; i++) {
 579                        buf[0] = (relocs[i] >>  0) & 0xff;
 580                        buf[1] = (relocs[i] >>  8) & 0xff;
 581                        buf[2] = (relocs[i] >> 16) & 0xff;
 582                        buf[3] = (relocs[i] >> 24) & 0xff;
 583                        printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
 584                }
 585        }
 586}
 587
 588static void usage(void)
 589{
 590        die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n");
 591}
 592
 593int main(int argc, char **argv)
 594{
 595        int show_absolute_syms, show_absolute_relocs;
 596        int as_text;
 597        const char *fname;
 598        FILE *fp;
 599        int i;
 600
 601        show_absolute_syms = 0;
 602        show_absolute_relocs = 0;
 603        as_text = 0;
 604        fname = NULL;
 605        for (i = 1; i < argc; i++) {
 606                char *arg = argv[i];
 607                if (*arg == '-') {
 608                        if (strcmp(argv[1], "--abs-syms") == 0) {
 609                                show_absolute_syms = 1;
 610                                continue;
 611                        }
 612
 613                        if (strcmp(argv[1], "--abs-relocs") == 0) {
 614                                show_absolute_relocs = 1;
 615                                continue;
 616                        }
 617                        else if (strcmp(argv[1], "--text") == 0) {
 618                                as_text = 1;
 619                                continue;
 620                        }
 621                }
 622                else if (!fname) {
 623                        fname = arg;
 624                        continue;
 625                }
 626                usage();
 627        }
 628        if (!fname) {
 629                usage();
 630        }
 631        fp = fopen(fname, "r");
 632        if (!fp) {
 633                die("Cannot open %s: %s\n",
 634                        fname, strerror(errno));
 635        }
 636        read_ehdr(fp);
 637        read_shdrs(fp);
 638        read_strtabs(fp);
 639        read_symtabs(fp);
 640        read_relocs(fp);
 641        if (show_absolute_syms) {
 642                print_absolute_symbols();
 643                return 0;
 644        }
 645        if (show_absolute_relocs) {
 646                print_absolute_relocs();
 647                return 0;
 648        }
 649        emit_relocs(as_text);
 650        return 0;
 651}
 652