blob: f3f2532406af43c311f115dea748844812d591ea [file] [log] [blame]
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +00001//===- 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
Michael J. Spencer001c9202011-06-25 17:54:50 +000014#include "llvm/Object/COFF.h"
Michael J. Spencer1f6e3f92012-03-19 20:27:37 +000015#include "llvm/ADT/ArrayRef.h"
Michael J. Spencer4344b1e2011-10-07 19:25:32 +000016#include "llvm/ADT/SmallString.h"
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +000017#include "llvm/ADT/StringSwitch.h"
18#include "llvm/ADT/Triple.h"
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +000019
20using namespace llvm;
21using namespace object;
22
23namespace {
24using support::ulittle8_t;
25using support::ulittle16_t;
26using support::ulittle32_t;
27using support::little16_t;
28}
29
Michael J. Spencer25b15772011-06-25 17:55:23 +000030namespace {
31// Returns false if size is greater than the buffer size. And sets ec.
32bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
33 if (m->getBufferSize() < size) {
34 ec = object_error::unexpected_eof;
35 return false;
36 }
37 return true;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +000038}
39
Rui Ueyama2f6c0482013-07-19 23:23:29 +000040// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
41// Returns unexpected_eof if error.
42template<typename T>
43error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr,
44 const size_t Size = sizeof(T)) {
45 uintptr_t Addr = uintptr_t(Ptr);
46 if (Addr + Size < Addr ||
47 Addr + Size < Size ||
48 Addr + Size > uintptr_t(M->getBufferEnd())) {
49 return object_error::unexpected_eof;
Michael J. Spencer25b15772011-06-25 17:55:23 +000050 }
Rui Ueyama2f6c0482013-07-19 23:23:29 +000051 Obj = reinterpret_cast<const T *>(Addr);
52 return object_error::success;
Michael J. Spencer25b15772011-06-25 17:55:23 +000053}
54}
55
56const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
57 const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
58
59# ifndef NDEBUG
60 // Verify that the symbol points to a valid entry in the symbol table.
61 uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
Rui Ueyama4bf771b2013-06-12 19:10:33 +000062 if (offset < COFFHeader->PointerToSymbolTable
63 || offset >= COFFHeader->PointerToSymbolTable
64 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
Michael J. Spencer25b15772011-06-25 17:55:23 +000065 report_fatal_error("Symbol was outside of symbol table.");
66
Rui Ueyama4bf771b2013-06-12 19:10:33 +000067 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
Michael J. Spencer25b15772011-06-25 17:55:23 +000068 == 0 && "Symbol did not point to the beginning of a symbol");
69# endif
70
71 return addr;
72}
73
74const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
75 const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
76
77# ifndef NDEBUG
78 // Verify that the section points to a valid entry in the section table.
79 if (addr < SectionTable
Rui Ueyama4bf771b2013-06-12 19:10:33 +000080 || addr >= (SectionTable + COFFHeader->NumberOfSections))
Michael J. Spencer25b15772011-06-25 17:55:23 +000081 report_fatal_error("Section was outside of section table.");
82
83 uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
84 assert(offset % sizeof(coff_section) == 0 &&
85 "Section did not point to the beginning of a section");
86# endif
87
88 return addr;
89}
90
91error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb,
92 SymbolRef &Result) const {
93 const coff_symbol *symb = toSymb(Symb);
94 symb += 1 + symb->NumberOfAuxSymbols;
95 Symb.p = reinterpret_cast<uintptr_t>(symb);
96 Result = SymbolRef(Symb, this);
97 return object_error::success;
98}
99
100 error_code COFFObjectFile::getSymbolName(DataRefImpl Symb,
101 StringRef &Result) const {
102 const coff_symbol *symb = toSymb(Symb);
Michael J. Spencer0e752cb2011-10-17 23:53:56 +0000103 return getSymbolName(symb, Result);
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000104}
105
Danil Malyshevb0436a72011-11-29 17:40:10 +0000106error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb,
Michael J. Spencer25b15772011-06-25 17:55:23 +0000107 uint64_t &Result) const {
108 const coff_symbol *symb = toSymb(Symb);
Michael J. Spencer64388ce2011-07-05 14:48:59 +0000109 const coff_section *Section = NULL;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000110 if (error_code ec = getSection(symb->SectionNumber, Section))
111 return ec;
112 char Type;
113 if (error_code ec = getSymbolNMTypeChar(Symb, Type))
114 return ec;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000115 if (Type == 'U' || Type == 'w')
Michael J. Spencer25b15772011-06-25 17:55:23 +0000116 Result = UnknownAddressOrSize;
117 else if (Section)
Danil Malyshevb0436a72011-11-29 17:40:10 +0000118 Result = Section->PointerToRawData + symb->Value;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000119 else
120 Result = symb->Value;
121 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000122}
123
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000124error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb,
125 uint64_t &Result) const {
126 const coff_symbol *symb = toSymb(Symb);
127 const coff_section *Section = NULL;
128 if (error_code ec = getSection(symb->SectionNumber, Section))
129 return ec;
130 char Type;
131 if (error_code ec = getSymbolNMTypeChar(Symb, Type))
132 return ec;
133 if (Type == 'U' || Type == 'w')
134 Result = UnknownAddressOrSize;
135 else if (Section)
Danil Malyshevb0436a72011-11-29 17:40:10 +0000136 Result = Section->VirtualAddress + symb->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000137 else
Danil Malyshevb0436a72011-11-29 17:40:10 +0000138 Result = symb->Value;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000139 return object_error::success;
140}
141
142error_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
Michael J. Spencer1130a792011-10-17 20:19:29 +0000143 SymbolRef::Type &Result) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000144 const coff_symbol *symb = toSymb(Symb);
145 Result = SymbolRef::ST_Other;
146 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
147 symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
David Meyer2c677272012-02-29 02:11:55 +0000148 Result = SymbolRef::ST_Unknown;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000149 } else {
Michael J. Spencer5e3a0822011-10-18 19:31:59 +0000150 if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000151 Result = SymbolRef::ST_Function;
152 } else {
153 char Type;
154 if (error_code ec = getSymbolNMTypeChar(Symb, Type))
155 return ec;
156 if (Type == 'r' || Type == 'R') {
157 Result = SymbolRef::ST_Data;
158 }
159 }
160 }
161 return object_error::success;
162}
163
David Meyerc46255a2012-02-28 23:47:53 +0000164error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb,
165 uint32_t &Result) const {
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000166 const coff_symbol *symb = toSymb(Symb);
David Meyerc46255a2012-02-28 23:47:53 +0000167 Result = SymbolRef::SF_None;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000168
David Meyer2c677272012-02-29 02:11:55 +0000169 // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common
170
171 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
172 symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
173 Result |= SymbolRef::SF_Undefined;
David Meyerc46255a2012-02-28 23:47:53 +0000174
175 // TODO: This are certainly too restrictive.
176 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
177 Result |= SymbolRef::SF_Global;
178
179 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
180 Result |= SymbolRef::SF_Weak;
181
182 if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE)
183 Result |= SymbolRef::SF_Absolute;
184
Michael J. Spencerc38c36a2011-10-17 23:54:22 +0000185 return object_error::success;
186}
187
Michael J. Spencer25b15772011-06-25 17:55:23 +0000188error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb,
189 uint64_t &Result) const {
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000190 // FIXME: Return the correct size. This requires looking at all the symbols
191 // in the same section as this symbol, and looking for either the next
192 // symbol, or the end of the section.
Michael J. Spencer25b15772011-06-25 17:55:23 +0000193 const coff_symbol *symb = toSymb(Symb);
Michael J. Spencer64388ce2011-07-05 14:48:59 +0000194 const coff_section *Section = NULL;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000195 if (error_code ec = getSection(symb->SectionNumber, Section))
196 return ec;
197 char Type;
198 if (error_code ec = getSymbolNMTypeChar(Symb, Type))
199 return ec;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000200 if (Type == 'U' || Type == 'w')
Michael J. Spencer25b15772011-06-25 17:55:23 +0000201 Result = UnknownAddressOrSize;
202 else if (Section)
203 Result = Section->SizeOfRawData - symb->Value;
204 else
205 Result = 0;
206 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000207}
208
Michael J. Spencer25b15772011-06-25 17:55:23 +0000209error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
210 char &Result) const {
211 const coff_symbol *symb = toSymb(Symb);
212 StringRef name;
213 if (error_code ec = getSymbolName(Symb, name))
214 return ec;
215 char ret = StringSwitch<char>(name)
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000216 .StartsWith(".debug", 'N')
217 .StartsWith(".sxdata", 'N')
218 .Default('?');
219
Michael J. Spencer25b15772011-06-25 17:55:23 +0000220 if (ret != '?') {
221 Result = ret;
222 return object_error::success;
223 }
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000224
225 uint32_t Characteristics = 0;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000226 if (symb->SectionNumber > 0) {
Michael J. Spencer64388ce2011-07-05 14:48:59 +0000227 const coff_section *Section = NULL;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000228 if (error_code ec = getSection(symb->SectionNumber, Section))
229 return ec;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000230 Characteristics = Section->Characteristics;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000231 }
232
233 switch (symb->SectionNumber) {
234 case COFF::IMAGE_SYM_UNDEFINED:
235 // Check storage classes.
Michael J. Spencer25b15772011-06-25 17:55:23 +0000236 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
237 Result = 'w';
238 return object_error::success; // Don't do ::toupper.
Michael J. Spencer11ba26d2011-11-16 23:36:12 +0000239 } else if (symb->Value != 0) // Check for common symbols.
240 ret = 'c';
241 else
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000242 ret = 'u';
243 break;
244 case COFF::IMAGE_SYM_ABSOLUTE:
245 ret = 'a';
246 break;
247 case COFF::IMAGE_SYM_DEBUG:
248 ret = 'n';
249 break;
250 default:
251 // Check section type.
252 if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
253 ret = 't';
254 else if ( Characteristics & COFF::IMAGE_SCN_MEM_READ
255 && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
256 ret = 'r';
257 else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
258 ret = 'd';
259 else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
260 ret = 'b';
261 else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
262 ret = 'i';
263
264 // Check for section symbol.
265 else if ( symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC
266 && symb->Value == 0)
267 ret = 's';
268 }
269
270 if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
Guy Benyei87d0b9e2013-02-12 21:21:59 +0000271 ret = ::toupper(static_cast<unsigned char>(ret));
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000272
Michael J. Spencer25b15772011-06-25 17:55:23 +0000273 Result = ret;
274 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000275}
276
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000277error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb,
278 section_iterator &Result) const {
279 const coff_symbol *symb = toSymb(Symb);
280 if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED)
281 Result = end_sections();
282 else {
Daniel Dunbara483fc82011-11-28 22:19:32 +0000283 const coff_section *sec = 0;
Michael J. Spencer9b2b8122011-10-17 23:54:46 +0000284 if (error_code ec = getSection(symb->SectionNumber, sec)) return ec;
285 DataRefImpl Sec;
286 Sec.p = reinterpret_cast<uintptr_t>(sec);
287 Result = section_iterator(SectionRef(Sec, this));
288 }
289 return object_error::success;
290}
291
Tim Northovera41dce32012-10-29 10:47:00 +0000292error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb,
293 uint64_t &Val) const {
294 report_fatal_error("getSymbolValue unimplemented in COFFObjectFile");
295}
296
Michael J. Spencer25b15772011-06-25 17:55:23 +0000297error_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
298 SectionRef &Result) const {
299 const coff_section *sec = toSec(Sec);
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000300 sec += 1;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000301 Sec.p = reinterpret_cast<uintptr_t>(sec);
302 Result = SectionRef(Sec, this);
303 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000304}
305
Michael J. Spencer25b15772011-06-25 17:55:23 +0000306error_code COFFObjectFile::getSectionName(DataRefImpl Sec,
307 StringRef &Result) const {
308 const coff_section *sec = toSec(Sec);
Michael J. Spencerb35a8962012-03-19 20:27:15 +0000309 return getSectionName(sec, Result);
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000310}
311
Michael J. Spencer25b15772011-06-25 17:55:23 +0000312error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
313 uint64_t &Result) const {
314 const coff_section *sec = toSec(Sec);
315 Result = sec->VirtualAddress;
316 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000317}
318
Michael J. Spencer25b15772011-06-25 17:55:23 +0000319error_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
320 uint64_t &Result) const {
321 const coff_section *sec = toSec(Sec);
322 Result = sec->SizeOfRawData;
323 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000324}
325
Michael J. Spencer25b15772011-06-25 17:55:23 +0000326error_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
327 StringRef &Result) const {
328 const coff_section *sec = toSec(Sec);
Michael J. Spencer1f6e3f92012-03-19 20:27:37 +0000329 ArrayRef<uint8_t> Res;
330 error_code EC = getSectionContents(sec, Res);
331 Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
332 return EC;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000333}
334
Michael J. Spencere2f2f072011-10-10 21:55:43 +0000335error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec,
336 uint64_t &Res) const {
337 const coff_section *sec = toSec(Sec);
338 if (!sec)
339 return object_error::parse_failed;
340 Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1);
341 return object_error::success;
342}
343
Michael J. Spencer25b15772011-06-25 17:55:23 +0000344error_code COFFObjectFile::isSectionText(DataRefImpl Sec,
345 bool &Result) const {
346 const coff_section *sec = toSec(Sec);
347 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
348 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000349}
350
Michael J. Spencer13afc5e2011-09-28 20:57:30 +0000351error_code COFFObjectFile::isSectionData(DataRefImpl Sec,
352 bool &Result) const {
353 const coff_section *sec = toSec(Sec);
354 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
355 return object_error::success;
356}
357
358error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
359 bool &Result) const {
360 const coff_section *sec = toSec(Sec);
361 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
362 return object_error::success;
363}
364
Preston Gurdc68dda82012-04-12 20:13:57 +0000365error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
366 bool &Result) const {
367 // FIXME: Unimplemented
368 Result = true;
369 return object_error::success;
370}
371
372error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec,
373 bool &Result) const {
374 const coff_section *sec = toSec(Sec);
375 Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
376 return object_error::success;
377}
378
379error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec,
380 bool &Result) const {
Andrew Kaylor30b20eb2012-10-10 01:45:52 +0000381 // FIXME: Unimplemented.
Preston Gurdc68dda82012-04-12 20:13:57 +0000382 Result = false;
383 return object_error::success;
384}
385
Andrew Kaylor3a129c82012-10-10 01:41:33 +0000386error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
387 bool &Result) const {
388 // FIXME: Unimplemented.
389 Result = false;
390 return object_error::success;
391}
392
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000393error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
394 DataRefImpl Symb,
395 bool &Result) const {
Michael J. Spencerbff6f862011-10-13 20:36:54 +0000396 const coff_section *sec = toSec(Sec);
397 const coff_symbol *symb = toSymb(Symb);
Daniel Dunbara483fc82011-11-28 22:19:32 +0000398 const coff_section *symb_sec = 0;
Michael J. Spencerbff6f862011-10-13 20:36:54 +0000399 if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
400 if (symb_sec == sec)
401 Result = true;
402 else
403 Result = false;
Benjamin Kramer07ea23a2011-07-15 18:39:21 +0000404 return object_error::success;
405}
406
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000407relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
408 const coff_section *sec = toSec(Sec);
409 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000410 if (sec->NumberOfRelocations == 0)
411 ret.p = 0;
412 else
413 ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
414
415 return relocation_iterator(RelocationRef(ret, this));
416}
417
418relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
419 const coff_section *sec = toSec(Sec);
420 DataRefImpl ret;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000421 if (sec->NumberOfRelocations == 0)
422 ret.p = 0;
423 else
424 ret.p = reinterpret_cast<uintptr_t>(
425 reinterpret_cast<const coff_relocation*>(
426 base() + sec->PointerToRelocations)
427 + sec->NumberOfRelocations);
428
429 return relocation_iterator(RelocationRef(ret, this));
430}
431
Michael J. Spencer001c9202011-06-25 17:54:50 +0000432COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
Rafael Espindola2c6f9972013-04-07 16:40:00 +0000433 : ObjectFile(Binary::ID_COFF, Object)
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000434 , COFFHeader(0)
435 , PE32Header(0)
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000436 , DataDirectory(0)
Michael J. Spencer7151ddd2011-11-08 23:34:07 +0000437 , SectionTable(0)
438 , SymbolTable(0)
439 , StringTable(0)
440 , StringTableSize(0) {
Michael J. Spencer25b15772011-06-25 17:55:23 +0000441 // Check that we at least have enough room for a header.
442 if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
Eric Christopher539d8d82011-04-03 22:53:19 +0000443
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000444 // The current location in the file where we are looking at.
445 uint64_t CurPtr = 0;
446
447 // PE header is optional and is present only in executables. If it exists,
448 // it is placed right after COFF header.
449 bool hasPEHeader = false;
Eric Christopher539d8d82011-04-03 22:53:19 +0000450
Michael J. Spencer25b15772011-06-25 17:55:23 +0000451 // Check if this is a PE/COFF file.
Michael J. Spencer001c9202011-06-25 17:54:50 +0000452 if (base()[0] == 0x4d && base()[1] == 0x5a) {
Eric Christopher539d8d82011-04-03 22:53:19 +0000453 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
454 // PE signature to find 'normal' COFF header.
Michael J. Spencer25b15772011-06-25 17:55:23 +0000455 if (!checkSize(Data, ec, 0x3c + 8)) return;
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000456 CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c);
457 // Check the PE magic bytes. ("PE\0\0")
458 if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) {
Michael J. Spencer25b15772011-06-25 17:55:23 +0000459 ec = object_error::parse_failed;
460 return;
461 }
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000462 CurPtr += 4; // Skip the PE magic bytes.
463 hasPEHeader = true;
Eric Christopher539d8d82011-04-03 22:53:19 +0000464 }
465
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000466 if ((ec = getObject(COFFHeader, Data, base() + CurPtr)))
Michael J. Spencer25b15772011-06-25 17:55:23 +0000467 return;
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000468 CurPtr += sizeof(coff_file_header);
469
470 if (hasPEHeader) {
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000471 if ((ec = getObject(PE32Header, Data, base() + CurPtr)))
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000472 return;
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000473 if (PE32Header->Magic != 0x10b) {
474 // We only support PE32. If this is PE32 (not PE32+), the magic byte
475 // should be 0x10b. If this is not PE32, continue as if there's no PE
476 // header in this file.
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000477 PE32Header = 0;
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000478 } else if (PE32Header->NumberOfRvaAndSize > 0) {
479 const uint8_t *addr = base() + CurPtr + sizeof(pe32_header);
480 uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
481 if ((ec = getObject(DataDirectory, Data, addr, size)))
482 return;
483 }
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000484 CurPtr += COFFHeader->SizeOfOptionalHeader;
485 }
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000486
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000487 if ((ec = getObject(SectionTable, Data, base() + CurPtr,
488 COFFHeader->NumberOfSections * sizeof(coff_section))))
Michael J. Spencer25b15772011-06-25 17:55:23 +0000489 return;
490
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000491 if (COFFHeader->PointerToSymbolTable != 0) {
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000492 if ((ec = getObject(SymbolTable, Data,
493 base() + COFFHeader->PointerToSymbolTable,
494 COFFHeader->NumberOfSymbols * sizeof(coff_symbol))))
Michael J. Spencer7151ddd2011-11-08 23:34:07 +0000495 return;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000496
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000497 // Find string table. The first four byte of the string table contains the
498 // total size of the string table, including the size field itself. If the
499 // string table is empty, the value of the first four byte would be 4.
500 const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable
501 + COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
502 const ulittle32_t *StringTableSizePtr;
503 if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr)))
504 return;
505 StringTableSize = *StringTableSizePtr;
506 if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize)))
Michael J. Spencer7151ddd2011-11-08 23:34:07 +0000507 return;
Michael J. Spencer25b15772011-06-25 17:55:23 +0000508
Michael J. Spencer7151ddd2011-11-08 23:34:07 +0000509 // Check that the string table is null terminated if has any in it.
510 if (StringTableSize < 4
511 || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
512 ec = object_error::parse_failed;
513 return;
514 }
Michael J. Spencer25b15772011-06-25 17:55:23 +0000515 }
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000516
Michael J. Spencer25b15772011-06-25 17:55:23 +0000517 ec = object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000518}
519
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000520symbol_iterator COFFObjectFile::begin_symbols() const {
Michael J. Spencer7acdb4d2011-01-21 02:27:02 +0000521 DataRefImpl ret;
522 ret.p = reinterpret_cast<intptr_t>(SymbolTable);
523 return symbol_iterator(SymbolRef(ret, this));
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000524}
525
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000526symbol_iterator COFFObjectFile::end_symbols() const {
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000527 // The symbol table ends where the string table begins.
Michael J. Spencer7acdb4d2011-01-21 02:27:02 +0000528 DataRefImpl ret;
529 ret.p = reinterpret_cast<intptr_t>(StringTable);
530 return symbol_iterator(SymbolRef(ret, this));
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000531}
532
Michael J. Spencerdfa18962012-02-28 00:40:37 +0000533symbol_iterator COFFObjectFile::begin_dynamic_symbols() const {
534 // TODO: implement
535 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
536}
537
538symbol_iterator COFFObjectFile::end_dynamic_symbols() const {
539 // TODO: implement
540 report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
541}
542
David Meyer5c2b4ea2012-03-01 01:36:50 +0000543library_iterator COFFObjectFile::begin_libraries_needed() const {
544 // TODO: implement
545 report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
546}
547
548library_iterator COFFObjectFile::end_libraries_needed() const {
549 // TODO: implement
550 report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
551}
552
David Meyer97f77872012-03-01 22:19:54 +0000553StringRef COFFObjectFile::getLoadName() const {
554 // COFF does not have this field.
555 return "";
556}
557
558
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000559section_iterator COFFObjectFile::begin_sections() const {
Michael J. Spencer7acdb4d2011-01-21 02:27:02 +0000560 DataRefImpl ret;
561 ret.p = reinterpret_cast<intptr_t>(SectionTable);
562 return section_iterator(SectionRef(ret, this));
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000563}
564
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000565section_iterator COFFObjectFile::end_sections() const {
Michael J. Spencer7acdb4d2011-01-21 02:27:02 +0000566 DataRefImpl ret;
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000567 ret.p = reinterpret_cast<intptr_t>(SectionTable + COFFHeader->NumberOfSections);
Michael J. Spencer7acdb4d2011-01-21 02:27:02 +0000568 return section_iterator(SectionRef(ret, this));
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000569}
570
571uint8_t COFFObjectFile::getBytesInAddress() const {
Michael J. Spencer7acdb4d2011-01-21 02:27:02 +0000572 return getArch() == Triple::x86_64 ? 8 : 4;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000573}
574
575StringRef COFFObjectFile::getFileFormatName() const {
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000576 switch(COFFHeader->Machine) {
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000577 case COFF::IMAGE_FILE_MACHINE_I386:
578 return "COFF-i386";
579 case COFF::IMAGE_FILE_MACHINE_AMD64:
580 return "COFF-x86-64";
581 default:
582 return "COFF-<unknown arch>";
583 }
584}
585
586unsigned COFFObjectFile::getArch() const {
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000587 switch(COFFHeader->Machine) {
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000588 case COFF::IMAGE_FILE_MACHINE_I386:
589 return Triple::x86;
590 case COFF::IMAGE_FILE_MACHINE_AMD64:
591 return Triple::x86_64;
592 default:
593 return Triple::UnknownArch;
594 }
595}
596
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000597// This method is kept here because lld uses this. As soon as we make
598// lld to use getCOFFHeader, this method will be removed.
Michael J. Spencer0e752cb2011-10-17 23:53:56 +0000599error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000600 return getCOFFHeader(Res);
601}
602
603error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
604 Res = COFFHeader;
605 return object_error::success;
606}
607
608error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
609 Res = PE32Header;
Michael J. Spencer0e752cb2011-10-17 23:53:56 +0000610 return object_error::success;
611}
612
Rui Ueyama2f6c0482013-07-19 23:23:29 +0000613error_code COFFObjectFile::getDataDirectory(uint32_t index,
614 const data_directory *&Res) const {
615 // Error if if there's no data directory or the index is out of range.
616 if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize)
617 return object_error::parse_failed;
618 Res = &DataDirectory[index];
619 return object_error::success;
620}
621
Michael J. Spencer25b15772011-06-25 17:55:23 +0000622error_code COFFObjectFile::getSection(int32_t index,
623 const coff_section *&Result) const {
624 // Check for special index values.
625 if (index == COFF::IMAGE_SYM_UNDEFINED ||
626 index == COFF::IMAGE_SYM_ABSOLUTE ||
627 index == COFF::IMAGE_SYM_DEBUG)
628 Result = NULL;
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000629 else if (index > 0 && index <= COFFHeader->NumberOfSections)
Michael J. Spencer25b15772011-06-25 17:55:23 +0000630 // We already verified the section table data, so no need to check again.
631 Result = SectionTable + (index - 1);
632 else
633 return object_error::parse_failed;
634 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000635}
636
Michael J. Spencer25b15772011-06-25 17:55:23 +0000637error_code COFFObjectFile::getString(uint32_t offset,
638 StringRef &Result) const {
639 if (StringTableSize <= 4)
640 // Tried to get a string from an empty string table.
641 return object_error::parse_failed;
642 if (offset >= StringTableSize)
643 return object_error::unexpected_eof;
644 Result = StringRef(StringTable + offset);
645 return object_error::success;
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000646}
647
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000648error_code COFFObjectFile::getSymbol(uint32_t index,
649 const coff_symbol *&Result) const {
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000650 if (index < COFFHeader->NumberOfSymbols)
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000651 Result = SymbolTable + index;
652 else
653 return object_error::parse_failed;
654 return object_error::success;
655}
656
Michael J. Spencer0e752cb2011-10-17 23:53:56 +0000657error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol,
658 StringRef &Res) const {
659 // Check for string table entry. First 4 bytes are 0.
660 if (symbol->Name.Offset.Zeroes == 0) {
661 uint32_t Offset = symbol->Name.Offset.Offset;
662 if (error_code ec = getString(Offset, Res))
663 return ec;
664 return object_error::success;
665 }
666
667 if (symbol->Name.ShortName[7] == 0)
668 // Null terminated, let ::strlen figure out the length.
669 Res = StringRef(symbol->Name.ShortName);
670 else
671 // Not null terminated, use all 8 bytes.
672 Res = StringRef(symbol->Name.ShortName, 8);
673 return object_error::success;
674}
675
Marshall Clowd4d03e02012-06-15 01:08:25 +0000676ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData(
677 const coff_symbol *symbol) const {
678 const uint8_t *aux = NULL;
679
680 if ( symbol->NumberOfAuxSymbols > 0 ) {
681 // AUX data comes immediately after the symbol in COFF
682 aux = reinterpret_cast<const uint8_t *>(symbol + 1);
683# ifndef NDEBUG
684 // Verify that the aux symbol points to a valid entry in the symbol table.
685 uintptr_t offset = uintptr_t(aux) - uintptr_t(base());
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000686 if (offset < COFFHeader->PointerToSymbolTable
687 || offset >= COFFHeader->PointerToSymbolTable
688 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
Marshall Clowd4d03e02012-06-15 01:08:25 +0000689 report_fatal_error("Aux Symbol data was outside of symbol table.");
690
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000691 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
Marshall Clowd4d03e02012-06-15 01:08:25 +0000692 == 0 && "Aux Symbol data did not point to the beginning of a symbol");
Marshall Clowd4d03e02012-06-15 01:08:25 +0000693# endif
Marshall Clow45aad162012-06-15 01:15:47 +0000694 }
Marshall Clowd4d03e02012-06-15 01:08:25 +0000695 return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol));
696}
697
Michael J. Spencerb35a8962012-03-19 20:27:15 +0000698error_code COFFObjectFile::getSectionName(const coff_section *Sec,
699 StringRef &Res) const {
700 StringRef Name;
701 if (Sec->Name[7] == 0)
702 // Null terminated, let ::strlen figure out the length.
703 Name = Sec->Name;
704 else
705 // Not null terminated, use all 8 bytes.
706 Name = StringRef(Sec->Name, 8);
707
708 // Check for string table entry. First byte is '/'.
709 if (Name[0] == '/') {
710 uint32_t Offset;
711 if (Name.substr(1).getAsInteger(10, Offset))
712 return object_error::parse_failed;
713 if (error_code ec = getString(Offset, Name))
714 return ec;
715 }
716
717 Res = Name;
718 return object_error::success;
719}
720
Michael J. Spencer1f6e3f92012-03-19 20:27:37 +0000721error_code COFFObjectFile::getSectionContents(const coff_section *Sec,
722 ArrayRef<uint8_t> &Res) const {
723 // The only thing that we need to verify is that the contents is contained
724 // within the file bounds. We don't need to make sure it doesn't cover other
725 // data, as there's nothing that says that is not allowed.
726 uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
727 uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
728 if (ConEnd > uintptr_t(Data->getBufferEnd()))
729 return object_error::parse_failed;
730 Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart),
731 Sec->SizeOfRawData);
732 return object_error::success;
733}
734
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000735const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000736 return reinterpret_cast<const coff_relocation*>(Rel.p);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000737}
738error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
739 RelocationRef &Res) const {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000740 Rel.p = reinterpret_cast<uintptr_t>(
741 reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000742 Res = RelocationRef(Rel, this);
743 return object_error::success;
744}
745error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
746 uint64_t &Res) const {
Rafael Espindola956ca722013-04-25 12:28:45 +0000747 report_fatal_error("getRelocationAddress not implemented in COFFObjectFile");
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000748}
Danil Malyshevb0436a72011-11-29 17:40:10 +0000749error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel,
750 uint64_t &Res) const {
751 Res = toRel(Rel)->VirtualAddress;
752 return object_error::success;
753}
Rafael Espindola6c1202c2013-06-05 01:33:53 +0000754symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000755 const coff_relocation* R = toRel(Rel);
756 DataRefImpl Symb;
757 Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
Rafael Espindola6c1202c2013-06-05 01:33:53 +0000758 return symbol_iterator(SymbolRef(Symb, this));
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000759}
760error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
Owen Anderson9472b8d2011-10-26 17:08:49 +0000761 uint64_t &Res) const {
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000762 const coff_relocation* R = toRel(Rel);
763 Res = R->Type;
764 return object_error::success;
765}
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000766
Marshall Clowd4d03e02012-06-15 01:08:25 +0000767const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const {
768 return toSec(It->getRawDataRefImpl());
769}
770
771const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const {
772 return toSymb(It->getRawDataRefImpl());
773}
774
Marshall Clow9ac0f1d2012-06-18 19:47:16 +0000775const coff_relocation *COFFObjectFile::getCOFFRelocation(
776 relocation_iterator &It) const {
777 return toRel(It->getRawDataRefImpl());
778}
779
Marshall Clowd4d03e02012-06-15 01:08:25 +0000780
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000781#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
782 case COFF::enum: res = #enum; break;
783
784error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
785 SmallVectorImpl<char> &Result) const {
786 const coff_relocation *reloc = toRel(Rel);
787 StringRef res;
Rui Ueyama4bf771b2013-06-12 19:10:33 +0000788 switch (COFFHeader->Machine) {
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000789 case COFF::IMAGE_FILE_MACHINE_AMD64:
790 switch (reloc->Type) {
791 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
792 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
793 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
794 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
795 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
796 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
797 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
798 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
799 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
800 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
801 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
802 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
803 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
804 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
805 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
806 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
807 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
808 default:
809 res = "Unknown";
810 }
811 break;
812 case COFF::IMAGE_FILE_MACHINE_I386:
813 switch (reloc->Type) {
814 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
815 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
816 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
817 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
818 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
819 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
820 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
821 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
822 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
823 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
824 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
825 default:
826 res = "Unknown";
827 }
828 break;
829 default:
830 res = "Unknown";
831 }
832 Result.append(res.begin(), res.end());
833 return object_error::success;
834}
835
836#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
837
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000838error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
839 SmallVectorImpl<char> &Result) const {
840 const coff_relocation *reloc = toRel(Rel);
NAKAMURA Takumi48f248a2011-10-08 11:22:53 +0000841 const coff_symbol *symb = 0;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000842 if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
843 DataRefImpl sym;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000844 sym.p = reinterpret_cast<uintptr_t>(symb);
845 StringRef symname;
846 if (error_code ec = getSymbolName(sym, symname)) return ec;
847 Result.append(symname.begin(), symname.end());
848 return object_error::success;
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000849}
Benjamin Kramer0fcab072011-09-08 20:52:17 +0000850
David Meyer5c2b4ea2012-03-01 01:36:50 +0000851error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData,
852 LibraryRef &Result) const {
853 report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
854}
855
856error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData,
857 StringRef &Result) const {
858 report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
859}
860
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000861namespace llvm {
862
863 ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
Michael J. Spencer001c9202011-06-25 17:54:50 +0000864 error_code ec;
865 return new COFFObjectFile(Object, ec);
Michael J. Spencera1ef8ef2011-01-20 06:38:34 +0000866 }
867
868} // end namespace llvm