Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 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" |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 11 | #include "llvm/Object/COFF.h" |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 12 | #include "llvm/Object/COFFYaml.h" |
| 13 | #include "llvm/Support/ErrorHandling.h" |
| 14 | #include "llvm/Support/YAMLTraits.h" |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 15 | |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 16 | using namespace llvm; |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 17 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 18 | namespace { |
| 19 | |
| 20 | class COFFDumper { |
| 21 | const object::COFFObjectFile &Obj; |
| 22 | COFFYAML::Object YAMLObj; |
| 23 | void dumpHeader(const object::coff_file_header *Header); |
| 24 | void dumpSections(unsigned numSections); |
| 25 | void dumpSymbols(unsigned numSymbols); |
| 26 | StringRef getHexString(ArrayRef<uint8_t> Data); |
| 27 | std::vector<std::string> Strings; |
| 28 | |
| 29 | public: |
| 30 | COFFDumper(const object::COFFObjectFile &Obj); |
| 31 | COFFYAML::Object &getYAMLObj(); |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 32 | }; |
| 33 | |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 34 | } |
| 35 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 36 | static void check(error_code ec) { |
| 37 | if (ec) |
| 38 | report_fatal_error(ec.message()); |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 39 | } |
| 40 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 41 | COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) { |
| 42 | const object::coff_file_header *Header; |
| 43 | check(Obj.getHeader(Header)); |
| 44 | dumpHeader(Header); |
| 45 | dumpSections(Header->NumberOfSections); |
| 46 | dumpSymbols(Header->NumberOfSymbols); |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 47 | } |
| 48 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 49 | void COFFDumper::dumpHeader(const object::coff_file_header *Header) { |
| 50 | YAMLObj.Header.Machine = Header->Machine; |
| 51 | YAMLObj.Header.Characteristics = Header->Characteristics; |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 52 | } |
| 53 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 54 | void COFFDumper::dumpSections(unsigned NumSections) { |
| 55 | std::vector<COFFYAML::Section> &Sections = YAMLObj.Sections; |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 56 | error_code ec; |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 57 | for (object::section_iterator iter = Obj.begin_sections(); |
| 58 | iter != Obj.end_sections(); iter.increment(ec)) { |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 59 | check(ec); |
| 60 | const object::coff_section *Sect = Obj.getCOFFSection(iter); |
| 61 | COFFYAML::Section Sec; |
| 62 | Sec.Name = Sect->Name; // FIXME: check the null termination! |
| 63 | uint32_t Characteristics = Sect->Characteristics; |
| 64 | Sec.Header.Characteristics = Characteristics; |
| 65 | Sec.Alignment = 1 << (((Characteristics >> 20) & 0xf) - 1); |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 66 | |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 67 | ArrayRef<uint8_t> sectionData; |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 68 | Obj.getSectionContents(Sect, sectionData); |
| 69 | Sec.SectionData = getHexString(sectionData); |
| 70 | |
| 71 | std::vector<COFF::relocation> Relocations; |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 72 | for (object::relocation_iterator rIter = iter->begin_relocations(); |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 73 | rIter != iter->end_relocations(); rIter.increment(ec)) { |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 74 | const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter); |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 75 | COFF::relocation Rel; |
| 76 | Rel.VirtualAddress = reloc->VirtualAddress; |
| 77 | Rel.SymbolTableIndex = reloc->SymbolTableIndex; |
| 78 | Rel.Type = reloc->Type; |
| 79 | Relocations.push_back(Rel); |
| 80 | } |
| 81 | Sec.Relocations = Relocations; |
| 82 | Sections.push_back(Sec); |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 83 | } |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 84 | } |
| 85 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 86 | void COFFDumper::dumpSymbols(unsigned NumSymbols) { |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 87 | error_code ec; |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 88 | std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols; |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 89 | for (object::symbol_iterator iter = Obj.begin_symbols(); |
| 90 | iter != Obj.end_symbols(); iter.increment(ec)) { |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 91 | check(ec); |
| 92 | const object::coff_symbol *Symbol = Obj.getCOFFSymbol(iter); |
| 93 | COFFYAML::Symbol Sym; |
| 94 | Obj.getSymbolName(Symbol, Sym.Name); |
| 95 | Sym.SimpleType = COFF::SymbolBaseType(Symbol->getBaseType()); |
| 96 | Sym.ComplexType = COFF::SymbolComplexType(Symbol->getComplexType()); |
| 97 | Sym.Header.StorageClass = Symbol->StorageClass; |
| 98 | Sym.Header.Value = Symbol->Value; |
| 99 | Sym.Header.SectionNumber = Symbol->SectionNumber; |
| 100 | Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols; |
| 101 | Sym.AuxiliaryData = getHexString(Obj.getSymbolAuxData(Symbol)); |
| 102 | Symbols.push_back(Sym); |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 103 | } |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 104 | } |
| 105 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 106 | StringRef COFFDumper::getHexString(ArrayRef<uint8_t> Data) { |
| 107 | std::string S; |
| 108 | for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E; |
| 109 | ++I) { |
| 110 | uint8_t Byte = *I; |
| 111 | S.push_back(hexdigit(Byte >> 4)); |
| 112 | S.push_back(hexdigit(Byte & 0xf)); |
| 113 | } |
| 114 | Strings.push_back(S); |
| 115 | return Strings.back(); |
| 116 | } |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 117 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 118 | COFFYAML::Object &COFFDumper::getYAMLObj() { |
| 119 | return YAMLObj; |
| 120 | } |
| 121 | |
| 122 | error_code coff2yaml(raw_ostream &Out, MemoryBuffer *Buff) { |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 123 | error_code ec; |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 124 | object::COFFObjectFile Obj(Buff, ec); |
| 125 | check(ec); |
| 126 | COFFDumper Dumper(Obj); |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 127 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 128 | yaml::Output Yout(Out); |
| 129 | Yout << Dumper.getYAMLObj(); |
Rafael Espindola | da177ce | 2013-04-20 02:55:00 +0000 | [diff] [blame] | 130 | |
Rafael Espindola | 2bbe378 | 2013-05-17 22:58:42 +0000 | [diff] [blame^] | 131 | return object::object_error::success; |
Marshall Clow | c57b888 | 2012-06-19 18:02:35 +0000 | [diff] [blame] | 132 | } |