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