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#include "llvm/Object/COFFYAML.h"
13#include "llvm/Support/ErrorHandling.h"
14#include "llvm/Support/YAMLTraits.h"
15
16using namespace llvm;
17
18namespace {
19
20class 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
27public:
28  COFFDumper(const object::COFFObjectFile &Obj);
29  COFFYAML::Object &getYAMLObj();
30};
31
32}
33
34static void check(error_code ec) {
35  if (ec)
36    report_fatal_error(ec.message());
37}
38
39COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) {
40  const object::coff_file_header *Header;
41  check(Obj.getCOFFHeader(Header));
42  dumpHeader(Header);
43  dumpSections(Header->NumberOfSections);
44  dumpSymbols(Header->NumberOfSymbols);
45}
46
47void COFFDumper::dumpHeader(const object::coff_file_header *Header) {
48  YAMLObj.Header.Machine = Header->Machine;
49  YAMLObj.Header.Characteristics = Header->Characteristics;
50}
51
52void COFFDumper::dumpSections(unsigned NumSections) {
53  std::vector<COFFYAML::Section> &Sections = YAMLObj.Sections;
54  error_code ec;
55  for (object::section_iterator iter = Obj.begin_sections();
56       iter != Obj.end_sections(); iter.increment(ec)) {
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);
64
65    ArrayRef<uint8_t> sectionData;
66    Obj.getSectionContents(Sect, sectionData);
67    Sec.SectionData = object::yaml::BinaryRef(sectionData);
68
69    std::vector<COFFYAML::Relocation> Relocations;
70    for (object::relocation_iterator rIter = iter->begin_relocations();
71                       rIter != iter->end_relocations(); rIter.increment(ec)) {
72      const object::coff_relocation *reloc = Obj.getCOFFRelocation(rIter);
73      COFFYAML::Relocation Rel;
74      object::symbol_iterator Sym = rIter->getSymbol();
75      StringRef Name;
76      Sym->getName(Rel.SymbolName);
77      Rel.VirtualAddress = reloc->VirtualAddress;
78      Rel.Type = reloc->Type;
79      Relocations.push_back(Rel);
80    }
81    Sec.Relocations = Relocations;
82    Sections.push_back(Sec);
83  }
84}
85
86void COFFDumper::dumpSymbols(unsigned NumSymbols) {
87  error_code ec;
88  std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
89  for (object::symbol_iterator iter = Obj.begin_symbols();
90       iter != Obj.end_symbols(); iter.increment(ec)) {
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 = object::yaml::BinaryRef(Obj.getSymbolAuxData(Symbol));
102    Symbols.push_back(Sym);
103  }
104}
105
106COFFYAML::Object &COFFDumper::getYAMLObj() {
107  return YAMLObj;
108}
109
110error_code coff2yaml(raw_ostream &Out, MemoryBuffer *Buff) {
111  error_code ec;
112  object::COFFObjectFile Obj(Buff, ec);
113  check(ec);
114  COFFDumper Dumper(Obj);
115
116  yaml::Output Yout(Out);
117  Yout << Dumper.getYAMLObj();
118
119  return object::object_error::success;
120}
121