summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2015-10-28 10:09:07 -0500
committerAaron Durbin <adurbin@chromium.org>2015-10-29 17:00:38 +0100
commit8e982eabfacf9cce5bcc011ee2c23ca7ced4b05c (patch)
tree4b9f5275a8fd39e61f8a3ae5dbdd1aa17a5461ff
parent5a1e85c405782731d298225482927fedb733a329 (diff)
cbfstool: merge consecutive elf sections in program segments
Instead of creating a loadable segment for each section with SHF_ALLOC flag merge those sections into a single program segment. This makes more tidy readelf, but it also allows one to extract an rmodule into an ELF and turn it back into an rmodule. TEST=Extracted both regular stages and rmodule stages. Compared against original ELF files prior to cbfs insert. Change-Id: I0a600d2e9db5ee6c11278d8ad673caab1af6c759 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/12220 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
-rw-r--r--util/cbfstool/elfheaders.c95
1 files changed, 78 insertions, 17 deletions
diff --git a/util/cbfstool/elfheaders.c b/util/cbfstool/elfheaders.c
index da11bfcb62..262137d580 100644
--- a/util/cbfstool/elfheaders.c
+++ b/util/cbfstool/elfheaders.c
@@ -841,6 +841,78 @@ phdr_write(struct elf_writer *ew, struct buffer *m, Elf64_Phdr *phdr)
}
+static int section_consecutive(struct elf_writer *ew, Elf64_Half secidx)
+{
+ Elf64_Half i;
+ struct elf_writer_section *prev_alloc = NULL;
+
+ if (secidx == 0)
+ return 0;
+
+ for (i = 0; i < secidx; i++) {
+ if (ew->sections[i].shdr.sh_flags & SHF_ALLOC)
+ prev_alloc = &ew->sections[i];
+ }
+
+ if (prev_alloc == NULL)
+ return 0;
+
+ if (prev_alloc->shdr.sh_addr + prev_alloc->shdr.sh_size ==
+ ew->sections[secidx].shdr.sh_addr)
+ return 1;
+
+ return 0;
+}
+
+static void write_phdrs(struct elf_writer *ew, struct buffer *phdrs)
+{
+ Elf64_Half i;
+ Elf64_Phdr phdr;
+ size_t num_written = 0;
+
+ for (i = 0; i < ew->num_secs; i++) {
+ struct elf_writer_section *sec = &ew->sections[i];
+
+ if (!(sec->shdr.sh_flags & SHF_ALLOC))
+ continue;
+
+ if (!section_consecutive(ew, i)) {
+ /* Write out previously set phdr. */
+ if (num_written != 0) {
+ phdr_write(ew, phdrs, &phdr);
+ num_written++;
+ }
+ phdr.p_type = PT_LOAD;
+ phdr.p_offset = sec->shdr.sh_offset;
+ phdr.p_vaddr = sec->shdr.sh_addr;
+ phdr.p_paddr = sec->shdr.sh_addr;
+ phdr.p_filesz = buffer_size(&sec->content);
+ phdr.p_memsz = sec->shdr.sh_size;
+ phdr.p_flags = 0;
+ if (sec->shdr.sh_flags & SHF_EXECINSTR)
+ phdr.p_flags |= PF_X | PF_R;
+ if (sec->shdr.sh_flags & SHF_WRITE)
+ phdr.p_flags |= PF_W;
+ phdr.p_align = sec->shdr.sh_addralign;
+ } else {
+ /* Accumulate file size and memsize. The assumption
+ * is that each section is either NOBITS or full
+ * (sh_size == file size). This is standard in that
+ * an ELF section doesn't have a file size component. */
+ if (sec->shdr.sh_flags & SHF_EXECINSTR)
+ phdr.p_flags |= PF_X | PF_R;
+ if (sec->shdr.sh_flags & SHF_WRITE)
+ phdr.p_flags |= PF_W;
+ phdr.p_filesz += buffer_size(&sec->content);
+ phdr.p_memsz += sec->shdr.sh_size;
+ }
+ }
+
+ /* Write out the last phdr. */
+ if (num_written != ew->ehdr.e_phnum)
+ phdr_write(ew, phdrs, &phdr);
+}
+
/*
* Serialize the ELF file to the output buffer. Return < 0 on error,
* 0 on success.
@@ -866,8 +938,10 @@ int elf_writer_serialize(struct elf_writer *ew, struct buffer *out)
for (i = 0; i < ew->num_secs; i++) {
struct elf_writer_section *sec = &ew->sections[i];
- if (sec->shdr.sh_flags & SHF_ALLOC)
- ew->ehdr.e_phnum++;
+ if (sec->shdr.sh_flags & SHF_ALLOC) {
+ if (!section_consecutive(ew, i))
+ ew->ehdr.e_phnum++;
+ }
program_size += buffer_size(&sec->content);
@@ -924,7 +998,6 @@ int elf_writer_serialize(struct elf_writer *ew, struct buffer *out)
* program headers. */
ew->xdr->put8(strtab, 0);
for (i = 0; i < ew->num_secs; i++) {
- Elf64_Phdr phdr;
struct elf_writer_section *sec = &ew->sections[i];
/* Update section offsets. Be sure to not update SHT_NULL. */
@@ -944,21 +1017,9 @@ int elf_writer_serialize(struct elf_writer *ew, struct buffer *out)
bputs(&data, buffer_get(&sec->content),
buffer_size(&sec->content));
-
- phdr.p_type = PT_LOAD;
- phdr.p_offset = sec->shdr.sh_offset;
- phdr.p_vaddr = sec->shdr.sh_addr;
- phdr.p_paddr = sec->shdr.sh_addr;
- phdr.p_filesz = buffer_size(&sec->content);
- phdr.p_memsz = sec->shdr.sh_size;
- phdr.p_flags = 0;
- if (sec->shdr.sh_flags & SHF_EXECINSTR)
- phdr.p_flags |= PF_X | PF_R;
- if (sec->shdr.sh_flags & SHF_WRITE)
- phdr.p_flags |= PF_W;
- phdr.p_align = sec->shdr.sh_addralign;
- phdr_write(ew, &phdrs, &phdr);
}
+ write_phdrs(ew, &phdrs);
+
return 0;
}