diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 1a56a90e91e..a0fc9e50cb8 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -212,7 +212,7 @@ namespace llvm { // // This emits the Dwarf file and the line tables. // - static void Emit(MCStreamer *MCOS); + static const MCSymbol *Emit(MCStreamer *MCOS); }; class MCDwarfLineAddr { @@ -235,7 +235,7 @@ namespace llvm { // When generating dwarf for assembly source files this emits the Dwarf // sections. // - static void Emit(MCStreamer *MCOS); + static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); }; // When generating dwarf for assembly source files this is the info that is diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index f7c6765ff32..742d15d9e7e 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -1309,13 +1309,15 @@ void MCAsmStreamer::EmitRawText(StringRef String) { } void MCAsmStreamer::FinishImpl() { + // FIXME: This header is duplicated with MCObjectStreamer // Dump out the dwarf file & directory tables and line tables. + const MCSymbol *LineSectionSymbol; if (getContext().hasDwarfFiles() && !UseLoc) - MCDwarfFileTable::Emit(this); + LineSectionSymbol = MCDwarfFileTable::Emit(this); // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this); + MCGenDwarfInfo::Emit(this, LineSectionSymbol); if (!UseCFI) EmitFrames(false); diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 614549e5239..e16f7aea078 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -209,7 +209,7 @@ static inline void EmitDwarfLineTable(MCStreamer *MCOS, // // This emits the Dwarf file and the line tables. // -void MCDwarfFileTable::Emit(MCStreamer *MCOS) { +const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { MCContext &context = MCOS->getContext(); // Switch to the section where the table will be emitted into. MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); @@ -322,6 +322,8 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS) { // This is the end of the section, so set the value of the symbol at the end // of this section (that was used in a previous expression). MCOS->EmitLabel(LineEndSym); + + return LineStartSym; } /// Utility function to write the encoding to an object writer. @@ -545,7 +547,9 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS) { // When generating dwarf for assembly source files this emits the data for // .debug_info section which contains three parts. The header, the compile_unit // DIE and a list of label DIEs. -static void EmitGenDwarfInfo(MCStreamer *MCOS) { +static void EmitGenDwarfInfo(MCStreamer *MCOS, + const MCSymbol *AbbrevSectionSymbol, + const MCSymbol *LineSectionSymbol) { MCContext &context = MCOS->getContext(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -568,7 +572,11 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS) { // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, // it is at the start of that section so this is zero. - MCOS->EmitIntValue(0, 4); + if (AbbrevSectionSymbol) { + MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4); + } else { + MCOS->EmitIntValue(0, 4); + } const MCAsmInfo &asmInfo = context.getAsmInfo(); int AddrSize = asmInfo.getPointerSize(); @@ -582,7 +590,11 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS) { // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, // which is at the start of that section so this is zero. - MCOS->EmitIntValue(0, 4); + if (LineSectionSymbol) { + MCOS->EmitSymbolValue(LineSectionSymbol, 4); + } else { + MCOS->EmitIntValue(0, 4); + } // AT_low_pc, the first address of the default .text section. const MCExpr *Start = MCSymbolRefExpr::Create( @@ -686,11 +698,20 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS) { // When generating dwarf for assembly source files this emits the Dwarf // sections. // -void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { +void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { // Create the dwarf sections in this order (.debug_line already created). MCContext &context = MCOS->getContext(); + const MCAsmInfo &AsmInfo = context.getAsmInfo(); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); + MCSymbol *AbbrevSectionSymbol; + if (AsmInfo.doesDwarfRequireRelocationForSectionOffset()) { + AbbrevSectionSymbol = context.CreateTempSymbol(); + MCOS->EmitLabel(AbbrevSectionSymbol); + } else { + AbbrevSectionSymbol = NULL; + LineSectionSymbol = NULL; + } MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); // If there are no line table entries then do not emit any section contents. @@ -704,7 +725,7 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { EmitGenDwarfAbbrev(MCOS); // Output the data for .debug_info section. - EmitGenDwarfInfo(MCOS); + EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); } // diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index f2911fa07b9..a7eb8b03a2c 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -266,12 +266,13 @@ void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) { void MCObjectStreamer::FinishImpl() { // Dump out the dwarf file & directory tables and line tables. + const MCSymbol *LineSectionSymbol; if (getContext().hasDwarfFiles()) - MCDwarfFileTable::Emit(this); + LineSectionSymbol = MCDwarfFileTable::Emit(this); // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) - MCGenDwarfInfo::Emit(this); + MCGenDwarfInfo::Emit(this, LineSectionSymbol); getAssembler().Finish(); } diff --git a/test/MC/ELF/gen-dwarf.s b/test/MC/ELF/gen-dwarf.s new file mode 100644 index 00000000000..b090e0802b1 --- /dev/null +++ b/test/MC/ELF/gen-dwarf.s @@ -0,0 +1,70 @@ +// RUN: llvm-mc -g -triple i686-pc-linux-gnu %s -filetype=obj -o - | elf-dump | FileCheck %s + + +// Test that on ELF the debug info has a relocation to debug_abbrev and one to +// to debug_line. + + + .text + .globl foo + .type foo, @function + .align 4 +foo: + ret + .size foo, .-foo + +// Section 4 is .debug_line +// CHECK: # Section 4 +// CHECK-NEXT: # '.debug_line' + + + +// The two relocations, one to symbol 6 and one to 4 +// CHECK: # '.rel.debug_info' +// CHECK-NEXT: ('sh_type', +// CHECK-NEXT: ('sh_flags' +// CHECK-NEXT: ('sh_addr', +// CHECK-NEXT: ('sh_offset', +// CHECK-NEXT: ('sh_size', +// CHECK-NEXT: ('sh_link', +// CHECK-NEXT: ('sh_info', +// CHECK-NEXT: ('sh_addralign', +// CHECK-NEXT: ('sh_entsize', +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0 +// CHECK-NEXT: (('r_offset', 0x00000006) +// CHECK-NEXT: ('r_sym', 0x000006) +// CHECK-NEXT: ('r_type', 0x01) +// CHECK-NEXT: ), +// CHECK-NEXT: # Relocation 1 +// CHECK-NEXT: (('r_offset', 0x0000000c) +// CHECK-NEXT: ('r_sym', 0x000004) +// CHECK-NEXT: ('r_type', 0x01) +// CHECK-NEXT: ), + + +// Section 8 is .debug_abbrev +// CHECK: # Section 8 +// CHECK-NEXT: (('sh_name', 0x00000001) # '.debug_abbrev' + +// Symbol 4 is section 4 (.debug_line) +// CHECK: # Symbol 4 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ('st_bind', 0x0) +// CHECK-NEXT: ('st_type', 0x3) +// CHECK-NEXT: ('st_other', 0x00) +// CHECK-NEXT: ('st_shndx', 0x0004) +// CHECK-NEXT: ), + +// Symbol 6 is section 8 (.debug_abbrev) +// CHECK: # Symbol 6 +// CHECK-NEXT: (('st_name', 0x00000000) # '' +// CHECK-NEXT: ('st_value', 0x00000000) +// CHECK-NEXT: ('st_size', 0x00000000) +// CHECK-NEXT: ('st_bind', 0x0) +// CHECK-NEXT: ('st_type', 0x3) +// CHECK-NEXT: ('st_other', 0x00) +// CHECK-NEXT: ('st_shndx', 0x0008) +// CHECK-NEXT: ),