[BOLT] Fix debug line info emission

Summary:
GDB does not like if the first entry in the line info table after
end_sequence entry is not marked with is_stmt. If this happens, it will
not print the correct line number information for such address. Note
that everything works fine starting with the first address marked
with is_stmt.

This could happen if the first instruction in the cold section wasn't
marked with is_stmt.

The fix is to always emit debug line info for the first instruction
in any function fragment with is_stmt flag.

(cherry picked from FBD14516629)
This commit is contained in:
Maksim Panchenko
2019-03-18 19:22:26 -07:00
parent 61ea19edf8
commit 17cd2034f3
2 changed files with 19 additions and 7 deletions

View File

@@ -2658,6 +2658,8 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
if (!EmitCodeOnly && EmitColdPart && hasConstantIsland())
duplicateConstantIslands();
// Track first emitted instruction with debug info.
bool FirstInstr = true;
for (auto BB : layout()) {
if (EmitColdPart != BB->isCold())
continue;
@@ -2714,7 +2716,8 @@ void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart,
}
if (!EmitCodeOnly && opts::UpdateDebugSections && UnitLineTable.first) {
LastLocSeen = emitLineInfo(Instr.getLoc(), LastLocSeen);
LastLocSeen = emitLineInfo(Instr.getLoc(), LastLocSeen, FirstInstr);
FirstInstr = false;
}
Streamer.EmitInstruction(Instr, *BC.STI);
@@ -3702,7 +3705,8 @@ bool BinaryFunction::isSymbolValidInScope(const SymbolRef &Symbol,
return true;
}
SMLoc BinaryFunction::emitLineInfo(SMLoc NewLoc, SMLoc PrevLoc) const {
SMLoc BinaryFunction::emitLineInfo(SMLoc NewLoc, SMLoc PrevLoc,
bool FirstInstr) const {
auto *FunctionCU = UnitLineTable.first;
const auto *FunctionLineTable = UnitLineTable.second;
assert(FunctionCU && "cannot emit line info for function without CU");
@@ -3737,14 +3741,20 @@ SMLoc BinaryFunction::emitLineInfo(SMLoc NewLoc, SMLoc PrevLoc) const {
if (!CurrentFilenum)
CurrentFilenum = CurrentRow.File;
unsigned Flags = (DWARF2_FLAG_IS_STMT * CurrentRow.IsStmt) |
(DWARF2_FLAG_BASIC_BLOCK * CurrentRow.BasicBlock) |
(DWARF2_FLAG_PROLOGUE_END * CurrentRow.PrologueEnd) |
(DWARF2_FLAG_EPILOGUE_BEGIN * CurrentRow.EpilogueBegin);
// Always emit is_stmt at the beginning of function fragment.
if (FirstInstr)
Flags |= DWARF2_FLAG_IS_STMT;
BC.Ctx->setCurrentDwarfLoc(
CurrentFilenum,
CurrentRow.Line,
CurrentRow.Column,
(DWARF2_FLAG_IS_STMT * CurrentRow.IsStmt) |
(DWARF2_FLAG_BASIC_BLOCK * CurrentRow.BasicBlock) |
(DWARF2_FLAG_PROLOGUE_END * CurrentRow.PrologueEnd) |
(DWARF2_FLAG_EPILOGUE_BEGIN * CurrentRow.EpilogueBegin),
Flags,
CurrentRow.Isa,
CurrentRow.Discriminator);
BC.Ctx->setDwarfCompileUnitID(FunctionUnitIndex);