1 using System; 2 using System.IO; 3 using System.Collections; 4 using System.Text; 5 6 namespace PEAPI { 7 8 /**************************************************************************/ 9 /// <summary> 10 /// Image for a PEFile 11 /// File Structure 12 /// DOS Header (128 bytes) 13 /// PE Signature ("PE\0\0") 14 /// PEFileHeader (20 bytes) 15 /// PEOptionalHeader (224 bytes) 16 /// SectionHeaders (40 bytes * NumSections) 17 /// 18 /// Sections .text (always present - contains metadata) 19 /// .sdata (contains any initialised data in the file - may not be present) 20 /// (for ilams /debug this contains the Debug table) 21 /// .reloc (always present - in pure CIL only has one fixup) 22 /// others??? c# produces .rsrc section containing a Resource Table 23 /// 24 /// .text layout 25 /// IAT (single entry 8 bytes for pure CIL) 26 /// CLIHeader (72 bytes) 27 /// CIL instructions for all methods (variable size) 28 /// MetaData 29 /// Root (20 bytes + UTF-8 Version String + quad align padding) 30 /// StreamHeaders (8 bytes + null terminated name string + quad align padding) 31 /// Streams 32 /// #~ (always present - holds metadata tables) 33 /// #Strings (always present - holds identifier strings) 34 /// #US (Userstring heap) 35 /// #Blob (signature blobs) 36 /// #GUID (guids for assemblies or Modules) 37 /// ImportTable (40 bytes) 38 /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files) 39 /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes) 40 /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes) 41 /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text) 42 /// 43 /// #~ stream structure 44 /// Header (24 bytes) 45 /// Rows (4 bytes * numTables) 46 /// Tables 47 /// </summary> 48 internal class FileImage : BinaryWriter { 49 50 internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}; 51 internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 52 0x0000000000FF0000, 0x00000000FF000000, 53 0x000000FF00000000, 0x0000FF0000000000, 54 0x00FF000000000000, 0xFF00000000000000 }; 55 internal readonly static uint nibble0Mask = 0x0000000F; 56 internal readonly static uint nibble1Mask = 0x000000F0; 57 58 private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00, 59 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00, 60 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 61 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 62 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 63 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 64 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 65 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00, 66 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd, 67 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68, 68 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72, 69 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f, 70 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e, 71 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20, 72 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a, 73 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 74 0x50,0x45,0x00,0x00}; 75 private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields 78 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 81 }; 82 83 private static readonly uint minFileAlign = 0x200; 84 private static readonly uint maxFileAlign = 0x1000; 85 private static readonly uint fileHeaderSize = 0x178; 86 private static readonly uint sectionHeaderSize = 40; 87 private static readonly uint SectionAlignment = 0x2000; 88 private static readonly uint ImageBase = 0x400000; 89 private static readonly uint ImportTableSize = 40; 90 private static readonly uint IATSize = 8; 91 private static readonly uint CLIHeaderSize = 72; 92 private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY 93 // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000 94 private static readonly uint StrongNameSignatureSize = 128; 95 private bool reserveStrongNameSignatureSpace = false; 96 97 private static readonly uint relocFlags = 0x42000040; 98 private static readonly ushort exeCharacteristics = 0x010E; 99 private static readonly ushort dllCharacteristics = 0x210E; 100 // section names are all 8 bytes 101 private static readonly string textName = ".text\0\0\0"; 102 private static readonly string sdataName = ".sdata\0\0"; 103 private static readonly string relocName = ".reloc\0\0"; 104 private static readonly string rsrcName = ".rsrc\0\0\0"; 105 private static readonly string exeHintNameTable = "\0\0_CorExeMain\0"; 106 private static readonly string dllHintNameTable = "\0\0_CorDllMain\0"; 107 private static readonly string runtimeEngineName = "mscoree.dll\0\0"; 108 109 private Section text, sdata; 110 static readonly Section rsrc = null; 111 ArrayList data; 112 BinaryWriter reloc = new BinaryWriter(new MemoryStream()); 113 uint dateStamp = 0; 114 DateTime origin = new DateTime(1970,1,1); 115 uint numSections = 2; // always have .text and .reloc sections 116 internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode 117 internal long stackReserve = 0x100000; // default is 1Mb 118 internal uint fileAlign = minFileAlign; 119 uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0; 120 uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset; 121 uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding; 122 uint resourcesSize, resourcesOffset; 123 uint strongNameSigOffset; 124 uint importTableOffset, importLookupTableOffset, totalImportTableSize; 125 MetaData metaData; 126 char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable; 127 bool doDLL, largeStrings, largeGUID, largeUS, largeBlob; 128 ushort characteristics; 129 FileImage(bool makeDLL, string fileName)130 internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create)) 131 { 132 InitFileImage(makeDLL); 133 TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin); 134 dateStamp = Convert.ToUInt32(tmp.TotalSeconds); 135 } 136 FileImage(bool makeDLL, Stream str)137 internal FileImage(bool makeDLL, Stream str) : base(str) 138 { 139 InitFileImage(makeDLL); 140 TimeSpan tmp = DateTime.Now.Subtract(origin); 141 dateStamp = Convert.ToUInt32(tmp.TotalSeconds); 142 } 143 InitFileImage(bool makeDLL)144 private void InitFileImage(bool makeDLL) 145 { 146 doDLL = makeDLL; 147 if (doDLL) { 148 hintNameTable = dllHintNameTable.ToCharArray(); 149 characteristics = dllCharacteristics; 150 } else { 151 hintNameTable = exeHintNameTable.ToCharArray(); 152 characteristics = exeCharacteristics; 153 } 154 text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ 155 // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ 156 metaData = new MetaData(this); 157 } 158 GetMetaData()159 internal MetaData GetMetaData() 160 { 161 return metaData; 162 } 163 GetNextSectStart(uint rva, uint tide)164 private uint GetNextSectStart(uint rva, uint tide) 165 { 166 uint c = tide / SectionAlignment; 167 if ((tide % SectionAlignment) != 0) 168 c++; 169 return rva + (c * SectionAlignment); 170 } 171 BuildTextSection()172 private void BuildTextSection() 173 { 174 // .text layout 175 // IAT (single entry 8 bytes for pure CIL) 176 // CLIHeader (72 bytes) 177 // CIL instructions for all methods (variable size) 178 // MetaData 179 // ImportTable (40 bytes) 180 // ImportLookupTable(8 bytes) (same as IAT for standard CIL files) 181 // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes) 182 // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes) 183 // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text) 184 metaData.BuildMetaData(IATSize + CLIHeaderSize); 185 metaDataOffset = IATSize + CLIHeaderSize; 186 // Console.WriteLine("Code starts at " + metaDataOffset); 187 metaDataOffset += metaData.CodeSize(); 188 // resourcesStart = 189 resourcesOffset = metaDataOffset + metaData.Size (); 190 resourcesSize = metaData.GetResourcesSize (); 191 if (reserveStrongNameSignatureSpace) { 192 strongNameSigOffset = resourcesOffset + resourcesSize; 193 // fixUps = RVA for vtable 194 importTableOffset = strongNameSigOffset + StrongNameSignatureSize; 195 } else { 196 strongNameSigOffset = 0; 197 // fixUps = RVA for vtable 198 importTableOffset = resourcesOffset + resourcesSize; 199 } 200 importTablePadding = NumToAlign(importTableOffset,16); 201 importTableOffset += importTablePadding; 202 importLookupTableOffset = importTableOffset + ImportTableSize; 203 hintNameTableOffset = importLookupTableOffset + IATSize; 204 runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length; 205 entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length; 206 totalImportTableSize = entryPointOffset - importTableOffset; 207 // Console.WriteLine("total import table size = " + totalImportTableSize); 208 // Console.WriteLine("entrypoint offset = " + entryPointOffset); 209 entryPointPadding = NumToAlign(entryPointOffset,4) + 2; 210 entryPointOffset += entryPointPadding; 211 text.AddReloc(entryPointOffset+2); 212 text.IncTide(entryPointOffset + 6); 213 //if (text.Tide() < fileAlign) fileAlign = minFileAlign; 214 text.SetSize(NumToAlign(text.Tide(),fileAlign)); 215 // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding()); 216 // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset)); 217 // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset)); 218 // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset)); 219 // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset)); 220 // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset)); 221 // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset)); 222 // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding)); 223 224 } 225 BuildRelocSection()226 internal void BuildRelocSection() 227 { 228 text.DoRelocs(reloc); 229 if (sdata != null) sdata.DoRelocs(reloc); 230 if (rsrc != null) rsrc.DoRelocs(reloc); 231 relocTide = (uint)reloc.Seek(0,SeekOrigin.Current); 232 relocPadding = NumToAlign(relocTide,fileAlign); 233 relocSize = relocTide + relocPadding; 234 imageSize = relocRVA + SectionAlignment; 235 initDataSize += relocSize; 236 } 237 CalcOffsets()238 private void CalcOffsets() 239 { 240 if (sdata != null) 241 numSections++; 242 if (rsrc != null) 243 numSections++; 244 headerSize = fileHeaderSize + (numSections * sectionHeaderSize); 245 headerPadding = NumToAlign(headerSize,fileAlign); 246 headerSize += headerPadding; 247 uint offset = headerSize; 248 uint rva = SectionAlignment; 249 text.SetOffset(offset); 250 text.SetRVA(rva); 251 offset += text.Size(); 252 rva = GetNextSectStart(rva,text.Tide()); 253 // Console.WriteLine("headerSize = " + headerSize); 254 // Console.WriteLine("headerPadding = " + headerPadding); 255 // Console.WriteLine("textOffset = " + Hex.Int(text.Offset())); 256 if (sdata != null) { 257 sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign)); 258 sdata.SetOffset(offset); 259 sdata.SetRVA(rva); 260 offset += sdata.Size(); 261 rva = GetNextSectStart(rva,sdata.Tide()); 262 initDataSize += sdata.Size(); 263 } 264 if (rsrc != null) { 265 rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign)); 266 rsrc.SetOffset(offset); 267 rsrc.SetRVA(rva); 268 offset += rsrc.Size(); 269 rva = GetNextSectStart(rva,rsrc.Tide()); 270 initDataSize += rsrc.Size(); 271 } 272 relocOffset = offset; 273 relocRVA = rva; 274 } 275 MakeFile()276 internal void MakeFile() 277 { 278 if (doDLL) hintNameTable = dllHintNameTable.ToCharArray(); 279 else hintNameTable = exeHintNameTable.ToCharArray(); 280 BuildTextSection(); 281 CalcOffsets(); 282 BuildRelocSection(); 283 // now write it out 284 WriteHeader(); 285 WriteSections(); 286 Flush(); 287 Close(); 288 } 289 WriteHeader()290 private void WriteHeader() 291 { 292 Write(DOSHeader); 293 // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current)); 294 WritePEHeader(); 295 // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current))); 296 text.WriteHeader(this,relocRVA); 297 if (sdata != null) sdata.WriteHeader(this,relocRVA); 298 if (rsrc != null) rsrc.WriteHeader(this,relocRVA); 299 // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current)); 300 WriteRelocSectionHeader(); 301 // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current)); 302 WriteZeros(headerPadding); 303 } 304 WriteSections()305 private void WriteSections() 306 { 307 // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current)); 308 WriteTextSection(); 309 if (sdata != null) WriteSDataSection(); 310 if (rsrc != null) WriteRsrcSection(); 311 WriteRelocSection(); 312 } 313 WriteIAT()314 private void WriteIAT() 315 { 316 Write(text.RVA() + hintNameTableOffset); 317 Write(0); 318 } 319 WriteImportTables()320 private void WriteImportTables() 321 { 322 // Import Table 323 WriteZeros(importTablePadding); 324 // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current))); 325 Write(importLookupTableOffset + text.RVA()); 326 WriteZeros(8); 327 Write(runtimeEngineOffset + text.RVA()); 328 Write(text.RVA()); // IAT is at the beginning of the text section 329 WriteZeros(20); 330 // Import Lookup Table 331 WriteIAT(); // lookup table and IAT are the same 332 // Hint/Name Table 333 // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current))); 334 Write(hintNameTable); 335 Write(runtimeEngineName.ToCharArray()); 336 } 337 WriteTextSection()338 private void WriteTextSection() 339 { 340 WriteIAT(); 341 WriteCLIHeader(); 342 // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current))); 343 metaData.WriteByteCodes(this); 344 // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current))); 345 largeStrings = metaData.LargeStringsIndex(); 346 largeGUID = metaData.LargeGUIDIndex(); 347 largeUS = metaData.LargeUSIndex(); 348 largeBlob = metaData.LargeBlobIndex(); 349 metaData.WriteMetaData(this); 350 metaData.WriteResources (this); 351 if (reserveStrongNameSignatureSpace) { 352 WriteZeros(StrongNameSignatureSize); 353 } 354 WriteImportTables(); 355 WriteZeros(entryPointPadding); 356 Write((ushort)0x25FF); 357 Write(ImageBase + text.RVA()); 358 WriteZeros(text.Padding()); 359 } 360 WriteCLIHeader()361 private void WriteCLIHeader() 362 { 363 Write(CLIHeaderSize); // Cb 364 Write((short)2); // Major runtime version 365 Write((short)0); // Minor runtime version 366 Write(text.RVA() + metaDataOffset); 367 Write(metaData.Size()); 368 Write(runtimeFlags); 369 Write(entryPointToken); 370 if (resourcesSize > 0) { 371 Write (text.RVA () + resourcesOffset); 372 Write (resourcesSize); 373 } else { 374 WriteZeros (8); 375 } 376 // Strong Name Signature (RVA, size) 377 if (reserveStrongNameSignatureSpace) { 378 Write(text.RVA() + strongNameSigOffset); 379 Write(StrongNameSignatureSize); 380 } else { 381 WriteZeros(8); 382 } 383 WriteZeros(8); // CodeManagerTable 384 WriteZeros(8); // VTableFixups NYI 385 WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader 386 } 387 WriteSDataSection()388 private void WriteSDataSection() 389 { 390 long size = sdata.Size (); 391 long start = BaseStream.Position; 392 for (int i=0; i < data.Count; i++) { 393 ((DataConstant)data[i]).Write(this); 394 } 395 while (BaseStream.Position < (start + size)) 396 Write ((byte) 0); 397 } 398 WriteRsrcSection()399 private void WriteRsrcSection() 400 { 401 } 402 WriteRelocSection()403 private void WriteRelocSection() 404 { 405 // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset); 406 MemoryStream str = (MemoryStream)reloc.BaseStream; 407 Write(str.ToArray()); 408 WriteZeros(NumToAlign((uint)str.Position,fileAlign)); 409 } 410 SetEntryPoint(uint entryPoint)411 internal void SetEntryPoint(uint entryPoint) 412 { 413 entryPointToken = entryPoint; 414 } 415 AddInitData(DataConstant cVal)416 internal void AddInitData(DataConstant cVal) 417 { 418 if (sdata == null) { 419 sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE 420 data = new ArrayList(); 421 } 422 data.Add(cVal); 423 cVal.DataOffset = sdata.Tide(); 424 sdata.IncTide(cVal.GetSize()); 425 } 426 WriteZeros(uint numZeros)427 internal void WriteZeros(uint numZeros) 428 { 429 for (int i=0; i < numZeros; i++) { 430 Write((byte)0); 431 } 432 } 433 WritePEHeader()434 internal void WritePEHeader() 435 { 436 Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??) 437 Write((ushort)numSections); 438 Write(dateStamp); 439 WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files) 440 Write((ushort)0x00E0); // Size of Optional Header 441 Write(characteristics); 442 // PE Optional Header 443 Write((ushort)0x010B); // Magic 444 Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7 445 Write((byte)0x0); // LMinor 446 Write(text.Size()); 447 Write(initDataSize); 448 Write(0); // Check other sections here!! 449 Write(text.RVA() + entryPointOffset); 450 Write(text.RVA()); 451 uint dataBase = 0; 452 if (sdata != null) dataBase = sdata.RVA(); 453 else if (rsrc != null) dataBase = rsrc.RVA(); 454 else dataBase = relocRVA; 455 Write(dataBase); 456 Write(ImageBase); 457 Write(SectionAlignment); 458 Write(fileAlign); 459 Write((ushort)0x04); // OS Major 460 WriteZeros(6); // OS Minor, User Major, User Minor 461 Write((ushort)0x04); // SubSys Major 462 WriteZeros(6); // SybSys Minor, Reserved 463 Write(imageSize); 464 Write(headerSize); 465 Write((int)0); // File Checksum 466 Write((ushort)subSys); 467 Write((short)0); // DLL Flags 468 Write((uint)stackReserve); // Stack Reserve Size 469 Write((uint)0x1000); // Stack Commit Size 470 Write((uint)0x100000); // Heap Reserve Size 471 Write((uint)0x1000); // Heap Commit Size 472 Write(0); // Loader Flags 473 Write(0x10); // Number of Data Directories 474 WriteZeros(8); // Export Table 475 Write(importTableOffset + text.RVA()); 476 Write(totalImportTableSize); 477 WriteZeros(24); // Resource, Exception and Certificate Tables 478 Write(relocRVA); 479 Write(relocTide); 480 WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables 481 Write(text.RVA()); // IATRVA - IAT is at start of .text Section 482 Write(IATSize); 483 WriteZeros(8); // Delay Import Descriptor 484 Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT 485 Write(CLIHeaderSize); 486 WriteZeros(8); // Reserved 487 } 488 WriteRelocSectionHeader()489 internal void WriteRelocSectionHeader() 490 { 491 Write(relocName.ToCharArray()); 492 Write(relocTide); 493 Write(relocRVA); 494 Write(relocSize); 495 Write(relocOffset); 496 WriteZeros(12); 497 Write(relocFlags); 498 } 499 Align(MemoryStream str, int val)500 private void Align (MemoryStream str, int val) 501 { 502 if ((str.Position % val) != 0) { 503 for (int i=val - (int)(str.Position % val); i > 0; i--) { 504 str.WriteByte(0); 505 } 506 } 507 } 508 Align(uint val, uint alignVal)509 private uint Align(uint val, uint alignVal) 510 { 511 if ((val % alignVal) != 0) { 512 val += alignVal - (val % alignVal); 513 } 514 return val; 515 } 516 NumToAlign(uint val, uint alignVal)517 private uint NumToAlign(uint val, uint alignVal) 518 { 519 if ((val % alignVal) == 0) return 0; 520 return alignVal - (val % alignVal); 521 } 522 StringsIndex(uint ix)523 internal void StringsIndex(uint ix) 524 { 525 if (largeStrings) Write(ix); 526 else Write((ushort)ix); 527 } 528 GUIDIndex(uint ix)529 internal void GUIDIndex(uint ix) 530 { 531 if (largeGUID) Write(ix); 532 else Write((ushort)ix); 533 } 534 USIndex(uint ix)535 internal void USIndex(uint ix) 536 { 537 if (largeUS) Write(ix); 538 else Write((ushort)ix); 539 } 540 BlobIndex(uint ix)541 internal void BlobIndex(uint ix) 542 { 543 if (largeBlob) Write(ix); 544 else Write((ushort)ix); 545 } 546 WriteIndex(MDTable tabIx,uint ix)547 internal void WriteIndex(MDTable tabIx,uint ix) 548 { 549 if (metaData.LargeIx(tabIx)) Write(ix); 550 else Write((ushort)ix); 551 } 552 WriteCodedIndex(CIx code, MetaDataElement elem)553 internal void WriteCodedIndex(CIx code, MetaDataElement elem) 554 { 555 metaData.WriteCodedIndex(code,elem,this); 556 } 557 WriteCodeRVA(uint offs)558 internal void WriteCodeRVA(uint offs) 559 { 560 Write(text.RVA() + offs); 561 } 562 WriteDataRVA(uint offs)563 internal void WriteDataRVA(uint offs) 564 { 565 Write(sdata.RVA() + offs); 566 } 567 Write3Bytes(uint val)568 internal void Write3Bytes(uint val) 569 { 570 byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16); 571 byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);; 572 byte b1 = (byte)(val & FileImage.iByteMask[0]); 573 Write(b1); 574 Write(b2); 575 Write(b3); 576 } 577 578 internal bool ReserveStrongNameSignatureSpace { 579 get { return reserveStrongNameSignatureSpace; } 580 set { reserveStrongNameSignatureSpace = value; } 581 } 582 583 } 584 585 /**************************************************************************/ 586 /// <summary> 587 /// Base class for the PEFile (starting point) 588 /// </summary> 589 public class PEFile { 590 591 private static readonly string mscorlibName = "mscorlib"; 592 private Module thisMod; 593 private ClassDef moduleClass; 594 private ArrayList resources = new ArrayList (); 595 private Assembly thisAssembly; 596 private static bool isMSCorlib; 597 private int corFlags = 1; 598 FileImage fileImage; 599 MetaData metaData; 600 601 /// <summary> 602 /// Create a new PEFile. Each PEFile is a module. 603 /// </summary> 604 /// <param name="name">module name, also used for the file name</param> 605 /// <param name="isDLL">create a .dll or .exe file</param> 606 /// <param name="hasAssembly">this file is an assembly and 607 /// will contain the assembly manifest. The assembly name is the 608 /// same as the module name</param> PEFile(string name, bool isDLL, bool hasAssembly)609 public PEFile(string name, bool isDLL, bool hasAssembly) 610 : this (name, null, isDLL, hasAssembly, null, null) 611 { 612 // Console.WriteLine(Hex.Byte(0x12)); 613 // Console.WriteLine(Hex.Short(0x1234)); 614 // Console.WriteLine(Hex.Int(0x12345678)); 615 } 616 617 /// <summary> 618 /// Create a new PEFile. Each PEFile is a module. 619 /// </summary> 620 /// <param name="name">module name, also used for the file name</param> 621 /// <param name="isDLL">create a .dll or .exe file</param> 622 /// <param name="hasAssembly">this file is an assembly and 623 /// will contain the assembly manifest. The assembly name is the 624 /// same as the module name</param> 625 /// <param name="outputDir">write the PEFile to this directory. If this 626 /// string is null then the output will be to the current directory</param> PEFile(string name, bool isDLL, bool hasAssembly, string outputDir)627 public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir) 628 : this (name, null, isDLL, hasAssembly, outputDir, null) 629 { 630 // Console.WriteLine(Hex.Byte(0x12)); 631 // Console.WriteLine(Hex.Short(0x1234)); 632 // Console.WriteLine(Hex.Int(0x12345678)); 633 } 634 635 /// <summary> 636 /// Create a new PEFile 637 /// </summary> 638 /// <param name="name">module name</param> 639 /// <param name="isDLL">create a .dll or .exe</param> 640 /// <param name="hasAssembly">this PEfile is an assembly and 641 /// will contain the assemly manifest. The assembly name is the 642 /// same as the module name</param> 643 /// <param name="outStream">write the PEFile to this stream instead 644 /// of to a new file</param> PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream)645 public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream) 646 : this (name, null, isDLL, hasAssembly, null, outStream) 647 { 648 } 649 PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream)650 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream) 651 : this (name, module_name, isDLL, hasAssembly, null, outStream) 652 { 653 } 654 PEFile(string name, string module_name, bool isDLL, bool hasAssembly, string outputDir, Stream outStream)655 public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, string outputDir, Stream outStream) 656 { 657 SetName (name); 658 string fname = module_name == null ? MakeFileName (outputDir, name, isDLL) : module_name; 659 if (outStream == null) 660 fileImage = new FileImage (isDLL, fname); 661 else 662 fileImage = new FileImage (isDLL, outStream); 663 664 InitPEFile (name, fname, hasAssembly); 665 } 666 SetName(string name)667 private void SetName (string name) 668 { 669 if (name == "mscorlib") 670 isMSCorlib = true; 671 } 672 InitPEFile(string name, string fName, bool hasAssembly)673 private void InitPEFile(string name, string fName, bool hasAssembly) 674 { 675 metaData = fileImage.GetMetaData(); 676 thisMod = new Module(fName,metaData); 677 if (hasAssembly) { 678 thisAssembly = new Assembly(name,metaData); 679 metaData.AddToTable(MDTable.Assembly,thisAssembly); 680 } 681 moduleClass = AddClass(TypeAttr.Private,"","<Module>"); 682 moduleClass.SpecialNoSuper(); 683 metaData.AddToTable(MDTable.Module,thisMod); 684 } 685 686 internal static bool IsMSCorlib { 687 get { return isMSCorlib; } 688 } 689 690 public ClassDef ModuleClass { 691 get { return moduleClass; } 692 } 693 694 /// <summary> 695 /// Set the subsystem (.subsystem) (Default is Windows Console mode) 696 /// </summary> 697 /// <param name="subS">subsystem value</param> SetSubSystem(SubSystem subS)698 public void SetSubSystem(SubSystem subS) 699 { 700 fileImage.subSys = subS; 701 } 702 703 /// <summary> 704 /// Set the flags (.corflags) 705 /// </summary> 706 /// <param name="flags">the flags value</param> SetCorFlags(int flags)707 public void SetCorFlags(int flags) 708 { 709 corFlags = flags; 710 } 711 SetStackReserve(long stackReserve)712 public void SetStackReserve (long stackReserve) 713 { 714 fileImage.stackReserve = stackReserve; 715 } 716 MakeFileName(string dirName, string name, bool isDLL)717 private string MakeFileName(string dirName, string name, bool isDLL) 718 { 719 string result = ""; 720 if ((dirName != null) && (dirName.CompareTo("") != 0)) { 721 result = dirName; 722 if (!dirName.EndsWith("\\")) result += "\\"; 723 } 724 result += name; 725 726 // if (isDLL) result += ".dll"; else result += ".exe"; 727 728 return result; 729 } 730 731 /// <summary> 732 /// Add an external assembly to this PEFile (.assembly extern) 733 /// </summary> 734 /// <param name="assemName">the external assembly name</param> 735 /// <returns>a descriptor for this external assembly</returns> AddExternAssembly(string assemName)736 public AssemblyRef AddExternAssembly(string assemName) 737 { 738 if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib; 739 AssemblyRef anAssem = new AssemblyRef(metaData,assemName); 740 metaData.AddToTable(MDTable.AssemblyRef,anAssem); 741 // Console.WriteLine("Adding assembly " + assemName); 742 return anAssem; 743 } 744 745 /// <summary> 746 /// Add an external module to this PEFile (.module extern) 747 /// </summary> 748 /// <param name="name">the external module name</param> 749 /// <returns>a descriptor for this external module</returns> AddExternModule(string name)750 public ModuleRef AddExternModule(string name) 751 { 752 ModuleRef modRef = new ModuleRef(metaData,name); 753 metaData.AddToTable(MDTable.ModuleRef,modRef); 754 return modRef; 755 } 756 AddExternClass(string ns, string name, TypeAttr attrs, MetaDataElement declRef)757 public ClassRef AddExternClass(string ns, string name, TypeAttr attrs, MetaDataElement declRef) 758 { 759 return new ExternClassRef (attrs, ns, name, declRef, metaData); 760 } 761 762 /// <summary> 763 /// Add a "global" method to this module 764 /// </summary> 765 /// <param name="name">method name</param> 766 /// <param name="retType">return type</param> 767 /// <param name="pars">method parameters</param> 768 /// <returns>a descriptor for this new "global" method</returns> AddMethod(string name, Param ret_param, Param [] pars)769 public MethodDef AddMethod (string name, Param ret_param, Param [] pars) 770 { 771 return moduleClass.AddMethod (name, ret_param, pars); 772 } 773 AddMethod(string name, Type retType, Param[] pars)774 public MethodDef AddMethod(string name, Type retType, Param[] pars) 775 { 776 return AddMethod (name, new Param (ParamAttr.Default, "", retType), pars); 777 } 778 779 /// <summary> 780 /// Add a "global" method to this module 781 /// </summary> 782 /// <param name="mAtts">method attributes</param> 783 /// <param name="iAtts">method implementation attributes</param> 784 /// <param name="name">method name</param> 785 /// <param name="retType">return type</param> 786 /// <param name="pars">method parameters</param> 787 /// <returns>a descriptor for this new "global" method</returns> AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Param ret_param, Param [] pars)788 public MethodDef AddMethod (MethAttr mAtts, ImplAttr iAtts, string name, Param ret_param, Param [] pars) 789 { 790 return moduleClass.AddMethod (mAtts, iAtts, name, ret_param, pars); 791 } 792 AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars)793 public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars) 794 { 795 return AddMethod (mAtts, iAtts, name, new Param (ParamAttr.Default, "", retType), pars); 796 } 797 AddMethodToTypeSpec(Type item, string name, Type retType, Type[] pars)798 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars) 799 { 800 return AddMethodToTypeSpec (item, name, retType, pars, 0); 801 } 802 AddMethodToTypeSpec(Type item, string name, Type retType, Type[] pars, int gen_param_count)803 public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars, int gen_param_count) 804 { 805 MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null, gen_param_count); 806 metaData.AddToTable (MDTable.MemberRef,meth); 807 return meth; 808 } 809 AddVarArgMethodToTypeSpec(Type item, string name, Type retType, Type[] pars, Type[] optPars)810 public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType, 811 Type[] pars, Type[] optPars) { 812 MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars, 0); 813 metaData.AddToTable(MDTable.MemberRef,meth); 814 return meth; 815 } 816 AddFieldToTypeSpec(Type item, string name, Type fType)817 public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType) 818 { 819 FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType); 820 metaData.AddToTable (MDTable.MemberRef,field); 821 return field; 822 } 823 AddMethodSpec(Method m, GenericMethodSig g_sig)824 public Method AddMethodSpec (Method m, GenericMethodSig g_sig) 825 { 826 MethodSpec ms = new MethodSpec (m, g_sig); 827 metaData.AddToTable (MDTable.MethodSpec, ms); 828 return ms; 829 } 830 831 /// <summary> 832 /// Add a "global" field to this module 833 /// </summary> 834 /// <param name="name">field name</param> 835 /// <param name="fType">field type</param> 836 /// <returns>a descriptor for this new "global" field</returns> AddField(string name, Type fType)837 public FieldDef AddField(string name, Type fType) 838 { 839 return moduleClass.AddField(name,fType); 840 } 841 842 /// <summary> 843 /// Add a "global" field to this module 844 /// </summary> 845 /// <param name="attrSet">attributes of this field</param> 846 /// <param name="name">field name</param> 847 /// <param name="fType">field type</param> 848 /// <returns>a descriptor for this new "global" field</returns> AddField(FieldAttr attrSet, string name, Type fType)849 public FieldDef AddField(FieldAttr attrSet, string name, Type fType) 850 { 851 return moduleClass.AddField(attrSet,name,fType); 852 } 853 854 /// <summary> 855 /// Add a class to this module 856 /// </summary> 857 /// <param name="attrSet">attributes of this class</param> 858 /// <param name="nsName">name space name</param> 859 /// <param name="name">class name</param> 860 /// <returns>a descriptor for this new class</returns> AddClass(TypeAttr attrSet, string nsName, string name)861 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name) 862 { 863 return AddClass (attrSet, nsName, name, null); 864 } 865 866 /// <summary> 867 /// Add a class which extends System.ValueType to this module 868 /// </summary> 869 /// <param name="attrSet">attributes of this class</param> 870 /// <param name="nsName">name space name</param> 871 /// <param name="name">class name</param> 872 /// <returns>a descriptor for this new class</returns> AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass)873 public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass) 874 { 875 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData); 876 if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name)) { 877 aClass.MakeValueClass(vClass); 878 } else { 879 if (ClassDef.IsEnum (nsName, name)) 880 aClass.SetSuper (metaData.mscorlib.ValueType ()); 881 else 882 aClass.SetSuper (metaData.mscorlib.GetSpecialSystemClass (PrimitiveType.Object)); 883 884 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass); 885 } 886 aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ()); 887 metaData.AddToTable(MDTable.TypeDef,aClass); 888 return aClass; 889 } 890 891 /// <summary> 892 /// Add a class to this module 893 /// </summary> 894 /// <param name="attrSet">attributes of this class</param> 895 /// <param name="nsName">name space name</param> 896 /// <param name="name">class name</param> 897 /// <param name="superType">super type of this class (extends)</param> 898 /// <returns>a descriptor for this new class</returns> AddClass(TypeAttr attrSet, string nsName, string name, Class superType)899 public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType) 900 { 901 ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData); 902 if (superType != null) 903 aClass.SetSuper(superType); 904 if (PEFile.IsMSCorlib) 905 metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass); 906 metaData.AddToTable(MDTable.TypeDef,aClass); 907 return aClass; 908 } 909 AddGenericClass(GenericTypeInst gti)910 public void AddGenericClass (GenericTypeInst gti) 911 { 912 metaData.AddToTable (MDTable.TypeSpec, gti); 913 } 914 AddGenericParam(GenParam param)915 public void AddGenericParam (GenParam param) 916 { 917 metaData.AddToTable (MDTable.TypeSpec, param); 918 } 919 AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint)920 public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint) 921 { 922 FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData); 923 metaData.AddToTable(MDTable.File,file); 924 return file; 925 } 926 AddPrimitiveType(PrimitiveType type)927 public PrimitiveTypeRef AddPrimitiveType (PrimitiveType type) 928 { 929 return new PrimitiveTypeRef (type, metaData); 930 } 931 932 /// <summary> 933 /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED 934 /// </summary> 935 /// <param name="mr"></param> AddManifestResource(ManifestResource mr)936 public void AddManifestResource(ManifestResource mr) 937 { 938 metaData.AddToTable(MDTable.ManifestResource,mr); 939 resources.Add (mr); 940 //mr.FixName(metaData); 941 } 942 AddCustomAttribute(Method meth, byte [] data, MetaDataElement element)943 public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element) 944 { 945 metaData.AddCustomAttribute (new CustomAttribute (element, meth, data)); 946 element.HasCustomAttr = true; 947 } 948 AddCustomAttribute(Method meth, Constant constant, MetaDataElement element)949 public void AddCustomAttribute (Method meth, Constant constant, MetaDataElement element) 950 { 951 metaData.AddCustomAttribute (new CustomAttribute (element, meth, constant)); 952 element.HasCustomAttr = true; 953 } 954 AddDeclSecurity(SecurityAction sec_action, byte [] data, MetaDataElement element)955 public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element) 956 { 957 metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data)); 958 } 959 AddDeclSecurity(SecurityAction sec_action, PEAPI.PermissionSet ps, MetaDataElement element)960 public void AddDeclSecurity (SecurityAction sec_action, PEAPI.PermissionSet ps, MetaDataElement element) 961 { 962 metaData.AddDeclSecurity (new DeclSecurity_20 (element, (ushort) sec_action, ps)); 963 } 964 965 /// <summary> 966 /// Add a managed resource from another assembly. 967 /// </summary> 968 /// <param name="resName">The name of the resource</param> 969 /// <param name="assem">The assembly where the resource is</param> 970 /// <param name="isPublic">Access for the resource</param> AddExternalManagedResource(string resName, AssemblyRef assem, uint flags)971 public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags) 972 { 973 resources.Add (new ManifestResource (resName, flags, assem)); 974 } 975 976 /// <summary> 977 /// Add a managed resource from another assembly. 978 /// </summary> 979 /// <param name="mr"></param> 980 /// <param name="isPublic"></param> AddExternalManagedResource(ManifestResource mr)981 public void AddExternalManagedResource (ManifestResource mr) 982 { 983 resources.Add (new ManifestResource (mr)); 984 } 985 /// <summary> 986 /// Find a resource 987 /// </summary> 988 /// <param name="name">The name of the resource</param> 989 /// <returns>The resource with the name "name" or null </returns> GetResource(string name)990 public ManifestResource GetResource (string name) 991 { 992 for (int i = 0; i < resources.Count; i ++) { 993 if (((ManifestResource) resources [i]).Name == name) 994 return (ManifestResource) resources [i]; 995 } 996 return null; 997 } 998 GetResources()999 public ManifestResource [] GetResources() 1000 { 1001 return (ManifestResource []) resources.ToArray (typeof (ManifestResource)); 1002 } 1003 1004 /// <summary> 1005 /// Write out the PEFile (the "bake" function) 1006 /// </summary> WritePEFile()1007 public void WritePEFile() { /* the "bake" function */ 1008 if (thisAssembly != null) 1009 fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey; 1010 fileImage.MakeFile(); 1011 } 1012 1013 /// <summary> 1014 /// Get the descriptor of this module 1015 /// </summary> 1016 /// <returns>the descriptor for this module</returns> GetThisModule()1017 public Module GetThisModule() 1018 { 1019 return thisMod; 1020 } 1021 1022 /// <summary> 1023 /// Get the descriptor for this assembly. The PEFile must have been 1024 /// created with hasAssembly = true 1025 /// </summary> 1026 /// <returns>the descriptor for this assembly</returns> GetThisAssembly()1027 public Assembly GetThisAssembly() 1028 { 1029 return thisAssembly; 1030 } 1031 1032 } 1033 1034 /**************************************************************************/ 1035 /// <summary> 1036 /// Descriptor for a Section in a PEFile eg .text, .sdata 1037 /// </summary> 1038 internal class Section { 1039 private static readonly uint relocPageSize = 4096; // 4K pages for fixups 1040 1041 char[] name; 1042 uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0; 1043 //uint relocOff = 0; 1044 uint flags = 0, padding = 0; 1045 uint[] relocs; 1046 Section(string sName, uint sFlags)1047 internal Section(string sName, uint sFlags) 1048 { 1049 name = sName.ToCharArray(); 1050 flags = sFlags; 1051 } 1052 Tide()1053 internal uint Tide() { return tide; } 1054 IncTide(uint incVal)1055 internal void IncTide(uint incVal) { tide += incVal; } 1056 Padding()1057 internal uint Padding() { return padding; } 1058 Size()1059 internal uint Size() { return size; } 1060 SetSize(uint pad)1061 internal void SetSize(uint pad) 1062 { 1063 padding = pad; 1064 size = tide + padding; 1065 } 1066 RVA()1067 internal uint RVA() { return rva; } 1068 SetRVA(uint rva)1069 internal void SetRVA(uint rva) { this.rva = rva; } 1070 Offset()1071 internal uint Offset() { return offset; } 1072 SetOffset(uint offs)1073 internal void SetOffset(uint offs) { offset = offs; } 1074 DoBlock(BinaryWriter reloc, uint page, int start, int end)1075 internal void DoBlock(BinaryWriter reloc, uint page, int start, int end) 1076 { 1077 //Console.WriteLine("rva = " + rva + " page = " + page); 1078 reloc.Write(rva + page); 1079 reloc.Write((uint)(((end-start+1)*2) + 8)); 1080 for (int j=start; j < end; j++) { 1081 //Console.WriteLine("reloc offset = " + relocs[j]); 1082 reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page))); 1083 } 1084 reloc.Write((ushort)0); 1085 } 1086 DoRelocs(BinaryWriter reloc)1087 internal void DoRelocs(BinaryWriter reloc) 1088 { 1089 if (relocTide > 0) { 1090 //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current); 1091 uint block = (relocs[0]/relocPageSize + 1) * relocPageSize; 1092 int start = 0; 1093 for (int i=1; i < relocTide; i++) { 1094 if (relocs[i] >= block) { 1095 DoBlock(reloc,block-relocPageSize,start,i); 1096 start = i; 1097 block = (relocs[i]/relocPageSize + 1) * relocPageSize; 1098 } 1099 } 1100 DoBlock(reloc,block-relocPageSize,start,(int)relocTide); 1101 } 1102 } 1103 AddReloc(uint offs)1104 internal void AddReloc(uint offs) 1105 { 1106 int pos = 0; 1107 if (relocs == null) { 1108 relocs = new uint[5]; 1109 } else { 1110 if (relocTide >= relocs.Length) { 1111 uint[] tmp = relocs; 1112 relocs = new uint[tmp.Length + 5]; 1113 for (int i=0; i < relocTide; i++) { 1114 relocs[i] = tmp[i]; 1115 } 1116 } 1117 while ((pos < relocTide) && (relocs[pos] < offs)) pos++; 1118 for (int i=pos; i < relocTide; i++) { 1119 relocs[i+1] = relocs[i]; 1120 } 1121 } 1122 relocs[pos] = offs; 1123 relocTide++; 1124 } 1125 WriteHeader(BinaryWriter output, uint relocRVA)1126 internal void WriteHeader(BinaryWriter output, uint relocRVA) 1127 { 1128 output.Write(name); 1129 output.Write(tide); 1130 output.Write(rva); 1131 output.Write(size); 1132 output.Write(offset); 1133 output.Write(0); 1134 //output.Write(relocRVA + relocOff); 1135 output.Write(0); 1136 output.Write(0); 1137 //output.Write((ushort)relocTide); 1138 //output.Write((ushort)0); 1139 output.Write(flags); 1140 } 1141 1142 } 1143 1144 public class Hex { 1145 readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7', 1146 '8','9','A','B','C','D','E','F'}; 1147 readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}; 1148 readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00, 1149 0x0000000000FF0000, 0x00000000FF000000, 1150 0x000000FF00000000, 0x0000FF0000000000, 1151 0x00FF000000000000, 0xFF00000000000000 }; 1152 readonly static uint nibble0Mask = 0x0000000F; 1153 readonly static uint nibble1Mask = 0x000000F0; 1154 Byte(int b)1155 public static String Byte(int b) 1156 { 1157 char[] str = new char[2]; 1158 uint num = (uint)b; 1159 uint b1 = num & nibble0Mask; 1160 uint b2 = (num & nibble1Mask) >> 4; 1161 str[0] = hexDigit[b2]; 1162 str[1] = hexDigit[b1]; 1163 return new String(str); 1164 } 1165 Short(int b)1166 public static String Short(int b) 1167 { 1168 char[] str = new char[4]; 1169 uint num1 = (uint)b & iByteMask[0]; 1170 uint num2 = ((uint)b & iByteMask[1]) >> 8; 1171 uint b1 = num1 & nibble0Mask; 1172 uint b2 = (num1 & nibble1Mask) >> 4; 1173 uint b3 = num2 & nibble0Mask; 1174 uint b4 = (num2 & nibble1Mask) >> 4; 1175 str[0] = hexDigit[b4]; 1176 str[1] = hexDigit[b3]; 1177 str[2] = hexDigit[b2]; 1178 str[3] = hexDigit[b1]; 1179 return new String(str); 1180 } 1181 Int(int val)1182 public static String Int(int val) 1183 { 1184 char[] str = new char[8]; 1185 uint num = (uint)val; 1186 int strIx = 7; 1187 for (int i=0; i < iByteMask.Length; i++) { 1188 uint b = num & iByteMask[i]; 1189 b >>= (i*8); 1190 uint b1 = b & nibble0Mask; 1191 uint b2 = (b & nibble1Mask) >> 4; 1192 str[strIx--] = hexDigit[b1]; 1193 str[strIx--] = hexDigit[b2]; 1194 } 1195 return new String(str); 1196 } 1197 Int(uint num)1198 public static String Int(uint num) 1199 { 1200 char[] str = new char[8]; 1201 int strIx = 7; 1202 for (int i=0; i < iByteMask.Length; i++) { 1203 uint b = num & iByteMask[i]; 1204 b >>= (i*8); 1205 uint b1 = b & nibble0Mask; 1206 uint b2 = (b & nibble1Mask) >> 4; 1207 str[strIx--] = hexDigit[b1]; 1208 str[strIx--] = hexDigit[b2]; 1209 } 1210 return new String(str); 1211 } 1212 Long(long lnum)1213 public static String Long(long lnum) 1214 { 1215 ulong num = (ulong)lnum; 1216 char[] str = new char[16]; 1217 int strIx = 15; 1218 for (int i=0; i < lByteMask.Length; i++) { 1219 ulong b = num & lByteMask[i]; 1220 b >>= (i*8); 1221 ulong b1 = b & nibble0Mask; 1222 ulong b2 = (b & nibble1Mask) >> 4; 1223 str[strIx--] = hexDigit[b1]; 1224 str[strIx--] = hexDigit[b2]; 1225 } 1226 return new String(str); 1227 } 1228 } 1229 1230 /// <summary> 1231 /// Error for invalid PE file 1232 /// </summary> 1233 public class PEFileException : System.Exception { PEFileException(string msg)1234 public PEFileException(string msg) : base(msg) { } 1235 } 1236 1237 public class NotYetImplementedException : System.Exception { NotYetImplementedException(string msg)1238 public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { } 1239 } 1240 1241 public class TypeSignatureException : System.Exception { TypeSignatureException(string msg)1242 public TypeSignatureException(string msg) : base(msg) { } 1243 } 1244 1245 } 1246