1 using System;
2 using System.Collections;
3
4 namespace cmsx.object
5 {
6 public const ulong undefinedValue = cast<ulong>(-1);
7
8 public enum Segment : byte
9 {
10 text = 0u, data = 1u, pool = 2u, stack = 3u, unknown = 255u
11 }
12
13 public string SegmentStr(Segment segment)
14 {
15 switch (segment)
16 {
17 case Segment.text: return "text";
18 case Segment.data: return "data";
19 case Segment.pool: return "pool";
20 case Segment.stack: return "stack";
21 }
22 return "-";
23 }
24
25 public enum Linkage : byte
26 {
27 internal_ = 0u, external = 1u, once = 2u, remove = 3u, undefined = 4u
28 }
29
30 public string LinkageStr(Linkage linkage)
31 {
32 switch (linkage)
33 {
34 case Linkage.internal_: return "internal";
35 case Linkage.external: return "external";
36 case Linkage.once: return "once";
37 case Linkage.remove: return "remove";
38 case Linkage.undefined: return "undefined";
39 }
40 return "";
41 }
42
43 public string ValueFlagStr(Value.Flag flags)
44 {
45 if (flags == Value.Flag.undefined)
46 {
47 return "U";
48 }
49 string s;
50 if ((flags & Value.Flag.definition) != Value.Flag.undefined)
51 {
52 s.Append('D');
53 }
54 if ((flags & Value.Flag.register) != Value.Flag.undefined)
55 {
56 s.Append('R');
57 }
58 if ((flags & Value.Flag.pure) != Value.Flag.undefined)
59 {
60 s.Append('P');
61 }
62 if ((flags & Value.Flag.address) != Value.Flag.undefined)
63 {
64 s.Append('A');
65 }
66 if ((flags & Value.Flag.function) != Value.Flag.undefined)
67 {
68 s.Append('F');
69 }
70 if ((flags & Value.Flag.structure) != Value.Flag.undefined)
71 {
72 s.Append('S');
73 }
74 return s;
75 }
76
77 public class Value
78 {
79 public enum Flag : byte
80 {
81 undefined = 0u,
82 definition = 1u << 0u,
83 register = 1u << 1u,
84 pure = 1u << 2u,
85 address = 1u << 3u,
86 function = 1u << 4u,
87 structure = 1u << 5u,
88 used = 1u << 6u
89 }
90 public nothrow Value() : flags(Flag.undefined), value(undefinedValue), symbol(null)
91 {
92 }
93 public nothrow Value(Flag flags_, ulong value_, Symbol* symbol_) : flags(flags_), value(value_), symbol(symbol_)
94 {
95 }
96 public inline nothrow void SetUndefined()
97 {
98 flags = Flag.undefined;
99 }
100 public inline nothrow void SetDefinition()
101 {
102 flags = cast<Flag>(flags | Flag.definition);
103 }
104 public inline nothrow void SetRegister()
105 {
106 flags = Flag.register;
107 }
108 public inline nothrow void SetPure()
109 {
110 flags = cast<Flag>(flags | Flag.pure);
111 }
112 public inline nothrow void SetAddress()
113 {
114 flags = cast<Flag>(flags | Flag.address);
115 }
116 public inline nothrow void SetFunction()
117 {
118 flags = cast<Flag>(flags | Flag.function);
119 }
120 public inline nothrow void SetStructure()
121 {
122 flags = cast<Flag>(flags | Flag.structure);
123 }
124 public inline nothrow void SetUsed()
125 {
126 flags = cast<Flag>(flags | Flag.used);
127 }
128 public inline nothrow bool GetFlag(Flag flag)
129 {
130 return (flags & flag) != Flag.undefined;
131 }
132 public Flag flags;
133 public ulong value;
134 public Symbol* symbol;
135 }
136
137 public string ValueStr(const Value& value)
138 {
139 string result = Format(ValueFlagStr(value.flags), 5) + " #" + ToHexString(value.value) + " ";
140 if (value.flags == Value.Flag.register)
141 {
142 result.Append(Format("$" + ToString(value.value), 20));
143 }
144 else
145 {
146 result.Append(Format(ToString(value.value), 20));
147 }
148 return result;
149 }
150
151 public class Symbol
152 {
153 public nothrow Symbol() : index(-1), segment(Segment.unknown), linkage(Linkage.internal_), parentIndex(-1), linkStart(-1), linkEnd(-1), alignment(1u)
154 {
155 }
156 public Symbol* Clone()
157 {
158 Symbol* clone = new Symbol();
159 clone->index = -1;
160 clone->name = name;
161 clone->segment = segment;
162 clone->linkage = linkage;
163 clone->value = value;
164 clone->start = start;
165 clone->length = length;
166 clone->section = section;
167 clone->parentIndex = -1;
168 clone->linkStart = linkStart;
169 clone->linkEnd = linkEnd;
170 clone->alignment = alignment;
171 return clone;
172 }
173 public int index;
174 public string name;
175 public string localName;
176 public Segment segment;
177 public Linkage linkage;
178 public Value value;
179 public ulong start;
180 public ulong length;
181 public Section* section;
182 public int parentIndex;
183 public int linkStart;
184 public int linkEnd;
185 public byte alignment;
186 }
187
188 public class SymbolTable
189 {
190 public SymbolTable(BinaryFile* file_, bool init) : file(file_)
191 {
192 if (init)
193 {
194 Symbol* ax = new Symbol();
195 ax->name = "ax";
196 ax->value = Value(Value.Flag.register, cmsx.machine.regAX, ax);
197 AddSymbol(ax);
198 Symbol* bx = new Symbol();
199 bx->name = "bx";
200 bx->value = Value(Value.Flag.register, cmsx.machine.regBX, bx);
201 AddSymbol(bx);
202 Symbol* cx = new Symbol();
203 cx->name = "cx";
204 cx->value = Value(Value.Flag.register, cmsx.machine.regCX, cx);
205 AddSymbol(cx);
206 Symbol* dx = new Symbol();
207 dx->name = "dx";
208 dx->value = Value(Value.Flag.register, cmsx.machine.regDX, dx);
209 AddSymbol(dx);
210 Symbol* ex = new Symbol();
211 ex->name = "ex";
212 ex->value = Value(Value.Flag.register, cmsx.machine.regEX, ex);
213 AddSymbol(ex);
214 Symbol* sp = new Symbol();
215 sp->name = "sp";
216 sp->value = Value(Value.Flag.register, cmsx.machine.regSP, sp);
217 AddSymbol(sp);
218 Symbol* fp = new Symbol();
219 fp->name = "fp";
220 fp->value = Value(Value.Flag.register, cmsx.machine.regFP, fp);
221 AddSymbol(fp);
222 Symbol* ix = new Symbol();
223 ix->name = "ix";
224 ix->value = Value(Value.Flag.register, cmsx.machine.regIX, ix);
225 AddSymbol(ix);
226 Symbol* rA = new Symbol();
227 rA->name = "rA";
228 rA->value = Value(Value.Flag.pure, cmsx.machine.Registers.rA, rA);
229 AddSymbol(rA);
230 Symbol* rB = new Symbol();
231 rB->name = "rB";
232 rB->value = Value(Value.Flag.pure, cmsx.machine.Registers.rB, rB);
233 AddSymbol(rB);
234 Symbol* rC = new Symbol();
235 rC->name = "rC";
236 rC->value = Value(Value.Flag.pure, cmsx.machine.Registers.rC, rC);
237 AddSymbol(rC);
238 Symbol* rD = new Symbol();
239 rD->name = "rD";
240 rD->value = Value(Value.Flag.pure, cmsx.machine.Registers.rD, rD);
241 AddSymbol(rD);
242 Symbol* rE = new Symbol();
243 rE->name = "rE";
244 rE->value = Value(Value.Flag.pure, cmsx.machine.Registers.rE, rE);
245 AddSymbol(rE);
246 Symbol* rF = new Symbol();
247 rF->name = "rF";
248 rF->value = Value(Value.Flag.pure, cmsx.machine.Registers.rF, rF);
249 AddSymbol(rF);
250 Symbol* rG = new Symbol();
251 rG->name = "rG";
252 rG->value = Value(Value.Flag.pure, cmsx.machine.Registers.rG, rG);
253 AddSymbol(rG);
254 Symbol* rH = new Symbol();
255 rH->name = "rH";
256 rH->value = Value(Value.Flag.pure, cmsx.machine.Registers.rH, rH);
257 AddSymbol(rH);
258 Symbol* rI = new Symbol();
259 rI->name = "rI";
260 rI->value = Value(Value.Flag.pure, cmsx.machine.Registers.rI, rI);
261 AddSymbol(rI);
262 Symbol* rJ = new Symbol();
263 rJ->name = "rJ";
264 rJ->value = Value(Value.Flag.pure, cmsx.machine.Registers.rJ, rJ);
265 AddSymbol(rJ);
266 Symbol* rK = new Symbol();
267 rK->name = "rK";
268 rK->value = Value(Value.Flag.pure, cmsx.machine.Registers.rK, rK);
269 AddSymbol(rK);
270 Symbol* rL = new Symbol();
271 rL->name = "rL";
272 rL->value = Value(Value.Flag.pure, cmsx.machine.Registers.rL, rL);
273 AddSymbol(rL);
274 Symbol* rM = new Symbol();
275 rM->name = "rM";
276 rM->value = Value(Value.Flag.pure, cmsx.machine.Registers.rM, rM);
277 AddSymbol(rM);
278 Symbol* rN = new Symbol();
279 rN->name = "rN";
280 rN->value = Value(Value.Flag.pure, cmsx.machine.Registers.rN, rN);
281 AddSymbol(rN);
282 Symbol* rO = new Symbol();
283 rO->name = "rO";
284 rO->value = Value(Value.Flag.pure, cmsx.machine.Registers.rO, rO);
285 AddSymbol(rO);
286 Symbol* rP = new Symbol();
287 rP->name = "rP";
288 rP->value = Value(Value.Flag.pure, cmsx.machine.Registers.rP, rP);
289 AddSymbol(rP);
290 Symbol* rQ = new Symbol();
291 rQ->name = "rQ";
292 rQ->value = Value(Value.Flag.pure, cmsx.machine.Registers.rQ, rQ);
293 AddSymbol(rQ);
294 Symbol* rR = new Symbol();
295 rR->name = "rR";
296 rR->value = Value(Value.Flag.pure, cmsx.machine.Registers.rR, rR);
297 AddSymbol(rR);
298 Symbol* rS = new Symbol();
299 rS->name = "rS";
300 rS->value = Value(Value.Flag.pure, cmsx.machine.Registers.rS, rS);
301 AddSymbol(rS);
302 Symbol* rT = new Symbol();
303 rT->name = "rT";
304 rT->value = Value(Value.Flag.pure, cmsx.machine.Registers.rT, rT);
305 AddSymbol(rT);
306 Symbol* rU = new Symbol();
307 rU->name = "rU";
308 rU->value = Value(Value.Flag.pure, cmsx.machine.Registers.rU, rU);
309 AddSymbol(rU);
310 Symbol* rV = new Symbol();
311 rV->name = "rV";
312 rV->value = Value(Value.Flag.pure, cmsx.machine.Registers.rV, rV);
313 AddSymbol(rV);
314 Symbol* rW = new Symbol();
315 rW->name = "rW";
316 rW->value = Value(Value.Flag.pure, cmsx.machine.Registers.rW, rW);
317 AddSymbol(rW);
318 Symbol* rX = new Symbol();
319 rX->name = "rX";
320 rX->value = Value(Value.Flag.pure, cmsx.machine.Registers.rX, rX);
321 AddSymbol(rX);
322 Symbol* rY = new Symbol();
323 rY->name = "rY";
324 rY->value = Value(Value.Flag.pure, cmsx.machine.Registers.rY, rY);
325 AddSymbol(rY);
326 Symbol* rZ = new Symbol();
327 rZ->name = "rZ";
328 rZ->value = Value(Value.Flag.pure, cmsx.machine.Registers.rZ, rZ);
329 AddSymbol(rZ);
330 Symbol* rBB = new Symbol();
331 rBB->name = "rBB";
332 rBB->value = Value(Value.Flag.pure, cmsx.machine.Registers.rBB, rBB);
333 AddSymbol(rBB);
334 Symbol* rTT = new Symbol();
335 rTT->name = "rTT";
336 rTT->value = Value(Value.Flag.pure, cmsx.machine.Registers.rTT, rTT);
337 AddSymbol(rTT);
338 Symbol* rWW = new Symbol();
339 rWW->name = "rWW";
340 rWW->value = Value(Value.Flag.pure, cmsx.machine.Registers.rWW, rWW);
341 AddSymbol(rWW);
342 Symbol* rXX = new Symbol();
343 rXX->name = "rXX";
344 rXX->value = Value(Value.Flag.pure, cmsx.machine.Registers.rXX, rXX);
345 AddSymbol(rXX);
346 Symbol* rYY = new Symbol();
347 rYY->name = "rYY";
348 rYY->value = Value(Value.Flag.pure, cmsx.machine.Registers.rYY, rYY);
349 AddSymbol(rYY);
350 Symbol* rZZ = new Symbol();
351 rZZ->name = "rZZ";
352 rZZ->value = Value(Value.Flag.pure, cmsx.machine.Registers.rZZ, rZZ);
353 AddSymbol(rZZ);
354 }
355 }
356 suppress SymbolTable(const SymbolTable&);
357 suppress void operator=(const SymbolTable&);
358 suppress SymbolTable(SymbolTable&&);
359 suppress void operator=(SymbolTable&&);
360 public nothrow const List<UniquePtr<Symbol>>& Symbols() const
361 {
362 return symbols;
363 }
364 public nothrow const List<UniquePtr<Symbol>>& InternalSymbols() const
365 {
366 return internalSymbols;
367 }
368 public Symbol* GetSymbol(int index) const
369 {
370 return symbols[index].Get();
371 }
372 public Symbol* GetSymbol(const string& name) const
373 {
374 Map<string, Symbol*>.ConstIterator it = table.CFind(name);
375 if (it != table.CEnd())
376 {
377 return it->second;
378 }
379 else
380 {
381 return null;
382 }
383 }
384 public Symbol* GetInternalSymbol(const string& name) const
385 {
386 Map<string, Symbol*>.ConstIterator it = internalTable.CFind(name);
387 if (it != internalTable.CEnd())
388 {
389 return it->second;
390 }
391 else
392 {
393 return null;
394 }
395 }
396 public Symbol* GetSymbolByAddress(ulong absoluteAddress) const
397 {
398 Map<ulong, Symbol*>.ConstIterator it = addressMap.CFind(absoluteAddress);
399 if (it != addressMap.CEnd())
400 {
401 return it->second;
402 }
403 else
404 {
405 return null;
406 }
407 }
408 public Symbol* GetSymbolByValue(ulong value) const
409 {
410 Map<ulong, Symbol*>.ConstIterator it = valueMap.CFind(value);
411 if (it != valueMap.CEnd())
412 {
413 return it->second;
414 }
415 else
416 {
417 return null;
418 }
419 }
420 public Symbol* GetRegisterSymbol(byte registerNumber) const
421 {
422 Map<byte, Symbol*>.ConstIterator it = registerMap.CFind(registerNumber);
423 if (it != registerMap.CEnd())
424 {
425 return it->second;
426 }
427 else
428 {
429 return null;
430 }
431 }
432 public void AddSymbol(Symbol* symbol, bool setIndex)
433 {
434 if (setIndex)
435 {
436 symbol->index = cast<int>(symbols.Count());
437 }
438 symbols.Add(UniquePtr<Symbol>(symbol));
439 table[symbol->name] = symbol;
440 if (symbol->value.flags == Value.Flag.register)
441 {
442 registerMap[cast<byte>(symbol->value.value)] = symbol;
443 }
444 valueMap[symbol->value.value] = symbol;
445 }
446 public void AddSymbol(Symbol* symbol)
447 {
448 AddSymbol(symbol, true);
449 }
450 public void AddSymbolToAddressMap(Symbol* symbol)
451 {
452 if (symbol->value.GetFlag(Value.Flag.address))
453 {
454 symbol->start = symbol->section->baseAddress + symbol->value.value;
455 addressMap[symbol->start] = symbol;
456 }
457 }
458 public void AddInternalSymbol(Symbol* internalSymbol, bool setIndex)
459 {
460 if (setIndex)
461 {
462 internalSymbol->index = cast<int>(internalSymbols.Count());
463 }
464 #assert(internalSymbol->linkage == Linkage.internal_);
465 internalSymbols.Add(UniquePtr<Symbol>(internalSymbol));
466 addressMap[internalSymbol->start] = internalSymbol;
467 if (internalSymbol->value.flags == Value.Flag.register)
468 {
469 registerMap[cast<byte>(internalSymbol->value.value)] = internalSymbol;
470 }
471 internalTable[internalSymbol->name] = internalSymbol;
472 }
473 public void AddInternalSymbol(Symbol* internalSymbol)
474 {
475 AddInternalSymbol(internalSymbol, true);
476 }
477 private BinaryFile* file;
478 private List<UniquePtr<Symbol>> symbols;
479 private List<UniquePtr<Symbol>> internalSymbols;
480 private Map<string, Symbol*> table;
481 private Map<string, Symbol*> internalTable;
482 private Map<ulong, Symbol*> addressMap;
483 private Map<byte, Symbol*> registerMap;
484 private Map<ulong, Symbol*> valueMap;
485 }
486 }