diff options
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 28 | ||||
-rw-r--r-- | binutils/readelf.c | 188 |
2 files changed, 156 insertions, 60 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index f08b7d2..1ddf1fa 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,31 @@ +2001-12-17 Alan Modra <amodra@bigpond.net.au> + + * readelf.c (symtab_shndx_hdr): New global. + (SECTION_HEADER_INDEX): Define. + (SECTION_HEADER_NUM): Define. + (SECTION_HEADER): Define. + (GET_ELF_SYMBOLS): Pass two params rather than three. + (get_32bit_elf_symbols): Take file and section args. Read and + use SHT_SYMTAB_SHNDX. + (get_64bit_elf_symbols): Likewise. + (dump_relocations): Use SECTION_HEADER to index "section_headers". + (process_section_headers): Likewise. Use SECTION_HEADER_NUM too. + Remember symtab_shdx_hdr. + (process_program_headers): Scan from index 1 for segment map. + (slurp_ia64_unwind_table): Use SECTION_HEADER to index + "section_headers". + (process_relocs): Likewise. Also adjust call to GET_ELF_SYMBOLS. + (process_unwind): Likewise. + (process_version_sections): Likewise. + (process_symbol_table): Likewise. + (display_debug_info): Likewise. + (process_dynamic_segment): Fake up a symtab section for changed + GET_ELF_SYMBOLS. + (get_symbol_index_type): Check SHN_LOOS before SHN_LORESERVE. + (process_program_headers): Kill signed/unsigned warning. + (load_debug_str): Likewise. + (display_debug_info): Likewise. + 2001-12-13 Jakub Jelinek <jakub@redhat.com> * readelf.c (get_segment_type): Support PT_GNU_EH_FRAME. diff --git a/binutils/readelf.c b/binutils/readelf.c index 73a98b5..cd97886 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -102,6 +102,7 @@ int loadaddr = 0; Elf_Internal_Ehdr elf_header; Elf_Internal_Shdr * section_headers; Elf_Internal_Dyn * dynamic_segment; +Elf_Internal_Shdr * symtab_shndx_hdr; int show_name; int do_dynamic; int do_syms; @@ -202,8 +203,8 @@ static int get_64bit_section_headers PARAMS ((FILE *, unsigned static int get_32bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); static int get_64bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); static int get_file_header PARAMS ((FILE *)); -static Elf_Internal_Sym * get_32bit_elf_symbols PARAMS ((FILE *, unsigned long, unsigned long)); -static Elf_Internal_Sym * get_64bit_elf_symbols PARAMS ((FILE *, unsigned long, unsigned long)); +static Elf_Internal_Sym * get_32bit_elf_symbols PARAMS ((FILE *, Elf_Internal_Shdr *)); +static Elf_Internal_Sym * get_64bit_elf_symbols PARAMS ((FILE *, Elf_Internal_Shdr *)); static const char * get_elf_section_flags PARAMS ((bfd_vma)); static int * get_dynamic_data PARAMS ((FILE *, unsigned int)); static int get_32bit_dynamic_segment PARAMS ((FILE *)); @@ -264,6 +265,22 @@ typedef int Elf32_Word; ((X)->sh_name >= string_table_length \ ? "<corrupt>" : string_table + (X)->sh_name)) +/* Given st_shndx I, map to section_headers index. */ +#define SECTION_HEADER_INDEX(I) \ + ((I) < SHN_LORESERVE \ + ? (I) \ + : ((I) <= SHN_HIRESERVE \ + ? 0 \ + : (I) - (SHN_HIRESERVE + 1 - SHN_LORESERVE))) + +/* Reverse of the above. */ +#define SECTION_HEADER_NUM(N) \ + ((N) < SHN_LORESERVE \ + ? (N) \ + : (N) + (SHN_HIRESERVE + 1 - SHN_LORESERVE)) + +#define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I)) + #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ #define BYTE_GET(field) byte_get (field, sizeof (field)) @@ -284,9 +301,9 @@ typedef int Elf32_Word; #define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0])) -#define GET_ELF_SYMBOLS(file, offset, size) \ - (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size) \ - : get_64bit_elf_symbols (file, offset, size)) +#define GET_ELF_SYMBOLS(file, section) \ + (is_32bit_elf ? get_32bit_elf_symbols (file, section) \ + : get_64bit_elf_symbols (file, section)) static void @@ -1042,7 +1059,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) if (psym->st_name == 0) printf ("%-25.25s", - SECTION_NAME (section_headers + psym->st_shndx)); + SECTION_NAME (SECTION_HEADER (psym->st_shndx))); else if (strtab == NULL) printf (_("<string table index %3ld>"), psym->st_name); else @@ -2745,7 +2762,7 @@ process_program_headers (file) for (i = 0; i < elf_header.e_phnum; i++) { - int j; + unsigned int j; Elf_Internal_Shdr * section; segment = program_headers + i; @@ -2753,7 +2770,7 @@ process_program_headers (file) printf (" %2.2d ", i); - for (j = 0; j < elf_header.e_shnum; j++, section ++) + for (j = 1; j < elf_header.e_shnum; j++, section ++) { if (section->sh_size > 0 /* Compare allocated sections by VMA, unallocated @@ -2871,29 +2888,47 @@ get_64bit_section_headers (file, num) } static Elf_Internal_Sym * -get_32bit_elf_symbols (file, offset, number) +get_32bit_elf_symbols (file, section) FILE * file; - unsigned long offset; - unsigned long number; + Elf_Internal_Shdr *section; { + unsigned long number; Elf32_External_Sym * esyms; + Elf_External_Sym_Shndx *shndx; Elf_Internal_Sym * isyms; Elf_Internal_Sym * psym; unsigned int j; esyms = ((Elf32_External_Sym *) - get_data (NULL, file, offset, - number * sizeof (Elf32_External_Sym), _("symbols"))); + get_data (NULL, file, section->sh_offset, + section->sh_size, _("symbols"))); if (!esyms) return NULL; + shndx = NULL; + if (symtab_shndx_hdr != NULL + && (symtab_shndx_hdr->sh_link + == (unsigned long) SECTION_HEADER_NUM (section - section_headers))) + { + shndx = ((Elf_External_Sym_Shndx *) + get_data (NULL, file, symtab_shndx_hdr->sh_offset, + symtab_shndx_hdr->sh_size, _("symtab shndx"))); + if (!shndx) + { + free (esyms); + return NULL; + } + } + + number = section->sh_size / section->sh_entsize; isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); if (isyms == NULL) { error (_("Out of memory\n")); + if (shndx) + free (shndx); free (esyms); - return NULL; } @@ -2905,39 +2940,62 @@ get_32bit_elf_symbols (file, offset, number) psym->st_value = BYTE_GET (esyms[j].st_value); psym->st_size = BYTE_GET (esyms[j].st_size); psym->st_shndx = BYTE_GET (esyms[j].st_shndx); + if (psym->st_shndx == SHN_XINDEX && shndx != NULL) + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); psym->st_info = BYTE_GET (esyms[j].st_info); psym->st_other = BYTE_GET (esyms[j].st_other); } + if (shndx) + free (shndx); free (esyms); return isyms; } static Elf_Internal_Sym * -get_64bit_elf_symbols (file, offset, number) +get_64bit_elf_symbols (file, section) FILE * file; - unsigned long offset; - unsigned long number; + Elf_Internal_Shdr *section; { + unsigned long number; Elf64_External_Sym * esyms; + Elf_External_Sym_Shndx *shndx; Elf_Internal_Sym * isyms; Elf_Internal_Sym * psym; unsigned int j; esyms = ((Elf64_External_Sym *) - get_data (NULL, file, offset, - number * sizeof (Elf64_External_Sym), _("symbols"))); + get_data (NULL, file, section->sh_offset, + section->sh_size, _("symbols"))); if (!esyms) return NULL; + shndx = NULL; + if (symtab_shndx_hdr != NULL + && (symtab_shndx_hdr->sh_link + == (unsigned long) SECTION_HEADER_NUM (section - section_headers))) + { + shndx = ((Elf_External_Sym_Shndx *) + get_data (NULL, file, symtab_shndx_hdr->sh_offset, + symtab_shndx_hdr->sh_size, _("symtab shndx"))); + if (!shndx) + { + free (esyms); + return NULL; + } + } + + number = section->sh_size / section->sh_entsize; isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); if (isyms == NULL) { error (_("Out of memory\n")); + if (shndx) + free (shndx); free (esyms); - return NULL; } @@ -2949,10 +3007,15 @@ get_64bit_elf_symbols (file, offset, number) psym->st_info = BYTE_GET (esyms[j].st_info); psym->st_other = BYTE_GET (esyms[j].st_other); psym->st_shndx = BYTE_GET (esyms[j].st_shndx); + if (psym->st_shndx == SHN_XINDEX && shndx != NULL) + psym->st_shndx + = byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j])); psym->st_value = BYTE_GET8 (esyms[j].st_value); psym->st_size = BYTE_GET8 (esyms[j].st_size); } + if (shndx) + free (shndx); free (esyms); return isyms; @@ -3010,7 +3073,7 @@ process_section_headers (file) FILE * file; { Elf_Internal_Shdr * section; - int i; + unsigned int i; section_headers = NULL; @@ -3035,7 +3098,7 @@ process_section_headers (file) return 0; /* Read in the string table, so that we have names to display. */ - section = section_headers + elf_header.e_shstrndx; + section = SECTION_HEADER (elf_header.e_shstrndx); if (section->sh_size != 0) { @@ -3066,8 +3129,7 @@ process_section_headers (file) } num_dynamic_syms = section->sh_size / section->sh_entsize; - dynamic_symbols = - GET_ELF_SYMBOLS (file, section->sh_offset, num_dynamic_syms); + dynamic_symbols = GET_ELF_SYMBOLS (file, section); } else if (section->sh_type == SHT_STRTAB && strcmp (name, ".dynstr") == 0) @@ -3082,6 +3144,15 @@ process_section_headers (file) section->sh_size, _("dynamic strings")); } + else if (section->sh_type == SHT_SYMTAB_SHNDX) + { + if (symtab_shndx_hdr != NULL) + { + error (_("File contains multiple symtab shndx tables\n")); + continue; + } + symtab_shndx_hdr = section; + } else if ((do_debugging || do_debug_info || do_debug_abbrevs || do_debug_lines || do_debug_pubnames || do_debug_aranges || do_debug_frames || do_debug_macinfo || do_debug_str) @@ -3130,8 +3201,8 @@ process_section_headers (file) i < elf_header.e_shnum; i ++, section ++) { - printf (" [%2d] %-17.17s %-15.15s ", - i, + printf (" [%2u] %-17.17s %-15.15s ", + SECTION_HEADER_NUM (i), SECTION_NAME (section), get_section_type_name (section->sh_type)); @@ -3330,14 +3401,14 @@ process_relocs (file) { Elf32_Internal_Shdr * symsec; - symsec = section_headers + section->sh_link; + symsec = SECTION_HEADER (section->sh_link); nsyms = symsec->sh_size / symsec->sh_entsize; - symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms); + symtab = GET_ELF_SYMBOLS (file, symsec); if (symtab == NULL) continue; - strsec = section_headers + symsec->sh_link; + strsec = SECTION_HEADER (symsec->sh_link); strtab = (char *) get_data (NULL, file, strsec->sh_offset, strsec->sh_size, @@ -3589,7 +3660,7 @@ slurp_ia64_unwind_table (file, aux, sec) ++relsec) { if (relsec->sh_type != SHT_RELA - || section_headers + relsec->sh_info != sec) + || SECTION_HEADER (relsec->sh_info) != sec) continue; if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, @@ -3683,9 +3754,9 @@ process_unwind (file) if (sec->sh_type == SHT_SYMTAB) { aux.nsyms = sec->sh_size / sec->sh_entsize; - aux.symtab = GET_ELF_SYMBOLS (file, sec->sh_offset, aux.nsyms); + aux.symtab = GET_ELF_SYMBOLS (file, sec); - strsec = section_headers + sec->sh_link; + strsec = SECTION_HEADER (sec->sh_link); aux.strtab_size = strsec->sh_size; aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset, aux.strtab_size, _("string table")); @@ -4065,7 +4136,7 @@ process_dynamic_segment (file) i < dynamic_size; ++i, ++ entry) { - unsigned long offset; + Elf32_Internal_Shdr section; if (entry->d_tag != DT_SYMTAB) continue; @@ -4076,23 +4147,25 @@ process_dynamic_segment (file) we default to reading in the entire file (!) and processing that. This is overkill, I know, but it should work. */ - offset = entry->d_un.d_val - loadaddr; + section.sh_offset = entry->d_un.d_val - loadaddr; if (fseek (file, 0, SEEK_END)) error (_("Unable to seek to end of file!")); + section.sh_size = ftell (file) - section.sh_offset; if (is_32bit_elf) - num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym); + section.sh_entsize = sizeof (Elf32_External_Sym); else - num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf64_External_Sym); + section.sh_entsize = sizeof (Elf64_External_Sym); + num_dynamic_syms = section.sh_size / section.sh_entsize; if (num_dynamic_syms < 1) { error (_("Unable to determine the number of symbols to load\n")); continue; } - dynamic_symbols = GET_ELF_SYMBOLS (file, offset, num_dynamic_syms); + dynamic_symbols = GET_ELF_SYMBOLS (file, §ion); } } @@ -4613,7 +4686,7 @@ process_version_sections (file) printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %lx (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, - SECTION_NAME (section_headers + section->sh_link)); + SECTION_NAME (SECTION_HEADER (section->sh_link))); edefs = ((Elf_External_Verdef *) get_data (NULL, file, section->sh_offset, @@ -4704,7 +4777,7 @@ process_version_sections (file) printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link to section: %ld (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, - SECTION_NAME (section_headers + section->sh_link)); + SECTION_NAME (SECTION_HEADER (section->sh_link))); eneed = ((Elf_External_Verneed *) get_data (NULL, file, section->sh_offset, @@ -4786,15 +4859,14 @@ process_version_sections (file) Elf_Internal_Sym * symbols; Elf32_Internal_Shdr * string_sec; - link_section = section_headers + section->sh_link; + link_section = SECTION_HEADER (section->sh_link); total = section->sh_size / section->sh_entsize; found = 1; - symbols = GET_ELF_SYMBOLS (file, link_section->sh_offset, - link_section->sh_size / link_section->sh_entsize); + symbols = GET_ELF_SYMBOLS (file, link_section); - string_sec = section_headers + link_section->sh_link; + string_sec = SECTION_HEADER (link_section->sh_link); strtab = (char *) get_data (NULL, file, string_sec->sh_offset, string_sec->sh_size, @@ -4855,8 +4927,7 @@ process_version_sections (file) check_def = 1; check_need = 1; - if (symbols [cnt + j].st_shndx >= SHN_LORESERVE - || section_headers[symbols [cnt + j].st_shndx].sh_type + if (SECTION_HEADER (symbols [cnt + j].st_shndx)->sh_type != SHT_NOBITS) { if (symbols [cnt + j].st_shndx == SHN_UNDEF) @@ -5082,10 +5153,10 @@ get_symbol_index_type (type) default: if (type >= SHN_LOPROC && type <= SHN_HIPROC) return "PRC"; - else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) - return "RSV"; else if (type >= SHN_LOOS && type <= SHN_HIOS) return "OS "; + else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) + return "RSV"; else { static char buff [32]; @@ -5244,8 +5315,7 @@ process_symbol_table (file) else printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); - symtab = GET_ELF_SYMBOLS (file, section->sh_offset, - section->sh_size / section->sh_entsize); + symtab = GET_ELF_SYMBOLS (file, section); if (symtab == NULL) continue; @@ -5255,7 +5325,7 @@ process_symbol_table (file) { Elf32_Internal_Shdr * string_sec; - string_sec = section_headers + section->sh_link; + string_sec = SECTION_HEADER (section->sh_link); strtab = (char *) get_data (NULL, file, string_sec->sh_offset, string_sec->sh_size, @@ -5293,9 +5363,8 @@ process_symbol_table (file) vers_data = byte_get (data, 2); - is_nobits = psym->st_shndx < SHN_LORESERVE ? - (section_headers [psym->st_shndx].sh_type == SHT_NOBITS) - : 0; + is_nobits = (SECTION_HEADER (psym->st_shndx)->sh_type + == SHT_NOBITS); check_def = (psym->st_shndx != SHN_UNDEF); @@ -6976,7 +7045,7 @@ load_debug_str (file) FILE * file; { Elf32_Internal_Shdr * sec; - int i; + unsigned int i; /* If it is already loaded, do nothing. */ if (debug_str_contents != NULL) @@ -7414,7 +7483,7 @@ display_debug_info (section, start, file) DWARF2_Internal_CompUnit compunit; Elf32_Internal_Shdr * relsec; unsigned char * tags; - int i; + unsigned int i; int level; unsigned long cu_offset; @@ -7437,23 +7506,22 @@ display_debug_info (section, start, file) relsec < section_headers + elf_header.e_shnum; ++relsec) { - unsigned long nrelas, nsyms; + unsigned long nrelas; Elf_Internal_Rela *rela, *rp; Elf32_Internal_Shdr *symsec; Elf_Internal_Sym *symtab; Elf_Internal_Sym *sym; if (relsec->sh_type != SHT_RELA - || section_headers + relsec->sh_info != section) + || SECTION_HEADER (relsec->sh_info) != section) continue; if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, & rela, & nrelas)) return 0; - symsec = section_headers + relsec->sh_link; - nsyms = symsec->sh_size / symsec->sh_entsize; - symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms); + symsec = SECTION_HEADER (relsec->sh_link); + symtab = GET_ELF_SYMBOLS (file, symsec); for (rp = rela; rp < rela + nrelas; ++rp) { |