llvm-6502/tools/dsymutil/DwarfLinker.cpp
Zachary Turner 50418a0ac4 Move DebugInfo to DebugInfo/DWARF.
In preparation for adding PDB support to LLVM, this moves the
DWARF parsing code to its own subdirectory under DebugInfo, and
renames LLVMDebugInfo to LLVMDebugInfoDWARF.

This is purely a mechanical / build system change.

Differential Revision: http://reviews.llvm.org/D7269
Reviewed by: Eric Christopher

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227586 91177308-0d34-0410-b5e6-96231b3b80d8
2015-01-30 18:07:45 +00:00

137 lines
3.8 KiB
C++

//===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker -----------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DebugMap.h"
#include "BinaryHolder.h"
#include "DebugMap.h"
#include "dsymutil.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
#include <string>
namespace llvm {
namespace dsymutil {
namespace {
/// \brief Stores all information relating to a compile unit, be it in
/// its original instance in the object file to its brand new cloned
/// and linked DIE tree.
class CompileUnit {
public:
/// \brief Information gathered about a DIE in the object file.
struct DIEInfo {
uint32_t ParentIdx;
};
CompileUnit(DWARFUnit &OrigUnit) : OrigUnit(OrigUnit) {
Info.resize(OrigUnit.getNumDIEs());
}
DWARFUnit &getOrigUnit() { return OrigUnit; }
DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
private:
DWARFUnit &OrigUnit;
std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
};
/// \brief The core of the Dwarf linking logic.
class DwarfLinker {
public:
DwarfLinker(StringRef OutputFilename, bool Verbose)
: OutputFilename(OutputFilename), Verbose(Verbose), BinHolder(Verbose) {}
/// \brief Link the contents of the DebugMap.
bool link(const DebugMap &);
private:
/// \brief Called at the start of a debug object link.
void startDebugObject(DWARFContext &);
/// \brief Called at the end of a debug object link.
void endDebugObject();
private:
std::string OutputFilename;
bool Verbose;
BinaryHolder BinHolder;
/// The units of the current debug map object.
std::vector<CompileUnit> Units;
};
/// \brief Recursive helper to gather the child->parent relationships in the
/// original compile unit.
void GatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE, unsigned ParentIdx,
CompileUnit &CU) {
unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
CU.getInfo(MyIdx).ParentIdx = ParentIdx;
if (DIE->hasChildren())
for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
Child = Child->getSibling())
GatherDIEParents(Child, MyIdx, CU);
}
void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
Units.reserve(Dwarf.getNumCompileUnits());
}
void DwarfLinker::endDebugObject() { Units.clear(); }
bool DwarfLinker::link(const DebugMap &Map) {
if (Map.begin() == Map.end()) {
errs() << "Empty debug map.\n";
return false;
}
for (const auto &Obj : Map.objects()) {
if (Verbose)
outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
auto ErrOrObj = BinHolder.GetObjectFile(Obj->getObjectFilename());
if (std::error_code EC = ErrOrObj.getError()) {
errs() << Obj->getObjectFilename() << ": " << EC.message() << "\n";
continue;
}
// Setup access to the debug info.
DWARFContextInMemory DwarfContext(*ErrOrObj);
startDebugObject(DwarfContext);
// In a first phase, just read in the debug info and store the DIE
// parent links that we will use during the next phase.
for (const auto &CU : DwarfContext.compile_units()) {
auto *CUDie = CU->getCompileUnitDIE(false);
if (Verbose) {
outs() << "Input compilation unit:";
CUDie->dump(outs(), CU.get(), 0);
}
Units.emplace_back(*CU);
GatherDIEParents(CUDie, 0, Units.back());
}
// Clean-up before starting working on the next object.
endDebugObject();
}
return true;
}
}
bool linkDwarf(StringRef OutputFilename, const DebugMap &DM, bool Verbose) {
DwarfLinker Linker(OutputFilename, Verbose);
return Linker.link(DM);
}
}
}