aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManman Ren <mren@apple.com>2013-03-12 18:27:15 +0000
committerManman Ren <mren@apple.com>2013-03-12 18:27:15 +0000
commitbc3e96f17bb278358cd3976f35b87591a392f5af (patch)
treec59c4eefb0e2cf7a67c9d80baf096c58331eb091
parent1a5c0510ecb029b7e5d04249cdd4e50b97bf1c3f (diff)
Debug Info: use DW_FORM_ref_addr instead of DW_FORM_ref4 if the referenced DIE
belongs to a different compile unit. DW_FORM_ref_addr should be used for cross compile-unit reference. When compiling a large application, we got a dwarfdump verification error where abstract_origin points to nowhere. This error can't be reproduced on any testing case in MultiSource. We may have other cases where we use DW_FORM_ref4 unconditionally. rdar://problem/13370501 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176882 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp11
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h3
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.h5
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp33
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h4
6 files changed, 54 insertions, 4 deletions
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index 4ded2818ed..68d6b6aef7 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -112,6 +112,17 @@ DIE::~DIE() {
delete Children[i];
}
+/// Climb up the parent chain to get the compile unit DIE this DIE belongs to.
+DIE *DIE::getCompileUnit() const{
+ DIE *p = getParent();
+ while (p) {
+ if (p->getTag() == dwarf::DW_TAG_compile_unit)
+ return p;
+ p = p->getParent();
+ }
+ return NULL;
+}
+
#ifndef NDEBUG
void DIE::print(raw_ostream &O, unsigned IncIndent) {
IndentCount += IncIndent;
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index 35d7959ac1..9907b01ceb 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -152,6 +152,9 @@ namespace llvm {
const std::vector<DIE *> &getChildren() const { return Children; }
const SmallVector<DIEValue*, 32> &getValues() const { return Values; }
DIE *getParent() const { return Parent; }
+ /// Climb up the parent chain to get the compile unit DIE this DIE belongs
+ /// to.
+ DIE *getCompileUnit() const;
void setTag(unsigned Tag) { Abbrev.setTag(Tag); }
void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 01f15e52e8..1c743c2414 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -35,7 +35,7 @@ using namespace llvm;
CompileUnit::CompileUnit(unsigned UID, unsigned L, DIE *D, AsmPrinter *A,
DwarfDebug *DW, DwarfUnits *DWU)
: UniqueID(UID), Language(L), CUDie(D), Asm(A), DD(DW), DU(DWU),
- IndexTyDie(0) {
+ IndexTyDie(0), DebugInfoOffset(0) {
DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 77bf6a9e50..2b180c6cc3 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -87,6 +87,9 @@ class CompileUnit {
/// corresponds to the MDNode mapped with the subprogram DIE.
DenseMap<DIE *, const MDNode *> ContainingTypeMap;
+ /// Offset of the CUDie from beginning of debug info section.
+ unsigned DebugInfoOffset;
+
/// getLowerBoundDefault - Return the default lower bound for an array. If the
/// DWARF version doesn't handle the language, return -1.
int64_t getDefaultLowerBound() const;
@@ -103,6 +106,7 @@ public:
unsigned getUniqueID() const { return UniqueID; }
unsigned getLanguage() const { return Language; }
DIE* getCUDie() const { return CUDie.get(); }
+ unsigned getDebugInfoOffset() const { return DebugInfoOffset; }
const StringMap<DIE*> &getGlobalNames() const { return GlobalNames; }
const StringMap<DIE*> &getGlobalTypes() const { return GlobalTypes; }
@@ -120,6 +124,7 @@ public:
return AccelTypes;
}
+ void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }
/// hasContent - Return true if this compile unit has something to write out.
///
bool hasContent() const { return !CUDie->getChildren().empty(); }
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 30bfa78989..2da0bb3364 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -352,11 +352,16 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
// If we're updating an abstract DIE, then we will be adding the children and
// object pointer later on. But what we don't want to do is process the
// concrete DIE twice.
- if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) {
+ DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode);
+ if (AbsSPDIE) {
+ bool InSameCU = (AbsSPDIE->getCompileUnit() == SPCU->getCUDie());
// Pick up abstract subprogram DIE.
SPDie = new DIE(dwarf::DW_TAG_subprogram);
+ // If AbsSPDIE belongs to a different CU, use DW_FORM_ref_addr instead of
+ // DW_FORM_ref4.
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
- dwarf::DW_FORM_ref4, AbsSPDIE);
+ InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+ AbsSPDIE);
SPCU->addDie(SPDie);
} else {
DISubprogram SPDecl = SP.getFunctionDeclaration();
@@ -1692,15 +1697,19 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
// Compute the size and offset of all the DIEs.
void DwarfUnits::computeSizeAndOffsets() {
+ // Offset from the beginning of debug info section.
+ unsigned AccuOffset = 0;
for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
E = CUs.end(); I != E; ++I) {
+ (*I)->setDebugInfoOffset(AccuOffset);
unsigned Offset =
sizeof(int32_t) + // Length of Compilation Unit Info
sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t); // Pointer Size (in bytes)
- computeSizeAndOffset((*I)->getCUDie(), Offset);
+ unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset);
+ AccuOffset += EndOffset;
}
}
@@ -1774,6 +1783,13 @@ void DwarfDebug::emitDIE(DIE *Die, std::vector<DIEAbbrev *> *Abbrevs) {
DIEEntry *E = cast<DIEEntry>(Values[i]);
DIE *Origin = E->getEntry();
unsigned Addr = Origin->getOffset();
+ if (Form == dwarf::DW_FORM_ref_addr) {
+ // For DW_FORM_ref_addr, output the offset from beginning of debug info
+ // section. Origin->getOffset() returns the offset from start of the
+ // compile unit.
+ DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Addr += Holder.getCUOffset(Origin->getCompileUnit());
+ }
Asm->EmitInt32(Addr);
break;
}
@@ -1871,6 +1887,17 @@ void DwarfUnits::emitUnits(DwarfDebug *DD,
}
}
+/// For a given compile unit DIE, returns offset from beginning of debug info.
+unsigned DwarfUnits::getCUOffset(DIE *Die) {
+ for (SmallVector<CompileUnit *, 1>::iterator I = CUs.begin(),
+ E = CUs.end(); I != E; ++I) {
+ CompileUnit *TheCU = *I;
+ if (TheCU->getCUDie() == Die)
+ return TheCU->getDebugInfoOffset();
+ }
+ return 0;
+}
+
// Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 771bc362cb..81e345e628 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -274,6 +274,10 @@ public:
/// \brief Returns the address pool.
AddrPool *getAddrPool() { return &AddressPool; }
+
+ /// \brief for a given compile unit DIE, returns offset from beginning of
+ /// debug info.
+ unsigned getCUOffset(DIE *Die);
};
/// \brief Collects and handles dwarf debug information.