Mercurial > hg > CbC > CbC_llvm
comparison lib/Object/COFFObjectFile.cpp @ 0:95c75e76d11b LLVM3.4
LLVM 3.4
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 12 Dec 2013 13:56:28 +0900 |
parents | |
children | 54457678186b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:95c75e76d11b |
---|---|
1 //===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===// | |
2 // | |
3 // The LLVM Compiler Infrastructure | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This file declares the COFFObjectFile class. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 | |
14 #include "llvm/Object/COFF.h" | |
15 #include "llvm/ADT/ArrayRef.h" | |
16 #include "llvm/ADT/SmallString.h" | |
17 #include "llvm/ADT/StringSwitch.h" | |
18 #include "llvm/ADT/Triple.h" | |
19 #include "llvm/Support/Debug.h" | |
20 #include "llvm/Support/raw_ostream.h" | |
21 #include <cctype> | |
22 | |
23 using namespace llvm; | |
24 using namespace object; | |
25 | |
26 namespace { | |
27 using support::ulittle8_t; | |
28 using support::ulittle16_t; | |
29 using support::ulittle32_t; | |
30 using support::little16_t; | |
31 } | |
32 | |
33 namespace { | |
34 // Returns false if size is greater than the buffer size. And sets ec. | |
35 bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { | |
36 if (m->getBufferSize() < size) { | |
37 ec = object_error::unexpected_eof; | |
38 return false; | |
39 } | |
40 return true; | |
41 } | |
42 | |
43 // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. | |
44 // Returns unexpected_eof if error. | |
45 template<typename T> | |
46 error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, | |
47 const size_t Size = sizeof(T)) { | |
48 uintptr_t Addr = uintptr_t(Ptr); | |
49 if (Addr + Size < Addr || | |
50 Addr + Size < Size || | |
51 Addr + Size > uintptr_t(M->getBufferEnd())) { | |
52 return object_error::unexpected_eof; | |
53 } | |
54 Obj = reinterpret_cast<const T *>(Addr); | |
55 return object_error::success; | |
56 } | |
57 } | |
58 | |
59 const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { | |
60 const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); | |
61 | |
62 # ifndef NDEBUG | |
63 // Verify that the symbol points to a valid entry in the symbol table. | |
64 uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); | |
65 if (offset < COFFHeader->PointerToSymbolTable | |
66 || offset >= COFFHeader->PointerToSymbolTable | |
67 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) | |
68 report_fatal_error("Symbol was outside of symbol table."); | |
69 | |
70 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) | |
71 == 0 && "Symbol did not point to the beginning of a symbol"); | |
72 # endif | |
73 | |
74 return addr; | |
75 } | |
76 | |
77 const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { | |
78 const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); | |
79 | |
80 # ifndef NDEBUG | |
81 // Verify that the section points to a valid entry in the section table. | |
82 if (addr < SectionTable | |
83 || addr >= (SectionTable + COFFHeader->NumberOfSections)) | |
84 report_fatal_error("Section was outside of section table."); | |
85 | |
86 uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); | |
87 assert(offset % sizeof(coff_section) == 0 && | |
88 "Section did not point to the beginning of a section"); | |
89 # endif | |
90 | |
91 return addr; | |
92 } | |
93 | |
94 error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, | |
95 SymbolRef &Result) const { | |
96 const coff_symbol *symb = toSymb(Symb); | |
97 symb += 1 + symb->NumberOfAuxSymbols; | |
98 Symb.p = reinterpret_cast<uintptr_t>(symb); | |
99 Result = SymbolRef(Symb, this); | |
100 return object_error::success; | |
101 } | |
102 | |
103 error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, | |
104 StringRef &Result) const { | |
105 const coff_symbol *symb = toSymb(Symb); | |
106 return getSymbolName(symb, Result); | |
107 } | |
108 | |
109 error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, | |
110 uint64_t &Result) const { | |
111 const coff_symbol *symb = toSymb(Symb); | |
112 const coff_section *Section = NULL; | |
113 if (error_code ec = getSection(symb->SectionNumber, Section)) | |
114 return ec; | |
115 | |
116 if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) | |
117 Result = UnknownAddressOrSize; | |
118 else if (Section) | |
119 Result = Section->PointerToRawData + symb->Value; | |
120 else | |
121 Result = symb->Value; | |
122 return object_error::success; | |
123 } | |
124 | |
125 error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, | |
126 uint64_t &Result) const { | |
127 const coff_symbol *symb = toSymb(Symb); | |
128 const coff_section *Section = NULL; | |
129 if (error_code ec = getSection(symb->SectionNumber, Section)) | |
130 return ec; | |
131 | |
132 if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) | |
133 Result = UnknownAddressOrSize; | |
134 else if (Section) | |
135 Result = Section->VirtualAddress + symb->Value; | |
136 else | |
137 Result = symb->Value; | |
138 return object_error::success; | |
139 } | |
140 | |
141 error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, | |
142 SymbolRef::Type &Result) const { | |
143 const coff_symbol *symb = toSymb(Symb); | |
144 Result = SymbolRef::ST_Other; | |
145 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && | |
146 symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { | |
147 Result = SymbolRef::ST_Unknown; | |
148 } else { | |
149 if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { | |
150 Result = SymbolRef::ST_Function; | |
151 } else { | |
152 uint32_t Characteristics = 0; | |
153 if (symb->SectionNumber > 0) { | |
154 const coff_section *Section = NULL; | |
155 if (error_code ec = getSection(symb->SectionNumber, Section)) | |
156 return ec; | |
157 Characteristics = Section->Characteristics; | |
158 } | |
159 if (Characteristics & COFF::IMAGE_SCN_MEM_READ && | |
160 ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. | |
161 Result = SymbolRef::ST_Data; | |
162 } | |
163 } | |
164 return object_error::success; | |
165 } | |
166 | |
167 error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, | |
168 uint32_t &Result) const { | |
169 const coff_symbol *symb = toSymb(Symb); | |
170 Result = SymbolRef::SF_None; | |
171 | |
172 // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common | |
173 | |
174 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && | |
175 symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) | |
176 Result |= SymbolRef::SF_Undefined; | |
177 | |
178 // TODO: This are certainly too restrictive. | |
179 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) | |
180 Result |= SymbolRef::SF_Global; | |
181 | |
182 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) | |
183 Result |= SymbolRef::SF_Weak; | |
184 | |
185 if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) | |
186 Result |= SymbolRef::SF_Absolute; | |
187 | |
188 return object_error::success; | |
189 } | |
190 | |
191 error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, | |
192 uint64_t &Result) const { | |
193 // FIXME: Return the correct size. This requires looking at all the symbols | |
194 // in the same section as this symbol, and looking for either the next | |
195 // symbol, or the end of the section. | |
196 const coff_symbol *symb = toSymb(Symb); | |
197 const coff_section *Section = NULL; | |
198 if (error_code ec = getSection(symb->SectionNumber, Section)) | |
199 return ec; | |
200 | |
201 if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) | |
202 Result = UnknownAddressOrSize; | |
203 else if (Section) | |
204 Result = Section->SizeOfRawData - symb->Value; | |
205 else | |
206 Result = 0; | |
207 return object_error::success; | |
208 } | |
209 | |
210 error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, | |
211 section_iterator &Result) const { | |
212 const coff_symbol *symb = toSymb(Symb); | |
213 if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) | |
214 Result = end_sections(); | |
215 else { | |
216 const coff_section *sec = 0; | |
217 if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; | |
218 DataRefImpl Sec; | |
219 Sec.p = reinterpret_cast<uintptr_t>(sec); | |
220 Result = section_iterator(SectionRef(Sec, this)); | |
221 } | |
222 return object_error::success; | |
223 } | |
224 | |
225 error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, | |
226 uint64_t &Val) const { | |
227 report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); | |
228 } | |
229 | |
230 error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, | |
231 SectionRef &Result) const { | |
232 const coff_section *sec = toSec(Sec); | |
233 sec += 1; | |
234 Sec.p = reinterpret_cast<uintptr_t>(sec); | |
235 Result = SectionRef(Sec, this); | |
236 return object_error::success; | |
237 } | |
238 | |
239 error_code COFFObjectFile::getSectionName(DataRefImpl Sec, | |
240 StringRef &Result) const { | |
241 const coff_section *sec = toSec(Sec); | |
242 return getSectionName(sec, Result); | |
243 } | |
244 | |
245 error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, | |
246 uint64_t &Result) const { | |
247 const coff_section *sec = toSec(Sec); | |
248 Result = sec->VirtualAddress; | |
249 return object_error::success; | |
250 } | |
251 | |
252 error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, | |
253 uint64_t &Result) const { | |
254 const coff_section *sec = toSec(Sec); | |
255 Result = sec->SizeOfRawData; | |
256 return object_error::success; | |
257 } | |
258 | |
259 error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, | |
260 StringRef &Result) const { | |
261 const coff_section *sec = toSec(Sec); | |
262 ArrayRef<uint8_t> Res; | |
263 error_code EC = getSectionContents(sec, Res); | |
264 Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); | |
265 return EC; | |
266 } | |
267 | |
268 error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, | |
269 uint64_t &Res) const { | |
270 const coff_section *sec = toSec(Sec); | |
271 if (!sec) | |
272 return object_error::parse_failed; | |
273 Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); | |
274 return object_error::success; | |
275 } | |
276 | |
277 error_code COFFObjectFile::isSectionText(DataRefImpl Sec, | |
278 bool &Result) const { | |
279 const coff_section *sec = toSec(Sec); | |
280 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; | |
281 return object_error::success; | |
282 } | |
283 | |
284 error_code COFFObjectFile::isSectionData(DataRefImpl Sec, | |
285 bool &Result) const { | |
286 const coff_section *sec = toSec(Sec); | |
287 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; | |
288 return object_error::success; | |
289 } | |
290 | |
291 error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, | |
292 bool &Result) const { | |
293 const coff_section *sec = toSec(Sec); | |
294 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; | |
295 return object_error::success; | |
296 } | |
297 | |
298 error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, | |
299 bool &Result) const { | |
300 // FIXME: Unimplemented | |
301 Result = true; | |
302 return object_error::success; | |
303 } | |
304 | |
305 error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, | |
306 bool &Result) const { | |
307 const coff_section *sec = toSec(Sec); | |
308 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; | |
309 return object_error::success; | |
310 } | |
311 | |
312 error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, | |
313 bool &Result) const { | |
314 // FIXME: Unimplemented. | |
315 Result = false; | |
316 return object_error::success; | |
317 } | |
318 | |
319 error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, | |
320 bool &Result) const { | |
321 // FIXME: Unimplemented. | |
322 Result = false; | |
323 return object_error::success; | |
324 } | |
325 | |
326 error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, | |
327 DataRefImpl Symb, | |
328 bool &Result) const { | |
329 const coff_section *sec = toSec(Sec); | |
330 const coff_symbol *symb = toSymb(Symb); | |
331 const coff_section *symb_sec = 0; | |
332 if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; | |
333 if (symb_sec == sec) | |
334 Result = true; | |
335 else | |
336 Result = false; | |
337 return object_error::success; | |
338 } | |
339 | |
340 relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Sec) const { | |
341 const coff_section *sec = toSec(Sec); | |
342 DataRefImpl ret; | |
343 if (sec->NumberOfRelocations == 0) | |
344 ret.p = 0; | |
345 else | |
346 ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); | |
347 | |
348 return relocation_iterator(RelocationRef(ret, this)); | |
349 } | |
350 | |
351 relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Sec) const { | |
352 const coff_section *sec = toSec(Sec); | |
353 DataRefImpl ret; | |
354 if (sec->NumberOfRelocations == 0) | |
355 ret.p = 0; | |
356 else | |
357 ret.p = reinterpret_cast<uintptr_t>( | |
358 reinterpret_cast<const coff_relocation*>( | |
359 base() + sec->PointerToRelocations) | |
360 + sec->NumberOfRelocations); | |
361 | |
362 return relocation_iterator(RelocationRef(ret, this)); | |
363 } | |
364 | |
365 // Initialize the pointer to the symbol table. | |
366 error_code COFFObjectFile::initSymbolTablePtr() { | |
367 if (error_code ec = getObject( | |
368 SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable, | |
369 COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) | |
370 return ec; | |
371 | |
372 // Find string table. The first four byte of the string table contains the | |
373 // total size of the string table, including the size field itself. If the | |
374 // string table is empty, the value of the first four byte would be 4. | |
375 const uint8_t *StringTableAddr = | |
376 base() + COFFHeader->PointerToSymbolTable + | |
377 COFFHeader->NumberOfSymbols * sizeof(coff_symbol); | |
378 const ulittle32_t *StringTableSizePtr; | |
379 if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr)) | |
380 return ec; | |
381 StringTableSize = *StringTableSizePtr; | |
382 if (error_code ec = | |
383 getObject(StringTable, Data, StringTableAddr, StringTableSize)) | |
384 return ec; | |
385 | |
386 // Check that the string table is null terminated if has any in it. | |
387 if (StringTableSize < 4 || | |
388 (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) | |
389 return object_error::parse_failed; | |
390 return object_error::success; | |
391 } | |
392 | |
393 // Returns the file offset for the given RVA. | |
394 error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const { | |
395 error_code ec; | |
396 for (section_iterator i = begin_sections(), e = end_sections(); i != e; | |
397 i.increment(ec)) { | |
398 if (ec) | |
399 return ec; | |
400 const coff_section *Section = getCOFFSection(i); | |
401 uint32_t SectionStart = Section->VirtualAddress; | |
402 uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; | |
403 if (SectionStart <= Rva && Rva < SectionEnd) { | |
404 uint32_t Offset = Rva - SectionStart; | |
405 Res = uintptr_t(base()) + Section->PointerToRawData + Offset; | |
406 return object_error::success; | |
407 } | |
408 } | |
409 return object_error::parse_failed; | |
410 } | |
411 | |
412 // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name | |
413 // table entry. | |
414 error_code COFFObjectFile:: | |
415 getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const { | |
416 uintptr_t IntPtr = 0; | |
417 if (error_code ec = getRvaPtr(Rva, IntPtr)) | |
418 return ec; | |
419 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); | |
420 Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); | |
421 Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); | |
422 return object_error::success; | |
423 } | |
424 | |
425 // Find the import table. | |
426 error_code COFFObjectFile::initImportTablePtr() { | |
427 // First, we get the RVA of the import table. If the file lacks a pointer to | |
428 // the import table, do nothing. | |
429 const data_directory *DataEntry; | |
430 if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) | |
431 return object_error::success; | |
432 | |
433 // Do nothing if the pointer to import table is NULL. | |
434 if (DataEntry->RelativeVirtualAddress == 0) | |
435 return object_error::success; | |
436 | |
437 uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; | |
438 NumberOfImportDirectory = DataEntry->Size / | |
439 sizeof(import_directory_table_entry); | |
440 | |
441 // Find the section that contains the RVA. This is needed because the RVA is | |
442 // the import table's memory address which is different from its file offset. | |
443 uintptr_t IntPtr = 0; | |
444 if (error_code ec = getRvaPtr(ImportTableRva, IntPtr)) | |
445 return ec; | |
446 ImportDirectory = reinterpret_cast< | |
447 const import_directory_table_entry *>(IntPtr); | |
448 | |
449 // It's an error if there's no section containing the Import Table RVA. | |
450 return object_error::parse_failed; | |
451 } | |
452 | |
453 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) | |
454 : ObjectFile(Binary::ID_COFF, Object) | |
455 , COFFHeader(0) | |
456 , PE32Header(0) | |
457 , DataDirectory(0) | |
458 , SectionTable(0) | |
459 , SymbolTable(0) | |
460 , StringTable(0) | |
461 , StringTableSize(0) | |
462 , ImportDirectory(0) | |
463 , NumberOfImportDirectory(0) { | |
464 // Check that we at least have enough room for a header. | |
465 if (!checkSize(Data, ec, sizeof(coff_file_header))) return; | |
466 | |
467 // The current location in the file where we are looking at. | |
468 uint64_t CurPtr = 0; | |
469 | |
470 // PE header is optional and is present only in executables. If it exists, | |
471 // it is placed right after COFF header. | |
472 bool hasPEHeader = false; | |
473 | |
474 // Check if this is a PE/COFF file. | |
475 if (base()[0] == 0x4d && base()[1] == 0x5a) { | |
476 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte | |
477 // PE signature to find 'normal' COFF header. | |
478 if (!checkSize(Data, ec, 0x3c + 8)) return; | |
479 CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); | |
480 // Check the PE magic bytes. ("PE\0\0") | |
481 if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { | |
482 ec = object_error::parse_failed; | |
483 return; | |
484 } | |
485 CurPtr += 4; // Skip the PE magic bytes. | |
486 hasPEHeader = true; | |
487 } | |
488 | |
489 if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) | |
490 return; | |
491 CurPtr += sizeof(coff_file_header); | |
492 | |
493 if (hasPEHeader) { | |
494 if ((ec = getObject(PE32Header, Data, base() + CurPtr))) | |
495 return; | |
496 if (PE32Header->Magic != 0x10b) { | |
497 // We only support PE32. If this is PE32 (not PE32+), the magic byte | |
498 // should be 0x10b. If this is not PE32, continue as if there's no PE | |
499 // header in this file. | |
500 PE32Header = 0; | |
501 } else if (PE32Header->NumberOfRvaAndSize > 0) { | |
502 const uint8_t *addr = base() + CurPtr + sizeof(pe32_header); | |
503 uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; | |
504 if ((ec = getObject(DataDirectory, Data, addr, size))) | |
505 return; | |
506 } | |
507 CurPtr += COFFHeader->SizeOfOptionalHeader; | |
508 } | |
509 | |
510 if (!COFFHeader->isImportLibrary()) | |
511 if ((ec = getObject(SectionTable, Data, base() + CurPtr, | |
512 COFFHeader->NumberOfSections * sizeof(coff_section)))) | |
513 return; | |
514 | |
515 // Initialize the pointer to the symbol table. | |
516 if (COFFHeader->PointerToSymbolTable != 0) | |
517 if ((ec = initSymbolTablePtr())) | |
518 return; | |
519 | |
520 // Initialize the pointer to the beginning of the import table. | |
521 if ((ec = initImportTablePtr())) | |
522 return; | |
523 | |
524 ec = object_error::success; | |
525 } | |
526 | |
527 symbol_iterator COFFObjectFile::begin_symbols() const { | |
528 DataRefImpl ret; | |
529 ret.p = reinterpret_cast<uintptr_t>(SymbolTable); | |
530 return symbol_iterator(SymbolRef(ret, this)); | |
531 } | |
532 | |
533 symbol_iterator COFFObjectFile::end_symbols() const { | |
534 // The symbol table ends where the string table begins. | |
535 DataRefImpl ret; | |
536 ret.p = reinterpret_cast<uintptr_t>(StringTable); | |
537 return symbol_iterator(SymbolRef(ret, this)); | |
538 } | |
539 | |
540 symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { | |
541 // TODO: implement | |
542 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); | |
543 } | |
544 | |
545 symbol_iterator COFFObjectFile::end_dynamic_symbols() const { | |
546 // TODO: implement | |
547 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); | |
548 } | |
549 | |
550 library_iterator COFFObjectFile::begin_libraries_needed() const { | |
551 // TODO: implement | |
552 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); | |
553 } | |
554 | |
555 library_iterator COFFObjectFile::end_libraries_needed() const { | |
556 // TODO: implement | |
557 report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); | |
558 } | |
559 | |
560 StringRef COFFObjectFile::getLoadName() const { | |
561 // COFF does not have this field. | |
562 return ""; | |
563 } | |
564 | |
565 import_directory_iterator COFFObjectFile::import_directory_begin() const { | |
566 DataRefImpl Imp; | |
567 Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory); | |
568 return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); | |
569 } | |
570 | |
571 import_directory_iterator COFFObjectFile::import_directory_end() const { | |
572 DataRefImpl Imp; | |
573 if (ImportDirectory) { | |
574 Imp.p = reinterpret_cast<uintptr_t>( | |
575 ImportDirectory + (NumberOfImportDirectory - 1)); | |
576 } else { | |
577 Imp.p = 0; | |
578 } | |
579 return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); | |
580 } | |
581 | |
582 section_iterator COFFObjectFile::begin_sections() const { | |
583 DataRefImpl ret; | |
584 ret.p = reinterpret_cast<uintptr_t>(SectionTable); | |
585 return section_iterator(SectionRef(ret, this)); | |
586 } | |
587 | |
588 section_iterator COFFObjectFile::end_sections() const { | |
589 DataRefImpl ret; | |
590 int numSections = COFFHeader->isImportLibrary() | |
591 ? 0 : COFFHeader->NumberOfSections; | |
592 ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections); | |
593 return section_iterator(SectionRef(ret, this)); | |
594 } | |
595 | |
596 uint8_t COFFObjectFile::getBytesInAddress() const { | |
597 return getArch() == Triple::x86_64 ? 8 : 4; | |
598 } | |
599 | |
600 StringRef COFFObjectFile::getFileFormatName() const { | |
601 switch(COFFHeader->Machine) { | |
602 case COFF::IMAGE_FILE_MACHINE_I386: | |
603 return "COFF-i386"; | |
604 case COFF::IMAGE_FILE_MACHINE_AMD64: | |
605 return "COFF-x86-64"; | |
606 default: | |
607 return "COFF-<unknown arch>"; | |
608 } | |
609 } | |
610 | |
611 unsigned COFFObjectFile::getArch() const { | |
612 switch(COFFHeader->Machine) { | |
613 case COFF::IMAGE_FILE_MACHINE_I386: | |
614 return Triple::x86; | |
615 case COFF::IMAGE_FILE_MACHINE_AMD64: | |
616 return Triple::x86_64; | |
617 default: | |
618 return Triple::UnknownArch; | |
619 } | |
620 } | |
621 | |
622 // This method is kept here because lld uses this. As soon as we make | |
623 // lld to use getCOFFHeader, this method will be removed. | |
624 error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { | |
625 return getCOFFHeader(Res); | |
626 } | |
627 | |
628 error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { | |
629 Res = COFFHeader; | |
630 return object_error::success; | |
631 } | |
632 | |
633 error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { | |
634 Res = PE32Header; | |
635 return object_error::success; | |
636 } | |
637 | |
638 error_code COFFObjectFile::getDataDirectory(uint32_t index, | |
639 const data_directory *&Res) const { | |
640 // Error if if there's no data directory or the index is out of range. | |
641 if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize) | |
642 return object_error::parse_failed; | |
643 Res = &DataDirectory[index]; | |
644 return object_error::success; | |
645 } | |
646 | |
647 error_code COFFObjectFile::getSection(int32_t index, | |
648 const coff_section *&Result) const { | |
649 // Check for special index values. | |
650 if (index == COFF::IMAGE_SYM_UNDEFINED || | |
651 index == COFF::IMAGE_SYM_ABSOLUTE || | |
652 index == COFF::IMAGE_SYM_DEBUG) | |
653 Result = NULL; | |
654 else if (index > 0 && index <= COFFHeader->NumberOfSections) | |
655 // We already verified the section table data, so no need to check again. | |
656 Result = SectionTable + (index - 1); | |
657 else | |
658 return object_error::parse_failed; | |
659 return object_error::success; | |
660 } | |
661 | |
662 error_code COFFObjectFile::getString(uint32_t offset, | |
663 StringRef &Result) const { | |
664 if (StringTableSize <= 4) | |
665 // Tried to get a string from an empty string table. | |
666 return object_error::parse_failed; | |
667 if (offset >= StringTableSize) | |
668 return object_error::unexpected_eof; | |
669 Result = StringRef(StringTable + offset); | |
670 return object_error::success; | |
671 } | |
672 | |
673 error_code COFFObjectFile::getSymbol(uint32_t index, | |
674 const coff_symbol *&Result) const { | |
675 if (index < COFFHeader->NumberOfSymbols) | |
676 Result = SymbolTable + index; | |
677 else | |
678 return object_error::parse_failed; | |
679 return object_error::success; | |
680 } | |
681 | |
682 error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, | |
683 StringRef &Res) const { | |
684 // Check for string table entry. First 4 bytes are 0. | |
685 if (symbol->Name.Offset.Zeroes == 0) { | |
686 uint32_t Offset = symbol->Name.Offset.Offset; | |
687 if (error_code ec = getString(Offset, Res)) | |
688 return ec; | |
689 return object_error::success; | |
690 } | |
691 | |
692 if (symbol->Name.ShortName[7] == 0) | |
693 // Null terminated, let ::strlen figure out the length. | |
694 Res = StringRef(symbol->Name.ShortName); | |
695 else | |
696 // Not null terminated, use all 8 bytes. | |
697 Res = StringRef(symbol->Name.ShortName, 8); | |
698 return object_error::success; | |
699 } | |
700 | |
701 ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( | |
702 const coff_symbol *symbol) const { | |
703 const uint8_t *aux = NULL; | |
704 | |
705 if ( symbol->NumberOfAuxSymbols > 0 ) { | |
706 // AUX data comes immediately after the symbol in COFF | |
707 aux = reinterpret_cast<const uint8_t *>(symbol + 1); | |
708 # ifndef NDEBUG | |
709 // Verify that the aux symbol points to a valid entry in the symbol table. | |
710 uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); | |
711 if (offset < COFFHeader->PointerToSymbolTable | |
712 || offset >= COFFHeader->PointerToSymbolTable | |
713 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) | |
714 report_fatal_error("Aux Symbol data was outside of symbol table."); | |
715 | |
716 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) | |
717 == 0 && "Aux Symbol data did not point to the beginning of a symbol"); | |
718 # endif | |
719 } | |
720 return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); | |
721 } | |
722 | |
723 error_code COFFObjectFile::getSectionName(const coff_section *Sec, | |
724 StringRef &Res) const { | |
725 StringRef Name; | |
726 if (Sec->Name[7] == 0) | |
727 // Null terminated, let ::strlen figure out the length. | |
728 Name = Sec->Name; | |
729 else | |
730 // Not null terminated, use all 8 bytes. | |
731 Name = StringRef(Sec->Name, 8); | |
732 | |
733 // Check for string table entry. First byte is '/'. | |
734 if (Name[0] == '/') { | |
735 uint32_t Offset; | |
736 if (Name.substr(1).getAsInteger(10, Offset)) | |
737 return object_error::parse_failed; | |
738 if (error_code ec = getString(Offset, Name)) | |
739 return ec; | |
740 } | |
741 | |
742 Res = Name; | |
743 return object_error::success; | |
744 } | |
745 | |
746 error_code COFFObjectFile::getSectionContents(const coff_section *Sec, | |
747 ArrayRef<uint8_t> &Res) const { | |
748 // The only thing that we need to verify is that the contents is contained | |
749 // within the file bounds. We don't need to make sure it doesn't cover other | |
750 // data, as there's nothing that says that is not allowed. | |
751 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; | |
752 uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; | |
753 if (ConEnd > uintptr_t(Data->getBufferEnd())) | |
754 return object_error::parse_failed; | |
755 Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), | |
756 Sec->SizeOfRawData); | |
757 return object_error::success; | |
758 } | |
759 | |
760 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { | |
761 return reinterpret_cast<const coff_relocation*>(Rel.p); | |
762 } | |
763 error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, | |
764 RelocationRef &Res) const { | |
765 Rel.p = reinterpret_cast<uintptr_t>( | |
766 reinterpret_cast<const coff_relocation*>(Rel.p) + 1); | |
767 Res = RelocationRef(Rel, this); | |
768 return object_error::success; | |
769 } | |
770 error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, | |
771 uint64_t &Res) const { | |
772 report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); | |
773 } | |
774 error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, | |
775 uint64_t &Res) const { | |
776 Res = toRel(Rel)->VirtualAddress; | |
777 return object_error::success; | |
778 } | |
779 symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { | |
780 const coff_relocation* R = toRel(Rel); | |
781 DataRefImpl Symb; | |
782 Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); | |
783 return symbol_iterator(SymbolRef(Symb, this)); | |
784 } | |
785 error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, | |
786 uint64_t &Res) const { | |
787 const coff_relocation* R = toRel(Rel); | |
788 Res = R->Type; | |
789 return object_error::success; | |
790 } | |
791 | |
792 const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { | |
793 return toSec(It->getRawDataRefImpl()); | |
794 } | |
795 | |
796 const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { | |
797 return toSymb(It->getRawDataRefImpl()); | |
798 } | |
799 | |
800 const coff_relocation *COFFObjectFile::getCOFFRelocation( | |
801 relocation_iterator &It) const { | |
802 return toRel(It->getRawDataRefImpl()); | |
803 } | |
804 | |
805 #define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ | |
806 case COFF::enum: res = #enum; break; | |
807 | |
808 error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, | |
809 SmallVectorImpl<char> &Result) const { | |
810 const coff_relocation *reloc = toRel(Rel); | |
811 StringRef res; | |
812 switch (COFFHeader->Machine) { | |
813 case COFF::IMAGE_FILE_MACHINE_AMD64: | |
814 switch (reloc->Type) { | |
815 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); | |
816 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); | |
817 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); | |
818 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); | |
819 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); | |
820 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); | |
821 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); | |
822 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); | |
823 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); | |
824 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); | |
825 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); | |
826 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); | |
827 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); | |
828 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); | |
829 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); | |
830 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); | |
831 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); | |
832 default: | |
833 res = "Unknown"; | |
834 } | |
835 break; | |
836 case COFF::IMAGE_FILE_MACHINE_I386: | |
837 switch (reloc->Type) { | |
838 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); | |
839 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); | |
840 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); | |
841 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); | |
842 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); | |
843 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); | |
844 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); | |
845 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); | |
846 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); | |
847 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); | |
848 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); | |
849 default: | |
850 res = "Unknown"; | |
851 } | |
852 break; | |
853 default: | |
854 res = "Unknown"; | |
855 } | |
856 Result.append(res.begin(), res.end()); | |
857 return object_error::success; | |
858 } | |
859 | |
860 #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME | |
861 | |
862 error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, | |
863 SmallVectorImpl<char> &Result) const { | |
864 const coff_relocation *reloc = toRel(Rel); | |
865 const coff_symbol *symb = 0; | |
866 if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; | |
867 DataRefImpl sym; | |
868 sym.p = reinterpret_cast<uintptr_t>(symb); | |
869 StringRef symname; | |
870 if (error_code ec = getSymbolName(sym, symname)) return ec; | |
871 Result.append(symname.begin(), symname.end()); | |
872 return object_error::success; | |
873 } | |
874 | |
875 error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, | |
876 LibraryRef &Result) const { | |
877 report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); | |
878 } | |
879 | |
880 error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, | |
881 StringRef &Result) const { | |
882 report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); | |
883 } | |
884 | |
885 bool ImportDirectoryEntryRef:: | |
886 operator==(const ImportDirectoryEntryRef &Other) const { | |
887 return ImportDirectoryPimpl == Other.ImportDirectoryPimpl; | |
888 } | |
889 | |
890 static const import_directory_table_entry *toImportEntry(DataRefImpl Imp) { | |
891 return reinterpret_cast<const import_directory_table_entry *>(Imp.p); | |
892 } | |
893 | |
894 error_code | |
895 ImportDirectoryEntryRef::getNext(ImportDirectoryEntryRef &Result) const { | |
896 const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); | |
897 Dir += 1; | |
898 DataRefImpl Next; | |
899 Next.p = reinterpret_cast<uintptr_t>(Dir); | |
900 Result = ImportDirectoryEntryRef(Next, OwningObject); | |
901 return object_error::success; | |
902 } | |
903 | |
904 error_code ImportDirectoryEntryRef:: | |
905 getImportTableEntry(const import_directory_table_entry *&Result) const { | |
906 Result = toImportEntry(ImportDirectoryPimpl); | |
907 return object_error::success; | |
908 } | |
909 | |
910 error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { | |
911 const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); | |
912 uintptr_t IntPtr = 0; | |
913 if (error_code ec = OwningObject->getRvaPtr(Dir->NameRVA, IntPtr)) | |
914 return ec; | |
915 const char *Ptr = reinterpret_cast<const char *>(IntPtr); | |
916 Result = StringRef(Ptr); | |
917 return object_error::success; | |
918 } | |
919 | |
920 error_code ImportDirectoryEntryRef::getImportLookupEntry( | |
921 const import_lookup_table_entry32 *&Result) const { | |
922 const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); | |
923 uintptr_t IntPtr = 0; | |
924 if (error_code ec = OwningObject->getRvaPtr( | |
925 Dir->ImportLookupTableRVA, IntPtr)) | |
926 return ec; | |
927 Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); | |
928 return object_error::success; | |
929 } | |
930 | |
931 namespace llvm { | |
932 | |
933 ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { | |
934 error_code ec; | |
935 return new COFFObjectFile(Object, ec); | |
936 } | |
937 | |
938 } // end namespace llvm |