1 |
dpavlin |
38 |
/* |
2 |
|
|
* Copyright (C) 2003-2007 Anders Gavare. All rights reserved. |
3 |
|
|
* |
4 |
|
|
* Redistribution and use in source and binary forms, with or without |
5 |
|
|
* modification, are permitted provided that the following conditions are met: |
6 |
|
|
* |
7 |
|
|
* 1. Redistributions of source code must retain the above copyright |
8 |
|
|
* notice, this list of conditions and the following disclaimer. |
9 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
10 |
|
|
* notice, this list of conditions and the following disclaimer in the |
11 |
|
|
* documentation and/or other materials provided with the distribution. |
12 |
|
|
* 3. The name of the author may not be used to endorse or promote products |
13 |
|
|
* derived from this software without specific prior written permission. |
14 |
|
|
* |
15 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 |
|
|
* SUCH DAMAGE. |
26 |
|
|
* |
27 |
|
|
* |
28 |
|
|
* $Id: file_ecoff.c,v 1.1 2007/04/10 16:33:44 debug Exp $ |
29 |
|
|
* |
30 |
|
|
* ECOFF file support. |
31 |
|
|
*/ |
32 |
|
|
|
33 |
|
|
/* Note: Included from file.c. */ |
34 |
|
|
|
35 |
|
|
|
36 |
|
|
#include "exec_ecoff.h" |
37 |
|
|
|
38 |
|
|
|
39 |
|
|
/* Special symbol format used by Microsoft-ish COFF files: */ |
40 |
|
|
struct ms_sym { |
41 |
|
|
unsigned char name[8]; |
42 |
|
|
unsigned char value[4]; |
43 |
|
|
unsigned char section[2]; |
44 |
|
|
unsigned char type[2]; |
45 |
|
|
unsigned char storage_class; |
46 |
|
|
unsigned char n_aux_syms; |
47 |
|
|
}; |
48 |
|
|
|
49 |
|
|
|
50 |
|
|
/* |
51 |
|
|
* file_load_ecoff(): |
52 |
|
|
* |
53 |
|
|
* Loads an ecoff binary image into the emulated memory. The entry point |
54 |
|
|
* (read from the ecoff header) is stored in the specified CPU's registers. |
55 |
|
|
*/ |
56 |
|
|
static void file_load_ecoff(struct machine *m, struct memory *mem, |
57 |
|
|
char *filename, uint64_t *entrypointp, |
58 |
|
|
int arch, uint64_t *gpp, int *byte_orderp) |
59 |
|
|
{ |
60 |
|
|
struct ecoff_exechdr exechdr; |
61 |
|
|
int f_magic, f_nscns, f_nsyms; |
62 |
|
|
int a_magic; |
63 |
|
|
off_t f_symptr, a_tsize, a_dsize, a_bsize; |
64 |
|
|
uint64_t a_entry, a_tstart, a_dstart, a_bstart, a_gp, end_addr=0; |
65 |
|
|
char *format_name; |
66 |
|
|
struct ecoff_scnhdr scnhdr; |
67 |
|
|
FILE *f; |
68 |
|
|
int len, secn, total_len, chunk_size; |
69 |
|
|
int encoding = ELFDATA2LSB; /* Assume little-endian. See below */ |
70 |
|
|
int program_byte_order = -1; |
71 |
|
|
unsigned char buf[8192]; |
72 |
|
|
|
73 |
|
|
f = fopen(filename, "r"); |
74 |
|
|
if (f == NULL) { |
75 |
|
|
perror(filename); |
76 |
|
|
exit(1); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
len = fread(&exechdr, 1, sizeof(exechdr), f); |
80 |
|
|
if (len != sizeof(exechdr)) { |
81 |
|
|
fprintf(stderr, " not a complete ecoff image\n"); |
82 |
|
|
exit(1); |
83 |
|
|
} |
84 |
|
|
|
85 |
|
|
/* |
86 |
|
|
* The following code looks a bit ugly, but it should work. The ECOFF |
87 |
|
|
* 16-bit magic value seems to be stored in MSB byte order for |
88 |
|
|
* big-endian binaries, and LSB byte order for little-endian binaries. |
89 |
|
|
* |
90 |
|
|
* The unencode() assumes little-endianness by default. |
91 |
|
|
*/ |
92 |
|
|
unencode(f_magic, &exechdr.f.f_magic, uint16_t); |
93 |
|
|
switch (f_magic) { |
94 |
|
|
case ((ECOFF_MAGIC_MIPSEB & 0xff) << 8) + |
95 |
|
|
((ECOFF_MAGIC_MIPSEB >> 8) & 0xff): |
96 |
|
|
format_name = "MIPS1 BE"; |
97 |
|
|
encoding = ELFDATA2MSB; |
98 |
|
|
break; |
99 |
|
|
case ECOFF_MAGIC_MIPSEB: |
100 |
|
|
/* NOTE: Big-endian header, little-endian code! */ |
101 |
|
|
format_name = "MIPS1 BE-LE"; |
102 |
|
|
encoding = ELFDATA2MSB; |
103 |
|
|
program_byte_order = ELFDATA2LSB; |
104 |
|
|
break; |
105 |
|
|
case ECOFF_MAGIC_MIPSEL: |
106 |
|
|
format_name = "MIPS1 LE"; |
107 |
|
|
encoding = ELFDATA2LSB; |
108 |
|
|
break; |
109 |
|
|
case ((ECOFF_MAGIC_MIPSEB2 & 0xff) << 8) + |
110 |
|
|
((ECOFF_MAGIC_MIPSEB2 >> 8) & 0xff): |
111 |
|
|
format_name = "MIPS2 BE"; |
112 |
|
|
encoding = ELFDATA2MSB; |
113 |
|
|
break; |
114 |
|
|
case ECOFF_MAGIC_MIPSEL2: |
115 |
|
|
format_name = "MIPS2 LE"; |
116 |
|
|
encoding = ELFDATA2LSB; |
117 |
|
|
break; |
118 |
|
|
case ((ECOFF_MAGIC_MIPSEB3 & 0xff) << 8) + |
119 |
|
|
((ECOFF_MAGIC_MIPSEB3 >> 8) & 0xff): |
120 |
|
|
format_name = "MIPS3 BE"; |
121 |
|
|
encoding = ELFDATA2MSB; |
122 |
|
|
break; |
123 |
|
|
case ECOFF_MAGIC_MIPSEL3: |
124 |
|
|
format_name = "MIPS3 LE"; |
125 |
|
|
encoding = ELFDATA2LSB; |
126 |
|
|
break; |
127 |
|
|
default: |
128 |
|
|
fprintf(stderr, "%s: unimplemented ECOFF format, magic = " |
129 |
|
|
"0x%04x\n", filename, (int)f_magic); |
130 |
|
|
exit(1); |
131 |
|
|
} |
132 |
|
|
|
133 |
|
|
/* Read various header information: */ |
134 |
|
|
unencode(f_nscns, &exechdr.f.f_nscns, uint16_t); |
135 |
|
|
unencode(f_symptr, &exechdr.f.f_symptr, uint32_t); |
136 |
|
|
unencode(f_nsyms, &exechdr.f.f_nsyms, uint32_t); |
137 |
|
|
debug("ECOFF, %s, %i sections, %i symbols @ 0x%lx\n", |
138 |
|
|
format_name, f_nscns, f_nsyms, (long)f_symptr); |
139 |
|
|
|
140 |
|
|
unencode(a_magic, &exechdr.a.magic, uint16_t); |
141 |
|
|
unencode(a_tsize, &exechdr.a.tsize, uint32_t); |
142 |
|
|
unencode(a_dsize, &exechdr.a.dsize, uint32_t); |
143 |
|
|
unencode(a_bsize, &exechdr.a.bsize, uint32_t); |
144 |
|
|
debug("magic 0x%04x, tsize 0x%x, dsize 0x%x, bsize 0x%x\n", |
145 |
|
|
a_magic, (int)a_tsize, (int)a_dsize, (int)a_bsize); |
146 |
|
|
|
147 |
|
|
unencode(a_tstart, &exechdr.a.text_start, uint32_t); |
148 |
|
|
unencode(a_dstart, &exechdr.a.data_start, uint32_t); |
149 |
|
|
unencode(a_bstart, &exechdr.a.bss_start, uint32_t); |
150 |
|
|
debug("text @ 0x%08x, data @ 0x%08x, bss @ 0x%08x\n", |
151 |
|
|
(int)a_tstart, (int)a_dstart, (int)a_bstart); |
152 |
|
|
|
153 |
|
|
unencode(a_entry, &exechdr.a.entry, uint32_t); |
154 |
|
|
unencode(a_gp, &exechdr.a.gp_value, uint32_t); |
155 |
|
|
debug("entrypoint 0x%08x, gp = 0x%08x\n", |
156 |
|
|
(int)a_entry, (int)a_gp); |
157 |
|
|
|
158 |
|
|
/* |
159 |
|
|
* Special hack for a MACH/pmax kernel, I don't know how applicable |
160 |
|
|
* this is for other files: |
161 |
|
|
* there are no sections (!), and a_magic = 0x0108 instead of |
162 |
|
|
* 0x0107 as it is on most other (E)COFF files I've seen. |
163 |
|
|
* |
164 |
|
|
* Then load everything after the header to the text start address. |
165 |
|
|
*/ |
166 |
|
|
if (f_nscns == 0 && a_magic == 0x108) { |
167 |
|
|
uint64_t where = a_tstart; |
168 |
|
|
total_len = 0; |
169 |
|
|
fseek(f, 0x50, SEEK_SET); |
170 |
|
|
while (!feof(f)) { |
171 |
|
|
chunk_size = 256; |
172 |
|
|
len = fread(buf, 1, chunk_size, f); |
173 |
|
|
|
174 |
|
|
if (len > 0) |
175 |
|
|
m->cpus[0]->memory_rw(m->cpus[0], mem, where, |
176 |
|
|
&buf[0], len, MEM_WRITE, NO_EXCEPTIONS); |
177 |
|
|
where += len; |
178 |
|
|
total_len += len; |
179 |
|
|
} |
180 |
|
|
debug("MACH/pmax hack (!), read 0x%x bytes\n", total_len); |
181 |
|
|
} |
182 |
|
|
|
183 |
|
|
/* Go through all the section headers: */ |
184 |
|
|
for (secn=0; secn<f_nscns; secn++) { |
185 |
|
|
off_t s_scnptr, s_relptr, s_lnnoptr, oldpos; |
186 |
|
|
int s_nreloc, s_nlnno, s_flags; |
187 |
|
|
int s_size; |
188 |
|
|
unsigned int i; |
189 |
|
|
uint64_t s_paddr, s_vaddr; |
190 |
|
|
|
191 |
|
|
/* Read a section header: */ |
192 |
|
|
len = fread(&scnhdr, 1, sizeof(scnhdr), f); |
193 |
|
|
if (len != sizeof(scnhdr)) { |
194 |
|
|
fprintf(stderr, "%s: incomplete section " |
195 |
|
|
"header %i\n", filename, secn); |
196 |
|
|
exit(1); |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
/* Show the section name: */ |
200 |
|
|
debug("section "); |
201 |
|
|
for (i=0; i<sizeof(scnhdr.s_name); i++) |
202 |
|
|
if (scnhdr.s_name[i] >= 32 && scnhdr.s_name[i] < 127) |
203 |
|
|
debug("%c", scnhdr.s_name[i]); |
204 |
|
|
else |
205 |
|
|
break; |
206 |
|
|
debug(" ("); |
207 |
|
|
|
208 |
|
|
unencode(s_paddr, &scnhdr.s_paddr, uint32_t); |
209 |
|
|
unencode(s_vaddr, &scnhdr.s_vaddr, uint32_t); |
210 |
|
|
unencode(s_size, &scnhdr.s_size, uint32_t); |
211 |
|
|
unencode(s_scnptr, &scnhdr.s_scnptr, uint32_t); |
212 |
|
|
unencode(s_relptr, &scnhdr.s_relptr, uint32_t); |
213 |
|
|
unencode(s_lnnoptr, &scnhdr.s_lnnoptr, uint32_t); |
214 |
|
|
unencode(s_nreloc, &scnhdr.s_nreloc, uint16_t); |
215 |
|
|
unencode(s_nlnno, &scnhdr.s_nlnno, uint16_t); |
216 |
|
|
unencode(s_flags, &scnhdr.s_flags, uint32_t); |
217 |
|
|
|
218 |
|
|
debug("0x%x @ 0x%08x, offset 0x%lx, flags 0x%x)\n", |
219 |
|
|
(int)s_size, (int)s_vaddr, (long)s_scnptr, (int)s_flags); |
220 |
|
|
|
221 |
|
|
end_addr = s_vaddr + s_size; |
222 |
|
|
|
223 |
|
|
if (s_relptr != 0) { |
224 |
|
|
/* |
225 |
|
|
* TODO: Read this url, or similar: |
226 |
|
|
* http://www.iecc.com/linker/linker07.html |
227 |
|
|
*/ |
228 |
|
|
fprintf(stderr, "%s: relocatable code/data in " |
229 |
|
|
"section nr %i: not yet implemented\n", |
230 |
|
|
filename, secn); |
231 |
|
|
exit(1); |
232 |
|
|
} |
233 |
|
|
|
234 |
|
|
/* Loadable? Then load the section: */ |
235 |
|
|
if (s_scnptr != 0 && s_size != 0 && |
236 |
|
|
s_vaddr != 0 && !(s_flags & 0x02)) { |
237 |
|
|
/* Remember the current file offset: */ |
238 |
|
|
oldpos = ftello(f); |
239 |
|
|
|
240 |
|
|
/* Load the section into emulated memory: */ |
241 |
|
|
fseek(f, s_scnptr, SEEK_SET); |
242 |
|
|
total_len = 0; |
243 |
|
|
chunk_size = 1; |
244 |
|
|
if ((s_vaddr & 0xf) == 0) chunk_size = 0x10; |
245 |
|
|
if ((s_vaddr & 0xff) == 0) chunk_size = 0x100; |
246 |
|
|
if ((s_vaddr & 0xfff) == 0) chunk_size = 0x1000; |
247 |
|
|
while (total_len < s_size) { |
248 |
|
|
len = chunk_size; |
249 |
|
|
if (total_len + len > s_size) |
250 |
|
|
len = s_size - total_len; |
251 |
|
|
len = fread(buf, 1, chunk_size, f); |
252 |
|
|
if (len == 0) { |
253 |
|
|
debug("!!! total_len = %i, " |
254 |
|
|
"chunk_size = %i, len = %i\n", |
255 |
|
|
total_len, chunk_size, len); |
256 |
|
|
break; |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
m->cpus[0]->memory_rw(m->cpus[0], mem, s_vaddr, |
260 |
|
|
&buf[0], len, MEM_WRITE, NO_EXCEPTIONS); |
261 |
|
|
s_vaddr += len; |
262 |
|
|
total_len += len; |
263 |
|
|
} |
264 |
|
|
|
265 |
|
|
/* Return to position inside the section headers: */ |
266 |
|
|
fseek(f, oldpos, SEEK_SET); |
267 |
|
|
} |
268 |
|
|
} |
269 |
|
|
|
270 |
|
|
if (f_symptr != 0 && f_nsyms != 0) { |
271 |
|
|
struct ecoff_symhdr symhdr; |
272 |
|
|
int sym_magic, iextMax, issExtMax, issMax, crfd; |
273 |
|
|
off_t cbRfdOffset, cbExtOffset, cbSsExtOffset, cbSsOffset; |
274 |
|
|
char *symbol_data; |
275 |
|
|
struct ecoff_extsym *extsyms; |
276 |
|
|
int nsymbols, sym_nr; |
277 |
|
|
|
278 |
|
|
fseek(f, f_symptr, SEEK_SET); |
279 |
|
|
|
280 |
|
|
len = fread(&symhdr, 1, sizeof(symhdr), f); |
281 |
|
|
if (len != sizeof(symhdr)) { |
282 |
|
|
fprintf(stderr, "%s: not a complete " |
283 |
|
|
"ecoff image: symhdr broken\n", filename); |
284 |
|
|
exit(1); |
285 |
|
|
} |
286 |
|
|
|
287 |
|
|
unencode(sym_magic, &symhdr.magic, uint16_t); |
288 |
|
|
unencode(crfd, &symhdr.crfd, uint32_t); |
289 |
|
|
unencode(cbRfdOffset, &symhdr.cbRfdOffset, uint32_t); |
290 |
|
|
unencode(issMax, &symhdr.issMax, uint32_t); |
291 |
|
|
unencode(cbSsOffset, &symhdr.cbSsOffset, uint32_t); |
292 |
|
|
unencode(issExtMax, &symhdr.issExtMax, uint32_t); |
293 |
|
|
unencode(cbSsExtOffset, &symhdr.cbSsExtOffset, uint32_t); |
294 |
|
|
unencode(iextMax, &symhdr.iextMax, uint32_t); |
295 |
|
|
unencode(cbExtOffset, &symhdr.cbExtOffset, uint32_t); |
296 |
|
|
|
297 |
|
|
if (sym_magic != MIPS_MAGIC_SYM) { |
298 |
|
|
unsigned char *ms_sym_buf; |
299 |
|
|
struct ms_sym *sym; |
300 |
|
|
int n_real_symbols = 0; |
301 |
|
|
|
302 |
|
|
debug("bad symbol magic, assuming Microsoft format: "); |
303 |
|
|
|
304 |
|
|
/* |
305 |
|
|
* See http://www.lisoleg.net/lisoleg/elfandlib/ |
306 |
|
|
* Microsoft%20Portable%20Executable%20COFF%20For |
307 |
|
|
* mat%20Specification.txt |
308 |
|
|
* for more details. |
309 |
|
|
*/ |
310 |
|
|
ms_sym_buf = malloc(sizeof(struct ms_sym) * f_nsyms); |
311 |
|
|
if (ms_sym_buf == NULL) { |
312 |
|
|
fprintf(stderr, "out of memory\n"); |
313 |
|
|
exit(1); |
314 |
|
|
} |
315 |
|
|
fseek(f, f_symptr, SEEK_SET); |
316 |
|
|
len = fread(ms_sym_buf, 1, |
317 |
|
|
sizeof(struct ms_sym) * f_nsyms, f); |
318 |
|
|
sym = (struct ms_sym *) ms_sym_buf; |
319 |
|
|
for (sym_nr=0; sym_nr<f_nsyms; sym_nr++) { |
320 |
|
|
char name[300]; |
321 |
|
|
uint32_t v, t, altname; |
322 |
|
|
/* debug("sym %5i: '", sym_nr); |
323 |
|
|
for (i=0; i<8 && sym->name[i]; i++) |
324 |
|
|
debug("%c", sym->name[i]); */ |
325 |
|
|
v = sym->value[0] + (sym->value[1] << 8) |
326 |
|
|
+ (sym->value[2] << 16) |
327 |
|
|
+ ((uint64_t)sym->value[3] << 24); |
328 |
|
|
altname = sym->name[4] + (sym->name[5] << 8) |
329 |
|
|
+ (sym->name[6] << 16) |
330 |
|
|
+ ((uint64_t)sym->name[3] << 24); |
331 |
|
|
t = (sym->type[1] << 8) + sym->type[0]; |
332 |
|
|
/* TODO: big endian COFF? */ |
333 |
|
|
/* debug("' value=0x%x type=0x%04x", v, t); */ |
334 |
|
|
|
335 |
|
|
if (t == 0x20 && sym->name[0]) { |
336 |
|
|
memcpy(name, sym->name, 8); |
337 |
|
|
name[8] = '\0'; |
338 |
|
|
add_symbol_name(&m->symbol_context, |
339 |
|
|
v, 0, name, 0, -1); |
340 |
|
|
n_real_symbols ++; |
341 |
|
|
} else if (t == 0x20 && !sym->name[0]) { |
342 |
|
|
off_t ofs; |
343 |
|
|
ofs = f_symptr + altname + |
344 |
|
|
sizeof(struct ms_sym) * f_nsyms; |
345 |
|
|
fseek(f, ofs, SEEK_SET); |
346 |
|
|
fread(name, 1, sizeof(name), f); |
347 |
|
|
name[sizeof(name)-1] = '\0'; |
348 |
|
|
/* debug(" [altname=0x%x '%s']", |
349 |
|
|
altname, name); */ |
350 |
|
|
add_symbol_name(&m->symbol_context, |
351 |
|
|
v, 0, name, 0, -1); |
352 |
|
|
n_real_symbols ++; |
353 |
|
|
} |
354 |
|
|
|
355 |
|
|
|
356 |
|
|
if (sym->n_aux_syms) { |
357 |
|
|
int n = sym->n_aux_syms; |
358 |
|
|
/* debug(" aux='"); */ |
359 |
|
|
while (n-- > 0) { |
360 |
|
|
sym ++; sym_nr ++; |
361 |
|
|
/* for (i=0; i<8 && |
362 |
|
|
sym->name[i]; i++) |
363 |
|
|
debug("%c", |
364 |
|
|
sym->name[i]); */ |
365 |
|
|
} |
366 |
|
|
/* debug("'"); */ |
367 |
|
|
} |
368 |
|
|
/* debug("\n"); */ |
369 |
|
|
sym ++; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
debug("%i symbols\n", n_real_symbols); |
373 |
|
|
free(ms_sym_buf); |
374 |
|
|
|
375 |
|
|
goto skip_normal_coff_symbols; |
376 |
|
|
} |
377 |
|
|
|
378 |
|
|
debug("symbol header: magic = 0x%x\n", sym_magic); |
379 |
|
|
|
380 |
|
|
debug("%i symbols @ 0x%08x (strings @ 0x%08x)\n", |
381 |
|
|
iextMax, cbExtOffset, cbSsExtOffset); |
382 |
|
|
|
383 |
|
|
symbol_data = malloc(issExtMax + 2); |
384 |
|
|
if (symbol_data == NULL) { |
385 |
|
|
fprintf(stderr, "out of memory\n"); |
386 |
|
|
exit(1); |
387 |
|
|
} |
388 |
|
|
memset(symbol_data, 0, issExtMax + 2); |
389 |
|
|
fseek(f, cbSsExtOffset, SEEK_SET); |
390 |
|
|
fread(symbol_data, 1, issExtMax + 1, f); |
391 |
|
|
|
392 |
|
|
nsymbols = iextMax; |
393 |
|
|
|
394 |
|
|
extsyms = malloc(iextMax * sizeof(struct ecoff_extsym)); |
395 |
|
|
if (extsyms == NULL) { |
396 |
|
|
fprintf(stderr, "out of memory\n"); |
397 |
|
|
exit(1); |
398 |
|
|
} |
399 |
|
|
memset(extsyms, 0, iextMax * sizeof(struct ecoff_extsym)); |
400 |
|
|
fseek(f, cbExtOffset, SEEK_SET); |
401 |
|
|
fread(extsyms, 1, iextMax * sizeof(struct ecoff_extsym), f); |
402 |
|
|
|
403 |
|
|
/* Unencode the strindex and value first: */ |
404 |
|
|
for (sym_nr=0; sym_nr<nsymbols; sym_nr++) { |
405 |
|
|
uint64_t value, strindex; |
406 |
|
|
|
407 |
|
|
unencode(strindex, &extsyms[sym_nr].es_strindex, |
408 |
|
|
uint32_t); |
409 |
|
|
unencode(value, &extsyms[sym_nr].es_value, uint32_t); |
410 |
|
|
|
411 |
|
|
extsyms[sym_nr].es_strindex = strindex; |
412 |
|
|
extsyms[sym_nr].es_value = value; |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
for (sym_nr=0; sym_nr<nsymbols; sym_nr++) { |
416 |
|
|
/* debug("symbol%6i: 0x%08x = %s\n", |
417 |
|
|
sym_nr, (int)extsyms[sym_nr].es_value, |
418 |
|
|
symbol_data + extsyms[sym_nr].es_strindex); */ |
419 |
|
|
|
420 |
|
|
add_symbol_name(&m->symbol_context, |
421 |
|
|
extsyms[sym_nr].es_value, 0, |
422 |
|
|
symbol_data + extsyms[sym_nr].es_strindex, 0, -1); |
423 |
|
|
} |
424 |
|
|
|
425 |
|
|
free(extsyms); |
426 |
|
|
free(symbol_data); |
427 |
|
|
|
428 |
|
|
skip_normal_coff_symbols: |
429 |
|
|
; |
430 |
|
|
} |
431 |
|
|
|
432 |
|
|
fclose(f); |
433 |
|
|
|
434 |
|
|
*entrypointp = a_entry; |
435 |
|
|
*gpp = a_gp; |
436 |
|
|
m->file_loaded_end_addr = end_addr; |
437 |
|
|
|
438 |
|
|
if (program_byte_order != -1) |
439 |
|
|
encoding = program_byte_order; |
440 |
|
|
|
441 |
|
|
if (encoding == ELFDATA2LSB) |
442 |
|
|
*byte_orderp = EMUL_LITTLE_ENDIAN; |
443 |
|
|
else |
444 |
|
|
*byte_orderp = EMUL_BIG_ENDIAN; |
445 |
|
|
|
446 |
|
|
n_executables_loaded ++; |
447 |
|
|
} |
448 |
|
|
|