COFFObjectFile.cpp revision 261991
1218885Sdim//===- COFFObjectFile.cpp - COFF object file implementation -----*- C++ -*-===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file declares the COFFObjectFile class.
11218885Sdim//
12218885Sdim//===----------------------------------------------------------------------===//
13218885Sdim
14224145Sdim#include "llvm/Object/COFF.h"
15234353Sdim#include "llvm/ADT/ArrayRef.h"
16226633Sdim#include "llvm/ADT/SmallString.h"
17218885Sdim#include "llvm/ADT/StringSwitch.h"
18218885Sdim#include "llvm/ADT/Triple.h"
19261991Sdim#include "llvm/Support/Debug.h"
20261991Sdim#include "llvm/Support/raw_ostream.h"
21261991Sdim#include <cctype>
22218885Sdim
23218885Sdimusing namespace llvm;
24218885Sdimusing namespace object;
25218885Sdim
26218885Sdimnamespace {
27218885Sdimusing support::ulittle8_t;
28218885Sdimusing support::ulittle16_t;
29218885Sdimusing support::ulittle32_t;
30218885Sdimusing support::little16_t;
31218885Sdim}
32218885Sdim
33218885Sdimnamespace {
34224145Sdim// Returns false if size is greater than the buffer size. And sets ec.
35224145Sdimbool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
36224145Sdim  if (m->getBufferSize() < size) {
37224145Sdim    ec = object_error::unexpected_eof;
38224145Sdim    return false;
39224145Sdim  }
40224145Sdim  return true;
41218885Sdim}
42218885Sdim
43261991Sdim// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
44261991Sdim// Returns unexpected_eof if error.
45261991Sdimtemplate<typename T>
46261991Sdimerror_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr,
47261991Sdim                     const size_t Size = sizeof(T)) {
48261991Sdim  uintptr_t Addr = uintptr_t(Ptr);
49261991Sdim  if (Addr + Size < Addr ||
50261991Sdim      Addr + Size < Size ||
51261991Sdim      Addr + Size > uintptr_t(M->getBufferEnd())) {
52261991Sdim    return object_error::unexpected_eof;
53224145Sdim  }
54261991Sdim  Obj = reinterpret_cast<const T *>(Addr);
55261991Sdim  return object_error::success;
56224145Sdim}
57224145Sdim}
58218885Sdim
59224145Sdimconst coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
60224145Sdim  const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
61218885Sdim
62224145Sdim# ifndef NDEBUG
63224145Sdim  // Verify that the symbol points to a valid entry in the symbol table.
64224145Sdim  uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
65261991Sdim  if (offset < COFFHeader->PointerToSymbolTable
66261991Sdim      || offset >= COFFHeader->PointerToSymbolTable
67261991Sdim         + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
68224145Sdim    report_fatal_error("Symbol was outside of symbol table.");
69218885Sdim
70261991Sdim  assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
71224145Sdim         == 0 && "Symbol did not point to the beginning of a symbol");
72224145Sdim# endif
73218885Sdim
74224145Sdim  return addr;
75218885Sdim}
76218885Sdim
77224145Sdimconst coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
78224145Sdim  const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
79218885Sdim
80224145Sdim# ifndef NDEBUG
81224145Sdim  // Verify that the section points to a valid entry in the section table.
82224145Sdim  if (addr < SectionTable
83261991Sdim      || addr >= (SectionTable + COFFHeader->NumberOfSections))
84224145Sdim    report_fatal_error("Section was outside of section table.");
85218885Sdim
86224145Sdim  uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
87224145Sdim  assert(offset % sizeof(coff_section) == 0 &&
88224145Sdim         "Section did not point to the beginning of a section");
89224145Sdim# endif
90218885Sdim
91224145Sdim  return addr;
92224145Sdim}
93218885Sdim
94224145Sdimerror_code COFFObjectFile::getSymbolNext(DataRefImpl Symb,
95224145Sdim                                         SymbolRef &Result) const {
96224145Sdim  const coff_symbol *symb = toSymb(Symb);
97218885Sdim  symb += 1 + symb->NumberOfAuxSymbols;
98224145Sdim  Symb.p = reinterpret_cast<uintptr_t>(symb);
99224145Sdim  Result = SymbolRef(Symb, this);
100224145Sdim  return object_error::success;
101218885Sdim}
102218885Sdim
103224145Sdim error_code COFFObjectFile::getSymbolName(DataRefImpl Symb,
104224145Sdim                                          StringRef &Result) const {
105224145Sdim  const coff_symbol *symb = toSymb(Symb);
106234353Sdim  return getSymbolName(symb, Result);
107218885Sdim}
108218885Sdim
109234353Sdimerror_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb,
110224145Sdim                                            uint64_t &Result) const {
111224145Sdim  const coff_symbol *symb = toSymb(Symb);
112224145Sdim  const coff_section *Section = NULL;
113224145Sdim  if (error_code ec = getSection(symb->SectionNumber, Section))
114224145Sdim    return ec;
115261991Sdim
116261991Sdim  if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
117224145Sdim    Result = UnknownAddressOrSize;
118224145Sdim  else if (Section)
119234353Sdim    Result = Section->PointerToRawData + symb->Value;
120224145Sdim  else
121224145Sdim    Result = symb->Value;
122224145Sdim  return object_error::success;
123218885Sdim}
124218885Sdim
125226633Sdimerror_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb,
126226633Sdim                                            uint64_t &Result) const {
127226633Sdim  const coff_symbol *symb = toSymb(Symb);
128226633Sdim  const coff_section *Section = NULL;
129226633Sdim  if (error_code ec = getSection(symb->SectionNumber, Section))
130226633Sdim    return ec;
131261991Sdim
132261991Sdim  if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
133226633Sdim    Result = UnknownAddressOrSize;
134226633Sdim  else if (Section)
135234353Sdim    Result = Section->VirtualAddress + symb->Value;
136226633Sdim  else
137234353Sdim    Result = symb->Value;
138226633Sdim  return object_error::success;
139226633Sdim}
140226633Sdim
141226633Sdimerror_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
142234353Sdim                                         SymbolRef::Type &Result) const {
143226633Sdim  const coff_symbol *symb = toSymb(Symb);
144226633Sdim  Result = SymbolRef::ST_Other;
145226633Sdim  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
146226633Sdim      symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {
147234353Sdim    Result = SymbolRef::ST_Unknown;
148226633Sdim  } else {
149234353Sdim    if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
150226633Sdim      Result = SymbolRef::ST_Function;
151226633Sdim    } else {
152261991Sdim      uint32_t Characteristics = 0;
153261991Sdim      if (symb->SectionNumber > 0) {
154261991Sdim        const coff_section *Section = NULL;
155261991Sdim        if (error_code ec = getSection(symb->SectionNumber, Section))
156261991Sdim          return ec;
157261991Sdim        Characteristics = Section->Characteristics;
158261991Sdim      }
159261991Sdim      if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
160261991Sdim          ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
161226633Sdim        Result = SymbolRef::ST_Data;
162226633Sdim    }
163226633Sdim  }
164226633Sdim  return object_error::success;
165226633Sdim}
166226633Sdim
167234353Sdimerror_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb,
168234353Sdim                                          uint32_t &Result) const {
169226633Sdim  const coff_symbol *symb = toSymb(Symb);
170234353Sdim  Result = SymbolRef::SF_None;
171234353Sdim
172234353Sdim  // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common
173234353Sdim
174234353Sdim  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
175234353Sdim      symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
176234353Sdim    Result |= SymbolRef::SF_Undefined;
177234353Sdim
178234353Sdim  // TODO: This are certainly too restrictive.
179234353Sdim  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
180234353Sdim    Result |= SymbolRef::SF_Global;
181234353Sdim
182234353Sdim  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
183234353Sdim    Result |= SymbolRef::SF_Weak;
184234353Sdim
185234353Sdim  if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE)
186234353Sdim    Result |= SymbolRef::SF_Absolute;
187234353Sdim
188226633Sdim  return object_error::success;
189226633Sdim}
190226633Sdim
191224145Sdimerror_code COFFObjectFile::getSymbolSize(DataRefImpl Symb,
192224145Sdim                                         uint64_t &Result) const {
193218885Sdim  // FIXME: Return the correct size. This requires looking at all the symbols
194218885Sdim  //        in the same section as this symbol, and looking for either the next
195218885Sdim  //        symbol, or the end of the section.
196224145Sdim  const coff_symbol *symb = toSymb(Symb);
197224145Sdim  const coff_section *Section = NULL;
198224145Sdim  if (error_code ec = getSection(symb->SectionNumber, Section))
199224145Sdim    return ec;
200261991Sdim
201261991Sdim  if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)
202224145Sdim    Result = UnknownAddressOrSize;
203224145Sdim  else if (Section)
204224145Sdim    Result = Section->SizeOfRawData - symb->Value;
205224145Sdim  else
206224145Sdim    Result = 0;
207224145Sdim  return object_error::success;
208218885Sdim}
209218885Sdim
210234353Sdimerror_code COFFObjectFile::getSymbolSection(DataRefImpl Symb,
211234353Sdim                                            section_iterator &Result) const {
212234353Sdim  const coff_symbol *symb = toSymb(Symb);
213234353Sdim  if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED)
214234353Sdim    Result = end_sections();
215234353Sdim  else {
216234353Sdim    const coff_section *sec = 0;
217234353Sdim    if (error_code ec = getSection(symb->SectionNumber, sec)) return ec;
218234353Sdim    DataRefImpl Sec;
219234353Sdim    Sec.p = reinterpret_cast<uintptr_t>(sec);
220234353Sdim    Result = section_iterator(SectionRef(Sec, this));
221234353Sdim  }
222224145Sdim  return object_error::success;
223218885Sdim}
224218885Sdim
225243830Sdimerror_code COFFObjectFile::getSymbolValue(DataRefImpl Symb,
226243830Sdim                                          uint64_t &Val) const {
227243830Sdim  report_fatal_error("getSymbolValue unimplemented in COFFObjectFile");
228243830Sdim}
229243830Sdim
230224145Sdimerror_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
231224145Sdim                                          SectionRef &Result) const {
232224145Sdim  const coff_section *sec = toSec(Sec);
233218885Sdim  sec += 1;
234224145Sdim  Sec.p = reinterpret_cast<uintptr_t>(sec);
235224145Sdim  Result = SectionRef(Sec, this);
236224145Sdim  return object_error::success;
237218885Sdim}
238218885Sdim
239224145Sdimerror_code COFFObjectFile::getSectionName(DataRefImpl Sec,
240224145Sdim                                          StringRef &Result) const {
241224145Sdim  const coff_section *sec = toSec(Sec);
242234353Sdim  return getSectionName(sec, Result);
243218885Sdim}
244218885Sdim
245224145Sdimerror_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
246224145Sdim                                             uint64_t &Result) const {
247224145Sdim  const coff_section *sec = toSec(Sec);
248224145Sdim  Result = sec->VirtualAddress;
249224145Sdim  return object_error::success;
250218885Sdim}
251218885Sdim
252224145Sdimerror_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
253224145Sdim                                          uint64_t &Result) const {
254224145Sdim  const coff_section *sec = toSec(Sec);
255224145Sdim  Result = sec->SizeOfRawData;
256224145Sdim  return object_error::success;
257218885Sdim}
258218885Sdim
259224145Sdimerror_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
260224145Sdim                                              StringRef &Result) const {
261224145Sdim  const coff_section *sec = toSec(Sec);
262234353Sdim  ArrayRef<uint8_t> Res;
263234353Sdim  error_code EC = getSectionContents(sec, Res);
264234353Sdim  Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());
265234353Sdim  return EC;
266218885Sdim}
267218885Sdim
268226633Sdimerror_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec,
269226633Sdim                                               uint64_t &Res) const {
270226633Sdim  const coff_section *sec = toSec(Sec);
271226633Sdim  if (!sec)
272226633Sdim    return object_error::parse_failed;
273226633Sdim  Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1);
274226633Sdim  return object_error::success;
275226633Sdim}
276226633Sdim
277224145Sdimerror_code COFFObjectFile::isSectionText(DataRefImpl Sec,
278224145Sdim                                         bool &Result) const {
279224145Sdim  const coff_section *sec = toSec(Sec);
280224145Sdim  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
281224145Sdim  return object_error::success;
282218885Sdim}
283218885Sdim
284226633Sdimerror_code COFFObjectFile::isSectionData(DataRefImpl Sec,
285226633Sdim                                         bool &Result) const {
286226633Sdim  const coff_section *sec = toSec(Sec);
287226633Sdim  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
288226633Sdim  return object_error::success;
289226633Sdim}
290226633Sdim
291226633Sdimerror_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
292226633Sdim                                        bool &Result) const {
293226633Sdim  const coff_section *sec = toSec(Sec);
294226633Sdim  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
295226633Sdim  return object_error::success;
296226633Sdim}
297226633Sdim
298234353Sdimerror_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,
299234353Sdim                                                         bool &Result) const {
300234353Sdim  // FIXME: Unimplemented
301234353Sdim  Result = true;
302234353Sdim  return object_error::success;
303234353Sdim}
304234353Sdim
305234353Sdimerror_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec,
306234353Sdim                                           bool &Result) const {
307234353Sdim  const coff_section *sec = toSec(Sec);
308234353Sdim  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
309234353Sdim  return object_error::success;
310234353Sdim}
311234353Sdim
312234353Sdimerror_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec,
313234353Sdim                                             bool &Result) const {
314243830Sdim  // FIXME: Unimplemented.
315234353Sdim  Result = false;
316234353Sdim  return object_error::success;
317234353Sdim}
318234353Sdim
319243830Sdimerror_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec,
320243830Sdim                                                bool &Result) const {
321243830Sdim  // FIXME: Unimplemented.
322243830Sdim  Result = false;
323243830Sdim  return object_error::success;
324243830Sdim}
325243830Sdim
326224145Sdimerror_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
327224145Sdim                                                 DataRefImpl Symb,
328224145Sdim                                                 bool &Result) const {
329226633Sdim  const coff_section *sec = toSec(Sec);
330226633Sdim  const coff_symbol *symb = toSymb(Symb);
331234353Sdim  const coff_section *symb_sec = 0;
332226633Sdim  if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
333226633Sdim  if (symb_sec == sec)
334226633Sdim    Result = true;
335226633Sdim  else
336226633Sdim    Result = false;
337224145Sdim  return object_error::success;
338224145Sdim}
339221345Sdim
340261991Sdimrelocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Sec) const {
341226633Sdim  const coff_section *sec = toSec(Sec);
342226633Sdim  DataRefImpl ret;
343226633Sdim  if (sec->NumberOfRelocations == 0)
344226633Sdim    ret.p = 0;
345226633Sdim  else
346226633Sdim    ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
347226633Sdim
348226633Sdim  return relocation_iterator(RelocationRef(ret, this));
349226633Sdim}
350226633Sdim
351261991Sdimrelocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Sec) const {
352226633Sdim  const coff_section *sec = toSec(Sec);
353226633Sdim  DataRefImpl ret;
354226633Sdim  if (sec->NumberOfRelocations == 0)
355226633Sdim    ret.p = 0;
356226633Sdim  else
357226633Sdim    ret.p = reinterpret_cast<uintptr_t>(
358226633Sdim              reinterpret_cast<const coff_relocation*>(
359226633Sdim                base() + sec->PointerToRelocations)
360226633Sdim              + sec->NumberOfRelocations);
361226633Sdim
362226633Sdim  return relocation_iterator(RelocationRef(ret, this));
363226633Sdim}
364226633Sdim
365261991Sdim// Initialize the pointer to the symbol table.
366261991Sdimerror_code COFFObjectFile::initSymbolTablePtr() {
367261991Sdim  if (error_code ec = getObject(
368261991Sdim          SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable,
369261991Sdim          COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
370261991Sdim    return ec;
371261991Sdim
372261991Sdim  // Find string table. The first four byte of the string table contains the
373261991Sdim  // total size of the string table, including the size field itself. If the
374261991Sdim  // string table is empty, the value of the first four byte would be 4.
375261991Sdim  const uint8_t *StringTableAddr =
376261991Sdim      base() + COFFHeader->PointerToSymbolTable +
377261991Sdim      COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
378261991Sdim  const ulittle32_t *StringTableSizePtr;
379261991Sdim  if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr))
380261991Sdim    return ec;
381261991Sdim  StringTableSize = *StringTableSizePtr;
382261991Sdim  if (error_code ec =
383261991Sdim      getObject(StringTable, Data, StringTableAddr, StringTableSize))
384261991Sdim    return ec;
385261991Sdim
386261991Sdim  // Check that the string table is null terminated if has any in it.
387261991Sdim  if (StringTableSize < 4 ||
388261991Sdim      (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0))
389261991Sdim    return  object_error::parse_failed;
390261991Sdim  return object_error::success;
391261991Sdim}
392261991Sdim
393261991Sdim// Returns the file offset for the given RVA.
394261991Sdimerror_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const {
395261991Sdim  error_code ec;
396261991Sdim  for (section_iterator i = begin_sections(), e = end_sections(); i != e;
397261991Sdim       i.increment(ec)) {
398261991Sdim    if (ec)
399261991Sdim      return ec;
400261991Sdim    const coff_section *Section = getCOFFSection(i);
401261991Sdim    uint32_t SectionStart = Section->VirtualAddress;
402261991Sdim    uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
403261991Sdim    if (SectionStart <= Rva && Rva < SectionEnd) {
404261991Sdim      uint32_t Offset = Rva - SectionStart;
405261991Sdim      Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
406261991Sdim      return object_error::success;
407261991Sdim    }
408261991Sdim  }
409261991Sdim  return object_error::parse_failed;
410261991Sdim}
411261991Sdim
412261991Sdim// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
413261991Sdim// table entry.
414261991Sdimerror_code COFFObjectFile::
415261991SdimgetHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const {
416261991Sdim  uintptr_t IntPtr = 0;
417261991Sdim  if (error_code ec = getRvaPtr(Rva, IntPtr))
418261991Sdim    return ec;
419261991Sdim  const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
420261991Sdim  Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
421261991Sdim  Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
422261991Sdim  return object_error::success;
423261991Sdim}
424261991Sdim
425261991Sdim// Find the import table.
426261991Sdimerror_code COFFObjectFile::initImportTablePtr() {
427261991Sdim  // First, we get the RVA of the import table. If the file lacks a pointer to
428261991Sdim  // the import table, do nothing.
429261991Sdim  const data_directory *DataEntry;
430261991Sdim  if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
431261991Sdim    return object_error::success;
432261991Sdim
433261991Sdim  // Do nothing if the pointer to import table is NULL.
434261991Sdim  if (DataEntry->RelativeVirtualAddress == 0)
435261991Sdim    return object_error::success;
436261991Sdim
437261991Sdim  uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
438261991Sdim  NumberOfImportDirectory = DataEntry->Size /
439261991Sdim      sizeof(import_directory_table_entry);
440261991Sdim
441261991Sdim  // Find the section that contains the RVA. This is needed because the RVA is
442261991Sdim  // the import table's memory address which is different from its file offset.
443261991Sdim  uintptr_t IntPtr = 0;
444261991Sdim  if (error_code ec = getRvaPtr(ImportTableRva, IntPtr))
445261991Sdim    return ec;
446261991Sdim  ImportDirectory = reinterpret_cast<
447261991Sdim      const import_directory_table_entry *>(IntPtr);
448261991Sdim
449261991Sdim  // It's an error if there's no section containing the Import Table RVA.
450261991Sdim  return object_error::parse_failed;
451261991Sdim}
452261991Sdim
453224145SdimCOFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
454251662Sdim  : ObjectFile(Binary::ID_COFF, Object)
455261991Sdim  , COFFHeader(0)
456261991Sdim  , PE32Header(0)
457261991Sdim  , DataDirectory(0)
458234353Sdim  , SectionTable(0)
459234353Sdim  , SymbolTable(0)
460234353Sdim  , StringTable(0)
461261991Sdim  , StringTableSize(0)
462261991Sdim  , ImportDirectory(0)
463261991Sdim  , NumberOfImportDirectory(0) {
464224145Sdim  // Check that we at least have enough room for a header.
465224145Sdim  if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
466221345Sdim
467261991Sdim  // The current location in the file where we are looking at.
468261991Sdim  uint64_t CurPtr = 0;
469224145Sdim
470261991Sdim  // PE header is optional and is present only in executables. If it exists,
471261991Sdim  // it is placed right after COFF header.
472261991Sdim  bool hasPEHeader = false;
473261991Sdim
474224145Sdim  // Check if this is a PE/COFF file.
475224145Sdim  if (base()[0] == 0x4d && base()[1] == 0x5a) {
476221345Sdim    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
477221345Sdim    // PE signature to find 'normal' COFF header.
478224145Sdim    if (!checkSize(Data, ec, 0x3c + 8)) return;
479261991Sdim    CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c);
480261991Sdim    // Check the PE magic bytes. ("PE\0\0")
481261991Sdim    if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) {
482224145Sdim      ec = object_error::parse_failed;
483224145Sdim      return;
484224145Sdim    }
485261991Sdim    CurPtr += 4; // Skip the PE magic bytes.
486261991Sdim    hasPEHeader = true;
487221345Sdim  }
488221345Sdim
489261991Sdim  if ((ec = getObject(COFFHeader, Data, base() + CurPtr)))
490224145Sdim    return;
491261991Sdim  CurPtr += sizeof(coff_file_header);
492226633Sdim
493261991Sdim  if (hasPEHeader) {
494261991Sdim    if ((ec = getObject(PE32Header, Data, base() + CurPtr)))
495234353Sdim      return;
496261991Sdim    if (PE32Header->Magic != 0x10b) {
497261991Sdim      // We only support PE32. If this is PE32 (not PE32+), the magic byte
498261991Sdim      // should be 0x10b. If this is not PE32, continue as if there's no PE
499261991Sdim      // header in this file.
500261991Sdim      PE32Header = 0;
501261991Sdim    } else if (PE32Header->NumberOfRvaAndSize > 0) {
502261991Sdim      const uint8_t *addr = base() + CurPtr + sizeof(pe32_header);
503261991Sdim      uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
504261991Sdim      if ((ec = getObject(DataDirectory, Data, addr, size)))
505261991Sdim        return;
506261991Sdim    }
507261991Sdim    CurPtr += COFFHeader->SizeOfOptionalHeader;
508261991Sdim  }
509218885Sdim
510261991Sdim  if (!COFFHeader->isImportLibrary())
511261991Sdim    if ((ec = getObject(SectionTable, Data, base() + CurPtr,
512261991Sdim                        COFFHeader->NumberOfSections * sizeof(coff_section))))
513234353Sdim      return;
514224145Sdim
515261991Sdim  // Initialize the pointer to the symbol table.
516261991Sdim  if (COFFHeader->PointerToSymbolTable != 0)
517261991Sdim    if ((ec = initSymbolTablePtr()))
518234353Sdim      return;
519226633Sdim
520261991Sdim  // Initialize the pointer to the beginning of the import table.
521261991Sdim  if ((ec = initImportTablePtr()))
522261991Sdim    return;
523261991Sdim
524224145Sdim  ec = object_error::success;
525218885Sdim}
526218885Sdim
527226633Sdimsymbol_iterator COFFObjectFile::begin_symbols() const {
528218885Sdim  DataRefImpl ret;
529261991Sdim  ret.p = reinterpret_cast<uintptr_t>(SymbolTable);
530218885Sdim  return symbol_iterator(SymbolRef(ret, this));
531218885Sdim}
532218885Sdim
533226633Sdimsymbol_iterator COFFObjectFile::end_symbols() const {
534218885Sdim  // The symbol table ends where the string table begins.
535218885Sdim  DataRefImpl ret;
536261991Sdim  ret.p = reinterpret_cast<uintptr_t>(StringTable);
537218885Sdim  return symbol_iterator(SymbolRef(ret, this));
538218885Sdim}
539218885Sdim
540234353Sdimsymbol_iterator COFFObjectFile::begin_dynamic_symbols() const {
541234353Sdim  // TODO: implement
542234353Sdim  report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
543234353Sdim}
544234353Sdim
545234353Sdimsymbol_iterator COFFObjectFile::end_dynamic_symbols() const {
546234353Sdim  // TODO: implement
547234353Sdim  report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile");
548234353Sdim}
549234353Sdim
550234353Sdimlibrary_iterator COFFObjectFile::begin_libraries_needed() const {
551234353Sdim  // TODO: implement
552234353Sdim  report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
553234353Sdim}
554234353Sdim
555234353Sdimlibrary_iterator COFFObjectFile::end_libraries_needed() const {
556234353Sdim  // TODO: implement
557234353Sdim  report_fatal_error("Libraries needed unimplemented in COFFObjectFile");
558234353Sdim}
559234353Sdim
560234353SdimStringRef COFFObjectFile::getLoadName() const {
561234353Sdim  // COFF does not have this field.
562234353Sdim  return "";
563234353Sdim}
564234353Sdim
565261991Sdimimport_directory_iterator COFFObjectFile::import_directory_begin() const {
566261991Sdim  DataRefImpl Imp;
567261991Sdim  Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory);
568261991Sdim  return import_directory_iterator(ImportDirectoryEntryRef(Imp, this));
569261991Sdim}
570234353Sdim
571261991Sdimimport_directory_iterator COFFObjectFile::import_directory_end() const {
572261991Sdim  DataRefImpl Imp;
573261991Sdim  if (ImportDirectory) {
574261991Sdim    Imp.p = reinterpret_cast<uintptr_t>(
575261991Sdim        ImportDirectory + (NumberOfImportDirectory - 1));
576261991Sdim  } else {
577261991Sdim    Imp.p = 0;
578261991Sdim  }
579261991Sdim  return import_directory_iterator(ImportDirectoryEntryRef(Imp, this));
580261991Sdim}
581261991Sdim
582226633Sdimsection_iterator COFFObjectFile::begin_sections() const {
583218885Sdim  DataRefImpl ret;
584261991Sdim  ret.p = reinterpret_cast<uintptr_t>(SectionTable);
585218885Sdim  return section_iterator(SectionRef(ret, this));
586218885Sdim}
587218885Sdim
588226633Sdimsection_iterator COFFObjectFile::end_sections() const {
589218885Sdim  DataRefImpl ret;
590261991Sdim  int numSections = COFFHeader->isImportLibrary()
591261991Sdim      ? 0 : COFFHeader->NumberOfSections;
592261991Sdim  ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections);
593218885Sdim  return section_iterator(SectionRef(ret, this));
594218885Sdim}
595218885Sdim
596218885Sdimuint8_t COFFObjectFile::getBytesInAddress() const {
597218885Sdim  return getArch() == Triple::x86_64 ? 8 : 4;
598218885Sdim}
599218885Sdim
600218885SdimStringRef COFFObjectFile::getFileFormatName() const {
601261991Sdim  switch(COFFHeader->Machine) {
602218885Sdim  case COFF::IMAGE_FILE_MACHINE_I386:
603218885Sdim    return "COFF-i386";
604218885Sdim  case COFF::IMAGE_FILE_MACHINE_AMD64:
605218885Sdim    return "COFF-x86-64";
606218885Sdim  default:
607218885Sdim    return "COFF-<unknown arch>";
608218885Sdim  }
609218885Sdim}
610218885Sdim
611218885Sdimunsigned COFFObjectFile::getArch() const {
612261991Sdim  switch(COFFHeader->Machine) {
613218885Sdim  case COFF::IMAGE_FILE_MACHINE_I386:
614218885Sdim    return Triple::x86;
615218885Sdim  case COFF::IMAGE_FILE_MACHINE_AMD64:
616218885Sdim    return Triple::x86_64;
617218885Sdim  default:
618218885Sdim    return Triple::UnknownArch;
619218885Sdim  }
620218885Sdim}
621218885Sdim
622261991Sdim// This method is kept here because lld uses this. As soon as we make
623261991Sdim// lld to use getCOFFHeader, this method will be removed.
624234353Sdimerror_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
625261991Sdim  return getCOFFHeader(Res);
626261991Sdim}
627261991Sdim
628261991Sdimerror_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
629261991Sdim  Res = COFFHeader;
630234353Sdim  return object_error::success;
631234353Sdim}
632234353Sdim
633261991Sdimerror_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
634261991Sdim  Res = PE32Header;
635261991Sdim  return object_error::success;
636261991Sdim}
637261991Sdim
638261991Sdimerror_code COFFObjectFile::getDataDirectory(uint32_t index,
639261991Sdim                                            const data_directory *&Res) const {
640261991Sdim  // Error if if there's no data directory or the index is out of range.
641261991Sdim  if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize)
642261991Sdim    return object_error::parse_failed;
643261991Sdim  Res = &DataDirectory[index];
644261991Sdim  return object_error::success;
645261991Sdim}
646261991Sdim
647224145Sdimerror_code COFFObjectFile::getSection(int32_t index,
648224145Sdim                                      const coff_section *&Result) const {
649224145Sdim  // Check for special index values.
650224145Sdim  if (index == COFF::IMAGE_SYM_UNDEFINED ||
651224145Sdim      index == COFF::IMAGE_SYM_ABSOLUTE ||
652224145Sdim      index == COFF::IMAGE_SYM_DEBUG)
653224145Sdim    Result = NULL;
654261991Sdim  else if (index > 0 && index <= COFFHeader->NumberOfSections)
655224145Sdim    // We already verified the section table data, so no need to check again.
656224145Sdim    Result = SectionTable + (index - 1);
657224145Sdim  else
658224145Sdim    return object_error::parse_failed;
659224145Sdim  return object_error::success;
660218885Sdim}
661218885Sdim
662224145Sdimerror_code COFFObjectFile::getString(uint32_t offset,
663224145Sdim                                     StringRef &Result) const {
664224145Sdim  if (StringTableSize <= 4)
665224145Sdim    // Tried to get a string from an empty string table.
666224145Sdim    return object_error::parse_failed;
667224145Sdim  if (offset >= StringTableSize)
668224145Sdim    return object_error::unexpected_eof;
669224145Sdim  Result = StringRef(StringTable + offset);
670224145Sdim  return object_error::success;
671218885Sdim}
672218885Sdim
673226633Sdimerror_code COFFObjectFile::getSymbol(uint32_t index,
674226633Sdim                                     const coff_symbol *&Result) const {
675261991Sdim  if (index < COFFHeader->NumberOfSymbols)
676226633Sdim    Result = SymbolTable + index;
677226633Sdim  else
678226633Sdim    return object_error::parse_failed;
679226633Sdim  return object_error::success;
680226633Sdim}
681226633Sdim
682234353Sdimerror_code COFFObjectFile::getSymbolName(const coff_symbol *symbol,
683234353Sdim                                         StringRef &Res) const {
684234353Sdim  // Check for string table entry. First 4 bytes are 0.
685234353Sdim  if (symbol->Name.Offset.Zeroes == 0) {
686234353Sdim    uint32_t Offset = symbol->Name.Offset.Offset;
687234353Sdim    if (error_code ec = getString(Offset, Res))
688234353Sdim      return ec;
689234353Sdim    return object_error::success;
690234353Sdim  }
691234353Sdim
692234353Sdim  if (symbol->Name.ShortName[7] == 0)
693234353Sdim    // Null terminated, let ::strlen figure out the length.
694234353Sdim    Res = StringRef(symbol->Name.ShortName);
695234353Sdim  else
696234353Sdim    // Not null terminated, use all 8 bytes.
697234353Sdim    Res = StringRef(symbol->Name.ShortName, 8);
698234353Sdim  return object_error::success;
699234353Sdim}
700234353Sdim
701239462SdimArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData(
702239462Sdim                                  const coff_symbol *symbol) const {
703239462Sdim  const uint8_t *aux = NULL;
704261991Sdim
705239462Sdim  if ( symbol->NumberOfAuxSymbols > 0 ) {
706239462Sdim  // AUX data comes immediately after the symbol in COFF
707239462Sdim    aux = reinterpret_cast<const uint8_t *>(symbol + 1);
708239462Sdim# ifndef NDEBUG
709239462Sdim    // Verify that the aux symbol points to a valid entry in the symbol table.
710239462Sdim    uintptr_t offset = uintptr_t(aux) - uintptr_t(base());
711261991Sdim    if (offset < COFFHeader->PointerToSymbolTable
712261991Sdim        || offset >= COFFHeader->PointerToSymbolTable
713261991Sdim           + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
714239462Sdim      report_fatal_error("Aux Symbol data was outside of symbol table.");
715239462Sdim
716261991Sdim    assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
717239462Sdim         == 0 && "Aux Symbol data did not point to the beginning of a symbol");
718239462Sdim# endif
719239462Sdim  }
720239462Sdim  return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol));
721239462Sdim}
722239462Sdim
723234353Sdimerror_code COFFObjectFile::getSectionName(const coff_section *Sec,
724234353Sdim                                          StringRef &Res) const {
725234353Sdim  StringRef Name;
726234353Sdim  if (Sec->Name[7] == 0)
727234353Sdim    // Null terminated, let ::strlen figure out the length.
728234353Sdim    Name = Sec->Name;
729234353Sdim  else
730234353Sdim    // Not null terminated, use all 8 bytes.
731234353Sdim    Name = StringRef(Sec->Name, 8);
732234353Sdim
733234353Sdim  // Check for string table entry. First byte is '/'.
734234353Sdim  if (Name[0] == '/') {
735234353Sdim    uint32_t Offset;
736234353Sdim    if (Name.substr(1).getAsInteger(10, Offset))
737234353Sdim      return object_error::parse_failed;
738234353Sdim    if (error_code ec = getString(Offset, Name))
739234353Sdim      return ec;
740234353Sdim  }
741234353Sdim
742234353Sdim  Res = Name;
743234353Sdim  return object_error::success;
744234353Sdim}
745234353Sdim
746234353Sdimerror_code COFFObjectFile::getSectionContents(const coff_section *Sec,
747234353Sdim                                              ArrayRef<uint8_t> &Res) const {
748234353Sdim  // The only thing that we need to verify is that the contents is contained
749234353Sdim  // within the file bounds. We don't need to make sure it doesn't cover other
750234353Sdim  // data, as there's nothing that says that is not allowed.
751234353Sdim  uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData;
752234353Sdim  uintptr_t ConEnd = ConStart + Sec->SizeOfRawData;
753234353Sdim  if (ConEnd > uintptr_t(Data->getBufferEnd()))
754234353Sdim    return object_error::parse_failed;
755234353Sdim  Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart),
756234353Sdim                          Sec->SizeOfRawData);
757234353Sdim  return object_error::success;
758234353Sdim}
759234353Sdim
760226633Sdimconst coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
761226633Sdim  return reinterpret_cast<const coff_relocation*>(Rel.p);
762226633Sdim}
763226633Sdimerror_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
764226633Sdim                                             RelocationRef &Res) const {
765226633Sdim  Rel.p = reinterpret_cast<uintptr_t>(
766226633Sdim            reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
767226633Sdim  Res = RelocationRef(Rel, this);
768226633Sdim  return object_error::success;
769226633Sdim}
770226633Sdimerror_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
771226633Sdim                                                uint64_t &Res) const {
772251662Sdim  report_fatal_error("getRelocationAddress not implemented in COFFObjectFile");
773226633Sdim}
774234353Sdimerror_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel,
775234353Sdim                                               uint64_t &Res) const {
776234353Sdim  Res = toRel(Rel)->VirtualAddress;
777234353Sdim  return object_error::success;
778234353Sdim}
779261991Sdimsymbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
780226633Sdim  const coff_relocation* R = toRel(Rel);
781226633Sdim  DataRefImpl Symb;
782226633Sdim  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
783261991Sdim  return symbol_iterator(SymbolRef(Symb, this));
784226633Sdim}
785226633Sdimerror_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
786234353Sdim                                             uint64_t &Res) const {
787226633Sdim  const coff_relocation* R = toRel(Rel);
788226633Sdim  Res = R->Type;
789226633Sdim  return object_error::success;
790226633Sdim}
791226633Sdim
792239462Sdimconst coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const {
793239462Sdim  return toSec(It->getRawDataRefImpl());
794239462Sdim}
795239462Sdim
796239462Sdimconst coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const {
797239462Sdim  return toSymb(It->getRawDataRefImpl());
798239462Sdim}
799239462Sdim
800239462Sdimconst coff_relocation *COFFObjectFile::getCOFFRelocation(
801239462Sdim                                             relocation_iterator &It) const {
802239462Sdim  return toRel(It->getRawDataRefImpl());
803239462Sdim}
804239462Sdim
805226633Sdim#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
806226633Sdim  case COFF::enum: res = #enum; break;
807226633Sdim
808226633Sdimerror_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
809226633Sdim                                          SmallVectorImpl<char> &Result) const {
810226633Sdim  const coff_relocation *reloc = toRel(Rel);
811226633Sdim  StringRef res;
812261991Sdim  switch (COFFHeader->Machine) {
813226633Sdim  case COFF::IMAGE_FILE_MACHINE_AMD64:
814226633Sdim    switch (reloc->Type) {
815226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
816226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
817226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
818226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
819226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
820226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
821226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
822226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
823226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
824226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
825226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
826226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
827226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
828226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
829226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
830226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
831226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
832226633Sdim    default:
833226633Sdim      res = "Unknown";
834226633Sdim    }
835226633Sdim    break;
836226633Sdim  case COFF::IMAGE_FILE_MACHINE_I386:
837226633Sdim    switch (reloc->Type) {
838226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
839226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
840226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
841226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
842226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
843226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
844226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
845226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
846226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
847226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
848226633Sdim    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
849226633Sdim    default:
850226633Sdim      res = "Unknown";
851226633Sdim    }
852226633Sdim    break;
853226633Sdim  default:
854226633Sdim    res = "Unknown";
855226633Sdim  }
856226633Sdim  Result.append(res.begin(), res.end());
857226633Sdim  return object_error::success;
858226633Sdim}
859226633Sdim
860226633Sdim#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
861226633Sdim
862226633Sdimerror_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
863226633Sdim                                          SmallVectorImpl<char> &Result) const {
864226633Sdim  const coff_relocation *reloc = toRel(Rel);
865226633Sdim  const coff_symbol *symb = 0;
866226633Sdim  if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
867226633Sdim  DataRefImpl sym;
868226633Sdim  sym.p = reinterpret_cast<uintptr_t>(symb);
869226633Sdim  StringRef symname;
870226633Sdim  if (error_code ec = getSymbolName(sym, symname)) return ec;
871226633Sdim  Result.append(symname.begin(), symname.end());
872226633Sdim  return object_error::success;
873226633Sdim}
874226633Sdim
875234353Sdimerror_code COFFObjectFile::getLibraryNext(DataRefImpl LibData,
876234353Sdim                                          LibraryRef &Result) const {
877234353Sdim  report_fatal_error("getLibraryNext not implemented in COFFObjectFile");
878234353Sdim}
879234353Sdim
880234353Sdimerror_code COFFObjectFile::getLibraryPath(DataRefImpl LibData,
881234353Sdim                                          StringRef &Result) const {
882234353Sdim  report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
883234353Sdim}
884234353Sdim
885261991Sdimbool ImportDirectoryEntryRef::
886261991Sdimoperator==(const ImportDirectoryEntryRef &Other) const {
887261991Sdim  return ImportDirectoryPimpl == Other.ImportDirectoryPimpl;
888261991Sdim}
889261991Sdim
890261991Sdimstatic const import_directory_table_entry *toImportEntry(DataRefImpl Imp) {
891261991Sdim  return reinterpret_cast<const import_directory_table_entry *>(Imp.p);
892261991Sdim}
893261991Sdim
894261991Sdimerror_code
895261991SdimImportDirectoryEntryRef::getNext(ImportDirectoryEntryRef &Result) const {
896261991Sdim  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
897261991Sdim  Dir += 1;
898261991Sdim  DataRefImpl Next;
899261991Sdim  Next.p = reinterpret_cast<uintptr_t>(Dir);
900261991Sdim  Result = ImportDirectoryEntryRef(Next, OwningObject);
901261991Sdim  return object_error::success;
902261991Sdim}
903261991Sdim
904261991Sdimerror_code ImportDirectoryEntryRef::
905261991SdimgetImportTableEntry(const import_directory_table_entry *&Result) const {
906261991Sdim  Result = toImportEntry(ImportDirectoryPimpl);
907261991Sdim  return object_error::success;
908261991Sdim}
909261991Sdim
910261991Sdimerror_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
911261991Sdim  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
912261991Sdim  uintptr_t IntPtr = 0;
913261991Sdim  if (error_code ec = OwningObject->getRvaPtr(Dir->NameRVA, IntPtr))
914261991Sdim    return ec;
915261991Sdim  const char *Ptr = reinterpret_cast<const char *>(IntPtr);
916261991Sdim  Result = StringRef(Ptr);
917261991Sdim  return object_error::success;
918261991Sdim}
919261991Sdim
920261991Sdimerror_code ImportDirectoryEntryRef::getImportLookupEntry(
921261991Sdim    const import_lookup_table_entry32 *&Result) const {
922261991Sdim  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
923261991Sdim  uintptr_t IntPtr = 0;
924261991Sdim  if (error_code ec = OwningObject->getRvaPtr(
925261991Sdim          Dir->ImportLookupTableRVA, IntPtr))
926261991Sdim    return ec;
927261991Sdim  Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);
928261991Sdim  return object_error::success;
929261991Sdim}
930261991Sdim
931218885Sdimnamespace llvm {
932218885Sdim
933218885Sdim  ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
934224145Sdim    error_code ec;
935224145Sdim    return new COFFObjectFile(Object, ec);
936218885Sdim  }
937218885Sdim
938218885Sdim} // end namespace llvm
939