[coreboot-gerrit] New patch to review for coreboot: b1f5446 cbfstool: add relocation parsing to ELF parser

Aaron Durbin (adurbin@google.com) gerrit at coreboot.org
Tue Mar 11 18:11:46 CET 2014


Aaron Durbin (adurbin at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5374

-gerrit

commit b1f544601bc6003a3f6c0691a81b650fa8317a4c
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Wed Mar 5 13:57:30 2014 -0600

    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 at chromium.org>
---
 util/cbfstool/elfheaders.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++
 util/cbfstool/elfparsing.h | 10 ++++++
 2 files changed, 97 insertions(+)

diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c
index 6c8f33d..d36dfbb 100644
--- a/util/cbfstool/elfheaders.c
+++ b/util/cbfstool/elfheaders.c
@@ -327,6 +327,79 @@ shdr_read(const struct buffer *in, struct parsed_elf *pelf,
 	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)
 {
 	struct xdr *xdr = &xdr_le;
@@ -356,12 +429,19 @@ int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
 
 	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))
 		goto fail;
 
 	if ((flags & ELF_PARSE_SHDR) && shdr_read(pinput, pelf, xdr, bit64))
 		goto fail;
 
+	if ((flags & ELF_PARSE_RELOC) && reloc_read(pinput, pelf, xdr, bit64))
+		goto fail;
+
 	return 0;
 
 fail:
@@ -373,6 +453,13 @@ void parsed_elf_destroy(struct parsed_elf *pelf)
 {
 	free(pelf->phdr);
 	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.
diff --git a/util/cbfstool/elfparsing.h b/util/cbfstool/elfparsing.h
index 4ad46b3..2827748 100644
--- a/util/cbfstool/elfparsing.h
+++ b/util/cbfstool/elfparsing.h
@@ -26,10 +26,20 @@ struct parsed_elf {
 	Elf64_Ehdr ehdr;
 	Elf64_Phdr *phdr;
 	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_SHDR		(1 << 1)
+#define ELF_PARSE_RELOC		(1 << 2)
 
 #define ELF_PARSE_ALL		(-1)
 



More information about the coreboot-gerrit mailing list