Home | History | Annotate | Download | only in Object
      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 
     19 using namespace llvm;
     20 using namespace object;
     21 
     22 namespace {
     23 using support::ulittle8_t;
     24 using support::ulittle16_t;
     25 using support::ulittle32_t;
     26 using support::little16_t;
     27 }
     28 
     29 namespace {
     30 // Returns false if size is greater than the buffer size. And sets ec.
     31 bool 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.
     40 bool 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 
     54 const 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 
     72 const 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 
     89 error_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 
    118 error_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 
    136 error_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 
    156 error_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 
    178 error_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 
    185 error_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 
    206 error_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 
    272 error_code COFFObjectFile::isSymbolInternal(DataRefImpl Symb,
    273                                             bool &Result) const {
    274   Result = false;
    275   return object_error::success;
    276 }
    277 
    278 error_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 
    287 error_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 
    310 error_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 
    317 error_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 
    324 error_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 
    339 error_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 
    348 error_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 
    355 error_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 
    362 error_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 
    369 error_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 
    383 relocation_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 
    395 relocation_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 
    410 COFFObjectFile::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 
    473 symbol_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 
    480 symbol_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 
    488 section_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 
    495 section_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 
    502 uint8_t COFFObjectFile::getBytesInAddress() const {
    503   return getArch() == Triple::x86_64 ? 8 : 4;
    504 }
    505 
    506 StringRef 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 
    517 unsigned 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 
    528 error_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 
    543 error_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 
    554 error_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 
    563 const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
    564   return reinterpret_cast<const coff_relocation*>(Rel.p);
    565 }
    566 error_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 }
    573 error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
    574                                                 uint64_t &Res) const {
    575   Res = toRel(Rel)->VirtualAddress;
    576   return object_error::success;
    577 }
    578 error_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 }
    586 error_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 
    596 error_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 
    650 error_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
    651                                                        int64_t &Res) const {
    652   Res = 0;
    653   return object_error::success;
    654 }
    655 error_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 
    669 namespace 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