summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-05-25 23:16:12 +0000
committerReid Kleckner <rnk@google.com>2016-05-25 23:16:12 +0000
commit5d122f872d5bb9164ae58eb5f79bbed2ede3f605 (patch)
tree3b717dd9316fe539e73421ff02ce311fa030f729 /llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
parentb5d7ff4fa363363aff9f27a216bd72b008089422 (diff)
downloadbcm5719-llvm-5d122f872d5bb9164ae58eb5f79bbed2ede3f605.tar.gz
bcm5719-llvm-5d122f872d5bb9164ae58eb5f79bbed2ede3f605.zip
[codeview] Use comdats for debug info describing comdat functions
Summary: This allows the linker to discard unused symbol information for comdat functions that were discarded during the link. Before this change, searching for the name of an inline function in the debugger would return multiple results, one per symbol subsection in the object file. After this change, there is only one result, the result for the function chosen by the linker. Reviewers: zturner, majnemer Subscribers: aaboud, amccarth, llvm-commits Differential Revision: http://reviews.llvm.org/D20642 llvm-svn: 270792
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp51
1 files changed, 40 insertions, 11 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 0eb3e44fba1..3f3408eb368 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -18,6 +18,7 @@
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/COFF.h"
#include "llvm/Target/TargetSubtargetInfo.h"
@@ -217,19 +218,19 @@ void CodeViewDebug::maybeRecordLocation(DebugLoc DL,
/*IsStmt=*/false, DL->getFilename());
}
+void CodeViewDebug::emitCodeViewMagicVersion() {
+ OS.EmitValueToAlignment(4);
+ OS.AddComment("Debug section magic");
+ OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
+}
+
void CodeViewDebug::endModule() {
if (FnDebugInfo.empty())
return;
emitTypeInformation();
- // FIXME: For functions that are comdat, we should emit separate .debug$S
- // sections that are comdat associative with the main function instead of
- // having one big .debug$S section.
assert(Asm != nullptr);
- OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
- OS.AddComment("Debug section magic");
- OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
// The COFF .debug$S section consists of several subsections, each starting
// with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
@@ -237,12 +238,16 @@ void CodeViewDebug::endModule() {
// aligned.
// Make a subsection for all the inlined subprograms.
- emitInlineeFuncIdsAndLines();
+ emitInlineeLinesSubsection();
// Emit per-function debug information.
for (auto &P : FnDebugInfo)
emitDebugInfoForFunction(P.first, P.second);
+ // Switch back to the generic .debug$S section after potentially processing
+ // comdat symbol sections.
+ switchToDebugSectionForSymbol(nullptr);
+
// This subsection holds a file index to offset in string table table.
OS.AddComment("File index to string table offset subsection");
OS.EmitCVFileChecksumsDirective();
@@ -275,9 +280,7 @@ void CodeViewDebug::emitTypeInformation() {
// Start the .debug$T section with 0x4.
OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());
- OS.AddComment("Debug section magic");
- OS.EmitValueToAlignment(4);
- OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
+ emitCodeViewMagicVersion();
TypeTable.ForEachRecord(
[&](TypeIndex Index, const MemoryTypeTableBuilder::Record *R) {
@@ -298,10 +301,13 @@ void CodeViewDebug::emitTypeInformation() {
});
}
-void CodeViewDebug::emitInlineeFuncIdsAndLines() {
+void CodeViewDebug::emitInlineeLinesSubsection() {
if (InlinedSubprograms.empty())
return;
+ // Use the generic .debug$S section.
+ switchToDebugSectionForSymbol(nullptr);
+
MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
*InlineEnd = MMI->getContext().createTempSymbol();
@@ -401,6 +407,26 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
OS.EmitIntValue(SymbolKind::S_INLINESITE_END, 2); // RecordKind
}
+void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
+ // If we have a symbol, it may be in a section that is COMDAT. If so, find the
+ // comdat key. A section may be comdat because of -ffunction-sections or
+ // because it is comdat in the IR.
+ MCSectionCOFF *GVSec =
+ GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->getSection()) : nullptr;
+ const MCSymbol *KeySym = GVSec ? GVSec->getCOMDATSymbol() : nullptr;
+
+ MCSectionCOFF *DebugSec = cast<MCSectionCOFF>(
+ Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
+ DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
+
+ OS.SwitchSection(DebugSec);
+
+ // Emit the magic version number if this is the first time we've switched to
+ // this section.
+ if (ComdatDebugSections.insert(DebugSec).second)
+ emitCodeViewMagicVersion();
+}
+
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FunctionInfo &FI) {
// For each function there is a separate subsection
@@ -408,6 +434,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
const MCSymbol *Fn = Asm->getSymbol(GV);
assert(Fn);
+ // Switch to the to a comdat section, if appropriate.
+ switchToDebugSectionForSymbol(Fn);
+
StringRef FuncName;
if (auto *SP = GV->getSubprogram())
FuncName = SP->getDisplayName();
OpenPOWER on IntegriCloud