Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
PEReader.cs
Go to the documentation of this file.
2using System.IO;
8
10
11public sealed class PEReader : IDisposable
12{
14
16
18
20
22
23 public bool IsLoadedImage { get; }
24
26 {
27 get
28 {
29 if (_lazyPEHeaders == null)
30 {
32 }
33 return _lazyPEHeaders;
34 }
35 }
36
38 {
39 get
40 {
41 if (_lazyImageBlock == null)
42 {
43 return _peImage != null;
44 }
45 return true;
46 }
47 }
48
49 public bool HasMetadata => PEHeaders.MetadataSize > 0;
50
51 public unsafe PEReader(byte* peImage, int size)
52 : this(peImage, size, isLoadedImage: false)
53 {
54 }
55
56 public unsafe PEReader(byte* peImage, int size, bool isLoadedImage)
57 {
58 if (peImage == null)
59 {
60 throw new ArgumentNullException("peImage");
61 }
62 if (size < 0)
63 {
64 throw new ArgumentOutOfRangeException("size");
65 }
66 _peImage = new ExternalMemoryBlockProvider(peImage, size);
67 IsLoadedImage = isLoadedImage;
68 }
69
70 public PEReader(Stream peStream)
71 : this(peStream, PEStreamOptions.Default)
72 {
73 }
74
76 : this(peStream, options, 0)
77 {
78 }
79
80 public unsafe PEReader(Stream peStream, PEStreamOptions options, int size)
81 {
82 if (peStream == null)
83 {
84 throw new ArgumentNullException("peStream");
85 }
86 if (!peStream.CanRead || !peStream.CanSeek)
87 {
89 }
90 if (!options.IsValid())
91 {
92 throw new ArgumentOutOfRangeException("options");
93 }
94 IsLoadedImage = (options & PEStreamOptions.IsLoadedImage) != 0;
95 long position = peStream.Position;
96 int andValidateSize = StreamExtensions.GetAndValidateSize(peStream, size, "peStream");
97 bool flag = true;
98 try
99 {
100 bool isFileStream = FileStreamReadLightUp.IsFileStream(peStream);
101 if ((options & (PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)) == 0)
102 {
103 _peImage = new StreamMemoryBlockProvider(peStream, position, andValidateSize, isFileStream, (options & PEStreamOptions.LeaveOpen) != 0);
104 flag = false;
105 }
106 else if ((options & PEStreamOptions.PrefetchEntireImage) != 0)
107 {
108 NativeHeapMemoryBlock nativeHeapMemoryBlock = (NativeHeapMemoryBlock)(_lazyImageBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, position, andValidateSize));
109 _peImage = new ExternalMemoryBlockProvider(nativeHeapMemoryBlock.Pointer, nativeHeapMemoryBlock.Size);
110 if ((options & PEStreamOptions.PrefetchMetadata) != 0)
111 {
113 }
114 }
115 else
116 {
117 _lazyPEHeaders = new PEHeaders(peStream);
119 }
120 }
121 finally
122 {
123 if (flag && (options & PEStreamOptions.LeaveOpen) == 0)
124 {
125 peStream.Dispose();
126 }
127 }
128 }
129
131 {
132 if (peImage.IsDefault)
133 {
134 throw new ArgumentNullException("peImage");
135 }
136 _peImage = new ByteArrayMemoryProvider(peImage);
137 }
138
139 public void Dispose()
140 {
141 _lazyPEHeaders = null;
142 _peImage?.Dispose();
143 _peImage = null;
145 _lazyImageBlock = null;
147 _lazyMetadataBlock = null;
148 AbstractMemoryBlock[] lazyPESectionBlocks = _lazyPESectionBlocks;
149 if (lazyPESectionBlocks != null)
150 {
151 AbstractMemoryBlock[] array = lazyPESectionBlocks;
152 for (int i = 0; i < array.Length; i++)
153 {
154 array[i]?.Dispose();
155 }
157 }
158 }
159
161 {
163 if (peImage == null)
164 {
165 if (_lazyPEHeaders == null)
166 {
168 }
170 }
171 return peImage;
172 }
173
174 private void InitializePEHeaders()
175 {
176 StreamConstraints constraints;
177 Stream stream = GetPEImage().GetStream(out constraints);
179 if (constraints.GuardOpt != null)
180 {
181 lock (constraints.GuardOpt)
182 {
184 }
185 }
186 else
187 {
189 }
191 }
192
193 private static PEHeaders ReadPEHeadersNoLock(Stream stream, long imageStartPosition, int imageSize, bool isLoadedImage)
194 {
195 stream.Seek(imageStartPosition, SeekOrigin.Begin);
196 return new PEHeaders(stream, imageSize, isLoadedImage);
197 }
198
200 {
201 if (_lazyImageBlock == null)
202 {
204 if (Interlocked.CompareExchange(ref _lazyImageBlock, memoryBlock, null) != null)
205 {
206 memoryBlock.Dispose();
207 }
208 }
209 return _lazyImageBlock;
210 }
211
213 {
214 if (!HasMetadata)
215 {
217 }
218 if (_lazyMetadataBlock == null)
219 {
221 if (Interlocked.CompareExchange(ref _lazyMetadataBlock, memoryBlock, null) != null)
222 {
223 memoryBlock.Dispose();
224 }
225 }
226 return _lazyMetadataBlock;
227 }
228
230 {
232 if (_lazyPESectionBlocks == null)
233 {
235 }
236 AbstractMemoryBlock memoryBlock;
237 if (IsLoadedImage)
238 {
239 memoryBlock = pEImage.GetMemoryBlock(PEHeaders.SectionHeaders[index].VirtualAddress, PEHeaders.SectionHeaders[index].VirtualSize);
240 }
241 else
242 {
243 int size = Math.Min(PEHeaders.SectionHeaders[index].VirtualSize, PEHeaders.SectionHeaders[index].SizeOfRawData);
244 memoryBlock = pEImage.GetMemoryBlock(PEHeaders.SectionHeaders[index].PointerToRawData, size);
245 }
246 if (Interlocked.CompareExchange(ref _lazyPESectionBlocks[index], memoryBlock, null) != null)
247 {
248 memoryBlock.Dispose();
249 }
251 }
252
254 {
256 }
257
259 {
260 return new PEMemoryBlock(GetMetadataBlock());
261 }
262
263 public PEMemoryBlock GetSectionData(int relativeVirtualAddress)
264 {
265 if (relativeVirtualAddress < 0)
266 {
267 Throw.ArgumentOutOfRange("relativeVirtualAddress");
268 }
269 int containingSectionIndex = PEHeaders.GetContainingSectionIndex(relativeVirtualAddress);
270 if (containingSectionIndex < 0)
271 {
272 return default(PEMemoryBlock);
273 }
274 AbstractMemoryBlock pESectionBlock = GetPESectionBlock(containingSectionIndex);
275 int num = relativeVirtualAddress - PEHeaders.SectionHeaders[containingSectionIndex].VirtualAddress;
276 if (num > pESectionBlock.Size)
277 {
278 return default(PEMemoryBlock);
279 }
280 return new PEMemoryBlock(pESectionBlock, num);
281 }
282
283 public PEMemoryBlock GetSectionData(string sectionName)
284 {
285 if (sectionName == null)
286 {
287 Throw.ArgumentNull("sectionName");
288 }
289 int num = PEHeaders.IndexOfSection(sectionName);
290 if (num < 0)
291 {
292 return default(PEMemoryBlock);
293 }
294 return new PEMemoryBlock(GetPESectionBlock(num));
295 }
296
298 {
300 if (debugTableDirectory.Size == 0)
301 {
303 }
304 if (!PEHeaders.TryGetDirectoryOffset(debugTableDirectory, out var offset))
305 {
307 }
308 if (debugTableDirectory.Size % 28 != 0)
309 {
311 }
312 using AbstractMemoryBlock abstractMemoryBlock = GetPEImage().GetMemoryBlock(offset, debugTableDirectory.Size);
313 return ReadDebugDirectoryEntries(abstractMemoryBlock.GetReader());
314 }
315
317 {
318 int num = reader.Length / 28;
320 for (int i = 0; i < num; i++)
321 {
322 if (reader.ReadInt32() != 0)
323 {
325 }
326 uint stamp = reader.ReadUInt32();
327 ushort majorVersion = reader.ReadUInt16();
328 ushort minorVersion = reader.ReadUInt16();
330 int dataSize = reader.ReadInt32();
331 int dataRelativeVirtualAddress = reader.ReadInt32();
332 int dataPointer = reader.ReadInt32();
333 builder.Add(new DebugDirectoryEntry(stamp, majorVersion, minorVersion, type, dataSize, dataRelativeVirtualAddress, dataPointer));
334 }
335 return builder.MoveToImmutable();
336 }
337
339 {
340 int start = (IsLoadedImage ? entry.DataRelativeVirtualAddress : entry.DataPointer);
341 return GetPEImage().GetMemoryBlock(start, entry.DataSize);
342 }
343
353
355 {
356 BlobReader reader = block.GetReader();
357 if (reader.ReadByte() != 82 || reader.ReadByte() != 83 || reader.ReadByte() != 68 || reader.ReadByte() != 83)
358 {
360 }
361 Guid guid = reader.ReadGuid();
362 int age = reader.ReadInt32();
363 string path = reader.ReadUtf8NullTerminated();
364 return new CodeViewDebugDirectoryData(guid, age, path);
365 }
366
376
378 {
379 BlobReader reader = block.GetReader();
380 string text = reader.ReadUtf8NullTerminated();
381 byte[] array = reader.ReadBytes(reader.RemainingBytes);
382 if (text.Length == 0 || array.Length == 0)
383 {
385 }
387 }
388
389 public bool TryOpenAssociatedPortablePdb(string peImagePath, Func<string, Stream?> pdbFileStreamProvider, out MetadataReaderProvider? pdbReaderProvider, out string? pdbPath)
390 {
391 if (peImagePath == null)
392 {
393 Throw.ArgumentNull("peImagePath");
394 }
395 if (pdbFileStreamProvider == null)
396 {
397 Throw.ArgumentNull("pdbFileStreamProvider");
398 }
399 pdbReaderProvider = null;
400 pdbPath = null;
401 string directoryName;
402 try
403 {
404 directoryName = Path.GetDirectoryName(peImagePath);
405 }
406 catch (Exception ex)
407 {
408 throw new ArgumentException(ex.Message, "peImagePath");
409 }
410 Exception errorToReport = null;
412 DebugDirectoryEntry codeViewEntry = collection.FirstOrDefault((DebugDirectoryEntry e) => e.IsPortableCodeView);
413 if (codeViewEntry.DataSize != 0 && TryOpenCodeViewPortablePdb(codeViewEntry, directoryName, pdbFileStreamProvider, out pdbReaderProvider, out pdbPath, ref errorToReport))
414 {
415 return true;
416 }
417 DebugDirectoryEntry embeddedPdbEntry = collection.FirstOrDefault((DebugDirectoryEntry e) => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);
418 if (embeddedPdbEntry.DataSize != 0)
419 {
420 bool openedEmbeddedPdb = false;
421 pdbReaderProvider = null;
422 TryOpenEmbeddedPortablePdb(embeddedPdbEntry, ref openedEmbeddedPdb, ref pdbReaderProvider, ref errorToReport);
423 if (openedEmbeddedPdb)
424 {
425 return true;
426 }
427 }
428 if (errorToReport != null)
429 {
430 ExceptionDispatchInfo.Capture(errorToReport).Throw();
431 }
432 return false;
433 }
434
435 private bool TryOpenCodeViewPortablePdb(DebugDirectoryEntry codeViewEntry, string peImageDirectory, Func<string, Stream> pdbFileStreamProvider, out MetadataReaderProvider provider, out string pdbPath, ref Exception errorToReport)
436 {
437 pdbPath = null;
438 provider = null;
439 CodeViewDebugDirectoryData codeViewDebugDirectoryData;
440 try
441 {
442 codeViewDebugDirectoryData = ReadCodeViewDebugDirectoryData(codeViewEntry);
443 }
444 catch (Exception ex) when (ex is BadImageFormatException || ex is IOException)
445 {
446 _ = errorToReport;
447 if (ex == null)
448 {
449 }
450 errorToReport = ex;
451 return false;
452 }
453 BlobContentId id = new BlobContentId(codeViewDebugDirectoryData.Guid, codeViewEntry.Stamp);
454 string text = PathUtilities.CombinePathWithRelativePath(peImageDirectory, PathUtilities.GetFileName(codeViewDebugDirectoryData.Path));
455 if (TryOpenPortablePdbFile(text, id, pdbFileStreamProvider, out provider, ref errorToReport))
456 {
457 pdbPath = text;
458 return true;
459 }
460 return false;
461 }
462
463 private bool TryOpenPortablePdbFile(string path, BlobContentId id, Func<string, Stream> pdbFileStreamProvider, out MetadataReaderProvider provider, ref Exception errorToReport)
464 {
465 provider = null;
466 MetadataReaderProvider metadataReaderProvider = null;
467 try
468 {
470 try
471 {
472 stream = pdbFileStreamProvider(path);
473 }
475 {
476 stream = null;
477 }
478 if (stream == null)
479 {
480 return false;
481 }
482 if (!stream.CanRead || !stream.CanSeek)
483 {
485 }
486 metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream);
487 if (new BlobContentId(metadataReaderProvider.GetMetadataReader().DebugMetadataHeader.Id) != id)
488 {
489 return false;
490 }
491 provider = metadataReaderProvider;
492 return true;
493 }
494 catch (Exception ex2) when (ex2 is BadImageFormatException || ex2 is IOException)
495 {
496 _ = errorToReport;
497 if (ex2 == null)
498 {
499 }
500 errorToReport = ex2;
501 return false;
502 }
503 finally
504 {
505 if (provider == null)
506 {
507 metadataReaderProvider?.Dispose();
508 }
509 }
510 }
511
512 private void TryOpenEmbeddedPortablePdb(DebugDirectoryEntry embeddedPdbEntry, ref bool openedEmbeddedPdb, ref MetadataReaderProvider provider, ref Exception errorToReport)
513 {
514 provider = null;
515 MetadataReaderProvider metadataReaderProvider = null;
516 try
517 {
518 metadataReaderProvider = ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry);
519 metadataReaderProvider.GetMetadataReader();
520 provider = metadataReaderProvider;
521 openedEmbeddedPdb = true;
522 }
523 catch (Exception ex) when (ex is BadImageFormatException || ex is IOException)
524 {
525 _ = errorToReport;
526 if (ex == null)
527 {
528 }
529 errorToReport = ex;
530 openedEmbeddedPdb = false;
531 }
532 finally
533 {
534 if (provider == null)
535 {
536 metadataReaderProvider?.Dispose();
537 }
538 }
539 }
540
551
553 {
554 ushort majorVersion = entry.MajorVersion;
555 if (majorVersion < 256)
556 {
558 }
559 ushort minorVersion = entry.MinorVersion;
560 if (minorVersion != 256)
561 {
563 }
564 }
565
567 {
568 BlobReader reader = block.GetReader();
569 if (reader.ReadUInt32() != 1111773261)
570 {
572 }
573 int num = reader.ReadInt32();
574 NativeHeapMemoryBlock nativeHeapMemoryBlock;
575 try
576 {
577 nativeHeapMemoryBlock = new NativeHeapMemoryBlock(num);
578 }
579 catch
580 {
582 }
583 bool flag = false;
584 try
585 {
587 DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true);
588 if (num > 0)
589 {
590 int num2;
591 try
592 {
593 num2 = deflateStream.TryReadAll(new Span<byte>(nativeHeapMemoryBlock.Pointer, nativeHeapMemoryBlock.Size));
594 }
595 catch (Exception ex)
596 {
598 }
599 if (num2 != nativeHeapMemoryBlock.Size)
600 {
602 }
603 }
604 if (deflateStream.ReadByte() != -1)
605 {
607 }
608 flag = true;
609 }
610 finally
611 {
612 if (!flag)
613 {
614 nativeHeapMemoryBlock.Dispose();
615 }
616 }
617 return nativeHeapMemoryBlock;
618 }
619}
static readonly ImmutableArray< T > Empty
virtual string Message
Definition Exception.cs:100
Exception? InnerException
Definition Exception.cs:104
static ? string GetDirectoryName(string? path)
Definition Path.cs:121
void Dispose()
Definition Stream.cs:639
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static ImmutableArray< byte > DangerousCreateFromUnderlyingArray(ref byte[]? array)
Stream GetStream(out StreamConstraints constraints)
static int GetAndValidateSize(Stream stream, int size, string streamParameterName)
static unsafe NativeHeapMemoryBlock ReadMemoryBlockNoLock(Stream stream, bool isFileStream, long start, int size)
unsafe MetadataReader GetMetadataReader(MetadataReaderOptions options=MetadataReaderOptions.Default, MetadataStringDecoder? utf8Decoder=null)
static MetadataReaderProvider FromPortablePdbStream(Stream stream, MetadataStreamOptions options=MetadataStreamOptions.Default, int size=0)
static string CombinePathWithRelativePath(string root, string relativePath)
static string GetFileName(string path, bool includeExtension=true)
ImmutableArray< SectionHeader > SectionHeaders
Definition PEHeaders.cs:51
int GetContainingSectionIndex(int relativeVirtualAddress)
Definition PEHeaders.cs:195
bool TryGetDirectoryOffset(DirectoryEntry directory, out int offset)
Definition PEHeaders.cs:173
unsafe PEReader(byte *peImage, int size, bool isLoadedImage)
Definition PEReader.cs:56
static ImmutableArray< DebugDirectoryEntry > ReadDebugDirectoryEntries(BlobReader reader)
Definition PEReader.cs:316
bool TryOpenPortablePdbFile(string path, BlobContentId id, Func< string, Stream > pdbFileStreamProvider, out MetadataReaderProvider provider, ref Exception errorToReport)
Definition PEReader.cs:463
bool TryOpenAssociatedPortablePdb(string peImagePath, Func< string, Stream?> pdbFileStreamProvider, out MetadataReaderProvider? pdbReaderProvider, out string? pdbPath)
Definition PEReader.cs:389
static PEHeaders ReadPEHeadersNoLock(Stream stream, long imageStartPosition, int imageSize, bool isLoadedImage)
Definition PEReader.cs:193
ImmutableArray< DebugDirectoryEntry > ReadDebugDirectory()
Definition PEReader.cs:297
static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block)
Definition PEReader.cs:566
MetadataReaderProvider ReadEmbeddedPortablePdbDebugDirectoryData(DebugDirectoryEntry entry)
Definition PEReader.cs:541
AbstractMemoryBlock GetPESectionBlock(int index)
Definition PEReader.cs:229
PEMemoryBlock GetSectionData(int relativeVirtualAddress)
Definition PEReader.cs:263
unsafe PEReader(byte *peImage, int size)
Definition PEReader.cs:51
static void ValidateEmbeddedPortablePdbVersion(DebugDirectoryEntry entry)
Definition PEReader.cs:552
CodeViewDebugDirectoryData ReadCodeViewDebugDirectoryData(DebugDirectoryEntry entry)
Definition PEReader.cs:344
PEReader(ImmutableArray< byte > peImage)
Definition PEReader.cs:130
AbstractMemoryBlock GetDebugDirectoryEntryDataBlock(DebugDirectoryEntry entry)
Definition PEReader.cs:338
static PdbChecksumDebugDirectoryData DecodePdbChecksumDebugDirectoryData(AbstractMemoryBlock block)
Definition PEReader.cs:377
PEMemoryBlock GetSectionData(string sectionName)
Definition PEReader.cs:283
PEReader(Stream peStream, PEStreamOptions options)
Definition PEReader.cs:75
static CodeViewDebugDirectoryData DecodeCodeViewDebugDirectoryData(AbstractMemoryBlock block)
Definition PEReader.cs:354
void TryOpenEmbeddedPortablePdb(DebugDirectoryEntry embeddedPdbEntry, ref bool openedEmbeddedPdb, ref MetadataReaderProvider provider, ref Exception errorToReport)
Definition PEReader.cs:512
PdbChecksumDebugDirectoryData ReadPdbChecksumDebugDirectoryData(DebugDirectoryEntry entry)
Definition PEReader.cs:367
bool TryOpenCodeViewPortablePdb(DebugDirectoryEntry codeViewEntry, string peImageDirectory, Func< string, Stream > pdbFileStreamProvider, out MetadataReaderProvider provider, out string pdbPath, ref Exception errorToReport)
Definition PEReader.cs:435
unsafe PEReader(Stream peStream, PEStreamOptions options, int size)
Definition PEReader.cs:80
static void ArgumentNull(string parameterName)
Definition Throw.cs:110
static void InvalidOperation_PEImageNotAvailable()
Definition Throw.cs:264
static void ArgumentOutOfRange(string parameterName)
Definition Throw.cs:145
static void PEReaderDisposed()
Definition Throw.cs:299
static void InvalidArgument(string message, string parameterName)
Definition Throw.cs:19
static ExceptionDispatchInfo Capture(Exception source)
static string InvalidPdbChecksumDataFormat
Definition SR.cs:162
static string InvalidDirectoryRVA
Definition SR.cs:152
static string DataTooBig
Definition SR.cs:230
static string InvalidDirectorySize
Definition SR.cs:154
static string SizeMismatch
Definition SR.cs:228
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string InvalidDebugDirectoryEntryCharacteristics
Definition SR.cs:156
static string PEImageDoesNotHaveMetadata
Definition SR.cs:108
static string UnexpectedDebugDirectoryType
Definition SR.cs:176
static string UnsupportedFormatVersion
Definition SR.cs:232
static string StreamMustSupportReadAndSeek
Definition SR.cs:52
static string UnexpectedEmbeddedPortablePdbDataSignature
Definition SR.cs:160
static string UnexpectedCodeViewDataSignature
Definition SR.cs:158
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
unsafe byte[] ReadBytes(int byteCount)