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