Skip to content
7 changes: 7 additions & 0 deletions llvm/include/llvm/MC/CAS/MCCASObjectV1.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ class MCObjectProxy : public cas::ObjectProxy {

MCObjectProxy() = delete;

static Error encodeReferences(ArrayRef<cas::ObjectRef> Refs,
SmallVectorImpl<char> &Data,
SmallVectorImpl<cas::ObjectRef> &IDs);

static Expected<SmallVector<cas::ObjectRef>>
decodeReferences(const MCObjectProxy &Node, StringRef &Remaining);

protected:
MCObjectProxy(const MCSchema &Schema, const cas::ObjectProxy &Node)
: cas::ObjectProxy(Node), Schema(&Schema) {}
Expand Down
15 changes: 8 additions & 7 deletions llvm/lib/MC/MCCASObjectV1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ static Error decodeRelocationsAndAddends(MCCASReader &Reader, StringRef Data) {
return Error::success();
}

static Error encodeReferences(ArrayRef<cas::ObjectRef> Refs,
SmallVectorImpl<char> &Data,
SmallVectorImpl<cas::ObjectRef> &IDs) {
Error MCObjectProxy::encodeReferences(ArrayRef<cas::ObjectRef> Refs,
SmallVectorImpl<char> &Data,
SmallVectorImpl<cas::ObjectRef> &IDs) {
DenseMap<cas::ObjectRef, unsigned> RefMap;
SmallVector<cas::ObjectRef> CompactRefs;
for (const auto &ID : Refs) {
Expand Down Expand Up @@ -430,8 +430,9 @@ static Error encodeReferences(ArrayRef<cas::ObjectRef> Refs,
return Error::success();
}

static Expected<SmallVector<cas::ObjectRef>>
decodeReferences(const MCObjectProxy &Node, StringRef &Remaining) {
Expected<SmallVector<cas::ObjectRef>>
MCObjectProxy::decodeReferences(const MCObjectProxy &Node,
StringRef &Remaining) {
Expected<SmallVector<cas::ObjectRef>> MaybeRefs = loadReferences(Node);
if (!MaybeRefs)
return MaybeRefs.takeError();
Expand Down Expand Up @@ -507,7 +508,7 @@ Expected<LoadedDebugAbbrevSection>
LoadedDebugAbbrevSection::load(DebugAbbrevSectionRef Section) {

StringRef Remaining = Section.getData();
auto Refs = decodeReferences(Section, Remaining);
auto Refs = MCObjectProxy::decodeReferences(Section, Remaining);
if (!Refs)
return Refs.takeError();

Expand Down Expand Up @@ -552,7 +553,7 @@ Expected<LoadedDebugLineSection>
LoadedDebugLineSection::load(DebugLineSectionRef Section) {

StringRef Remaining = Section.getData();
auto Refs = decodeReferences(Section, Remaining);
auto Refs = MCObjectProxy::decodeReferences(Section, Remaining);
if (!Refs)
return Refs.takeError();

Expand Down
161 changes: 153 additions & 8 deletions llvm/tools/llvm-cas-dump/CASDWARFObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,40 @@ using namespace llvm;
using namespace llvm::cas;
using namespace llvm::mccasformats::v1;

std::unordered_map<std::string, std::unordered_set<std::string>>
CASDWARFObject::MapOfLinkageNames =
std::unordered_map<std::string, std::unordered_set<std::string>>();

// template <> struct DenseMapInfo<std::string> {
// static inline std::string getEmptyKey() {
// return std::string(
// reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)), 0);
// }

// static inline std::string getTombstoneKey() {
// return std::string(
// reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)), 0);
// }

// static unsigned getHashValue(std::string Val);

// static bool isEqual(std::string LHS, std::string RHS) {
// if (RHS.data() == getEmptyKey().data())
// return LHS.data() == getEmptyKey().data();
// if (RHS.data() == getTombstoneKey().data())
// return LHS.data() == getTombstoneKey().data();
// return LHS == RHS;
// }
// };

// unsigned DenseMapInfo<std::string>::getHashValue(std::string Val) {
// assert(Val.data() != getEmptyKey().data() &&
// "Cannot hash the empty key!");
// assert(Val.data() != getTombstoneKey().data() &&
// "Cannot hash the tombstone key!");
// return (unsigned)(hash_value(Val));
// }

namespace {
/// Parse the MachO header to extract details such as endianness.
/// Unfortunately object::MachOObjectfile() doesn't support parsing
Expand Down Expand Up @@ -150,24 +184,99 @@ Error CASDWARFObject::discoverDwarfSections(MCObjectProxy MCObj) {
else if (DebugStrRef::Cast(MCObj)) {
DebugStringSection.append(Data.begin(), Data.end());
DebugStringSection.push_back(0);
} else if (DebugInfoCURef::Cast(MCObj))
return Error::success();
if (DebugAbbrevSectionRef::Cast(MCObj) || GroupRef::Cast(MCObj) ||
SymbolTableRef::Cast(MCObj) || SectionRef::Cast(MCObj) ||
DebugLineSectionRef::Cast(MCObj) || AtomRef::Cast(MCObj)) {
auto Refs = MCObjectProxy::decodeReferences(MCObj, Data);
if (!Refs)
return Refs.takeError();
for (auto Ref : *Refs) {
if (Error E = discoverDwarfSections(Ref))
return E;
}
return Error::success();
}
return MCObj.forEachReference(
[this](ObjectRef CASObj) { return discoverDwarfSections(CASObj); });
}

static Optional<StringRef> getLinkageName(DWARFDie &CUDie) {
if (CUDie.getTag() == dwarf::DW_TAG_subprogram) {
auto Decl = CUDie.findRecursively({dwarf::DW_AT_declaration});
if (!Decl) {
StringRef LinkageName = CUDie.getLinkageName();
if (LinkageName.size())
return LinkageName;
}
}
DWARFDie Child = CUDie.getFirstChild();
while(Child) {
auto Name = getLinkageName(Child);
Child = Child.getSibling();
if (Name)
return Name;
}
return None;
}

static void findStrpsInCompileUnit(DWARFDie &CUDie, raw_ostream &OS) {
for (auto Attr : CUDie.attributes()) {
if (Attr.Value.getForm() == llvm::dwarf::DW_FORM_strp) {
Attr.Value.dump(OS);
OS << "\n";
}
}
DWARFDie Child = CUDie.getFirstChild();
while (Child && Child.getAbbreviationDeclarationPtr()) {
findStrpsInCompileUnit(Child, OS);
Child = Child.getSibling();
}
}

// void CASDWARFObject::addLinkageNameAndObjectRefToMap(DWARFDie &CUDie,
// MCObjectProxy MCObj,
// bool &LinkageFound, DWARFUnit &U, DIDumpOptions &DumpOpts) {
// if (CUDie.getTag() == dwarf::DW_TAG_subprogram) {
// auto Decl = CUDie.findRecursively({dwarf::DW_AT_declaration});
// if (!Decl) {
// StringRef LinkageName = CUDie.getLinkageName();
// if (LinkageName.size()) {
// if (MapOfLinkageNames.find(LinkageName.data()) ==
// MapOfLinkageNames.end())
// MapOfLinkageNames.try_emplace(LinkageName.data(),
// std::unordered_set<std::string>());
// SmallVector<char, 0> DumpContents;
// raw_svector_ostream DumpStream(DumpContents);
// U.dump(DumpStream, DumpOpts);
// MapOfLinkageNames[LinkageName.data()].insert(DumpStream.str().data());
// LinkageFound = true;
// }
// }
// }
// DWARFDie Child = CUDie.getFirstChild();
// while (Child && !LinkageFound) {
// addLinkageNameAndObjectRefToMap(Child, MCObj, LinkageFound, U, DumpOpts);
// Child = Child.getSibling();
// }
// }

Error CASDWARFObject::dump(raw_ostream &OS, int Indent, DWARFContext &DWARFCtx,
MCObjectProxy MCObj, bool ShowForm, bool Verbose) {
OS.indent(Indent);
MCObjectProxy MCObj, bool ShowForm, bool Verbose,
bool DumpSameLinkageDifferentCU) {
if (!DumpSameLinkageDifferentCU)
OS.indent(Indent);
DIDumpOptions DumpOpts;
DumpOpts.ShowChildren = true;
DumpOpts.ShowForm = ShowForm;
DumpOpts.Verbose = Verbose;
Error Err = Error::success();
StringRef Data = MCObj.getData();
if (Data.empty())
return Err;
if (DebugStrRef::Cast(MCObj)) {
return Error::success();
if (DebugStrRef::Cast(MCObj) && !DumpSameLinkageDifferentCU) {
// Dump __debug_str data.
Error Err = Error::success();
assert(Data.data()[Data.size()] == 0);
DataExtractor StrData(StringRef(Data.data(), Data.size() + 1),
isLittleEndian(), 0);
Expand All @@ -184,7 +293,7 @@ Error CASDWARFObject::dump(raw_ostream &OS, int Indent, DWARFContext &DWARFCtx,
OS << "\"\n";
StrOffset = Offset;
}
} else if (DebugLineRef::Cast(MCObj)) {
} else if (DebugLineRef::Cast(MCObj) && !DumpSameLinkageDifferentCU) {
// Dump __debug_line data.
uint64_t Address = 0;
DWARFDataExtractor LineData(*this, {Data, Address}, isLittleEndian(), 0);
Expand Down Expand Up @@ -215,7 +324,43 @@ Error CASDWARFObject::dump(raw_ostream &OS, int Indent, DWARFContext &DWARFCtx,
&getLocSection(), getStrSection(),
getStrOffsetsSection(), &getAddrSection(),
getLocSection(), isLittleEndian(), false, UV);
U.dump(OS, DumpOpts);
if (DumpSameLinkageDifferentCU) {
if (DWARFDie CUDie = U.getUnitDIE(false)) {
auto Name = getLinkageName(CUDie);
if (!Name)
return Error::success();
SmallVector<char, 0> StrpData;
raw_svector_ostream OS(StrpData);
findStrpsInCompileUnit(CUDie, OS);
if (MapOfLinkageNames.find(Name->data()) == MapOfLinkageNames.end())
MapOfLinkageNames.try_emplace(Name->data(), std::unordered_set<std::string>());
MapOfLinkageNames[Name->data()].insert(StrpData.data());
}

} else {
U.dump(OS, DumpOpts);
}
}
return Err;
return Error::success();
}

Error CASDWARFObject::dumpSimilarCUs() {
for (auto KeyValue : MapOfLinkageNames) {
if (KeyValue.second.size() == 2) {
for (auto ID : KeyValue.second) {
llvm::outs() << KeyValue.first << " " << ID << "\n";
break;
}
}
}
for (auto KeyValue : MapOfLinkageNames) {
if (KeyValue.second.size() == 2) {
int count = 0;
for (auto ID : KeyValue.second) {
if (count == 0) { count++; continue; }
llvm::outs() << KeyValue.first << " " << ID << "\n";
}
}
}
return Error::success();
}
19 changes: 17 additions & 2 deletions llvm/tools/llvm-cas-dump/CASDWARFObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/MC/CAS/MCCASObjectV1.h"
#include <unordered_map>
#include <unordered_set>

namespace llvm {

Expand All @@ -32,6 +34,9 @@ class CASDWARFObject : public DWARFObject {
SmallVector<StringRef> CUDataVec;
SmallVector<uint32_t> SecOffsetVals;
unsigned LineTableOffset = 0;
DenseMap<cas::ObjectRef, unsigned> MapOfStringOffsets;
static std::unordered_map<std::string, std::unordered_set<std::string>>
MapOfLinkageNames;
unsigned CompileUnitIndex = 0;

const mccasformats::v1::MCSchema &Schema;
Expand All @@ -45,6 +50,10 @@ class CASDWARFObject : public DWARFObject {
/// raw_ostream &OS);
Error discoverDebugInfoSection(cas::ObjectRef CASObj, raw_ostream &OS);

void addLinkageNameAndObjectRefToMap(DWARFDie &CUDie,
mccasformats::v1::MCObjectProxy MCObj,
bool &LinkageFound, DWARFUnit &U, DIDumpOptions &DumpOpts);

public:
CASDWARFObject(const mccasformats::v1::MCSchema &Schema) : Schema(Schema) {}

Expand All @@ -57,10 +66,14 @@ class CASDWARFObject : public DWARFObject {
Error discoverDebugInfoSection(mccasformats::v1::MCObjectProxy MCObj,
raw_ostream &OS);

void addLinkageNameAndObjectRefToMap(DWARFDie CUDie,
mccasformats::v1::MCObjectProxy MCObj,
bool &LinkageFound);

/// Dump MCObj as textual DWARF output.
Error dump(raw_ostream &OS, int Indent, DWARFContext &DWARFCtx,
mccasformats::v1::MCObjectProxy MCObj, bool ShowForm,
bool Verbose);
mccasformats::v1::MCObjectProxy MCObj, bool ShowForm, bool Verbose,
bool DumpSameLinkageDifferentCU);

StringRef getFileName() const override { return "CAS"; }
ArrayRef<SectionName> getSectionNames() const override { return {}; }
Expand All @@ -77,6 +90,8 @@ class CASDWARFObject : public DWARFObject {
return {};
};
ArrayRef<uint32_t> getSecOffsetVals() { return SecOffsetVals; }

static Error dumpSimilarCUs();
};
} // namespace llvm

Expand Down
Loading