summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2014-03-05 16:41:27 -0600
committerAaron Durbin <adurbin@google.com>2014-03-14 21:51:38 +0100
commitc078094f39d8683b9a1087dc7f60e8605733ed99 (patch)
tree78b79dee26d91d16e514c45b789fb1fa296e76fe /util
parentc3e6e14a1227421c3e520a2a62f279bc4408ee3a (diff)
downloadcoreboot-c078094f39d8683b9a1087dc7f60e8605733ed99.tar.xz
cbfstool: add symbol table parsing to the ELF parser
Optionally parse the symbol table contained within an ELF file. It currently assumes there is only one symbol table present, and it errors out if more than one is found. Change-Id: I4ac4ad03184a319562576d8ab24fa620e701672a Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/5376 Tested-by: build bot (Jenkins) Reviewed-by: Marc Jones <marc.jones@se-eng.com>
Diffstat (limited to 'util')
-rw-r--r--util/cbfstool/elfheaders.c71
-rw-r--r--util/cbfstool/elfparsing.h3
2 files changed, 74 insertions, 0 deletions
diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c
index 37371e2bf8..f3ed05c105 100644
--- a/util/cbfstool/elfheaders.c
+++ b/util/cbfstool/elfheaders.c
@@ -430,6 +430,69 @@ static int strtab_read(const struct buffer *in, struct parsed_elf *pelf)
return 0;
}
+static int
+symtab_read(const struct buffer *in, struct parsed_elf *pelf,
+ struct xdr *xdr, int bit64)
+{
+ Elf64_Ehdr *ehdr;
+ Elf64_Shdr *shdr;
+ Elf64_Half i;
+ Elf64_Xword nsyms;
+ Elf64_Sym *sym;
+ struct buffer b;
+
+ ehdr = &pelf->ehdr;
+
+ shdr = NULL;
+ for (i = 0; i < ehdr->e_shnum; i++) {
+ if (pelf->shdr[i].sh_type != SHT_SYMTAB)
+ continue;
+
+ if (shdr != NULL) {
+ ERROR("Multiple symbol sections found. %u and %u\n",
+ (unsigned int)(shdr - pelf->shdr), i);
+ return -1;
+ }
+
+ shdr = &pelf->shdr[i];
+ }
+
+ if (shdr == NULL) {
+ ERROR("No symbol table found.\n");
+ return -1;
+ }
+
+ buffer_splice(&b, in, shdr->sh_offset, shdr->sh_size);
+ if (check_size(in, shdr->sh_offset, buffer_size(&b), "symtab"))
+ return -1;
+
+ nsyms = shdr->sh_size / shdr->sh_entsize;
+
+ pelf->syms = calloc(nsyms, sizeof(Elf64_Sym));
+
+ for (i = 0; i < nsyms; i++) {
+ sym = &pelf->syms[i];
+
+ if (bit64) {
+ sym->st_name = xdr->get32(&b);
+ sym->st_info = xdr->get8(&b);
+ sym->st_other = xdr->get8(&b);
+ sym->st_shndx = xdr->get16(&b);
+ sym->st_value = xdr->get64(&b);
+ sym->st_size = xdr->get64(&b);
+ } else {
+ sym->st_name = xdr->get32(&b);
+ sym->st_value = xdr->get32(&b);
+ sym->st_size = xdr->get32(&b);
+ sym->st_info = xdr->get8(&b);
+ sym->st_other = xdr->get8(&b);
+ sym->st_shndx = xdr->get16(&b);
+ }
+ }
+
+ return 0;
+}
+
int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
{
struct xdr *xdr = &xdr_le;
@@ -467,6 +530,10 @@ int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
if (flags & ELF_PARSE_STRTAB)
flags |= ELF_PARSE_SHDR;
+ /* Symbole table processing requires section header parsing. */
+ if (flags & ELF_PARSE_SYMTAB)
+ flags |= ELF_PARSE_SHDR;
+
if ((flags & ELF_PARSE_PHDR) && phdr_read(pinput, pelf, xdr, bit64))
goto fail;
@@ -479,6 +546,9 @@ int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags)
if ((flags & ELF_PARSE_STRTAB) && strtab_read(pinput, pelf))
goto fail;
+ if ((flags & ELF_PARSE_SYMTAB) && symtab_read(pinput, pelf, xdr, bit64))
+ goto fail;
+
return 0;
fail:
@@ -503,6 +573,7 @@ void parsed_elf_destroy(struct parsed_elf *pelf)
free(pelf->strtabs[i]);
}
free(pelf->strtabs);
+ free(pelf->syms);
}
/* Get the headers from the buffer.
diff --git a/util/cbfstool/elfparsing.h b/util/cbfstool/elfparsing.h
index 9107c21007..113301aae2 100644
--- a/util/cbfstool/elfparsing.h
+++ b/util/cbfstool/elfparsing.h
@@ -41,12 +41,15 @@ struct parsed_elf {
* entry.
*/
struct buffer **strtabs;
+ /* Parsed symbols. */
+ Elf64_Sym *syms;
};
#define ELF_PARSE_PHDR (1 << 0)
#define ELF_PARSE_SHDR (1 << 1)
#define ELF_PARSE_RELOC (1 << 2)
#define ELF_PARSE_STRTAB (1 << 3)
+#define ELF_PARSE_SYMTAB (1 << 4)
#define ELF_PARSE_ALL (-1)