]>
Commit | Line | Data |
---|---|---|
3475187d FB |
1 | #ifdef BSWAP_NEEDED |
2 | static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr) | |
3 | { | |
4 | bswap16s(&ehdr->e_type); /* Object file type */ | |
5 | bswap16s(&ehdr->e_machine); /* Architecture */ | |
6 | bswap32s(&ehdr->e_version); /* Object file version */ | |
7 | bswapSZs(&ehdr->e_entry); /* Entry point virtual address */ | |
8 | bswapSZs(&ehdr->e_phoff); /* Program header table file offset */ | |
9 | bswapSZs(&ehdr->e_shoff); /* Section header table file offset */ | |
10 | bswap32s(&ehdr->e_flags); /* Processor-specific flags */ | |
11 | bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ | |
12 | bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ | |
13 | bswap16s(&ehdr->e_phnum); /* Program header table entry count */ | |
14 | bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ | |
15 | bswap16s(&ehdr->e_shnum); /* Section header table entry count */ | |
16 | bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ | |
17 | } | |
18 | ||
19 | static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr) | |
20 | { | |
21 | bswap32s(&phdr->p_type); /* Segment type */ | |
22 | bswapSZs(&phdr->p_offset); /* Segment file offset */ | |
23 | bswapSZs(&phdr->p_vaddr); /* Segment virtual address */ | |
24 | bswapSZs(&phdr->p_paddr); /* Segment physical address */ | |
25 | bswapSZs(&phdr->p_filesz); /* Segment size in file */ | |
26 | bswapSZs(&phdr->p_memsz); /* Segment size in memory */ | |
27 | bswap32s(&phdr->p_flags); /* Segment flags */ | |
28 | bswapSZs(&phdr->p_align); /* Segment alignment */ | |
29 | } | |
30 | ||
31 | static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr) | |
32 | { | |
33 | bswap32s(&shdr->sh_name); | |
34 | bswap32s(&shdr->sh_type); | |
35 | bswapSZs(&shdr->sh_flags); | |
36 | bswapSZs(&shdr->sh_addr); | |
37 | bswapSZs(&shdr->sh_offset); | |
38 | bswapSZs(&shdr->sh_size); | |
39 | bswap32s(&shdr->sh_link); | |
40 | bswap32s(&shdr->sh_info); | |
41 | bswapSZs(&shdr->sh_addralign); | |
42 | bswapSZs(&shdr->sh_entsize); | |
43 | } | |
44 | ||
45 | static void glue(bswap_sym, SZ)(struct elf_sym *sym) | |
46 | { | |
47 | bswap32s(&sym->st_name); | |
48 | bswapSZs(&sym->st_value); | |
49 | bswapSZs(&sym->st_size); | |
50 | bswap16s(&sym->st_shndx); | |
51 | } | |
52 | #endif | |
53 | ||
54 | static int glue(find_phdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, elf_word type) | |
55 | { | |
56 | int i, retval; | |
57 | ||
58 | retval = lseek(fd, ehdr->e_phoff, SEEK_SET); | |
59 | if (retval < 0) | |
60 | return -1; | |
61 | ||
62 | for (i = 0; i < ehdr->e_phnum; i++) { | |
63 | retval = read(fd, phdr, sizeof(*phdr)); | |
64 | if (retval < 0) | |
65 | return -1; | |
66 | glue(bswap_phdr, SZ)(phdr); | |
67 | if (phdr->p_type == type) | |
68 | return 0; | |
69 | } | |
70 | return -1; | |
71 | } | |
72 | ||
73 | static void * glue(find_shdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type) | |
74 | { | |
75 | int i, retval; | |
76 | ||
77 | retval = lseek(fd, ehdr->e_shoff, SEEK_SET); | |
78 | if (retval < 0) | |
79 | return NULL; | |
80 | ||
81 | for (i = 0; i < ehdr->e_shnum; i++) { | |
82 | retval = read(fd, shdr, sizeof(*shdr)); | |
83 | if (retval < 0) | |
84 | return NULL; | |
85 | glue(bswap_shdr, SZ)(shdr); | |
86 | if (shdr->sh_type == type) | |
87 | return qemu_malloc(shdr->sh_size); | |
88 | } | |
89 | return NULL; | |
90 | } | |
91 | ||
92 | static void * glue(find_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab) | |
93 | { | |
94 | int retval; | |
95 | ||
96 | retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET); | |
97 | if (retval < 0) | |
98 | return NULL; | |
99 | ||
100 | retval = read(fd, shdr, sizeof(*shdr)); | |
101 | if (retval < 0) | |
102 | return NULL; | |
103 | glue(bswap_shdr, SZ)(shdr); | |
104 | if (shdr->sh_type == SHT_STRTAB) | |
105 | return qemu_malloc(shdr->sh_size);; | |
106 | return NULL; | |
107 | } | |
108 | ||
109 | static int glue(read_program, SZ)(int fd, struct elf_phdr *phdr, void *dst, elf_word entry) | |
110 | { | |
111 | int retval; | |
112 | retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET); | |
113 | if (retval < 0) | |
114 | return -1; | |
115 | return read(fd, dst, phdr->p_filesz); | |
116 | } | |
117 | ||
118 | static int glue(read_section, SZ)(int fd, struct elf_shdr *s, void *dst) | |
119 | { | |
120 | int retval; | |
121 | ||
122 | retval = lseek(fd, s->sh_offset, SEEK_SET); | |
123 | if (retval < 0) | |
124 | return -1; | |
125 | retval = read(fd, dst, s->sh_size); | |
126 | if (retval < 0) | |
127 | return -1; | |
128 | return 0; | |
129 | } | |
130 | ||
131 | static void * glue(process_section, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type) | |
132 | { | |
133 | void *dst; | |
134 | ||
135 | dst = glue(find_shdr, SZ)(ehdr, fd, shdr, type); | |
136 | if (!dst) | |
137 | goto error; | |
138 | ||
139 | if (glue(read_section, SZ)(fd, shdr, dst)) | |
140 | goto error; | |
141 | return dst; | |
142 | error: | |
143 | qemu_free(dst); | |
144 | return NULL; | |
145 | } | |
146 | ||
147 | static void * glue(process_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab) | |
148 | { | |
149 | void *dst; | |
150 | ||
151 | dst = glue(find_strtab, SZ)(ehdr, fd, shdr, symtab); | |
152 | if (!dst) | |
153 | goto error; | |
154 | ||
155 | if (glue(read_section, SZ)(fd, shdr, dst)) | |
156 | goto error; | |
157 | return dst; | |
158 | error: | |
159 | qemu_free(dst); | |
160 | return NULL; | |
161 | } | |
162 | ||
163 | static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd) | |
164 | { | |
165 | struct elf_shdr symtab, strtab; | |
166 | struct elf_sym *syms; | |
167 | #if (SZ == 64) | |
168 | struct elf32_sym *syms32; | |
169 | #endif | |
170 | struct syminfo *s; | |
171 | int nsyms, i; | |
172 | char *str; | |
173 | ||
174 | /* Symbol table */ | |
175 | syms = glue(process_section, SZ)(ehdr, fd, &symtab, SHT_SYMTAB); | |
176 | if (!syms) | |
177 | return; | |
178 | ||
179 | nsyms = symtab.sh_size / sizeof(struct elf_sym); | |
180 | #if (SZ == 64) | |
181 | syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym)); | |
182 | #endif | |
183 | for (i = 0; i < nsyms; i++) { | |
184 | glue(bswap_sym, SZ)(&syms[i]); | |
185 | #if (SZ == 64) | |
186 | syms32[i].st_name = syms[i].st_name; | |
187 | syms32[i].st_info = syms[i].st_info; | |
188 | syms32[i].st_other = syms[i].st_other; | |
189 | syms32[i].st_shndx = syms[i].st_shndx; | |
190 | syms32[i].st_value = syms[i].st_value & 0xffffffff; | |
191 | syms32[i].st_size = syms[i].st_size & 0xffffffff; | |
192 | #endif | |
193 | } | |
194 | /* String table */ | |
195 | str = glue(process_strtab, SZ)(ehdr, fd, &strtab, &symtab); | |
196 | if (!str) | |
197 | goto error_freesyms; | |
198 | ||
199 | /* Commit */ | |
200 | s = qemu_mallocz(sizeof(*s)); | |
201 | #if (SZ == 64) | |
202 | s->disas_symtab = syms32; | |
203 | qemu_free(syms); | |
204 | #else | |
205 | s->disas_symtab = syms; | |
206 | #endif | |
207 | s->disas_num_syms = nsyms; | |
208 | s->disas_strtab = str; | |
209 | s->next = syminfos; | |
210 | syminfos = s; | |
211 | return; | |
212 | error_freesyms: | |
213 | #if (SZ == 64) | |
214 | qemu_free(syms32); | |
215 | #endif | |
216 | qemu_free(syms); | |
217 | return; | |
218 | } |