[coreboot-gerrit] New patch to review for coreboot: ddb4cce cbfstool: introduce struct parsed_elf and parse_elf()

Aaron Durbin (adurbin@google.com) gerrit at coreboot.org
Tue Mar 11 18:11:44 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/5373

-gerrit

commit ddb4cce283daf19c0b43f73e3bc00f476e39bd9d
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Wed Mar 5 13:09:55 2014 -0600

    cbfstool: introduce struct parsed_elf and parse_elf()
    
    In order to make the ELF parsing more flexible introduce
    a parse_elf() function which takes a struct parsed_elf
    parameter. In addition take a flags parameter which instructs
    the ELF parser as to what data within the ELF file should be
    parsed.
    
    Change-Id: I3e30e84bf8043c3df96a6ab56cd077eef2632173
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 util/cbfstool/elfheaders.c | 114 ++++++++++++++++++++++++++++++++-------------
 util/cbfstool/elfparsing.h |  25 ++++++++++
 2 files changed, 107 insertions(+), 32 deletions(-)

diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c
index 505af78..6c8f33d 100644
--- a/util/cbfstool/elfheaders.c
+++ b/util/cbfstool/elfheaders.c
@@ -251,13 +251,16 @@ elf_shdr(struct buffer *pinput, Elf64_Shdr *shdr,
 	buffer_seek(pinput, entsize);
 }
 
-static Elf64_Phdr *
-phdr_read(const struct buffer *in, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
+static int
+phdr_read(const struct buffer *in, struct parsed_elf *pelf,
+          struct xdr *xdr, int bit64)
 {
 	struct buffer b;
 	Elf64_Phdr *phdr;
+	Elf64_Ehdr *ehdr;
 	int i;
 
+	ehdr = &pelf->ehdr;
 	/* cons up an input buffer for the headers.
 	 * Note that the program headers can be anywhere,
 	 * per the ELF spec, You'd be surprised how many ELF
@@ -265,7 +268,7 @@ phdr_read(const struct buffer *in, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
 	 */
 	buffer_splice(&b, in, ehdr->e_phoff, ehdr->e_phentsize * ehdr->e_phnum);
 	if (check_size(in, ehdr->e_phoff, buffer_size(&b), "program headers"))
-		return NULL;
+		return -1;
 
 	/* gather up all the phdrs.
 	 * We do them all at once because there is more
@@ -279,19 +282,25 @@ phdr_read(const struct buffer *in, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
 		/* Ensure the contents are valid within the elf file. */
 		if (check_size(in, phdr[i].p_offset, phdr[i].p_filesz,
 	                  "segment contents"))
-			return NULL;
+			return -1;
 	}
 
-	return phdr;
+	pelf->phdr = phdr;
+
+	return 0;
 }
 
-static Elf64_Shdr *
-shdr_read(const struct buffer *in, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
+static int
+shdr_read(const struct buffer *in, struct parsed_elf *pelf,
+          struct xdr *xdr, int bit64)
 {
 	struct buffer b;
 	Elf64_Shdr *shdr;
+	Elf64_Ehdr *ehdr;
 	int i;
 
+	ehdr = &pelf->ehdr;
+
 	/* cons up an input buffer for the section headers.
 	 * Note that the section headers can be anywhere,
 	 * per the ELF spec, You'd be surprised how many ELF
@@ -299,7 +308,7 @@ shdr_read(const struct buffer *in, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
 	 */
 	buffer_splice(&b, in, ehdr->e_shoff, ehdr->e_shentsize * ehdr->e_shnum);
 	if (check_size(in, ehdr->e_shoff, buffer_size(&b), "section headers"))
-		return NULL;
+		return -1;
 
 	/* gather up all the shdrs. */
 	shdr = calloc(ehdr->e_shnum, sizeof(*shdr));
@@ -310,37 +319,31 @@ shdr_read(const struct buffer *in, Elf64_Ehdr *ehdr, struct xdr *xdr, int bit64)
 		/* Ensure the contents are valid within the elf file. */
 		if (check_size(in, shdr[i].sh_offset, shdr[i].sh_size,
 		               "section contents"))
-			return NULL;
+			return -1;
 	}
 
-	return shdr;
+	pelf->shdr = shdr;
+
+	return 0;
 }
 
