cbfstool: add relocation parsing to ELF parser
Optionally parse the relocation entries found within an ELF file. Change-Id: I343647f104901eb8a6a997ddf44aa5d36c31b44b Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/5374 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones <marc.jones@se-eng.com>
This commit is contained in:
parent
d0f6165923
commit
ccb5ad8d3c
|
@ -322,6 +322,79 @@ shdr_read(const struct buffer *in, struct parsed_elf *pelf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
reloc_read(const struct buffer *in, struct parsed_elf *pelf,
|
||||||
|
struct xdr *xdr, int bit64)
|
||||||
|
{
|
||||||
|
struct buffer b;
|
||||||
|
Elf64_Word i;
|
||||||
|
Elf64_Ehdr *ehdr;
|
||||||
|
|
||||||
|
ehdr = &pelf->ehdr;
|
||||||
|
pelf->relocs = calloc(ehdr->e_shnum, sizeof(Elf64_Rela *));
|
||||||
|
|
||||||
|
/* Allocate array for each section that contains relocation entries. */
|
||||||
|
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||||
|
Elf64_Shdr *shdr;
|
||||||
|
Elf64_Rela *rela;
|
||||||
|
Elf64_Xword j;
|
||||||
|
Elf64_Xword nrelocs;
|
||||||
|
int is_rela;
|
||||||
|
|
||||||
|
shdr = &pelf->shdr[i];
|
||||||
|
|
||||||
|
/* Only process REL and RELA sections. */
|
||||||
|
if (shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DEBUG("Checking relocation section %u\n", i);
|
||||||
|
|
||||||
|
/* Ensure the section that relocations apply is a valid. */
|
||||||
|
if (shdr->sh_info >= ehdr->e_shnum ||
|
||||||
|
shdr->sh_info == SHN_UNDEF) {
|
||||||
|
ERROR("Relocations apply to an invalid section: %u\n",
|
||||||
|
shdr[i].sh_info);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_rela = shdr->sh_type == SHT_RELA;
|
||||||
|
|
||||||
|
/* Determine the number relocations in this section. */
|
||||||
|
nrelocs = shdr->sh_size / shdr->sh_entsize;
|
||||||
|
|
||||||
|
pelf->relocs[i] = calloc(nrelocs, sizeof(Elf64_Rela));
|
||||||
|
|
||||||
|
buffer_splice(&b, in, shdr->sh_offset, shdr->sh_size);
|
||||||
|
if (check_size(in, shdr->sh_offset, buffer_size(&b),
|
||||||
|
"relocation section")) {
|
||||||
|
ERROR("Relocation section %u failed.\n", i);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rela = pelf->relocs[i];
|
||||||
|
for (j = 0; j < nrelocs; j++) {
|
||||||
|
if (bit64) {
|
||||||
|
rela->r_offset = xdr->get64(&b);
|
||||||
|
rela->r_info = xdr->get64(&b);
|
||||||
|
if (is_rela)
|
||||||
|
rela->r_addend = xdr->get64(&b);
|
||||||
|
} else {
|
||||||
|
uint32_t r_info;
|
||||||
|
|
||||||
|
rela->r_offset = xdr->get32(&b);
|
||||||
|
r_info = xdr->get32(&b);
|
||||||
|
rela->r_info = ELF64_R_INFO(ELF32_R_SYM(r_info),
|
||||||
|
ELF32_R_TYPE(r_info));
|
||||||
|
if (is_rela)
|
||||||
|
rela->r_addend = xdr->get32(&b);
|
||||||
|
}
|
||||||
|
rela++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
|
int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
|
||||||
{
|
{
|
||||||
struct xdr *xdr = &xdr_le;
|
struct xdr *xdr = &xdr_le;
|
||||||
|
@ -351,12 +424,19 @@ int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
|
||||||
|
|
||||||
elf_ehdr(&input, ehdr, xdr, bit64);
|
elf_ehdr(&input, ehdr, xdr, bit64);
|
||||||
|
|
||||||
|
/* Relocation processing requires section header parsing. */
|
||||||
|
if (flags & ELF_PARSE_RELOC)
|
||||||
|
flags |= ELF_PARSE_SHDR;
|
||||||
|
|
||||||
if ((flags & ELF_PARSE_PHDR) && phdr_read(pinput, pelf, xdr, bit64))
|
if ((flags & ELF_PARSE_PHDR) && phdr_read(pinput, pelf, xdr, bit64))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if ((flags & ELF_PARSE_SHDR) && shdr_read(pinput, pelf, xdr, bit64))
|
if ((flags & ELF_PARSE_SHDR) && shdr_read(pinput, pelf, xdr, bit64))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if ((flags & ELF_PARSE_RELOC) && reloc_read(pinput, pelf, xdr, bit64))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -368,6 +448,13 @@ void parsed_elf_destroy(struct parsed_elf *pelf)
|
||||||
{
|
{
|
||||||
free(pelf->phdr);
|
free(pelf->phdr);
|
||||||
free(pelf->shdr);
|
free(pelf->shdr);
|
||||||
|
if (pelf->relocs != NULL) {
|
||||||
|
Elf64_Half i;
|
||||||
|
|
||||||
|
for (i = 0; i < pelf->ehdr.e_shnum; i++)
|
||||||
|
free(pelf->relocs[i]);
|
||||||
|
}
|
||||||
|
free(pelf->relocs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the headers from the buffer.
|
/* Get the headers from the buffer.
|
||||||
|
|
|
@ -26,10 +26,20 @@ struct parsed_elf {
|
||||||
Elf64_Ehdr ehdr;
|
Elf64_Ehdr ehdr;
|
||||||
Elf64_Phdr *phdr;
|
Elf64_Phdr *phdr;
|
||||||
Elf64_Shdr *shdr;
|
Elf64_Shdr *shdr;
|
||||||
|
/*
|
||||||
|
* The relocs array contains pointers to arrays of relocation
|
||||||
|
* structures. Each index into the relocs array corresponds to its
|
||||||
|
* corresponding section index. i.e. if a section i is of type SHT_REL
|
||||||
|
* or SHT_RELA then the corresponding index into the relocs array will
|
||||||
|
* contain the associated relocations. Otherwise thee entry will be
|
||||||
|
* NULL.
|
||||||
|
*/
|
||||||
|
Elf64_Rela **relocs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ELF_PARSE_PHDR (1 << 0)
|
#define ELF_PARSE_PHDR (1 << 0)
|
||||||
#define ELF_PARSE_SHDR (1 << 1)
|
#define ELF_PARSE_SHDR (1 << 1)
|
||||||
|
#define ELF_PARSE_RELOC (1 << 2)
|
||||||
|
|
||||||
#define ELF_PARSE_ALL (-1)
|
#define ELF_PARSE_ALL (-1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue