Index: readelf.c =================================================================== --- readelf.c (revision 2212) +++ readelf.c (working copy) @@ -204,6 +204,14 @@ static int do_arch; static int do_notes; static int do_archive_index; static int is_32bit_elf; +static int hole_in_shndx; + +struct original_shndx_info +{ + unsigned int sh_link; + unsigned int sh_info; +}; +static struct original_shndx_info *original_shndx; struct group_list { @@ -270,6 +278,8 @@ static void (*byte_put) (unsigned char * #define UNKNOWN -1 +#define SECTION_HEADER_INDEX_GAP (SHN_HIRESERVE + 1 - SHN_LORESERVE) + #define SECTION_NAME(X) \ ((X) == NULL ? "" \ : string_table == NULL ? "" \ @@ -3275,16 +3285,6 @@ get_data_encoding (unsigned int encoding static int process_file_header (void) { - if ( elf_header.e_ident[EI_MAG0] != ELFMAG0 - || elf_header.e_ident[EI_MAG1] != ELFMAG1 - || elf_header.e_ident[EI_MAG2] != ELFMAG2 - || elf_header.e_ident[EI_MAG3] != ELFMAG3) - { - error - (_("Not an ELF file - it has the wrong magic bytes at the start\n")); - return 0; - } - init_dwarf_regnames (elf_header.e_machine); if (do_header) @@ -3765,6 +3765,10 @@ get_32bit_section_headers (FILE *file, u internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); + /* The older linker generates section header indices with + hole. */ + if (internal->sh_link >= elf_header.e_shnum) + hole_in_shndx = 1; } free (shdrs); @@ -3806,6 +3810,10 @@ get_64bit_section_headers (FILE *file, u internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); + /* The older linker generates section header indices with + hole. */ + if (i > 0 && internal->sh_link >= elf_header.e_shnum) + hole_in_shndx = 1; } free (shdrs); @@ -3863,8 +3871,12 @@ get_32bit_elf_symbols (FILE *file, Elf_I psym->st_size = BYTE_GET (esyms[j].st_size); psym->st_shndx = BYTE_GET (esyms[j].st_shndx); if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL) - psym->st_shndx - = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + { + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + if (hole_in_shndx && psym->st_shndx > (SHN_HIRESERVE & 0xffff)) + psym->st_shndx -= SECTION_HEADER_INDEX_GAP; + } else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff)) psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); psym->st_info = BYTE_GET (esyms[j].st_info); @@ -3928,8 +3940,12 @@ get_64bit_elf_symbols (FILE *file, Elf_I psym->st_other = BYTE_GET (esyms[j].st_other); psym->st_shndx = BYTE_GET (esyms[j].st_shndx); if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL) - psym->st_shndx - = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + { + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); + if (hole_in_shndx && psym->st_shndx > (SHN_HIRESERVE & 0xffff)) + psym->st_shndx -= SECTION_HEADER_INDEX_GAP; + } else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff)) psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); psym->st_value = BYTE_GET (esyms[j].st_value); @@ -4154,6 +4170,7 @@ process_section_headers (FILE *file) unsigned int i; section_headers = NULL; + original_shndx = NULL; if (elf_header.e_shnum == 0) { @@ -4175,6 +4192,47 @@ process_section_headers (FILE *file) else if (! get_64bit_section_headers (file, elf_header.e_shnum)) return 0; + if (hole_in_shndx) + { + Elf_Internal_Shdr *internal; + struct original_shndx_info *p; + + if (elf_header.e_shstrndx > (SHN_HIRESERVE & 0xffff)) + elf_header.e_shstrndx -= SECTION_HEADER_INDEX_GAP; + + original_shndx = cmalloc (elf_header.e_shnum, + sizeof (*original_shndx)); + if (original_shndx == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + internal = section_headers; + p = original_shndx; + for (i = elf_header.e_shnum; + i > 0; + i--, internal++, p++) + { + p->sh_link = internal->sh_link; + p->sh_info = internal->sh_info; + + if (internal->sh_link > (SHN_HIRESERVE & 0xffff)) + internal->sh_link -= SECTION_HEADER_INDEX_GAP; + + switch (internal->sh_type) + { + case SHT_REL: + case SHT_RELA: + if (internal->sh_info > (SHN_HIRESERVE & 0xffff)) + internal->sh_info -= SECTION_HEADER_INDEX_GAP; + break; + default: + break; + } + } + } + /* Read in the string table, so that we have names to display. */ if (elf_header.e_shstrndx != SHN_UNDEF && elf_header.e_shstrndx < elf_header.e_shnum) @@ -4420,10 +4478,27 @@ process_section_headers (FILE *file) else printf (" %3s ", get_elf_section_flags (section->sh_flags)); - printf ("%2u %3u %2lu\n", - section->sh_link, - section->sh_info, - (unsigned long) section->sh_addralign); + if (hole_in_shndx) + { + if (original_shndx[i].sh_link != section->sh_link) + printf ("%2u/-%3u ", + original_shndx[i].sh_link, + SECTION_HEADER_INDEX_GAP); + else + printf ("%2u ", section->sh_link); + if (original_shndx[i].sh_info != section->sh_info) + printf ("%3u/-%3u ", + original_shndx[i].sh_info, + SECTION_HEADER_INDEX_GAP); + else + printf ("%3u ", section->sh_info); + printf ("%2lu\n", (unsigned long) section->sh_addralign); + } + else + printf ("%2u %3u %2lu\n", + section->sh_link, + section->sh_info, + (unsigned long) section->sh_addralign); } else if (do_wide) { @@ -4458,7 +4533,23 @@ process_section_headers (FILE *file) else printf (" %3s ", get_elf_section_flags (section->sh_flags)); - printf ("%2u %3u ", section->sh_link, section->sh_info); + if (hole_in_shndx) + { + if (original_shndx[i].sh_link != section->sh_link) + printf ("%2u/-%3u ", + original_shndx[i].sh_link, + SECTION_HEADER_INDEX_GAP); + else + printf ("%2u ", section->sh_link); + if (original_shndx[i].sh_info != section->sh_info) + printf ("%3u/-%3u ", + original_shndx[i].sh_info, + SECTION_HEADER_INDEX_GAP); + else + printf ("%3u ", section->sh_info); + } + else + printf ("%2u %3u ", section->sh_link, section->sh_info); if ((unsigned long) section->sh_addralign == section->sh_addralign) printf ("%2lu\n", (unsigned long) section->sh_addralign); @@ -4480,14 +4571,35 @@ process_section_headers (FILE *file) printf (" "); print_vma (section->sh_offset, LONG_HEX); } - printf (" %u\n ", section->sh_link); + if (hole_in_shndx) + { + if (original_shndx[i].sh_link != section->sh_link) + printf (" %u/-%3u\n ", + original_shndx[i].sh_link, + SECTION_HEADER_INDEX_GAP); + else + printf (" %u\n ", section->sh_link); + } + else + printf (" %u\n ", section->sh_link); print_vma (section->sh_size, LONG_HEX); putchar (' '); print_vma (section->sh_entsize, LONG_HEX); - printf (" %-16u %lu\n", - section->sh_info, - (unsigned long) section->sh_addralign); + if (hole_in_shndx) + { + if (original_shndx[i].sh_info != section->sh_info) + printf (" %-11u/-%3u", + original_shndx[i].sh_info, + SECTION_HEADER_INDEX_GAP); + else + printf (" %-16u", section->sh_info); + printf (" %lu\n", (unsigned long) section->sh_addralign); + } + else + printf (" %-16u %lu\n", + section->sh_info, + (unsigned long) section->sh_addralign); } else { @@ -4507,10 +4619,28 @@ process_section_headers (FILE *file) printf (" %3s ", get_elf_section_flags (section->sh_flags)); - printf (" %2u %3u %lu\n", - section->sh_link, - section->sh_info, - (unsigned long) section->sh_addralign); + if (hole_in_shndx) + { + if (original_shndx[i].sh_link != section->sh_link) + printf (" %2u/-%3u", + original_shndx[i].sh_link, + SECTION_HEADER_INDEX_GAP); + else + printf (" %2u", section->sh_link); + if (original_shndx[i].sh_info != section->sh_info) + printf (" %3u/-%3u", + original_shndx[i].sh_info, + SECTION_HEADER_INDEX_GAP); + else + printf (" %3u", section->sh_info); + printf (" %lu\n", + (unsigned long) section->sh_addralign); + } + else + printf (" %2u %3u %lu\n", + section->sh_link, + section->sh_info, + (unsigned long) section->sh_addralign); } if (do_section_details) @@ -4704,10 +4834,15 @@ process_section_groups (FILE *file) for (j = 0; j < size; j++) { struct group_list *g; + unsigned int orig; entry = byte_get (indices, 4); indices += 4; + orig = entry; + if (hole_in_shndx && entry > (SHN_HIRESERVE & 0xffff)) + entry -= SECTION_HEADER_INDEX_GAP; + if (entry >= elf_header.e_shnum) { error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"), @@ -4744,7 +4879,13 @@ process_section_groups (FILE *file) if (do_section_groups) { sec = section_headers + entry; - printf (" [%5u] %s\n", entry, SECTION_NAME (sec)); + if (orig != entry) + printf (" [%5u/-%3u] %s\n", + orig, SECTION_HEADER_INDEX_GAP, + SECTION_NAME (sec)); + else + printf (" [%5u] %s\n", + entry, SECTION_NAME (sec)); } g = xmalloc (sizeof (struct group_list)); @@ -10083,6 +10224,15 @@ get_file_header (FILE *file) if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1) return 0; + if (elf_header.e_ident[EI_MAG0] != ELFMAG0 + || elf_header.e_ident[EI_MAG1] != ELFMAG1 + || elf_header.e_ident[EI_MAG2] != ELFMAG2 + || elf_header.e_ident[EI_MAG3] != ELFMAG3) + { + error (_("Not an ELF file - it has the wrong magic bytes at the start\n")); + return 0; + } + /* Determine how to read the rest of the header. */ switch (elf_header.e_ident[EI_DATA]) { @@ -10178,6 +10328,8 @@ process_object (char *file_name, FILE *f { unsigned int i; + hole_in_shndx = 0; + if (! get_file_header (file)) { error (_("%s: Failed to read file header\n"), file_name); @@ -10265,6 +10417,12 @@ process_object (char *file_name, FILE *f section_headers = NULL; } + if (original_shndx) + { + free (original_shndx); + original_shndx = NULL; + } + if (string_table) { free (string_table);