Home | History | Annotate | Download | only in obj2yaml
      1 //===------ utils/obj2yaml.cpp - obj2yaml conversion tool -------*- 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 #include "obj2yaml.h"
     11 #include "llvm/Object/COFF.h"
     12 
     13 
     14 template <typename One, typename Two>
     15 struct pod_pair { // I'd much rather use std::pair, but it's not a POD
     16   One first;
     17   Two second;
     18 };
     19 
     20 #define STRING_PAIR(x)  {llvm::COFF::x, #x}
     21 static const pod_pair<llvm::COFF::MachineTypes, const char *>
     22 MachineTypePairs [] = {
     23   STRING_PAIR(IMAGE_FILE_MACHINE_UNKNOWN),
     24   STRING_PAIR(IMAGE_FILE_MACHINE_AM33),
     25   STRING_PAIR(IMAGE_FILE_MACHINE_AMD64),
     26   STRING_PAIR(IMAGE_FILE_MACHINE_ARM),
     27   STRING_PAIR(IMAGE_FILE_MACHINE_ARMV7),
     28   STRING_PAIR(IMAGE_FILE_MACHINE_EBC),
     29   STRING_PAIR(IMAGE_FILE_MACHINE_I386),
     30   STRING_PAIR(IMAGE_FILE_MACHINE_IA64),
     31   STRING_PAIR(IMAGE_FILE_MACHINE_M32R),
     32   STRING_PAIR(IMAGE_FILE_MACHINE_MIPS16),
     33   STRING_PAIR(IMAGE_FILE_MACHINE_MIPSFPU),
     34   STRING_PAIR(IMAGE_FILE_MACHINE_MIPSFPU16),
     35   STRING_PAIR(IMAGE_FILE_MACHINE_POWERPC),
     36   STRING_PAIR(IMAGE_FILE_MACHINE_POWERPCFP),
     37   STRING_PAIR(IMAGE_FILE_MACHINE_R4000),
     38   STRING_PAIR(IMAGE_FILE_MACHINE_SH3),
     39   STRING_PAIR(IMAGE_FILE_MACHINE_SH3DSP),
     40   STRING_PAIR(IMAGE_FILE_MACHINE_SH4),
     41   STRING_PAIR(IMAGE_FILE_MACHINE_SH5),
     42   STRING_PAIR(IMAGE_FILE_MACHINE_THUMB),
     43   STRING_PAIR(IMAGE_FILE_MACHINE_WCEMIPSV2)
     44 };
     45 
     46 static const pod_pair<llvm::COFF::SectionCharacteristics, const char *>
     47 SectionCharacteristicsPairs1 [] = {
     48   STRING_PAIR(IMAGE_SCN_TYPE_NO_PAD),
     49   STRING_PAIR(IMAGE_SCN_CNT_CODE),
     50   STRING_PAIR(IMAGE_SCN_CNT_INITIALIZED_DATA),
     51   STRING_PAIR(IMAGE_SCN_CNT_UNINITIALIZED_DATA),
     52   STRING_PAIR(IMAGE_SCN_LNK_OTHER),
     53   STRING_PAIR(IMAGE_SCN_LNK_INFO),
     54   STRING_PAIR(IMAGE_SCN_LNK_REMOVE),
     55   STRING_PAIR(IMAGE_SCN_LNK_COMDAT),
     56   STRING_PAIR(IMAGE_SCN_GPREL),
     57   STRING_PAIR(IMAGE_SCN_MEM_PURGEABLE),
     58   STRING_PAIR(IMAGE_SCN_MEM_16BIT),
     59   STRING_PAIR(IMAGE_SCN_MEM_LOCKED),
     60   STRING_PAIR(IMAGE_SCN_MEM_PRELOAD)
     61 };
     62 
     63 static const pod_pair<llvm::COFF::SectionCharacteristics, const char *>
     64 SectionCharacteristicsPairsAlignment [] = {
     65   STRING_PAIR(IMAGE_SCN_ALIGN_1BYTES),
     66   STRING_PAIR(IMAGE_SCN_ALIGN_2BYTES),
     67   STRING_PAIR(IMAGE_SCN_ALIGN_4BYTES),
     68   STRING_PAIR(IMAGE_SCN_ALIGN_8BYTES),
     69   STRING_PAIR(IMAGE_SCN_ALIGN_16BYTES),
     70   STRING_PAIR(IMAGE_SCN_ALIGN_32BYTES),
     71   STRING_PAIR(IMAGE_SCN_ALIGN_64BYTES),
     72   STRING_PAIR(IMAGE_SCN_ALIGN_128BYTES),
     73   STRING_PAIR(IMAGE_SCN_ALIGN_256BYTES),
     74   STRING_PAIR(IMAGE_SCN_ALIGN_512BYTES),
     75   STRING_PAIR(IMAGE_SCN_ALIGN_1024BYTES),
     76   STRING_PAIR(IMAGE_SCN_ALIGN_2048BYTES),
     77   STRING_PAIR(IMAGE_SCN_ALIGN_4096BYTES),
     78   STRING_PAIR(IMAGE_SCN_ALIGN_8192BYTES)
     79 };
     80 
     81 static const pod_pair<llvm::COFF::SectionCharacteristics, const char *>
     82 SectionCharacteristicsPairs2 [] = {
     83   STRING_PAIR(IMAGE_SCN_LNK_NRELOC_OVFL),
     84   STRING_PAIR(IMAGE_SCN_MEM_DISCARDABLE),
     85   STRING_PAIR(IMAGE_SCN_MEM_NOT_CACHED),
     86   STRING_PAIR(IMAGE_SCN_MEM_NOT_PAGED),
     87   STRING_PAIR(IMAGE_SCN_MEM_SHARED),
     88   STRING_PAIR(IMAGE_SCN_MEM_EXECUTE),
     89   STRING_PAIR(IMAGE_SCN_MEM_READ),
     90   STRING_PAIR(IMAGE_SCN_MEM_WRITE)
     91 };
     92 
     93 static const pod_pair<llvm::COFF::SymbolBaseType, const char *>
     94 SymbolBaseTypePairs [] = {
     95   STRING_PAIR(IMAGE_SYM_TYPE_NULL),
     96   STRING_PAIR(IMAGE_SYM_TYPE_VOID),
     97   STRING_PAIR(IMAGE_SYM_TYPE_CHAR),
     98   STRING_PAIR(IMAGE_SYM_TYPE_SHORT),
     99   STRING_PAIR(IMAGE_SYM_TYPE_INT),
    100   STRING_PAIR(IMAGE_SYM_TYPE_LONG),
    101   STRING_PAIR(IMAGE_SYM_TYPE_FLOAT),
    102   STRING_PAIR(IMAGE_SYM_TYPE_DOUBLE),
    103   STRING_PAIR(IMAGE_SYM_TYPE_STRUCT),
    104   STRING_PAIR(IMAGE_SYM_TYPE_UNION),
    105   STRING_PAIR(IMAGE_SYM_TYPE_ENUM),
    106   STRING_PAIR(IMAGE_SYM_TYPE_MOE),
    107   STRING_PAIR(IMAGE_SYM_TYPE_BYTE),
    108   STRING_PAIR(IMAGE_SYM_TYPE_WORD),
    109   STRING_PAIR(IMAGE_SYM_TYPE_UINT),
    110   STRING_PAIR(IMAGE_SYM_TYPE_DWORD)
    111 };
    112 
    113 static const pod_pair<llvm::COFF::SymbolComplexType, const char *>
    114 SymbolComplexTypePairs [] = {
    115   STRING_PAIR(IMAGE_SYM_DTYPE_NULL),
    116   STRING_PAIR(IMAGE_SYM_DTYPE_POINTER),
    117   STRING_PAIR(IMAGE_SYM_DTYPE_FUNCTION),
    118   STRING_PAIR(IMAGE_SYM_DTYPE_ARRAY),
    119 };
    120 
    121 static const pod_pair<llvm::COFF::SymbolStorageClass, const char *>
    122 SymbolStorageClassPairs [] = {
    123   STRING_PAIR(IMAGE_SYM_CLASS_END_OF_FUNCTION),
    124   STRING_PAIR(IMAGE_SYM_CLASS_NULL),
    125   STRING_PAIR(IMAGE_SYM_CLASS_AUTOMATIC),
    126   STRING_PAIR(IMAGE_SYM_CLASS_EXTERNAL),
    127   STRING_PAIR(IMAGE_SYM_CLASS_STATIC),
    128   STRING_PAIR(IMAGE_SYM_CLASS_REGISTER),
    129   STRING_PAIR(IMAGE_SYM_CLASS_EXTERNAL_DEF),
    130   STRING_PAIR(IMAGE_SYM_CLASS_LABEL),
    131   STRING_PAIR(IMAGE_SYM_CLASS_UNDEFINED_LABEL),
    132   STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT),
    133   STRING_PAIR(IMAGE_SYM_CLASS_ARGUMENT),
    134   STRING_PAIR(IMAGE_SYM_CLASS_STRUCT_TAG),
    135   STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_UNION),
    136   STRING_PAIR(IMAGE_SYM_CLASS_UNION_TAG),
    137   STRING_PAIR(IMAGE_SYM_CLASS_TYPE_DEFINITION),
    138   STRING_PAIR(IMAGE_SYM_CLASS_UNDEFINED_STATIC),
    139   STRING_PAIR(IMAGE_SYM_CLASS_ENUM_TAG),
    140   STRING_PAIR(IMAGE_SYM_CLASS_MEMBER_OF_ENUM),
    141   STRING_PAIR(IMAGE_SYM_CLASS_REGISTER_PARAM),
    142   STRING_PAIR(IMAGE_SYM_CLASS_BIT_FIELD),
    143   STRING_PAIR(IMAGE_SYM_CLASS_BLOCK),
    144   STRING_PAIR(IMAGE_SYM_CLASS_FUNCTION),
    145   STRING_PAIR(IMAGE_SYM_CLASS_END_OF_STRUCT),
    146   STRING_PAIR(IMAGE_SYM_CLASS_FILE),
    147   STRING_PAIR(IMAGE_SYM_CLASS_SECTION),
    148   STRING_PAIR(IMAGE_SYM_CLASS_WEAK_EXTERNAL),
    149   STRING_PAIR(IMAGE_SYM_CLASS_CLR_TOKEN),
    150 };
    151 
    152 static const pod_pair<llvm::COFF::RelocationTypeX86, const char *>
    153 RelocationTypeX86Pairs [] = {
    154   STRING_PAIR(IMAGE_REL_I386_ABSOLUTE),
    155   STRING_PAIR(IMAGE_REL_I386_DIR16),
    156   STRING_PAIR(IMAGE_REL_I386_REL16),
    157   STRING_PAIR(IMAGE_REL_I386_DIR32),
    158   STRING_PAIR(IMAGE_REL_I386_DIR32NB),
    159   STRING_PAIR(IMAGE_REL_I386_SEG12),
    160   STRING_PAIR(IMAGE_REL_I386_SECTION),
    161   STRING_PAIR(IMAGE_REL_I386_SECREL),
    162   STRING_PAIR(IMAGE_REL_I386_TOKEN),
    163   STRING_PAIR(IMAGE_REL_I386_SECREL7),
    164   STRING_PAIR(IMAGE_REL_I386_REL32),
    165   STRING_PAIR(IMAGE_REL_AMD64_ABSOLUTE),
    166   STRING_PAIR(IMAGE_REL_AMD64_ADDR64),
    167   STRING_PAIR(IMAGE_REL_AMD64_ADDR32),
    168   STRING_PAIR(IMAGE_REL_AMD64_ADDR32NB),
    169   STRING_PAIR(IMAGE_REL_AMD64_REL32),
    170   STRING_PAIR(IMAGE_REL_AMD64_REL32_1),
    171   STRING_PAIR(IMAGE_REL_AMD64_REL32_2),
    172   STRING_PAIR(IMAGE_REL_AMD64_REL32_3),
    173   STRING_PAIR(IMAGE_REL_AMD64_REL32_4),
    174   STRING_PAIR(IMAGE_REL_AMD64_REL32_5),
    175   STRING_PAIR(IMAGE_REL_AMD64_SECTION),
    176   STRING_PAIR(IMAGE_REL_AMD64_SECREL),
    177   STRING_PAIR(IMAGE_REL_AMD64_SECREL7),
    178   STRING_PAIR(IMAGE_REL_AMD64_TOKEN),
    179   STRING_PAIR(IMAGE_REL_AMD64_SREL32),
    180   STRING_PAIR(IMAGE_REL_AMD64_PAIR),
    181   STRING_PAIR(IMAGE_REL_AMD64_SSPAN32)
    182 };
    183 
    184 static const pod_pair<llvm::COFF::RelocationTypesARM, const char *>
    185 RelocationTypesARMPairs [] = {
    186   STRING_PAIR(IMAGE_REL_ARM_ABSOLUTE),
    187   STRING_PAIR(IMAGE_REL_ARM_ADDR32),
    188   STRING_PAIR(IMAGE_REL_ARM_ADDR32NB),
    189   STRING_PAIR(IMAGE_REL_ARM_BRANCH24),
    190   STRING_PAIR(IMAGE_REL_ARM_BRANCH11),
    191   STRING_PAIR(IMAGE_REL_ARM_TOKEN),
    192   STRING_PAIR(IMAGE_REL_ARM_BLX24),
    193   STRING_PAIR(IMAGE_REL_ARM_BLX11),
    194   STRING_PAIR(IMAGE_REL_ARM_SECTION),
    195   STRING_PAIR(IMAGE_REL_ARM_SECREL),
    196   STRING_PAIR(IMAGE_REL_ARM_MOV32A),
    197   STRING_PAIR(IMAGE_REL_ARM_MOV32T),
    198   STRING_PAIR(IMAGE_REL_ARM_BRANCH20T),
    199   STRING_PAIR(IMAGE_REL_ARM_BRANCH24T),
    200   STRING_PAIR(IMAGE_REL_ARM_BLX23T)
    201 };
    202 #undef STRING_PAIR
    203 
    204 
    205 static const char endl = '\n';
    206 
    207 namespace yaml {  // COFF-specific yaml-writing specific routines
    208 
    209 static llvm::raw_ostream &writeName(llvm::raw_ostream &Out,
    210                              const char *Name, std::size_t NameSize) {
    211   for (std::size_t i = 0; i < NameSize; ++i) {
    212     if (!Name[i]) break;
    213     Out << Name[i];
    214   }
    215   return Out;
    216 }
    217 
    218 // Given an array of pod_pair<enum, const char *>, write all enums that match
    219 template <typename T, std::size_t N>
    220 static llvm::raw_ostream &writeBitMask(llvm::raw_ostream &Out,
    221               const pod_pair<T, const char *> (&Arr)[N], unsigned long Val) {
    222   for (std::size_t i = 0; i < N; ++i)
    223     if (Val & Arr[i].first)
    224       Out << Arr[i].second << ", ";
    225   return Out;
    226 }
    227 
    228 } // end of yaml namespace
    229 
    230 // Given an array of pod_pair<enum, const char *>, look up a value
    231 template <typename T, std::size_t N>
    232 const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N],
    233                            unsigned long Val, const char *NotFound = NULL) {
    234   T n = static_cast<T>(Val);
    235   for (std::size_t i = 0; i < N; ++i)
    236     if (n == Arr[i].first)
    237       return Arr[i].second;
    238   return NotFound;
    239 }
    240 
    241 
    242 static llvm::raw_ostream &yamlCOFFHeader(
    243           const llvm::object::coff_file_header *Header,llvm::raw_ostream &Out) {
    244 
    245   Out << "header: !Header" << endl;
    246   Out << "  Machine: ";
    247   Out << nameLookup(MachineTypePairs, Header->Machine, "# Unknown_MachineTypes")
    248       << " # (";
    249   return yaml::writeHexNumber(Out, Header->Machine) << ")" << endl << endl;
    250 }
    251 
    252 
    253 static llvm::raw_ostream &yamlCOFFSections(llvm::object::COFFObjectFile &Obj,
    254                             std::size_t NumSections, llvm::raw_ostream &Out) {
    255   llvm::error_code ec;
    256   Out << "sections:" << endl;
    257   for (llvm::object::section_iterator iter = Obj.begin_sections();
    258                              iter != Obj.end_sections(); iter.increment(ec)) {
    259     const llvm::object::coff_section *sect = Obj.getCOFFSection(iter);
    260 
    261     Out << "  - !Section" << endl;
    262     Out << "    Name: ";
    263     yaml::writeName(Out, sect->Name, sizeof(sect->Name)) << endl;
    264 
    265     Out << "    Characteristics: [";
    266     yaml::writeBitMask(Out, SectionCharacteristicsPairs1, sect->Characteristics);
    267     Out << nameLookup(SectionCharacteristicsPairsAlignment,
    268         sect->Characteristics & 0x00F00000, "# Unrecognized_IMAGE_SCN_ALIGN")
    269         << ", ";
    270     yaml::writeBitMask(Out, SectionCharacteristicsPairs2, sect->Characteristics);
    271     Out << "] # ";
    272     yaml::writeHexNumber(Out, sect->Characteristics) << endl;
    273 
    274     llvm::ArrayRef<uint8_t> sectionData;
    275     Obj.getSectionContents(sect, sectionData);
    276     Out << "    SectionData: ";
    277     yaml::writeHexStream(Out, sectionData) << endl;
    278     if (iter->begin_relocations() != iter->end_relocations())
    279       Out << "    Relocations:\n";
    280     for (llvm::object::relocation_iterator rIter = iter->begin_relocations();
    281                        rIter != iter->end_relocations(); rIter.increment(ec)) {
    282       const llvm::object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter);
    283 
    284         Out << "      - !Relocation" << endl;
    285         Out << "        VirtualAddress: " ;
    286         yaml::writeHexNumber(Out, reloc->VirtualAddress) << endl;
    287         Out << "        SymbolTableIndex: " << reloc->SymbolTableIndex << endl;
    288         Out << "        Type: "
    289             << nameLookup(RelocationTypeX86Pairs, reloc->Type) << endl;
    290     // TODO: Use the correct reloc type for the machine.
    291         Out << endl;
    292       }
    293 
    294   }
    295   return Out;
    296 }
    297 
    298 static llvm::raw_ostream& yamlCOFFSymbols(llvm::object::COFFObjectFile &Obj,
    299                               std::size_t NumSymbols, llvm::raw_ostream &Out) {
    300   llvm::error_code ec;
    301   Out << "symbols:" << endl;
    302   for (llvm::object::symbol_iterator iter = Obj.begin_symbols();
    303                              iter != Obj.end_symbols(); iter.increment(ec)) {
    304  // Gather all the info that we need
    305     llvm::StringRef str;
    306     const llvm::object::coff_symbol *symbol = Obj.getCOFFSymbol(iter);
    307     Obj.getSymbolName(symbol, str);
    308     std::size_t  simpleType  = symbol->getBaseType();
    309     std::size_t complexType  = symbol->getComplexType();
    310     std::size_t storageClass = symbol->StorageClass;
    311 
    312     Out << "  - !Symbol" << endl;
    313     Out << "    Name: " << str << endl;
    314 
    315     Out << "    Value: "         << symbol->Value << endl;
    316     Out << "    SectionNumber: " << symbol->SectionNumber << endl;
    317 
    318     Out << "    SimpleType: "
    319         << nameLookup(SymbolBaseTypePairs, simpleType,
    320             "# Unknown_SymbolBaseType")
    321         << " # (" << simpleType << ")" << endl;
    322 
    323     Out << "    ComplexType: "
    324         << nameLookup(SymbolComplexTypePairs, complexType,
    325                 "# Unknown_SymbolComplexType")
    326         << " # (" << complexType << ")" << endl;
    327 
    328     Out << "    StorageClass: "
    329         << nameLookup(SymbolStorageClassPairs, storageClass,
    330               "# Unknown_StorageClass")
    331         << " # (" << (int) storageClass << ")" << endl;
    332 
    333     if (symbol->NumberOfAuxSymbols > 0) {
    334       llvm::ArrayRef<uint8_t> aux = Obj.getSymbolAuxData(symbol);
    335       Out << "    NumberOfAuxSymbols: "
    336           << (int) symbol->NumberOfAuxSymbols << endl;
    337       Out << "    AuxillaryData: ";
    338       yaml::writeHexStream(Out, aux);
    339     }
    340 
    341     Out << endl;
    342   }
    343 
    344   return Out;
    345 }
    346 
    347 
    348 llvm::error_code coff2yaml(llvm::raw_ostream &Out, llvm::MemoryBuffer *TheObj) {
    349   llvm::error_code ec;
    350   llvm::object::COFFObjectFile obj(TheObj, ec);
    351   if (!ec) {
    352     const llvm::object::coff_file_header *hd;
    353     ec = obj.getHeader(hd);
    354     if (!ec) {
    355       yamlCOFFHeader(hd, Out);
    356       yamlCOFFSections(obj, hd->NumberOfSections, Out);
    357       yamlCOFFSymbols(obj, hd->NumberOfSymbols, Out);
    358     }
    359   }
    360   return ec;
    361 }
    362