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/SmallString.h"
16#include "llvm/ADT/StringSwitch.h"
17#include "llvm/ADT/Triple.h"
18
19using namespace llvm;
20using namespace object;
21
22namespace {
23using support::ulittle8_t;
24using support::ulittle16_t;
25using support::ulittle32_t;
26using support::little16_t;
27}
28
29namespace {
30// Returns false if size is greater than the buffer size. And sets ec.
31bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
32  if (m->getBufferSize() < size) {
33    ec = object_error::unexpected_eof;
34    return false;
35  }
36  return true;
37}
38
39// Returns false if any bytes in [addr, addr + size) fall outsize of m.
40bool checkAddr(const MemoryBuffer *m,
41               error_code &ec,
42               uintptr_t addr,
43               uint64_t size) {
44  if (addr + size < addr ||
45      addr + size < size ||
46      addr + size > uintptr_t(m->getBufferEnd())) {
47    ec = object_error::unexpected_eof;
48    return false;
49  }
50  return true;
51}
52}
53
54const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const {
55  const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p);
56
57# ifndef NDEBUG
58  // Verify that the symbol points to a valid entry in the symbol table.
59  uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
60  if (offset < Header->PointerToSymbolTable
61      || offset >= Header->PointerToSymbolTable
62         + (Header->NumberOfSymbols * sizeof(coff_symbol)))
63    report_fatal_error("Symbol was outside of symbol table.");
64
65  assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol)
66         == 0 && "Symbol did not point to the beginning of a symbol");
67# endif
68
69  return addr;
70}
71
72const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const {
73  const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p);
74
75# ifndef NDEBUG
76  // Verify that the section points to a valid entry in the section table.
77  if (addr < SectionTable
78      || addr >= (SectionTable + Header->NumberOfSections))
79    report_fatal_error("Section was outside of section table.");
80
81  uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
82  assert(offset % sizeof(coff_section) == 0 &&
83         "Section did not point to the beginning of a section");
84# endif
85
86  return addr;
87}
88
89error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb,
90                                         SymbolRef &Result) const {
91  const coff_symbol *symb = toSymb(Symb);
92  symb += 1 + symb->NumberOfAuxSymbols;
93  Symb.p = reinterpret_cast<uintptr_t>(symb);
94  Result = SymbolRef(Symb, this);
95  return object_error::success;
96}
97
98 error_code COFFObjectFile::getSymbolName(DataRefImpl Symb,
99                                          StringRef &Result) const {
100  const coff_symbol *symb = toSymb(Symb);
101  return getSymbolName(symb, Result);
102}
103
104error_code COFFObjectFile::getSymbolOffset(DataRefImpl Symb,
105                                            uint64_t &Result) const {
106  const coff_symbol *symb = toSymb(Symb);
107  const coff_section *Section = NULL;
108  if (error_code ec = getSection(symb->SectionNumber, Section))
109    return ec;
110  char Type;
111  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
112    return ec;
113  if (Type == 'U' || Type == 'w')
114    Result = UnknownAddressOrSize;
115  else if (Section)
116    Result = Section->VirtualAddress + symb->Value;
117  else
118    Result = symb->Value;
119  return object_error::success;
120}
121
122error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb,
123                                            uint64_t &Result) const {
124  const coff_symbol *symb = toSymb(Symb);
125  const coff_section *Section = NULL;
126  if (error_code ec = getSection(symb->SectionNumber, Section))
127    return ec;
128  char Type;
129  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
130    return ec;
131  if (Type == 'U' || Type == 'w')
132    Result = UnknownAddressOrSize;
133  else if (Section)
134    Result = reinterpret_cast<uintptr_t>(base() +
135                                         Section->PointerToRawData +
136                                         symb->Value);
137  else
138    Result = reinterpret_cast<uintptr_t>(base() + symb->Value);
139  return object_error::success;
140}
141
142error_code COFFObjectFile::getSymbolType(DataRefImpl Symb,
143                                         SymbolRef::Type &Result) const {
144  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) {
148    Result = SymbolRef::ST_External;
149  } else {
150    if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
151      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
164error_code COFFObjectFile::isSymbolGlobal(DataRefImpl Symb,
165                                          bool &Result) const {
166  const coff_symbol *symb = toSymb(Symb);
167  Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL);
168  return object_error::success;
169}
170
171error_code COFFObjectFile::isSymbolWeak(DataRefImpl Symb,
172                                          bool &Result) const {
173  const coff_symbol *symb = toSymb(Symb);
174  Result = (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL);
175  return object_error::success;
176}
177
178error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb,
179                                         uint64_t &Result) const {
180  // FIXME: Return the correct size. This requires looking at all the symbols
181  //        in the same section as this symbol, and looking for either the next
182  //        symbol, or the end of the section.
183  const coff_symbol *symb = toSymb(Symb);
184  const coff_section *Section = NULL;
185  if (error_code ec = getSection(symb->SectionNumber, Section))
186    return ec;
187  char Type;
188  if (error_code ec = getSymbolNMTypeChar(Symb, Type))
189    return ec;
190  if (Type == 'U' || Type == 'w')
191    Result = UnknownAddressOrSize;
192  else if (Section)
193    Result = Section->SizeOfRawData - symb->Value;
194  else
195    Result = 0;
196  return object_error::success;
197}
198
199error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb,
200                                               char &Result) const {
201  const coff_symbol *symb = toSymb(Symb);
202  StringRef name;
203  if (error_code ec = getSymbolName(Symb, name))
204    return ec;
205  char ret = StringSwitch<char>(name)
206    .StartsWith(".debug", 'N')
207    .StartsWith(".sxdata", 'N')
208    .Default('?');
209
210  if (ret != '?') {
211    Result = ret;
212    return object_error::success;
213  }
214
215  uint32_t Characteristics = 0;
216  if (symb->SectionNumber > 0) {
217    const coff_section *Section = NULL;
218    if (error_code ec = getSection(symb->SectionNumber, Section))
219      return ec;
220    Characteristics = Section->Characteristics;
221  }
222
223  switch (symb->SectionNumber) {
224  case COFF::IMAGE_SYM_UNDEFINED:
225    // Check storage classes.
226    if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) {
227      Result = 'w';
228      return object_error::success; // Don't do ::toupper.
229    } else
230      ret = 'u';
231    break;
232  case COFF::IMAGE_SYM_ABSOLUTE:
233    ret = 'a';
234    break;
235  case COFF::IMAGE_SYM_DEBUG:
236    ret = 'n';
237    break;
238  default:
239    // Check section type.
240    if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
241      ret = 't';
242    else if (  Characteristics & COFF::IMAGE_SCN_MEM_READ
243            && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
244      ret = 'r';
245    else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
246      ret = 'd';
247    else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
248      ret = 'b';
249    else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
250      ret = 'i';
251
252    // Check for section symbol.
253    else if (  symb->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC
254            && symb->Value == 0)
255       ret = 's';
256  }
257
258  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)
259    ret = ::toupper(ret);
260
261  Result = ret;
262  return object_error::success;
263}
264
265error_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb,
266                                            bool &Result) const {
267  Result = false;
268  return object_error::success;
269}
270
271error_code COFFObjectFile::isSymbolAbsolute(DataRefImpl Symb,
272                                            bool &Result) const {
273  const coff_symbol *symb = toSymb(Symb);
274  Result = symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE;
275  return object_error::success;
276}
277
278error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb,
279                                            section_iterator &Result) const {
280  const coff_symbol *symb = toSymb(Symb);
281  if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED)
282    Result = end_sections();
283  else {
284    const coff_section *sec;
285    if (error_code ec = getSection(symb->SectionNumber, sec)) return ec;
286    DataRefImpl Sec;
287    Sec.p = reinterpret_cast<uintptr_t>(sec);
288    Result = section_iterator(SectionRef(Sec, this));
289  }
290  return object_error::success;
291}
292
293error_code COFFObjectFile::getSectionNext(DataRefImpl Sec,
294                                          SectionRef &Result) const {
295  const coff_section *sec = toSec(Sec);
296  sec += 1;
297  Sec.p = reinterpret_cast<uintptr_t>(sec);
298  Result = SectionRef(Sec, this);
299  return object_error::success;
300}
301
302error_code COFFObjectFile::getSectionName(DataRefImpl Sec,
303                                          StringRef &Result) const {
304  const coff_section *sec = toSec(Sec);
305  StringRef name;
306  if (sec->Name[7] == 0)
307    // Null terminated, let ::strlen figure out the length.
308    name = sec->Name;
309  else
310    // Not null terminated, use all 8 bytes.
311    name = StringRef(sec->Name, 8);
312
313  // Check for string table entry. First byte is '/'.
314  if (name[0] == '/') {
315    uint32_t Offset;
316    name.substr(1).getAsInteger(10, Offset);
317    if (error_code ec = getString(Offset, name))
318      return ec;
319  }
320
321  Result = name;
322  return object_error::success;
323}
324
325error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec,
326                                             uint64_t &Result) const {
327  const coff_section *sec = toSec(Sec);
328  Result = sec->VirtualAddress;
329  return object_error::success;
330}
331
332error_code COFFObjectFile::getSectionSize(DataRefImpl Sec,
333                                          uint64_t &Result) const {
334  const coff_section *sec = toSec(Sec);
335  Result = sec->SizeOfRawData;
336  return object_error::success;
337}
338
339error_code COFFObjectFile::getSectionContents(DataRefImpl Sec,
340                                              StringRef &Result) const {
341  const coff_section *sec = toSec(Sec);
342  // The only thing that we need to verify is that the contents is contained
343  // within the file bounds. We don't need to make sure it doesn't cover other
344  // data, as there's nothing that says that is not allowed.
345  uintptr_t con_start = uintptr_t(base()) + sec->PointerToRawData;
346  uintptr_t con_end = con_start + sec->SizeOfRawData;
347  if (con_end >= uintptr_t(Data->getBufferEnd()))
348    return object_error::parse_failed;
349  Result = StringRef(reinterpret_cast<const char*>(con_start),
350                     sec->SizeOfRawData);
351  return object_error::success;
352}
353
354error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec,
355                                               uint64_t &Res) const {
356  const coff_section *sec = toSec(Sec);
357  if (!sec)
358    return object_error::parse_failed;
359  Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1);
360  return object_error::success;
361}
362
363error_code COFFObjectFile::isSectionText(DataRefImpl Sec,
364                                         bool &Result) const {
365  const coff_section *sec = toSec(Sec);
366  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
367  return object_error::success;
368}
369
370error_code COFFObjectFile::isSectionData(DataRefImpl Sec,
371                                         bool &Result) const {
372  const coff_section *sec = toSec(Sec);
373  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
374  return object_error::success;
375}
376
377error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec,
378                                        bool &Result) const {
379  const coff_section *sec = toSec(Sec);
380  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
381  return object_error::success;
382}
383
384error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec,
385                                                 DataRefImpl Symb,
386                                                 bool &Result) const {
387  const coff_section *sec = toSec(Sec);
388  const coff_symbol *symb = toSymb(Symb);
389  const coff_section *symb_sec;
390  if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec;
391  if (symb_sec == sec)
392    Result = true;
393  else
394    Result = false;
395  return object_error::success;
396}
397
398relocation_iterator COFFObjectFile::getSectionRelBegin(DataRefImpl Sec) const {
399  const coff_section *sec = toSec(Sec);
400  DataRefImpl ret;
401  std::memset(&ret, 0, sizeof(ret));
402  if (sec->NumberOfRelocations == 0)
403    ret.p = 0;
404  else
405    ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations);
406
407  return relocation_iterator(RelocationRef(ret, this));
408}
409
410relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const {
411  const coff_section *sec = toSec(Sec);
412  DataRefImpl ret;
413  std::memset(&ret, 0, sizeof(ret));
414  if (sec->NumberOfRelocations == 0)
415    ret.p = 0;
416  else
417    ret.p = reinterpret_cast<uintptr_t>(
418              reinterpret_cast<const coff_relocation*>(
419                base() + sec->PointerToRelocations)
420              + sec->NumberOfRelocations);
421
422  return relocation_iterator(RelocationRef(ret, this));
423}
424
425COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
426  : ObjectFile(Binary::isCOFF, Object, ec) {
427  // Check that we at least have enough room for a header.
428  if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
429
430  // The actual starting location of the COFF header in the file. This can be
431  // non-zero in PE/COFF files.
432  uint64_t HeaderStart = 0;
433
434  // Check if this is a PE/COFF file.
435  if (base()[0] == 0x4d && base()[1] == 0x5a) {
436    // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
437    // PE signature to find 'normal' COFF header.
438    if (!checkSize(Data, ec, 0x3c + 8)) return;
439    HeaderStart += *reinterpret_cast<const ulittle32_t *>(base() + 0x3c);
440    // Check the PE header. ("PE\0\0")
441    if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) {
442      ec = object_error::parse_failed;
443      return;
444    }
445    HeaderStart += 4; // Skip the PE Header.
446  }
447
448  Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart);
449  if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
450    return;
451
452  SectionTable =
453    reinterpret_cast<const coff_section *>( base()
454                                          + HeaderStart
455                                          + sizeof(coff_file_header)
456                                          + Header->SizeOfOptionalHeader);
457  if (!checkAddr(Data, ec, uintptr_t(SectionTable),
458                 Header->NumberOfSections * sizeof(coff_section)))
459    return;
460
461  SymbolTable =
462    reinterpret_cast<const coff_symbol *>(base()
463                                          + Header->PointerToSymbolTable);
464  if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
465                 Header->NumberOfSymbols * sizeof(coff_symbol)))
466    return;
467
468  // Find string table.
469  StringTable = reinterpret_cast<const char *>(base())
470                + Header->PointerToSymbolTable
471                + Header->NumberOfSymbols * sizeof(coff_symbol);
472  if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
473    return;
474
475  StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable);
476  if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize))
477    return;
478  // Check that the string table is null terminated if has any in it.
479  if (StringTableSize < 4
480      || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
481    ec = object_error::parse_failed;
482    return;
483  }
484
485  ec = object_error::success;
486}
487
488symbol_iterator COFFObjectFile::begin_symbols() const {
489  DataRefImpl ret;
490  std::memset(&ret, 0, sizeof(DataRefImpl));
491  ret.p = reinterpret_cast<intptr_t>(SymbolTable);
492  return symbol_iterator(SymbolRef(ret, this));
493}
494
495symbol_iterator COFFObjectFile::end_symbols() const {
496  // The symbol table ends where the string table begins.
497  DataRefImpl ret;
498  std::memset(&ret, 0, sizeof(DataRefImpl));
499  ret.p = reinterpret_cast<intptr_t>(StringTable);
500  return symbol_iterator(SymbolRef(ret, this));
501}
502
503section_iterator COFFObjectFile::begin_sections() const {
504  DataRefImpl ret;
505  std::memset(&ret, 0, sizeof(DataRefImpl));
506  ret.p = reinterpret_cast<intptr_t>(SectionTable);
507  return section_iterator(SectionRef(ret, this));
508}
509
510section_iterator COFFObjectFile::end_sections() const {
511  DataRefImpl ret;
512  std::memset(&ret, 0, sizeof(DataRefImpl));
513  ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
514  return section_iterator(SectionRef(ret, this));
515}
516
517uint8_t COFFObjectFile::getBytesInAddress() const {
518  return getArch() == Triple::x86_64 ? 8 : 4;
519}
520
521StringRef COFFObjectFile::getFileFormatName() const {
522  switch(Header->Machine) {
523  case COFF::IMAGE_FILE_MACHINE_I386:
524    return "COFF-i386";
525  case COFF::IMAGE_FILE_MACHINE_AMD64:
526    return "COFF-x86-64";
527  default:
528    return "COFF-<unknown arch>";
529  }
530}
531
532unsigned COFFObjectFile::getArch() const {
533  switch(Header->Machine) {
534  case COFF::IMAGE_FILE_MACHINE_I386:
535    return Triple::x86;
536  case COFF::IMAGE_FILE_MACHINE_AMD64:
537    return Triple::x86_64;
538  default:
539    return Triple::UnknownArch;
540  }
541}
542
543error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
544  Res = Header;
545  return object_error::success;
546}
547
548error_code COFFObjectFile::getSection(int32_t index,
549                                      const coff_section *&Result) const {
550  // Check for special index values.
551  if (index == COFF::IMAGE_SYM_UNDEFINED ||
552      index == COFF::IMAGE_SYM_ABSOLUTE ||
553      index == COFF::IMAGE_SYM_DEBUG)
554    Result = NULL;
555  else if (index > 0 && index <= Header->NumberOfSections)
556    // We already verified the section table data, so no need to check again.
557    Result = SectionTable + (index - 1);
558  else
559    return object_error::parse_failed;
560  return object_error::success;
561}
562
563error_code COFFObjectFile::getString(uint32_t offset,
564                                     StringRef &Result) const {
565  if (StringTableSize <= 4)
566    // Tried to get a string from an empty string table.
567    return object_error::parse_failed;
568  if (offset >= StringTableSize)
569    return object_error::unexpected_eof;
570  Result = StringRef(StringTable + offset);
571  return object_error::success;
572}
573
574error_code COFFObjectFile::getSymbol(uint32_t index,
575                                     const coff_symbol *&Result) const {
576  if (index < Header->NumberOfSymbols)
577    Result = SymbolTable + index;
578  else
579    return object_error::parse_failed;
580  return object_error::success;
581}
582
583error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol,
584                                         StringRef &Res) const {
585  // Check for string table entry. First 4 bytes are 0.
586  if (symbol->Name.Offset.Zeroes == 0) {
587    uint32_t Offset = symbol->Name.Offset.Offset;
588    if (error_code ec = getString(Offset, Res))
589      return ec;
590    return object_error::success;
591  }
592
593  if (symbol->Name.ShortName[7] == 0)
594    // Null terminated, let ::strlen figure out the length.
595    Res = StringRef(symbol->Name.ShortName);
596  else
597    // Not null terminated, use all 8 bytes.
598    Res = StringRef(symbol->Name.ShortName, 8);
599  return object_error::success;
600}
601
602const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
603  return reinterpret_cast<const coff_relocation*>(Rel.p);
604}
605error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
606                                             RelocationRef &Res) const {
607  Rel.p = reinterpret_cast<uintptr_t>(
608            reinterpret_cast<const coff_relocation*>(Rel.p) + 1);
609  Res = RelocationRef(Rel, this);
610  return object_error::success;
611}
612error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
613                                                uint64_t &Res) const {
614  Res = toRel(Rel)->VirtualAddress;
615  return object_error::success;
616}
617error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
618                                               SymbolRef &Res) const {
619  const coff_relocation* R = toRel(Rel);
620  DataRefImpl Symb;
621  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
622  Res = SymbolRef(Symb, this);
623  return object_error::success;
624}
625error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
626                                             uint32_t &Res) const {
627  const coff_relocation* R = toRel(Rel);
628  Res = R->Type;
629  return object_error::success;
630}
631
632#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
633  case COFF::enum: res = #enum; break;
634
635error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,
636                                          SmallVectorImpl<char> &Result) const {
637  const coff_relocation *reloc = toRel(Rel);
638  StringRef res;
639  switch (Header->Machine) {
640  case COFF::IMAGE_FILE_MACHINE_AMD64:
641    switch (reloc->Type) {
642    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
643    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
644    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
645    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB);
646    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32);
647    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1);
648    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2);
649    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3);
650    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4);
651    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5);
652    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION);
653    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL);
654    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7);
655    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN);
656    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32);
657    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
658    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
659    default:
660      res = "Unknown";
661    }
662    break;
663  case COFF::IMAGE_FILE_MACHINE_I386:
664    switch (reloc->Type) {
665    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
666    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
667    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
668    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32);
669    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB);
670    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12);
671    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION);
672    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL);
673    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN);
674    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
675    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
676    default:
677      res = "Unknown";
678    }
679    break;
680  default:
681    res = "Unknown";
682  }
683  Result.append(res.begin(), res.end());
684  return object_error::success;
685}
686
687#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
688
689error_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
690                                                       int64_t &Res) const {
691  Res = 0;
692  return object_error::success;
693}
694error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel,
695                                          SmallVectorImpl<char> &Result) const {
696  const coff_relocation *reloc = toRel(Rel);
697  const coff_symbol *symb = 0;
698  if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec;
699  DataRefImpl sym;
700  ::memset(&sym, 0, sizeof(sym));
701  sym.p = reinterpret_cast<uintptr_t>(symb);
702  StringRef symname;
703  if (error_code ec = getSymbolName(sym, symname)) return ec;
704  Result.append(symname.begin(), symname.end());
705  return object_error::success;
706}
707
708namespace llvm {
709
710  ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
711    error_code ec;
712    return new COFFObjectFile(Object, ec);
713  }
714
715} // end namespace llvm
716