* readelf.c (ia64_process_unwind): Turn into a void funtion.

(hppa_process_unwind): Likewise.
	(arm_process_unwind): Likewise.
	(process_unwind): Likewise.
	(arm_get_section_word): Rename to get_unwind_section_word.
	Add sym_name parameter to return the offset into the string table
	of the symbol associated with the reloc applied to the word.
	(decode_tic6x_unwind_regmask): Add NULL argument to invocation of
	get_unwind_section_word.
	(dump_arm_unwind): Likewise.
	(decode_arm_unwind_bytecode): Prepend a comma when *not* the first
	register in a list.
	(decode_arm_unwind): If the returned function address is 0 and a
	valid symname offset is provided use that to compute the name
	associated with the entry.
	Add extra checks of the compact model index entry.
This commit is contained in:
Nick Clifton 2011-12-02 17:04:33 +00:00
parent 585861ead5
commit 1b31d05e6b
2 changed files with 132 additions and 68 deletions

View File

@ -1,3 +1,22 @@
2011-12-02 Nick Clifton <nickc@redhat.com>
* readelf.c (ia64_process_unwind): Turn into a void funtion.
(hppa_process_unwind): Likewise.
(arm_process_unwind): Likewise.
(process_unwind): Likewise.
(arm_get_section_word): Rename to get_unwind_section_word.
Add sym_name parameter to return the offset into the string table
of the symbol associated with the reloc applied to the word.
(decode_tic6x_unwind_regmask): Add NULL argument to invocation of
get_unwind_section_word.
(dump_arm_unwind): Likewise.
(decode_arm_unwind_bytecode): Prepend a comma when *not* the first
register in a list.
(decode_arm_unwind): If the returned function address is 0 and a
valid symname offset is provided use that to compute the name
associated with the entry.
Add extra checks of the compact model index entry.
2011-11-29 Roland McGrath <mcgrathr@google.com>
* ar.c (ranlib_usage): Describe -D.

View File

