forked from OSchip/llvm-project
[BOLT][DWARF] Properly emit of end-of-sequence entries for line tables
Summary: When the compiler emits line table program, it emits EOS using the label at the end of the containing code section. Since each compilation unit has its own set of code sections it works as expected (* see the excerpt from the standard below). However, in BOLT the code from many CUs is combined into a common section, such as hot text or cold text. As a result, the symbol at the end of the section may point way past the code sequence for a given unit. Since we can emit functions in any order, we conservatively emit end-of-sequence at the end of every emitted function. Fixes a problem while intermixing source code with disassembly in binutils' objdump. (*) DWARF v4 6.2.5.3: "Every line number program sequence must end with a DW_LNE_end_sequence instruction which creates a row whose address is that of the byte after the last target machine instruction of the sequence." (cherry picked from FBD31347870)
This commit is contained in:
parent
98bc9876fb
commit
8ef3b27834
|
@ -11,6 +11,7 @@
|
|||
#include "BinaryEmitter.h"
|
||||
#include "BinaryContext.h"
|
||||
#include "BinaryFunction.h"
|
||||
#include "DebugData.h"
|
||||
#include "Utils.h"
|
||||
#include "llvm/MC/MCSection.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
|
@ -179,6 +180,12 @@ private:
|
|||
SMLoc emitLineInfo(const BinaryFunction &BF, SMLoc NewLoc, SMLoc PrevLoc,
|
||||
bool FirstInstr);
|
||||
|
||||
/// Use \p FunctionEndSymbol to mark the end of the line info sequence.
|
||||
/// Note that it does not automatically result in the insertion of the EOS
|
||||
/// marker in the line table program, but provides one to the DWARF generator
|
||||
/// when it needs it.
|
||||
void emitLineInfoEnd(const BinaryFunction &BF, MCSymbol *FunctionEndSymbol);
|
||||
|
||||
/// Emit debug line information for functions that were not emitted.
|
||||
void emitDebugLineInfoForOriginalFunctions();
|
||||
|
||||
|
@ -385,6 +392,9 @@ bool BinaryEmitter::emitFunction(BinaryFunction &Function, bool EmitColdPart) {
|
|||
Streamer.emitELFSize(StartSymbol, SizeExpr);
|
||||
}
|
||||
|
||||
if (opts::UpdateDebugSections && Function.getDWARFUnit())
|
||||
emitLineInfoEnd(Function, EndSymbol);
|
||||
|
||||
// Exception handling info for the function.
|
||||
emitLSDA(Function, EmitColdPart);
|
||||
|
||||
|
@ -670,6 +680,19 @@ SMLoc BinaryEmitter::emitLineInfo(const BinaryFunction &BF, SMLoc NewLoc,
|
|||
return NewLoc;
|
||||
}
|
||||
|
||||
void BinaryEmitter::emitLineInfoEnd(const BinaryFunction &BF,
|
||||
MCSymbol *FunctionEndLabel) {
|
||||
DWARFUnit *FunctionCU = BF.getDWARFUnit();
|
||||
assert(FunctionCU && "DWARF unit expected");
|
||||
BC.Ctx->setCurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_END_SEQUENCE, 0, 0);
|
||||
const MCDwarfLoc &DwarfLoc = BC.Ctx->getCurrentDwarfLoc();
|
||||
BC.Ctx->clearDwarfLocSeen();
|
||||
BC.getDwarfLineTable(FunctionCU->getOffset())
|
||||
.getMCLineSections()
|
||||
.addLineEntry(MCDwarfLineEntry(FunctionEndLabel, DwarfLoc),
|
||||
Streamer.getCurrentSectionOnly());
|
||||
}
|
||||
|
||||
void BinaryEmitter::emitJumpTables(const BinaryFunction &BF) {
|
||||
MCSection *ReadOnlySection = BC.MOFI->getReadOnlySection();
|
||||
MCSection *ReadOnlyColdSection = BC.MOFI->getContext().getELFSection(
|
||||
|
|
|
@ -642,6 +642,9 @@ static inline void emitBinaryDwarfLineTable(
|
|||
emitEndOfSequence(PrevEndOfSequence);
|
||||
}
|
||||
|
||||
// This function is similar to the one from MCDwarfLineTable, except it handles
|
||||
// end-of-sequence entries differently by utilizing line entries with
|
||||
// DWARF2_FLAG_END_SEQUENCE flag.
|
||||
static inline void emitDwarfLineTable(
|
||||
MCStreamer *MCOS, MCSection *Section,
|
||||
const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
|
||||
|
@ -656,6 +659,19 @@ static inline void emitDwarfLineTable(
|
|||
|
||||
// Loop through each MCDwarfLineEntry and encode the dwarf line number table.
|
||||
for (const MCDwarfLineEntry &LineEntry : LineEntries) {
|
||||
if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
|
||||
MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
|
||||
AsmInfo->getCodePointerSize());
|
||||
FileNum = 1;
|
||||
LastLine = 1;
|
||||
Column = 0;
|
||||
Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
|
||||
Isa = 0;
|
||||
Discriminator = 0;
|
||||
LastLabel = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
|
||||
|
||||
if (FileNum != LineEntry.getFileNum()) {
|
||||
|
@ -705,8 +721,7 @@ static inline void emitDwarfLineTable(
|
|||
LastLabel = Label;
|
||||
}
|
||||
|
||||
// Generate DWARF line end entry.
|
||||
MCOS->emitDwarfLineEndEntry(Section, LastLabel);
|
||||
assert(LastLabel == nullptr && "end of sequence expected");
|
||||
}
|
||||
|
||||
void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#define DWARF2_FLAG_END_SEQUENCE (1 << 4)
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFAbbreviationDeclarationSet;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
## Check that debug_line offsets for the compile unit and for the type unit
|
||||
## match.
|
||||
# REQUIRES: system-linux
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \
|
||||
|
@ -8,6 +10,7 @@
|
|||
# RUN: %p/Inputs/file2.s -o %tfile2.o
|
||||
# RUN: %clangxx %cxxflags %tmain.o %tfile1.o %tfile2.o -o %t.exe -Wl,-q
|
||||
# RUN: llvm-bolt %t.exe --reorder-blocks=reverse -update-debug-sections -o %t.out
|
||||
# RUN: llvm-dwarfdump --debug-types=0x000005f7 %t.out | grep DW_AT_stmt_list | FileCheck %s --check-prefix=CHECK-OUTPUT
|
||||
# RUN: llvm-dwarfdump --debug-info=0x00001c36 --debug-types=0x000005f7 %t.out | FileCheck %s --check-prefix=CHECK-OUTPUT
|
||||
|
||||
# CHECK-OUTPUT: DW_AT_stmt_list (0x000004d4)
|
||||
# CHECK-OUTPUT: DW_AT_stmt_list ([[#%#.8x,OFFSET:]]
|
||||
# CHECK-OUTPUT: DW_AT_stmt_list ([[#OFFSET]])
|
||||
|
|
Loading…
Reference in New Issue