1 using System;
   2 using System.IO;
   3 using System.Collections;
   4 using cmsx.machine;
   5 
   6 namespace cmsx.object
   7 {
   8     public const char objectFileVersion_1 = '1';
   9     public const char objectFileVersion_2 = '2';
  10     public const char objectFileVersion_3 = '3';
  11     public const char libraryFileVersion_1 = '1';
  12     public const char libraryFileVersion_2 = '2';
  13     public const char libraryFileVersion_3 = '3';
  14     public const char executableFileVersion_1 = '1';
  15     public const char executableFileVersion_2 = '2';
  16     public const char executableFileVersion_3 = '3';
  17 
  18     public const char currentObjectFileVersion = objectFileVersion_3;
  19     public const char currentLibraryFileVersion = libraryFileVersion_3;
  20     public const char currentExecutableFileVersion = executableFileVersion_3;
  21 
  22     public const ulong fileBlockSize = 4096u;
  23 
  24     public string ObjectFileVersionStr()
  25     {
  26         return string(currentObjectFileVersion);
  27     }
  28 
  29     public string LibraryFileVersionStr()
  30     {
  31         return string(currentLibraryFileVersion);
  32     }
  33 
  34     public string ExecutableFileVersionStr()
  35     {
  36         return string(currentExecutableFileVersion);
  37     }
  38 
  39     public string ReadHeaderName(const string& fileNameSystem.IO.BinaryReader& readerint length)
  40     {
  41         string result;
  42         for (int i = 0; i < length; ++i;)
  43         {
  44             int x = reader.ReadByteOrEnd();
  45             if (x == -1)
  46             {
  47                 throw Exception("unexpected end of file " + fileName + " while reading header name, length is " + ToString(length));
  48             }
  49             result.Append(cast<char>(x));
  50         }
  51         return result;
  52     }
  53 
  54     public void WriteHeaderName(System.IO.BinaryWriter& writerconst string& headerName)
  55     {
  56         for (char c : headerName)
  57         {
  58             writer.Write(c);
  59         }
  60     }
  61 
  62     public ulong ReadULong(const string& fileNameSystem.IO.BinaryReader& reader)
  63     {
  64         List<byte> b;
  65         for (int i = 0; i < 8; ++i;)
  66         {
  67             int x = reader.ReadByteOrEnd();
  68             if (x == -1)
  69             {
  70                 throw Exception("unexpected end of file " + fileName);
  71             }
  72             b.Add(cast<byte>(x));
  73         }
  74         ulong x = (cast<ulong>(b[0]) << 56u) | (cast<ulong>(b[1]) << 48u) | (cast<ulong>(b[2]) << 40u) | (cast<ulong>(b[3]) << 32u) | (cast<ulong>(b[4]) << 24u) | (cast<ulong>(b[5]) << 16u) | 
  75             (cast<ulong>(b[6]) << 8u) | cast<ulong>(b[7]);
  76         return x;
  77     }
  78 
  79     public void WriteULong(System.IO.BinaryWriter& writerulong x)
  80     {
  81         byte x0 = cast<byte>(x);
  82         x = x >> 8u;
  83         byte x1 = cast<byte>(x);
  84         x = x >> 8u;
  85         byte x2 = cast<byte>(x);
  86         x = x >> 8u;
  87         byte x3 = cast<byte>(x);
  88         x = x >> 8u;
  89         byte x4 = cast<byte>(x);
  90         x = x >> 8u;
  91         byte x5 = cast<byte>(x);
  92         x = x >> 8u;
  93         byte x6 = cast<byte>(x);
  94         x = x >> 8u;
  95         byte x7 = cast<byte>(x);
  96         x = x >> 8u;
  97         writer.Write(x7);
  98         writer.Write(x6);
  99         writer.Write(x5);
 100         writer.Write(x4);
 101         writer.Write(x3);
 102         writer.Write(x2);
 103         writer.Write(x1);
 104         writer.Write(x0);
 105     }
 106 
 107     public enum ReadOption : int
 108     {
 109         readAll = 0readHeadersOnly = 1
 110     }
 111 
 112     public UniquePtr<BinaryFile> ReadBinaryFile(System.IO.BinaryReader& readerconst string& fileNameReadOption readOption)
 113     {
 114         UniquePtr<BinaryFile> file;
 115         ulong fileOffset = cast<ulong>(reader.Tell());
 116         if (fileOffset > 0u)
 117         {
 118             fileOffset = ((fileOffset - 1u) / fileBlockSize + 1u) * fileBlockSize;
 119         }
 120         reader.Seek(cast<long>(fileOffset)Origin.seekSet);
 121         string fileHeaderName = ReadHeaderName(fileNamereader8);
 122         string headerBaseName = fileHeaderName.Substring(0fileHeaderName.Length() - 1);
 123         string fileVersion = fileHeaderName.Substring(fileHeaderName.Length() - 11);
 124         if (headerBaseName == "CMSXOBJ")
 125         {
 126             if (fileVersion == ObjectFileVersionStr())
 127             {
 128                 file.Reset(new ObjectFile(fileNamefalsefalse));
 129             }
 130             else
 131             {
 132                 throw Exception("invalid file " + fileName + " " + headerBaseName + " version " + fileVersion + " read, version " + ObjectFileVersionStr() + " expected");
 133             }
 134         }
 135         else if (headerBaseName == "CMSXLIB")
 136         {
 137             if (fileVersion == LibraryFileVersionStr())
 138             {
 139                 file.Reset(new LibraryFile(fileNamefalsefalse));
 140             }
 141             else
 142             {
 143                 throw Exception("invalid file " + fileName + " " + headerBaseName + " version " + fileVersion + " read, version " + LibraryFileVersionStr() + " expected");
 144             }
 145         }
 146         else if (headerBaseName == "CMSXEXE")
 147         {
 148             if (fileVersion == ExecutableFileVersionStr())
 149             {
 150                 file.Reset(new ExecutableFile(fileNamefalsefalse0u0u0u0u));
 151             }
 152             else
 153             {
 154                 throw Exception("invalid file " + fileName + " " + headerBaseName + " version " + fileVersion + " read, version " + ExecutableFileVersionStr() + " expected");
 155             }
 156         }
 157         else
 158         {
 159             throw Exception("invalid file " + fileName + " header '" + headerBaseName + "' not CMSXOBJ, CMSXLIB or CMSXEXE");
 160         }
 161         file->Read(readerreadOption);
 162         return file;
 163     }
 164 
 165     public UniquePtr<BinaryFile> ReadBinaryFile(System.IO.BinaryReader& readerconst string& fileName)
 166     {
 167         return ReadBinaryFile(readerfileNameReadOption.readAll);
 168     }
 169 
 170     public UniquePtr<BinaryFile> ReadBinaryFile(const string& fileName)
 171     {
 172         System.IO.BinaryReader reader = System.IO.File.OpenBinary(fileName);
 173         return ReadBinaryFile(readerfileName);
 174     }
 175 
 176     public class BinaryFileFormatter : Formatter
 177     {
 178         public nothrow BinaryFileFormatter(BinaryFile& file_) : file(file_)
 179         {
 180         }
 181         public override string FormatRegisterNumber(byte x)
 182         {
 183             Symbol* registerSymbol = file.GetSymbolTable().GetRegisterSymbol(x);
 184             if (registerSymbol != null)
 185             {
 186                 return registerSymbol->name;
 187             }
 188             else
 189             {
 190                 return base->FormatRegisterNumber(x);
 191             }
 192         }
 193         public override string GetLabel(ulong address)
 194         {
 195             Symbol* symbol = file.GetSymbolTable().GetSymbolByAddress(address);
 196             if (symbol != null)
 197             {
 198                 if (!symbol->localName.IsEmpty())
 199                 {
 200                     return symbol->localName;
 201                 }
 202                 else
 203                 {
 204                     return symbol->name;
 205                 }
 206             }
 207             else
 208             {
 209                 return string();
 210             }
 211         }
 212         private BinaryFile& file;
 213     }
 214 
 215     public class BinaryFile
 216     {
 217         public nothrow BinaryFile(const string& fileName_Section* headerSection_bool initSymbolTable) : fileName(fileName_)headerSection(headerSection_)symbolTable(thisinitSymbolTable)
 218         {
 219         }
 220         public virtual default ~BinaryFile();
 221         public virtual void Finalize()
 222         {
 223             for (const UniquePtr<Section>& section : sections)
 224             {
 225                 section->Finalize();
 226             }
 227         }
 228         public virtual void AddSection(Section* section)
 229         {
 230             section->file = this;
 231             sections.Add(UniquePtr<Section>(section));
 232         }
 233         public nothrow Section* GetHeaderSection() const
 234         {
 235             return headerSection.Get();
 236         }
 237         public virtual nothrow Section* GetCodeSection() const
 238         {
 239             return null;
 240         }
 241         public virtual nothrow Section* GetDataSection() const
 242         {
 243             return null;
 244         }
 245         public virtual nothrow Section* GetSymbolSection() const
 246         {
 247             return null;
 248         }
 249         public Section* CreateSection(const string& sectionName)
 250         {
 251             if (sectionName == "CODE")
 252             {
 253                 return new CodeSection(this);
 254             }
 255             else if (sectionName == "DATA")
 256             {
 257                 return new DataSection(this);
 258             }
 259             else if (sectionName == "SYMB")
 260             {
 261                 return new SymbolSection(this);
 262             }
 263             else if (sectionName == "LINK")
 264             {
 265                 return new LinkSection(this);
 266             }
 267             else if (sectionName == "DBUG")
 268             {
 269                 return new DebugSection(this);
 270             }
 271             else
 272             {
 273                 throw Exception("unknown section '" + sectionName + " in file " + fileName);
 274             }
 275         }
 276         public void Write()
 277         {
 278             System.IO.BinaryWriter writer = System.IO.File.CreateBinary(fileName);
 279             Write(writer);
 280         }
 281         public void WriteHeader(System.IO.BinaryWriter& writer)
 282         {
 283             WriteHeaderName(writerheaderSection->name);
 284             headerSection->Write(writer);
 285             ulong numSections = cast<ulong>(sections.Count());
 286             WriteULong(writernumSections);
 287             for (const UniquePtr<Section>& section : sections)
 288             {
 289                 WriteHeaderName(writersection->name);
 290                 writer.Write(section->fileOffset);
 291                 writer.Write(section->length);
 292             }
 293             WriteExtendedHeader(writer);
 294         }
 295         public virtual void WriteExtendedHeader(System.IO.BinaryWriter& writer)
 296         {
 297         }
 298         public void ReadHeader(System.IO.BinaryReader& reader)
 299         {
 300             headerSection->Read(reader);
 301             ulong numSections = ReadULong(fileNamereader);
 302             for (ulong i = 0u; i < numSections; ++i;)
 303             {
 304                 string sectionName = ReadHeaderName(fileNamereader4);
 305                 Section* section = CreateSection(sectionName);
 306                 section->fileOffset = reader.ReadULong();
 307                 section->length = reader.ReadULong();
 308                 AddSection(section);
 309             }
 310             ReadExtendedHeader(reader);
 311         }
 312         public virtual void ReadExtendedHeader(System.IO.BinaryReader& reader)
 313         {
 314         }
 315         public void Write(System.IO.BinaryWriter& writer)
 316         {
 317             ulong prevFileOffset = cast<ulong>(writer.Tell());
 318             if (prevFileOffset > 0u)
 319             {
 320                 prevFileOffset = ((prevFileOffset - 1u) / fileBlockSize + 1u) * fileBlockSize;
 321             }
 322             writer.Seek(cast<long>(prevFileOffset)Origin.seekSet);
 323             WriteHeader(writer);
 324             for (const UniquePtr<Section>& section : sections)
 325             {
 326                 ulong sectionFileOffset = cast<ulong>(writer.Tell());
 327                 if (sectionFileOffset > 0u)
 328                 {
 329                     sectionFileOffset = ((sectionFileOffset - 1u) / fileBlockSize + 1u) * fileBlockSize;
 330                 }
 331                 writer.Seek(cast<long>(sectionFileOffset)Origin.seekSet);
 332                 section->fileOffset = sectionFileOffset;
 333                 section->Write(writer);
 334             }
 335             ulong currentFileOffset = cast<ulong>(writer.Tell());
 336             if (currentFileOffset > 0u)
 337             {
 338                 currentFileOffset = ((currentFileOffset - 1u) / fileBlockSize + 1u) * fileBlockSize;
 339             }
 340             writer.Seek(cast<long>(prevFileOffset)Origin.seekSet);
 341             WriteHeader(writer);
 342             writer.Seek(cast<long>(currentFileOffset)Origin.seekSet);
 343             WriteExtended(writer);
 344         }
 345         public virtual void WriteExtended(System.IO.BinaryWriter& writer)
 346         {
 347         }
 348         public void Read(System.IO.BinaryReader& readerReadOption readOption)
 349         {
 350             ReadHeader(reader);
 351             if (readOption == ReadOption.readAll)
 352             {
 353                 long n = sections.Count();
 354                 for (long i = 0; i < n; ++i;)
 355                 {
 356                     Section* section = sections[i].Get();
 357                     reader.Seek(cast<long>(section->fileOffset)Origin.seekSet);
 358                     section->Read(reader);
 359                 }
 360                 ReadExtended(reader);
 361             }
 362         }
 363         public virtual void ReadExtended(System.IO.BinaryReader& reader)
 364         {
 365         }
 366         public virtual void AddSymbolsToAddressMap()
 367         {
 368         }
 369         public virtual void Dump(StreamWriter& writer)
 370         {
 371             headerSection->Dump(writer);
 372             for (const UniquePtr<Section>& section : sections)
 373             {
 374                 section->Dump(writer);
 375                 writer.WriteLine();
 376             }
 377         }
 378         public nothrow SymbolTable& GetSymbolTable()
 379         {
 380             return symbolTable;
 381         }
 382         public nothrow const string& FileName() const
 383         {
 384             return fileName;
 385         }
 386         public virtual void ReplaceLinkSection(UniquePtr<Section>& newLinkSection)
 387         {
 388             for (UniquePtr<Section>& section : sections)
 389             {
 390                 if (section.Get() is LinkSection*)
 391                 {
 392                     Swap(sectionnewLinkSection);
 393                     return;
 394                 }
 395             }
 396         }
 397         private string fileName;
 398         private UniquePtr<Section> headerSection;
 399         private List<UniquePtr<Section>> sections;
 400         private SymbolTable symbolTable;
 401     }
 402 
 403     public class ObjectFile : BinaryFile
 404     {
 405         public ObjectFile(const string& fileName_bool createSections_bool initSymbolTable) : base(fileName_new ObjectFileHeaderSection(this)initSymbolTable)
 406         {
 407             if (createSections_)
 408             {
 409                 AddSection(new CodeSection(this));
 410                 AddSection(new DataSection(this));
 411                 AddSection(new SymbolSection(this));
 412                 AddSection(new LinkSection(this));
 413                 AddSection(new DebugSection(this));
 414             }
 415         }
 416         public ObjectFile(const string& fileName_bool initSymbolTable) : this(fileName_trueinitSymbolTable)
 417         {
 418         }
 419         public override void AddSection(Section* section)
 420         {
 421             base->AddSection(section);
 422             if (section is CodeSection*)
 423             {
 424                 codeSection = section;
 425             }
 426             else if (section is DataSection*)
 427             {
 428                 dataSection = section;
 429             }
 430             else if (section is SymbolSection*)
 431             {
 432                 symbolSection = section;
 433             }
 434             else if (section is LinkSection*)
 435             {
 436                 linkSection = section;
 437             }
 438             else if (section is DebugSection*)
 439             {
 440                 debugSection = section;
 441             }
 442         }
 443         public override nothrow Section* GetCodeSection() const
 444         {
 445             return codeSection;
 446         }
 447         public override nothrow Section* GetDataSection() const
 448         {
 449             return dataSection;
 450         }
 451         public override nothrow Section* GetSymbolSection() const
 452         {
 453             return symbolSection;
 454         }
 455         public override void AddSymbolsToAddressMap()
 456         {
 457             symbolSection->AddSymbolsToAddressMap();
 458         }
 459         public override void ReplaceLinkSection(UniquePtr<Section>& newLinkSection)
 460         {
 461             linkSection = newLinkSection.Get();
 462             base->ReplaceLinkSection(newLinkSection);
 463         }
 464         public Section* codeSection;
 465         public Section* dataSection;
 466         public Section* symbolSection;
 467         public Section* linkSection;
 468         public Section* debugSection;
 469     }
 470 
 471     public class LibraryFile : BinaryFile
 472     {
 473         public LibraryFile(const string& fileName_bool createSections_bool initSymbolTable) : base(fileName_new LibraryFileHeaderSection(this)initSymbolTable)
 474         {
 475         }
 476         public LibraryFile(const string& fileName_bool initSymbolTable) : this(fileName_trueinitSymbolTable)
 477         {
 478         }
 479         public override void WriteExtendedHeader(System.IO.BinaryWriter& writer)
 480         {
 481             ulong numObjectFiles = cast<ulong>(objectFiles.Count());
 482             WriteULong(writernumObjectFiles);
 483             for (const UniquePtr<ObjectFile>& objectFile : objectFiles)
 484             {
 485                 writer.Write(objectFile->FileName());
 486             }
 487         }
 488         public override void WriteExtended(System.IO.BinaryWriter& writer)
 489         {
 490             for (const UniquePtr<ObjectFile>& objectFile : objectFiles)
 491             {
 492                 objectFile->Write(writer);
 493             }
 494         }
 495         public override void ReadExtendedHeader(System.IO.BinaryReader& reader)
 496         {
 497             ulong numObjectFiles = ReadULong(FileName()reader);
 498             for (ulong i = 0u; i < numObjectFiles; ++i;)
 499             {
 500                 string objectFileName = reader.ReadString();
 501                 objectFileNames.Add(objectFileName);
 502             }
 503         }
 504         public override void ReadExtended(System.IO.BinaryReader& reader)
 505         {
 506             long n = objectFileNames.Count();
 507             for (long i = 0u; i < n; ++i;)
 508             {
 509                 const string& objectFileName = objectFileNames[i];
 510                 UniquePtr<BinaryFile> binaryFile = ReadBinaryFile(readerobjectFileName);
 511                 if (binaryFile.Get() is ObjectFile*)
 512                 {
 513                     objectFiles.Add(UniquePtr<ObjectFile>(cast<ObjectFile*>(binaryFile.Release())));
 514                 }
 515                 else
 516                 {
 517                     throw Exception("object file expected");
 518                 }
 519             }
 520         }
 521         public override void Dump(StreamWriter& writer)
 522         {
 523             writer.WriteLine(ToString(objectFiles.Count()) + " object files:");
 524             for (UniquePtr<ObjectFile>& objectFile : objectFiles)
 525             {
 526                 writer.WriteLine(objectFile->FileName() + ":");
 527                 objectFile->Dump(writer);
 528                 writer.WriteLine();
 529             }
 530         }
 531         public List<UniquePtr<ObjectFile>> objectFiles;
 532         public List<string> objectFileNames;
 533     }
 534 
 535     public class ExecutableFile : BinaryFile
 536     {
 537         public ExecutableFile(const string& fileName_bool createSections_bool initSymbolTableulong minStackSize_ulong maxStackSize_ulong stackSizeIncrement_ulong initialPoolSize_) : 
 538             base(fileName_new ExecutableFileHeaderSection(thisminStackSize_maxStackSize_stackSizeIncrement_initialPoolSize_)initSymbolTable)
 539         {
 540             if (createSections_)
 541             {
 542                 AddSection(new CodeSection(this));
 543                 AddSection(new DataSection(this));
 544                 AddSection(new SymbolSection(this));
 545             }
 546         }
 547         public ExecutableFile(const string& fileName_bool initSymbolTableulong minStackSize_ulong maxStackSize_ulong stackSizeIncrement_ulong initialPoolSize_) : 
 548             this(fileName_trueinitSymbolTableminStackSize_maxStackSize_stackSizeIncrement_initialPoolSize_)
 549         {
 550         }
 551         public nothrow ulong MinStackSize() const
 552         {
 553             Section* headerSection = GetHeaderSection();
 554             if (headerSection is ExecutableFileHeaderSection*)
 555             {
 556                 ExecutableFileHeaderSection* executableFileHeaderSection = cast<ExecutableFileHeaderSection*>(headerSection);
 557                 return executableFileHeaderSection->minStackSize;
 558             }
 559             else
 560             {
 561                 return 0u;
 562             }
 563         }
 564         public nothrow ulong MaxStackSize() const
 565         {
 566             Section* headerSection = GetHeaderSection();
 567             if (headerSection is ExecutableFileHeaderSection*)
 568             {
 569                 ExecutableFileHeaderSection* executableFileHeaderSection = cast<ExecutableFileHeaderSection*>(headerSection);
 570                 return executableFileHeaderSection->maxStackSize;
 571             }
 572             else
 573             {
 574                 return 0u;
 575             }
 576         }
 577         public nothrow ulong StackSizeIncrement() const
 578         {
 579             Section* headerSection = GetHeaderSection();
 580             if (headerSection is ExecutableFileHeaderSection*)
 581             {
 582                 ExecutableFileHeaderSection* executableFileHeaderSection = cast<ExecutableFileHeaderSection*>(headerSection);
 583                 return executableFileHeaderSection->stackSizeIncrement;
 584             }
 585             else
 586             {
 587                 return 0u;
 588             }
 589         }
 590         public nothrow ulong InitialPoolSize() const
 591         {
 592             Section* headerSection = GetHeaderSection();
 593             if (headerSection is ExecutableFileHeaderSection*)
 594             {
 595                 ExecutableFileHeaderSection* executableFileHeaderSection = cast<ExecutableFileHeaderSection*>(headerSection);
 596                 return executableFileHeaderSection->initialPoolSize;
 597             }
 598             else
 599             {
 600                 return 0u;
 601             }
 602         }
 603         public override nothrow Section* GetCodeSection() const
 604         {
 605             return codeSection;
 606         }
 607         public override nothrow Section* GetDataSection() const
 608         {
 609             return dataSection;
 610         }
 611         public override nothrow Section* GetSymbolSection() const
 612         {
 613             return symbolSection;
 614         }
 615         public override void AddSymbolsToAddressMap()
 616         {
 617             symbolSection->AddSymbolsToAddressMap();
 618         }
 619         public override void AddSection(Section* section)
 620         {
 621             base->AddSection(section);
 622             if (section is CodeSection*)
 623             {
 624                 codeSection = section;
 625             }
 626             else if (section is DataSection*)
 627             {
 628                 dataSection = section;
 629             }
 630             else if (section is SymbolSection*)
 631             {
 632                 symbolSection = section;
 633             }
 634         }
 635         public Section* codeSection;
 636         public Section* dataSection;
 637         public Section* symbolSection;
 638     }
 639 
 640     public class Section
 641     {
 642         public nothrow Section() : file(null)name()pos(0)baseAddress(0u)length(0u)dataLength(0u)copyStartPos(0u)removeOffset(0u)fileOffset(0u)
 643         {
 644         }
 645         public nothrow Section(BinaryFile* file_const string& name_) : file(file_)name(name_)pos(0)baseAddress(0u)length(0u)dataLength(0u)copyStartPos(0u)removeOffset(0u)fileOffset(0u)
 646         {
 647         }
 648         public virtual default ~Section();
 649         public virtual void Finalize()
 650         {
 651         }
 652         public virtual void AddSymbol(Symbol* symbol)
 653         {
 654         }
 655         public virtual void AddSymbolsToAddressMap()
 656         {
 657         }
 658         public nothrow ulong Address() const
 659         {
 660             return cast<ulong>(pos);
 661         }
 662         public nothrow ulong BaseAddress() const
 663         {
 664             return baseAddress;
 665         }
 666         public nothrow void SetBaseAddress(ulong baseAddress_)
 667         {
 668             baseAddress = baseAddress_;
 669         }
 670         public nothrow ulong DataLength() const
 671         {
 672             return cast<ulong>(data.Count());
 673         }
 674         public void Write(System.IO.BinaryWriter& writer)
 675         {
 676             length = cast<ulong>(data.Count()) + 2u * 8u;
 677             dataLength = cast<ulong>(data.Count());
 678             WriteULong(writerdataLength);
 679             WriteULong(writerbaseAddress);
 680             for (byte b : data)
 681             {
 682                 writer.Write(b);
 683             }
 684             WriteExtended(writer);
 685         }
 686         public virtual void WriteExtended(System.IO.BinaryWriter& writer)
 687         {
 688         }
 689         public void Read(System.IO.BinaryReader& reader)
 690         {
 691             dataLength = reader.ReadULong();
 692             baseAddress = ReadULong(file->FileName()reader);
 693             for (ulong i = 0u; i < dataLength; ++i;)
 694             {
 695                 int x = reader.ReadByteOrEnd();
 696                 if (x == -1)
 697                 {
 698                     throw Exception("unexpected end of " + name + " section  of file '" + file->FileName() + "': dataLength=" + ToString(dataLength) + ", " + ToString(i) + " bytes read.");
 699                 }
 700                 data.Add(cast<byte>(x));
 701             }
 702             ReadExtended(reader);
 703         }
 704         public virtual void ReadExtended(System.IO.BinaryReader& reader)
 705         {
 706         }
 707         public virtual void Dump(StreamWriter& writer)
 708         {
 709             writer.WriteLine(name + " section");
 710             if ((this is CodeSection*) || (this is DataSection*))
 711             {
 712                 writer.WriteLine(Format("base address:"17) + " #" + ToHexString(baseAddress));
 713             }
 714             writer.WriteLine(Format("length:"17) + " #" + ToHexString(dataLength));
 715         }
 716         public nothrow int GetByte()
 717         {
 718             if (pos < data.Count())
 719             {
 720                 return data[pos++];
 721             }
 722             else
 723             {
 724                 return -1;
 725             }
 726         }
 727         public void EmitByte(byte b)
 728         {
 729             if (pos == data.Count())
 730             {
 731                 data.Add(b);
 732                 ++pos;
 733             }
 734             else if (pos < data.Count())
 735             {
 736                 data[pos++] = b;
 737             }
 738             else
 739             {
 740                 throw Exception("invalid pos for file " + file->FileName() + " " + name + " section: " + ToString(pos));
 741             }
 742         }
 743         public void EmitByte(ulong addressbyte b)
 744         {
 745             long prevPos = pos;
 746             pos = cast<long>(address);
 747             EmitByte(b);
 748             pos = prevPos;
 749         }
 750         public nothrow void EmitLongOffset(ulong addressuint longOffset)
 751         {
 752             long prevPos = pos;
 753             pos = cast<long>(address + 1u);
 754             EmitLongOffset(longOffset);
 755             pos = prevPos;
 756         }
 757         public nothrow void EmitShortOffset(ulong addressushort shortOffset)
 758         {
 759             long prevPos = pos;
 760             pos = cast<long>(address + 2u);
 761             EmitShortOffset(shortOffset);
 762             pos = prevPos;
 763         }
 764         public nothrow void EmitULong(ulong addressulong x)
 765         {
 766             long prevPos = pos;
 767             pos = cast<long>(address);
 768             EmitULong(x);
 769             pos = prevPos;
 770         }
 771         public string GetString()
 772         {
 773             string result;
 774             int x = GetByte();
 775             while (x != -1 && x != 0)
 776             {
 777                 result.Append(cast<char>(x));
 778                 x = GetByte();
 779             }
 780             if (x == -1)
 781             {
 782                 throw Exception("unexpected end of " + name + " section of file " + file->FileName());
 783             }
 784             return result;
 785         }
 786         public void EmitString(const string& s)
 787         {
 788             for (char c : s)
 789             {
 790                 EmitByte(cast<byte>(c));
 791             }
 792             EmitByte(0u);
 793         }
 794         public void EmitShortOffset(ushort offset)
 795         {
 796             byte b0 = cast<byte>(offset);
 797             offset = offset >> 8u;
 798             byte b1 = cast<byte>(offset);
 799             offset = offset >> 8u;
 800             #assert(offset == 0u);
 801             EmitByte(b1);
 802             EmitByte(b0);
 803         }
 804         public void EmitLongOffset(uint offset)
 805         {
 806             byte b0 = cast<byte>(offset);
 807             offset = offset >> 8u;
 808             byte b1 = cast<byte>(offset);
 809             offset = offset >> 8u;
 810             byte b2 = cast<byte>(offset);
 811             offset = offset >> 8u;
 812             EmitByte(b2);
 813             EmitByte(b1);
 814             EmitByte(b0);
 815         }
 816         public uint GetUInt()
 817         {
 818             List<byte> b;
 819             for (int i = 0; i < 4; ++i;)
 820             {
 821                 int x = GetByte();
 822                 if (x == -1)
 823                 {
 824                     throw Exception("unexpected end of " + name + " section of file " + file->FileName());
 825                 }
 826                 b.Add(cast<byte>(x));
 827             }
 828             uint u = (cast<uint>(b[0]) << 24u) | (cast<uint>(b[1]) << 16u) | (cast<uint>(b[2]) << 8u) | cast<uint>(b[3]);
 829             return u;
 830         }
 831         public void EmitUInt(uint x)
 832         {
 833             byte b0 = cast<byte>(x);
 834             x = x >> 8u;
 835             byte b1 = cast<byte>(x);
 836             x = x >> 8u;
 837             byte b2 = cast<byte>(x);
 838             x = x >> 8u;
 839             byte b3 = cast<byte>(x);
 840             x = x >> 8u;
 841             #assert(x == 0u);
 842             EmitByte(b3);
 843             EmitByte(b2);
 844             EmitByte(b1);
 845             EmitByte(b0);
 846         }
 847         public void EmitUInt(ulong addressuint x)
 848         {
 849             long prevPos = pos;
 850             pos = cast<long>(address);
 851             EmitUInt(x);
 852             pos = prevPos;
 853         }
 854         public ulong GetULong()
 855         {
 856             List<byte> b;
 857             for (int i = 0; i < 8; ++i;)
 858             {
 859                 int x = GetByte();
 860                 if (x == -1)
 861                 {
 862                     throw Exception("unexpected end of " + name + " section of file " + file->FileName());
 863                 }
 864                 b.Add(cast<byte>(x));
 865             }
 866             ulong u = (cast<ulong>(b[0]) << 56u) | (cast<ulong>(b[1]) << 48u) | (cast<ulong>(b[2]) << 40u) | (cast<ulong>(b[3]) << 32u) | (cast<ulong>(b[4]) << 24u) | (cast<ulong>(b[5]) << 16u) | 
 867                 (cast<ulong>(b[6]) << 8u) | cast<ulong>(b[7]);
 868             return u;
 869         }
 870         public void EmitULong(ulong x)
 871         {
 872             byte b0 = cast<byte>(x);
 873             x = x >> 8u;
 874             byte b1 = cast<byte>(x);
 875             x = x >> 8u;
 876             byte b2 = cast<byte>(x);
 877             x = x >> 8u;
 878             byte b3 = cast<byte>(x);
 879             x = x >> 8u;
 880             byte b4 = cast<byte>(x);
 881             x = x >> 8u;
 882             byte b5 = cast<byte>(x);
 883             x = x >> 8u;
 884             byte b6 = cast<byte>(x);
 885             x = x >> 8u;
 886             byte b7 = cast<byte>(x);
 887             x = x >> 8u;
 888             #assert(x == 0u);
 889             EmitByte(b7);
 890             EmitByte(b6);
 891             EmitByte(b5);
 892             EmitByte(b4);
 893             EmitByte(b3);
 894             EmitByte(b2);
 895             EmitByte(b1);
 896             EmitByte(b0);
 897         }
 898         public void Align(ulong alignment)
 899         {
 900             ulong at = Address();
 901             ulong a = at & (alignment - 1u);
 902             if (a != 0u)
 903             {
 904                 ulong offset = alignment - a;
 905                 for (ulong i = 0u; i < offset; ++i;)
 906                 {
 907                     EmitByte(0u);
 908                 }
 909             }
 910         }
 911         public BinaryFile* file;
 912         public string name;
 913         public List<byte> data;
 914         public long pos;
 915         public ulong baseAddress;
 916         public ulong length;
 917         public ulong dataLength;
 918         public ulong copyStartPos;
 919         public ulong removeOffset;
 920         public Section* copyTargetSection;
 921         public ulong fileOffset;
 922     }
 923 
 924     public class ObjectFileHeaderSection : Section
 925     {
 926         public nothrow ObjectFileHeaderSection(BinaryFile* file_) : base(file_"CMSXOBJ" + ObjectFileVersionStr())
 927         {
 928         }
 929         public override void Dump(StreamWriter& writer)
 930         {
 931         }
 932     }
 933 
 934     public class LibraryFileHeaderSection : Section
 935     {
 936         public nothrow LibraryFileHeaderSection(BinaryFile* file_) : base(file_"CMSXLIB" + LibraryFileVersionStr())
 937         {
 938         }
 939         public override void Dump(StreamWriter& writer)
 940         {
 941         }
 942     }
 943 
 944     public class ExecutableFileHeaderSection : Section
 945     {
 946         public nothrow ExecutableFileHeaderSection(BinaryFile* file_ulong minStackSize_ulong maxStackSize_ulong stackSizeIncrement_ulong initialPoolSize_) : 
 947             base(file_"CMSXEXE" + ExecutableFileVersionStr())minStackSize(minStackSize_)maxStackSize(maxStackSize_)stackSizeIncrement(stackSizeIncrement_)initialPoolSize(initialPoolSize_)
 948         {
 949         }
 950         public override void WriteExtended(System.IO.BinaryWriter& writer)
 951         {
 952             WriteULong(writerminStackSize);
 953             WriteULong(writermaxStackSize);
 954             WriteULong(writerstackSizeIncrement);
 955             WriteULong(writerinitialPoolSize);
 956             length = length + 4u * 8u;
 957         }
 958         public override void ReadExtended(System.IO.BinaryReader& reader)
 959         {
 960             minStackSize = ReadULong(file->FileName()reader);
 961             maxStackSize = ReadULong(file->FileName()reader);
 962             stackSizeIncrement = ReadULong(file->FileName()reader);
 963             initialPoolSize = ReadULong(file->FileName()reader);
 964         }
 965         public override void Dump(StreamWriter& writer)
 966         {
 967             writer.WriteLine("HEADER section");
 968             writer.WriteLine(Format("min stack size:"17) + " #" + ToHexString(minStackSize));
 969             writer.WriteLine(Format("max stack size:"17) + " #" + ToHexString(maxStackSize));
 970             writer.WriteLine(Format("initial pool size:"17) + " #" + ToHexString(initialPoolSize));
 971             writer.WriteLine();
 972         }
 973         public ulong minStackSize;
 974         public ulong maxStackSize;
 975         public ulong stackSizeIncrement;
 976         public ulong initialPoolSize;
 977     }
 978 
 979     public class CodeSection : Section
 980     {
 981         public nothrow CodeSection(BinaryFile* file_) : base(file_"CODE")
 982         {
 983         }
 984         public override void Dump(StreamWriter& writer)
 985         {
 986             if (file == null)
 987             {
 988                 throw Exception("file is null");
 989             }
 990             BinaryFileFormatter formatter(*file);
 991             base->Dump(writer);
 992             pos = 0;
 993             ulong address = 0u;
 994             int opc = GetByte();
 995             while (opc != -1)
 996             {
 997                 byte opCode = cast<byte>(opc);
 998                 int x = GetByte();
 999                 int y = GetByte();
1000                 int z = GetByte();
1001                 if (x != -1 && y != -1 && z != -1)
1002                 {
1003                     byte xx = cast<byte>(x);
1004                     byte yy = cast<byte>(y);
1005                     byte zz = cast<byte>(z);
1006                     string instructionLine = FormatInstruction(BaseAddress() + addressopCodexxyyzzformatter);
1007                     writer.WriteLine(instructionLine);
1008                 }
1009                 else
1010                 {
1011                     throw Exception("unexpected end of data of file " + file->FileName());
1012                 }
1013                 address = address + 4u;
1014                 opc = GetByte();
1015             }
1016         }
1017     }
1018 
1019     public class DataSection : Section
1020     {
1021         public nothrow DataSection(BinaryFile* file_) : base(file_"DATA")
1022         {
1023             SetBaseAddress(cmsx.machine.dataSegmentBaseAddress);
1024         }
1025         public override void AddSymbol(Symbol* symbol)
1026         {
1027             symbols.Add(symbol);
1028         }
1029         public override void WriteExtended(System.IO.BinaryWriter& writer)
1030         {
1031             long n = symbols.Count();
1032             writer.Write(cast<ulong>(n));
1033             for (long i = 0; i < n; ++i;)
1034             {
1035                 Symbol* symbol = symbols[i];
1036                 ulong startOffset = symbol->start;
1037                 writer.Write(startOffset);
1038             }
1039             length = length + (cast<ulong>(n) + 1u) * 8u;
1040         }
1041         public override void ReadExtended(System.IO.BinaryReader& reader)
1042         {
1043             ulong n = reader.ReadULong();
1044             for (ulong i = 0u; i < n; ++i;)
1045             {
1046                 ulong startOffset = reader.ReadULong();
1047                 startOffsets.Add(startOffset);
1048             }
1049         }
1050         public override void Dump(StreamWriter& writer)
1051         {
1052             if (file == null)
1053             {
1054                 throw Exception("file is null");
1055             }
1056             Symbol* debugInfoSymbol = file->GetSymbolTable().GetSymbol("@debug_info");
1057             long maxPos = MaxValue<long>();
1058             if (debugInfoSymbol != null)
1059             {
1060                 maxPos = cast<long>(debugInfoSymbol->value.value);
1061             }
1062             BinaryFileFormatter formatter(*file);
1063             base->Dump(writer);
1064             ulong startOffset = cast<ulong>(-1);
1065             long startOffsetIndex = 0;
1066             if (!startOffsets.IsEmpty())
1067             {
1068                 startOffset = startOffsets[0];
1069                 ++startOffsetIndex;
1070                 if (startOffsetIndex < startOffsets.Count())
1071                 {
1072                     startOffset = startOffsets[startOffsetIndex];
1073                     ++startOffsetIndex;
1074                 }
1075                 else
1076                 {
1077                     startOffset = cast<ulong>(-1);
1078                 }
1079             }
1080             pos = 0;
1081             ulong address = 0u;
1082             ulong baseAddr = BaseAddress() + address;
1083             string currentBytes;
1084             string currentChars;
1085             string currentHeader = "#" + ToHexString(baseAddr) + " " + Format(formatter.GetLabel(baseAddr)80FormatWidth.min);
1086             int b = GetByte();
1087             while (b != -1)
1088             {
1089                 if (pos >= maxPos)
1090                 {
1091                     break;
1092                 }
1093                 baseAddr = BaseAddress() + address;
1094                 if (baseAddr == startOffset)
1095                 {
1096                     writer.WriteLine(currentHeader + " " + currentBytes + " " + currentChars);
1097                     currentBytes.Clear();
1098                     currentChars.Clear();
1099                     currentHeader = "#" + ToHexString(baseAddr) + " " + Format(formatter.GetLabel(baseAddr)80FormatWidth.min);
1100                     if (startOffsetIndex < startOffsets.Count())
1101                     {
1102                         startOffset = startOffsets[startOffsetIndex];
1103                         ++startOffsetIndex;
1104                     }
1105                     else
1106                     {
1107                         startOffset = cast<ulong>(-1);
1108                     }
1109                 }
1110                 if (!currentBytes.IsEmpty())
1111                 {
1112                     currentBytes.Append(" ");
1113                 }
1114                 currentBytes.Append(ToHexString(cast<byte>(b)));
1115                 char c = '.';
1116                 if (b >= 32u && b < 127u)
1117                 {
1118                     c = cast<char>(b);
1119                 }
1120                 currentChars.Append(c);
1121                 b = GetByte();
1122                 ++address;
1123             }
1124             if (!currentBytes.IsEmpty())
1125             {
1126                 writer.WriteLine(currentHeader + " " + currentBytes + " " + currentChars);
1127             }
1128             writer.WriteLine();
1129             if (debugInfoSymbol != null)
1130             {
1131                 writer.WriteLine("DEBUG INFO");
1132                 writer.WriteLine("start:  " + ToHexString(debugInfoSymbol->start));
1133                 writer.WriteLine("length: " + ToHexString(debugInfoSymbol->length));
1134                 writer.WriteLine();
1135                 Symbol* functionTableSymbol = file->GetSymbolTable().GetSymbol("@function_table");
1136                 DumpFunctionTable(functionTableSymbolwriter);
1137             }
1138         }
1139         public override void Finalize()
1140         {
1141             Align(8u);
1142         }
1143         private void DumpFunctionTable(Symbol* functionTableSymbolStreamWriter& writer)
1144         {
1145             writer.WriteLine("FUNCTION TABLE");
1146             writer.WriteLine("start:  " + ToHexString(functionTableSymbol->start));
1147             writer.WriteLine("length: " + ToHexString(functionTableSymbol->length));
1148             writer.WriteLine();
1149             long prevPos = pos;
1150             long functionTableStartPos = cast<long>(functionTableSymbol->value.value);
1151             long functionTableEndPos = functionTableStartPos + cast<long>(functionTableSymbol->length);
1152             pos = functionTableStartPos;
1153             while (pos < functionTableEndPos)
1154             {
1155                 DumpFunctionTableEntry(writer);
1156             }
1157         }
1158         private void DumpFunctionTableEntry(StreamWriter& writer)
1159         {
1160             writer.WriteLine("FUNCTION TABLE ENTRY");
1161             ulong start = GetULong();
1162             Symbol* functionSymbol = file->GetSymbolTable().GetSymbolByAddress(start);
1163             ulong length = GetULong();
1164             ulong mangledNameAddress = GetULong();
1165             ulong fullNameAddress = GetULong();
1166             ulong sourceFileNameAddress = GetULong();
1167             ulong lineNumberTableStartAddress = GetULong();
1168             ulong lineNumberTableEndAddress = GetULong();
1169             ulong exceptionTableAddress = GetULong();
1170             writer.Write("                start: " + ToHexString(start));
1171             if (functionSymbol != null)
1172             {
1173                 writer.Write(" " + functionSymbol->name);
1174             }
1175             writer.WriteLine();
1176             writer.WriteLine("               length: " + ToHexString(length));
1177             writer.WriteLine("          mangledName: " + ToHexString(mangledNameAddress) + " " + GetString(mangledNameAddress));
1178             writer.WriteLine("             fullName: " + ToHexString(fullNameAddress) + " " + GetString(fullNameAddress));
1179             writer.WriteLine("       sourceFileName: " + ToHexString(sourceFileNameAddress) + " " + GetString(sourceFileNameAddress));
1180             writer.WriteLine(" lineNumberTableStart: " + ToHexString(lineNumberTableStartAddress));
1181             writer.WriteLine("   lineNumberTableEnd: " + ToHexString(lineNumberTableEndAddress));
1182             writer.Write(    "      lineNumberTable: ");
1183             DumpLineNumberTable(lineNumberTableStartAddresslineNumberTableEndAddresswriter);
1184             writer.WriteLine();
1185             writer.WriteLine("exceptionTableAddress: " + ToHexString(exceptionTableAddress));
1186             if (exceptionTableAddress != 0u)
1187             {
1188                 DumpExceptionTable(exceptionTableAddresswriter);
1189             }
1190             writer.WriteLine();
1191         }
1192         private string GetString(ulong address)
1193         {
1194             long prevPos = pos;
1195             pos = cast<long>(address);
1196             string s = GetString();
1197             pos = prevPos;
1198             return s;
1199         }
1200         private void DumpLineNumberTable(ulong lineNumberTableStartAddressulong lineNumberTableEndAddressStreamWriter& writer)
1201         {
1202             if (lineNumberTableStartAddress == lineNumberTableEndAddress) return;
1203             writer.Write("[");
1204             long prevPos = pos;
1205             pos = cast<long>(lineNumberTableStartAddress);
1206             bool first = true;
1207             while (pos < cast<long>(lineNumberTableEndAddress))
1208             {
1209                 if (first)
1210                 {
1211                     first = false;
1212                 }
1213                 else
1214                 {
1215                     writer.Write(" : ");
1216                 }
1217                 uint offset = GetUInt();
1218                 uint line = GetUInt();
1219                 writer.Write("offset: " + ToString(offset) + ", line: " + ToString(line));
1220             }
1221             writer.Write("]");
1222             pos = prevPos;
1223         }
1224         private void DumpExceptionTable(ulong exceptionTableAddressStreamWriter& writer)
1225         {
1226             writer.WriteLine();
1227             writer.WriteLine("EXCEPTION TABLE " + ToHexString(exceptionTableAddress));
1228             long prevPos = pos;
1229             pos = cast<long>(exceptionTableAddress);
1230             ulong frameSize = GetUInt();
1231             writer.WriteLine("frame size: " + ToString(frameSize));
1232             ulong numDispatchTableEntries = GetUInt();
1233             writer.WriteLine();
1234             writer.WriteLine("DISPATCH TABLE (" + ToString(numDispatchTableEntries) + " entries)");
1235             Set<ulong> exceptionBlockTableAddressSet;
1236             for (ulong i = 0u; i < numDispatchTableEntries; ++i;)
1237             {
1238                 uint offset = GetUInt();
1239                 uint length = GetUInt();
1240                 ulong exceptionBlockTableAddress = GetULong();
1241                 writer.WriteLine(ToString(i) + ": offset: " + ToString(offset) + ", length: " + ToString(length) + ", exception block table address: " + ToHexString(exceptionBlockTableAddress));
1242                 exceptionBlockTableAddressSet.Insert(exceptionBlockTableAddress);
1243             }
1244             while (!exceptionBlockTableAddressSet.IsEmpty())
1245             {
1246                 Set<ulong> newExceptionBlockTableAddressSet;
1247                 for (ulong exceptionBlockTableAddress : exceptionBlockTableAddressSet)
1248                 {
1249                     writer.WriteLine();
1250                     writer.WriteLine("EXCEPTION BLOCK TABLE " + ToHexString(exceptionBlockTableAddress));
1251                     long prevPos = pos;
1252                     pos = cast<long>(exceptionBlockTableAddress);
1253                     while (true)
1254                     {
1255                         ulong discriminator = GetULong();
1256                         if (discriminator == handlerBlockDiscriminator)
1257                         {
1258                             writer.WriteLine();
1259                             writer.WriteLine("HANDLER BLOCK");
1260                             ulong catchedClassId = GetULong();
1261                             ulong handlerAddress = GetULong();
1262                             writer.WriteLine("catched class id:   " + ToString(catchedClassId));
1263                             writer.Write("handlerAddress:     " + ToHexString(handlerAddress) + " ");
1264                             Symbol* handlerSymbol = file->GetSymbolTable().GetSymbolByAddress(handlerAddress);
1265                             if (handlerSymbol != null)
1266                             {
1267                                 writer.Write(handlerSymbol->name);
1268                             }
1269                             writer.WriteLine();
1270                         }
1271                         else if (discriminator == cleanupBlockDiscriminator)
1272                         {
1273                             writer.WriteLine();
1274                             writer.WriteLine("CLEANUP BLOCK");
1275                             ulong cleanupAddress = GetULong();
1276                             ulong  parentTableAddress = GetULong();
1277                             writer.Write("cleanup address:    " + ToHexString(cleanupAddress) + " ");
1278                             Symbol* cleanupSymbol = file->GetSymbolTable().GetSymbolByAddress(cleanupAddress);
1279                             if (cleanupSymbol != null)
1280                             {
1281                                 writer.Write(cleanupSymbol->name);
1282                             }
1283                             writer.WriteLine();
1284                             writer.WriteLine("parent table addr:  " + ToHexString(parentTableAddress));
1285                             if (parentTableAddress != 0u)
1286                             {
1287                                 newExceptionBlockTableAddressSet.Insert(parentTableAddress);
1288                             }
1289                         }
1290                         else if (discriminator == endBlockDiscriminator)
1291                         {
1292                             break;
1293                         }
1294                         else
1295                         {
1296                             throw Exception("unknonwn exception block table discriminator " + ToString(discriminator));
1297                         }
1298                     }
1299                     pos = prevPos;
1300                 }
1301                 Swap(exceptionBlockTableAddressSetnewExceptionBlockTableAddressSet);
1302             }
1303             pos = prevPos;
1304         }
1305         private List<Symbol*> symbols;
1306         private List<ulong> startOffsets;
1307     }
1308 
1309     public class SymbolSection : Section
1310     {
1311         public nothrow SymbolSection(BinaryFile* file_) : base(file_"SYMB")
1312         {
1313         }
1314         public override void Finalize()
1315         {
1316             if (file is ExecutableFile*)
1317             {
1318                 SymbolTable& symbolTable = file->GetSymbolTable();
1319                 for (const UniquePtr<Symbol>& symbol : symbolTable.Symbols())
1320                 {
1321                     if (symbol->section != null)
1322                     {
1323                         if (symbol->section is CodeSection*)
1324                         {
1325                             symbol->value.value = symbol->start - file->GetCodeSection()->BaseAddress();
1326                         }
1327                         else if (symbol->section is DataSection*)
1328                         {
1329                             symbol->value.value = symbol->start - file->GetDataSection()->BaseAddress();
1330                         }
1331                     }
1332                 }
1333             }
1334             EmitSymbols();
1335         }
1336         public Segment GetSegment()
1337         {
1338             int segment = GetByte();
1339             if (segment == -1)
1340             {
1341                 throw Exception("unexpected end of " + name + " section of file " + file->FileName());
1342             }
1343             return cast<Segment>(cast<byte>(segment));
1344         }
1345         public Linkage GetLinkage()
1346         {
1347             int linkage = GetByte();
1348             if (linkage == -1)
1349             {
1350                 throw Exception("unexpected end of " + name + " section of file " + file->FileName());
1351             }
1352             return cast<Linkage>(cast<byte>(linkage));
1353         }
1354         public Value.Flag GetValueFlags()
1355         {
1356             int flags = GetByte();
1357             if (flags == -1)
1358             {
1359                 throw Exception("unexpected end of " + name + " section of file " + file->FileName());
1360             }
1361             return cast<Value.Flag>(cast<byte>(flags));
1362         }
1363         public Value GetValue()
1364         {
1365             Value.Flag flags = GetValueFlags();
1366             ulong v = GetULong();
1367             Value value(flagsvnull);
1368             return value;
1369         }
1370         public override void ReadExtended(System.IO.BinaryReader& reader)
1371         {
1372             pos = 0;
1373             ulong numSymbols = GetULong();
1374             for (ulong i = 0u; i < numSymbols; ++i;)
1375             {
1376                 uint symbolIndex = GetUInt();
1377                 string symbolName = GetString();
1378                 string symbolLocalName = GetString();
1379                 Segment segment = GetSegment();
1380                 Section* section = null;
1381                 if (segment == Segment.text)
1382                 {
1383                     section = file->GetCodeSection();
1384                 }
1385                 else if (segment == Segment.data)
1386                 {
1387                     section = file->GetDataSection();
1388                 }
1389                 Linkage linkage = GetLinkage();
1390                 Value value = GetValue();
1391                 ulong start = GetULong();
1392                 ulong length = GetULong();
1393                 Symbol* symbol = new Symbol();
1394                 symbol->index = cast<int>(symbolIndex);
1395                 symbol->name = symbolName;
1396                 symbol->localName = symbolLocalName;
1397                 symbol->segment = segment;
1398                 symbol->linkage = linkage;
1399                 symbol->value = value;
1400                 symbol->start = start;
1401                 symbol->length = length;
1402                 symbol->section = section;
1403                 uint parentIndex = GetUInt();
1404                 symbol->parentIndex = cast<int>(parentIndex);
1405                 uint linkStart = GetUInt();
1406                 uint linkEnd = GetUInt();
1407                 symbol->linkStart = cast<int>(linkStart);
1408                 symbol->linkEnd = cast<int>(linkEnd);
1409                 int alignment = GetByte();
1410                 symbol->alignment = cast<byte>(alignment);
1411                 file->GetSymbolTable().AddSymbol(symbolfalse);
1412             }
1413             ulong numInternalSymbols = GetULong();
1414             for (ulong i = 0u; i < numInternalSymbols; ++i;)
1415             {
1416                 uint symbolIndex = GetUInt();
1417                 string symbolName = GetString();
1418                 string symbolLocalName = GetString();
1419                 Segment segment = GetSegment();
1420                 Section* section = null;
1421                 if (segment == Segment.text)
1422                 {
1423                     section = file->GetCodeSection();
1424                 }
1425                 else if (segment == Segment.data)
1426                 {
1427                     section = file->GetDataSection();
1428                 }
1429                 Linkage linkage = GetLinkage();
1430                 Value value = GetValue();
1431                 ulong start = GetULong();
1432                 ulong length = GetULong();
1433                 Symbol* symbol = new Symbol();
1434                 symbol->index = cast<int>(symbolIndex);
1435                 symbol->name = symbolName;
1436                 symbol->localName = symbolLocalName;
1437                 symbol->segment = segment;
1438                 symbol->linkage = linkage;
1439                 symbol->value = value;
1440                 symbol->start = start;
1441                 symbol->length = length;
1442                 symbol->section = section;
1443                 uint parentIndex = GetUInt();
1444                 symbol->parentIndex = cast<int>(parentIndex);
1445                 uint linkStart = GetUInt();
1446                 uint linkEnd = GetUInt();
1447                 symbol->linkStart = cast<int>(linkStart);
1448                 symbol->linkEnd = cast<int>(linkEnd);
1449                 int alignment = GetByte();
1450                 symbol->alignment = cast<byte>(alignment);
1451                 file->GetSymbolTable().AddInternalSymbol(symbolfalse);
1452             }
1453         }
1454         public void EmitSymbols()
1455         {
1456             if (file == null)
1457             {
1458                 throw Exception("file is null");
1459             }
1460             SymbolTable& symbolTable = file->GetSymbolTable();
1461             EmitULong(cast<ulong>(symbolTable.Symbols().Count()));
1462             for (const UniquePtr<Symbol>& symbol : symbolTable.Symbols())
1463             {
1464                 EmitSymbol(symbol.Get());
1465             }
1466             EmitULong(cast<ulong>(symbolTable.InternalSymbols().Count()));
1467             for (const UniquePtr<Symbol>& symbol : symbolTable.InternalSymbols())
1468             {
1469                 EmitSymbol(symbol.Get());
1470             }
1471         }
1472         public void EmitSymbol(Symbol* symbol)
1473         {
1474             EmitUInt(cast<uint>(symbol->index));
1475             EmitString(symbol->name);
1476             EmitString(symbol->localName);
1477             EmitByte(symbol->segment);
1478             EmitByte(symbol->linkage);
1479             EmitValue(symbol->value);
1480             EmitULong(symbol->start);
1481             EmitULong(symbol->length);
1482             EmitUInt(cast<uint>(symbol->parentIndex));
1483             EmitUInt(cast<uint>(symbol->linkStart));
1484             EmitUInt(cast<uint>(symbol->linkEnd));
1485             EmitByte(symbol->alignment);
1486         }
1487         public void EmitValue(const Value& value)
1488         {
1489             EmitByte(value.flags);
1490             EmitULong(value.value);
1491         }
1492         public override void AddSymbolsToAddressMap()
1493         {
1494             SymbolTable& symbolTable = file->GetSymbolTable();
1495             for (const UniquePtr<Symbol>& symbol : symbolTable.Symbols())
1496             {
1497                 symbolTable.AddSymbolToAddressMap(symbol.Get());
1498             }
1499         }
1500         public override void Dump(StreamWriter& writer)
1501         {
1502             base->Dump(writer);
1503             SymbolTable& symbolTable = file->GetSymbolTable();
1504             for (const UniquePtr<Symbol>& symbol : symbolTable.Symbols())
1505             {
1506                 string symbolLine;
1507                 string absoluteAddress;
1508                 if (symbol->value.GetFlag(Value.Flag.pure))
1509                 {
1510                     absoluteAddress = "#" + ToHexString(symbol->start);
1511                 }
1512                 symbolLine.Append(Format(absoluteAddress17));
1513                 symbolLine.Append(" ").Append(Format(ToString(symbol->index)11));
1514                 symbolLine.Append(" ").Append(Format(symbol->name80FormatWidth.min));
1515                 symbolLine.Append(" ").Append(Format(SegmentStr(symbol->segment)7));
1516                 symbolLine.Append(" ").Append(Format(LinkageStr(symbol->linkage)9));
1517                 symbolLine.Append(" ").Append(ValueStr(symbol->value));
1518                 if (symbol->value.GetFlag(Value.Flag.function) || symbol->value.GetFlag(Value.Flag.structure))
1519                 {
1520                     symbolLine.Append(" ").Append("#").Append(ToHexString(symbol->start));
1521                     symbolLine.Append(" ").Append("#").Append(ToHexString(symbol->length));
1522                     symbolLine.Append(" ").Append(ToString(symbol->linkStart));
1523                     symbolLine.Append(" ").Append(ToString(symbol->linkEnd));
1524                 }
1525                 symbolLine.Append(" ").Append(ToString(symbol->alignment));
1526                 writer.WriteLine(symbolLine);
1527             }
1528             for (const UniquePtr<Symbol>& symbol : symbolTable.InternalSymbols())
1529             {
1530                 string symbolLine;
1531                 string absoluteAddress;
1532                 if (symbol->value.GetFlag(Value.Flag.pure))
1533                 {
1534                     absoluteAddress = "#" + ToHexString(symbol->start);
1535                 }
1536                 symbolLine.Append(Format(absoluteAddress17));
1537                 symbolLine.Append(" ").Append(Format(ToString(symbol->index)11));
1538                 symbolLine.Append(" ").Append(Format(symbol->name80FormatWidth.min));
1539                 symbolLine.Append(" ").Append(Format(SegmentStr(symbol->segment)7));
1540                 symbolLine.Append(" ").Append(Format(LinkageStr(symbol->linkage)9));
1541                 symbolLine.Append(" ").Append(ValueStr(symbol->value));
1542                 if (symbol->value.GetFlag(Value.Flag.function) || symbol->value.GetFlag(Value.Flag.structure))
1543                 {
1544                     symbolLine.Append(" ").Append("#").Append(ToHexString(symbol->start));
1545                     symbolLine.Append(" ").Append("#").Append(ToHexString(symbol->length));
1546                 }
1547                 symbolLine.Append(" ").Append(ToString(symbol->alignment));
1548                 writer.WriteLine(symbolLine);
1549             }
1550         }
1551     }
1552 
1553     public class LinkSection : Section
1554     {
1555         public nothrow LinkSection(BinaryFile* file_) : base(file_"LINK")
1556         {
1557         }
1558         public override void Dump(StreamWriter& writer)
1559         {
1560             if (file == null)
1561             {
1562                 throw Exception("file is null");
1563             }
1564             BinaryFileFormatter formatter(*file);
1565             base->Dump(writer);
1566             pos = 0;
1567             long p = pos;
1568             int x = GetByte();
1569             while (x != -1)
1570             {
1571                 LinkCode linkCode = cast<LinkCode>(cast<byte>(x));
1572                 if (linkCode == LinkCode.end)
1573                 {
1574                     break;
1575                 }
1576                 string linkLine = Format(ToString(p)5FormatWidth.minFormatJustify.right);
1577                 linkLine.Append(" ").Append(Format(LinkCodeStr(linkCode)maxLinkCodeStrLength));
1578                 switch (linkCode)
1579                 {
1580                     case LinkCode.forwardLongJump:
1581                     {
1582                         uint index = GetUInt();
1583                         linkLine.Append(" ").Append(Format(ToString(index)5FormatWidth.minFormatJustify.right));
1584                         Symbol* s = file->GetSymbolTable().GetSymbol(cast<int>(index));
1585                         linkLine.Append(" ").Append(s->name);
1586                         ulong address = GetULong();
1587                         linkLine.Append(" #").Append(ToHexString(address));
1588                         break;
1589                     }
1590                     case LinkCode.forwardShortJump:
1591                     {
1592                         uint index = GetUInt();
1593                         linkLine.Append(" ").Append(Format(ToString(index)5FormatWidth.minFormatJustify.right));
1594                         Symbol* s = file->GetSymbolTable().GetSymbol(cast<int>(index));
1595                         linkLine.Append(" ").Append(s->name);
1596                         ulong address = GetULong();
1597                         linkLine.Append(" #").Append(ToHexString(address));
1598                         break;
1599                     }
1600                     case LinkCode.absoluteAddrValue:
1601                     {
1602                         uint index = GetUInt();
1603                         linkLine.Append(" ").Append(Format(ToString(index)5FormatWidth.minFormatJustify.right));
1604                         Symbol* s = file->GetSymbolTable().GetSymbol(cast<int>(index));
1605                         linkLine.Append(" ").Append(s->name);
1606                         ulong address = GetULong();
1607                         linkLine.Append(" #").Append(ToHexString(address));
1608                         break;
1609                     }
1610                     case LinkCode.farJump:
1611                     {
1612                         uint index = GetUInt();
1613                         linkLine.Append(" ").Append(Format(ToString(index)5FormatWidth.minFormatJustify.right));
1614                         Symbol* s = file->GetSymbolTable().GetSymbol(cast<int>(index));
1615                         linkLine.Append(" ").Append(s->name);
1616                         ulong address = GetULong();
1617                         linkLine.Append(" #").Append(ToHexString(address));
1618                         break;
1619                     }
1620                     case LinkCode.farOcta:
1621                     {
1622                         uint index = GetUInt();
1623                         linkLine.Append(" ").Append(Format(ToString(index)5FormatWidth.minFormatJustify.right));
1624                         Symbol* s = file->GetSymbolTable().GetSymbol(cast<int>(index));
1625                         linkLine.Append(" ").Append(s->name);
1626                         ulong address = GetULong();
1627                         linkLine.Append(" #").Append(ToHexString(address));
1628                         break;
1629                     }
1630                     case LinkCode.clsid:
1631                     {
1632                         ulong address = GetULong();
1633                         linkLine.Append(" #").Append(ToHexString(address));
1634                         ulong typeId1 = GetULong();
1635                         ulong typeId2 = GetULong();
1636                         Uuid typeId(typeId1typeId2);
1637                         linkLine.Append(" #").Append(ToString(typeId));
1638                         break;
1639                     }
1640                 }
1641                 writer.WriteLine(linkLine);
1642                 p = pos;
1643                 x = GetByte();
1644             }
1645         }
1646         public override void Finalize()
1647         {
1648             EmitByte(LinkCode.end);
1649         }
1650     }
1651 
1652     public class DebugSection : Section
1653     {
1654         public nothrow DebugSection(BinaryFile* file_) : base(file_"DBUG")
1655         {
1656         }
1657         public override void Dump(StreamWriter& writer)
1658         {
1659             BinaryFileFormatter formatter(*file);
1660             base->Dump(writer);
1661             pos = 0;
1662             int x = GetByte();
1663             while (x != -1)
1664             {
1665                 DebugRecordCode debugRecordCode = cast<DebugRecordCode>(cast<byte>(x));
1666                 if (debugRecordCode == DebugRecordCode.end)
1667                 {
1668                     break;
1669                 }
1670                 string debugLine = Format(DebugRecordCodeStr(debugRecordCode)maxDebugCodeStrLength);
1671                 if (debugRecordCode == DebugRecordCode.fileInfo)
1672                 {
1673                     string sourceFileName = GetString();
1674                     uint sourceFileNameId = GetUInt();
1675                     debugLine.Append(" ").Append(sourceFileName).Append(" ").Append(ToString(sourceFileNameId));
1676                 }
1677                 else if (debugRecordCode == DebugRecordCode.functionInfo)
1678                 {
1679                     uint functionSymbolIndex = GetUInt();
1680                     string functionFullName = GetString();
1681                     uint sourceFileNameId = GetUInt();
1682                     uint frameSize = GetUInt();
1683                     debugLine.Append(" ").Append(ToString(functionSymbolIndex)).Append(' ').Append(functionFullName).Append(' ').Append(ToString(sourceFileNameId)).Append(' ').Append(ToString(frameSize));
1684                 }
1685                 else if (debugRecordCode == DebugRecordCode.startFunc)
1686                 {
1687                     uint functionSymbolIndex = GetUInt();
1688                     Symbol* functionSymbol = file->GetSymbolTable().GetSymbol(cast<int>(functionSymbolIndex));
1689                     debugLine.Append(" ").Append(ToString(functionSymbolIndex)).Append(' ').Append(functionSymbol->name);
1690                 }
1691                 else if (debugRecordCode == DebugRecordCode.endFunc)
1692                 {
1693                     uint functionSymbolIndex = GetUInt();
1694                     Symbol* functionSymbol = file->GetSymbolTable().GetSymbol(cast<int>(functionSymbolIndex));
1695                     debugLine.Append(" ").Append(ToString(functionSymbolIndex)).Append(' ').Append(functionSymbol->name);
1696                 }
1697                 else if (debugRecordCode == DebugRecordCode.lineInfo)
1698                 {
1699                     uint offset = GetUInt();
1700                     uint line = GetUInt();
1701                     debugLine.Append(" ").Append(ToString(offset)).Append(' ').Append(ToString(line));
1702                 }
1703                 else if (debugRecordCode == DebugRecordCode.beginTry)
1704                 {
1705                     uint tryBlockId = GetUInt();
1706                     uint parentTryBlockId = GetUInt();
1707                     uint offset = GetUInt();
1708                     debugLine.Append(" ").Append(ToString(tryBlockId)).Append(' ').Append(ToString(parentTryBlockId)).Append(' ').Append(ToString(offset));
1709                 }
1710                 else if (debugRecordCode == DebugRecordCode.endTry)
1711                 {
1712                     uint tryBlockId = GetUInt();
1713                     uint offset = GetUInt();
1714                     debugLine.Append(" ").Append(ToString(tryBlockId)).Append(' ').Append(ToString(offset));
1715                 }
1716                 else if (debugRecordCode == DebugRecordCode.catch_)
1717                 {
1718                     uint catchBlockId = GetUInt();
1719                     uint tryBlockId = GetUInt();
1720                     ulong catchTypeId1 = GetULong();
1721                     ulong catchTypeId2 = GetULong();
1722                     Uuid catchedTypeId(catchTypeId1catchTypeId2);
1723                     debugLine.Append(" ").Append(ToString(catchBlockId)).Append(' ').Append(ToString(tryBlockId)).Append(' ').Append(ToString(catchedTypeId));
1724                 }
1725                 else if (debugRecordCode == DebugRecordCode.beginCleanup)
1726                 {
1727                     uint cleanupBlockId = GetUInt();
1728                     uint tryBlockId = GetUInt();
1729                     uint offset = GetUInt();
1730                     debugLine.Append(" ").Append(ToString(cleanupBlockId)).Append(' ').Append(ToString(cast<int>(tryBlockId))).Append(' ').Append(ToString(offset));
1731                 }
1732                 else if (debugRecordCode == DebugRecordCode.endCleanup)
1733                 {
1734                     uint cleanupBlockId = GetUInt();
1735                     uint offset = GetUInt();
1736                     debugLine.Append(" ").Append(ToString(cleanupBlockId)).Append(' ').Append(' ').Append(ToString(offset));
1737                 }
1738                 else
1739                 {
1740                     throw Exception("unknown debug record code " + ToString(debugRecordCode));
1741                 }
1742                 writer.WriteLine(debugLine);
1743                 x = GetByte();
1744             }
1745         }
1746         public void EmitFunctionInfo(const FunctionInfo& functionInfo)
1747         {
1748             EmitByte(cast<byte>(DebugRecordCode.functionInfo));
1749             EmitUInt(functionInfo.functionSymbolIndex);
1750             EmitString(functionInfo.fullName);
1751             EmitUInt(functionInfo.sourceFileNameId);
1752             EmitUInt(functionInfo.frameSize);
1753         }
1754         public void EmitLineInfo(const LineInfo& lineInfo)
1755         {
1756             EmitByte(cast<byte>(DebugRecordCode.lineInfo));
1757             EmitUInt(lineInfo.offset);
1758             EmitUInt(lineInfo.lineNumber);
1759         }
1760         public void EmitSourceFileName(const string& sourceFileNameuint sourceFileNameId)
1761         {
1762             EmitByte(cast<byte>(DebugRecordCode.fileInfo));
1763             EmitString(sourceFileName);
1764             EmitUInt(sourceFileNameId);
1765         }
1766         public void EmitStartFunc(uint functionSymbolIndex)
1767         {
1768             EmitByte(cast<byte>(DebugRecordCode.startFunc));
1769             EmitUInt(functionSymbolIndex);
1770         }
1771         public void EmitEndFunc(uint functionSymbolIndex)
1772         {
1773             EmitByte(cast<byte>(DebugRecordCode.endFunc));
1774             EmitUInt(functionSymbolIndex);
1775         }
1776         public void EmitBeginTry(uint tryBlockIduint parentTryBlockIduint offset)
1777         {
1778             EmitByte(cast<byte>(DebugRecordCode.beginTry));
1779             EmitUInt(tryBlockId);
1780             EmitUInt(parentTryBlockId);
1781             EmitUInt(offset);
1782         }
1783         public void EmitEndTry(uint tryBlockIduint offset)
1784         {
1785             EmitByte(cast<byte>(DebugRecordCode.endTry));
1786             EmitUInt(tryBlockId);
1787             EmitUInt(offset);
1788         }
1789         public void EmitCatch(uint catchBlockIduint tryBlockIdulong catchedTypeId1ulong catchedTypeId2)
1790         {
1791             EmitByte(cast<byte>(DebugRecordCode.catch_));
1792             EmitUInt(catchBlockId);
1793             EmitUInt(tryBlockId);
1794             EmitULong(catchedTypeId1);
1795             EmitULong(catchedTypeId2);
1796         }
1797         public void EmitBeginCleanup(uint cleanupBlockIduint tryBlockIduint offset)
1798         {
1799             EmitByte(cast<byte>(DebugRecordCode.beginCleanup));
1800             EmitUInt(cleanupBlockId);
1801             EmitUInt(tryBlockId);
1802             EmitUInt(offset);
1803         }
1804         public void EmitEndCleanup(uint cleanupBlockIduint offset)
1805         {
1806             EmitByte(cast<byte>(DebugRecordCode.endCleanup));
1807             EmitUInt(cleanupBlockId);
1808             EmitUInt(offset);
1809         }
1810         public override void Finalize()
1811         {
1812             EmitByte(DebugRecordCode.end);
1813         }
1814     }
1815 }