annotate keiko/loader.c @ 0:bfdcc3820b32

Basis
author Mike Spivey <mike@cs.ox.ac.uk>
date Thu, 05 Oct 2017 08:04:15 +0100
parents
children
rev   line source
0
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
1 /*
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
2 * loader.c
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
3 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
4 * This file is part of the Oxford Oberon-2 compiler
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
5 * Copyright (c) 2006--2016 J. M. Spivey
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
6 * All rights reserved
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
7 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
8 * Redistribution and use in source and binary forms, with or without
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
9 * modification, are permitted provided that the following conditions are met:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
10 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
11 * 1. Redistributions of source code must retain the above copyright notice,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
12 * this list of conditions and the following disclaimer.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
14 * this list of conditions and the following disclaimer in the documentation
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
15 * and/or other materials provided with the distribution.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
16 * 3. The name of the author may not be used to endorse or promote products
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
17 * derived from this software without specific prior written permission.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
18 *
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
29 */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
30
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
31 #include "obx.h"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
32 #include "keiko.h"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
33 #include "exec.h"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
34
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
35 static FILE *binfp;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
36
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
37 static int binread(void *buf, int size) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
38 return fread(buf, 1, size, binfp);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
39 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
40
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
41 static int bingetc(void) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
42 char buf[1];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
43 if (binread(buf, 1) == 0) return EOF;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
44 return buf[0];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
45 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
46
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
47 /* read_string -- input a null-terminated string, allocate space dynamically */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
48 static char *read_string() {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
49 int n = 0;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
50 int c;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
51 char *p;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
52 char buf[256];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
53
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
54 do {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
55 c = bingetc();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
56 if (c == EOF) panic("*unexpected EOF");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
57 buf[n++] = c;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
58 } while (c != '\0');
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
59
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
60 p = (char *) scratch_alloc(n);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
61 strcpy(p, buf);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
62 return p;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
63 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
64
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
65 /* get_int -- get a 4-byte value in portable byte order */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
66 static int get_int(uchar *p) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
67 return (p[3]<<24) + (p[2]<<16) + (p[1]<<8) + p[0];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
68 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
69
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
70
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
71 /* read_int -- input a 4-byte value in portable byte order */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
72 static int read_int() {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
73 uchar buf[4];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
74 binread(buf, 4);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
75 return get_int(buf);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
76 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
77
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
78 /* Here is the still centre of the whirling vortex that is byte-order
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
79 independence. The compiler output, Kieko assembly language, is
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
80 plain text. The assembler/linker translates this into a byte-order
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
81 independent file of object code.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
82
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
83 The bytecode in this file contains one and two byte embedded
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
84 constants that are in little-endian order, and the bytecode
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
85 interpreter puts the bytes together where necessary, respecting the
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
86 little-endian order in the code even on a big-endian machine. (It
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
87 has to address bytecode one byte a time anyway, because of
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
88 alignment restrictions.)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
89
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
90 The data segment in the object code consists of 4-byte words, and
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
91 these are relocated when the program is loaded. Some of these
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
92 words contain character data for string constants, and they require
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
93 no relocation. Some words contain integer or floating-point
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
94 constants, and they are relocated by swapping the byte order if
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
95 necessary. Finally, some words contain addresses in the data or
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
96 code segment, and they are relocated by swapping the byte order as
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
97 needed, and adding the base address of the segment in question.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
98 Thus in the running program, both the memory and the evaluation
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
99 stack contain only values in native byte order -- and all pointers
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
100 are represented as absolute addresses, enabling the program to live
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
101 in harmony with a conservative garbage collector.
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
102
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
103 One final twist: double-precision values are always stored as two
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
104 words, with each word in native byte order, but with the less
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
105 significant word first, even on a big-endian machine. This is ok,
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
106 because these values are always loaded and stored one word at a
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
107 time, and assembled into native order immediately before doing
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
108 arithmetic. */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
109
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
110 #define REL_BLOCK 1024
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
111
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
112 /* relocate -- read relocation data */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
113 static void relocate(int size) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
114 unsigned reloc[REL_BLOCK];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
115 int n;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
116
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
117 for (int base = 0; base < size; base += n) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
118 n = min(size - base, REL_BLOCK * CODES_PER_WORD * WORD_SIZE);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
119 int nwords = (n/WORD_SIZE+CODES_PER_WORD-1)/CODES_PER_WORD;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
120 binread(reloc, nwords * sizeof(unsigned));
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
121
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
122 for (int i = 0; i < n; i += WORD_SIZE) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
123 int rbits = reloc_bits(reloc, i/WORD_SIZE);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
124
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
125 #ifdef DEBUG
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
126 if (dflag >= 2)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
127 printf("Reloc %d %d\n", base+i, rbits);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
128 #endif
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
129
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
130 int m = get_int(&dmem[base+i]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
131 value *p = (value *) &dmem[base+i];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
132
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
133 switch (rbits) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
134 case R_WORD:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
135 (*p).i = m;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
136 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
137 case R_DATA:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
138 (*p).a = address(dmem + m);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
139 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
140 case R_CODE:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
141 (*p).a = address(imem + m);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
142 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
143 case R_SUBR:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
144 switch (m) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
145 case INTERP: (*p).a = interpreter; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
146 case DLTRAP: (*p).a = dyntrap; break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
147 default:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
148 panic("bad subr code");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
149 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
150 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
151 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
152 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
153 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
154 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
155
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
156 /* read_symbols -- read symbol table */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
157 static void read_symbols(int dseg) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
158 uchar *addr;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
159 int chksum, nlines;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
160 int nm = 0, np = 0;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
161 #ifdef DEBUG
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
162 const char *kname;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
163 #define debug_kind(n) kname = n
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
164 #else
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
165 #define debug_kind(n)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
166 #endif
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
167
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
168 modtab = (module *) scratch_alloc(nmods * sizeof(module));
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
169 proctab = (proc *) scratch_alloc(nprocs * sizeof(proc));
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
170
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
171 for (int i = 0; i < nsyms; i++) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
172 int kind = read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
173 char *name = read_string();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
174
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
175 switch (kind) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
176 case X_MODULE:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
177 debug_kind("Module");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
178 addr = dmem + read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
179 chksum = read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
180 nlines = read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
181 modtab[nm++] = make_module(name, addr, chksum, nlines);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
182 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
183
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
184 case X_PROC:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
185 debug_kind("Proc");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
186 addr = dmem + read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
187 proctab[np++] = make_proc(name, addr);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
188 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
189
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
190 case X_DATA:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
191 debug_kind("Data");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
192 addr = dmem + read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
193 make_symbol("data", name, addr);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
194 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
195
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
196 case X_LINE:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
197 debug_kind("Line");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
198 addr = imem + read_int();
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
199 make_symbol("line", name, addr);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
200 break;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
201
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
202 default:
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
203 debug_kind("Unknown");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
204 addr = NULL;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
205 panic("*bad symbol %s", name);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
206 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
207
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
208 #ifdef DEBUG
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
209 if (dflag >= 1) printf("%s %s = %p\n", kname, name, addr);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
210 #endif
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
211 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
212
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
213 if (nm != nmods || np != nprocs)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
214 panic("*symbol counts don't match (mods %d/%d, procs %d/%d)\n",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
215 nm, nmods, np, nprocs);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
216
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
217 /* Calculate module lengths */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
218 addr = dmem + dseg;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
219 for (int i = nmods-1; i >= 0; i--) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
220 modtab[i]->m_length = addr - modtab[i]->m_addr;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
221 addr = modtab[i]->m_addr;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
222 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
223 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
224
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
225 /* load_file -- load a file of object code */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
226 void load_file(FILE *bfp) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
227 /* Get trailer */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
228 trailer t;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
229 fseek(bfp, - (long) sizeof(trailer), SEEK_END);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
230 int nread = fread(&t, 1, sizeof(trailer), bfp);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
231 if (nread != sizeof(trailer)) panic("couldn't read trailer");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
232
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
233 /* Check magic numbers */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
234 if (nread < sizeof(trailer))
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
235 panic("couldn't read trailer");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
236 if (strncmp((char *) t.magic, MAGIC, 4) != 0)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
237 panic("bad magic number\n%s",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
238 "[The program you are running is not a valid"
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
239 " Oberon bytecode file]");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
240 if (get_int(t.sig) != SIG)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
241 panic("bad signature %#0.8x\n%s\n%s", get_int(t.sig),
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
242 "[Although this appears to be an Oberon bytecode file,",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
243 " it needs a different version of the runtime system]");
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
244
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
245 /* Decode the other data */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
246 int seglen[NSEGS];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
247 for (int i = 0; i < NSEGS; i++)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
248 seglen[i] = get_int(t.segment[i]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
249
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
250 code_size = seglen[S_CODE];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
251 stack_size = seglen[S_STACK];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
252
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
253 nmods = get_int(t.nmods); nprocs = get_int(t.nprocs);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
254 nsyms = get_int(t.nsyms);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
255 int start = get_int(t.start);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
256
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
257 #ifdef DEBUG
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
258 if (dflag >= 1) {
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
259 printf("csize = %d, dsize = %d, bss = %d, stk = %d\n",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
260 seglen[S_CODE], seglen[S_DATA],
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
261 seglen[S_BSS], seglen[S_STACK]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
262 printf("nmods = %d, nprocs = %d, nsyms = %d\n",
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
263 nmods, nprocs, nsyms);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
264 }
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
265 #endif
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
266
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
267 fseek(bfp, start, SEEK_END);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
268 binfp = bfp;
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
269
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
270 /* Load the code */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
271 imem = (uchar *) scratch_alloc(seglen[S_CODE]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
272 binread(imem, seglen[S_CODE]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
273
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
274 /* Load and relocate the data */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
275 dmem = (uchar *) scratch_alloc(seglen[S_DATA]+seglen[S_BSS]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
276 binread(dmem, seglen[S_DATA]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
277 relocate(seglen[S_DATA]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
278 memset(dmem+seglen[S_DATA], 0, seglen[S_BSS]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
279
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
280 /* Allocate stack */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
281 stack = (uchar *) scratch_alloc(stack_size);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
282
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
283 /* Save the entry point, pointer map and library path */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
284 entry = (value *) &dmem[get_int(t.entry)];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
285 gcmap = (value *) &dmem[get_int(t.gcmap)];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
286 if (get_int(t.libdir) != 0)
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
287 libpath = (char *) &dmem[get_int(t.libdir)];
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
288
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
289 /* Read the symbols */
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
290 if (nsyms > 0) read_symbols(seglen[S_DATA]);
Mike Spivey <mike@cs.ox.ac.uk>
parents:
diff changeset
291 }