Rewrite DIContext interface to take an object. Update all callers.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167757 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher 2012-11-12 21:40:38 +00:00
parent f4e3309e84
commit d1726a4580
8 changed files with 116 additions and 264 deletions

View File

@ -19,6 +19,8 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/RelocVisitor.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
@ -102,14 +104,7 @@ public:
virtual ~DIContext();
/// getDWARFContext - get a context for binary DWARF data.
static DIContext *getDWARFContext(bool isLittleEndian,
StringRef infoSection,
StringRef abbrevSection,
StringRef aRangeSection = StringRef(),
StringRef lineSection = StringRef(),
StringRef stringSection = StringRef(),
StringRef rangeSection = StringRef(),
const RelocAddrMap *Map = 0);
static DIContext *getDWARFContext(object::ObjectFile *);
virtual void dump(raw_ostream &OS) = 0;

View File

@ -13,15 +13,6 @@ using namespace llvm;
DIContext::~DIContext() {}
DIContext *DIContext::getDWARFContext(bool isLittleEndian,
StringRef infoSection,
StringRef abbrevSection,
StringRef aRangeSection,
StringRef lineSection,
StringRef stringSection,
StringRef rangeSection,
const RelocAddrMap *Map) {
return new DWARFContextInMemory(isLittleEndian, infoSection, abbrevSection,
aRangeSection, lineSection, stringSection,
rangeSection, Map);
DIContext *DIContext::getDWARFContext(object::ObjectFile *Obj) {
return new DWARFContextInMemory(Obj);
}

View File

@ -298,4 +298,84 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
IsLittleEndian(true /* FIXME */) {
error_code ec;
for (object::section_iterator i = Obj->begin_sections(),
e = Obj->end_sections();
i != e; i.increment(ec)) {
StringRef name;
i->getName(name);
StringRef data;
i->getContents(data);
if (name.startswith("__DWARF,"))
name = name.substr(8); // Skip "__DWARF," prefix.
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
if (name == "debug_info")
InfoSection = data;
else if (name == "debug_abbrev")
AbbrevSection = data;
else if (name == "debug_line")
LineSection = data;
else if (name == "debug_aranges")
ARangeSection = data;
else if (name == "debug_str")
StringSection = data;
else if (name == "debug_ranges")
RangeSection = data;
// Any more debug info sections go here.
else
continue;
// TODO: For now only handle relocations for the debug_info section.
if (name != "debug_info")
continue;
if (i->begin_relocations() != i->end_relocations()) {
uint64_t SectionSize;
i->getSize(SectionSize);
for (object::relocation_iterator reloc_i = i->begin_relocations(),
reloc_e = i->end_relocations();
reloc_i != reloc_e; reloc_i.increment(ec)) {
uint64_t Address;
reloc_i->getAddress(Address);
uint64_t Type;
reloc_i->getType(Type);
object::RelocVisitor V(Obj->getFileFormatName());
// The section address is always 0 for debug sections.
object::RelocToApply R(V.visit(Type, *reloc_i));
if (V.error()) {
SmallString<32> Name;
error_code ec(reloc_i->getTypeName(Name));
if (ec) {
errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
}
errs() << "error: failed to compute relocation: "
<< Name << "\n";
continue;
}
if (Address + R.Width > SectionSize) {
errs() << "error: " << R.Width << "-byte relocation starting "
<< Address << " bytes into section " << name << " which is "
<< SectionSize << " bytes long.\n";
continue;
}
if (R.Width > 8) {
errs() << "error: can't handle a relocation of more than 8 bytes at "
"a time.\n";
continue;
}
DEBUG(dbgs() << "Writing " << format("%p", R.Value)
<< " at " << format("%p", Address)
<< " with width " << format("%d", R.Width)
<< "\n");
RelocMap[Address] = std::make_pair(R.Width, R.Value);
}
}
}
}
void DWARFContextInMemory::anchor() { }

View File

@ -25,9 +25,6 @@ namespace llvm {
/// information parsing. The actual data is supplied through pure virtual
/// methods that a concrete implementation provides.
class DWARFContext : public DIContext {
bool IsLittleEndian;
const RelocAddrMap *RelocMap;
SmallVector<DWARFCompileUnit, 1> CUs;
OwningPtr<DWARFDebugAbbrev> Abbrev;
OwningPtr<DWARFDebugAranges> Aranges;
@ -38,10 +35,9 @@ class DWARFContext : public DIContext {
/// Read compile units from the debug_info section and store them in CUs.
void parseCompileUnits();
protected:
DWARFContext(bool isLittleEndian, const RelocAddrMap *Map) :
IsLittleEndian(isLittleEndian), RelocMap(Map) {}
public:
DWARFContext() {}
virtual void dump(raw_ostream &OS);
/// Get the number of compile units in this context.
@ -72,9 +68,8 @@ public:
virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier());
bool isLittleEndian() const { return IsLittleEndian; }
const RelocAddrMap *relocMap() const { return RelocMap; }
virtual bool isLittleEndian() const = 0;
virtual const RelocAddrMap &relocMap() const = 0;
virtual StringRef getInfoSection() = 0;
virtual StringRef getAbbrevSection() = 0;
virtual StringRef getARangeSection() = 0;
@ -99,6 +94,8 @@ private:
/// pointers to it.
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
bool IsLittleEndian;
RelocAddrMap RelocMap;
StringRef InfoSection;
StringRef AbbrevSection;
StringRef ARangeSection;
@ -106,23 +103,9 @@ class DWARFContextInMemory : public DWARFContext {
StringRef StringSection;
StringRef RangeSection;
public:
DWARFContextInMemory(bool isLittleEndian,
StringRef infoSection,
StringRef abbrevSection,
StringRef aRangeSection,
StringRef lineSection,
StringRef stringSection,
StringRef rangeSection,
const RelocAddrMap *Map = 0)
: DWARFContext(isLittleEndian, Map),
InfoSection(infoSection),
AbbrevSection(abbrevSection),
ARangeSection(aRangeSection),
LineSection(lineSection),
StringSection(stringSection),
RangeSection(rangeSection)
{}
DWARFContextInMemory(object::ObjectFile *);
virtual bool isLittleEndian() const { return IsLittleEndian; }
virtual const RelocAddrMap &relocMap() const { return RelocMap; }
virtual StringRef getInfoSection() { return InfoSection; }
virtual StringRef getAbbrevSection() { return AbbrevSection; }
virtual StringRef getARangeSection() { return ARangeSection; }

View File

@ -100,17 +100,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
switch (Form) {
case DW_FORM_addr:
case DW_FORM_ref_addr: {
bool InRelocMap = false;
if (const RelocAddrMap *RelocMap = cu->getContext().relocMap()) {
RelocAddrMap::const_iterator AI = RelocMap->find(*offset_ptr);
if (AI != RelocMap->end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
Value.uval = R.second;
*offset_ptr += R.first;
InRelocMap = true;
}
}
if (!InRelocMap)
RelocAddrMap::const_iterator AI
= cu->getContext().relocMap().find(*offset_ptr);
if (AI != cu->getContext().relocMap().end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
Value.uval = R.second;
*offset_ptr += R.first;
} else
Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
break;
}
@ -152,17 +148,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Value.sval = data.getSLEB128(offset_ptr);
break;
case DW_FORM_strp: {
bool InRelocMap = false;
if (const RelocAddrMap *RelocMap = cu->getContext().relocMap()) {
RelocAddrMap::const_iterator AI = RelocMap->find(*offset_ptr);
if (AI != RelocMap->end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
Value.uval = R.second;
*offset_ptr += R.first;
InRelocMap = true;
}
}
if (!InRelocMap)
RelocAddrMap::const_iterator AI
= cu->getContext().relocMap().find(*offset_ptr);
if (AI != cu->getContext().relocMap().end()) {
const std::pair<uint8_t, int64_t> &R = AI->second;
Value.uval = R.second;
*offset_ptr += R.first;
} else
Value.uval = data.getU32(offset_ptr);
break;
}

View File

@ -69,100 +69,8 @@ static void DumpInput(const StringRef &Filename) {
}
OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
OwningPtr<DIContext> dictx(DIContext::getDWARFContext(Obj.get()));
StringRef DebugInfoSection;
RelocAddrMap RelocMap;
StringRef DebugAbbrevSection;
StringRef DebugLineSection;
StringRef DebugArangesSection;
StringRef DebugStringSection;
StringRef DebugRangesSection;
error_code ec;
for (section_iterator i = Obj->begin_sections(),
e = Obj->end_sections();
i != e; i.increment(ec)) {
StringRef name;
i->getName(name);
StringRef data;
i->getContents(data);
if (name.startswith("__DWARF,"))
name = name.substr(8); // Skip "__DWARF," prefix.
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
if (name == "debug_info")
DebugInfoSection = data;
else if (name == "debug_abbrev")
DebugAbbrevSection = data;
else if (name == "debug_line")
DebugLineSection = data;
else if (name == "debug_aranges")
DebugArangesSection = data;
else if (name == "debug_str")
DebugStringSection = data;
else if (name == "debug_ranges")
DebugRangesSection = data;
// Any more debug info sections go here.
else
continue;
// TODO: For now only handle relocations for the debug_info section.
if (name != "debug_info")
continue;
if (i->begin_relocations() != i->end_relocations()) {
uint64_t SectionSize;
i->getSize(SectionSize);
for (relocation_iterator reloc_i = i->begin_relocations(),
reloc_e = i->end_relocations();
reloc_i != reloc_e; reloc_i.increment(ec)) {
uint64_t Address;
reloc_i->getAddress(Address);
uint64_t Type;
reloc_i->getType(Type);
RelocVisitor V(Obj->getFileFormatName());
// The section address is always 0 for debug sections.
RelocToApply R(V.visit(Type, *reloc_i));
if (V.error()) {
SmallString<32> Name;
error_code ec(reloc_i->getTypeName(Name));
if (ec) {
errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
}
errs() << "error: failed to compute relocation: "
<< Name << "\n";
continue;
}
if (Address + R.Width > SectionSize) {
errs() << "error: " << R.Width << "-byte relocation starting "
<< Address << " bytes into section " << name << " which is "
<< SectionSize << " bytes long.\n";
continue;
}
if (R.Width > 8) {
errs() << "error: can't handle a relocation of more than 8 bytes at "
"a time.\n";
continue;
}
DEBUG(dbgs() << "Writing " << format("%p", R.Value)
<< " at " << format("%p", Address)
<< " with width " << format("%d", R.Width)
<< "\n");
RelocMap[Address] = std::make_pair(R.Width, R.Value);
}
}
}
OwningPtr<DIContext> dictx(DIContext::getDWARFContext(/*FIXME*/true,
DebugInfoSection,
DebugAbbrevSection,
DebugArangesSection,
DebugLineSection,
DebugStringSection,
DebugRangesSection,
&RelocMap));
if (Address == -1ULL) {
outs() << Filename
<< ":\tfile format " << Obj->getFileFormatName() << "\n\n";

View File

@ -309,16 +309,10 @@ void llvm::DisassembleInputMachO(StringRef Filename) {
raw_ostream &DebugOut = nulls();
#endif
StringRef DebugAbbrevSection, DebugInfoSection, DebugArangesSection,
DebugLineSection, DebugStrSection;
OwningPtr<DIContext> diContext;
OwningPtr<MachOObjectFile> DSYMObj;
MachOObject *DbgInfoObj = MachOObj;
ObjectFile *DbgObj = MachOOF.get();
// Try to find debug info and set up the DIContext for it.
if (UseDbg) {
ArrayRef<SectionRef> DebugSections = Sections;
std::vector<SectionRef> DSYMSections;
// A separate DSym file path was specified, parse it as a macho file,
// get the sections and supply it to the section name parsing machinery.
if (!DSYMFile.empty()) {
@ -327,42 +321,11 @@ void llvm::DisassembleInputMachO(StringRef Filename) {
errs() << "llvm-objdump: " << Filename << ": " << ec.message() << '\n';
return;
}
DSYMObj.reset(static_cast<MachOObjectFile*>(
ObjectFile::createMachOObjectFile(Buf.take())));
const macho::Header &Header = DSYMObj->getObject()->getHeader();
std::vector<SymbolRef> Symbols;
SmallVector<uint64_t, 8> FoundFns;
getSectionsAndSymbols(Header, DSYMObj.get(), 0, DSYMSections, Symbols,
FoundFns);
DebugSections = DSYMSections;
DbgInfoObj = DSYMObj.get()->getObject();
DbgObj = ObjectFile::createMachOObjectFile(Buf.take());
}
// Find the named debug info sections.
for (unsigned SectIdx = 0; SectIdx != DebugSections.size(); SectIdx++) {
StringRef SectName;
if (!DebugSections[SectIdx].getName(SectName)) {
if (SectName.equals("__DWARF,__debug_abbrev"))
DebugSections[SectIdx].getContents(DebugAbbrevSection);
else if (SectName.equals("__DWARF,__debug_info"))
DebugSections[SectIdx].getContents(DebugInfoSection);
else if (SectName.equals("__DWARF,__debug_aranges"))
DebugSections[SectIdx].getContents(DebugArangesSection);
else if (SectName.equals("__DWARF,__debug_line"))
DebugSections[SectIdx].getContents(DebugLineSection);
else if (SectName.equals("__DWARF,__debug_str"))
DebugSections[SectIdx].getContents(DebugStrSection);
}
}
// Setup the DIContext.
diContext.reset(DIContext::getDWARFContext(DbgInfoObj->isLittleEndian(),
DebugInfoSection,
DebugAbbrevSection,
DebugArangesSection,
DebugLineSection,
DebugStrSection));
// Setup the DIContext
diContext.reset(DIContext::getDWARFContext(DbgObj));
}
FunctionMapTy FunctionMap;

View File

@ -170,18 +170,6 @@ typedef ModuleMapTy::iterator ModuleMapIter;
static ModuleMapTy Modules;
static bool isFullNameOfDwarfSection(const StringRef &FullName,
const StringRef &ShortName) {
static const char kDwarfPrefix[] = "__DWARF,";
StringRef Name = FullName;
// Skip "__DWARF," prefix.
if (Name.startswith(kDwarfPrefix))
Name = Name.substr(strlen(kDwarfPrefix));
// Skip . and _ prefixes.
Name = Name.substr(Name.find_first_not_of("._"));
return (Name == ShortName);
}
// Returns true if the object endianness is known.
static bool getObjectEndianness(const ObjectFile *Obj,
bool &IsLittleEndian) {
@ -190,41 +178,6 @@ static bool getObjectEndianness(const ObjectFile *Obj,
return true;
}
static void getDebugInfoSections(const ObjectFile *Obj,
StringRef &DebugInfoSection,
StringRef &DebugAbbrevSection,
StringRef &DebugLineSection,
StringRef &DebugArangesSection,
StringRef &DebugStringSection,
StringRef &DebugRangesSection) {
if (Obj == 0)
return;
error_code ec;
for (section_iterator i = Obj->begin_sections(),
e = Obj->end_sections();
i != e; i.increment(ec)) {
if (error(ec)) break;
StringRef Name;
if (error(i->getName(Name))) continue;
StringRef Data;
if (error(i->getContents(Data))) continue;
if (isFullNameOfDwarfSection(Name, "debug_info"))
DebugInfoSection = Data;
else if (isFullNameOfDwarfSection(Name, "debug_abbrev"))
DebugAbbrevSection = Data;
else if (isFullNameOfDwarfSection(Name, "debug_line"))
DebugLineSection = Data;
// Don't use debug_aranges for now, as address ranges contained
// there may not cover all instructions in the module
// else if (isFullNameOfDwarfSection(Name, "debug_aranges"))
// DebugArangesSection = Data;
else if (isFullNameOfDwarfSection(Name, "debug_str"))
DebugStringSection = Data;
else if (isFullNameOfDwarfSection(Name, "debug_ranges"))
DebugRangesSection = Data;
}
}
static ObjectFile *getObjectFile(const std::string &Path) {
OwningPtr<MemoryBuffer> Buff;
MemoryBuffer::getFile(Path, Buff);
@ -246,6 +199,7 @@ static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) {
return I->second;
ObjectFile *Obj = getObjectFile(ModuleName);
ObjectFile *DbgObj = Obj;
if (Obj == 0) {
// Module name doesn't point to a valid object file.
Modules.insert(make_pair(ModuleName, (ModuleInfo*)0));
@ -255,15 +209,6 @@ static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) {
DIContext *Context = 0;
bool IsLittleEndian;
if (getObjectEndianness(Obj, IsLittleEndian)) {
StringRef DebugInfo;
StringRef DebugAbbrev;
StringRef DebugLine;
StringRef DebugAranges;
StringRef DebugString;
StringRef DebugRanges;
getDebugInfoSections(Obj, DebugInfo, DebugAbbrev, DebugLine,
DebugAranges, DebugString, DebugRanges);
// On Darwin we may find DWARF in separate object file in
// resource directory.
if (isa<MachOObjectFile>(Obj)) {
@ -271,14 +216,9 @@ static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) {
ModuleName);
ObjectFile *ResourceObj = getObjectFile(ResourceName);
if (ResourceObj != 0)
getDebugInfoSections(ResourceObj, DebugInfo, DebugAbbrev, DebugLine,
DebugAranges, DebugString, DebugRanges);
DbgObj = ResourceObj;
}
Context = DIContext::getDWARFContext(
IsLittleEndian, DebugInfo, DebugAbbrev,
DebugAranges, DebugLine, DebugString,
DebugRanges);
Context = DIContext::getDWARFContext(DbgObj);
assert(Context);
}