diff options
author | Hsiangkai Wang <hsiangkai@gmail.com> | 2018-08-01 02:18:06 +0000 |
---|---|---|
committer | Hsiangkai Wang <hsiangkai@gmail.com> | 2018-08-01 02:18:06 +0000 |
commit | 5c63af0d040a377c4fe13a75dea5bb6f84116b9e (patch) | |
tree | 8df74eeda05e08aa0508669022ca335bbb73e3dd /llvm/lib | |
parent | 6cdfe29d8efaa6987fe708963d65096689f72b14 (diff) | |
download | bcm5719-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.cpp | 36 | ||||
-rw-r--r-- | llvm/lib/MC/MCDwarf.cpp | 51 |
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); |