summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorHsiangkai Wang <hsiangkai@gmail.com>2018-08-01 02:18:06 +0000
committerHsiangkai Wang <hsiangkai@gmail.com>2018-08-01 02:18:06 +0000
commit5c63af0d040a377c4fe13a75dea5bb6f84116b9e (patch)
tree8df74eeda05e08aa0508669022ca335bbb73e3dd /llvm/lib
parent6cdfe29d8efaa6987fe708963d65096689f72b14 (diff)
downloadbcm5719-llvm-5c63af0d040a377c4fe13a75dea5bb6f84116b9e.tar.gz
bcm5719-llvm-5c63af0d040a377c4fe13a75dea5bb6f84116b9e.zip
[DebugInfo] Generate fixups as emitting DWARF .debug_line.
It is necessary to generate fixups in .debug_line as relaxation is enabled due to the address delta may be changed after relaxation. DWARF will record the mappings of lines and addresses in .debug_line section. It will encode the information using special opcodes, standard opcodes and extended opcodes in Line Number Program. I use DW_LNS_fixed_advance_pc to encode fixed length address delta and DW_LNE_set_address to encode absolute address to make it possible to generate fixups in .debug_line section. Differential Revision: https://reviews.llvm.org/D46850 llvm-svn: 338477
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/MC/MCAssembler.cpp36
-rw-r--r--llvm/lib/MC/MCDwarf.cpp51
2 files changed, 81 insertions, 6 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index d54e51f0c0d..d3a84e26f1b 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -822,6 +822,9 @@ void MCAssembler::layout(MCAsmLayout &Layout) {
} else if (auto *FragWithFixups = dyn_cast<MCCVDefRangeFragment>(&Frag)) {
Fixups = FragWithFixups->getFixups();
Contents = FragWithFixups->getContents();
+ } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
+ Fixups = FragWithFixups->getFixups();
+ Contents = FragWithFixups->getContents();
} else
llvm_unreachable("Unknown fragment with fixups!");
for (const MCFixup &Fixup : Fixups) {
@@ -951,16 +954,37 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout,
MCContext &Context = Layout.getAssembler().getContext();
uint64_t OldSize = DF.getContents().size();
int64_t AddrDelta;
- bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout);
- assert(Abs && "We created a line delta with an invalid expression");
- (void) Abs;
+ bool Abs = DF.getAddrDelta().evaluateAsAbsolute(AddrDelta, Layout);
int64_t LineDelta;
LineDelta = DF.getLineDelta();
- SmallString<8> &Data = DF.getContents();
+ SmallVectorImpl<char> &Data = DF.getContents();
Data.clear();
raw_svector_ostream OSE(Data);
- MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
- AddrDelta, OSE);
+ DF.getFixups().clear();
+
+ if (Abs) {
+ MCDwarfLineAddr::Encode(Context, getDWARFLinetableParams(), LineDelta,
+ AddrDelta, OSE);
+ } else {
+ uint32_t Offset;
+ uint32_t Size;
+ bool SetDelta = MCDwarfLineAddr::FixedEncode(Context,
+ getDWARFLinetableParams(),
+ LineDelta, AddrDelta,
+ OSE, &Offset, &Size);
+ // Add Fixups for address delta or new address.
+ const MCExpr *FixupExpr;
+ if (SetDelta) {
+ FixupExpr = &DF.getAddrDelta();
+ } else {
+ const MCBinaryExpr *ABE = cast<MCBinaryExpr>(&DF.getAddrDelta());
+ FixupExpr = ABE->getLHS();
+ }
+ DF.getFixups().push_back(
+ MCFixup::create(Offset, FixupExpr,
+ MCFixup::getKindForSize(Size, false /*isPCRel*/)));
+ }
+
return OldSize != Data.size();
}
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index a02cddb5a0b..0461c2564cc 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -731,6 +731,57 @@ void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,
}
}
+bool MCDwarfLineAddr::FixedEncode(MCContext &Context,
+ MCDwarfLineTableParams Params,
+ int64_t LineDelta, uint64_t AddrDelta,
+ raw_ostream &OS,
+ uint32_t *Offset, uint32_t *Size) {
+ if (LineDelta != INT64_MAX) {
+ OS << char(dwarf::DW_LNS_advance_line);
+ encodeSLEB128(LineDelta, OS);
+ }
+
+ // Use address delta to adjust address or use absolute address to adjust
+ // address.
+ bool SetDelta;
+ // According to DWARF spec., the DW_LNS_fixed_advance_pc opcode takes a
+ // single uhalf (unencoded) operand. So, the maximum value of AddrDelta
+ // is 65535. We set a conservative upper bound for it for relaxation.
+ if (AddrDelta > 60000) {
+ const MCAsmInfo *asmInfo = Context.getAsmInfo();
+ unsigned AddrSize = asmInfo->getCodePointerSize();
+
+ OS << char(dwarf::DW_LNS_extended_op);
+ encodeULEB128(1 + AddrSize, OS);
+ OS << char(dwarf::DW_LNE_set_address);
+ // Generate fixup for the address.
+ *Offset = OS.tell();
+ *Size = AddrSize;
+ SetDelta = false;
+ std::vector<uint8_t> FillData;
+ FillData.insert(FillData.begin(), AddrSize, 0);
+ OS.write(reinterpret_cast<char *>(FillData.data()), AddrSize);
+ } else {
+ OS << char(dwarf::DW_LNS_fixed_advance_pc);
+ // Generate fixup for 2-bytes address delta.
+ *Offset = OS.tell();
+ *Size = 2;
+ SetDelta = true;
+ OS << char(0);
+ OS << char(0);
+ }
+
+ if (LineDelta == INT64_MAX) {
+ OS << char(dwarf::DW_LNS_extended_op);
+ OS << char(1);
+ OS << char(dwarf::DW_LNE_end_sequence);
+ } else {
+ OS << char(dwarf::DW_LNS_copy);
+ }
+
+ return SetDelta;
+}
+
// Utility function to write a tuple for .debug_abbrev.
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
MCOS->EmitULEB128IntValue(Name);
OpenPOWER on IntegriCloud