From 37aaa28292baee3592492933beb49d5e8884aa14 Mon Sep 17 00:00:00 2001 From: Drasko DRASKOVIC Date: Wed, 22 Jun 2011 12:45:21 +0200 Subject: [PATCH] Fix load_image for ELF with all p_paddr set to zero So far image_load command tries to load ELF binaries to address discovered by reading p_paddr member of a Program header of an ELF segment. However, ELF specifications says for p_paddr : ...Because System V ignores physical addressing for application programs, this member has unspecified contents for executable files and shared objects. ARM ELF specifiaction goes even further, demanding that this member be set to zero, using the p_vaddr as a segment load address. To avoid the cases to wrong addr where p_paddr is zero, we are now using p_vaddr to as a load destination in case that *all* p_paddr == 0. Basically, this patch re-implements the approach present in BDF's elf.c, which is used by GDB also (so that we can be consistent). --- src/target/image.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/target/image.c b/src/target/image.c index 454fc6c183..21ce11f630 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -396,6 +396,7 @@ static int image_elf_read_headers(struct image *image) size_t read_bytes; uint32_t i,j; int retval; + uint32_t nload,load_to_vaddr=0; elf->header = malloc(sizeof(Elf32_Ehdr)); @@ -471,6 +472,26 @@ static int image_elf_read_headers(struct image *image) for (i = 0;i < elf->segment_count;i++) if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0)) image->num_sections++; + + /** + * some ELF linkers produce binaries with *all* the program header + * p_paddr fields zero (there can be however one loadable segment + * that has valid physical address 0x0). + * If we have such a binary with more than + * one PT_LOAD header, then use p_vaddr instead of p_paddr + * (ARM ELF standard demands p_paddr = 0 anyway, and BFD + * library uses this approach to workaround zero-initialized p_paddrs + * when obtaining lma - look at elf.c of BDF) + */ + for (nload = 0, i = 0; i < elf->segment_count; i++) + if (elf->segments[i].p_paddr != 0) + break; + else if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_memsz) != 0)) + ++nload; + + if (i >= elf->segment_count && nload > 1) + load_to_vaddr = 1; + /* alloc and fill sections array with loadable segments */ image->sections = malloc(image->num_sections * sizeof(struct imagesection)); for (i = 0,j = 0;i < elf->segment_count;i++) @@ -478,7 +499,10 @@ static int image_elf_read_headers(struct image *image) if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0)) { image->sections[j].size = field32(elf,elf->segments[i].p_filesz); - image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr); + if (load_to_vaddr) + image->sections[j].base_address = field32(elf,elf->segments[i].p_vaddr); + else + image->sections[j].base_address = field32(elf,elf->segments[i].p_paddr); image->sections[j].private = &elf->segments[i]; image->sections[j].flags = field32(elf,elf->segments[i].p_flags); j++; -- 2.30.2