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