aboutsummaryrefslogtreecommitdiff
path: root/binutils/readelf.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>1999-05-28 10:14:11 +0000
committerNick Clifton <nickc@redhat.com>1999-05-28 10:14:11 +0000
commit9c19a80986dd5a5b9a7f52bbbfa3318313427bb8 (patch)
treea01306995191d2679c47de05d13b7f413055c704 /binutils/readelf.c
parent633fd09f3cfd79906b88fc1adcd2c16f39e9848e (diff)
downloadgdb-9c19a80986dd5a5b9a7f52bbbfa3318313427bb8.zip
gdb-9c19a80986dd5a5b9a7f52bbbfa3318313427bb8.tar.gz
gdb-9c19a80986dd5a5b9a7f52bbbfa3318313427bb8.tar.bz2
Better coping with different reloc types.
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r--binutils/readelf.c189
1 files changed, 119 insertions, 70 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 520344c..d2e1552 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -118,7 +118,7 @@ unsigned int num_dump_sects = 0;
static unsigned long (* byte_get) PARAMS ((unsigned char *, int));
static const char * get_mips_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_machine_name PARAMS ((unsigned e_machine));
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_data_encoding PARAMS ((unsigned char));
static const char * get_osabi_name PARAMS ((unsigned char));
+static int guess_is_rela PARAMS ((unsigned long));
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 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
- found at the specified offset. */
+/* Guess the relocation sized based on the sized commonly used by the specific machine. */
static int
-dump_relocations (file, rel_offset, rel_size, symtab, strtab)
- FILE * file;
- unsigned long rel_offset;
- unsigned long rel_size;
- Elf_Internal_Sym * symtab;
- char * strtab;
+guess_is_rela (e_machine)
+ unsigned long e_machine;
{
- unsigned int i;
- int is_rela;
- Elf_Internal_Rel * rels;
- Elf_Internal_Rela * relas;
-
-
- /* Compute number of relocations and read them in. */
- switch (elf_header.e_machine)
+ switch (e_machine)
{
/* Targets that use REL relocations. */
case EM_ARM:
@@ -357,30 +352,8 @@ dump_relocations (file, rel_offset, rel_size, symtab, strtab)
case EM_CYGNUS_D10V:
case EM_MIPS:
case EM_MIPS_RS4_BE:
- {
- 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;
-
+ return FALSE;
+
/* Targets that use RELA relocations. */
case EM_68K:
case EM_SPARC:
@@ -390,37 +363,95 @@ dump_relocations (file, rel_offset, rel_size, symtab, strtab)
case EM_CYGNUS_MN10200:
case EM_CYGNUS_MN10300:
case EM_CYGNUS_FR30:
+/* start-sanitize-venus */
+ case EM_CYGNUS_VENUS:
+/* end-sanitize-venus */
case EM_SH:
case EM_ALPHA:
case EM_MCORE:
- {
- 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));
+ return TRUE;
+
+ default:
+ warn (_("Don't know about relocations on this machine architecture\n"));
+ return FALSE;
+ }
+}
- 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);
- }
+/* 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;
- free (erelas);
+
+ if (is_rela == UNKNOWN)
+ is_rela = guess_is_rela (elf_header.e_machine);
- is_rela = 1;
- rels = (Elf_Internal_Rel *) relas;
- }
- break;
+ 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;
- default:
- warn (_("Don't know about relocations on this machine architecture\n"));
- return 0;
+ 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)
@@ -1827,6 +1858,8 @@ process_relocs (file)
if (do_using_dynamic)
{
+ int is_rela;
+
rel_size = 0;
rel_offset = 0;
@@ -1834,16 +1867,19 @@ process_relocs (file)
{
rel_offset = dynamic_info[DT_REL];
rel_size = dynamic_info[DT_RELSZ];
+ is_rela = FALSE;
}
else if (dynamic_info [DT_RELA])
{
rel_offset = dynamic_info[DT_RELA];
rel_size = dynamic_info[DT_RELASZ];
+ is_rela = TRUE;
}
else if (dynamic_info[DT_JMPREL])
{
rel_offset = dynamic_info[DT_JMPREL];
rel_size = dynamic_info[DT_PLTRELSZ];
+ is_rela = UNKNOWN;
}
if (rel_size)
@@ -1853,7 +1889,7 @@ process_relocs (file)
rel_offset, rel_size);
dump_relocations (file, rel_offset - loadaddr, rel_size,
- dynamic_symbols, dynamic_strings);
+ dynamic_symbols, dynamic_strings, is_rela);
}
else
printf (_("\nThere are no dynamic relocations in this file.\n"));
@@ -1881,13 +1917,26 @@ process_relocs (file)
Elf32_Internal_Shdr * symsec;
Elf_Internal_Sym * symtab;
char * strtab;
-
+ int is_rela;
+
printf (_("\nRelocation section "));
if (string_table == NULL)
- printf ("%d", section->sh_name);
+ {
+ printf ("%d", section->sh_name);
+ is_rela = UNKNOWN;
+ }
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"),
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,
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 (symtab);