BearParser
Portable Executable parsing library (from PE-bear)
Loading...
Searching...
No Matches
RelocDirWrapper.cpp
Go to the documentation of this file.
2#include "pe/PEFile.h"
3
4/*
5// Based relocation format.
6
7typedef struct _IMAGE_BASE_RELOCATION {
8 DWORD VirtualAddress;
9 DWORD SizeOfBlock;
10 // WORD TypeOffset[1];
11} IMAGE_BASE_RELOCATION;
12typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
13
14
15//Based relocation types.
16
17enum reloc_based {
18 RELB_ABSOLUTE = 0,
19 RELB_HIGH = 1,
20 RELB_LOW = 2,
21 RELB_HIGHLOW = 3,
22 RELB_HIGHADJ = 4,
23 RELB_MIPS_JMPADDR = 5,
24 RELB_SECTION = 6,
25 RELB_REL32 = 7,
26 RELB_MIPS_JMPADDR16 = 9,
27 RELB_IA64_IMM64 = 9,
28 RELB_DIR64 = 10,
29 RELB_HIGH3ADJ = 11
30};
31
32*/
33
35{
36 clear();
37 this->parsedSize = 0;
38 this->invalidEntries = 0;
39
40 const size_t INVALID_SERIES_LIMIT = 10;
41 const size_t INVALID_ENTRIES_LIMIT = 20;
43 size_t entryId = 0;
44 size_t invalidSeries = 0;
45 while (parsedSize < maxSize) {
46 RelocBlockWrapper* entry = new RelocBlockWrapper(this->m_Exe, this, entryId++);
47 if (!entry) break;
48
49 bool isOk = false;
51
52 if (!entry->getPtr() || !val || !isOk) {
53 delete entry;
54 break;
55 }
56 if (entry->isValid()) {
57 invalidSeries = 0;
58 }
59 else {
61 this->invalidEntries++;
63 if (invalidEntries >= INVALID_ENTRIES_LIMIT) break;
64 }
65 this->parsedSize += val;
66 this->entries.push_back(entry);
67
68 }
69 return true;
70}
71
72
83
84//----------------
85
87{
88 clear();
89 this->parsedSize = 0;
90 this->invalidEntries = 0;
91
93 if (!reloc) return false;
94
95 const size_t INVALID_SERIES_LIMIT = 10;
96 const size_t INVALID_ENTRIES_LIMIT = 100;
97 size_t maxSize = reloc->SizeOfBlock;
98 parsedSize = sizeof(IMAGE_BASE_RELOCATION); // the block begins with IMAGE_BASE_RELOCATION record
99 size_t entryId = 0;
100 size_t invalidSeries = 0;
101 while (parsedSize < maxSize) {
102 RelocEntryWrapper* entry = new RelocEntryWrapper(this->m_Exe, this, entryId++);
103 if (!entry->getPtr()) {
104 delete entry;
105 break;
106 }
107 if (entry->isValid()) {
108 invalidSeries = 0;
109 }
110 else {
112 this->invalidEntries++;
114 if (invalidEntries >= INVALID_ENTRIES_LIMIT) break;
115 }
116 this->parsedSize += sizeof(pe::BASE_RELOCATION_ENTRY);
117 this->entries.push_back(entry);
118 }
119 return true;
120}
121
122
124{
125 if (this->parentDir == NULL) return NULL;
126 IMAGE_BASE_RELOCATION* reloc = this->parentDir->reloc();
127 if (!reloc) return NULL;
128
130 BYTE *ptr = NULL;
131
132 // use my cached:
133 if (this->cachedRaw != INVALID_ADDR) {
134 ptr = m_Exe->getContentAt(this->cachedRaw, Executable::RAW, sizeof(IMAGE_BASE_RELOCATION));
135 return ptr;
136 }
137
138 // use previous cached to calculate my cached
139 size_t prevNum = this->entryNum - 1;
140
141 RelocBlockWrapper *prevEntry = dynamic_cast<RelocBlockWrapper*> (this->parentDir->getEntryAt(prevNum));
142 if (prevEntry) {
143 offset_t prevRaw = prevEntry->cachedRaw;
144
146 raw = prevRaw + prevReloc->SizeOfBlock;
147
148 if (prevRaw != INVALID_ADDR) {
150
151 if (ptr != NULL) {
152 this->cachedRaw = raw;
153 return ptr;
154 }
155 }
156 }
157 // previous cached not avaliable, calculate...
158 offset_t firstRaw = this->getOffset(reloc);
159 offset_t blockSize = reloc->SizeOfBlock;
160
161 raw = firstRaw;
162 ptr = (BYTE*) reloc;
163
164 for ( size_t i = 0; i < this->entryNum; i++) { //TODO: make caching
165 raw += blockSize;
166
168 if (!ptr) return NULL;
169
170 reloc = (IMAGE_BASE_RELOCATION*) ptr;
171 blockSize = reloc->SizeOfBlock;
172 }
173
174 this->cachedRaw = raw;
175 return ptr;
176}
177
179{
180 if (this->parentDir == NULL) return 0;
182 if (!reloc) return 0;
183
184 if (reloc->SizeOfBlock > 0) return reloc->SizeOfBlock;
185
186 return sizeof(IMAGE_BASE_RELOCATION);
187}
188
190{
192 if (!reloc) return NULL;
193
194 switch (fieldId) {
195 case PAGE_VA: return (void*) &reloc->VirtualAddress;
196 case BLOCK_SIZE : return (void*) &reloc->SizeOfBlock;
197 case ENTRIES_PTR :
198 {
199 BYTE *blockSizePtr = (BYTE*) &reloc->SizeOfBlock;
200 return blockSizePtr + sizeof(DWORD);
201 }
202 }
203 return getPtr();
204}
205
207{
208 switch (fieldId) {
209 case BLOCK_SIZE : return "Block Size";
210 case PAGE_VA: return "Page RVA";
211 case ENTRIES_PTR: return "Entries";
212 }
213 return getName();
214}
215
217{
218 switch (fieldId) {
219 case PAGE_VA:
220 return Executable::RVA;
221 }
223}
224
232
234{
237
238 if (entriesPtr == NULL || entriesSize == 0) return NULL;
239
241 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, sizeof(WORD));
242
243 return ptr;
244}
245
247{
248 if (this->cachedMaxNum > 0) return this->cachedMaxNum;
249
251 if (!reloc) return 0;
252
255
256 offset_t fileSize = m_Exe->getRawSize();
257 if (entriesOffset + entriesSize > fileSize) {
258 entriesSize = fileSize - entriesOffset; // truncate to fileSize
259 }
260
261 void *ptr = this->m_Exe->getContentAt(entriesOffset, Executable::RAW, entriesSize);
262
264 if (ptr) {
265 entriesNum = entriesSize / sizeof(WORD); //sizeof(BASE_RELOCATION_ENTRY);
266 }
267 this->cachedMaxNum = entriesNum;
268 return entriesNum;
269}
270//-------------------------------------------------------------------------------------------------
272{
273 if (!getPtr()) return false;
274
275 bool isOk = false;
277 if (!isOk) return false;
278
280 if (relocType != 0 && relocType != 3 && relocType != 10) {
281 return false;
282 }
283 return true;
284}
285
287{
288 if (this->parentDir == NULL) return NULL;
289
290 size_t maxNum = this->parentDir->maxEntriesNumInBlock();
291 if (this->entryNum >= maxNum) return NULL;
292
293 WORD* entriesPtr = (WORD* ) parentDir->getEntriesPtr();
294 if (entriesPtr == NULL) return NULL;
295
296 WORD* ptr = &entriesPtr[this->entryNum];
297 return ptr;
298}
299
301{
302 if (this->parentDir == NULL) return 0;
303 return sizeof(WORD);
304}
305
307{
308 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
309 return entry->Type;
310}
311
313{
314 pe::BASE_RELOCATION_ENTRY* entry = (pe::BASE_RELOCATION_ENTRY*) &relocEntryVal;
315 return entry->Offset;
316}
317
319{
320 switch (relocType) {
321 case 0 : return "Padding (skipped)";
322 case 1 : return "High WORD of 32-bit field";
323 case 2 : return "Low WORD of 32-bit field";
324 case 3 : return "32 bit field";
325 case 4 : return "HighAdj";
326 case 5 : return "MIPS JumpAddr";
327 case 6 : case 7 : return "Reserved";
328 case 9 : return "MIPS16 JumpAddr";
329 case 10 : return "64 bit field";
330 }
331 return "";
332}
333
335{
336 if (this->parentDir == NULL) return INVALID_ADDR;
337
338 IMAGE_BASE_RELOCATION* reloc = parentDir->myReloc();
339 if (reloc == NULL) return INVALID_ADDR;
340
341 offset_t offset = static_cast<offset_t>(reloc->VirtualAddress + delta);
342 return offset;
343}
344
INT_TYPE _getNumValue(void *ptr)
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
bufsize_t getDirEntrySize(bool trimToExeSize=false)
offset_t getDirEntryAddress()
virtual bufsize_t getFieldSize(size_t fieldId, size_t subField=FIELD_NONE)
virtual offset_t getFieldOffset(size_t fieldId, size_t subField=FIELD_NONE)
virtual offset_t getOffset()
virtual uint64_t getNumValue(size_t fieldId, size_t subField, bool *isOk)
virtual ExeNodeWrapper * getEntryAt(size_t fieldId)
std::vector< ExeNodeWrapper * > entries
virtual void clear()
BYTE * getContentAt(offset_t offset, bufsize_t size, bool allowExceptions=false)
Definition Executable.h:57
virtual offset_t getRawSize() const
Definition Executable.h:54
virtual QString getFieldName(size_t fieldId)
virtual WrappedValue::data_type containsDataType(size_t fieldId, size_t subField)
virtual void * getFieldPtr(size_t fieldId, size_t subField=FIELD_NONE)
virtual void * getPtr()
virtual QString getName()
virtual bufsize_t getSize()
virtual Executable::addr_type containsAddrType(size_t fieldId, size_t subField)
IMAGE_BASE_RELOCATION * myReloc()
friend class RelocBlockWrapper
IMAGE_BASE_RELOCATION * reloc()
offset_t deltaToRVA(WORD delta)
static QString translateType(WORD type)
@ RELOC_ENTRY_VAL
virtual void * getPtr()
virtual bool isValid()
virtual bufsize_t getSize()
static WORD getDelta(WORD relocEntryVal)
static WORD getType(WORD relocEntryVal)