Browse Source

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).
tags/v0.5.0-rc1
Drasko DRASKOVIC 13 years ago
committed by Øyvind Harboe
parent
commit
37aaa28292
1 changed files with 25 additions and 1 deletions
  1. +25
    -1
      src/target/image.c

+ 25
- 1
src/target/image.c View File

@@ -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++;


Loading…
Cancel
Save