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