file_ecoff.cc Source File

Back to the index.

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

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13