diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 3f939bbbc01..c064e241283 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -616,6 +616,10 @@ static const MCSymbol *getBaseSymbol(const MCAsmLayout &Layout, void ELFObjectWriter::WriteSymbol(SymbolTableWriter &Writer, ELFSymbolData &MSD, const MCAsmLayout &Layout) { MCSymbolData &OrigData = *MSD.SymbolData; + assert(!OrigData.getFragment() || + (&OrigData.getFragment()->getParent()->getSection() == + &OrigData.getSymbol().getSection()) && + "The symbol's section doesn't match the fragment's symbol"); const MCSymbol *Base = getBaseSymbol(Layout, OrigData.getSymbol()); // This has to be in sync with when computeSymbolTable uses SHN_ABS or @@ -1244,6 +1248,19 @@ getCompressedFragment(MCAsmLayout &Layout, return CompressedFragment; } +static void UpdateSymbols(const MCAsmLayout &Layout, const MCSectionData &SD, + MCAssembler::symbol_range Symbols, + MCFragment *NewFragment) { + for (MCSymbolData &Data : Symbols) { + MCFragment *F = Data.getFragment(); + if (F && F->getParent() == &SD) { + Data.setOffset(Data.getOffset() + + Layout.getFragmentOffset(Data.Fragment)); + Data.setFragment(NewFragment); + } + } +} + static void CompressDebugSection(MCAssembler &Asm, MCAsmLayout &Layout, const MCSectionELF &Section, MCSectionData &SD) { @@ -1257,6 +1274,10 @@ static void CompressDebugSection(MCAssembler &Asm, MCAsmLayout &Layout, if (!CompressedFragment) return; + // Update the fragment+offsets of any symbols referring to fragments in this + // section to refer to the new fragment. + UpdateSymbols(Layout, SD, Asm.symbols(), CompressedFragment.get()); + // Invalidate the layout for the whole section since it will have new and // different fragments now. Layout.invalidateFragmentsFrom(&Fragments.front()); diff --git a/test/MC/ELF/compression.s b/test/MC/ELF/compression.s index 2ecb271e43e..65f920c0926 100644 --- a/test/MC/ELF/compression.s +++ b/test/MC/ELF/compression.s @@ -1,6 +1,8 @@ -// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple x86_64-pc-linux-gnu %s -o %t +// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple x86_64-pc-linux-gnu < %s -o %t // RUN: llvm-objdump -s %t | FileCheck %s // RUN: llvm-dwarfdump -debug-dump=abbrev %t | FileCheck --check-prefix=ABBREV %s +// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple i386-pc-linux-gnu < %s \ +// RUN: | llvm-readobj -symbols - | FileCheck --check-prefix=386-SYMBOLS %s // REQUIRES: zlib @@ -22,12 +24,21 @@ // ABBREV: Abbrev table for offset: 0x00000000 // ABBREV: [1] DW_TAG_compile_unit DW_CHILDREN_no +// In x86 32 bit named symbols are used for temporary symbols in merge +// sections, so make sure we handle symbols inside compressed sections +// 386-SYMBOLS: Name: .Linfo_string0 +// 386-SYMBOLS-NOT: } +// 386-SYMBOLS: Section: .zdebug_str + .section .debug_line,"",@progbits .section .debug_abbrev,"",@progbits +.Lsection_abbrev: .byte 1 # Abbreviation Code .byte 17 # DW_TAG_compile_unit .byte 0 # DW_CHILDREN_no + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp .byte 0 # EOM(1) .byte 0 # EOM(2) .text @@ -38,3 +49,15 @@ foo: nop .cfi_endproc .cfi_sections .debug_frame + + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "foo" + + .section .debug_info,"",@progbits + .long 40 # Length of Unit + .short 4 # DWARF version number + .long .Lsection_abbrev # Offset Into Abbrev. Section + .byte 4 # Address Size (in bytes) + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_comp_dir