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