sbtools: implement virtual to physical address translation for elf files

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30556 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Amaury Pouly 2011-09-15 14:36:58 +00:00
parent 782708e494
commit 64b4672359
3 changed files with 76 additions and 5 deletions

View file

@ -155,6 +155,21 @@ static struct elf_section_t *elf_add_section(struct elf_params_t *params)
return sec;
}
static struct elf_segment_t *elf_add_segment(struct elf_params_t *params)
{
struct elf_segment_t *seg = xmalloc(sizeof(struct elf_section_t));
if(params->first_segment == NULL)
params->first_segment = params->last_segment = seg;
else
{
params->last_segment->next = seg;
params->last_segment = seg;
}
seg->next = NULL;
return seg;
}
void elf_add_load_section(struct elf_params_t *params,
uint32_t load_addr, uint32_t size, const void *section)
{
@ -406,7 +421,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
}
/* run through sections */
printf(user, false, "ELF file:\n");
for(int i = 1; i< ehdr.e_shnum; i++)
for(int i = 1; i < ehdr.e_shnum; i++)
{
uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize;
Elf32_Shdr shdr;
@ -437,9 +452,51 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
}
}
/* run through segments */
for(int i = 1; i < ehdr.e_phnum; i++)
{
uint32_t off = ehdr.e_phoff + i * ehdr.e_phentsize;
Elf32_Phdr phdr;
memset(&phdr, 0, sizeof(phdr));
if(!read(user, off, &phdr, sizeof(phdr)))
error_printf("error reading elf segment header");
if(phdr.p_type != PT_LOAD)
continue;
struct elf_segment_t *seg = elf_add_segment(params);
seg->vaddr = phdr.p_vaddr;
seg->paddr = phdr.p_paddr;
seg->vsize = phdr.p_memsz;
seg->psize = phdr.p_filesz;
printf(user, false, "create segment [%#x,+%#x[ -> [%#x,+%#x[\n",
seg->vaddr, seg->vsize, seg->paddr, seg->psize);
}
return true;
}
uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr)
{
struct elf_segment_t *seg = params->first_segment;
while(seg)
{
if(seg->vaddr <= addr && addr < seg->vaddr + seg->vsize)
return addr - seg->vaddr + seg->paddr;
seg = seg->next;
}
return addr;
}
void elf_translate_addresses(struct elf_params_t *params)
{
struct elf_section_t *sec = params->first_section;
while(sec)
{
sec->addr = elf_translate_virtual_address(params, sec->addr);
sec = sec->next;
}
params->start_addr = elf_translate_virtual_address(params, params->start_addr);
}
bool elf_is_empty(struct elf_params_t *params)
{
return params->first_section == NULL;

View file

@ -16,24 +16,35 @@ enum elf_section_type_t
struct elf_section_t
{
uint32_t addr;
uint32_t size;
uint32_t addr; /* virtual address */
uint32_t size; /* virtual size */
enum elf_section_type_t type;
/* <union> */
void *section;
uint32_t pattern;
void *section; /* data */
uint32_t pattern; /* fill pattern */
/* </union> */
struct elf_section_t *next;
/* Internal to elf_write_file */
uint32_t offset;
};
struct elf_segment_t
{
uint32_t vaddr; /* virtual address */
uint32_t paddr; /* physical address */
uint32_t vsize; /* virtual size */
uint32_t psize; /* physical size */
struct elf_segment_t *next;
};
struct elf_params_t
{
bool has_start_addr;
uint32_t start_addr;
struct elf_section_t *first_section;
struct elf_section_t *last_section;
struct elf_segment_t *first_segment;
struct elf_segment_t *last_segment;
};
typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count);
@ -46,6 +57,8 @@ void elf_add_load_section(struct elf_params_t *params,
uint32_t load_addr, uint32_t size, const void *section);
void elf_add_fill_section(struct elf_params_t *params,
uint32_t fill_addr, uint32_t size, uint32_t pattern);
uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr);
void elf_translate_addresses(struct elf_params_t *params);
void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, void *user);
bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, elf_printf_fn_t printf,
void *user);

View file

@ -817,6 +817,7 @@ static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id)
close(fd);
if(!src->loaded)
bug("error loading elf file '%s' (id '%s')\n", src->filename, id);
elf_translate_addresses(&src->elf);
}
static void load_bin_by_id(struct cmd_file_t *cmd_file, const char *id)