/[gxemul]/trunk/src/file.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/src/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 47331 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


1 dpavlin 2 /*
2     * Copyright (C) 2003-2005 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 dpavlin 6 * $Id: file.c,v 1.96 2005/06/02 12:31:39 debug Exp $
29 dpavlin 2 *
30     * This file contains functions which load executable images into (emulated)
31     * memory. File formats recognized so far:
32     *
33     * ELF 32-bit and 64-bit ELFs
34     * a.out old format used by OpenBSD 2.x pmax kernels
35     * ecoff old format used by Ultrix, Windows NT, etc
36     * srec Motorola SREC format
37     * raw raw binaries, "address:[skiplen:[entrypoint:]]filename"
38     *
39     * If a file is not of one of the above mentioned formats, it is assumed
40     * to be symbol data generated by 'nm' or 'nm -S'.
41     */
42    
43     #include <stdio.h>
44     #include <stdlib.h>
45     #include <string.h>
46     #include <sys/types.h>
47    
48     #include "cpu.h"
49     #include "exec_aout.h"
50     #include "exec_ecoff.h"
51     #include "exec_elf.h"
52     #include "machine.h"
53     #include "memory.h"
54     #include "misc.h"
55     #include "symbol.h"
56    
57    
58     /* ELF machine types as strings: (same as exec_elf.h) */
59 dpavlin 4 #define N_ELF_MACHINE_TYPES 64
60 dpavlin 2 static char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
61     "NONE", "M32", "SPARC", "386", /* 0..3 */
62     "68K", "88K", "486", "860", /* 4..7 */
63     "MIPS", "S370", "MIPS_RS3_LE", "RS6000", /* 8..11 */
64     "unknown12", "unknown13", "unknown14", "PARISC", /* 12..15 */
65     "NCUBE", "VPP500", "SPARC32PLUS", "960", /* 16..19 */
66     "PPC", "PPC64", "unknown22", "unknown23", /* 20..23 */
67     "unknown24", "unknown25", "unknown26", "unknown27", /* 24..27 */
68     "unknown28", "unknown29", "unknown30", "unknown31", /* 28..31 */
69     "unknown32", "unknown33", "unknown34", "unknown35", /* 32..35 */
70     "V800", "FR20", "RH32", "RCE", /* 36..39 */
71     "ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */
72     "TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */
73     "H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */
74 dpavlin 4 "COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */
75     "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */
76     "unknown60", "unknown61", "AMD64", "unknown63" /* 60..63 */
77 dpavlin 2 };
78    
79    
80     /*
81     * This should be increased by every routine here that actually loads an
82     * executable file into memory. (For example, loading a symbol file should
83     * NOT increase this.)
84     */
85     static int n_executables_loaded = 0;
86    
87    
88     struct aout_symbol {
89     uint32_t strindex;
90     uint32_t type;
91     uint32_t addr;
92     };
93    
94     /* Special symbol format used by Microsoft-ish COFF files: */
95     struct ms_sym {
96     unsigned char name[8];
97     unsigned char value[4];
98     unsigned char section[2];
99     unsigned char type[2];
100     unsigned char storage_class;
101     unsigned char n_aux_syms;
102     };
103    
104    
105     #define unencode(var,dataptr,typ) { \
106     int Wi; unsigned char Wb; \
107     unsigned char *Wp = (unsigned char *) dataptr; \
108     int Wlen = sizeof(typ); \
109     var = 0; \
110     for (Wi=0; Wi<Wlen; Wi++) { \
111     if (encoding == ELFDATA2LSB) \
112     Wb = Wp[Wlen-1 - Wi]; \
113     else \
114     Wb = Wp[Wi]; \
115     if (Wi == 0 && (Wb & 0x80)) { \
116     var --; /* set var to -1 :-) */ \
117     var <<= 8; \
118     } \
119     var |= Wb; \
120     if (Wi < Wlen-1) \
121     var <<= 8; \
122     } \
123     }
124    
125    
126 dpavlin 6 #define AOUT_FLAG_DECOSF1 1
127     #define AOUT_FLAG_FROM_BEGINNING 2
128 dpavlin 2 /*
129     * file_load_aout():
130     *
131     * Loads an a.out binary image into the emulated memory. The entry point
132     * (read from the a.out header) is stored in the specified CPU's registers.
133     *
134     * TODO: This has to be rewritten / corrected to support multiple a.out
135     * formats, where text/data are aligned differently.
136     */
137     static void file_load_aout(struct machine *m, struct memory *mem,
138 dpavlin 6 char *filename, int flags,
139 dpavlin 2 uint64_t *entrypointp, int arch, int *byte_orderp)
140     {
141     struct exec aout_header;
142     FILE *f;
143     int len;
144     int encoding = ELFDATA2LSB;
145     uint32_t entry, datasize, textsize;
146     int32_t symbsize = 0;
147     uint32_t vaddr, total_len;
148     unsigned char buf[4096];
149     unsigned char *syms;
150    
151     f = fopen(filename, "r");
152     if (f == NULL) {
153     perror(filename);
154     exit(1);
155     }
156    
157 dpavlin 6 if (flags & AOUT_FLAG_DECOSF1) {
158 dpavlin 2 fread(&buf, 1, 32, f);
159     vaddr = buf[16] + (buf[17] << 8) +
160     (buf[18] << 16) + (buf[19] << 24);
161     entry = buf[20] + (buf[21] << 8) +
162     (buf[22] << 16) + (buf[23] << 24);
163     debug("OSF1 a.out, load address 0x%08lx, "
164     "entry point 0x%08x\n", (long)vaddr, (long)entry);
165     symbsize = 0;
166     fseek(f, 0, SEEK_END);
167     /* This is of course wrong, but should work anyway: */
168     textsize = ftell(f) - 512;
169     datasize = 0;
170     fseek(f, 512, SEEK_SET);
171     } else {
172     len = fread(&aout_header, 1, sizeof(aout_header), f);
173     if (len != sizeof(aout_header)) {
174     fprintf(stderr, "%s: not a complete a.out image\n",
175     filename);
176     exit(1);
177     }
178    
179     unencode(entry, &aout_header.a_entry, uint32_t);
180     vaddr = entry;
181     debug("a.out, entry point 0x%08lx\n", (long)entry);
182    
183     unencode(textsize, &aout_header.a_text, uint32_t);
184     unencode(datasize, &aout_header.a_data, uint32_t);
185     debug("text + data = %i + %i bytes\n", textsize, datasize);
186    
187     unencode(symbsize, &aout_header.a_syms, uint32_t);
188     }
189    
190 dpavlin 6 if (flags & AOUT_FLAG_FROM_BEGINNING) {
191     fseek(f, 0, SEEK_SET);
192     vaddr &= ~0xfff;
193     }
194    
195 dpavlin 2 /* Load text and data: */
196     total_len = textsize + datasize;
197     while (total_len != 0) {
198     len = total_len > sizeof(buf) ? sizeof(buf) : total_len;
199     len = fread(buf, 1, len, f);
200    
201     /* printf("fread len=%i vaddr=%x buf[0..]=%02x %02x %02x\n",
202     len, (int)vaddr, buf[0], buf[1], buf[2]); */
203    
204     if (len > 0)
205     m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr,
206     &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);
207     else {
208 dpavlin 6 if (flags & AOUT_FLAG_DECOSF1)
209 dpavlin 2 break;
210     else {
211     fprintf(stderr, "could not read from %s\n",
212     filename);
213     exit(1);
214     }
215     }
216    
217     vaddr += len;
218     total_len -= len;
219     }
220    
221     if (symbsize != 0) {
222     struct aout_symbol *aout_symbol_ptr;
223     int i, n_symbols;
224     uint32_t type, addr, str_index;
225     uint32_t strings_len;
226     char *string_symbols;
227     off_t oldpos;
228    
229     debug("symbols: %i bytes @ 0x%x\n", symbsize, (int)ftell(f));
230     syms = malloc(symbsize);
231     if (syms == NULL) {
232     fprintf(stderr, "out of memory\n");
233     exit(1);
234     }
235     len = fread(syms, 1, symbsize, f);
236     if (len != symbsize) {
237     fprintf(stderr, "error reading symbols from %s\n",
238     filename);
239     exit(1);
240     }
241    
242     oldpos = ftell(f);
243     fseek(f, 0, SEEK_END);
244     strings_len = ftell(f) - oldpos;
245     fseek(f, oldpos, SEEK_SET);
246     debug("strings: %i bytes @ 0x%x\n", strings_len, (int)ftell(f));
247     string_symbols = malloc(strings_len);
248     if (string_symbols == NULL) {
249     fprintf(stderr, "out of memory\n");
250     exit(1);
251     }
252     fread(string_symbols, 1, strings_len, f);
253    
254     aout_symbol_ptr = (struct aout_symbol *) syms;
255     n_symbols = symbsize / sizeof(struct aout_symbol);
256     i = 0;
257     while (i < n_symbols) {
258     unencode(str_index, &aout_symbol_ptr[i].strindex,
259     uint32_t);
260     unencode(type, &aout_symbol_ptr[i].type, uint32_t);
261     unencode(addr, &aout_symbol_ptr[i].addr, uint32_t);
262    
263     /* debug("symbol type 0x%04x @ 0x%08x: %s\n",
264     type, addr, string_symbols + str_index); */
265    
266     if (type != 0 && addr != 0)
267     add_symbol_name(&m->symbol_context,
268     addr, 0, string_symbols + str_index, 0);
269     i++;
270     }
271    
272     free(string_symbols);
273     free(syms);
274     }
275    
276     fclose(f);
277    
278 dpavlin 6 *entrypointp = (int32_t)entry;
279 dpavlin 2
280     if (encoding == ELFDATA2LSB)
281     *byte_orderp = EMUL_LITTLE_ENDIAN;
282     else
283     *byte_orderp = EMUL_BIG_ENDIAN;
284    
285     n_executables_loaded ++;
286     }
287    
288    
289     /*
290     * file_load_ecoff():
291     *
292     * Loads an ecoff binary image into the emulated memory. The entry point
293     * (read from the ecoff header) is stored in the specified CPU's registers.
294     */
295     static void file_load_ecoff(struct machine *m, struct memory *mem,
296     char *filename, uint64_t *entrypointp,
297     int arch, uint64_t *gpp, int *byte_orderp)
298     {
299     struct ecoff_exechdr exechdr;
300     int f_magic, f_nscns, f_nsyms;
301     int a_magic;
302     off_t f_symptr, a_tsize, a_dsize, a_bsize;
303     uint64_t a_entry, a_tstart, a_dstart, a_bstart, a_gp, end_addr=0;
304     char *format_name;
305     struct ecoff_scnhdr scnhdr;
306     FILE *f;
307     int len, secn, total_len, chunk_size;
308     int encoding = ELFDATA2LSB; /* Assume little-endian. See below */
309     int program_byte_order = -1;
310     unsigned char buf[8192];
311    
312     f = fopen(filename, "r");
313     if (f == NULL) {
314     perror(filename);
315     exit(1);
316     }
317    
318     len = fread(&exechdr, 1, sizeof(exechdr), f);
319     if (len != sizeof(exechdr)) {
320     fprintf(stderr, " not a complete ecoff image\n");
321     exit(1);
322     }
323    
324     /*
325     * The following code looks a bit ugly, but it should work. The ECOFF
326     * 16-bit magic value seems to be stored in MSB byte order for
327     * big-endian binaries, and LSB byte order for little-endian binaries.
328     *
329     * The unencode() assumes little-endianness by default.
330     */
331     unencode(f_magic, &exechdr.f.f_magic, uint16_t);
332     switch (f_magic) {
333     case ((ECOFF_MAGIC_MIPSEB & 0xff) << 8) +
334     ((ECOFF_MAGIC_MIPSEB >> 8) & 0xff):
335     format_name = "MIPS1 BE";
336     encoding = ELFDATA2MSB;
337     break;
338     case ECOFF_MAGIC_MIPSEB:
339     /* NOTE: Big-endian header, little-endian code! */
340     format_name = "MIPS1 BE-LE";
341     encoding = ELFDATA2MSB;
342     program_byte_order = ELFDATA2LSB;
343     break;
344     case ECOFF_MAGIC_MIPSEL:
345     format_name = "MIPS1 LE";
346     encoding = ELFDATA2LSB;
347     break;
348     case ((ECOFF_MAGIC_MIPSEB2 & 0xff) << 8) +
349     ((ECOFF_MAGIC_MIPSEB2 >> 8) & 0xff):
350     format_name = "MIPS2 BE";
351     encoding = ELFDATA2MSB;
352     break;
353     case ECOFF_MAGIC_MIPSEL2:
354     format_name = "MIPS2 LE";
355     encoding = ELFDATA2LSB;
356     break;
357     case ((ECOFF_MAGIC_MIPSEB3 & 0xff) << 8) +
358     ((ECOFF_MAGIC_MIPSEB3 >> 8) & 0xff):
359     format_name = "MIPS3 BE";
360     encoding = ELFDATA2MSB;
361     break;
362     case ECOFF_MAGIC_MIPSEL3:
363     format_name = "MIPS3 LE";
364     encoding = ELFDATA2LSB;
365     break;
366     default:
367     fprintf(stderr, "%s: unimplemented ECOFF format, magic = "
368     "0x%04x\n", filename, (int)f_magic);
369     exit(1);
370     }
371    
372     /* Read various header information: */
373     unencode(f_nscns, &exechdr.f.f_nscns, uint16_t);
374     unencode(f_symptr, &exechdr.f.f_symptr, uint32_t);
375     unencode(f_nsyms, &exechdr.f.f_nsyms, uint32_t);
376     debug("ECOFF, %s, %i sections, %i symbols @ 0x%lx\n",
377     format_name, f_nscns, f_nsyms, (long)f_symptr);
378    
379     unencode(a_magic, &exechdr.a.magic, uint16_t);
380     unencode(a_tsize, &exechdr.a.tsize, uint32_t);
381     unencode(a_dsize, &exechdr.a.dsize, uint32_t);
382     unencode(a_bsize, &exechdr.a.bsize, uint32_t);
383     debug("magic 0x%04x, tsize 0x%x, dsize 0x%x, bsize 0x%x\n",
384     a_magic, (int)a_tsize, (int)a_dsize, (int)a_bsize);
385    
386     unencode(a_tstart, &exechdr.a.text_start, uint32_t);
387     unencode(a_dstart, &exechdr.a.data_start, uint32_t);
388     unencode(a_bstart, &exechdr.a.bss_start, uint32_t);
389     debug("text @ 0x%08x, data @ 0x%08x, bss @ 0x%08x\n",
390     (int)a_tstart, (int)a_dstart, (int)a_bstart);
391    
392     unencode(a_entry, &exechdr.a.entry, uint32_t);
393     unencode(a_gp, &exechdr.a.gp_value, uint32_t);
394     debug("entrypoint 0x%08x, gp = 0x%08x\n",
395     (int)a_entry, (int)a_gp);
396    
397     /*
398     * Special hack for a MACH/pmax kernel, I don't know how applicable
399     * this is for other files:
400     * there are no sections (!), and a_magic = 0x0108 instead of
401     * 0x0107 as it is on most other (E)COFF files I've seen.
402     *
403     * Then load everything after the header to the text start address.
404     */
405     if (f_nscns == 0 && a_magic == 0x108) {
406     uint64_t where = a_tstart;
407     total_len = 0;
408     fseek(f, 0x50, SEEK_SET);
409     while (!feof(f)) {
410     chunk_size = 256;
411     len = fread(buf, 1, chunk_size, f);
412    
413     if (len > 0)
414     m->cpus[0]->memory_rw(m->cpus[0], mem, where,
415     &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);
416     where += len;
417     total_len += len;
418     }
419     debug("MACH/pmax hack (!), read 0x%x bytes\n", total_len);
420     }
421    
422     /* Go through all the section headers: */
423     for (secn=0; secn<f_nscns; secn++) {
424     off_t s_scnptr, s_relptr, s_lnnoptr, oldpos;
425     int s_nreloc, s_nlnno, s_flags;
426     int s_size;
427     unsigned int i;
428     uint64_t s_paddr, s_vaddr;
429    
430     /* Read a section header: */
431     len = fread(&scnhdr, 1, sizeof(scnhdr), f);
432     if (len != sizeof(scnhdr)) {
433     fprintf(stderr, "%s: incomplete section "
434     "header %i\n", filename, secn);
435     exit(1);
436     }
437    
438     /* Show the section name: */
439     debug("section ");
440     for (i=0; i<sizeof(scnhdr.s_name); i++)
441     if (scnhdr.s_name[i] >= 32 && scnhdr.s_name[i] < 127)
442     debug("%c", scnhdr.s_name[i]);
443     else
444     break;
445     debug(" (");
446    
447     unencode(s_paddr, &scnhdr.s_paddr, uint32_t);
448     unencode(s_vaddr, &scnhdr.s_vaddr, uint32_t);
449     unencode(s_size, &scnhdr.s_size, uint32_t);
450     unencode(s_scnptr, &scnhdr.s_scnptr, uint32_t);
451     unencode(s_relptr, &scnhdr.s_relptr, uint32_t);
452     unencode(s_lnnoptr, &scnhdr.s_lnnoptr, uint32_t);
453     unencode(s_nreloc, &scnhdr.s_nreloc, uint16_t);
454     unencode(s_nlnno, &scnhdr.s_nlnno, uint16_t);
455     unencode(s_flags, &scnhdr.s_flags, uint32_t);
456    
457     debug("0x%x @ 0x%08x, offset 0x%lx, flags 0x%x)\n",
458     (int)s_size, (int)s_vaddr, (long)s_scnptr, (int)s_flags);
459    
460     end_addr = s_vaddr + s_size;
461    
462     if (s_relptr != 0) {
463     /*
464     * TODO: Read this url, or similar:
465     * http://www.iecc.com/linker/linker07.html
466     */
467     fprintf(stderr, "%s: relocatable code/data in "
468     "section nr %i: not yet implemented\n",
469     filename, secn);
470     exit(1);
471     }
472    
473     /* Loadable? Then load the section: */
474     if (s_scnptr != 0 && s_size != 0 &&
475     s_vaddr != 0 && !(s_flags & 0x02)) {
476     /* Remember the current file offset: */
477     oldpos = ftell(f);
478    
479     /* Load the section into emulated memory: */
480     fseek(f, s_scnptr, SEEK_SET);
481     total_len = 0;
482     chunk_size = 1;
483     if ((s_vaddr & 0xf) == 0) chunk_size = 0x10;
484     if ((s_vaddr & 0xff) == 0) chunk_size = 0x100;
485     if ((s_vaddr & 0xfff) == 0) chunk_size = 0x1000;
486     while (total_len < s_size) {
487     len = chunk_size;
488     if (total_len + len > s_size)
489     len = s_size - total_len;
490     len = fread(buf, 1, chunk_size, f);
491     if (len == 0) {
492     debug("!!! total_len = %i, "
493     "chunk_size = %i, len = %i\n",
494     total_len, chunk_size, len);
495     break;
496     }
497    
498     m->cpus[0]->memory_rw(m->cpus[0], mem, s_vaddr,
499     &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);
500     s_vaddr += len;
501     total_len += len;
502     }
503    
504     /* Return to position inside the section headers: */
505     fseek(f, oldpos, SEEK_SET);
506     }
507     }
508    
509     if (f_symptr != 0 && f_nsyms != 0) {
510     struct ecoff_symhdr symhdr;
511     int sym_magic, iextMax, issExtMax, issMax, crfd;
512     off_t cbRfdOffset, cbExtOffset, cbSsExtOffset, cbSsOffset;
513     char *symbol_data;
514     struct ecoff_extsym *extsyms;
515     int nsymbols, sym_nr;
516    
517     fseek(f, f_symptr, SEEK_SET);
518    
519     len = fread(&symhdr, 1, sizeof(symhdr), f);
520     if (len != sizeof(symhdr)) {
521     fprintf(stderr, "%s: not a complete "
522     "ecoff image: symhdr broken\n", filename);
523     exit(1);
524     }
525    
526     unencode(sym_magic, &symhdr.magic, uint16_t);
527     unencode(crfd, &symhdr.crfd, uint32_t);
528     unencode(cbRfdOffset, &symhdr.cbRfdOffset, uint32_t);
529     unencode(issMax, &symhdr.issMax, uint32_t);
530     unencode(cbSsOffset, &symhdr.cbSsOffset, uint32_t);
531     unencode(issExtMax, &symhdr.issExtMax, uint32_t);
532     unencode(cbSsExtOffset, &symhdr.cbSsExtOffset, uint32_t);
533     unencode(iextMax, &symhdr.iextMax, uint32_t);
534     unencode(cbExtOffset, &symhdr.cbExtOffset, uint32_t);
535    
536     if (sym_magic != MIPS_MAGIC_SYM) {
537     unsigned char *ms_sym_buf;
538     struct ms_sym *sym;
539     int n_real_symbols = 0;
540    
541     debug("bad symbol magic, assuming Microsoft format: ");
542    
543     /*
544     * See http://www.lisoleg.net/lisoleg/elfandlib/
545     * Microsoft%20Portable%20Executable%20COFF%20For
546     * mat%20Specification.txt
547     * for more details.
548     */
549     ms_sym_buf = malloc(sizeof(struct ms_sym) * f_nsyms);
550     if (ms_sym_buf == NULL) {
551     fprintf(stderr, "out of memory\n");
552     exit(1);
553     }
554     fseek(f, f_symptr, SEEK_SET);
555     len = fread(ms_sym_buf, 1,
556     sizeof(struct ms_sym) * f_nsyms, f);
557     sym = (struct ms_sym *) ms_sym_buf;
558     for (sym_nr=0; sym_nr<f_nsyms; sym_nr++) {
559     char name[300];
560     uint32_t v, t, altname;
561     /* debug("sym %5i: '", sym_nr);
562     for (i=0; i<8 && sym->name[i]; i++)
563     debug("%c", sym->name[i]); */
564     v = sym->value[0] + (sym->value[1] << 8)
565     + (sym->value[2] << 16)
566     + (sym->value[3] << 24);
567     altname = sym->name[4] + (sym->name[5] << 8)
568     + (sym->name[6] << 16)
569     + (sym->name[3] << 24);
570     t = (sym->type[1] << 8) + sym->type[0];
571     /* TODO: big endian COFF? */
572     /* debug("' value=0x%x type=0x%04x", v, t); */
573    
574     if (t == 0x20 && sym->name[0]) {
575     memcpy(name, sym->name, 8);
576     name[8] = '\0';
577     add_symbol_name(&m->symbol_context,
578     v, 0, name, 0);
579     n_real_symbols ++;
580     } else if (t == 0x20 && !sym->name[0]) {
581     off_t ofs;
582     ofs = f_symptr + altname +
583     sizeof(struct ms_sym) * f_nsyms;
584     fseek(f, ofs, SEEK_SET);
585     fread(name, 1, sizeof(name), f);
586     name[sizeof(name)-1] = '\0';
587     /* debug(" [altname=0x%x '%s']",
588     altname, name); */
589     add_symbol_name(&m->symbol_context,
590     v, 0, name, 0);
591     n_real_symbols ++;
592     }
593    
594    
595     if (sym->n_aux_syms) {
596     int n = sym->n_aux_syms;
597     /* debug(" aux='"); */
598     while (n-- > 0) {
599     sym ++; sym_nr ++;
600     /* for (i=0; i<8 &&
601     sym->name[i]; i++)
602     debug("%c",
603     sym->name[i]); */
604     }
605     /* debug("'"); */
606     }
607     /* debug("\n"); */
608     sym ++;
609     }
610    
611     debug("%i symbols\n", n_real_symbols);
612     free(ms_sym_buf);
613    
614     goto skip_normal_coff_symbols;
615     }
616    
617     debug("symbol header: magic = 0x%x\n", sym_magic);
618    
619     debug("%i symbols @ 0x%08x (strings @ 0x%08x)\n",
620     iextMax, cbExtOffset, cbSsExtOffset);
621    
622     symbol_data = malloc(issExtMax + 2);
623     if (symbol_data == NULL) {
624     fprintf(stderr, "out of memory\n");
625     exit(1);
626     }
627     memset(symbol_data, 0, issExtMax + 2);
628     fseek(f, cbSsExtOffset, SEEK_SET);
629     fread(symbol_data, 1, issExtMax + 1, f);
630    
631     nsymbols = iextMax;
632    
633     extsyms = malloc(iextMax * sizeof(struct ecoff_extsym));
634     if (extsyms == NULL) {
635     fprintf(stderr, "out of memory\n");
636     exit(1);
637     }
638     memset(extsyms, 0, iextMax * sizeof(struct ecoff_extsym));
639     fseek(f, cbExtOffset, SEEK_SET);
640     fread(extsyms, 1, iextMax * sizeof(struct ecoff_extsym), f);
641    
642     /* Unencode the strindex and value first: */
643     for (sym_nr=0; sym_nr<nsymbols; sym_nr++) {
644     uint64_t value, strindex;
645    
646     unencode(strindex, &extsyms[sym_nr].es_strindex,
647     uint32_t);
648     unencode(value, &extsyms[sym_nr].es_value, uint32_t);
649    
650     extsyms[sym_nr].es_strindex = strindex;
651     extsyms[sym_nr].es_value = value;
652     }
653    
654     for (sym_nr=0; sym_nr<nsymbols; sym_nr++) {
655     /* debug("symbol%6i: 0x%08x = %s\n",
656     sym_nr, (int)extsyms[sym_nr].es_value,
657     symbol_data + extsyms[sym_nr].es_strindex); */
658    
659     add_symbol_name(&m->symbol_context,
660     extsyms[sym_nr].es_value, 0,
661     symbol_data + extsyms[sym_nr].es_strindex, 0);
662     }
663    
664     free(extsyms);
665     free(symbol_data);
666    
667     skip_normal_coff_symbols:
668     ;
669     }
670    
671     fclose(f);
672    
673     *entrypointp = a_entry;
674     *gpp = a_gp;
675     m->file_loaded_end_addr = end_addr;
676    
677     if (program_byte_order != -1)
678     encoding = program_byte_order;
679    
680     if (encoding == ELFDATA2LSB)
681     *byte_orderp = EMUL_LITTLE_ENDIAN;
682     else
683     *byte_orderp = EMUL_BIG_ENDIAN;
684    
685     n_executables_loaded ++;
686     }
687    
688    
689     /*
690     * file_load_srec():
691     *
692     * Loads a Motorola SREC file into emulated memory. Description of the SREC
693     * file format can be found at here:
694     *
695     * http://www.ndsu.nodak.edu/instruct/tareski/373f98/notes/srecord.htm
696     * or http://www.amelek.gda.pl/avr/uisp/srecord.htm
697     */
698     static void file_load_srec(struct machine *m, struct memory *mem,
699     char *filename, uint64_t *entrypointp)
700     {
701     FILE *f;
702     unsigned char buf[516];
703     unsigned char bytes[270];
704     uint64_t entry = 0, vaddr = 0;
705     int i, j, count;
706     char ch;
707     int buf_len, data_start = 0;
708     int entry_set = 0;
709     int warning = 0;
710     int warning_len = 0;
711     int total_bytes_loaded = 0;
712    
713     f = fopen(filename, "r");
714     if (f == NULL) {
715     perror(filename);
716     exit(1);
717     }
718    
719     /* Load file contents: */
720     while (!feof(f)) {
721     memset(buf, 0, sizeof(buf));
722     fgets((char *)buf, sizeof(buf)-1, f);
723    
724     if (buf[0] == 0 || buf[0]=='\r' || buf[0]=='\n')
725     continue;
726    
727     if (buf[0] != 'S') {
728     if (!warning)
729     debug("WARNING! non-S-record found\n");
730     warning = 1;
731     continue;
732     }
733    
734     buf_len = strlen((char *)buf);
735    
736     if (buf_len < 10) {
737     if (!warning_len)
738     debug("WARNING! invalid S-record found\n");
739     warning_len = 1;
740     continue;
741     }
742    
743     /*
744     * Stype count address data checksum
745     * 01 23 4.. .. (last 2 bytes)
746     *
747     * TODO: actually check the checksum
748     */
749    
750     j = 0;
751     for (i=1; i<buf_len; i++) {
752     if (buf[i]>='a' && buf[i]<='f')
753     buf[i] += 10 - 'a';
754     else if (buf[i] >= 'A' && buf[i] <= 'F')
755     buf[i] += 10 - 'A';
756     else if (buf[i] >= '0' && buf[i] <= '9')
757     buf[i] -= '0';
758     else if (buf[i] == '\r' || buf[i] == '\n') {
759     } else
760     fatal("invalid characters '%c' in S-record\n",
761     buf[i]);
762    
763     if (i >= 4) {
764     if (i & 1)
765     bytes[j++] += buf[i];
766     else
767     bytes[j] = buf[i] * 16;
768     }
769     }
770    
771     count = buf[2] * 16 + buf[3];
772     /* debug("count=%i j=%i\n", count, j); */
773     /* count is j - 1. */
774    
775     switch (buf[1]) {
776     case 0:
777     debug("SREC \"");
778     for (i=2; i<count-1; i++) {
779     ch = bytes[i];
780     if (ch >= ' ' && ch < 127)
781     debug("%c", ch);
782     else
783     debug("?");
784     }
785     debug("\"\n");
786     break;
787     case 1:
788     case 2:
789     case 3:
790     /* switch again, to get the load address: */
791     switch (buf[1]) {
792     case 1: data_start = 2;
793     vaddr = (bytes[0] << 8) + bytes[1];
794     break;
795     case 2: data_start = 3;
796     vaddr = (bytes[0] << 16) + (bytes[1] << 8) +
797     bytes[2];
798     break;
799     case 3: data_start = 4;
800     vaddr = (bytes[0] << 24) + (bytes[1] << 16) +
801     (bytes[2] << 8) + bytes[3];
802     }
803     m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr,
804     &bytes[data_start], count - 1 - data_start,
805     MEM_WRITE, NO_EXCEPTIONS);
806     total_bytes_loaded += count - 1 - data_start;
807     break;
808     case 7:
809     case 8:
810     case 9:
811     /* switch again, to get the entry point: */
812     switch (buf[1]) {
813     case 7: entry = (bytes[0] << 24) + (bytes[1] << 16) +
814     (bytes[2] << 8) + bytes[3];
815     break;
816     case 8: entry = (bytes[0] << 16) + (bytes[1] << 8) +
817     bytes[2];
818     break;
819     case 9: entry = (bytes[0] << 8) + bytes[1];
820     break;
821     }
822     entry_set = 1;
823     debug("entry point 0x%08x\n", (unsigned int)entry);
824     break;
825     default:
826     debug("unimplemented S-record type %i\n", buf[1]);
827     }
828     }
829    
830     debug("0x%x bytes loaded\n", total_bytes_loaded);
831    
832     fclose(f);
833    
834     if (!entry_set)
835     debug("WARNING! no entrypoint found!\n");
836     else
837     *entrypointp = entry;
838    
839     n_executables_loaded ++;
840     }
841    
842    
843     /*
844     * file_load_raw():
845     *
846     * Loads a raw binary into emulated memory. The filename should be
847     * of the following form: loadaddress:filename
848     * or loadaddress:skiplen:filename
849     * or loadaddress:skiplen:pc:filename
850     */
851     static void file_load_raw(struct machine *m, struct memory *mem,
852     char *filename, uint64_t *entrypointp)
853     {
854     FILE *f;
855     int len;
856     unsigned char buf[4096];
857     uint64_t entry, loadaddr, vaddr, skip = 0;
858     char *p, *p2;
859    
860     p = strchr(filename, ':');
861     if (p == NULL) {
862     fprintf(stderr, "\n");
863     perror(filename);
864     exit(1);
865     }
866    
867     loadaddr = vaddr = entry = strtoull(filename, NULL, 0);
868     p2 = p+1;
869    
870     /* A second value? That's the optional skip value */
871     p = strchr(p2, ':');
872     if (p != NULL) {
873     skip = strtoull(p2, NULL, 0);
874     p = p+1;
875     /* A third value? That's the initial pc: */
876     if (strchr(p, ':') != NULL) {
877     entry = strtoull(p, NULL, 0);
878     p = strchr(p, ':') + 1;
879     }
880     } else
881     p = p2;
882    
883     f = fopen(strrchr(filename, ':')+1, "r");
884     if (f == NULL) {
885     perror(p);
886     exit(1);
887     }
888    
889     fseek(f, skip, SEEK_SET);
890    
891     /* Load file contents: */
892     while (!feof(f)) {
893     len = fread(buf, 1, sizeof(buf), f);
894    
895     if (len > 0)
896     m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0],
897     len, MEM_WRITE, NO_EXCEPTIONS);
898    
899     vaddr += len;
900     }
901    
902     debug("RAW: 0x%llx bytes @ 0x%08llx",
903     (long long) (ftell(f) - skip), (long long)loadaddr);
904     if (skip != 0)
905     debug(" (0x%llx bytes of header skipped)", (long long)skip);
906     debug("\n");
907    
908     fclose(f);
909    
910     *entrypointp = entry;
911    
912     n_executables_loaded ++;
913     }
914    
915    
916     /*
917     * file_load_elf():
918     *
919     * Loads an ELF image into the emulated memory. The entry point (read from
920     * the ELF header) and the initial value of the gp register (read from the
921     * ELF symbol table) are stored in the specified CPU's registers.
922     *
923     * This is pretty heavy stuff, but is needed because of the heaviness of
924     * ELF files. :-/ Hopefully it will be able to recognize most valid ELFs.
925     */
926     static void file_load_elf(struct machine *m, struct memory *mem,
927     char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp,
928     int *byte_order, uint64_t *tocp)
929     {
930     Elf32_Ehdr hdr32;
931     Elf64_Ehdr hdr64;
932     FILE *f;
933     uint64_t eentry;
934     int len, i, ok;
935     int elf64, encoding, eflags;
936     int etype, emachine;
937     int ephnum, ephentsize, eshnum, eshentsize;
938     off_t ephoff, eshoff;
939     Elf32_Phdr phdr32;
940     Elf64_Phdr phdr64;
941     Elf32_Shdr shdr32;
942     Elf64_Shdr shdr64;
943     Elf32_Sym sym32;
944     Elf64_Sym sym64;
945     int ofs;
946     int chunk_len = 1024, align_len;
947     char *symbol_strings = NULL; size_t symbol_length = 0;
948     char *s;
949     Elf32_Sym *symbols_sym32 = NULL; int n_symbols = 0;
950     Elf64_Sym *symbols_sym64 = NULL;
951    
952     f = fopen(filename, "r");
953     if (f == NULL) {
954     perror(filename);
955     exit(1);
956     }
957    
958     len = fread(&hdr32, 1, sizeof(Elf32_Ehdr), f);
959     if (len < (signed int)sizeof(Elf32_Ehdr)) {
960     fprintf(stderr, "%s: not an ELF file image\n", filename);
961     exit(1);
962     }
963    
964     if (memcmp(&hdr32.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0) {
965     fprintf(stderr, "%s: not an ELF file image\n", filename);
966     exit(1);
967     }
968    
969     switch (hdr32.e_ident[EI_CLASS]) {
970     case ELFCLASS32:
971     elf64 = 0;
972     break;
973     case ELFCLASS64:
974     elf64 = 1;
975     fseek(f, 0, SEEK_SET);
976     len = fread(&hdr64, 1, sizeof(Elf64_Ehdr), f);
977     if (len < (signed int)sizeof(Elf64_Ehdr)) {
978     fprintf(stderr, "%s: not an ELF64 file image\n",
979     filename);
980     exit(1);
981     }
982     break;
983     default:
984     fprintf(stderr, "%s: unknown ELF class '%i'\n",
985     filename, hdr32.e_ident[EI_CLASS]);
986     exit(1);
987     }
988    
989     encoding = hdr32.e_ident[EI_DATA];
990     if (encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) {
991     fprintf(stderr, "%s: unknown data encoding '%i'\n",
992     filename, hdr32.e_ident[EI_DATA]);
993     exit(1);
994     }
995    
996     if (elf64) {
997     unencode(etype, &hdr64.e_type, Elf64_Quarter);
998     unencode(eflags, &hdr64.e_flags, Elf64_Half);
999     unencode(emachine, &hdr64.e_machine, Elf64_Quarter);
1000     unencode(eentry, &hdr64.e_entry, Elf64_Addr);
1001     unencode(ephnum, &hdr64.e_phnum, Elf64_Quarter);
1002     unencode(ephentsize, &hdr64.e_phentsize, Elf64_Quarter);
1003     unencode(ephoff, &hdr64.e_phoff, Elf64_Off);
1004     unencode(eshnum, &hdr64.e_shnum, Elf64_Quarter);
1005     unencode(eshentsize, &hdr64.e_shentsize, Elf64_Quarter);
1006     unencode(eshoff, &hdr64.e_shoff, Elf64_Off);
1007     if (ephentsize != sizeof(Elf64_Phdr)) {
1008     fprintf(stderr, "%s: incorrect phentsize? %i, should "
1009 dpavlin 6 "be %i\nPerhaps this is a dynamically linked "
1010     "binary (which isn't supported yet).\n", filename,
1011     (int)ephentsize, (int)sizeof(Elf64_Phdr));
1012 dpavlin 2 exit(1);
1013     }
1014     if (eshentsize != sizeof(Elf64_Shdr)) {
1015 dpavlin 6 fprintf(stderr, "%s: incorrect shentsize? %i, should "
1016     "be %i\nPerhaps this is a dynamically linked "
1017     "binary (which isn't supported yet).\n", filename,
1018     (int)eshentsize, (int)sizeof(Elf64_Shdr));
1019 dpavlin 2 exit(1);
1020     }
1021     } else {
1022     unencode(etype, &hdr32.e_type, Elf32_Half);
1023     unencode(eflags, &hdr32.e_flags, Elf32_Word);
1024     unencode(emachine, &hdr32.e_machine, Elf32_Half);
1025     unencode(eentry, &hdr32.e_entry, Elf32_Addr);
1026     unencode(ephnum, &hdr32.e_phnum, Elf32_Half);
1027     unencode(ephentsize, &hdr32.e_phentsize, Elf32_Half);
1028     unencode(ephoff, &hdr32.e_phoff, Elf32_Off);
1029     unencode(eshnum, &hdr32.e_shnum, Elf32_Half);
1030     unencode(eshentsize, &hdr32.e_shentsize, Elf32_Half);
1031     unencode(eshoff, &hdr32.e_shoff, Elf32_Off);
1032     if (ephentsize != sizeof(Elf32_Phdr)) {
1033     fprintf(stderr, "%s: incorrect phentsize? %i, should "
1034 dpavlin 6 "be %i\nPerhaps this is a dynamically linked "
1035     "binary (which isn't supported yet).\n", filename,
1036     (int)ephentsize, (int)sizeof(Elf32_Phdr));
1037 dpavlin 2 exit(1);
1038     }
1039     if (eshentsize != sizeof(Elf32_Shdr)) {
1040 dpavlin 6 fprintf(stderr, "%s: incorrect shentsize? %i, should "
1041     "be %i\nPerhaps this is a dynamically linked "
1042     "binary (which isn't supported yet).\n", filename,
1043     (int)eshentsize, (int)sizeof(Elf32_Shdr));
1044 dpavlin 2 exit(1);
1045     }
1046     }
1047    
1048     if ( etype != ET_EXEC ) {
1049     fprintf(stderr, "%s is not an ELF Executable file, type = %i\n",
1050     filename, etype);
1051     exit(1);
1052     }
1053    
1054     ok = 0;
1055     switch (arch) {
1056 dpavlin 4 case ARCH_ALPHA:
1057     switch (emachine) {
1058     case EM_ALPHA:
1059     case -28634:
1060     ok = 1;
1061     }
1062     break;
1063     case ARCH_HPPA:
1064     switch (emachine) {
1065     case EM_PARISC:
1066     ok = 1;
1067     }
1068     break;
1069 dpavlin 2 case ARCH_MIPS:
1070     switch (emachine) {
1071     case EM_MIPS:
1072     case EM_MIPS_RS3_LE:
1073     ok = 1;
1074     }
1075     break;
1076     case ARCH_PPC:
1077     switch (emachine) {
1078     case EM_PPC:
1079     case EM_PPC64:
1080     ok = 1;
1081     }
1082     break;
1083     case ARCH_SPARC:
1084     switch (emachine) {
1085     case EM_SPARC:
1086     case EM_SPARCV9:
1087     ok = 1;
1088     }
1089     break;
1090 dpavlin 4 case ARCH_X86:
1091 dpavlin 2 switch (emachine) {
1092 dpavlin 4 case EM_386:
1093     case EM_486:
1094 dpavlin 6 *tocp = 1;
1095 dpavlin 2 ok = 1;
1096 dpavlin 4 break;
1097     case EM_AMD64:
1098 dpavlin 6 *tocp = 2;
1099 dpavlin 2 ok = 1;
1100 dpavlin 4 break;
1101 dpavlin 2 }
1102     break;
1103 dpavlin 6 case ARCH_ARM:
1104     switch (emachine) {
1105     case EM_ARM:
1106     ok = 1;
1107     }
1108     break;
1109 dpavlin 2 default:
1110     fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n");
1111     }
1112     if (!ok) {
1113     fprintf(stderr, "%s: this is a ", filename);
1114     if (emachine >= 0 && emachine < N_ELF_MACHINE_TYPES)
1115     fprintf(stderr, elf_machine_type[emachine]);
1116     else
1117     fprintf(stderr, "machine type '%i'", emachine);
1118     fprintf(stderr, " ELF binary!\n");
1119     exit(1);
1120     }
1121    
1122     s = "entry point";
1123     if (elf64 && arch == ARCH_PPC)
1124     s = "function descriptor at";
1125    
1126     debug("ELF%i %s, %s 0x", elf64? 64 : 32,
1127     encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s);
1128    
1129     if (elf64)
1130     debug("%016llx\n", (long long)eentry);
1131     else
1132     debug("%08x\n", (int)eentry);
1133    
1134     /*
1135     * MIPS16 encoding?
1136     *
1137     * TODO: Find out what e_flag actually contains.
1138     * TODO 2: This only sets mips16 for cpu 0. Yuck. Fix this!
1139     */
1140    
1141     if (((eflags >> 24) & 0xff) == 0x24) {
1142     debug("MIPS16 encoding (e_flags = 0x%08x)\n", eflags);
1143     #ifdef ENABLE_MIPS16
1144     m->cpus[0]->cd.mips.mips16 = 1;
1145     #else
1146     fatal("ENABLE_MIPS16 must be defined in misc.h.\n"
1147     "(or use the --mips16 configure option)\n");
1148     exit(1);
1149     #endif
1150     } else if (eentry & 0x3) {
1151     debug("MIPS16 encoding (eentry not 32-bit aligned)\n");
1152     #ifdef ENABLE_MIPS16
1153     m->cpus[0]->cd.mips.mips16 = 1;
1154     #else
1155     fatal("ENABLE_MIPS16 must be defined in misc.h.\n"
1156     "(or use the --mips16 configure option)\n");
1157     exit(1);
1158     #endif
1159     }
1160    
1161     /* Read the program headers: */
1162    
1163     for (i=0; i<ephnum; i++) {
1164     int p_type;
1165     uint64_t p_offset;
1166     uint64_t p_vaddr;
1167     uint64_t p_paddr;
1168     uint64_t p_filesz;
1169     uint64_t p_memsz;
1170     int p_flags;
1171     int p_align;
1172    
1173     fseek(f, ephoff + i * ephentsize, SEEK_SET);
1174    
1175     if (elf64) {
1176     fread(&phdr64, 1, sizeof(Elf64_Phdr), f);
1177     unencode(p_type, &phdr64.p_type, Elf64_Half);
1178     unencode(p_flags, &phdr64.p_flags, Elf64_Half);
1179     unencode(p_offset, &phdr64.p_offset, Elf64_Off);
1180     unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr);
1181     unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr);
1182     unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword);
1183     unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword);
1184     unencode(p_align, &phdr64.p_align, Elf64_Xword);
1185     } else {
1186     fread(&phdr32, 1, sizeof(Elf32_Phdr), f);
1187     unencode(p_type, &phdr32.p_type, Elf32_Word);
1188     unencode(p_offset, &phdr32.p_offset, Elf32_Off);
1189     unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr);
1190     unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr);
1191     unencode(p_filesz, &phdr32.p_filesz, Elf32_Word);
1192     unencode(p_memsz, &phdr32.p_memsz, Elf32_Word);
1193     unencode(p_flags, &phdr32.p_flags, Elf32_Word);
1194     unencode(p_align, &phdr32.p_align, Elf32_Word);
1195     }
1196    
1197     if (p_memsz != 0 && (p_type == PT_LOAD ||
1198     (p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) {
1199     debug("chunk %i (", i);
1200     if (p_type == PT_LOAD)
1201     debug("load");
1202     else
1203     debug("0x%08x", (int)p_type);
1204    
1205     debug(") @ 0x%llx, vaddr 0x", (long long)p_offset);
1206    
1207     if (elf64)
1208     debug("%016llx", (long long)p_vaddr);
1209     else
1210     debug("%08x", (int)p_vaddr);
1211    
1212     debug(" len=0x%llx\n", (long long)p_memsz);
1213    
1214     if (p_vaddr != p_paddr) {
1215     fprintf(stderr, "%s: vaddr != paddr. TODO: "
1216     "how to handle this? vaddr=%016llx paddr"
1217     "=%016llx\n", filename, (long long)p_vaddr,
1218     (long long)p_paddr);
1219     exit(1);
1220     }
1221    
1222     if (p_memsz < p_filesz) {
1223     fprintf(stderr, "%s: memsz < filesz. TODO: how"
1224     " to handle this? memsz=%016llx filesz="
1225     "%016llx\n", filename, (long long)p_memsz,
1226     (long long)p_filesz);
1227     exit(1);
1228     }
1229    
1230     fseek(f, p_offset, SEEK_SET);
1231     align_len = 1;
1232     if ((p_vaddr & 0xf)==0) align_len = 0x10;
1233     if ((p_vaddr & 0x3f)==0) align_len = 0x40;
1234     if ((p_vaddr & 0xff)==0) align_len = 0x100;
1235     if ((p_vaddr & 0xfff)==0) align_len = 0x1000;
1236     if ((p_vaddr & 0x3fff)==0) align_len = 0x4000;
1237     if ((p_vaddr & 0xffff)==0) align_len = 0x10000;
1238     ofs = 0; len = chunk_len = align_len;
1239     while (ofs < (int64_t)p_filesz && len==chunk_len) {
1240     unsigned char *ch = malloc(chunk_len);
1241     int i = 0;
1242    
1243     /* Switch to larger size, if possible: */
1244     if (align_len < 0x10000 &&
1245     ((p_vaddr + ofs) & 0xffff)==0) {
1246     align_len = 0x10000;
1247     len = chunk_len = align_len;
1248     free(ch);
1249     ch = malloc(chunk_len);
1250     } else if (align_len < 0x1000 &&
1251     ((p_vaddr + ofs) & 0xfff)==0) {
1252     align_len = 0x1000;
1253     len = chunk_len = align_len;
1254     free(ch);
1255     ch = malloc(chunk_len);
1256     }
1257    
1258     if (ch == NULL) {
1259     fprintf(stderr, "out of memory\n");
1260     exit(1);
1261     }
1262    
1263     len = fread(&ch[0], 1, chunk_len, f);
1264     if (ofs + len > (int64_t)p_filesz)
1265     len = p_filesz - ofs;
1266    
1267     while (i < len) {
1268     size_t len_to_copy;
1269     len_to_copy = (i + align_len) <= len?
1270     align_len : len - i;
1271     m->cpus[0]->memory_rw(m->cpus[0], mem,
1272     p_vaddr + ofs, &ch[i], len_to_copy,
1273     MEM_WRITE, NO_EXCEPTIONS);
1274     ofs += align_len;
1275     i += align_len;
1276     }
1277    
1278     free(ch);
1279     }
1280     }
1281     }
1282    
1283     /* Read the section headers to find the address of the _gp symbol: */
1284    
1285     for (i=0; i<eshnum; i++) {
1286     int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize;
1287     uint64_t sh_addr, sh_size, sh_addralign;
1288     off_t sh_offset;
1289     int n_entries; /* for reading the symbol / string tables */
1290    
1291     /* debug("section header %i at %016llx\n", i,
1292     (long long) eshoff+i*eshentsize); */
1293    
1294     fseek(f, eshoff + i * eshentsize, SEEK_SET);
1295    
1296     if (elf64) {
1297     len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f);
1298     if (len != sizeof(Elf64_Shdr)) {
1299     fprintf(stderr, "couldn't read header\n");
1300     exit(1);
1301     }
1302     unencode(sh_name, &shdr64.sh_name, Elf64_Half);
1303     unencode(sh_type, &shdr64.sh_type, Elf64_Half);
1304     unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword);
1305     unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr);
1306     unencode(sh_offset, &shdr64.sh_offset, Elf64_Off);
1307     unencode(sh_size, &shdr64.sh_size, Elf64_Xword);
1308     unencode(sh_link, &shdr64.sh_link, Elf64_Half);
1309     unencode(sh_info, &shdr64.sh_info, Elf64_Half);
1310     unencode(sh_addralign, &shdr64.sh_addralign,
1311     Elf64_Xword);
1312     unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword);
1313     } else {
1314     len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f);
1315     if (len != sizeof(Elf32_Shdr)) {
1316     fprintf(stderr, "couldn't read header\n");
1317     exit(1);
1318     }
1319     unencode(sh_name, &shdr32.sh_name, Elf32_Word);
1320     unencode(sh_type, &shdr32.sh_type, Elf32_Word);
1321     unencode(sh_flags, &shdr32.sh_flags, Elf32_Word);
1322     unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr);
1323     unencode(sh_offset, &shdr32.sh_offset, Elf32_Off);
1324     unencode(sh_size, &shdr32.sh_size, Elf32_Word);
1325     unencode(sh_link, &shdr32.sh_link, Elf32_Word);
1326     unencode(sh_info, &shdr32.sh_info, Elf32_Word);
1327     unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word);
1328     unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word);
1329     }
1330    
1331     /* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx"
1332     " sh_size=%06lx sh_entsize=%03lx\n",
1333     (long)sh_name, (long)sh_type, (long)sh_flags,
1334     (long)sh_size, (long)sh_entsize); */
1335    
1336     /* Perhaps it is bad to reuse sh_entsize like this? TODO */
1337     if (elf64)
1338     sh_entsize = sizeof(Elf64_Sym);
1339     else
1340     sh_entsize = sizeof(Elf32_Sym);
1341    
1342     if (sh_type == SHT_SYMTAB) {
1343     size_t len;
1344     n_entries = sh_size / sh_entsize;
1345    
1346     fseek(f, sh_offset, SEEK_SET);
1347    
1348     if (elf64) {
1349     if (symbols_sym64 != NULL)
1350     free(symbols_sym64);
1351     symbols_sym64 = malloc(sh_size);
1352     if (symbols_sym64 == NULL) {
1353     fprintf(stderr, "out of memory\n");
1354     exit(1);
1355     }
1356    
1357     len = fread(symbols_sym64, 1, sh_entsize *
1358     n_entries, f);
1359     } else {
1360     if (symbols_sym32 != NULL)
1361     free(symbols_sym32);
1362     symbols_sym32 = malloc(sh_size);
1363     if (symbols_sym32 == NULL) {
1364     fprintf(stderr, "out of memory\n");
1365     exit(1);
1366     }
1367    
1368     len = fread(symbols_sym32, 1,
1369     sh_entsize * n_entries, f);
1370     }
1371    
1372     if (len != sh_size) {
1373     fprintf(stderr, "could not read symbols from "
1374     "%s\n", filename);
1375     exit(1);
1376     }
1377    
1378     debug("%i symbol entries at 0x%llx\n",
1379     (int)n_entries, (long long)sh_offset);
1380    
1381     n_symbols = n_entries;
1382     }
1383    
1384     /*
1385     * TODO: This is incorrect, there may be several strtab
1386     * sections.
1387     *
1388     * For now, the simple/stupid guess that the largest string
1389     * table is the one to use seems to be good enough.
1390     */
1391    
1392     if (sh_type == SHT_STRTAB && sh_size > symbol_length) {
1393     size_t len;
1394    
1395     if (symbol_strings != NULL)
1396     free(symbol_strings);
1397    
1398     symbol_strings = malloc(sh_size + 1);
1399     if (symbol_strings == NULL) {
1400     fprintf(stderr, "out of memory\n");
1401     exit(1);
1402     }
1403    
1404     fseek(f, sh_offset, SEEK_SET);
1405     len = fread(symbol_strings, 1, sh_size, f);
1406     if (len != sh_size) {
1407     fprintf(stderr, "could not read symbols from "
1408     "%s\n", filename);
1409     exit(1);
1410     }
1411    
1412     debug("%i bytes of symbol strings at 0x%llx\n",
1413     (int)sh_size, (long long)sh_offset);
1414    
1415     symbol_strings[sh_size] = '\0';
1416     symbol_length = sh_size;
1417     }
1418     }
1419    
1420     fclose(f);
1421    
1422     /* Decode symbols: */
1423     if (symbol_strings != NULL) {
1424     for (i=0; i<n_symbols; i++) {
1425     uint64_t st_name, addr, size;
1426     int st_info;
1427    
1428     if (elf64) {
1429     sym64 = symbols_sym64[i];
1430     unencode(st_name, &sym64.st_name, Elf64_Half);
1431     unencode(st_info, &sym64.st_info, Elf_Byte);
1432     unencode(addr, &sym64.st_value, Elf64_Addr);
1433     unencode(size, &sym64.st_size, Elf64_Xword);
1434     } else {
1435     sym32 = symbols_sym32[i];
1436     unencode(st_name, &sym32.st_name, Elf32_Word);
1437     unencode(st_info, &sym64.st_info, Elf_Byte);
1438     unencode(addr, &sym32.st_value, Elf32_Word);
1439     unencode(size, &sym32.st_size, Elf32_Word);
1440     }
1441    
1442     if (size == 0)
1443     size ++;
1444    
1445 dpavlin 6 if (addr != 0) /* && ((st_info >> 4) & 0xf)
1446     >= STB_GLOBAL) */ {
1447 dpavlin 2 /* debug("symbol info=0x%02x addr=0x%016llx"
1448     " '%s'\n", st_info, (long long)addr,
1449     symbol_strings + st_name); */
1450     add_symbol_name(&m->symbol_context,
1451     addr, size, symbol_strings + st_name, 0);
1452     }
1453    
1454     if (strcmp(symbol_strings + st_name, "_gp") == 0) {
1455     debug("found _gp address: 0x");
1456     if (elf64)
1457     debug("%016llx\n", (long long)addr);
1458     else
1459     debug("%08x\n", (int)addr);
1460     *gpp = addr;
1461     }
1462     }
1463     }
1464    
1465     *entrypointp = eentry;
1466    
1467     if (encoding == ELFDATA2LSB)
1468     *byte_order = EMUL_LITTLE_ENDIAN;
1469     else
1470     *byte_order = EMUL_BIG_ENDIAN;
1471    
1472     if (elf64 && arch == ARCH_PPC) {
1473     /*
1474     * Special case for 64-bit PPC ELFs:
1475     *
1476     * The ELF starting symbol points to a ".opd" section
1477     * which contains a function descriptor:
1478     *
1479     * uint64_t start;
1480     * uint64_t toc_base;
1481     * uint64_t something_else; (?)
1482     */
1483     int res;
1484     unsigned char b[sizeof(uint64_t)];
1485     uint64_t toc_base;
1486    
1487     debug("PPC64: ");
1488    
1489     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
1490     sizeof(b), MEM_READ, NO_EXCEPTIONS);
1491     if (!res)
1492     debug(" [WARNING: could not read memory?] ");
1493    
1494     /* PPC are always big-endian: */
1495     *entrypointp = ((uint64_t)b[0] << 56) +
1496     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
1497     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
1498     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
1499     (uint64_t)b[7];
1500    
1501     res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
1502     b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
1503     if (!res)
1504     fatal(" [WARNING: could not read memory?] ");
1505    
1506     toc_base = ((uint64_t)b[0] << 56) +
1507     ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
1508     ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
1509     ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
1510     (uint64_t)b[7];
1511    
1512     debug("entrypoint 0x%016llx, toc_base 0x%016llx\n",
1513     (long long)*entrypointp, (long long)toc_base);
1514     if (tocp != NULL)
1515     *tocp = toc_base;
1516     }
1517    
1518     n_executables_loaded ++;
1519     }
1520    
1521    
1522     /*
1523     * file_n_executables_loaded():
1524     *
1525     * Returns the number of executable files loaded into emulated memory.
1526     */
1527     int file_n_executables_loaded(void)
1528     {
1529     return n_executables_loaded;
1530     }
1531    
1532    
1533     /*
1534     * file_load():
1535     *
1536     * Sense the file format of a file (ELF, a.out, ecoff), and call the
1537     * right file_load_XXX() function. If the file isn't of a recognized
1538     * binary format, assume that it contains symbol definitions.
1539     *
1540     * If the filename doesn't exist, try to treat the name as
1541     * "address:filename" and load the file as a raw binary.
1542     */
1543     void file_load(struct machine *machine, struct memory *mem,
1544     char *filename, uint64_t *entrypointp,
1545     int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp)
1546     {
1547     int iadd = 4;
1548     FILE *f;
1549     unsigned char buf[12];
1550 dpavlin 6 unsigned char buf2[2];
1551     size_t len, len2, i;
1552 dpavlin 2 off_t size;
1553    
1554     if (byte_orderp == NULL) {
1555     fprintf(stderr, "file_load(): byte_order == NULL\n");
1556     exit(1);
1557     }
1558    
1559     if (arch == ARCH_NOARCH) {
1560     fprintf(stderr, "file_load(): FATAL ERROR: no arch?\n");
1561     exit(1);
1562     }
1563    
1564     if (mem == NULL || filename == NULL) {
1565     fprintf(stderr, "file_load(): mem or filename is NULL\n");
1566     exit(1);
1567     }
1568    
1569     /* Skip configuration files: */
1570     if (filename[0] == '@')
1571     return;
1572    
1573     debug("loading %s:\n", filename);
1574     debug_indentation(iadd);
1575    
1576     f = fopen(filename, "r");
1577     if (f == NULL) {
1578     file_load_raw(machine, mem, filename, entrypointp);
1579     goto ret;
1580     }
1581    
1582     fseek(f, 0, SEEK_END);
1583     size = ftell(f);
1584     fseek(f, 0, SEEK_SET);
1585    
1586     memset(buf, 0, sizeof(buf));
1587     len = fread(buf, 1, sizeof(buf), f);
1588 dpavlin 6 fseek(f, 510, SEEK_SET);
1589     len2 = fread(buf2, 1, sizeof(buf2), f);
1590 dpavlin 2 fclose(f);
1591    
1592     if (len < (signed int)sizeof(buf)) {
1593     fprintf(stderr, "\nThis file is too small to contain "
1594     "anything useful\n");
1595     exit(1);
1596     }
1597    
1598     /* Is it an ELF? */
1599     if (buf[0] == 0x7f && buf[1]=='E' && buf[2]=='L' && buf[3]=='F') {
1600     file_load_elf(machine, mem, filename,
1601     entrypointp, arch, gpp, byte_orderp, tocp);
1602     goto ret;
1603     }
1604    
1605 dpavlin 6 /* Is it an a.out? */
1606 dpavlin 2 if (buf[0]==0x00 && buf[1]==0x8b && buf[2]==0x01 && buf[3]==0x07) {
1607 dpavlin 6 /* MIPS a.out */
1608 dpavlin 2 file_load_aout(machine, mem, filename, 0,
1609     entrypointp, arch, byte_orderp);
1610     goto ret;
1611     }
1612 dpavlin 6 if (buf[0]==0x00 && buf[1]==0x86 && buf[2]==0x01 && buf[3]==0x0b) {
1613     /* i386 a.out (old OpenBSD and NetBSD etc) */
1614     file_load_aout(machine, mem, filename, AOUT_FLAG_FROM_BEGINNING,
1615     entrypointp, arch, byte_orderp);
1616     goto ret;
1617     }
1618 dpavlin 2 if (buf[0]==0x00 && buf[2]==0x00 && buf[8]==0x7a && buf[9]==0x75) {
1619 dpavlin 6 /* DEC OSF1 on MIPS: */
1620     file_load_aout(machine, mem, filename, AOUT_FLAG_DECOSF1,
1621 dpavlin 2 entrypointp, arch, byte_orderp);
1622     goto ret;
1623     }
1624    
1625     /*
1626     * Is it an ecoff?
1627     *
1628     * TODO: What's the deal with the magic value's byte order? Sometimes
1629     * it seems to be reversed for BE when compared to LE, but not always?
1630     */
1631     if (buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB ||
1632     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL ||
1633     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB2 ||
1634     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL2 ||
1635     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEB3 ||
1636     buf[0]+256*buf[1] == ECOFF_MAGIC_MIPSEL3 ||
1637     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB ||
1638     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL ||
1639     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB2 ||
1640     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL2 ||
1641     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEB3 ||
1642     buf[1]+256*buf[0] == ECOFF_MAGIC_MIPSEL3) {
1643     file_load_ecoff(machine, mem, filename, entrypointp,
1644     arch, gpp, byte_orderp);
1645     goto ret;
1646     }
1647    
1648     /* Is it a Motorola SREC file? */
1649     if ((buf[0]=='S' && buf[1]>='0' && buf[1]<='9')) {
1650     file_load_srec(machine, mem, filename, entrypointp);
1651     goto ret;
1652     }
1653    
1654     /* gzipped files are not supported: */
1655     if (buf[0]==0x1f && buf[1]==0x8b) {
1656     fprintf(stderr, "\nYou need to gunzip the file before you"
1657     " try to use it.\n");
1658     exit(1);
1659     }
1660    
1661     if (size > 24000000) {
1662     fprintf(stderr, "\nThis file is very large (%lli bytes)\n",
1663     (long long)size);
1664     fprintf(stderr, "Are you sure it is a kernel and not a disk "
1665 dpavlin 6 "image? (Use the -d option.)\n");
1666 dpavlin 2 exit(1);
1667     }
1668    
1669 dpavlin 4 if (size == 1474560)
1670     fprintf(stderr, "Hm... this file is the size of a 1.44 MB "
1671     "floppy image. Maybe you forgot the\n-d switch?\n");
1672    
1673 dpavlin 2 /*
1674     * Last resort: symbol definitions from nm (or nm -S):
1675     *
1676     * If the buf contains typical 'binary' characters, then print
1677     * an error message and quit instead of assuming that it is a
1678     * symbol file.
1679     */
1680     for (i=0; i<(signed)sizeof(buf); i++)
1681     if (buf[i] < 32 && buf[i] != '\t' &&
1682     buf[i] != '\n' && buf[i] != '\r' &&
1683     buf[i] != '\f') {
1684     fprintf(stderr, "\nThe file format of '%s' is "
1685     "unknown.\n\n ", filename);
1686     for (i=0; i<(signed)sizeof(buf); i++)
1687     fprintf(stderr, " %02x", buf[i]);
1688 dpavlin 6
1689     if (len2 == 2 && buf2[0] == 0x55 && buf2[1] == 0xaa)
1690     fprintf(stderr, "\n\nIt has a PC-style "
1691     "bootsector marker.");
1692    
1693 dpavlin 2 fprintf(stderr, "\n\nPossible explanations:\n\n"
1694     " o) If this is a disk image, you forgot '-d' "
1695     "on the command line.\n"
1696     " o) This is an unsupported binary format.\n\n");
1697     exit(1);
1698     }
1699    
1700     symbol_readfile(&machine->symbol_context, filename);
1701    
1702     ret:
1703     debug_indentation(-iadd);
1704     }
1705    

  ViewVC Help
Powered by ViewVC 1.1.26