coff2yaml.cpp revision 9e39d0bc2092f97c531591737af8abda48211169
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 13using namespace llvm; 14 15template <typename One, typename Two> 16struct 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) {COFF::x, #x} 22static const pod_pair<COFF::MachineTypes, const char *> 23MachineTypePairs [] = { 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 47static const pod_pair<COFF::SectionCharacteristics, const char *> 48SectionCharacteristicsPairs1 [] = { 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 64static const pod_pair<COFF::SectionCharacteristics, const char *> 65SectionCharacteristicsPairsAlignment [] = { 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 82static const pod_pair<COFF::SectionCharacteristics, const char *> 83SectionCharacteristicsPairs2 [] = { 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 94static const pod_pair<COFF::SymbolBaseType, const char *> 95SymbolBaseTypePairs [] = { 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 114static const pod_pair<COFF::SymbolComplexType, const char *> 115SymbolComplexTypePairs [] = { 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 122static const pod_pair<COFF::SymbolStorageClass, const char *> 123SymbolStorageClassPairs [] = { 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 153static const pod_pair<COFF::RelocationTypeX86, const char *> 154RelocationTypeX86Pairs [] = { 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 185static const pod_pair<COFF::RelocationTypesARM, const char *> 186RelocationTypesARMPairs [] = { 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 205static raw_ostream &writeName(raw_ostream &Out, 206 const char *Name, std::size_t NameSize) { 207 for (std::size_t i = 0; i < NameSize; ++i) { 208 if (!Name[i]) break; 209 Out << Name[i]; 210 } 211 return Out; 212} 213 214// Given an array of pod_pair<enum, const char *>, write all enums that match 215template <typename T, std::size_t N> 216static raw_ostream &writeBitMask(raw_ostream &Out, 217 const pod_pair<T, const char *> (&Arr)[N], 218 unsigned long Val) { 219 for (std::size_t i = 0; i < N; ++i) 220 if (Val & Arr[i].first) 221 Out << Arr[i].second << ", "; 222 return Out; 223} 224 225// Given an array of pod_pair<enum, const char *>, look up a value 226template <typename T, std::size_t N> 227const char *nameLookup(const pod_pair<T, const char *> (&Arr)[N], 228 unsigned long Val, const char *NotFound = NULL) { 229 T n = static_cast<T>(Val); 230 for (std::size_t i = 0; i < N; ++i) 231 if (n == Arr[i].first) 232 return Arr[i].second; 233 return NotFound; 234} 235 236static raw_ostream &yamlCOFFHeader(const object::coff_file_header *Header, 237 raw_ostream &Out) { 238 COFF::header H; 239 H.Machine = Header->Machine; 240 H.Characteristics = Header->Characteristics; 241 242 Out << "header: !Header\n"; 243 Out << " Machine: "; 244 Out << nameLookup(MachineTypePairs, Header->Machine, "# Unknown_MachineTypes") 245 << " # ("; 246 return yaml::writeHexNumber(Out, Header->Machine) << ")\n\n"; 247} 248 249 250static raw_ostream &yamlCOFFSections(object::COFFObjectFile &Obj, 251 std::size_t NumSections, 252 raw_ostream &Out) { 253 error_code ec; 254 Out << "sections:\n"; 255 for (object::section_iterator iter = Obj.begin_sections(); 256 iter != Obj.end_sections(); iter.increment(ec)) { 257 const object::coff_section *sect = Obj.getCOFFSection(iter); 258 259 Out << " - !Section\n"; 260 Out << " Name: "; 261 writeName(Out, sect->Name, sizeof(sect->Name)) << '\n'; 262 263 Out << " Characteristics: ["; 264 writeBitMask(Out, SectionCharacteristicsPairs1, sect->Characteristics); 265 Out << nameLookup(SectionCharacteristicsPairsAlignment, 266 sect->Characteristics & 0x00F00000, "# Unrecognized_IMAGE_SCN_ALIGN") 267 << ", "; 268 writeBitMask(Out, SectionCharacteristicsPairs2, sect->Characteristics); 269 Out << "] # "; 270 yaml::writeHexNumber(Out, sect->Characteristics) << '\n'; 271 272 ArrayRef<uint8_t> sectionData; 273 Obj.getSectionContents(sect, sectionData); 274 Out << " SectionData: "; 275 yaml::writeHexStream(Out, sectionData) << '\n'; 276 if (iter->begin_relocations() != iter->end_relocations()) 277 Out << " Relocations:\n"; 278 for (object::relocation_iterator rIter = iter->begin_relocations(); 279 rIter != iter->end_relocations(); rIter.increment(ec)) { 280 const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter); 281 282 Out << " - !Relocation\n"; 283 Out << " VirtualAddress: " ; 284 yaml::writeHexNumber(Out, reloc->VirtualAddress) << '\n'; 285 Out << " SymbolTableIndex: " << reloc->SymbolTableIndex << '\n'; 286 Out << " Type: " 287 << nameLookup(RelocationTypeX86Pairs, reloc->Type) << '\n'; 288 // TODO: Use the correct reloc type for the machine. 289 Out << '\n'; 290 } 291 292 } 293 return Out; 294} 295 296static raw_ostream& yamlCOFFSymbols(object::COFFObjectFile &Obj, 297 std::size_t NumSymbols, 298 raw_ostream &Out) { 299 error_code ec; 300 Out << "symbols:\n"; 301 for (object::symbol_iterator iter = Obj.begin_symbols(); 302 iter != Obj.end_symbols(); iter.increment(ec)) { 303 // Gather all the info that we need 304 StringRef str; 305 const object::coff_symbol *symbol = Obj.getCOFFSymbol(iter); 306 Obj.getSymbolName(symbol, str); 307 std::size_t simpleType = symbol->getBaseType(); 308 std::size_t complexType = symbol->getComplexType(); 309 std::size_t storageClass = symbol->StorageClass; 310 311 Out << " - !Symbol\n"; 312 Out << " Name: " << str << '\n'; 313 314 Out << " Value: " << symbol->Value << '\n'; 315 Out << " SectionNumber: " << symbol->SectionNumber << '\n'; 316 317 Out << " SimpleType: " 318 << nameLookup(SymbolBaseTypePairs, simpleType, 319 "# Unknown_SymbolBaseType") 320 << " # (" << simpleType << ")\n"; 321 322 Out << " ComplexType: " 323 << nameLookup(SymbolComplexTypePairs, complexType, 324 "# Unknown_SymbolComplexType") 325 << " # (" << complexType << ")\n"; 326 327 Out << " StorageClass: " 328 << nameLookup(SymbolStorageClassPairs, storageClass, 329 "# Unknown_StorageClass") 330 << " # (" << (int) storageClass << ")\n"; 331 332 if (symbol->NumberOfAuxSymbols > 0) { 333 ArrayRef<uint8_t> aux = Obj.getSymbolAuxData(symbol); 334 Out << " NumberOfAuxSymbols: " 335 << (int) symbol->NumberOfAuxSymbols << '\n'; 336 Out << " AuxillaryData: "; 337 yaml::writeHexStream(Out, aux); 338 } 339 340 Out << '\n'; 341 } 342 343 return Out; 344} 345 346 347error_code coff2yaml(raw_ostream &Out, MemoryBuffer *TheObj) { 348 error_code ec; 349 object::COFFObjectFile obj(TheObj, ec); 350 if (ec) 351 return ec; 352 353 const object::coff_file_header *hd; 354 ec = obj.getHeader(hd); 355 if (ec) 356 return ec; 357 358 yamlCOFFHeader(hd, Out); 359 yamlCOFFSections(obj, hd->NumberOfSections, Out); 360 yamlCOFFSymbols(obj, hd->NumberOfSymbols, Out); 361 362 return ec; 363} 364