-/* Get the headers from the buffer.
- * Return -1 in the event of an error.
- * The section headers are optional; if NULL
- * is passed in for pshdr they won't be parsed.
- * We don't (yet) make payload parsing optional
- * because we've never seen a use case.
- */
-int
-elf_headers(const struct buffer *pinput,
-	    uint32_t arch,
-	    Elf64_Ehdr *ehdr,
-	    Elf64_Phdr **pphdr,
-	    Elf64_Shdr **pshdr)
+int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
 {
 	struct xdr *xdr = &xdr_le;
 	int bit64 = 0;
 	struct buffer input;
+	Elf64_Ehdr *ehdr;
 
-	buffer_clone(&input, pinput);
+	/* Zero out the parsed elf structure. */
+	memset(pelf, 0, sizeof(*pelf));
 
 	if (!iself(buffer_get(pinput))) {
 		ERROR("The stage file is not in ELF format!\n");
 		return -1;
 	}
 
+	buffer_clone(&input, pinput);
+	ehdr = &pelf->ehdr;
 	elf_eident(&input, ehdr);
 	bit64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
 	/* Assume LE unless we are sure otherwise.
@@ -353,6 +356,54 @@ elf_headers(const struct buffer *pinput,
 
 	elf_ehdr(&input, ehdr, xdr, bit64);
 
+	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;
+
+	return 0;
+
+fail:
+	parsed_elf_destroy(pelf);
+	return -1;
+}
+
+void parsed_elf_destroy(struct parsed_elf *pelf)
+{
+	free(pelf->phdr);
+	free(pelf->shdr);
+}
+
+/* Get the headers from the buffer.
+ * Return -1 in the event of an error.
+ * The section headers are optional; if NULL
+ * is passed in for pshdr they won't be parsed.
+ * We don't (yet) make payload parsing optional
+ * because we've never seen a use case.
+ */
+int
+elf_headers(const struct buffer *pinput,
+	    uint32_t arch,
+	    Elf64_Ehdr *ehdr,
+	    Elf64_Phdr **pphdr,
+	    Elf64_Shdr **pshdr)
+{
+
+	struct parsed_elf pelf;
+	int flags;
+
+	flags = ELF_PARSE_PHDR;
+
+	if (pshdr != NULL)
+		flags |= ELF_PARSE_SHDR;
+
+	if (parse_elf(pinput, &pelf, flags))
+		return -1;
+
+	/* Copy out the parsed elf header. */
+	memcpy(ehdr, &pelf.ehdr, sizeof(*ehdr));
+
 	// The tool may work in architecture-independent way.
 	if (arch != CBFS_ARCHITECTURE_UNKNOWN &&
 	    !((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) &&
@@ -361,16 +412,15 @@ elf_headers(const struct buffer *pinput,
 		return -1;
 	}
 
-	*pphdr = phdr_read(pinput, ehdr, xdr, bit64);
-	if (*pphdr == NULL)
-		return -1;
+	*pphdr = calloc(ehdr->e_phnum, sizeof(Elf64_Phdr));
+	memcpy(*pphdr, pelf.phdr, ehdr->e_phnum * sizeof(Elf64_Phdr));
 
-	if (!pshdr)
-		return 0;
+	if (pshdr != NULL) {
+		*pshdr = calloc(ehdr->e_shnum, sizeof(Elf64_Shdr));
+		memcpy(*pshdr, pelf.shdr, ehdr->e_shnum * sizeof(Elf64_Shdr));
+	}
 
-	*pshdr = shdr_read(pinput, ehdr, xdr, bit64);
-	if (*pshdr == NULL)
-		return -1;
+	parsed_elf_destroy(&pelf);
 
 	return 0;
 }
diff --git a/util/cbfstool/elfparsing.h b/util/cbfstool/elfparsing.h
index 3cfa1cd..4ad46b3 100644
--- a/util/cbfstool/elfparsing.h
+++ b/util/cbfstool/elfparsing.h
@@ -22,6 +22,31 @@
 
 struct buffer;
 
+struct parsed_elf {
+	Elf64_Ehdr ehdr;
+	Elf64_Phdr *phdr;
+	Elf64_Shdr *shdr;
+};
+
+#define ELF_PARSE_PHDR		(1 << 0)
+#define ELF_PARSE_SHDR		(1 << 1)
+
+#define ELF_PARSE_ALL		(-1)
+
+/*
+ * Parse an ELF file contained within provide struct buffer. The ELF header
+ * is always parsed while the flags value containing the ELF_PARSE_* values
+ * determine if other parts of the ELF file will be parsed as well.
+ * Returns 0 on success, < 0 error.
+ */
+int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags);
+
+/*
+ * Clean up memory associated with parsed_elf.
+ */
+void parsed_elf_destroy(struct parsed_elf *pelf);
+
+
 int
 elf_headers(const struct buffer *pinput,
 	    uint32_t arch,



More information about the coreboot-gerrit mailing list