| //===------ utils/obj2yaml.cpp - obj2yaml conversion tool -------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "obj2yaml.h" |
| #include "llvm/Object/COFF.h" |
| #include "llvm/Object/COFFYAML.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/YAMLTraits.h" |
| |
| using namespace llvm; |
| |
| namespace { |
| |
| class COFFDumper { |
| const object::COFFObjectFile &Obj; |
| COFFYAML::Object YAMLObj; |
| void dumpHeader(const object::coff_file_header *Header); |
| void dumpSections(unsigned numSections); |
| void dumpSymbols(unsigned numSymbols); |
| |
| public: |
| COFFDumper(const object::COFFObjectFile &Obj); |
| COFFYAML::Object &getYAMLObj(); |
| }; |
| |
| } |
| |
| static void check(error_code ec) { |
| if (ec) |
| report_fatal_error(ec.message()); |
| } |
| |
| COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) { |
| const object::coff_file_header *Header; |
| check(Obj.getCOFFHeader(Header)); |
| dumpHeader(Header); |
| dumpSections(Header->NumberOfSections); |
| dumpSymbols(Header->NumberOfSymbols); |
| } |
| |
| void COFFDumper::dumpHeader(const object::coff_file_header *Header) { |
| YAMLObj.Header.Machine = Header->Machine; |
| YAMLObj.Header.Characteristics = Header->Characteristics; |
| } |
| |
| void COFFDumper::dumpSections(unsigned NumSections) { |
| std::vector<COFFYAML::Section> &Sections = YAMLObj.Sections; |
| error_code ec; |
| for (object::section_iterator iter = Obj.begin_sections(); |
| iter != Obj.end_sections(); iter.increment(ec)) { |
| check(ec); |
| const object::coff_section *Sect = Obj.getCOFFSection(iter); |
| COFFYAML::Section Sec; |
| Sec.Name = Sect->Name; // FIXME: check the null termination! |
| uint32_t Characteristics = Sect->Characteristics; |
| Sec.Header.Characteristics = Characteristics; |
| Sec.Alignment = 1 << (((Characteristics >> 20) & 0xf) - 1); |
| |
| ArrayRef<uint8_t> sectionData; |
| Obj.getSectionContents(Sect, sectionData); |
| Sec.SectionData = object::yaml::BinaryRef(sectionData); |
| |
| std::vector<COFFYAML::Relocation> Relocations; |
| for (object::relocation_iterator rIter = iter->begin_relocations(); |
| rIter != iter->end_relocations(); rIter.increment(ec)) { |
| const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter); |
| COFFYAML::Relocation Rel; |
| object::symbol_iterator Sym = rIter->getSymbol(); |
| Sym->getName(Rel.SymbolName); |
| Rel.VirtualAddress = reloc->VirtualAddress; |
| Rel.Type = reloc->Type; |
| Relocations.push_back(Rel); |
| } |
| Sec.Relocations = Relocations; |
| Sections.push_back(Sec); |
| } |
| } |
| |
| void COFFDumper::dumpSymbols(unsigned NumSymbols) { |
| error_code ec; |
| std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols; |
| for (object::symbol_iterator iter = Obj.begin_symbols(); |
| iter != Obj.end_symbols(); iter.increment(ec)) { |
| check(ec); |
| const object::coff_symbol *Symbol = Obj.getCOFFSymbol(iter); |
| COFFYAML::Symbol Sym; |
| Obj.getSymbolName(Symbol, Sym.Name); |
| Sym.SimpleType = COFF::SymbolBaseType(Symbol->getBaseType()); |
| Sym.ComplexType = COFF::SymbolComplexType(Symbol->getComplexType()); |
| Sym.Header.StorageClass = Symbol->StorageClass; |
| Sym.Header.Value = Symbol->Value; |
| Sym.Header.SectionNumber = Symbol->SectionNumber; |
| Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols; |
| Sym.AuxiliaryData = object::yaml::BinaryRef(Obj.getSymbolAuxData(Symbol)); |
| Symbols.push_back(Sym); |
| } |
| } |
| |
| COFFYAML::Object &COFFDumper::getYAMLObj() { |
| return YAMLObj; |
| } |
| |
| error_code coff2yaml(raw_ostream &Out, MemoryBuffer *Buff) { |
| error_code ec; |
| object::COFFObjectFile Obj(Buff, ec); |
| check(ec); |
| COFFDumper Dumper(Obj); |
| |
| yaml::Output Yout(Out); |
| Yout << Dumper.getYAMLObj(); |
| |
| return object::object_error::success; |
| } |