diff options
Diffstat (limited to 'utils/sbtools/elf.c')
-rw-r--r-- | utils/sbtools/elf.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/utils/sbtools/elf.c b/utils/sbtools/elf.c index fed09cd6ff..57f38b8016 100644 --- a/utils/sbtools/elf.c +++ b/utils/sbtools/elf.c | |||
@@ -155,6 +155,21 @@ static struct elf_section_t *elf_add_section(struct elf_params_t *params) | |||
155 | return sec; | 155 | return sec; |
156 | } | 156 | } |
157 | 157 | ||
158 | static struct elf_segment_t *elf_add_segment(struct elf_params_t *params) | ||
159 | { | ||
160 | struct elf_segment_t *seg = xmalloc(sizeof(struct elf_section_t)); | ||
161 | if(params->first_segment == NULL) | ||
162 | params->first_segment = params->last_segment = seg; | ||
163 | else | ||
164 | { | ||
165 | params->last_segment->next = seg; | ||
166 | params->last_segment = seg; | ||
167 | } | ||
168 | seg->next = NULL; | ||
169 | |||
170 | return seg; | ||
171 | } | ||
172 | |||
158 | void elf_add_load_section(struct elf_params_t *params, | 173 | void elf_add_load_section(struct elf_params_t *params, |
159 | uint32_t load_addr, uint32_t size, const void *section) | 174 | uint32_t load_addr, uint32_t size, const void *section) |
160 | { | 175 | { |
@@ -406,7 +421,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, | |||
406 | } | 421 | } |
407 | /* run through sections */ | 422 | /* run through sections */ |
408 | printf(user, false, "ELF file:\n"); | 423 | printf(user, false, "ELF file:\n"); |
409 | for(int i = 1; i< ehdr.e_shnum; i++) | 424 | for(int i = 1; i < ehdr.e_shnum; i++) |
410 | { | 425 | { |
411 | uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize; | 426 | uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize; |
412 | Elf32_Shdr shdr; | 427 | Elf32_Shdr shdr; |
@@ -437,9 +452,51 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, | |||
437 | } | 452 | } |
438 | 453 | ||
439 | } | 454 | } |
455 | /* run through segments */ | ||
456 | for(int i = 1; i < ehdr.e_phnum; i++) | ||
457 | { | ||
458 | uint32_t off = ehdr.e_phoff + i * ehdr.e_phentsize; | ||
459 | Elf32_Phdr phdr; | ||
460 | memset(&phdr, 0, sizeof(phdr)); | ||
461 | if(!read(user, off, &phdr, sizeof(phdr))) | ||
462 | error_printf("error reading elf segment header"); | ||
463 | if(phdr.p_type != PT_LOAD) | ||
464 | continue; | ||
465 | struct elf_segment_t *seg = elf_add_segment(params); | ||
466 | seg->vaddr = phdr.p_vaddr; | ||
467 | seg->paddr = phdr.p_paddr; | ||
468 | seg->vsize = phdr.p_memsz; | ||
469 | seg->psize = phdr.p_filesz; | ||
470 | printf(user, false, "create segment [%#x,+%#x[ -> [%#x,+%#x[\n", | ||
471 | seg->vaddr, seg->vsize, seg->paddr, seg->psize); | ||
472 | } | ||
473 | |||
440 | return true; | 474 | return true; |
441 | } | 475 | } |
442 | 476 | ||
477 | uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr) | ||
478 | { | ||
479 | struct elf_segment_t *seg = params->first_segment; | ||
480 | while(seg) | ||
481 | { | ||
482 | if(seg->vaddr <= addr && addr < seg->vaddr + seg->vsize) | ||
483 | return addr - seg->vaddr + seg->paddr; | ||
484 | seg = seg->next; | ||
485 | } | ||
486 | return addr; | ||
487 | } | ||
488 | |||
489 | void elf_translate_addresses(struct elf_params_t *params) | ||
490 | { | ||
491 | struct elf_section_t *sec = params->first_section; | ||
492 | while(sec) | ||
493 | { | ||
494 | sec->addr = elf_translate_virtual_address(params, sec->addr); | ||
495 | sec = sec->next; | ||
496 | } | ||
497 | params->start_addr = elf_translate_virtual_address(params, params->start_addr); | ||
498 | } | ||
499 | |||
443 | bool elf_is_empty(struct elf_params_t *params) | 500 | bool elf_is_empty(struct elf_params_t *params) |
444 | { | 501 | { |
445 | return params->first_section == NULL; | 502 | return params->first_section == NULL; |