1 static void glue(bswap_ehdr
, SZ
)(struct elfhdr
*ehdr
)
3 bswap16s(&ehdr
->e_type
); /* Object file type */
4 bswap16s(&ehdr
->e_machine
); /* Architecture */
5 bswap32s(&ehdr
->e_version
); /* Object file version */
6 bswapSZs(&ehdr
->e_entry
); /* Entry point virtual address */
7 bswapSZs(&ehdr
->e_phoff
); /* Program header table file offset */
8 bswapSZs(&ehdr
->e_shoff
); /* Section header table file offset */
9 bswap32s(&ehdr
->e_flags
); /* Processor-specific flags */
10 bswap16s(&ehdr
->e_ehsize
); /* ELF header size in bytes */
11 bswap16s(&ehdr
->e_phentsize
); /* Program header table entry size */
12 bswap16s(&ehdr
->e_phnum
); /* Program header table entry count */
13 bswap16s(&ehdr
->e_shentsize
); /* Section header table entry size */
14 bswap16s(&ehdr
->e_shnum
); /* Section header table entry count */
15 bswap16s(&ehdr
->e_shstrndx
); /* Section header string table index */
18 static void glue(bswap_phdr
, SZ
)(struct elf_phdr
*phdr
)
20 bswap32s(&phdr
->p_type
); /* Segment type */
21 bswapSZs(&phdr
->p_offset
); /* Segment file offset */
22 bswapSZs(&phdr
->p_vaddr
); /* Segment virtual address */
23 bswapSZs(&phdr
->p_paddr
); /* Segment physical address */
24 bswapSZs(&phdr
->p_filesz
); /* Segment size in file */
25 bswapSZs(&phdr
->p_memsz
); /* Segment size in memory */
26 bswap32s(&phdr
->p_flags
); /* Segment flags */
27 bswapSZs(&phdr
->p_align
); /* Segment alignment */
30 static void glue(bswap_shdr
, SZ
)(struct elf_shdr
*shdr
)
32 bswap32s(&shdr
->sh_name
);
33 bswap32s(&shdr
->sh_type
);
34 bswapSZs(&shdr
->sh_flags
);
35 bswapSZs(&shdr
->sh_addr
);
36 bswapSZs(&shdr
->sh_offset
);
37 bswapSZs(&shdr
->sh_size
);
38 bswap32s(&shdr
->sh_link
);
39 bswap32s(&shdr
->sh_info
);
40 bswapSZs(&shdr
->sh_addralign
);
41 bswapSZs(&shdr
->sh_entsize
);
44 static void glue(bswap_sym
, SZ
)(struct elf_sym
*sym
)
46 bswap32s(&sym
->st_name
);
47 bswapSZs(&sym
->st_value
);
48 bswapSZs(&sym
->st_size
);
49 bswap16s(&sym
->st_shndx
);
52 static struct elf_shdr
*glue(find_section
, SZ
)(struct elf_shdr
*shdr_table
,
57 if (shdr_table
[i
].sh_type
== type
)
58 return shdr_table
+ i
;
63 static int glue(symfind
, SZ
)(const void *s0
, const void *s1
)
65 struct elf_sym
*key
= (struct elf_sym
*)s0
;
66 struct elf_sym
*sym
= (struct elf_sym
*)s1
;
68 if (key
->st_value
< sym
->st_value
) {
70 } else if (key
->st_value
> sym
->st_value
+ sym
->st_size
) {
76 static const char *glue(lookup_symbol
, SZ
)(struct syminfo
*s
, target_ulong orig_addr
)
78 struct elf_sym
*syms
= glue(s
->disas_symtab
.elf
, SZ
);
82 key
.st_value
= orig_addr
;
84 sym
= bsearch(&key
, syms
, s
->disas_num_syms
, sizeof(*syms
), glue(symfind
, SZ
));
86 return s
->disas_strtab
+ sym
->st_name
;
92 static int glue(symcmp
, SZ
)(const void *s0
, const void *s1
)
94 struct elf_sym
*sym0
= (struct elf_sym
*)s0
;
95 struct elf_sym
*sym1
= (struct elf_sym
*)s1
;
96 return (sym0
->st_value
< sym1
->st_value
)
98 : ((sym0
->st_value
> sym1
->st_value
) ? 1 : 0);
101 static int glue(load_symbols
, SZ
)(struct elfhdr
*ehdr
, int fd
, int must_swab
)
103 struct elf_shdr
*symtab
, *strtab
, *shdr_table
= NULL
;
104 struct elf_sym
*syms
= NULL
;
109 shdr_table
= load_at(fd
, ehdr
->e_shoff
,
110 sizeof(struct elf_shdr
) * ehdr
->e_shnum
);
115 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
116 glue(bswap_shdr
, SZ
)(shdr_table
+ i
);
120 symtab
= glue(find_section
, SZ
)(shdr_table
, ehdr
->e_shnum
, SHT_SYMTAB
);
123 syms
= load_at(fd
, symtab
->sh_offset
, symtab
->sh_size
);
127 nsyms
= symtab
->sh_size
/ sizeof(struct elf_sym
);
132 glue(bswap_sym
, SZ
)(&syms
[i
]);
133 /* We are only interested in function symbols.
134 Throw everything else away. */
135 if (syms
[i
].st_shndx
== SHN_UNDEF
||
136 syms
[i
].st_shndx
>= SHN_LORESERVE
||
137 ELF_ST_TYPE(syms
[i
].st_info
) != STT_FUNC
) {
140 syms
[i
] = syms
[nsyms
];
144 #if defined(TARGET_ARM) || defined (TARGET_MIPS)
145 /* The bottom address bit marks a Thumb or MIPS16 symbol. */
146 syms
[i
].st_value
&= ~(target_ulong
)1;
150 syms
= qemu_realloc(syms
, nsyms
* sizeof(*syms
));
152 qsort(syms
, nsyms
, sizeof(*syms
), glue(symcmp
, SZ
));
155 if (symtab
->sh_link
>= ehdr
->e_shnum
)
157 strtab
= &shdr_table
[symtab
->sh_link
];
159 str
= load_at(fd
, strtab
->sh_offset
, strtab
->sh_size
);
164 s
= qemu_mallocz(sizeof(*s
));
165 s
->lookup_symbol
= glue(lookup_symbol
, SZ
);
166 glue(s
->disas_symtab
.elf
, SZ
) = syms
;
167 s
->disas_num_syms
= nsyms
;
168 s
->disas_strtab
= str
;
171 qemu_free(shdr_table
);
176 qemu_free(shdr_table
);
180 static int glue(load_elf
, SZ
)(int fd
, int64_t address_offset
,
181 int must_swab
, uint64_t *pentry
,
182 uint64_t *lowaddr
, uint64_t *highaddr
)
185 struct elf_phdr
*phdr
= NULL
, *ph
;
186 int size
, i
, total_size
;
188 uint64_t addr
, low
= 0, high
= 0;
189 uint8_t *data
= NULL
;
191 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
194 glue(bswap_ehdr
, SZ
)(&ehdr
);
197 if (ELF_MACHINE
!= ehdr
.e_machine
)
201 *pentry
= (uint64_t)(elf_sword
)ehdr
.e_entry
;
203 glue(load_symbols
, SZ
)(&ehdr
, fd
, must_swab
);
205 size
= ehdr
.e_phnum
* sizeof(phdr
[0]);
206 lseek(fd
, ehdr
.e_phoff
, SEEK_SET
);
207 phdr
= qemu_mallocz(size
);
210 if (read(fd
, phdr
, size
) != size
)
213 for(i
= 0; i
< ehdr
.e_phnum
; i
++) {
215 glue(bswap_phdr
, SZ
)(ph
);
220 for(i
= 0; i
< ehdr
.e_phnum
; i
++) {
222 if (ph
->p_type
== PT_LOAD
) {
223 mem_size
= ph
->p_memsz
;
224 /* XXX: avoid allocating */
225 data
= qemu_mallocz(mem_size
);
226 if (ph
->p_filesz
> 0) {
227 if (lseek(fd
, ph
->p_offset
, SEEK_SET
) < 0)
229 if (read(fd
, data
, ph
->p_filesz
) != ph
->p_filesz
)
232 /* address_offset is hack for kernel images that are
233 linked at the wrong physical address. */
234 addr
= ph
->p_paddr
+ address_offset
;
236 cpu_physical_memory_write_rom(addr
, data
, mem_size
);
238 total_size
+= mem_size
;
239 if (!low
|| addr
< low
)
241 if (!high
|| (addr
+ mem_size
) > high
)
242 high
= addr
+ mem_size
;
250 *lowaddr
= (uint64_t)(elf_sword
)low
;
252 *highaddr
= (uint64_t)(elf_sword
)high
;