mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
readelf: Support SHT_RELR/DT_RELR for -r
The -r output for SHT_RELR looks like: Relocation section '.relr.dyn' at offset 0x530 contains 4 entries: 7 offsets 00000000000028c0 00000000000028c8 0000000000003ad0 0000000000003ad8 0000000000003ae0 0000000000003ae8 0000000000003af0 For --use-dynamic, the header looks like 'RELR' relocation section at offset 0x530 contains 32 bytes: include/ * elf/common.h (DT_ENCODING): Bump to 38. * elf/external.h (Elf32_External_Relr): New. (Elf64_External_Relr): New. binutils/ * readelf.c (enum relocation_type): New. (slurp_relr_relocs): New. (dump_relocations): Change is_rela to rel_type. Dump RELR. (dynamic_relocations): Add DT_RELR. (process_relocs): Check SHT_RELR and DT_RELR. (process_dynamic_section): Store into dynamic_info for DT_RELR/DT_RELRENT/DT_RELRSZ.
This commit is contained in:
parent
830070c66d
commit
a7fd118627
@ -1,3 +1,14 @@
|
||||
2021-11-16 Fangrui Song <maskray@google.com>
|
||||
|
||||
* readelf.c (enum relocation_type): New.
|
||||
(slurp_relr_relocs): New.
|
||||
(dump_relocations): Change is_rela to rel_type.
|
||||
Dump RELR.
|
||||
(dynamic_relocations): Add DT_RELR.
|
||||
(process_relocs): Check SHT_RELR and DT_RELR.
|
||||
(process_dynamic_section): Store into dynamic_info for
|
||||
DT_RELR/DT_RELRENT/DT_RELRSZ.
|
||||
|
||||
2021-11-09 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* nm.c: Add --unicode option to control how unicode characters are
|
||||
|
@ -11,6 +11,8 @@
|
||||
using --unicode=highlight will display them as unicode escape sequences
|
||||
highlighted in red (if supported by the output device).
|
||||
|
||||
* readelf -r dumps RELR relative relocations now.
|
||||
|
||||
Changes in 2.37:
|
||||
|
||||
* The readelf tool has a new command line option which can be used to specify
|
||||
|
@ -342,6 +342,13 @@ typedef enum unicode_display_type
|
||||
|
||||
static unicode_display_type unicode_display = unicode_default;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
reltype_unknown,
|
||||
reltype_rel,
|
||||
reltype_rela,
|
||||
reltype_relr
|
||||
} relocation_type;
|
||||
|
||||
/* Versioned symbol info. */
|
||||
enum versioned_symbol_info
|
||||
@ -1354,6 +1361,76 @@ slurp_rel_relocs (Filedata * filedata,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
slurp_relr_relocs (Filedata * filedata,
|
||||
unsigned long relr_offset,
|
||||
unsigned long relr_size,
|
||||
bfd_vma ** relrsp,
|
||||
unsigned long * nrelrsp)
|
||||
{
|
||||
void *relrs;
|
||||
size_t size = 0, nentries, i;
|
||||
bfd_vma base = 0, addr, entry;
|
||||
|
||||
relrs = get_data (NULL, filedata, relr_offset, 1, relr_size,
|
||||
_("RELR relocation data"));
|
||||
if (!relrs)
|
||||
return false;
|
||||
|
||||
if (is_32bit_elf)
|
||||
nentries = relr_size / sizeof (Elf32_External_Relr);
|
||||
else
|
||||
nentries = relr_size / sizeof (Elf64_External_Relr);
|
||||
for (i = 0; i < nentries; i++)
|
||||
{
|
||||
if (is_32bit_elf)
|
||||
entry = BYTE_GET (((Elf32_External_Relr *)relrs)[i].r_data);
|
||||
else
|
||||
entry = BYTE_GET (((Elf64_External_Relr *)relrs)[i].r_data);
|
||||
if ((entry & 1) == 0)
|
||||
size++;
|
||||
else
|
||||
while ((entry >>= 1) != 0)
|
||||
if ((entry & 1) == 1)
|
||||
size++;
|
||||
}
|
||||
|
||||
*relrsp = (bfd_vma *) xmalloc (size * sizeof (bfd_vma));
|
||||
if (*relrsp == NULL)
|
||||
{
|
||||
free (relrs);
|
||||
error (_("out of memory parsing relocs\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < nentries; i++)
|
||||
{
|
||||
const bfd_vma entry_bytes = is_32bit_elf ? 4 : 8;
|
||||
|
||||
if (is_32bit_elf)
|
||||
entry = BYTE_GET (((Elf32_External_Relr *)relrs)[i].r_data);
|
||||
else
|
||||
entry = BYTE_GET (((Elf64_External_Relr *)relrs)[i].r_data);
|
||||
if ((entry & 1) == 0)
|
||||
{
|
||||
(*relrsp)[size++] = entry;
|
||||
base = entry + entry_bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (addr = base; (entry >>= 1) != 0; addr += entry_bytes)
|
||||
if ((entry & 1) != 0)
|
||||
(*relrsp)[size++] = addr;
|
||||
base += entry_bytes * (entry_bytes * CHAR_BIT - 1);
|
||||
}
|
||||
}
|
||||
|
||||
*nrelrsp = size;
|
||||
free (relrs);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Returns the reloc type extracted from the reloc info field. */
|
||||
|
||||
static unsigned int
|
||||
@ -1406,30 +1483,46 @@ dump_relocations (Filedata * filedata,
|
||||
unsigned long nsyms,
|
||||
char * strtab,
|
||||
unsigned long strtablen,
|
||||
int is_rela,
|
||||
relocation_type rel_type,
|
||||
bool is_dynsym)
|
||||
{
|
||||
unsigned long i;
|
||||
Elf_Internal_Rela * rels;
|
||||
bool res = true;
|
||||
|
||||
if (is_rela == UNKNOWN)
|
||||
is_rela = guess_is_rela (filedata->file_header.e_machine);
|
||||
if (rel_type == reltype_unknown)
|
||||
rel_type = guess_is_rela (filedata->file_header.e_machine) ? reltype_rela : reltype_rel;
|
||||
|
||||
if (is_rela)
|
||||
if (rel_type == reltype_rela)
|
||||
{
|
||||
if (!slurp_rela_relocs (filedata, rel_offset, rel_size, &rels, &rel_size))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
else if (rel_type == reltype_rel)
|
||||
{
|
||||
if (!slurp_rel_relocs (filedata, rel_offset, rel_size, &rels, &rel_size))
|
||||
return false;
|
||||
}
|
||||
else if (rel_type == reltype_relr)
|
||||
{
|
||||
bfd_vma * relrs;
|
||||
const char *format
|
||||
= is_32bit_elf ? "%08" BFD_VMA_FMT "x\n" : "%016" BFD_VMA_FMT "x\n";
|
||||
|
||||
if (!slurp_relr_relocs (filedata, rel_offset, rel_size, &relrs,
|
||||
&rel_size))
|
||||
return false;
|
||||
|
||||
printf (ngettext (" %lu offset\n", " %lu offsets\n", rel_size), rel_size);
|
||||
for (i = 0; i < rel_size; i++)
|
||||
printf (format, relrs[i]);
|
||||
free (relrs);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_32bit_elf)
|
||||
{
|
||||
if (is_rela)
|
||||
if (rel_type == reltype_rela)
|
||||
{
|
||||
if (do_wide)
|
||||
printf (_(" Offset Info Type Sym. Value Symbol's Name + Addend\n"));
|
||||
@ -1446,7 +1539,7 @@ dump_relocations (Filedata * filedata,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_rela)
|
||||
if (rel_type == reltype_rela)
|
||||
{
|
||||
if (do_wide)
|
||||
printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n"));
|
||||
@ -1841,7 +1934,7 @@ dump_relocations (Filedata * filedata,
|
||||
if (filedata->file_header.e_machine == EM_ALPHA
|
||||
&& rtype != NULL
|
||||
&& streq (rtype, "R_ALPHA_LITUSE")
|
||||
&& is_rela)
|
||||
&& rel_type == reltype_rela)
|
||||
{
|
||||
switch (rels[i].r_addend)
|
||||
{
|
||||
@ -1989,7 +2082,7 @@ dump_relocations (Filedata * filedata,
|
||||
version_string);
|
||||
}
|
||||
|
||||
if (is_rela)
|
||||
if (rel_type == reltype_rela)
|
||||
{
|
||||
bfd_vma off = rels[i].r_addend;
|
||||
|
||||
@ -2000,7 +2093,7 @@ dump_relocations (Filedata * filedata,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_rela)
|
||||
else if (rel_type == reltype_rela)
|
||||
{
|
||||
bfd_vma off = rels[i].r_addend;
|
||||
|
||||
@ -8021,13 +8114,14 @@ static struct
|
||||
const char * name;
|
||||
int reloc;
|
||||
int size;
|
||||
int rela;
|
||||
relocation_type rel_type;
|
||||
}
|
||||
dynamic_relocations [] =
|
||||
{
|
||||
{ "REL", DT_REL, DT_RELSZ, false },
|
||||
{ "RELA", DT_RELA, DT_RELASZ, true },
|
||||
{ "PLT", DT_JMPREL, DT_PLTRELSZ, UNKNOWN }
|
||||
{ "REL", DT_REL, DT_RELSZ, reltype_rel },
|
||||
{ "RELA", DT_RELA, DT_RELASZ, reltype_rela },
|
||||
{ "RELR", DT_RELR, DT_RELRSZ, reltype_relr },
|
||||
{ "PLT", DT_JMPREL, DT_PLTRELSZ, reltype_unknown }
|
||||
};
|
||||
|
||||
/* Process the reloc section. */
|
||||
@ -8043,7 +8137,7 @@ process_relocs (Filedata * filedata)
|
||||
|
||||
if (do_using_dynamic)
|
||||
{
|
||||
int is_rela;
|
||||
relocation_type rel_type;
|
||||
const char * name;
|
||||
bool has_dynamic_reloc;
|
||||
unsigned int i;
|
||||
@ -8052,7 +8146,7 @@ process_relocs (Filedata * filedata)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
|
||||
{
|
||||
is_rela = dynamic_relocations [i].rela;
|
||||
rel_type = dynamic_relocations [i].rel_type;
|
||||
name = dynamic_relocations [i].name;
|
||||
rel_size = filedata->dynamic_info[dynamic_relocations [i].size];
|
||||
rel_offset = filedata->dynamic_info[dynamic_relocations [i].reloc];
|
||||
@ -8060,16 +8154,16 @@ process_relocs (Filedata * filedata)
|
||||
if (rel_size)
|
||||
has_dynamic_reloc = true;
|
||||
|
||||
if (is_rela == UNKNOWN)
|
||||
if (rel_type == reltype_unknown)
|
||||
{
|
||||
if (dynamic_relocations [i].reloc == DT_JMPREL)
|
||||
switch (filedata->dynamic_info[DT_PLTREL])
|
||||
{
|
||||
case DT_REL:
|
||||
is_rela = false;
|
||||
rel_type = reltype_rel;
|
||||
break;
|
||||
case DT_RELA:
|
||||
is_rela = true;
|
||||
rel_type = reltype_rela;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -8092,7 +8186,7 @@ process_relocs (Filedata * filedata)
|
||||
filedata->num_dynamic_syms,
|
||||
filedata->dynamic_strings,
|
||||
filedata->dynamic_strings_length,
|
||||
is_rela, true /* is_dynamic */);
|
||||
rel_type, true /* is_dynamic */);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8120,7 +8214,8 @@ process_relocs (Filedata * filedata)
|
||||
i++, section++)
|
||||
{
|
||||
if ( section->sh_type != SHT_RELA
|
||||
&& section->sh_type != SHT_REL)
|
||||
&& section->sh_type != SHT_REL
|
||||
&& section->sh_type != SHT_RELR)
|
||||
continue;
|
||||
|
||||
rel_offset = section->sh_offset;
|
||||
@ -8128,7 +8223,7 @@ process_relocs (Filedata * filedata)
|
||||
|
||||
if (rel_size)
|
||||
{
|
||||
int is_rela;
|
||||
relocation_type rel_type;
|
||||
unsigned long num_rela;
|
||||
|
||||
if (filedata->is_separate)
|
||||
@ -8148,7 +8243,8 @@ process_relocs (Filedata * filedata)
|
||||
num_rela),
|
||||
rel_offset, num_rela);
|
||||
|
||||
is_rela = section->sh_type == SHT_RELA;
|
||||
rel_type = section->sh_type == SHT_RELA ? reltype_rela :
|
||||
section->sh_type == SHT_REL ? reltype_rel : reltype_relr;
|
||||
|
||||
if (section->sh_link != 0
|
||||
&& section->sh_link < filedata->file_header.e_shnum)
|
||||
@ -8170,15 +8266,14 @@ process_relocs (Filedata * filedata)
|
||||
|
||||
dump_relocations (filedata, rel_offset, rel_size,
|
||||
symtab, nsyms, strtab, strtablen,
|
||||
is_rela,
|
||||
rel_type,
|
||||
symsec->sh_type == SHT_DYNSYM);
|
||||
free (strtab);
|
||||
free (symtab);
|
||||
}
|
||||
else
|
||||
dump_relocations (filedata, rel_offset, rel_size,
|
||||
NULL, 0, NULL, 0, is_rela,
|
||||
false /* is_dynamic */);
|
||||
NULL, 0, NULL, 0, rel_type, false /* is_dynamic */);
|
||||
|
||||
found = true;
|
||||
}
|
||||
@ -11499,6 +11594,7 @@ the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n"));
|
||||
case DT_RPATH :
|
||||
case DT_SYMBOLIC:
|
||||
case DT_REL :
|
||||
case DT_RELR :
|
||||
case DT_DEBUG :
|
||||
case DT_TEXTREL :
|
||||
case DT_JMPREL :
|
||||
@ -11555,6 +11651,8 @@ the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n"));
|
||||
case DT_STRSZ :
|
||||
case DT_RELSZ :
|
||||
case DT_RELAENT :
|
||||
case DT_RELRENT :
|
||||
case DT_RELRSZ :
|
||||
case DT_SYMENT :
|
||||
case DT_RELENT :
|
||||
filedata->dynamic_info[entry->d_tag] = entry->d_un.d_val;
|
||||
@ -11562,8 +11660,6 @@ the .dynstr section doesn't match the DT_STRTAB and DT_STRSZ tags\n"));
|
||||
case DT_PLTPADSZ:
|
||||
case DT_MOVEENT :
|
||||
case DT_MOVESZ :
|
||||
case DT_RELRENT :
|
||||
case DT_RELRSZ :
|
||||
case DT_PREINIT_ARRAYSZ:
|
||||
case DT_INIT_ARRAYSZ:
|
||||
case DT_FINI_ARRAYSZ:
|
||||
|
@ -1,3 +1,9 @@
|
||||
2021-11-16 Fangrui Song <maskray@google.com>
|
||||
|
||||
* elf/common.h (DT_ENCODING): Bump to 38.
|
||||
* elf/external.h (Elf32_External_Relr): New.
|
||||
(Elf64_External_Relr): New.
|
||||
|
||||
2021-09-07 Luis Machado <luis.machado@linaro.org>
|
||||
|
||||
Revert: [AArch64] MTE corefile support
|
||||
|
@ -1102,13 +1102,13 @@
|
||||
#define DT_FINI_ARRAYSZ 28
|
||||
#define DT_RUNPATH 29
|
||||
#define DT_FLAGS 30
|
||||
#define DT_ENCODING 32
|
||||
#define DT_PREINIT_ARRAY 32
|
||||
#define DT_PREINIT_ARRAYSZ 33
|
||||
#define DT_SYMTAB_SHNDX 34
|
||||
#define DT_RELRSZ 35
|
||||
#define DT_RELR 36
|
||||
#define DT_RELRENT 37
|
||||
#define DT_ENCODING 38
|
||||
|
||||
/* Note, the Oct 4, 1999 draft of the ELF ABI changed the values
|
||||
for DT_LOOS and DT_HIOS. Some implementations however, use
|
||||
|
@ -211,6 +211,10 @@ typedef struct {
|
||||
unsigned char r_addend[4]; /* Constant addend used to compute value */
|
||||
} Elf32_External_Rela;
|
||||
|
||||
typedef struct {
|
||||
unsigned char r_data[4]; /* RELR entry */
|
||||
} Elf32_External_Relr;
|
||||
|
||||
typedef struct {
|
||||
unsigned char r_offset[8]; /* Location at which to apply the action */
|
||||
unsigned char r_info[8]; /* index and type of relocation */
|
||||
@ -222,6 +226,10 @@ typedef struct {
|
||||
unsigned char r_addend[8]; /* Constant addend used to compute value */
|
||||
} Elf64_External_Rela;
|
||||
|
||||
typedef struct {
|
||||
unsigned char r_data[8]; /* RELR entry */
|
||||
} Elf64_External_Relr;
|
||||
|
||||
/* dynamic section structure */
|
||||
|
||||
typedef struct {
|
||||
|
Loading…
Reference in New Issue
Block a user