Better coping with different reloc types.

This commit is contained in:
Nick Clifton 1999-05-28 10:14:11 +00:00
parent 633fd09f3c
commit 9c19a80986
2 changed files with 131 additions and 72 deletions

View file

@ -1,3 +1,13 @@
1999-05-28 Nick Clifton <nickc@cygnus.com>
* readelf.c (dump_relocations): Add extra parameter: is_rela to
specify the kind of relocations to be dumped. Call guess_is_rela
if this parameter has a value of UNKNOWN.
(guess_is_rela): New function: Guess the kind of reloc being used
baced on the machine number.
(process_relocs): Determine type of reloc before calling
dump_relocations.
1999-05-28 Ian Lance Taylor <ian@zembu.com> 1999-05-28 Ian Lance Taylor <ian@zembu.com>
* readelf.c: Include "elf/i960.h". * readelf.c: Include "elf/i960.h".

View file

@ -118,7 +118,7 @@ unsigned int num_dump_sects = 0;
static unsigned long (* byte_get) PARAMS ((unsigned char *, int)); static unsigned long (* byte_get) PARAMS ((unsigned char *, int));
static const char * get_mips_dynamic_type PARAMS ((unsigned long type)); static const char * get_mips_dynamic_type PARAMS ((unsigned long type));
static const char * get_dynamic_type PARAMS ((unsigned long type)); static const char * get_dynamic_type PARAMS ((unsigned long type));
static int dump_relocations PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *)); static int dump_relocations PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, char *, int));
static char * get_file_type PARAMS ((unsigned e_type)); static char * get_file_type PARAMS ((unsigned e_type));
static char * get_machine_name PARAMS ((unsigned e_machine)); static char * get_machine_name PARAMS ((unsigned e_machine));
static char * get_machine_data PARAMS ((unsigned e_data)); static char * get_machine_data PARAMS ((unsigned e_data));
@ -174,9 +174,16 @@ static void request_dump PARAMS ((unsigned int, char));
static const char * get_elf_class PARAMS ((unsigned char)); static const char * get_elf_class PARAMS ((unsigned char));
static const char * get_data_encoding PARAMS ((unsigned char)); static const char * get_data_encoding PARAMS ((unsigned char));
static const char * get_osabi_name PARAMS ((unsigned char)); static const char * get_osabi_name PARAMS ((unsigned char));
static int guess_is_rela PARAMS ((unsigned long));
typedef int Elf32_Word; typedef int Elf32_Word;
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define UNKNOWN -1
#define SECTION_NAME(X) (string_table + (X)->sh_name) #define SECTION_NAME(X) (string_table + (X)->sh_name)
#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
@ -329,24 +336,12 @@ byte_get_big_endian (field, size)
} }
/* Display the contents of the relocation data /* Guess the relocation sized based on the sized commonly used by the specific machine. */
found at the specified offset. */
static int static int
dump_relocations (file, rel_offset, rel_size, symtab, strtab) guess_is_rela (e_machine)
FILE * file; unsigned long e_machine;
unsigned long rel_offset;
unsigned long rel_size;
Elf_Internal_Sym * symtab;
char * strtab;
{ {
unsigned int i; switch (e_machine)
int is_rela;
Elf_Internal_Rel * rels;
Elf_Internal_Rela * relas;
/* Compute number of relocations and read them in. */
switch (elf_header.e_machine)
{ {
/* Targets that use REL relocations. */ /* Targets that use REL relocations. */
case EM_ARM: case EM_ARM:
@ -357,30 +352,8 @@ dump_relocations (file, rel_offset, rel_size, symtab, strtab)
case EM_CYGNUS_D10V: case EM_CYGNUS_D10V:
case EM_MIPS: case EM_MIPS:
case EM_MIPS_RS4_BE: case EM_MIPS_RS4_BE:
{ return FALSE;
Elf32_External_Rel * erels;
GET_DATA_ALLOC (rel_offset, rel_size, erels,
Elf32_External_Rel *, "relocs");
rel_size = rel_size / sizeof (Elf32_External_Rel);
rels = (Elf_Internal_Rel *) malloc (rel_size *
sizeof (Elf_Internal_Rel));
for (i = 0; i < rel_size; i++)
{
rels[i].r_offset = BYTE_GET (erels[i].r_offset);
rels[i].r_info = BYTE_GET (erels[i].r_info);
}
free (erels);
is_rela = 0;
relas = (Elf_Internal_Rela *) rels;
}
break;
/* Targets that use RELA relocations. */ /* Targets that use RELA relocations. */
case EM_68K: case EM_68K:
case EM_SPARC: case EM_SPARC:
@ -390,37 +363,95 @@ dump_relocations (file, rel_offset, rel_size, symtab, strtab)
case EM_CYGNUS_MN10200: case EM_CYGNUS_MN10200:
case EM_CYGNUS_MN10300: case EM_CYGNUS_MN10300:
case EM_CYGNUS_FR30: case EM_CYGNUS_FR30:
/* start-sanitize-venus */
case EM_CYGNUS_VENUS:
/* end-sanitize-venus */
case EM_SH: case EM_SH:
case EM_ALPHA: case EM_ALPHA:
case EM_MCORE: case EM_MCORE:
{ return TRUE;
Elf32_External_Rela * erelas;
GET_DATA_ALLOC (rel_offset, rel_size, erelas,
Elf32_External_Rela *, "relocs");
rel_size = rel_size / sizeof (Elf32_External_Rela);
relas = (Elf_Internal_Rela *) malloc (rel_size *
sizeof (Elf_Internal_Rela));
for (i = 0; i < rel_size; i++)
{
relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
relas[i].r_info = BYTE_GET (erelas[i].r_info);
relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
}
free (erelas);
is_rela = 1;
rels = (Elf_Internal_Rel *) relas;
}
break;
default: default:
warn (_("Don't know about relocations on this machine architecture\n")); warn (_("Don't know about relocations on this machine architecture\n"));
return 0; return FALSE;
}
}
/* Display the contents of the relocation data
found at the specified offset. */
static int
dump_relocations (file, rel_offset, rel_size, symtab, strtabm, is_rela)
FILE * file;
unsigned long rel_offset;
unsigned long rel_size;
Elf_Internal_Sym * symtab;
char * strtab;
int is_rela;
{
unsigned int i;
Elf_Internal_Rel * rels;
Elf_Internal_Rela * relas;
if (is_rela == UNKNOWN)
is_rela = guess_is_rela (elf_header.e_machine);
if (is_rela)
{
Elf32_External_Rela * erelas;
GET_DATA_ALLOC (rel_offset, rel_size, erelas,
Elf32_External_Rela *, "relocs");
rel_size = rel_size / sizeof (Elf32_External_Rela);
relas = (Elf_Internal_Rela *) malloc (rel_size *
sizeof (Elf_Internal_Rela));
if (relas == NULL)
{
error(_("out of memory parsing relocs"));
return 0;
}
for (i = 0; i < rel_size; i++)
{
relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
relas[i].r_info = BYTE_GET (erelas[i].r_info);
relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
}
free (erelas);
rels = (Elf_Internal_Rel *) relas;
}
else
{
Elf32_External_Rel * erels;
unsigned long saved_rel_size = rel_size;
GET_DATA_ALLOC (rel_offset, rel_size, erels,
Elf32_External_Rel *, "relocs");
rel_size = rel_size / sizeof (Elf32_External_Rel);
rels = (Elf_Internal_Rel *) malloc (rel_size *
sizeof (Elf_Internal_Rel));
if (rels == NULL)
{
error(_("out of memory parsing relocs"));
return 0;
}
for (i = 0; i < rel_size; i++)
{
rels[i].r_offset = BYTE_GET (erels[i].r_offset);
rels[i].r_info = BYTE_GET (erels[i].r_info);
}
free (erels);
relas = (Elf_Internal_Rela *) rels;
} }
if (is_rela) if (is_rela)
@ -1827,6 +1858,8 @@ process_relocs (file)
if (do_using_dynamic) if (do_using_dynamic)
{ {
int is_rela;
rel_size = 0; rel_size = 0;
rel_offset = 0; rel_offset = 0;
@ -1834,16 +1867,19 @@ process_relocs (file)
{ {
rel_offset = dynamic_info[DT_REL]; rel_offset = dynamic_info[DT_REL];
rel_size = dynamic_info[DT_RELSZ]; rel_size = dynamic_info[DT_RELSZ];
is_rela = FALSE;
} }
else if (dynamic_info [DT_RELA]) else if (dynamic_info [DT_RELA])
{ {
rel_offset = dynamic_info[DT_RELA]; rel_offset = dynamic_info[DT_RELA];
rel_size = dynamic_info[DT_RELASZ]; rel_size = dynamic_info[DT_RELASZ];
is_rela = TRUE;
} }
else if (dynamic_info[DT_JMPREL]) else if (dynamic_info[DT_JMPREL])
{ {
rel_offset = dynamic_info[DT_JMPREL]; rel_offset = dynamic_info[DT_JMPREL];
rel_size = dynamic_info[DT_PLTRELSZ]; rel_size = dynamic_info[DT_PLTRELSZ];
is_rela = UNKNOWN;
} }
if (rel_size) if (rel_size)
@ -1853,7 +1889,7 @@ process_relocs (file)
rel_offset, rel_size); rel_offset, rel_size);
dump_relocations (file, rel_offset - loadaddr, rel_size, dump_relocations (file, rel_offset - loadaddr, rel_size,
dynamic_symbols, dynamic_strings); dynamic_symbols, dynamic_strings, is_rela);
} }
else else
printf (_("\nThere are no dynamic relocations in this file.\n")); printf (_("\nThere are no dynamic relocations in this file.\n"));
@ -1881,13 +1917,26 @@ process_relocs (file)
Elf32_Internal_Shdr * symsec; Elf32_Internal_Shdr * symsec;
Elf_Internal_Sym * symtab; Elf_Internal_Sym * symtab;
char * strtab; char * strtab;
int is_rela;
printf (_("\nRelocation section ")); printf (_("\nRelocation section "));
if (string_table == NULL) if (string_table == NULL)
printf ("%d", section->sh_name); {
printf ("%d", section->sh_name);
is_rela = UNKNOWN;
}
else else
printf ("'%s'", SECTION_NAME (section)); {
printf ("'%s'", SECTION_NAME (section));
if (strncmp (".rela.", SECTION_NAME (section), 6) == 0)
is_rela = TRUE;
else if (strncmp (".rel.", SECTION_NAME (section), 5) == 0)
is_rela = FALSE;
else
is_rela = UNKNOWN;
}
printf (_(" at offset 0x%lx contains %lu entries:\n"), printf (_(" at offset 0x%lx contains %lu entries:\n"),
rel_offset, (unsigned long) (rel_size / section->sh_entsize)); rel_offset, (unsigned long) (rel_size / section->sh_entsize));
@ -1905,7 +1954,7 @@ process_relocs (file)
GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab, GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab,
char *, "string table"); char *, "string table");
dump_relocations (file, rel_offset, rel_size, symtab, strtab); dump_relocations (file, rel_offset, rel_size, symtab, strtab, is_rela);
free (strtab); free (strtab);
free (symtab); free (symtab);