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