@ -3187,7 +3187,7 @@ usage (FILE * stream)
-u --unwind Display the unwind info (if present)\n\
-d --dynamic Display the dynamic section (if present)\n\
-V --version-info Display the version sections (if present)\n\
-A --arch-specific Display architecture specific information (if any).\n\
-A --arch-specific Display architecture specific information (if any)\n\
-c --archive-index Display the symbol/file index in an archive\n\
-D --use-dynamic Use the dynamic section info when displaying symbols\n\
-x --hex-dump=<number|name>\n\
@ -5595,6 +5595,7 @@ find_symbol_for_address (Elf_Internal_Sym * symtab,
break;
}
}
if (best)
{
*symname = (best->st_name >= strtab_size
@ -5602,6 +5603,7 @@ find_symbol_for_address (Elf_Internal_Sym * symtab,
*offset = dist;
return;
}
*symname = NULL;
*offset = addr.offset;
}
@ -5779,7 +5781,7 @@ slurp_ia64_unwind_table (FILE * file,
return 1;
}
static int
static void
ia64_process_unwind (FILE * file)
{
Elf_Internal_Shdr * sec;
@ -5916,8 +5918,6 @@ ia64_process_unwind (FILE * file)
free (aux.symtab);
if (aux.strtab)
free ((char *) aux.strtab);
return 1;
}
struct hppa_unw_table_entry
@ -6189,7 +6189,7 @@ slurp_hppa_unwind_table (FILE * file,
return 1;
}
static int
static void
hppa_process_unwind (FILE * file)
{
struct hppa_unw_aux_info aux;
@ -6198,10 +6198,10 @@ hppa_process_unwind (FILE * file)
Elf_Internal_Shdr * sec;
unsigned long i;
memset (& aux, 0, sizeof (aux));
if (string_table == NULL)
return 1;
return;
memset (& aux, 0, sizeof (aux));
for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
{
@ -6249,8 +6249,6 @@ hppa_process_unwind (FILE * file)
free (aux.symtab);
if (aux.strtab)
free ((char *) aux.strtab);
return 1;
}
struct arm_section
@ -6315,17 +6313,21 @@ arm_free_section (struct arm_section *arm_sec)
cached section and install SEC instead.
2) Locate the 32-bit word at WORD_OFFSET in unwind section SEC
and return its valued in * WORDP, relocating if necessary.
3) Update the NEXT_RELA field in ARM_SEC and stores the section index and
3) Update the NEXT_RELA field in ARM_SEC and store the section index and
relocation's offset in ADDR.
4) Return TRUE upon success, FALSE otherwise. */
4) If SYM_NAME is non-NULL and a relocation was applied, record the offset
into the string table of the symbol associated with the reloc. If no
reloc was applied store -1 there.
5) Return TRUE upon success, FALSE otherwise. */
static bfd_boolean
arm_section_get_word (struct arm_unw_aux_info * aux,
struct arm_section * arm_sec,
Elf_Internal_Shdr * sec,
bfd_vma word_offset,
unsigned int * wordp,
struct absaddr * addr)
get_unwind_section_word (struct arm_unw_aux_info * aux,
struct arm_section * arm_sec,
Elf_Internal_Shdr * sec,
bfd_vma word_offset,
unsigned int * wordp,
struct absaddr * addr,
bfd_vma * sym_name)
{
Elf_Internal_Rela *rp;
Elf_Internal_Sym *sym;
@ -6336,6 +6338,9 @@ arm_section_get_word (struct arm_unw_aux_info * aux,
addr->section = SHN_UNDEF;
addr->offset = 0;
if (sym_name != NULL)
*sym_name = (bfd_vma) -1;
/* If necessary, update the section cache. */
if (sec != arm_sec->sec)
{
@ -6465,6 +6470,8 @@ arm_section_get_word (struct arm_unw_aux_info * aux,
word = (word & ~ (bfd_vma) 0x7fffffff) | (prelval & 0x7fffffff);
addr->section = sym->st_shndx;
addr->offset = offset;
if (sym_name)
* sym_name = sym->st_name;
break;
}
@ -6501,8 +6508,8 @@ decode_tic6x_unwind_regmask (unsigned int mask)
if (remaining == 0 && more_words) \
{ \
data_offset += 4; \
if (!arm_section_get_word (aux, data_arm_sec, data_sec, \
data_offset, &word, &addr)) \
if (! get_unwind_section_word (aux, data_arm_sec, data_sec, \
data_offset, & word, & addr, NULL)) \
return; \
remaining = 4; \
more_words--; \
@ -6606,7 +6613,7 @@ decode_arm_unwind_bytecode (struct arm_unw_aux_info *aux,
}
if (op & 0x08)
{
if (first)
if (!first)
printf (", ");
printf ("r14");
}
@ -6883,21 +6890,29 @@ arm_expand_prel31 (bfd_vma word, bfd_vma where)
}
static void
decode_arm_unwind (struct arm_unw_aux_info *aux,
unsigned int word, unsigned int remaining,
bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
struct arm_section *data_arm_sec)
decode_arm_unwind (struct arm_unw_aux_info * aux,
unsigned int word,
unsigned int remaining,
bfd_vma data_offset,
Elf_Internal_Shdr * data_sec,
struct arm_section * data_arm_sec)
{
int per_index;
unsigned int more_words = 0;
struct absaddr addr;
bfd_vma sym_name = (bfd_vma) -1;
if (remaining == 0)
{
/* Fetch the first word. */
if (!arm_section_get_word (aux, data_arm_sec, data_sec, data_offset,
&word, &addr))
/* Fetch the first word.
Note - when decoding an object file the address extracted
here will always be 0. So we also pass in the sym_name
parameter so that we can find the symbol associated with
the personality routine. */
if (! get_unwind_section_word (aux, data_arm_sec, data_sec, data_offset,
& word, & addr, & sym_name))
return;
remaining = 4;
}
@ -6909,7 +6924,21 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
fn = arm_expand_prel31 (word, data_sec->sh_addr + data_offset);
printf (_(" Personality routine: "));
procname = arm_print_vma_and_name (aux, fn, addr);
if (fn == 0
&& addr.section == SHN_UNDEF && addr.offset == 0
&& sym_name != (bfd_vma) -1 && sym_name < aux->strtab_size)
{
procname = aux->strtab + sym_name;
print_vma (fn, PREFIX_HEX);
if (procname)
{
fputs (" <", stdout);
fputs (procname, stdout);
fputc ('>', stdout);
}
}
else
procname = arm_print_vma_and_name (aux, fn, addr);
fputc ('\n', stdout);
/* The GCC personality routines use the standard compact
@ -6939,9 +6968,20 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
}
else
{
/* ARM EHABI Section 6.3:
An exception-handling table entry for the compact model looks like:
31 30-28 27-24 23-0
-- ----- ----- ----
1 0 index Data for personalityRoutine[index] */
if (elf_header.e_machine == EM_ARM
&& (word & 0x70000000))
warn (_("Corrupt ARM compact model table entry (%08x)\n"), word);
per_index = (word >> 24) & 0x7f;
printf (_(" Compact model %d\n"), per_index);
printf (_(" Compact model index: %d\n"), per_index);
if (per_index == 0)
{
more_words = 0;
@ -6965,14 +7005,17 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
data_offset, data_sec, data_arm_sec);
}
else
printf (" [reserved]\n");
{
warn (_("Unknown ARM compact model index encountered\n"));
printf (_(" [reserved]\n"));
}
break;
case EM_TI_C6000:
if (per_index < 3)
{
decode_tic6x_unwind_bytecode (aux, word, remaining, more_words,
data_offset, data_sec, data_arm_sec);
data_offset, data_sec, data_arm_sec);
}
else if (per_index < 5)
{
@ -6989,11 +7032,12 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
tic6x_unwind_regnames[word & 0xf]);
}
else
printf (" [reserved]\n");
printf (_(" [reserved (%d)]\n"), per_index);
break;
default:
abort ();
error (_("Unsupported architecture type %d encountered when decoding unwind table"),
elf_header.e_machine);
}
/* Decode the descriptors. Not implemented. */
@ -7017,13 +7061,13 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
fputc ('\n', stdout);
if (!arm_section_get_word (aux, &exidx_arm_sec, exidx_sec,
8 * i, &exidx_fn, &fn_addr)
|| !arm_section_get_word (aux, &exidx_arm_sec, exidx_sec,
8 * i + 4, &exidx_entry, &entry_addr))
if (! get_unwind_section_word (aux, & exidx_arm_sec, exidx_sec,
8 * i, & exidx_fn, & fn_addr, NULL)
|| ! get_unwind_section_word (aux, & exidx_arm_sec, exidx_sec,
8 * i + 4, & exidx_entry, & entry_addr, NULL))
{
arm_free_section (&exidx_arm_sec);
arm_free_section (&extab_arm_sec);
arm_free_section (& exidx_arm_sec);
arm_free_section (& extab_arm_sec);
return;
}
@ -7084,7 +7128,8 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
}
/* Used for both ARM and C6X unwinding tables. */
static int
static void
arm_process_unwind (FILE *file)
{
struct arm_unw_aux_info aux;
@ -7094,9 +7139,6 @@ arm_process_unwind (FILE *file)
unsigned long i;
unsigned int sec_type;
memset (& aux, 0, sizeof (aux));
aux.file = file;
switch (elf_header.e_machine)
{
case EM_ARM:
@ -7107,12 +7149,17 @@ arm_process_unwind (FILE *file)
sec_type = SHT_C6000_UNWIND;
break;
default:
abort();
default:
error (_("Unsupported architecture type %d encountered when processing unwind table"),
elf_header.e_machine);
return;
}
if (string_table == NULL)
return 1;
return;
memset (& aux, 0, sizeof (aux));
aux.file = file;
for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
{
@ -7130,37 +7177,35 @@ arm_process_unwind (FILE *file)
unwsec = sec;
}
if (!unwsec)
if (unwsec == NULL)
printf (_("\nThere are no unwind sections in this file.\n"));
else
for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
{
if (sec->sh_type == sec_type)
{
printf (_("\nUnwind table index '%s' at offset 0x%lx contains %lu entries:\n"),
SECTION_NAME (sec),
(unsigned long) sec->sh_offset,
(unsigned long) (sec->sh_size / (2 * eh_addr_size)));
for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
{
if (sec->sh_type == sec_type)
{
printf (_("\nUnwind table index '%s' at offset 0x%lx contains %lu entries:\n"),
SECTION_NAME (sec),
(unsigned long) sec->sh_offset,
(unsigned long) (sec->sh_size / (2 * eh_addr_size)));
dump_arm_unwind (&aux, sec);
}
}
dump_arm_unwind (&aux, sec);
}
}
if (aux.symtab)
free (aux.symtab);
if (aux.strtab)
free ((char *) aux.strtab);
return 1;
}
static int
static void
process_unwind (FILE * file)
{
struct unwind_handler
{
int machtype;
int (* handler)(FILE *);
void (* handler)(FILE *);
} handlers[] =
{
{ EM_ARM, arm_process_unwind },
@ -7172,14 +7217,14 @@ process_unwind (FILE * file)
int i;
if (!do_unwind)
return 1;
return;
for (i = 0; handlers[i].handler != NULL; i++)
if (elf_header.e_machine == handlers[i].machtype)
return handlers[i].handler (file);
printf (_("\nThere are no unwind sections in this file.\n"));
return 1;
printf (_("\nThe decoding of unwind sections for machine type %s is not currently supported.\n"),
get_machine_name (elf_header.e_machine));
}
static void