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 = 0udata = 1upool = 2ustack = 3uunknown = 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_ = 0uexternal = 1uonce = 2uremove = 3uundefined = 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.registercmsx.machine.regAXax);
197                 AddSymbol(ax);
198                 Symbol* bx = new Symbol();
199                 bx->name = "bx";
200                 bx->value = Value(Value.Flag.registercmsx.machine.regBXbx);
201                 AddSymbol(bx);
202                 Symbol* cx = new Symbol();
203                 cx->name = "cx";
204                 cx->value = Value(Value.Flag.registercmsx.machine.regCXcx);
205                 AddSymbol(cx);
206                 Symbol* dx = new Symbol();
207                 dx->name = "dx";
208                 dx->value = Value(Value.Flag.registercmsx.machine.regDXdx);
209                 AddSymbol(dx);
210                 Symbol* ex = new Symbol();
211                 ex->name = "ex";
212                 ex->value = Value(Value.Flag.registercmsx.machine.regEXex);
213                 AddSymbol(ex);
214                 Symbol* sp = new Symbol();
215                 sp->name = "sp";
216                 sp->value = Value(Value.Flag.registercmsx.machine.regSPsp);
217                 AddSymbol(sp);
218                 Symbol* fp = new Symbol();
219                 fp->name = "fp";
220                 fp->value = Value(Value.Flag.registercmsx.machine.regFPfp);
221                 AddSymbol(fp);
222                 Symbol* ix = new Symbol();
223                 ix->name = "ix";
224                 ix->value = Value(Value.Flag.registercmsx.machine.regIXix);
225                 AddSymbol(ix);
226                 Symbol* rA = new Symbol();
227                 rA->name = "rA";
228                 rA->value = Value(Value.Flag.purecmsx.machine.Registers.rArA);
229                 AddSymbol(rA);
230                 Symbol* rB = new Symbol();
231                 rB->name = "rB";
232                 rB->value = Value(Value.Flag.purecmsx.machine.Registers.rBrB);
233                 AddSymbol(rB);
234                 Symbol* rC = new Symbol();
235                 rC->name = "rC";
236                 rC->value = Value(Value.Flag.purecmsx.machine.Registers.rCrC);
237                 AddSymbol(rC);
238                 Symbol* rD = new Symbol();
239                 rD->name = "rD";
240                 rD->value = Value(Value.Flag.purecmsx.machine.Registers.rDrD);
241                 AddSymbol(rD);
242                 Symbol* rE = new Symbol();
243                 rE->name = "rE";
244                 rE->value = Value(Value.Flag.purecmsx.machine.Registers.rErE);
245                 AddSymbol(rE);
246                 Symbol* rF = new Symbol();
247                 rF->name = "rF";
248                 rF->value = Value(Value.Flag.purecmsx.machine.Registers.rFrF);
249                 AddSymbol(rF);
250                 Symbol* rG = new Symbol();
251                 rG->name = "rG";
252                 rG->value = Value(Value.Flag.purecmsx.machine.Registers.rGrG);
253                 AddSymbol(rG);
254                 Symbol* rH = new Symbol();
255                 rH->name = "rH";
256                 rH->value = Value(Value.Flag.purecmsx.machine.Registers.rHrH);
257                 AddSymbol(rH);
258                 Symbol* rI = new Symbol();
259                 rI->name = "rI";
260                 rI->value = Value(Value.Flag.purecmsx.machine.Registers.rIrI);
261                 AddSymbol(rI);
262                 Symbol* rJ = new Symbol();
263                 rJ->name = "rJ";
264                 rJ->value = Value(Value.Flag.purecmsx.machine.Registers.rJrJ);
265                 AddSymbol(rJ);
266                 Symbol* rK = new Symbol();
267                 rK->name = "rK";
268                 rK->value = Value(Value.Flag.purecmsx.machine.Registers.rKrK);
269                 AddSymbol(rK);
270                 Symbol* rL = new Symbol();
271                 rL->name = "rL";
272                 rL->value = Value(Value.Flag.purecmsx.machine.Registers.rLrL);
273                 AddSymbol(rL);
274                 Symbol* rM = new Symbol();
275                 rM->name = "rM";
276                 rM->value = Value(Value.Flag.purecmsx.machine.Registers.rMrM);
277                 AddSymbol(rM);
278                 Symbol* rN = new Symbol();
279                 rN->name = "rN";
280                 rN->value = Value(Value.Flag.purecmsx.machine.Registers.rNrN);
281                 AddSymbol(rN);
282                 Symbol* rO = new Symbol();
283                 rO->name = "rO";
284                 rO->value = Value(Value.Flag.purecmsx.machine.Registers.rOrO);
285                 AddSymbol(rO);
286                 Symbol* rP = new Symbol();
287                 rP->name = "rP";
288                 rP->value = Value(Value.Flag.purecmsx.machine.Registers.rPrP);
289                 AddSymbol(rP);
290                 Symbol* rQ = new Symbol();
291                 rQ->name = "rQ";
292                 rQ->value = Value(Value.Flag.purecmsx.machine.Registers.rQrQ);
293                 AddSymbol(rQ);
294                 Symbol* rR = new Symbol();
295                 rR->name = "rR";
296                 rR->value = Value(Value.Flag.purecmsx.machine.Registers.rRrR);
297                 AddSymbol(rR);
298                 Symbol* rS = new Symbol();
299                 rS->name = "rS";
300                 rS->value = Value(Value.Flag.purecmsx.machine.Registers.rSrS);
301                 AddSymbol(rS);
302                 Symbol* rT = new Symbol();
303                 rT->name = "rT";
304                 rT->value = Value(Value.Flag.purecmsx.machine.Registers.rTrT);
305                 AddSymbol(rT);
306                 Symbol* rU = new Symbol();
307                 rU->name = "rU";
308                 rU->value = Value(Value.Flag.purecmsx.machine.Registers.rUrU);
309                 AddSymbol(rU);
310                 Symbol* rV = new Symbol();
311                 rV->name = "rV";
312                 rV->value = Value(Value.Flag.purecmsx.machine.Registers.rVrV);
313                 AddSymbol(rV);
314                 Symbol* rW = new Symbol();
315                 rW->name = "rW";
316                 rW->value = Value(Value.Flag.purecmsx.machine.Registers.rWrW);
317                 AddSymbol(rW);
318                 Symbol* rX = new Symbol();
319                 rX->name = "rX";
320                 rX->value = Value(Value.Flag.purecmsx.machine.Registers.rXrX);
321                 AddSymbol(rX);
322                 Symbol* rY = new Symbol();
323                 rY->name = "rY";
324                 rY->value = Value(Value.Flag.purecmsx.machine.Registers.rYrY);
325                 AddSymbol(rY);
326                 Symbol* rZ = new Symbol();
327                 rZ->name = "rZ";
328                 rZ->value = Value(Value.Flag.purecmsx.machine.Registers.rZrZ);
329                 AddSymbol(rZ);
330                 Symbol* rBB = new Symbol();
331                 rBB->name = "rBB";
332                 rBB->value = Value(Value.Flag.purecmsx.machine.Registers.rBBrBB);
333                 AddSymbol(rBB);
334                 Symbol* rTT = new Symbol();
335                 rTT->name = "rTT";
336                 rTT->value = Value(Value.Flag.purecmsx.machine.Registers.rTTrTT);
337                 AddSymbol(rTT);
338                 Symbol* rWW = new Symbol();
339                 rWW->name = "rWW";
340                 rWW->value = Value(Value.Flag.purecmsx.machine.Registers.rWWrWW);
341                 AddSymbol(rWW);
342                 Symbol* rXX = new Symbol();
343                 rXX->name = "rXX";
344                 rXX->value = Value(Value.Flag.purecmsx.machine.Registers.rXXrXX);
345                 AddSymbol(rXX);
346                 Symbol* rYY = new Symbol();
347                 rYY->name = "rYY";
348                 rYY->value = Value(Value.Flag.purecmsx.machine.Registers.rYYrYY);
349                 AddSymbol(rYY);
350                 Symbol* rZZ = new Symbol();
351                 rZZ->name = "rZZ";
352                 rZZ->value = Value(Value.Flag.purecmsx.machine.Registers.rZZrZZ);
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<stringSymbol*>.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<stringSymbol*>.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<ulongSymbol*>.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<ulongSymbol*>.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<byteSymbol*>.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* symbolbool 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(symboltrue);
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* internalSymbolbool 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(internalSymboltrue);
476         }
477         private BinaryFile* file;
478         private List<UniquePtr<Symbol>> symbols;
479         private List<UniquePtr<Symbol>> internalSymbols;
480         private Map<stringSymbol*> table;
481         private Map<stringSymbol*> internalTable;
482         private Map<ulongSymbol*> addressMap;
483         private Map<byteSymbol*> registerMap;
484         private Map<ulongSymbol*> valueMap;
485     }
486 }