diff options
-rw-r--r-- | util/cbfstool/elfheaders.c | 52 | ||||
-rw-r--r-- | util/cbfstool/elfparsing.h | 11 |
2 files changed, 59 insertions, 4 deletions
diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c index 8e06f5e9d5..37371e2bf8 100644 --- a/util/cbfstool/elfheaders.c +++ b/util/cbfstool/elfheaders.c @@ -395,6 +395,41 @@ reloc_read(const struct buffer *in, struct parsed_elf *pelf, return 0; } +static int strtab_read(const struct buffer *in, struct parsed_elf *pelf) +{ + Elf64_Ehdr *ehdr; + Elf64_Word i; + + ehdr = &pelf->ehdr; + + if (ehdr->e_shstrndx >= ehdr->e_shnum) { + ERROR("Section header string table index out of range: %d\n", + ehdr->e_shstrndx); + return -1; + } + + /* For each section of type SHT_STRTAB create a symtab buffer. */ + pelf->strtabs = calloc(ehdr->e_shnum, sizeof(struct buffer *)); + + for (i = 0; i < ehdr->e_shnum; i++) { + struct buffer *b; + Elf64_Shdr *shdr = &pelf->shdr[i]; + + if (shdr->sh_type != SHT_STRTAB) + continue; + + b = calloc(1, sizeof(*b)); + buffer_splice(b, in, shdr->sh_offset, shdr->sh_size); + if (check_size(in, shdr->sh_offset, buffer_size(b), "strtab")) { + ERROR("STRTAB section not within bounds: %d\n", i); + return -1; + } + pelf->strtabs[i] = b; + } + + return 0; +} + int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags) { struct xdr *xdr = &xdr_le; @@ -428,6 +463,10 @@ int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags) if (flags & ELF_PARSE_RELOC) flags |= ELF_PARSE_SHDR; + /* String table processing requires section header parsing. */ + if (flags & ELF_PARSE_STRTAB) + flags |= ELF_PARSE_SHDR; + if ((flags & ELF_PARSE_PHDR) && phdr_read(pinput, pelf, xdr, bit64)) goto fail; @@ -437,6 +476,9 @@ int parse_elf(const struct buffer *pinput, struct parsed_elf *pelf, int flags) if ((flags & ELF_PARSE_RELOC) && reloc_read(pinput, pelf, xdr, bit64)) goto fail; + if ((flags & ELF_PARSE_STRTAB) && strtab_read(pinput, pelf)) + goto fail; + return 0; fail: @@ -446,15 +488,21 @@ fail: void parsed_elf_destroy(struct parsed_elf *pelf) { + Elf64_Half i; + 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); + + if (pelf->strtabs != NULL) { + for (i = 0; i < pelf->ehdr.e_shnum; i++) + free(pelf->strtabs[i]); + } + free(pelf->strtabs); } /* Get the headers from the buffer. diff --git a/util/cbfstool/elfparsing.h b/util/cbfstool/elfparsing.h index 2827748c06..9107c21007 100644 --- a/util/cbfstool/elfparsing.h +++ b/util/cbfstool/elfparsing.h @@ -19,8 +19,7 @@ #define ELFPARSING_H #include "elf.h" - -struct buffer; +#include "common.h" struct parsed_elf { Elf64_Ehdr ehdr; @@ -35,11 +34,19 @@ struct parsed_elf { * NULL. */ Elf64_Rela **relocs; + /* + * Similarly to the relocs array the strtabs array consists of an + * array of pointers where each entry represents a potential struct + * buffer pointer. Only setions of type SHT_STRTAB will have a non-NULL + * entry. + */ + struct buffer **strtabs; }; #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_ALL (-1) |