Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
PEHeaders.cs
Go to the documentation of this file.
2using System.IO;
4
6
7public sealed class PEHeaders
8{
9 private readonly CoffHeader _coffHeader;
10
11 private readonly PEHeader _peHeader;
12
14
15 private readonly CorHeader _corHeader;
16
17 private readonly bool _isLoadedImage;
18
19 private readonly int _metadataStartOffset = -1;
20
21 private readonly int _metadataSize;
22
23 private readonly int _coffHeaderStartOffset = -1;
24
25 private readonly int _corHeaderStartOffset = -1;
26
27 private readonly int _peHeaderStartOffset = -1;
28
29 internal const ushort DosSignature = 23117;
30
31 internal const int PESignatureOffsetLocation = 60;
32
33 internal const uint PESignature = 17744u;
34
35 internal const int PESignatureSize = 4;
36
38
40
42
44
45 public bool IsCoffOnly => _peHeader == null;
46
48
50
52
54
56
58 {
59 get
60 {
61 if (_peHeader != null)
62 {
63 return _peHeader.Subsystem == Subsystem.WindowsCui;
64 }
65 return false;
66 }
67 }
68
69 public bool IsDll => (_coffHeader.Characteristics & Characteristics.Dll) != 0;
70
71 public bool IsExe => (_coffHeader.Characteristics & Characteristics.Dll) == 0;
72
73 public PEHeaders(Stream peStream)
74 : this(peStream, 0)
75 {
76 }
77
78 public PEHeaders(Stream peStream, int size)
79 : this(peStream, size, isLoadedImage: false)
80 {
81 }
82
83 public PEHeaders(Stream peStream, int size, bool isLoadedImage)
84 {
85 if (peStream == null)
86 {
87 throw new ArgumentNullException("peStream");
88 }
89 if (!peStream.CanRead || !peStream.CanSeek)
90 {
92 }
93 _isLoadedImage = isLoadedImage;
94 int andValidateSize = StreamExtensions.GetAndValidateSize(peStream, size, "peStream");
95 PEBinaryReader reader = new PEBinaryReader(peStream, andValidateSize);
96 SkipDosHeader(ref reader, out var isCOFFOnly);
98 _coffHeader = new CoffHeader(ref reader);
99 if (!isCOFFOnly)
100 {
102 _peHeader = new PEHeader(ref reader);
103 }
105 if (!isCOFFOnly && TryCalculateCorHeaderOffset(andValidateSize, out var startOffset))
106 {
107 _corHeaderStartOffset = startOffset;
108 reader.Seek(startOffset);
109 _corHeader = new CorHeader(ref reader);
110 }
112 }
113
114 private bool TryCalculateCorHeaderOffset(long peStreamSize, out int startOffset)
115 {
116 if (!TryGetDirectoryOffset(_peHeader.CorHeaderTableDirectory, out startOffset, canCrossSectionBoundary: false))
117 {
118 startOffset = -1;
119 return false;
120 }
122 if (size < 72)
123 {
125 }
126 return true;
127 }
128
129 private void SkipDosHeader(ref PEBinaryReader reader, out bool isCOFFOnly)
130 {
131 ushort num = reader.ReadUInt16();
132 if (num != 23117)
133 {
134 if (num == 0 && reader.ReadUInt16() == ushort.MaxValue)
135 {
137 }
138 isCOFFOnly = true;
139 reader.Seek(0);
140 }
141 else
142 {
143 isCOFFOnly = false;
144 }
145 if (!isCOFFOnly)
146 {
147 reader.Seek(60);
148 int offset = reader.ReadInt32();
149 reader.Seek(offset);
150 uint num2 = reader.ReadUInt32();
151 if (num2 != 17744)
152 {
154 }
155 }
156 }
157
159 {
160 int numberOfSections = _coffHeader.NumberOfSections;
161 if (numberOfSections < 0)
162 {
164 }
165 ImmutableArray<SectionHeader>.Builder builder = ImmutableArray.CreateBuilder<SectionHeader>(numberOfSections);
166 for (int i = 0; i < numberOfSections; i++)
167 {
168 builder.Add(new SectionHeader(ref reader));
169 }
170 return builder.MoveToImmutable();
171 }
172
173 public bool TryGetDirectoryOffset(DirectoryEntry directory, out int offset)
174 {
175 return TryGetDirectoryOffset(directory, out offset, canCrossSectionBoundary: true);
176 }
177
178 internal bool TryGetDirectoryOffset(DirectoryEntry directory, out int offset, bool canCrossSectionBoundary)
179 {
180 int containingSectionIndex = GetContainingSectionIndex(directory.RelativeVirtualAddress);
181 if (containingSectionIndex < 0)
182 {
183 offset = -1;
184 return false;
185 }
186 int num = directory.RelativeVirtualAddress - _sectionHeaders[containingSectionIndex].VirtualAddress;
187 if (!canCrossSectionBoundary && directory.Size > _sectionHeaders[containingSectionIndex].VirtualSize - num)
188 {
190 }
191 offset = (_isLoadedImage ? directory.RelativeVirtualAddress : (_sectionHeaders[containingSectionIndex].PointerToRawData + num));
192 return true;
193 }
194
195 public int GetContainingSectionIndex(int relativeVirtualAddress)
196 {
197 for (int i = 0; i < _sectionHeaders.Length; i++)
198 {
199 if (_sectionHeaders[i].VirtualAddress <= relativeVirtualAddress && relativeVirtualAddress < _sectionHeaders[i].VirtualAddress + _sectionHeaders[i].VirtualSize)
200 {
201 return i;
202 }
203 }
204 return -1;
205 }
206
207 internal int IndexOfSection(string name)
208 {
209 for (int i = 0; i < SectionHeaders.Length; i++)
210 {
211 if (SectionHeaders[i].Name.Equals(name, StringComparison.Ordinal))
212 {
213 return i;
214 }
215 }
216 return -1;
217 }
218
219 private void CalculateMetadataLocation(long peImageSize, out int start, out int size)
220 {
221 if (IsCoffOnly)
222 {
223 int num = IndexOfSection(".cormeta");
224 if (num == -1)
225 {
226 start = -1;
227 size = 0;
228 return;
229 }
230 if (_isLoadedImage)
231 {
232 start = SectionHeaders[num].VirtualAddress;
233 size = SectionHeaders[num].VirtualSize;
234 }
235 else
236 {
237 start = SectionHeaders[num].PointerToRawData;
238 size = SectionHeaders[num].SizeOfRawData;
239 }
240 }
241 else
242 {
243 if (_corHeader == null)
244 {
245 start = 0;
246 size = 0;
247 return;
248 }
249 if (!TryGetDirectoryOffset(_corHeader.MetadataDirectory, out start, canCrossSectionBoundary: false))
250 {
252 }
254 }
255 if (start < 0 || start >= peImageSize || size <= 0 || start > peImageSize - size)
256 {
258 }
259 }
260}
static int GetAndValidateSize(Stream stream, int size, string streamParameterName)
void CalculateMetadataLocation(long peImageSize, out int start, out int size)
Definition PEHeaders.cs:219
ImmutableArray< SectionHeader > SectionHeaders
Definition PEHeaders.cs:51
int GetContainingSectionIndex(int relativeVirtualAddress)
Definition PEHeaders.cs:195
readonly ImmutableArray< SectionHeader > _sectionHeaders
Definition PEHeaders.cs:13
PEHeaders(Stream peStream, int size, bool isLoadedImage)
Definition PEHeaders.cs:83
bool TryCalculateCorHeaderOffset(long peStreamSize, out int startOffset)
Definition PEHeaders.cs:114
void SkipDosHeader(ref PEBinaryReader reader, out bool isCOFFOnly)
Definition PEHeaders.cs:129
bool TryGetDirectoryOffset(DirectoryEntry directory, out int offset, bool canCrossSectionBoundary)
Definition PEHeaders.cs:178
ImmutableArray< SectionHeader > ReadSectionHeaders(ref PEBinaryReader reader)
Definition PEHeaders.cs:158
bool TryGetDirectoryOffset(DirectoryEntry directory, out int offset)
Definition PEHeaders.cs:173
static string InvalidPESignature
Definition SR.cs:32
static string MissingDataDirectory
Definition SR.cs:44
static string InvalidNumberOfSections
Definition SR.cs:104
static string StreamMustSupportReadAndSeek
Definition SR.cs:52
static string InvalidCorHeaderSize
Definition SR.cs:16
static string InvalidMetadataSectionSpan
Definition SR.cs:26
static string SectionTooSmall
Definition SR.cs:50
static string UnknownFileFormat
Definition SR.cs:54
Definition SR.cs:7