diff --git a/lib/MC/MCWinEH.cpp b/lib/MC/MCWinEH.cpp index f0c354feb61..47eaf0f5564 100644 --- a/lib/MC/MCWinEH.cpp +++ b/lib/MC/MCWinEH.cpp @@ -17,52 +17,45 @@ namespace llvm { namespace WinEH { -static StringRef getSectionSuffix(const MCSymbol *Function) { - if (!Function || !Function->isInSection()) - return ""; - - const MCSection *FunctionSection = &Function->getSection(); - if (const auto Section = dyn_cast(FunctionSection)) { - StringRef Name = Section->getSectionName(); - size_t Dollar = Name.find('$'); - size_t Dot = Name.find('.', 1); - - if (Dollar == StringRef::npos && Dot == StringRef::npos) - return ""; - if (Dot == StringRef::npos) - return Name.substr(Dollar); - if (Dollar == StringRef::npos || Dot < Dollar) - return Name.substr(Dot); - - return Name.substr(Dollar); - } - - return ""; -} +/// We can't have one section for all .pdata or .xdata because the Microsoft +/// linker seems to want all code relocations to refer to the same object file +/// section. If the code described is comdat, create a new comdat section +/// associated with that comdat. If the code described is not in the main .text +/// section, make a new section for it. Otherwise use the main unwind info +/// section. static const MCSection *getUnwindInfoSection( StringRef SecName, const MCSectionCOFF *UnwindSec, const MCSymbol *Function, MCContext &Context) { - // If Function is in a COMDAT, get or create an unwind info section in that - // COMDAT group. if (Function && Function->isInSection()) { + // If Function is in a COMDAT, get or create an unwind info section in that + // COMDAT group. const MCSectionCOFF *FunctionSection = cast(&Function->getSection()); if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { return Context.getAssociativeCOFFSection( UnwindSec, FunctionSection->getCOMDATSymbol()); } + + // If Function is in a section other than .text, create a new .pdata section. + // Otherwise use the plain .pdata section. + if (const auto *Section = dyn_cast(FunctionSection)) { + StringRef CodeSecName = Section->getSectionName(); + if (CodeSecName == ".text") + return UnwindSec; + + if (CodeSecName.startswith(".text$")) + CodeSecName = CodeSecName.substr(6); + + return Context.getCOFFSection( + (SecName + Twine('$') + CodeSecName).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, + SectionKind::getDataRel()); + } } - // If Function is in a section other than .text, create a new .pdata section. - // Otherwise use the plain .pdata section. - StringRef Suffix = getSectionSuffix(Function); - if (Suffix.empty()) - return UnwindSec; - return Context.getCOFFSection((SecName + Suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); + return UnwindSec; + } const MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function, diff --git a/test/MC/COFF/seh-section.s b/test/MC/COFF/seh-section.s index 026c0d73348..c95eece800b 100644 --- a/test/MC/COFF/seh-section.s +++ b/test/MC/COFF/seh-section.s @@ -1,5 +1,7 @@ -// This test ensures that, if the section containing a function has a suffix -// (e.g. .text$foo), its unwind info section also has a suffix (.xdata$foo). +// This test ensures functions in custom sections get unwind info emitted in a +// distinct .xdata section. Ideally we'd just emit a second .xdata section with +// the same name and characteristics, but MC uniques sections by name and +// characteristics, so that is not possible. // RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -s -sd | FileCheck %s // CHECK: Name: .xdata$foo @@ -20,6 +22,44 @@ // CHECK-NEXT: 0000: 01050200 05500402 // CHECK-NEXT: ) +// CHECK: Name: .xdata$.mytext +// CHECK-NEXT: VirtualSize +// CHECK-NEXT: VirtualAddress +// CHECK-NEXT: RawDataSize: 8 +// CHECK-NEXT: PointerToRawData +// CHECK-NEXT: PointerToRelocations +// CHECK-NEXT: PointerToLineNumbers +// CHECK-NEXT: RelocationCount: 0 +// CHECK-NEXT: LineNumberCount: 0 +// CHECK-NEXT: Characteristics [ +// CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES +// CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +// CHECK-NEXT: IMAGE_SCN_MEM_READ +// CHECK-NEXT: ] +// CHECK-NEXT: SectionData ( +// CHECK-NEXT: 0000: 01050200 05500402 +// CHECK-NEXT: ) + +// CHECK: Name: .xdata +// CHECK-NEXT: VirtualSize +// CHECK-NEXT: VirtualAddress +// CHECK-NEXT: RawDataSize: 8 +// CHECK-NEXT: PointerToRawData +// CHECK-NEXT: PointerToRelocations +// CHECK-NEXT: PointerToLineNumbers +// CHECK-NEXT: RelocationCount: 0 +// CHECK-NEXT: LineNumberCount: 0 +// CHECK-NEXT: Characteristics [ +// CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES +// CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA +// CHECK-NEXT: IMAGE_SCN_MEM_READ +// CHECK-NEXT: ] +// CHECK-NEXT: SectionData ( +// CHECK-NEXT: 0000: 01050200 05500402 +// CHECK-NEXT: ) + + + .section .text$foo,"x" .globl foo .def foo; .scl 2; .type 32; .endef @@ -35,3 +75,33 @@ foo: ret .seh_endproc + .section .mytext,"x" + .globl bar + .def bar; .scl 2; .type 32; .endef + .seh_proc bar +bar: + subq $8, %rsp + .seh_stackalloc 8 + pushq %rbp + .seh_pushreg %rbp + .seh_endprologue + popq %rbp + addq $8, %rsp + ret + .seh_endproc + + .section .text + .globl baz + .def baz; .scl 2; .type 32; .endef + .seh_proc baz +baz: + subq $8, %rsp + .seh_stackalloc 8 + pushq %rbp + .seh_pushreg %rbp + .seh_endprologue + popq %rbp + addq $8, %rsp + ret + .seh_endproc +