From 89fac5e3c33745a93c9b90538048505d46ca365c Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 31 Jan 2005 20:35:25 +0000 Subject: [PATCH] * readelf.c (eh_addr_size): New variable. (find_section): Move earlier in file. Return empty sections too. (process_program_headers): Use find_section to find .dynamic. (process_section_headers): Initialize eh_addr_size. (dump_ia64_unwind, slurp_ia64_unwind_table, ia64_process_unwind) (dump_hppa_unwind, slurp_hppa_unwind_table, hppa_process_unwind) (display_debug_frames): Use it instead of local addr_size variable. (size_of_encoded_value): Get pointer size from eh_addr_size rather than is_32bit_elf. --- binutils/ChangeLog | 12 +++++ binutils/readelf.c | 120 ++++++++++++++++++++++----------------------- 2 files changed, 70 insertions(+), 62 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 1fd7dcfda5e..bf5c01b5cb1 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,15 @@ +2005-01-31 Richard Sandiford + + * readelf.c (eh_addr_size): New variable. + (find_section): Move earlier in file. Return empty sections too. + (process_program_headers): Use find_section to find .dynamic. + (process_section_headers): Initialize eh_addr_size. + (dump_ia64_unwind, slurp_ia64_unwind_table, ia64_process_unwind) + (dump_hppa_unwind, slurp_hppa_unwind_table, hppa_process_unwind) + (display_debug_frames): Use it instead of local addr_size variable. + (size_of_encoded_value): Get pointer size from eh_addr_size rather + than is_32bit_elf. + 2005-01-31 Andrew Cagney * configure: Regenerate to track ../gettext.m4. diff --git a/binutils/readelf.c b/binutils/readelf.c index 2c61ed0f758..a4650b47036 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -170,6 +170,7 @@ int do_notes; int is_32bit_elf; int have_frame_base; int need_base_address; +bfd_vma eh_addr_size; struct group_list { @@ -643,6 +644,20 @@ byte_put_big_endian (unsigned char *field, bfd_vma value, int size) } } +/* Return a pointer to section NAME, or NULL if no such section exists. */ + +static Elf_Internal_Shdr * +find_section (const char *name) +{ + unsigned int i; + + for (i = 0; i < elf_header.e_shnum; i++) + if (streq (SECTION_NAME (section_headers + i), name)) + return section_headers + i; + + return NULL; +} + /* Guess the relocation size commonly used by the specific machines. */ static int @@ -3284,15 +3299,9 @@ process_program_headers (FILE *file) if (section_headers != NULL) { Elf_Internal_Shdr *sec; - unsigned int j; - for (j = 0, sec = section_headers; - j < elf_header.e_shnum; - j++, sec++) - if (streq (SECTION_NAME (sec), ".dynamic")) - break; - - if (j == elf_header.e_shnum || sec->sh_size == 0) + sec = find_section (".dynamic"); + if (sec == NULL || sec->sh_size == 0) { error (_("no .dynamic section in the dynamic segment")); break; @@ -3716,6 +3725,26 @@ process_section_headers (FILE *file) dynamic_syminfo = NULL; symtab_shndx_hdr = NULL; + eh_addr_size = is_32bit_elf ? 4 : 8; + switch (elf_header.e_machine) + { + case EM_MIPS: + case EM_MIPS_RS3_LE: + /* The 64-bit MIPS EABI uses a combination of 32-bit ELF and 64-bit + FDE addresses. However, the ABI also has a semi-official ILP32 + variant for which the normal FDE address size rules apply. + + GCC 4.0 marks EABI64 objects with a dummy .gcc_compiled_longXX + section, where XX is the size of longs in bits. Unfortunately, + earlier compilers provided no way of distinguishing ILP32 objects + from LP64 objects, so if there's any doubt, we should assume that + the official LP64 form is being used. */ + if ((elf_header.e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64 + && find_section (".gcc_compiled_long32") == NULL) + eh_addr_size = 8; + break; + } + for (i = 0, section = section_headers; i < elf_header.e_shnum; i++, section++) @@ -4301,12 +4330,9 @@ find_symbol_for_address (Elf_Internal_Sym *symtab, static void dump_ia64_unwind (struct ia64_unw_aux_info *aux) { - bfd_vma addr_size; struct ia64_unw_table_entry *tp; int in_body; - addr_size = is_32bit_elf ? 4 : 8; - for (tp = aux->table; tp < aux->table + aux->table_len; ++tp) { bfd_vma stamp; @@ -4343,7 +4369,7 @@ dump_ia64_unwind (struct ia64_unw_aux_info *aux) (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32), UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "", UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "", - (unsigned long) (addr_size * UNW_LENGTH (stamp))); + (unsigned long) (eh_addr_size * UNW_LENGTH (stamp))); if (UNW_VER (stamp) != 1) { @@ -4352,7 +4378,7 @@ dump_ia64_unwind (struct ia64_unw_aux_info *aux) } in_body = 0; - for (dp = head + 8; dp < head + 8 + addr_size * UNW_LENGTH (stamp);) + for (dp = head + 8; dp < head + 8 + eh_addr_size * UNW_LENGTH (stamp);) dp = unw_decode (dp, in_body, & in_body); } } @@ -4362,7 +4388,7 @@ slurp_ia64_unwind_table (FILE *file, struct ia64_unw_aux_info *aux, Elf_Internal_Shdr *sec) { - unsigned long size, addr_size, nrelas, i; + unsigned long size, nrelas, i; Elf_Internal_Phdr *seg; struct ia64_unw_table_entry *tep; Elf_Internal_Shdr *relsec; @@ -4371,8 +4397,6 @@ slurp_ia64_unwind_table (FILE *file, Elf_Internal_Sym *sym; const char *relname; - addr_size = is_32bit_elf ? 4 : 8; - /* First, find the starting address of the segment that includes this section: */ @@ -4403,8 +4427,9 @@ slurp_ia64_unwind_table (FILE *file, if (!table) return 0; - tep = aux->table = xmalloc (size / (3 * addr_size) * sizeof (aux->table[0])); - for (tp = table; tp < table + size; tp += 3 * addr_size, ++tep) + aux->table = xmalloc (size / (3 * eh_addr_size) * sizeof (aux->table[0])); + tep = aux->table; + for (tp = table; tp < table + size; tp += 3 * eh_addr_size, ++tep) { tep->start.section = SHN_UNDEF; tep->end.section = SHN_UNDEF; @@ -4460,9 +4485,9 @@ slurp_ia64_unwind_table (FILE *file, continue; } - i = rp->r_offset / (3 * addr_size); + i = rp->r_offset / (3 * eh_addr_size); - switch (rp->r_offset/addr_size % 3) + switch (rp->r_offset/eh_addr_size % 3) { case 0: aux->table[i].start.section = sym->st_shndx; @@ -4484,7 +4509,7 @@ slurp_ia64_unwind_table (FILE *file, free (rela); } - aux->table_len = size / (3 * addr_size); + aux->table_len = size / (3 * eh_addr_size); return 1; } @@ -4492,13 +4517,11 @@ static int ia64_process_unwind (FILE *file) { Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec; - unsigned long i, addr_size, unwcount = 0, unwstart = 0; + unsigned long i, unwcount = 0, unwstart = 0; struct ia64_unw_aux_info aux; memset (& aux, 0, sizeof (aux)); - addr_size = is_32bit_elf ? 4 : 8; - for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec) { if (sec->sh_type == SHT_SYMTAB) @@ -4602,7 +4625,7 @@ ia64_process_unwind (FILE *file) printf (_(" at offset 0x%lx contains %lu entries:\n"), (unsigned long) unwsec->sh_offset, - (unsigned long) (unwsec->sh_size / (3 * addr_size))); + (unsigned long) (unwsec->sh_size / (3 * eh_addr_size))); (void) slurp_ia64_unwind_table (file, & aux, unwsec); @@ -4676,10 +4699,8 @@ struct hppa_unw_aux_info static void dump_hppa_unwind (struct hppa_unw_aux_info *aux) { - bfd_vma addr_size; struct hppa_unw_table_entry *tp; - addr_size = is_32bit_elf ? 4 : 8; for (tp = aux->table; tp < aux->table + aux->table_len; ++tp) { bfd_vma offset; @@ -4746,7 +4767,7 @@ slurp_hppa_unwind_table (FILE *file, struct hppa_unw_aux_info *aux, Elf_Internal_Shdr *sec) { - unsigned long size, unw_ent_size, addr_size, nrelas, i; + unsigned long size, unw_ent_size, nrelas, i; Elf_Internal_Phdr *seg; struct hppa_unw_table_entry *tep; Elf_Internal_Shdr *relsec; @@ -4755,8 +4776,6 @@ slurp_hppa_unwind_table (FILE *file, Elf_Internal_Sym *sym; const char *relname; - addr_size = is_32bit_elf ? 4 : 8; - /* First, find the starting address of the segment that includes this section. */ @@ -4788,11 +4807,11 @@ slurp_hppa_unwind_table (FILE *file, if (!table) return 0; - unw_ent_size = 2 * addr_size + 8; + unw_ent_size = 2 * eh_addr_size + 8; tep = aux->table = xmalloc (size / unw_ent_size * sizeof (aux->table[0])); - for (tp = table; tp < table + size; tp += (2 * addr_size + 8), ++tep) + for (tp = table; tp < table + size; tp += (2 * eh_addr_size + 8), ++tep) { unsigned int tmp1, tmp2; @@ -4887,7 +4906,7 @@ slurp_hppa_unwind_table (FILE *file, i = rp->r_offset / unw_ent_size; - switch ((rp->r_offset % unw_ent_size) / addr_size) + switch ((rp->r_offset % unw_ent_size) / eh_addr_size) { case 0: aux->table[i].start.section = sym->st_shndx; @@ -4917,13 +4936,11 @@ hppa_process_unwind (FILE *file) Elf_Internal_Shdr *unwsec = NULL; Elf_Internal_Shdr *strsec; Elf_Internal_Shdr *sec; - unsigned long addr_size; unsigned long i; memset (& aux, 0, sizeof (aux)); assert (string_table != NULL); - addr_size = is_32bit_elf ? 4 : 8; for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec) { @@ -4953,7 +4970,7 @@ hppa_process_unwind (FILE *file) printf (_(" at offset 0x%lx contains %lu entries:\n"), (unsigned long) sec->sh_offset, - (unsigned long) (sec->sh_size / (2 * addr_size + 8))); + (unsigned long) (sec->sh_size / (2 * eh_addr_size + 8))); slurp_hppa_unwind_table (file, &aux, sec); if (aux.table_len > 0) @@ -7050,26 +7067,6 @@ process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size) return len; } -/* Finds section NAME inside FILE and returns a - pointer to it, or NULL upon failure. */ - -static Elf_Internal_Shdr * -find_section (const char * name) -{ - Elf_Internal_Shdr *sec; - unsigned int i; - - for (i = elf_header.e_shnum, sec = section_headers + i - 1; - i; --i, --sec) - if (streq (SECTION_NAME (sec), name)) - break; - - if (i && sec && sec->sh_size != 0) - return sec; - - return NULL; -} - static const char *debug_str_contents; static bfd_vma debug_str_size; @@ -9913,7 +9910,7 @@ size_of_encoded_value (int encoding) switch (encoding & 0x7) { default: /* ??? */ - case 0: return is_32bit_elf ? 4 : 8; + case 0: return eh_addr_size; case 2: return 2; case 3: return 4; case 4: return 8; @@ -9947,7 +9944,6 @@ display_debug_frames (Elf_Internal_Shdr *section, int is_eh = streq (SECTION_NAME (section), ".eh_frame"); int length_return; int max_regs = 0; - int addr_size = is_32bit_elf ? 4 : 8; printf (_("The section %s contains:\n"), SECTION_NAME (section)); @@ -9962,7 +9958,7 @@ display_debug_frames (Elf_Internal_Shdr *section, int need_col_headers = 1; unsigned char *augmentation_data = NULL; unsigned long augmentation_data_len = 0; - int encoded_ptr_size = addr_size; + int encoded_ptr_size = eh_addr_size; int offset_size; int initial_length_size; @@ -10035,7 +10031,7 @@ display_debug_frames (Elf_Internal_Shdr *section, } else if (streq (fc->augmentation, "eh")) { - start += addr_size; + start += eh_addr_size; fc->code_factor = LEB (); fc->data_factor = SLEB (); if (version == 1) @@ -10515,7 +10511,7 @@ display_debug_frames (Elf_Internal_Shdr *section, if (! do_debug_frames_interp) { printf (" DW_CFA_def_cfa_expression ("); - decode_location_expression (start, addr_size, ul, 0); + decode_location_expression (start, eh_addr_size, ul, 0); printf (")\n"); } fc->cfa_exp = 1; @@ -10528,7 +10524,7 @@ display_debug_frames (Elf_Internal_Shdr *section, if (! do_debug_frames_interp) { printf (" DW_CFA_expression: r%ld (", reg); - decode_location_expression (start, addr_size, ul, 0); + decode_location_expression (start, eh_addr_size, ul, 0); printf (")\n"); } fc->col_type[reg] = DW_CFA_expression; -- 2.30.2