1
2
3
4 package joeq.Bootstrap;
5
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.Iterator;
10 import java.util.LinkedList;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14 import java.io.IOException;
15 import java.io.PrintStream;
16 import java.lang.reflect.Array;
17 import joeq.Allocator.CodeAllocator;
18 import joeq.Allocator.ObjectLayout;
19 import joeq.Assembler.Code2CodeReference;
20 import joeq.Assembler.Code2HeapReference;
21 import joeq.Assembler.DirectBindCall;
22 import joeq.Assembler.ExternalReference;
23 import joeq.Assembler.Heap2CodeReference;
24 import joeq.Assembler.Heap2HeapReference;
25 import joeq.Assembler.Reloc;
26 import joeq.Class.PrimordialClassLoader;
27 import joeq.Class.jq_Array;
28 import joeq.Class.jq_Class;
29 import joeq.Class.jq_CompiledCode;
30 import joeq.Class.jq_InstanceField;
31 import joeq.Class.jq_Member;
32 import joeq.Class.jq_Method;
33 import joeq.Class.jq_Primitive;
34 import joeq.Class.jq_Reference;
35 import joeq.Class.jq_StaticField;
36 import joeq.Class.jq_StaticMethod;
37 import joeq.Class.jq_Type;
38 import joeq.Linker.ELF.ELF;
39 import joeq.Linker.ELF.ELFConstants;
40 import joeq.Linker.ELF.ELFOutput;
41 import joeq.Linker.ELF.RelocEntry;
42 import joeq.Linker.ELF.Section;
43 import joeq.Linker.ELF.SymbolTableEntry;
44 import joeq.Memory.Address;
45 import joeq.Memory.CodeAddress;
46 import joeq.Memory.HeapAddress;
47 import joeq.Runtime.ExceptionDeliverer;
48 import joeq.Runtime.Reflection;
49 import joeq.Runtime.SystemInterface;
50 import joeq.Runtime.Unsafe;
51 import joeq.Scheduler.jq_NativeThread;
52 import jwutil.collections.IdentityHashCodeWrapper;
53 import jwutil.io.ExtendedDataOutput;
54 import jwutil.strings.Strings;
55 import jwutil.util.Assert;
56
57 /***
58 * BootImage
59 *
60 * @author John Whaley <jwhaley@alum.mit.edu>
61 * @version $Id: MultiPassBootImage.java 2475 2006-12-24 09:44:50Z joewhaley $
62 */
63 public class MultiPassBootImage implements ELFConstants {
64
65 public static
66 public static final PrintStream out = System.out;
67
68 public static final MultiPassBootImage DEFAULT = new MultiPassBootImage(BootstrapCodeAllocator.DEFAULT);
69
70 private final Map
71 private final ArrayList
72 private int heapCurrent;
73 private final int startAddress;
74
75 private BootstrapCodeAllocator bca;
76 private List data_relocs;
77
78 public Set boot_types;
79
80 public MultiPassBootImage(BootstrapCodeAllocator bca, int initialCapacity, float loadFactor) {
81 hash = new HashMap(initialCapacity, loadFactor);
82 entries = new ArrayList(initialCapacity);
83 this.bca = bca;
84 this.heapCurrent = this.startAddress = 0;
85 this.data_relocs = new LinkedList();
86 }
87 public MultiPassBootImage(BootstrapCodeAllocator bca, int initialCapacity) {
88 hash = new HashMap(initialCapacity);
89 entries = new ArrayList(initialCapacity);
90 this.bca = bca;
91 this.heapCurrent = this.startAddress = 0;
92 this.data_relocs = new LinkedList();
93 }
94 public MultiPassBootImage(BootstrapCodeAllocator bca) {
95 hash = new HashMap();
96 entries = new ArrayList();
97 this.bca = bca;
98 this.heapCurrent = this.startAddress = 0;
99 this.data_relocs = new LinkedList();
100 }
101
102 public final HeapAddress addressOf(Object o) {
103 Assert._assert(!(o instanceof BootstrapAddress));
104 return getOrAllocateObject(o);
105 }
106
107 public final void addCodeReloc(HeapAddress addr, CodeAddress target) {
108 Heap2CodeReference r = new Heap2CodeReference(addr, target);
109 data_relocs.add(r);
110 }
111 public final void addDataReloc(HeapAddress addr, HeapAddress target) {
112 Heap2HeapReference r = new Heap2HeapReference(addr, target);
113 data_relocs.add(r);
114 }
115
116 public final void invokeclinit(jq_Class c) {
117
118 String cname = c.getName().toString();
119 try {
120 Class.forName(cname);
121 } catch (ClassNotFoundException x) {
122
123 System.err.println("ERROR: bootstrapping jvm cannot find class "+cname);
124 Assert.UNREACHABLE();
125 }
126 }
127
128 private boolean alloc_enabled = false;
129
130 public void enableAllocations() { alloc_enabled = true; }
131 public void disableAllocations() { alloc_enabled = false; }
132
133 public HeapAddress getOrAllocateObject(Object o) {
134 if (o == null) return HeapAddress.getNull();
135
136 IdentityHashCodeWrapper k = IdentityHashCodeWrapper.create(o);
137 Entry e = (Entry)hash.get(k);
138 if (e != null) return e.getAddress();
139
140 Assert._assert(alloc_enabled);
141 Class objType = o.getClass();
142 try {
143 jq_Reference type = (jq_Reference)Reflection.getJQType(objType);
144 if (!boot_types.contains(type)) {
145 System.err.println("--> class "+type+" is not in the set of boot types!");
146
147 return HeapAddress.getNull();
148 }
149 int addr;
150 int size;
151 if (type.isArrayType()) {
152 addr = heapCurrent + ObjectLayout.ARRAY_HEADER_SIZE;
153 size = ((jq_Array)type).getInstanceSize(Array.getLength(o));
154 size = (size+3) & ~3;
155 if (TRACE)
156 out.println("Allocating entry "+entries.size()+": "+objType+" length "+Array.getLength(o)+" size "+size+" "+Strings.hex(System.identityHashCode(o))+" at "+Strings.hex(addr));
157 } else {
158 Assert._assert(type.isClassType());
159 addr = heapCurrent + ObjectLayout.OBJ_HEADER_SIZE;
160 size = ((jq_Class)type).getInstanceSize();
161 if (TRACE)
162 out.println("Allocating entry "+entries.size()+": "+objType+" size "+size+" "+Strings.hex(System.identityHashCode(o))+" at "+Strings.hex(addr)+((o instanceof jq_Type)?": "+o:""));
163 }
164 heapCurrent += size;
165 BootstrapHeapAddress a = new BootstrapHeapAddress(addr);
166 e = Entry.create(o, a);
167 hash.put(k, e);
168 entries.add(e);
169 return a;
170 } catch (Exception ie) {
171 ie.printStackTrace();
172 HashSet visited = new HashSet();
173 UnknownObjectException x = new UnknownObjectException(o);
174 boolean found = findReferencePath(o, x, visited);
175 if (found) {
176 System.out.println(x);
177 }
178 return HeapAddress.getNull();
179 }
180 }
181
182 public static boolean IGNORE_UNKNOWN_OBJECTS = false;
183
184 public HeapAddress getAddressOf(Object o) {
185 Assert._assert(!(o instanceof BootstrapAddress));
186 if (o == null) return HeapAddress.getNull();
187 IdentityHashCodeWrapper k = IdentityHashCodeWrapper.create(o);
188 Entry e = (Entry)hash.get(k);
189 if (e == null) {
190 System.err.println("Unknown object of type: "+o.getClass()+" address: "+Strings.hex(System.identityHashCode(o))+" value: "+o);
191 if (IGNORE_UNKNOWN_OBJECTS) return HeapAddress.getNull();
192 throw new UnknownObjectException(o);
193 }
194 Class objType = o.getClass();
195 jq_Reference type = (jq_Reference)Reflection.getJQType(objType);
196 Assert._assert(type.isClsInitialized(), type.toString());
197 return e.getAddress();
198 }
199
200 public Object getObject(int i) {
201 Entry e = (Entry)entries.get(i);
202 return e.getObject();
203 }
204
205 public void addStaticFieldReloc(jq_StaticField f) {
206 jq_Type ftype = f.getType();
207 if (f.isCodeAddressType()) {
208 CodeAddress addr = (CodeAddress)Reflection.getstatic_P(f);
209 if (addr != null && !addr.isNull()) {
210 if (TRACE)
211 out.println("Adding code reloc for "+f+": "+f.getAddress().stringRep()+" "+addr.stringRep());
212 addCodeReloc(f.getAddress(), addr);
213 }
214 } else if (f.isHeapAddressType()) {
215 HeapAddress addr = (HeapAddress)Reflection.getstatic_P(f);
216 if (addr != null && !addr.isNull()) {
217 if (TRACE)
218 out.println("Adding data reloc for "+f+": "+f.getAddress().stringRep()+" "+addr.stringRep());
219 addDataReloc(f.getAddress(), addr);
220 }
221 } else if (ftype.isReferenceType()) {
222 Object val = Reflection.getstatic_A(f);
223 if (val != null) {
224 if (val instanceof BootstrapAddress) {
225 Assert.UNREACHABLE("Error: "+f+" contains "+((Address)val).stringRep());
226 }
227 HeapAddress addr = HeapAddress.addressOf(val);
228 if (TRACE) out.println("Adding data reloc for "+f+": "+f.getAddress().stringRep()+" "+addr.stringRep());
229 addDataReloc(f.getAddress(), addr);
230 }
231 }
232 }
233
234 public void initStaticField(jq_StaticField f) {
235 jq_Class k = f.getDeclaringClass();
236 jq_Type ftype = f.getType();
237 if (ftype.isPrimitiveType()) {
238 if (ftype == jq_Primitive.INT) {
239 int v = Reflection.getstatic_I(f);
240 k.setStaticData(f, v);
241 } else if (ftype == jq_Primitive.FLOAT) {
242 float v = Reflection.getstatic_F(f);
243 k.setStaticData(f, v);
244 } else if (ftype == jq_Primitive.LONG) {
245 long v = Reflection.getstatic_L(f);
246 k.setStaticData(f, v);
247 } else if (ftype == jq_Primitive.DOUBLE) {
248 double v = Reflection.getstatic_D(f);
249 k.setStaticData(f, v);
250 } else if (ftype == jq_Primitive.BOOLEAN) {
251 int v = Reflection.getstatic_Z(f)?1:0;
252 k.setStaticData(f, v);
253 } else if (ftype == jq_Primitive.BYTE) {
254 byte v = Reflection.getstatic_B(f);
255 k.setStaticData(f, v);
256 } else if (ftype == jq_Primitive.SHORT) {
257 short v = Reflection.getstatic_S(f);
258 k.setStaticData(f, v);
259 } else if (ftype == jq_Primitive.CHAR) {
260 char v = Reflection.getstatic_C(f);
261 k.setStaticData(f, v);
262 } else
263 Assert.UNREACHABLE();
264 } else if (ftype.isAddressType()) {
265 Address addr = Reflection.getstatic_P(f);
266 if (addr == null) addr = HeapAddress.getNull();
267 if (TRACE) out.println("Initializing static field "+f+" to "+addr.stringRep());
268 k.setStaticData(f, addr);
269 } else {
270 Object val = Reflection.getstatic_A(f);
271 HeapAddress addr = HeapAddress.addressOf(val);
272 if (TRACE) out.println("Initializing static field "+f+" to "+addr.stringRep());
273 k.setStaticData(f, addr);
274 }
275 }
276
277 public int numOfEntries() { return entries.size(); }
278
279 public static int UPDATE_PERIOD = 10000;
280
281 public void find_reachable(int i) {
282 for (; i<entries.size(); ++i) {
283 if ((i % UPDATE_PERIOD) == 0) {
284 out.print("Scanning: "+i+"/"+entries.size()+" objects, memory used: "+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())+" \r");
285 }
286 Entry e = (Entry)entries.get(i);
287 Object o = e.getObject();
288 if (o == null) continue;
289 HeapAddress addr = e.getAddress();
290 Assert._assert(!addr.isNull());
291 Class objType = o.getClass();
292 jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
293 if (TRACE)
294 out.println("Entry "+i+": "+objType+" "+Strings.hex(System.identityHashCode(o)));
295 addDataReloc((HeapAddress)addr.offset(ObjectLayout.VTABLE_OFFSET), getOrAllocateObject(jqType));
296 if (jqType.isArrayType()) {
297 jq_Type elemType = ((jq_Array)jqType).getElementType();
298 if (elemType.isAddressType()) {
299
300 } else if (elemType.isReferenceType()) {
301 int length = Array.getLength(o);
302 Object[] v = (Object[])o;
303 for (int k=0; k<length; ++k) {
304 Object o2 = Reflection.arrayload_A(v, k);
305 if (o2 != null) {
306 addDataReloc((HeapAddress)addr.offset(k*HeapAddress.size()), getOrAllocateObject(o2));
307 }
308 }
309 }
310 } else {
311 Assert._assert(jqType.isClassType());
312 jq_Class clazz = (jq_Class)jqType;
313 jq_InstanceField[] fields = clazz.getInstanceFields();
314 for (int k=0; k<fields.length; ++k) {
315 jq_InstanceField f = fields[k];
316 jq_Type ftype = f.getType();
317 if (f.isCodeAddressType()) {
318 CodeAddress val = (CodeAddress)Reflection.getfield_P(o, f);
319 if (val != null && !val.isNull())
320 addCodeReloc((HeapAddress)addr.offset(f.getOffset()), val);
321 } else if (f.isHeapAddressType()) {
322 HeapAddress val = (HeapAddress)Reflection.getfield_P(o, f);
323 if (val != null && !val.isNull())
324 addDataReloc((HeapAddress)addr.offset(f.getOffset()), val);
325 } else if (f.isStackAddressType()) {
326
327 } else if (f.getType().isAddressType()) {
328 Assert.UNREACHABLE("Field has untyped Address type: "+f);
329 } else if (ftype.isReferenceType()) {
330 Object val = Reflection.getfield_A(o, f);
331 if (val != null) {
332 addDataReloc((HeapAddress)addr.offset(f.getOffset()), getOrAllocateObject(val));
333 }
334 }
335 }
336 }
337 }
338 }
339
340 public int size() { return heapCurrent-startAddress; }
341
342 private static class Entry {
343 private Object o;
344 private HeapAddress address;
345 private Entry(Object o, HeapAddress address) { this.o = o; this.address = address; }
346 static Entry create(Object o, HeapAddress address) {
347 Assert._assert(o != null);
348 return new Entry(o, address);
349 }
350 Object getObject() { return o; }
351 HeapAddress getAddress() { return address; }
352 }
353
354 public static final char F_RELFLG = (char)0x0001;
355 public static final char F_EXEC = (char)0x0002;
356 public static final char F_LNNO = (char)0x0004;
357 public static final char F_LSYMS = (char)0x0008;
358 public static final char F_AR32WR = (char)0x0100;
359
360 public void dumpFILHDR(ExtendedDataOutput out, int symptr, int nsyms)
361 throws IOException {
362
363 out.writeUShort((char)0x014c);
364 out.writeUShort((char)2);
365 long ms = System.currentTimeMillis();
366 int s = (int)(ms/1000);
367 out.writeUInt(s);
368 out.writeUInt(symptr);
369 out.writeUInt(nsyms);
370 out.writeUShort((char)0);
371 out.writeUShort((char)(F_LNNO | F_LSYMS | F_AR32WR));
372 }
373
374 public static final int STYP_TEXT = 0x00000020;
375 public static final int STYP_DATA = 0x00000040;
376 public static final int STYP_BSS = 0x00000080;
377 public static final int STYP_RELOV = 0x01000000;
378 public static final int STYP_EXEC = 0x20000000;
379 public static final int STYP_READ = 0x40000000;
380 public static final int STYP_WRITE = 0x80000000;
381
382 public void dumpTEXTSCNHDR(ExtendedDataOutput out, int size, int nreloc)
383 throws IOException {
384
385 write_bytes(out, ".text", 8);
386 out.writeUInt(0);
387 out.writeUInt(0);
388 out.writeUInt(size);
389 out.writeUInt(20+40+40);
390 out.writeUInt(20+40+40+size);
391 out.writeUInt(0);
392 if (nreloc > 65535)
393 out.writeUShort((char)0xffff);
394 else
395 out.writeUShort((char)nreloc);
396 out.writeUShort((char)0);
397 if (nreloc > 65535)
398 out.writeUInt(STYP_TEXT | STYP_READ | STYP_WRITE | STYP_RELOV);
399 else
400 out.writeUInt(STYP_TEXT | STYP_READ | STYP_WRITE);
401 }
402
403 public void dumpDATASCNHDR(ExtendedDataOutput out, int scnptr, int size, int nreloc)
404 throws IOException {
405
406 write_bytes(out, ".data", 8);
407 out.writeUInt(0);
408 out.writeUInt(0);
409 out.writeUInt(size);
410 out.writeUInt(scnptr);
411 out.writeUInt(scnptr+size);
412 out.writeUInt(0);
413 if (nreloc > 65535)
414 out.writeUShort((char)0xffff);
415 else
416 out.writeUShort((char)nreloc);
417 out.writeUShort((char)0);
418 if (nreloc > 65535)
419 out.writeUInt(STYP_DATA | STYP_READ | STYP_WRITE | STYP_RELOV);
420 else
421 out.writeUInt(STYP_DATA | STYP_READ | STYP_WRITE);
422 }
423
424 public static final char RELOC_ADDR32 = (char)0x0006;
425 public static final char RELOC_REL32 = (char)0x0014;
426
427 public void dumpLINENO(ExtendedDataOutput out, int addr, char lnno)
428 throws IOException {
429 out.writeUInt(addr);
430 out.writeUShort(lnno);
431 }
432
433 public static final short N_UNDEF = 0;
434 public static final short N_ABS = -1;
435 public static final short N_DEBUG = -2;
436
437 public static final char T_NULL = 0x00;
438 public static final char T_VOID = 0x01;
439 public static final char T_CHAR = 0x02;
440 public static final char T_SHORT = 0x03;
441 public static final char T_INT = 0x04;
442 public static final char T_LONG = 0x05;
443 public static final char T_FLOAT = 0x06;
444 public static final char T_DOUBLE = 0x07;
445 public static final char T_STRUCT = 0x08;
446 public static final char T_UNION = 0x09;
447 public static final char T_ENUM = 0x0A;
448 public static final char T_MOE = 0x0B;
449 public static final char T_UCHAR = 0x0C;
450 public static final char T_USHORT = 0x0D;
451 public static final char T_UINT = 0x0E;
452 public static final char T_ULONG = 0x0F;
453 public static final char T_LNGDBL = 0x10;
454
455 public static final char DT_NON = 0x0000;
456 public static final char DT_PTR = 0x0100;
457 public static final char DT_FCN = 0x0200;
458 public static final char DT_ARY = 0x0300;
459
460 public static final byte C_NULL = 0;
461 public static final byte C_AUTO = 1;
462 public static final byte C_EXT = 2;
463 public static final byte C_STAT = 3;
464 public static final byte C_REG = 4;
465 public static final byte C_EXTDEF = 5;
466 public static final byte C_LABEL = 6;
467 public static final byte C_ULABEL = 7;
468 public static final byte C_MOS = 8;
469 public static final byte C_ARG = 9;
470 public static final byte C_STRTAG = 10;
471 public static final byte C_MOU = 11;
472 public static final byte C_UNTAG = 12;
473 public static final byte C_TPDEF = 13;
474 public static final byte C_USTATIC = 14;
475 public static final byte C_ENTAG = 15;
476 public static final byte C_MOE = 16;
477 public static final byte C_REGPARM = 17;
478 public static final byte C_FIELD = 18;
479 public static final byte C_AUTOARG = 19;
480 public static final byte C_LASTENT = 20;
481 public static final byte C_BLOCK = 100;
482 public static final byte C_FCN = 101;
483 public static final byte C_EOS = 102;
484 public static final byte C_FILE = 103;
485 public static final byte C_SECTION = 104;
486 public static final byte C_WEAKEXT = 105;
487 public static final byte C_EFCN = -1;
488
489 public void dumpSECTIONSYMENTs(ExtendedDataOutput out)
490 throws IOException {
491 write_bytes(out, ".text", 8);
492 out.writeUInt(0);
493 out.writeShort((short)1);
494 out.writeUShort((char)0);
495 out.writeUByte(C_STAT);
496 out.writeUByte(0);
497
498 write_bytes(out, ".data", 8);
499 out.writeUInt(0);
500 out.writeShort((short)2);
501 out.writeUShort((char)0);
502 out.writeUByte(C_STAT);
503 out.writeUByte(0);
504 }
505
506 public static boolean USE_MICROSOFT_STYLE_MUNGE = true;
507
508 public static final int NUM_OF_EXTERNAL_SYMS = 9;
509 public void dumpEXTSYMENTs(ExtendedDataOutput out, jq_StaticMethod rootm)
510 throws IOException {
511
512 String s;
513 if (USE_MICROSOFT_STYLE_MUNGE) s = "_entry@0";
514 else s = "entry";
515 write_bytes(out, s, 8);
516 CodeAddress addr = rootm.getDefaultCompiledVersion().getEntrypoint();
517 out.writeUInt(addr.to32BitValue());
518 out.writeShort((short)1);
519 out.writeUShort((char)DT_FCN);
520 out.writeUByte(C_EXT);
521 out.writeUByte(0);
522
523 out.writeUInt(0);
524 if (USE_MICROSOFT_STYLE_MUNGE) s = "_trap_handler@4";
525 else s = "trap_handler";
526 int idx = alloc_string(s);
527 out.writeUInt(idx);
528 addr = ExceptionDeliverer._trap_handler.getDefaultCompiledVersion().getEntrypoint();
529 out.writeUInt(addr.to32BitValue());
530 out.writeShort((short)1);
531 out.writeUShort((char)DT_FCN);
532 out.writeUByte(C_EXT);
533 out.writeUByte(0);
534
535 out.writeUInt(0);
536 if (USE_MICROSOFT_STYLE_MUNGE) s = "_debug_trap_handler@4";
537 else s = "debug_trap_handler";
538 idx = alloc_string(s);
539 out.writeUInt(idx);
540 addr = ExceptionDeliverer._debug_trap_handler.getDefaultCompiledVersion().getEntrypoint();
541 out.writeUInt(addr.to32BitValue());
542 out.writeShort((short)1);
543 out.writeUShort((char)DT_FCN);
544 out.writeUByte(C_EXT);
545 out.writeUByte(0);
546
547 out.writeUInt(0);
548 if (USE_MICROSOFT_STYLE_MUNGE) s = "_threadSwitch@4";
549 else s = "threadSwitch";
550 idx = alloc_string(s);
551 out.writeUInt(idx);
552 addr = jq_NativeThread._threadSwitch.getDefaultCompiledVersion().getEntrypoint();
553 out.writeUInt(addr.to32BitValue());
554 out.writeShort((short)1);
555 out.writeUShort((char)DT_FCN);
556 out.writeUByte(C_EXT);
557 out.writeUByte(0);
558
559 out.writeUInt(0);
560 if (USE_MICROSOFT_STYLE_MUNGE) s = "_ctrl_break_handler@0";
561 else s = "ctrl_break_handler";
562 idx = alloc_string(s);
563 out.writeUInt(idx);
564 addr = jq_NativeThread._ctrl_break_handler.getDefaultCompiledVersion().getEntrypoint();
565 out.writeUInt(addr.to32BitValue());
566 out.writeShort((short)1);
567 out.writeUShort((char)DT_FCN);
568 out.writeUByte(C_EXT);
569 out.writeUByte(0);
570
571 out.writeUInt(0);
572 if (USE_MICROSOFT_STYLE_MUNGE) s = "_joeq_code_startaddress";
573 else s = "joeq_code_startaddress";
574 idx = alloc_string(s);
575 out.writeUInt(idx);
576 out.writeUInt(0);
577 out.writeShort((short)1);
578 out.writeUShort((char)(DT_PTR | T_VOID));
579 out.writeUByte(C_EXT);
580 out.writeUByte(0);
581
582 out.writeUInt(0);
583 if (USE_MICROSOFT_STYLE_MUNGE) s = "_joeq_code_endaddress";
584 else s = "joeq_code_endaddress";
585 idx = alloc_string(s);
586 out.writeUInt(idx);
587 out.writeUInt(bca.size());
588 out.writeShort((short)1);
589 out.writeUShort((char)(DT_PTR | T_VOID));
590 out.writeUByte(C_EXT);
591 out.writeUByte(0);
592
593 out.writeUInt(0);
594 if (USE_MICROSOFT_STYLE_MUNGE) s = "_joeq_data_startaddress";
595 else s = "joeq_data_startaddress";
596 idx = alloc_string(s);
597 out.writeUInt(idx);
598 out.writeUInt(0);
599 out.writeShort((short)2);
600 out.writeUShort((char)(DT_PTR | T_VOID));
601 out.writeUByte(C_EXT);
602 out.writeUByte(0);
603
604 out.writeUInt(0);
605 if (USE_MICROSOFT_STYLE_MUNGE) s = "_joeq_data_endaddress";
606 else s = "joeq_data_endaddress";
607 idx = alloc_string(s);
608 out.writeUInt(idx);
609 out.writeUInt(heapCurrent);
610 out.writeShort((short)2);
611 out.writeUShort((char)(DT_PTR | T_VOID));
612 out.writeUByte(C_EXT);
613 out.writeUByte(0);
614 }
615
616 public void dumpEXTDEFSYMENTs(ExtendedDataOutput out, List extrefs)
617 throws IOException {
618 Iterator i = extrefs.iterator();
619 int k = 2+NUM_OF_EXTERNAL_SYMS;
620 while (i.hasNext()) {
621 ExternalReference extref = (ExternalReference)i.next();
622 Assert._assert(extref.getSymbolIndex() == k);
623 String name = extref.getName();
624 if (name.length() <= 8) {
625 write_bytes(out, name, 8);
626 } else {
627 out.writeUInt(0);
628 int idx = alloc_string(name);
629 out.writeUInt(idx);
630 }
631 out.writeUInt(0);
632 out.writeShort((short)0);
633 out.writeUShort((char)DT_FCN);
634 out.writeUByte(C_EXT);
635 out.writeUByte(0);
636 ++k;
637 }
638 }
639
640 public void dumpSFIELDSYMENT(ExtendedDataOutput out, jq_StaticField sf)
641 throws IOException {
642
643 String name = mungeMemberName(sf);
644 if (name.length() <= 8) {
645 write_bytes(out, name, 8);
646 } else {
647 out.writeUInt(0);
648 int idx = alloc_string(name);
649 out.writeUInt(idx);
650 }
651 HeapAddress addr = sf.getAddress();
652 out.writeUInt(addr.to32BitValue());
653 out.writeShort((short)2);
654 jq_Type t = sf.getType();
655 char type = (char)0;
656 if (t.isArrayType()) {
657 t = ((jq_Array)t).getElementType();
658 type = DT_ARY;
659 } else if (t.isReferenceType()) {
660 type = DT_PTR;
661 }
662 if (t.isPrimitiveType()) {
663 if (t == jq_Primitive.INT) type |= T_LONG;
664 else if (t == jq_Primitive.LONG) type |= T_LNGDBL;
665 else if (t == jq_Primitive.FLOAT) type |= T_FLOAT;
666 else if (t == jq_Primitive.DOUBLE) type |= T_DOUBLE;
667 else if (t == jq_Primitive.BYTE) type |= T_CHAR;
668 else if (t == jq_Primitive.BOOLEAN) type |= T_UCHAR;
669 else if (t == jq_Primitive.SHORT) type |= T_SHORT;
670 else if (t == jq_Primitive.CHAR) type |= T_USHORT;
671 else Assert.UNREACHABLE();
672 } else {
673 type |= T_STRUCT;
674 }
675 out.writeUShort(type);
676 out.writeUByte(C_STAT);
677 out.writeUByte(0);
678 }
679
680 public void dumpIFIELDSYMENT(ExtendedDataOutput out, jq_InstanceField f)
681 throws IOException {
682 String name = f.getName().toString();
683 if (name.length() <= 8) {
684 write_bytes(out, name, 8);
685 } else {
686 out.writeUInt(0);
687 int idx = alloc_string(name);
688 out.writeUInt(idx);
689 }
690 int off = f.getOffset();
691 out.writeUInt(off);
692 out.writeShort((short)2);
693 jq_Type t = f.getType();
694 char type = (char)0;
695 if (t.isArrayType()) {
696 t = ((jq_Array)t).getElementType();
697 type = DT_ARY;
698 } else if (t.isReferenceType()) {
699 type = DT_PTR;
700 }
701 if (t.isPrimitiveType()) {
702 if (t == jq_Primitive.INT) type |= T_LONG;
703 else if (t == jq_Primitive.LONG) type |= T_LNGDBL;
704 else if (t == jq_Primitive.FLOAT) type |= T_FLOAT;
705 else if (t == jq_Primitive.DOUBLE) type |= T_DOUBLE;
706 else if (t == jq_Primitive.BYTE) type |= T_CHAR;
707 else if (t == jq_Primitive.BOOLEAN) type |= T_UCHAR;
708 else if (t == jq_Primitive.SHORT) type |= T_SHORT;
709 else if (t == jq_Primitive.CHAR) type |= T_USHORT;
710 else Assert.UNREACHABLE();
711 } else {
712 type |= T_STRUCT;
713 }
714 out.writeUShort(type);
715 out.writeUByte(C_MOS);
716 out.writeUByte(0);
717 }
718
719 public void dumpMETHODSYMENT(ExtendedDataOutput out, jq_CompiledCode cc)
720 throws IOException {
721 jq_Method m = cc.getMethod();
722 String name;
723 if (m == null) {
724 name = "unknown@"+cc.getEntrypoint().stringRep();
725 } else {
726
727 name = mungeMemberName(m);
728 }
729 if (name.length() <= 8) {
730 write_bytes(out, name, 8);
731 } else {
732 out.writeUInt(0);
733 int idx = alloc_string(name);
734 out.writeUInt(idx);
735 }
736 CodeAddress addr = cc.getEntrypoint();
737 out.writeUInt(addr.to32BitValue());
738 out.writeShort((short)1);
739 out.writeUShort((char)DT_FCN);
740 out.writeUByte(C_EXT);
741 out.writeUByte(0);
742 }
743
744 public void addSystemInterfaceRelocs_COFF(List extref, List dataRelocs) {
745 jq_StaticField[] fs = SystemInterface._class.getDeclaredStaticFields();
746 int total = 1+NUM_OF_EXTERNAL_SYMS;
747 for (int i=0; i<fs.length; ++i) {
748 jq_StaticField f = fs[i];
749 if (f.isFinal()) continue;
750 if (f.getType() == CodeAddress._class) {
751 String name = f.getName().toString();
752 int ind = name.lastIndexOf('_');
753 if (USE_MICROSOFT_STYLE_MUNGE)
754 name = "_"+name.substring(0, ind)+"@"+name.substring(ind+1);
755 else
756 name = name.substring(0, ind);
757 if (TRACE) System.out.println("External ref="+f+", symndx="+(total+1)+" address="+f.getAddress().stringRep());
758 ExternalReference r = new ExternalReference(f.getAddress(), name);
759 r.setSymbolIndex(++total);
760 extref.add(r);
761 dataRelocs.add(r);
762 } else if (f.getType() == HeapAddress._class) {
763 String name = f.getName().toString();
764 if (USE_MICROSOFT_STYLE_MUNGE)
765 name = "_"+name;
766 if (TRACE) System.out.println("External ref="+f+", symndx="+(total+1)+" address="+f.getAddress().stringRep());
767 ExternalReference r = new ExternalReference(f.getAddress(), name);
768 r.setSymbolIndex(++total);
769 extref.add(r);
770 dataRelocs.add(r);
771 }
772 }
773
774 }
775
776 public void addSystemInterfaceRelocs_ELF(List extref, List dataRelocs) {
777 jq_StaticField[] fs = SystemInterface._class.getDeclaredStaticFields();
778 int total = 1+NUM_OF_EXTERNAL_SYMS;
779 for (int i=0; i<fs.length; ++i) {
780 jq_StaticField f = fs[i];
781 if (f.isFinal()) continue;
782 if (f.getType() == CodeAddress._class) {
783 String name = f.getName().toString();
784 int ind = name.lastIndexOf('_');
785 name = name.substring(0, ind);
786 if (TRACE) System.out.println("External ref="+f+", symndx="+(total+1)+" address="+f.getAddress().stringRep());
787 ExternalReference r = new ExternalReference(f.getAddress(), name);
788 r.setSymbolIndex(++total);
789 extref.add(r);
790 dataRelocs.add(r);
791 } else if (f.getType() == HeapAddress._class) {
792 String name = f.getName().toString();
793 if (TRACE) System.out.println("External ref="+f+", symndx="+(total+1)+" address="+f.getAddress().stringRep());
794 ExternalReference r = new ExternalReference(f.getAddress(), name);
795 r.setSymbolIndex(++total);
796 extref.add(r);
797 dataRelocs.add(r);
798 }
799 }
800 }
801
802 public int addVTableRelocs(List list) {
803 int total = 0;
804 Iterator i = boot_types.iterator();
805 while (i.hasNext()) {
806 jq_Type t = (jq_Type)i.next();
807 if (t.isReferenceType()) {
808 if (t == Unsafe._class) continue;
809 try {
810 if (TRACE) System.out.println("Adding vtable relocs for: "+t);
811 Address[] vtable = (Address[])((jq_Reference)t).getVTable();
812 HeapAddress addr = getAddressOf(vtable);
813
814 Heap2HeapReference r1 = new Heap2HeapReference(addr, (HeapAddress) vtable[0]);
815 list.add(r1);
816 for (int j=1; j<vtable.length; ++j) {
817 Heap2CodeReference r2 = new Heap2CodeReference((HeapAddress) addr.offset(CodeAddress.size()*j), (CodeAddress) vtable[j]);
818 list.add(r2);
819 }
820 total += vtable.length;
821 } catch (UnknownObjectException x) {
822 x.appendMessage("vtable for "+t);
823 x.setObject(null);
824 throw x;
825 }
826 }
827 }
828 return total;
829 }
830
831 public void dumpCOFF(ExtendedDataOutput out, jq_StaticMethod rootm) throws IOException {
832
833 final List text_relocs1 = bca.getAllCodeRelocs();
834 final List text_relocs2 = bca.getAllDataRelocs();
835
836 Iterator i = text_relocs1.iterator();
837 while (i.hasNext()) {
838 Object r = i.next();
839 ((Reloc)r).patch();
840
841
842 if (r instanceof DirectBindCall)
843 i.remove();
844 }
845
846
847 final int textsize = bca.size();
848 final List exts = new LinkedList();
849 final int nlinenum = 0;
850 int ntextreloc = text_relocs1.size() + text_relocs2.size();
851 if (ntextreloc > 65535) ++ntextreloc;
852 final int datastart = 20+40+40+textsize+(10*ntextreloc);
853 final int datasize = heapCurrent;
854 final int numOfVTableRelocs = addVTableRelocs(data_relocs);
855 addSystemInterfaceRelocs_COFF(exts, data_relocs);
856 int ndatareloc = data_relocs.size();
857 if (ndatareloc > 65535) ++ndatareloc;
858 final int symtabstart = datastart+datasize+(10*ndatareloc)+(10*nlinenum);
859 final int num_ccs = CodeAllocator.getNumberOfCompiledMethods();
860 final int nsyms = 2+NUM_OF_EXTERNAL_SYMS+num_ccs+exts.size();
861
862 if (TRACE) {
863 System.out.println("Text size="+textsize);
864 System.out.println("Num text relocs="+ntextreloc);
865 System.out.println("Data start="+datastart);
866 System.out.println("Data size="+datasize);
867 System.out.println("Num of VTable relocs="+numOfVTableRelocs);
868 System.out.println("Num data relocs="+ntextreloc);
869 System.out.println("Sym tab start="+symtabstart);
870 System.out.println("Num syms="+nsyms);
871 }
872
873
874 dumpFILHDR(out, symtabstart, nsyms);
875
876
877 dumpTEXTSCNHDR(out, textsize, ntextreloc);
878 dumpDATASCNHDR(out, datastart, datasize, ndatareloc);
879
880
881 bca.dump(out);
882
883
884 if (ntextreloc > 65535) {
885 out.writeUInt(ntextreloc);
886 out.writeUInt(0);
887 out.writeUShort((char)0);
888 }
889 Iterator it = text_relocs1.iterator();
890 while (it.hasNext()) {
891 Reloc r = (Reloc)it.next();
892 r.dumpCOFF(out);
893 }
894 it = text_relocs2.iterator();
895 while (it.hasNext()) {
896 Reloc r = (Reloc)it.next();
897 r.dumpCOFF(out);
898 }
899
900
901
902 try {
903 dumpHeap(out);
904 } catch (UnknownObjectException x) {
905 Object u = x.getObject();
906 HashSet visited = new HashSet();
907 findReferencePath(u, x, visited);
908 throw x;
909 }
910
911
912 int j=0;
913 if (ndatareloc > 65535) {
914 out.writeUInt(ndatareloc);
915 out.writeUInt(0);
916 out.writeUShort((char)0);
917 ++j;
918 }
919 it = data_relocs.iterator();
920 while (it.hasNext()) {
921 if ((j % UPDATE_PERIOD) == 0) {
922 MultiPassBootImage.out.print("Written: "+j+"/"+ndatareloc+" relocations\r");
923 }
924 Reloc r = (Reloc)it.next();
925 r.dumpCOFF(out);
926 ++j;
927 }
928 MultiPassBootImage.out.println("Written: "+ndatareloc+" relocations \n");
929 Assert._assert(j == ndatareloc);
930
931
932
933
934 dumpSECTIONSYMENTs(out);
935 dumpEXTSYMENTs(out, rootm);
936 dumpEXTDEFSYMENTs(out, exts);
937 it = CodeAllocator.getCompiledMethods();
938 j=0;
939 while (it.hasNext()) {
940 jq_CompiledCode r = (jq_CompiledCode)it.next();
941 dumpMETHODSYMENT(out, r);
942 ++j;
943 }
944 Assert._assert(j == num_ccs);
945
946
947 dump_strings(out);
948
949
950 }
951
952 static class UnknownObjectException extends RuntimeException {
953 /***
954 * Version ID for serialization.
955 */
956 private static final long serialVersionUID = 3257002155398345015L;
957 Object o; StringBuffer message;
958 UnknownObjectException(Object o) {
959 this.o = o;
960 this.message = new StringBuffer();
961 this.message.append("type: ");
962 this.message.append(o.getClass().toString());
963 this.message.append(" address: ");
964 this.message.append(Strings.hex(System.identityHashCode(o)));
965 this.message.append(' ');
966 }
967 void setObject(Object o) { this.o = o; }
968 Object getObject() { return o; }
969 void prependMessage(String s) {
970 StringBuffer sb = new StringBuffer();
971 sb.append(s);
972 sb.append(this.message);
973 this.message = sb;
974 }
975 void appendMessage(String s) { this.message.append(s); }
976 public String toString() { return this.message.toString(); }
977 }
978
979 private jq_StaticField searchStaticVariables(Object p) {
980 int num = PrimordialClassLoader.loader.getNumTypes();
981 jq_Type[] types = PrimordialClassLoader.loader.getAllTypes();
982 for (int i = 0; i < num; ++i) {
983 Object o = types[i];
984 if (!(o instanceof jq_Class)) continue;
985 jq_Class k = (jq_Class) o;
986 if (!k.isLoaded()) continue;
987 jq_StaticField[] fs = k.getDeclaredStaticFields();
988 for (int j=0; j<fs.length; ++j) {
989 jq_StaticField f = fs[j];
990 if (f.getType().isAddressType()) {
991
992 } else if (f.getType().isReferenceType()) {
993 Object val = Reflection.getstatic_A(f);
994 if (val == p) return f;
995 }
996 }
997 }
998 return null;
999 }
1000
1001 private boolean findReferencePath(Object p, UnknownObjectException x, HashSet visited) {
1002 jq_StaticField sf = searchStaticVariables(p);
1003 if (sf != null) {
1004 x.appendMessage(sf.getDeclaringClass()+"."+sf.getName());
1005 return true;
1006 }
1007 Iterator i = entries.iterator();
1008 while (i.hasNext()) {
1009 Entry e = (Entry)i.next();
1010 Object o = e.getObject();
1011 IdentityHashCodeWrapper w = IdentityHashCodeWrapper.create(o);
1012 if (visited.contains(w)) continue;
1013 Class objType = o.getClass();
1014 jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
1015 if (jqType.isArrayType()) {
1016 jq_Type elemType = ((jq_Array)jqType).getElementType();
1017 if (elemType.isAddressType()) {
1018
1019 } else if (elemType.isReferenceType()) {
1020 int length = Array.getLength(o);
1021 Object[] v = (Object[])o;
1022 for (int k=0; k<length; ++k) {
1023 Object o2 = Reflection.arrayload_A(v, k);
1024 if (o2 == p) {
1025 System.err.println("Possible path: ["+k+"]");
1026 visited.add(w);
1027 if (findReferencePath(o, x, visited)) {
1028 x.appendMessage("["+k+"]");
1029 return true;
1030 } else {
1031 System.err.println("Backtracking ["+k+"]");
1032 }
1033 }
1034 }
1035 }
1036 } else {
1037 Assert._assert(jqType.isClassType());
1038 jq_Class clazz = (jq_Class)jqType;
1039 jq_InstanceField[] fields = clazz.getInstanceFields();
1040 for (int k=0; k<fields.length; ++k) {
1041 jq_InstanceField f = fields[k];
1042 jq_Type ftype = f.getType();
1043 if (ftype.isAddressType()) {
1044
1045 } else if (ftype.isReferenceType()) {
1046 Object val = Reflection.getfield_A(o, f);
1047 if (val == p) {
1048 System.err.println("Possible path: ."+f.getName());
1049 visited.add(w);
1050 if (findReferencePath(o, x, visited)) {
1051 x.appendMessage("."+f.getName());
1052 return true;
1053 } else {
1054 System.err.println("Backtracking ."+f.getName());
1055 }
1056 }
1057 }
1058 }
1059 }
1060 }
1061 return false;
1062 }
1063
1064 private void dumpHeap(ExtendedDataOutput out)
1065 throws IOException {
1066 Assert._assert(ObjectLayout.ARRAY_LENGTH_OFFSET == -12);
1067 Assert._assert(ObjectLayout.STATUS_WORD_OFFSET == -8);
1068 Assert._assert(ObjectLayout.VTABLE_OFFSET == -4);
1069 Assert._assert(ObjectLayout.OBJ_HEADER_SIZE == 8);
1070 Assert._assert(ObjectLayout.ARRAY_HEADER_SIZE == 12);
1071 Iterator i = entries.iterator();
1072 int currentAddr=0;
1073 int j=0;
1074 while (i.hasNext()) {
1075 if ((j % UPDATE_PERIOD) == 0) {
1076 System.out.print("Written: "+j+"/"+entries.size()+" objects, "+currentAddr+"/"+heapCurrent+" bytes\r");
1077 }
1078 Entry e = (Entry)i.next();
1079 Object o = e.getObject();
1080 HeapAddress addr = e.getAddress();
1081 Class objType = o.getClass();
1082 jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
1083 if (TRACE)
1084 MultiPassBootImage.out.println("Dumping entry "+j+": "+objType+" "+Strings.hex(System.identityHashCode(o))+" addr "+addr.stringRep());
1085 Assert._assert(!jqType.isAddressType());
1086 if (!jqType.isClsInitialized()) {
1087 Assert.UNREACHABLE(jqType.toString());
1088 return;
1089 }
1090 HeapAddress vtable;
1091 try { vtable = getAddressOf(jqType.getVTable()); }
1092 catch (UnknownObjectException x) {
1093 x.appendMessage("vtable for "+jqType);
1094 x.setObject(null);
1095 throw x;
1096 }
1097 if (jqType.isArrayType()) {
1098 while (currentAddr+ObjectLayout.ARRAY_HEADER_SIZE < addr.to32BitValue()) {
1099 out.writeByte((byte)0); ++currentAddr;
1100 }
1101 int length = Array.getLength(o);
1102 out.writeUInt(length);
1103 out.writeUInt(0);
1104 out.writeUInt(vtable.to32BitValue());
1105 currentAddr += ObjectLayout.ARRAY_HEADER_SIZE;
1106 Assert._assert(addr.to32BitValue() == currentAddr);
1107 jq_Type elemType = ((jq_Array)jqType).getElementType();
1108 if (elemType.isPrimitiveType()) {
1109 if (elemType == jq_Primitive.INT) {
1110 int[] v = (int[])o;
1111 for (int k=0; k<length; ++k)
1112 out.writeUInt(v[k]);
1113 currentAddr += length << 2;
1114 } else if (elemType == jq_Primitive.FLOAT) {
1115 float[] v = (float[])o;
1116 for (int k=0; k<length; ++k)
1117 out.writeUInt(Float.floatToRawIntBits(v[k]));
1118 currentAddr += length << 2;
1119 } else if (elemType == jq_Primitive.LONG) {
1120 long[] v = (long[])o;
1121 for (int k=0; k<length; ++k)
1122 out.writeULong(v[k]);
1123 currentAddr += length << 3;
1124 } else if (elemType == jq_Primitive.DOUBLE) {
1125 double[] v = (double[])o;
1126 for (int k=0; k<length; ++k)
1127 out.writeULong(Double.doubleToRawLongBits(v[k]));
1128 currentAddr += length << 3;
1129 } else if (elemType == jq_Primitive.BOOLEAN) {
1130 boolean[] v = (boolean[])o;
1131 for (int k=0; k<length; ++k)
1132 out.writeUByte(v[k]?1:0);
1133 currentAddr += length;
1134 } else if (elemType == jq_Primitive.BYTE) {
1135 byte[] v = (byte[])o;
1136 for (int k=0; k<length; ++k)
1137 out.writeByte(v[k]);
1138 currentAddr += length;
1139 } else if (elemType == jq_Primitive.SHORT) {
1140 short[] v = (short[])o;
1141 for (int k=0; k<length; ++k)
1142 out.writeShort(v[k]);
1143 currentAddr += length << 1;
1144 } else if (elemType == jq_Primitive.CHAR) {
1145 char[] v = (char[])o;
1146 for (int k=0; k<length; ++k)
1147 out.writeUShort(v[k]);
1148 currentAddr += length << 1;
1149 } else Assert.UNREACHABLE();
1150 } else if (elemType.isAddressType()) {
1151 Address[] v = (Address[])o;
1152 for (int k=0; k<length; ++k) {
1153 out.writeUInt(v[k]==null?0:v[k].to32BitValue());
1154 }
1155 currentAddr += length << 2;
1156 } else {
1157 Object[] v = (Object[])o;
1158 for (int k=0; k<length; ++k) {
1159 Object o2 = Reflection.arrayload_A(v, k);
1160 try { out.writeUInt(getAddressOf(o2).to32BitValue()); }
1161 catch (UnknownObjectException x) {
1162 System.err.println("Object array element #"+k);
1163
1164
1165 throw x;
1166 }
1167 }
1168 currentAddr += length << 2;
1169 }
1170 } else {
1171 Assert._assert(jqType.isClassType());
1172 jq_Class clazz = (jq_Class)jqType;
1173 while (currentAddr+ObjectLayout.OBJ_HEADER_SIZE < addr.to32BitValue()) {
1174 out.writeByte((byte)0); ++currentAddr;
1175 }
1176 out.writeUInt(0);
1177 out.writeUInt(vtable.to32BitValue());
1178 currentAddr += 8;
1179 Assert._assert(addr.to32BitValue() == currentAddr);
1180 jq_InstanceField[] fields = clazz.getInstanceFields();
1181 for (int k=0; k<fields.length; ++k) {
1182 jq_InstanceField f = fields[k];
1183 jq_Type ftype = f.getType();
1184 int foffset = f.getOffset();
1185 if (TRACE) MultiPassBootImage.out.println("Field "+f+" offset "+Strings.shex(foffset)+": "+System.identityHashCode(Reflection.getfield(o, f)));
1186 while (currentAddr != addr.offset(foffset).to32BitValue()) {
1187 out.writeByte((byte)0); ++currentAddr;
1188 }
1189 if (ftype.isPrimitiveType()) {
1190 if (ftype == jq_Primitive.INT)
1191 out.writeUInt(Reflection.getfield_I(o, f));
1192 else if (ftype == jq_Primitive.FLOAT)
1193 out.writeUInt(Float.floatToRawIntBits(Reflection.getfield_F(o, f)));
1194 else if (ftype == jq_Primitive.LONG)
1195 out.writeULong(Reflection.getfield_L(o, f));
1196 else if (ftype == jq_Primitive.DOUBLE)
1197 out.writeULong(Double.doubleToRawLongBits(Reflection.getfield_D(o, f)));
1198 else if (ftype == jq_Primitive.BOOLEAN)
1199 out.writeUByte(Reflection.getfield_Z(o, f)?1:0);
1200 else if (ftype == jq_Primitive.BYTE)
1201 out.writeByte(Reflection.getfield_B(o, f));
1202 else if (ftype == jq_Primitive.SHORT)
1203 out.writeShort(Reflection.getfield_S(o, f));
1204 else if (ftype == jq_Primitive.CHAR)
1205 out.writeUShort(Reflection.getfield_C(o, f));
1206 else Assert.UNREACHABLE();
1207 } else if (ftype.isAddressType()) {
1208 Address a = Reflection.getfield_P(o, f);
1209 out.writeUInt(a==null?0:a.to32BitValue());
1210 } else {
1211 try { out.writeUInt(getAddressOf(Reflection.getfield_A(o, f)).to32BitValue()); }
1212 catch (UnknownObjectException x) {
1213 System.err.println("Instance field "+f);
1214
1215
1216 throw x;
1217 }
1218 }
1219 currentAddr += f.getSize();
1220 }
1221 }
1222 ++j;
1223 }
1224 while (currentAddr < heapCurrent) {
1225 out.writeByte((byte)0); ++currentAddr;
1226 }
1227 System.out.println("Written: "+j+" objects, "+heapCurrent+" bytes ");
1228 }
1229
1230 public static void write_bytes(ExtendedDataOutput out, String s, int len)
1231 throws IOException {
1232 Assert._assert(s.length() <= len);
1233 int i;
1234 for (i=0; ; ++i) {
1235 if (i == s.length()) {
1236 for (; i<len; ++i) {
1237 out.write((byte)0);
1238 }
1239 return;
1240 }
1241 out.write((byte)s.charAt(i));
1242 }
1243 }
1244
1245 private String mungeMemberName(jq_Member m) {
1246 String name = m.getDeclaringClass().getName().toString() +
1247 "_"+m.getName()+
1248 "_"+m.getDesc();
1249 StringBuffer sb = new StringBuffer();
1250 for (int i = 0; i < name.length(); ++i) {
1251 char c = name.charAt(i);
1252 switch (c) {
1253 case '.':
1254 case '/':
1255 case '(':
1256 case ')':
1257 case ';':
1258 break;
1259 default:
1260 sb.append(c);
1261 break;
1262 }
1263 }
1264 return sb.toString();
1265 }
1266
1267 int stringTableOffset = 4;
1268 List stringTable = new LinkedList();
1269 private int alloc_string(String name) {
1270 int off = stringTableOffset;
1271 byte[] b = SystemInterface.toCString(name);
1272 stringTable.add(b);
1273 stringTableOffset += b.length;
1274 return off;
1275 }
1276
1277 private void dump_strings(ExtendedDataOutput out)
1278 throws IOException {
1279 Iterator i = stringTable.iterator();
1280 out.writeUInt(stringTableOffset);
1281 while (i.hasNext()) {
1282 byte[] b = (byte[])i.next();
1283 out.write(b);
1284 }
1285 }
1286
1287
1288 public void dumpELF(ExtendedDataOutput out, jq_StaticMethod rootm) throws IOException {
1289 final List text_relocs1 = bca.getAllCodeRelocs();
1290 final List text_relocs2 = bca.getAllDataRelocs();
1291 Iterator i = text_relocs1.iterator();
1292 while (i.hasNext()) {
1293 Object r = i.next();
1294 ((Reloc)r).patch();
1295
1296
1297 if (r instanceof DirectBindCall)
1298 i.remove();
1299 }
1300
1301 System.out.print("Initializing ELF data structures...");
1302 long time = System.currentTimeMillis();
1303
1304 ELFOutput f = new ELFOutput(ELFDATA2LSB, ET_REL, EM_386, 0, out);
1305 f.setLittleEndian();
1306 Section.NullSection empty = Section.NullSection.INSTANCE;
1307 Section.StrTabSection shstrtab = new Section.StrTabSection(".shstrtab", 0, 0);
1308 Section.StrTabSection strtab = new Section.StrTabSection(".strtab", 0, 0);
1309 Section.SymTabSection symtab = new Section.SymTabSection(".symtab", 0, 0, strtab);
1310 Section.ProgBitsSection text = new TextSection();
1311 Section.ProgBitsSection data = new DataSection();
1312 Section.RelSection textrel = new Section.RelSection(".rel.text", 0, 0, symtab, text);
1313 Section.RelSection datarel = new Section.RelSection(".rel.data", 0, 0, symtab, data);
1314 f.setSectionHeaderStringTable(shstrtab);
1315
1316 f.addSection(empty);
1317 f.addSection(shstrtab);
1318 f.addSection(strtab);
1319 f.addSection(symtab);
1320 f.addSection(text);
1321 f.addSection(data);
1322 f.addSection(textrel);
1323 f.addSection(datarel);
1324
1325 final List exts = new LinkedList();
1326 final int numOfVTableRelocs = addVTableRelocs(data_relocs);
1327 addSystemInterfaceRelocs_ELF(exts, data_relocs);
1328
1329 symtab.addSymbol(new SymbolTableEntry("", 0, 0, SymbolTableEntry.STB_LOCAL, SymbolTableEntry.STT_NOTYPE, empty));
1330
1331 SymbolTableEntry textsyment = new SymbolTableEntry("", 0, 0, SymbolTableEntry.STB_LOCAL, SymbolTableEntry.STT_SECTION, text);
1332 SymbolTableEntry datasyment = new SymbolTableEntry("", 0, 0, SymbolTableEntry.STB_LOCAL, SymbolTableEntry.STT_SECTION, data);
1333 symtab.addSymbol(textsyment);
1334 symtab.addSymbol(datasyment);
1335
1336 Iterator it = exts.iterator();
1337 while (it.hasNext()) {
1338 ExternalReference r = (ExternalReference)it.next();
1339 SymbolTableEntry e = new SymbolTableEntry(r.getName(), 0, 0, SymbolTableEntry.STB_GLOBAL, SymbolTableEntry.STT_FUNC, empty);
1340 symtab.addSymbol(e);
1341 datarel.addReloc(new RelocEntry(r.getAddress().to32BitValue(), e, RelocEntry.R_386_32));
1342 }
1343
1344 it = CodeAllocator.getCompiledMethods();
1345 while (it.hasNext()) {
1346 jq_CompiledCode cc = (jq_CompiledCode)it.next();
1347 jq_Method m = cc.getMethod();
1348 String name;
1349 if (m == null) {
1350 name = "unknown@"+cc.getEntrypoint().stringRep();
1351 } else {
1352 name = mungeMemberName(m);
1353 }
1354 SymbolTableEntry e = new SymbolTableEntry(name, cc.getEntrypoint().to32BitValue(), cc.getLength(), STB_LOCAL, STT_FUNC, text);
1355 symtab.addSymbol(e);
1356 }
1357
1358 {
1359 jq_CompiledCode cc = rootm.getDefaultCompiledVersion();
1360 SymbolTableEntry e = new SymbolTableEntry("entry", cc.getEntrypoint().to32BitValue(), cc.getLength(), STB_GLOBAL, STT_FUNC, text);
1361 symtab.addSymbol(e);
1362
1363 cc = ExceptionDeliverer._trap_handler.getDefaultCompiledVersion();
1364 e = new SymbolTableEntry("trap_handler", cc.getEntrypoint().to32BitValue(), cc.getLength(), STB_GLOBAL, STT_FUNC, text);
1365 symtab.addSymbol(e);
1366
1367 cc = ExceptionDeliverer._debug_trap_handler.getDefaultCompiledVersion();
1368 e = new SymbolTableEntry("debug_trap_handler", cc.getEntrypoint().to32BitValue(), cc.getLength(), STB_GLOBAL, STT_FUNC, text);
1369 symtab.addSymbol(e);
1370
1371 cc = jq_NativeThread._threadSwitch.getDefaultCompiledVersion();
1372 e = new SymbolTableEntry("threadSwitch", cc.getEntrypoint().to32BitValue(), cc.getLength(), STB_GLOBAL, STT_FUNC, text);
1373 symtab.addSymbol(e);
1374
1375 cc = jq_NativeThread._ctrl_break_handler.getDefaultCompiledVersion();
1376 e = new SymbolTableEntry("ctrl_break_handler", cc.getEntrypoint().to32BitValue(), cc.getLength(), STB_GLOBAL, STT_FUNC, text);
1377 symtab.addSymbol(e);
1378
1379 e = new SymbolTableEntry("joeq_code_startaddress", 0, 0, STB_GLOBAL, STT_OBJECT, text);
1380 symtab.addSymbol(e);
1381
1382 e = new SymbolTableEntry("joeq_code_endaddress", bca.size(), 0, STB_GLOBAL, STT_OBJECT, text);
1383 symtab.addSymbol(e);
1384
1385 e = new SymbolTableEntry("joeq_data_startaddress", 0, 0, STB_GLOBAL, STT_OBJECT, data);
1386 symtab.addSymbol(e);
1387
1388 e = new SymbolTableEntry("joeq_data_endaddress", heapCurrent, 0, STB_GLOBAL, STT_OBJECT, data);
1389 symtab.addSymbol(e);
1390 }
1391
1392 it = text_relocs1.iterator();
1393 while (it.hasNext()) {
1394 Reloc r = (Reloc)it.next();
1395 if (r instanceof Code2CodeReference) {
1396 Code2CodeReference cr = (Code2CodeReference)r;
1397 textrel.addReloc(new RelocEntry(cr.getFrom().to32BitValue(), datasyment, RelocEntry.R_386_32));
1398 } else {
1399 Assert.UNREACHABLE(r.toString());
1400 }
1401 }
1402
1403 it = text_relocs2.iterator();
1404 while (it.hasNext()) {
1405 Reloc r = (Reloc)it.next();
1406 if (r instanceof Code2HeapReference) {
1407 Code2HeapReference cr = (Code2HeapReference)r;
1408 textrel.addReloc(new RelocEntry(cr.getFrom().to32BitValue(), datasyment, RelocEntry.R_386_32));
1409 } else {
1410 Assert.UNREACHABLE(r.toString());
1411 }
1412 }
1413
1414 it = data_relocs.iterator();
1415 while (it.hasNext()) {
1416 Reloc r = (Reloc)it.next();
1417 if (r instanceof Heap2HeapReference) {
1418 Heap2HeapReference cr = (Heap2HeapReference)r;
1419 datarel.addReloc(new RelocEntry(cr.getFrom().to32BitValue(), datasyment, RelocEntry.R_386_32));
1420 } else if (r instanceof Heap2CodeReference) {
1421 Heap2CodeReference cr = (Heap2CodeReference)r;
1422 datarel.addReloc(new RelocEntry(cr.getFrom().to32BitValue(), textsyment, RelocEntry.R_386_32));
1423 } else if (r instanceof ExternalReference) {
1424
1425 } else {
1426 Assert.UNREACHABLE(r.toString());
1427 }
1428 }
1429
1430 time = System.currentTimeMillis() - time;
1431 System.out.println("done. ("+(time/1000.)+" seconds)");
1432
1433 f.write();
1434
1435
1436 }
1437
1438 class TextSection extends Section.ProgBitsSection {
1439 TextSection() {
1440 super(".text", Section.SHF_ALLOC | Section.SHF_EXECINSTR | Section.SHF_WRITE, 0);
1441 }
1442 public int getSize() { return bca.size(); }
1443 public int getAddrAlign() { return 64; }
1444 public void writeData(ELF file) throws IOException {
1445 ExtendedDataOutput out = (ExtendedDataOutput) ((ELFOutput)file).getOutput();
1446 bca.dump(out);
1447 }
1448 public void load(Section.UnloadedSection s, ELF file) throws IOException {
1449 Assert.UNREACHABLE();
1450 }
1451 }
1452
1453 class DataSection extends Section.ProgBitsSection {
1454 DataSection() {
1455 super(".data", Section.SHF_ALLOC | Section.SHF_WRITE, 0);
1456 }
1457 public int getSize() { return heapCurrent; }
1458 public int getAddrAlign() { return 64; }
1459 public void writeData(ELF file) throws IOException {
1460 try {
1461 ExtendedDataOutput out = (ExtendedDataOutput) ((ELFOutput)file).getOutput();
1462 dumpHeap(out);
1463 } catch (UnknownObjectException x) {
1464 Object u = x.getObject();
1465 HashSet visited = new HashSet();
1466 findReferencePath(u, x, visited);
1467 throw x;
1468 }
1469 }
1470 public void load(Section.UnloadedSection s, ELF file) throws IOException {
1471 Assert.UNREACHABLE();
1472 }
1473 }
1474
1475 public static final jq_StaticField _DEFAULT;
1476 static {
1477 jq_Class k = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Bootstrap/MultiPassBootImage;");
1478 _DEFAULT = k.getOrCreateStaticField("DEFAULT", "Ljoeq/Bootstrap/MultiPassBootImage;");
1479 }
1480
1481 }