diff options
| -rw-r--r-- | lld/COFF/Driver.cpp | 4 | ||||
| -rw-r--r-- | lld/COFF/InputFiles.cpp | 2 | ||||
| -rw-r--r-- | lld/COFF/PDB.cpp | 148 | ||||
| -rw-r--r-- | lld/COFF/Writer.cpp | 18 | ||||
| -rw-r--r-- | lld/COFF/Writer.h | 16 | ||||
| -rw-r--r-- | lld/test/COFF/pdb-publics-import.test | 155 | 
6 files changed, 312 insertions, 31 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index bbebe5d9fe3..0ffe05994e2 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -204,7 +204,9 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName,                                      StringRef ParentName) {    file_magic Magic = identify_magic(MB.getBuffer());    if (Magic == file_magic::coff_import_library) { -    Symtab->addFile(make<ImportFile>(MB)); +    InputFile *Imp = make<ImportFile>(MB); +    Imp->ParentName = ParentName; +    Symtab->addFile(Imp);      return;    } diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index b0fbaeff374..eaab17c813b 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -778,7 +778,7 @@ static StringRef getBasename(StringRef Path) {  std::string lld::toString(const coff::InputFile *File) {    if (!File)      return "<internal>"; -  if (File->ParentName.empty()) +  if (File->ParentName.empty() || File->kind() == coff::InputFile::ImportKind)      return File->getName();    return (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index bf1438e7407..b69eac8aac6 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -109,6 +109,9 @@ public:    /// Link CodeView from each object file in the symbol table into the PDB.    void addObjectsToPDB(); +  /// Link info for each import file in the symbol table into the PDB. +  void addImportFilesToPDB(ArrayRef<OutputSection *> OutputSections); +    /// Link CodeView from a single object file into the target (output) PDB.    /// When a precompiled headers object is linked, its TPI map might be provided    /// externally. @@ -878,7 +881,7 @@ static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack,  }  static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, -                            uint32_t CurOffset, ObjFile *File) { +                            uint32_t CurOffset, InputFile *File) {    if (Stack.empty()) {      warn("symbol scopes are not balanced in " + File->getName());      return; @@ -1104,7 +1107,6 @@ static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) {      SC.DataCrc = CRC.getCRC();    } else {      SC.Characteristics = OS ? OS->Header.Characteristics : 0; -    // FIXME: When we start creating DBI for import libraries, use those here.      SC.Imod = Modi;    }    SC.RelocCrc = 0; // FIXME @@ -1454,16 +1456,7 @@ static std::string quote(ArrayRef<StringRef> Args) {    return R;  } -static void addCommonLinkerModuleSymbols(StringRef Path, -                                         pdb::DbiModuleDescriptorBuilder &Mod, -                                         BumpPtrAllocator &Allocator) { -  ObjNameSym ONS(SymbolRecordKind::ObjNameSym); -  Compile3Sym CS(SymbolRecordKind::Compile3Sym); -  EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); - -  ONS.Name = "* Linker *"; -  ONS.Signature = 0; - +static void fillLinkerVerRecord(Compile3Sym &CS) {    CS.Machine = toCodeViewMachine(Config->Machine);    // Interestingly, if we set the string to 0.0.0.0, then when trying to view    // local variables WinDbg emits an error that private symbols are not present. @@ -1487,6 +1480,18 @@ static void addCommonLinkerModuleSymbols(StringRef Path,    CS.VersionFrontendQFE = 0;    CS.Version = "LLVM Linker";    CS.setLanguage(SourceLanguage::Link); +} + +static void addCommonLinkerModuleSymbols(StringRef Path, +                                         pdb::DbiModuleDescriptorBuilder &Mod, +                                         BumpPtrAllocator &Allocator) { +  ObjNameSym ONS(SymbolRecordKind::ObjNameSym); +  EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym); +  Compile3Sym CS(SymbolRecordKind::Compile3Sym); +  fillLinkerVerRecord(CS); + +  ONS.Name = "* Linker *"; +  ONS.Signature = 0;    ArrayRef<StringRef> Args = makeArrayRef(Config->Argv).drop_front();    std::string ArgStr = quote(Args); @@ -1513,6 +1518,33 @@ static void addCommonLinkerModuleSymbols(StringRef Path,        EBS, Allocator, CodeViewContainer::Pdb));  } +static void addLinkerModuleCoffGroup(PartialSection *Sec, +                                     pdb::DbiModuleDescriptorBuilder &Mod, +                                     OutputSection &OS, +                                     BumpPtrAllocator &Allocator) { +  // If there's a section, there's at least one chunk +  assert(!Sec->Chunks.empty()); +  const Chunk *firstChunk = *Sec->Chunks.begin(); +  const Chunk *lastChunk = *Sec->Chunks.rbegin(); + +  // Emit COFF group +  CoffGroupSym CGS(SymbolRecordKind::CoffGroupSym); +  CGS.Name = Sec->Name; +  CGS.Segment = OS.SectionIndex; +  CGS.Offset = firstChunk->getRVA() - OS.getRVA(); +  CGS.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA(); +  CGS.Characteristics = Sec->Characteristics; + +  // Somehow .idata sections & sections groups in the debug symbol stream have +  // the "write" flag set. However the section header for the corresponding +  // .idata section doesn't have it. +  if (CGS.Name.startswith(".idata")) +    CGS.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE; + +  Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol( +      CGS, Allocator, CodeViewContainer::Pdb)); +} +  static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod,                                           OutputSection &OS,                                           BumpPtrAllocator &Allocator) { @@ -1525,6 +1557,97 @@ static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod,    Sym.SectionNumber = OS.SectionIndex;    Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(        Sym, Allocator, CodeViewContainer::Pdb)); + +  // Skip COFF groups in MinGW because it adds a significant footprint to the +  // PDB, due to each function being in its own section +  if (Config->MinGW) +    return; + +  // Output COFF groups for individual chunks of this section. +  for (PartialSection *Sec : OS.ContribSections) { +    addLinkerModuleCoffGroup(Sec, Mod, OS, Allocator); +  } +} + +// Add all import files as modules to the PDB. +void PDBLinker::addImportFilesToPDB(ArrayRef<OutputSection *> OutputSections) { +  if (ImportFile::Instances.empty()) +    return; + +  std::map<std::string, llvm::pdb::DbiModuleDescriptorBuilder *> DllToModuleDbi; + +  for (ImportFile *File : ImportFile::Instances) { +    if (!File->Live) +      continue; + +    if (!File->ThunkSym) +      continue; + +    std::string DLL = StringRef(File->DLLName).lower(); +    llvm::pdb::DbiModuleDescriptorBuilder *&Mod = DllToModuleDbi[DLL]; +    if (!Mod) { +      pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); +      SmallString<128> LibPath = File->ParentName; +      pdbMakeAbsolute(LibPath); +      sys::path::native(LibPath); + +      // Name modules similar to MSVC's link.exe. +      // The first module is the simple dll filename +      llvm::pdb::DbiModuleDescriptorBuilder &FirstMod = +          ExitOnErr(DbiBuilder.addModuleInfo(File->DLLName)); +      FirstMod.setObjFileName(LibPath); +      pdb::SectionContrib SC = +          createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex); +      FirstMod.setFirstSectionContrib(SC); + +      // The second module is where the import stream goes. +      Mod = &ExitOnErr(DbiBuilder.addModuleInfo("Import:" + File->DLLName)); +      Mod->setObjFileName(LibPath); +    } + +    DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym); + +    ObjNameSym ONS(SymbolRecordKind::ObjNameSym); +    Compile3Sym CS(SymbolRecordKind::Compile3Sym); +    Thunk32Sym TS(SymbolRecordKind::Thunk32Sym); +    ScopeEndSym ES(SymbolRecordKind::ScopeEndSym); + +    ONS.Name = File->DLLName; +    ONS.Signature = 0; + +    fillLinkerVerRecord(CS); + +    TS.Name = Thunk->getName(); +    TS.Parent = 0; +    TS.End = 0; +    TS.Next = 0; +    TS.Thunk = ThunkOrdinal::Standard; +    TS.Length = Thunk->getChunk()->getSize(); +    TS.Segment = Thunk->getChunk()->getOutputSection()->SectionIndex; +    TS.Offset = Thunk->getChunk()->OutputSectionOff; + +    Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( +        ONS, Alloc, CodeViewContainer::Pdb)); +    Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol( +        CS, Alloc, CodeViewContainer::Pdb)); + +    SmallVector<SymbolScope, 4> Scopes; +    CVSymbol NewSym = codeview::SymbolSerializer::writeOneSymbol( +        TS, Alloc, CodeViewContainer::Pdb); +    scopeStackOpen(Scopes, Mod->getNextSymbolOffset(), NewSym); + +    Mod->addSymbol(NewSym); + +    NewSym = codeview::SymbolSerializer::writeOneSymbol(ES, Alloc, +                                                        CodeViewContainer::Pdb); +    scopeStackClose(Scopes, Mod->getNextSymbolOffset(), File); + +    Mod->addSymbol(NewSym); + +    pdb::SectionContrib SC = +        createSectionContrib(Thunk->getChunk(), Mod->getModuleIndex()); +    Mod->setFirstSectionContrib(SC); +  }  }  // Creates a PDB file. @@ -1537,6 +1660,7 @@ void coff::createPDB(SymbolTable *Symtab,    PDB.initialize(BuildId);    PDB.addObjectsToPDB(); +  PDB.addImportFilesToPDB(OutputSections);    PDB.addSections(OutputSections, SectionTable);    PDB.addNatvisFiles(); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 07190aff287..0419cef5ea6 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -175,15 +175,6 @@ public:    }  }; -class PartialSection { -public: -  PartialSection(StringRef N, uint32_t Chars) -      : Name(N), Characteristics(Chars) {} -  StringRef Name; -  unsigned Characteristics; -  std::vector<Chunk *> Chunks; -}; -  // The writer writes a SymbolTable result to a file.  class Writer {  public: @@ -312,6 +303,9 @@ void OutputSection::merge(OutputSection *Other) {      C->setOutputSection(this);    Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end());    Other->Chunks.clear(); +  ContribSections.insert(ContribSections.end(), Other->ContribSections.begin(), +                         Other->ContribSections.end()); +  Other->ContribSections.clear();  }  // Write the section header to a given buffer. @@ -329,6 +323,10 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {    }  } +void OutputSection::addContributingPartialSection(PartialSection *Sec) { +  ContribSections.push_back(Sec); +} +  } // namespace coff  } // namespace lld @@ -842,6 +840,8 @@ void Writer::createSections() {      OutputSection *Sec = CreateSection(Name, OutChars);      for (Chunk *C : PSec->Chunks)        Sec->addChunk(C); + +    Sec->addContributingPartialSection(PSec);    }    // Finally, move some output sections to the end. diff --git a/lld/COFF/Writer.h b/lld/COFF/Writer.h index 36ad259a09f..8fd97cb2c96 100644 --- a/lld/COFF/Writer.h +++ b/lld/COFF/Writer.h @@ -22,6 +22,15 @@ static const int PageSize = 4096;  void writeResult(); +class PartialSection { +public: +  PartialSection(StringRef N, uint32_t Chars) +      : Name(N), Characteristics(Chars) {} +  StringRef Name; +  unsigned Characteristics; +  std::vector<Chunk *> Chunks; +}; +  // OutputSection represents a section in an output file. It's a  // container of chunks. OutputSection and Chunk are 1:N relationship.  // Chunks cannot belong to more than one OutputSections. The writer @@ -39,6 +48,7 @@ public:    uint64_t getRVA() { return Header.VirtualAddress; }    uint64_t getFileOff() { return Header.PointerToRawData; }    void writeHeaderTo(uint8_t *Buf); +  void addContributingPartialSection(PartialSection *Sec);    // Returns the size of this section in an executable memory image.    // This may be smaller than the raw size (the raw size is multiple @@ -63,11 +73,13 @@ public:    std::vector<Chunk *> Chunks;    std::vector<Chunk *> OrigChunks; +  std::vector<PartialSection *> ContribSections; +  private:    uint32_t StringTableOff = 0;  }; -} -} +} // namespace coff +} // namespace lld  #endif diff --git a/lld/test/COFF/pdb-publics-import.test b/lld/test/COFF/pdb-publics-import.test index a1fe7d00a08..1b91242c59d 100644 --- a/lld/test/COFF/pdb-publics-import.test +++ b/lld/test/COFF/pdb-publics-import.test @@ -8,7 +8,48 @@ RUN:   /export:exportfn1 /export:exportfn2  RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj  RUN: lld-link /out:%t2.exe /pdb:%t2.pdb /pdbaltpath:test.pdb \  RUN:   /debug /entry:main %t2.obj %t1.lib -RUN: llvm-pdbutil dump %t2.pdb -publics -section-contribs | FileCheck %s +RUN: llvm-pdbutil dump %t2.pdb -all | FileCheck %s + +CHECK:                             Streams +CHECK-NEXT: ============================================================ +CHECK-LABEL:   Stream 10 ( 256 bytes): [Module "Import:pdb-publics-import.test.tmp1.dll"]
 + +CHECK:                         Module Stats
 +CHECK-NEXT: ============================================================
 +CHECK-NEXT: Mod 0000 | `{{.*}}pdb-publics-import.test.tmp2.obj`:
 +CHECK-NEXT:   Mod 0 (debug info not present): [{{.*}}pdb-publics-import.test.tmp2.obj]
 +CHECK-NEXT: Mod 0001 | `pdb-publics-import.test.tmp1.dll`:
 +CHECK-NEXT:   Mod 1 (debug info not present): [pdb-publics-import.test.tmp1.dll]
 +CHECK-NEXT: Mod 0002 | `Import:pdb-publics-import.test.tmp1.dll`:
 +CHECK-NEXT:   Stream 10, 256 bytes
 + +CHECK:                           Modules
 +CHECK-NEXT: ============================================================
 +CHECK-NEXT:   Mod 0000 | `{{.*}}pdb-publics-import.test.tmp2.obj`:
 +CHECK-NEXT:   SC[.text]  | mod = 0, 0001:0000, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:           IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE |
 +CHECK-NEXT:           IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   Obj: `{{.*}}pdb-publics-import.test.tmp2.obj`:
 +CHECK-NEXT:   debug stream: 65535, # files: 0, has ec info: false
 +CHECK-NEXT:   pdb file ni: 0 ``, src file ni: 0 ``
 +CHECK-NEXT: Mod 0001 | `pdb-publics-import.test.tmp1.dll`:
 +CHECK-NEXT: SC[???]  | mod = 65535, 65535:0000, size = -1, data crc = 0, reloc crc = 0
 +CHECK-NEXT:         none
 +CHECK-NEXT: Obj: `{{.*}}pdb-publics-import.test.tmp1.lib`:
 +CHECK-NEXT: debug stream: 65535, # files: 0, has ec info: false
 +CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
 +CHECK-NEXT: Mod 0002 | `Import:pdb-publics-import.test.tmp1.dll`:
 +CHECK-NEXT: SC[.text]  | mod = 2, 0001:0032, size = 6, data crc = 0, reloc crc = 0
 +CHECK-NEXT:         IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
 +CHECK-NEXT: Obj: `{{.*}}pdb-publics-import.test.tmp1.lib`:
 +CHECK-NEXT: debug stream: 10, # files: 0, has ec info: false
 +CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
 +CHECK-NEXT: Mod 0003 | `* Linker *`:
 +CHECK-NEXT: SC[???]  | mod = 65535, 65535:0000, size = -1, data crc = 0, reloc crc = 0
 +CHECK-NEXT:         none
 +CHECK-NEXT: Obj: ``:
 +CHECK-NEXT: debug stream: 11, # files: 0, has ec info: false
 +CHECK-NEXT: pdb file ni: 1 `{{.*}}pdb-publics-import.test.tmp2.pdb`, src file ni: 0 ``
  CHECK:                             Public Symbols  CHECK-NEXT: ============================================================ @@ -24,6 +65,86 @@ CHECK-NEXT:            flags = none, addr = 0002:0136  CHECK-NEXT:        0 | S_PUB32 [size = 32] `__imp_exportfn1`  CHECK-NEXT:            flags = none, addr = 0002:0128 +CHECK:                           Symbols
 +CHECK-NEXT: ============================================================
 +CHECK-NEXT:   Mod 0000 | `{{.*}}pdb-publics-import.test.tmp2.obj`:
 +CHECK-NEXT:   Error loading module stream 0.  The specified stream could not be loaded. Module stream not present
 +CHECK-NEXT: Mod 0001 | `pdb-publics-import.test.tmp1.dll`:
 +CHECK-NEXT: Error loading module stream 1.  The specified stream could not be loaded. Module stream not present
 +CHECK-NEXT: Mod 0002 | `Import:pdb-publics-import.test.tmp1.dll`:
 +CHECK-NEXT:      4 | S_OBJNAME [size = 44] sig=0, `pdb-publics-import.test.tmp1.dll`
 +CHECK-NEXT:     48 | S_COMPILE3 [size = 40]
 +CHECK-NEXT:          machine = intel x86-x64, Ver = LLVM Linker, language = link
 +CHECK-NEXT:          frontend = 0.0.0.0, backend = 14.10.25019.0
 +CHECK-NEXT:          flags = none
 +CHECK-NEXT:     88 | S_THUNK32 [size = 36] `exportfn1`
 +CHECK-NEXT:          parent = 0, end = 124, next = 0
 +CHECK-NEXT:          kind = thunk, size = 6, addr = 0001:0016
 +CHECK-NEXT:    124 | S_END [size = 4]
 +CHECK-NEXT:    128 | S_OBJNAME [size = 44] sig=0, `pdb-publics-import.test.tmp1.dll`
 +CHECK-NEXT:    172 | S_COMPILE3 [size = 40]
 +CHECK-NEXT:          machine = intel x86-x64, Ver = LLVM Linker, language = link
 +CHECK-NEXT:          frontend = 0.0.0.0, backend = 14.10.25019.0
 +CHECK-NEXT:          flags = none
 +CHECK-NEXT:    212 | S_THUNK32 [size = 36] `exportfn2`
 +CHECK-NEXT:          parent = 0, end = 248, next = 0
 +CHECK-NEXT:          kind = thunk, size = 6, addr = 0001:0032
 +CHECK-NEXT:    248 | S_END [size = 4]
 +CHECK-NEXT: Mod 0003 | `* Linker *`:
 +CHECK-NEXT:      4 | S_OBJNAME [size = 20] sig=0, `* Linker *`
 +CHECK-NEXT:     24 | S_COMPILE3 [size = 40]
 +CHECK-NEXT:          machine = intel x86-x64, Ver = LLVM Linker, language = link
 +CHECK-NEXT:          frontend = 0.0.0.0, backend = 14.10.25019.0
 +CHECK-NEXT:          flags = none
 +CHECK-NEXT:     64 | S_ENVBLOCK [size = {{[0-9]+}}]
 +CHECK:  {{[0-9]+}} | S_SECTION [size = 28] `.text`
 +CHECK-NEXT:          length = 38, alignment = 12, rva = 4096, section # = 1
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            code
 +CHECK-NEXT:            execute permissions
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 24] `.text`
 +CHECK-NEXT:          length = 8, addr = 0001:0000
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            code
 +CHECK-NEXT:            execute permissions
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT: {{[0-9]+}} | S_SECTION [size = 28] `.rdata`
 +CHECK-NEXT:          length = 209, alignment = 12, rva = 8192, section # = 2
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            initialized data
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$2`
 +CHECK-NEXT:          length = 40, addr = 0002:0061
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            initialized data
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT:            write permissions
 +CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$4`
 +CHECK-NEXT:          length = 24, addr = 0002:0104
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            initialized data
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT:            write permissions
 +CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$5`
 +CHECK-NEXT:          length = 24, addr = 0002:0128
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            initialized data
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT:            write permissions
 +CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$6`
 +CHECK-NEXT:          length = 24, addr = 0002:0152
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            initialized data
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT:            write permissions
 +CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$7`
 +CHECK-NEXT:          length = 33, addr = 0002:0176
 +CHECK-NEXT:          characteristics =
 +CHECK-NEXT:            initialized data
 +CHECK-NEXT:            read permissions
 +CHECK-NEXT:            write permissions
 +  CHECK:                         Section Contributions  CHECK-NEXT: ============================================================      main @@ -31,13 +152,35 @@ CHECK-NEXT:   SC[.text]   | mod = 0, 0001:0000, size = 8, data crc = 0, reloc cr  CHECK-NEXT:                 IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE |  CHECK-NEXT:                 IMAGE_SCN_MEM_READ      exportfn1 thunk -CHECK-NEXT:   SC[.text]   | mod = 1, 0001:0016, size = 6, data crc = 0, reloc crc = 0 +CHECK-NEXT:   SC[.text]   | mod = 3, 0001:0016, size = 6, data crc = 0, reloc crc = 0  CHECK-NEXT:                 IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ      exportfn2 thunk -CHECK-NEXT:   SC[.text]   | mod = 1, 0001:0032, size = 6, data crc = 0, reloc crc = 0 +CHECK-NEXT:   SC[.text]   | mod = 3, 0001:0032, size = 6, data crc = 0, reloc crc = 0  CHECK-NEXT:                 IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ      .rdata debug directory data chunks -CHECK-NEXT:   SC[.rdata]  | mod = 1, 0002:0000, size = 28, data crc = 0, reloc crc = 0 -CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ -CHECK-NEXT:   SC[.rdata]  | mod = 1, 0002:0028, size = 33, data crc = 0, reloc crc = 0 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0000, size = 28, data crc = 0, reloc crc = 0  CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0028, size = 33, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0061, size = 20, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0081, size = 20, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0104, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0112, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0120, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0128, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0136, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0144, size = 8, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0152, size = 12, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0164, size = 12, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 +CHECK-NEXT:   SC[.rdata]  | mod = 3, 0002:0176, size = 33, data crc = 0, reloc crc = 0
 +CHECK-NEXT:                 IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
  | 

