diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/MC/MCWinEH.cpp | 59 | ||||
| -rw-r--r-- | llvm/test/MC/COFF/seh-section.s | 74 | 
2 files changed, 98 insertions, 35 deletions
diff --git a/llvm/lib/MC/MCWinEH.cpp b/llvm/lib/MC/MCWinEH.cpp index f0c354feb61..47eaf0f5564 100644 --- a/llvm/lib/MC/MCWinEH.cpp +++ b/llvm/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<MCSectionCOFF>(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<MCSectionCOFF>(&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<MCSectionCOFF>(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/llvm/test/MC/COFF/seh-section.s b/llvm/test/MC/COFF/seh-section.s index 026c0d73348..c95eece800b 100644 --- a/llvm/test/MC/COFF/seh-section.s +++ b/llvm/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 +  | 

