[lld] r309303 - [PDB] Write public symbol records and the publics hash table
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 27 11:25:59 PDT 2017
Author: rnk
Date: Thu Jul 27 11:25:59 2017
New Revision: 309303
URL: http://llvm.org/viewvc/llvm-project?rev=309303&view=rev
Log:
[PDB] Write public symbol records and the publics hash table
Summary:
MSVC link.exe records all external symbol names in the publics stream.
It provides similar functionality to an ELF .symtab.
Reviewers: zturner, ruiu
Subscribers: hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D35871
Added:
lld/trunk/test/COFF/pdb-publics-import.test
Modified:
lld/trunk/COFF/PDB.cpp
lld/trunk/COFF/SymbolTable.h
lld/trunk/COFF/Symbols.cpp
lld/trunk/COFF/Symbols.h
lld/trunk/COFF/Writer.cpp
lld/trunk/test/COFF/pdb-import-gc.yaml
lld/trunk/test/COFF/pdb.test
Modified: lld/trunk/COFF/PDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/PDB.cpp?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/COFF/PDB.cpp (original)
+++ lld/trunk/COFF/PDB.cpp Thu Jul 27 11:25:59 2017
@@ -13,6 +13,7 @@
#include "Error.h"
#include "SymbolTable.h"
#include "Symbols.h"
+#include "Writer.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@@ -34,6 +35,7 @@
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
@@ -545,6 +547,23 @@ void PDBLinker::addObjFile(ObjFile *File
}
}
+static PublicSym32 createPublic(Defined *Def) {
+ PublicSym32 Pub(SymbolKind::S_PUB32);
+ Pub.Name = Def->getName();
+ if (auto *D = dyn_cast<DefinedCOFF>(Def)) {
+ if (D->getCOFFSymbol().isFunctionDefinition())
+ Pub.Flags = PublicSymFlags::Function;
+ } else if (isa<DefinedImportThunk>(Def)) {
+ Pub.Flags = PublicSymFlags::Function;
+ }
+
+ OutputSection *OS = Def->getChunk()->getOutputSection();
+ assert(OS && "all publics should be in final image");
+ Pub.Offset = Def->getRVA() - OS->getRVA();
+ Pub.Segment = OS->SectionIndex;
+ return Pub;
+}
+
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
// TpiData.
void PDBLinker::addObjectsToPDB() {
@@ -559,12 +578,25 @@ void PDBLinker::addObjectsToPDB() {
// Construct IPI stream contents.
addTypeInfo(Builder.getIpiBuilder(), IDTable);
- // Add public and symbol records stream.
+ // Compute the public symbols.
+ std::vector<PublicSym32> Publics;
+ Symtab->forEachSymbol([&Publics](Symbol *S) {
+ // Only emit defined, live symbols that have a chunk.
+ auto *Def = dyn_cast<Defined>(S->body());
+ if (Def && Def->isLive() && Def->getChunk())
+ Publics.push_back(createPublic(Def));
+ });
- // For now we don't actually write any thing useful to the publics stream, but
- // the act of "getting" it also creates it lazily so that we write an empty
- // stream.
- (void)Builder.getPublicsBuilder();
+ if (!Publics.empty()) {
+ // Sort the public symbols and add them to the stream.
+ std::sort(Publics.begin(), Publics.end(),
+ [](const PublicSym32 &L, const PublicSym32 &R) {
+ return L.Name < R.Name;
+ });
+ auto &PublicsBuilder = Builder.getPublicsBuilder();
+ for (const PublicSym32 &Pub : Publics)
+ PublicsBuilder.addPublicSymbol(Pub);
+ }
}
static void addLinkerModuleSymbols(StringRef Path,
Modified: lld/trunk/COFF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.h (original)
+++ lld/trunk/COFF/SymbolTable.h Thu Jul 27 11:25:59 2017
@@ -99,6 +99,12 @@ public:
// A list of chunks which to be added to .rdata.
std::vector<Chunk *> LocalImportChunks;
+ // Iterates symbols in non-determinstic hash table order.
+ template <typename T> void forEachSymbol(T Callback) {
+ for (auto &Pair : Symtab)
+ Callback(Pair.second);
+ }
+
private:
std::pair<Symbol *, bool> insert(StringRef Name);
StringRef findByPrefix(StringRef Prefix);
Modified: lld/trunk/COFF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.cpp?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.cpp (original)
+++ lld/trunk/COFF/Symbols.cpp Thu Jul 27 11:25:59 2017
@@ -52,6 +52,17 @@ InputFile *SymbolBody::getFile() {
return nullptr;
}
+bool SymbolBody::isLive() const {
+ if (auto *R = dyn_cast<DefinedRegular>(this))
+ return R->getChunk()->isLive();
+ if (auto *Imp = dyn_cast<DefinedImportData>(this))
+ return Imp->File->Live;
+ if (auto *Imp = dyn_cast<DefinedImportThunk>(this))
+ return Imp->WrappedSym->File->Live;
+ // Assume any other kind of symbol is live.
+ return true;
+}
+
COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
size_t SymSize = cast<ObjFile>(File)->getCOFFObj()->getSymbolTableEntrySize();
if (SymSize == sizeof(coff_symbol16))
Modified: lld/trunk/COFF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.h?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.h (original)
+++ lld/trunk/COFF/Symbols.h Thu Jul 27 11:25:59 2017
@@ -70,6 +70,10 @@ public:
// Returns the file from which this symbol was created.
InputFile *getFile();
+ // Indicates that this symbol will be included in the final image. Only valid
+ // after calling markLive.
+ bool isLive() const;
+
Symbol *symbol();
const Symbol *symbol() const {
return const_cast<SymbolBody *>(this)->symbol();
@@ -155,10 +159,10 @@ public:
return S->kind() == DefinedRegularKind;
}
- uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; }
- bool isCOMDAT() { return IsCOMDAT; }
- SectionChunk *getChunk() { return *Data; }
- uint32_t getValue() { return Sym->Value; }
+ uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }
+ bool isCOMDAT() const { return IsCOMDAT; }
+ SectionChunk *getChunk() const { return *Data; }
+ uint32_t getValue() const { return Sym->Value; }
private:
SectionChunk **Data;
Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Thu Jul 27 11:25:59 2017
@@ -432,19 +432,12 @@ Optional<coff_symbol16> Writer::createSy
if (isa<DefinedSynthetic>(Def))
return None;
- if (auto *D = dyn_cast<DefinedRegular>(Def)) {
- // Don't write dead symbols or symbols in codeview sections to the symbol
- // table.
- if (!D->getChunk()->isLive() || D->getChunk()->isCodeView())
- return None;
- }
-
- if (auto *Sym = dyn_cast<DefinedImportData>(Def))
- if (!Sym->File->Live)
- return None;
-
- if (auto *Sym = dyn_cast<DefinedImportThunk>(Def))
- if (!Sym->WrappedSym->File->Live)
+ // Don't write dead symbols or symbols in codeview sections to the symbol
+ // table.
+ if (!Def->isLive())
+ return None;
+ if (auto *D = dyn_cast<DefinedRegular>(Def))
+ if (D->getChunk()->isCodeView())
return None;
coff_symbol16 Sym;
Modified: lld/trunk/test/COFF/pdb-import-gc.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/pdb-import-gc.yaml?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/test/COFF/pdb-import-gc.yaml (original)
+++ lld/trunk/test/COFF/pdb-import-gc.yaml Thu Jul 27 11:25:59 2017
@@ -1,7 +1,7 @@
# RUN: yaml2obj %s -o %t.obj
# RUN: lld-link %t.obj %S/Inputs/pdb-import-gc.lib -debug -entry:main \
# RUN: -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb
-# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s
+# RUN: llvm-pdbutil dump -publics -symbols %t.pdb | FileCheck %s
# This tests the case where an __imp_ chunk is discarded by linker GC. The debug
# info may refer to the __imp_ symbol still.
Added: lld/trunk/test/COFF/pdb-publics-import.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/pdb-publics-import.test?rev=309303&view=auto
==============================================================================
--- lld/trunk/test/COFF/pdb-publics-import.test (added)
+++ lld/trunk/test/COFF/pdb-publics-import.test Thu Jul 27 11:25:59 2017
@@ -0,0 +1,23 @@
+Make a DLL that exports a few functions, then make a DLL with PDBs that imports
+them. Check that the __imp_ pointer and the generated thunks appear in the
+publics stream.
+
+RUN: yaml2obj < %p/Inputs/export.yaml > %t1.obj
+RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib \
+RUN: /export:exportfn1 /export:exportfn2
+RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
+RUN: lld-link /out:%t2.exe /pdb:%t2.pdb /debug /entry:main %t2.obj %t1.lib
+RUN: llvm-pdbutil dump %t2.pdb -publics | FileCheck %s
+
+CHECK: Public Symbols
+CHECK-NEXT: ============================================================
+CHECK-NEXT: 112 | S_PUB32 [size = 20] `main`
+CHECK-NEXT: flags = function, addr = 0001:0000
+CHECK-NEXT: 64 | S_PUB32 [size = 24] `exportfn1`
+CHECK-NEXT: flags = function, addr = 0001:0016
+CHECK-NEXT: 88 | S_PUB32 [size = 24] `exportfn2`
+CHECK-NEXT: flags = function, addr = 0001:0032
+CHECK-NEXT: 32 | S_PUB32 [size = 32] `__imp_exportfn2`
+CHECK-NEXT: flags = none, addr = 0003:0072
+CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1`
+CHECK-NEXT: flags = none, addr = 0003:0064
Modified: lld/trunk/test/COFF/pdb.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/pdb.test?rev=309303&r1=309302&r2=309303&view=diff
==============================================================================
--- lld/trunk/test/COFF/pdb.test (original)
+++ lld/trunk/test/COFF/pdb.test Thu Jul 27 11:25:59 2017
@@ -7,7 +7,8 @@
# RUN: -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s
# RUN: llvm-pdbutil dump -modules -section-map -section-contribs \
-# RUN: -types -ids -type-extras -id-extras %t.pdb | FileCheck -check-prefix RAW %s
+# RUN: -publics -public-extras -types -ids -type-extras -id-extras %t.pdb \
+# RUN: | FileCheck -check-prefix RAW %s
# CHECK: MSF:
# CHECK-NEXT: SuperBlock:
@@ -171,6 +172,22 @@ RAW-NEXT: 0x1003: `C:\vs14\VC
RAW-NEXT: 0x100A: `ret42-sub.c`
RAW-NEXT: 0x1008: `D:\b\vc140.pdb`
RAW-NEXT: 0x1006: ` -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X`
+RAW: Public Symbols
+RAW-NEXT:============================================================
+RAW-NEXT: 20 | S_PUB32 [size = 20] `main`
+RAW-NEXT: flags = function, addr = 0002:0000
+RAW-NEXT: 0 | S_PUB32 [size = 20] `foo`
+RAW-NEXT: flags = function, addr = 0002:0016
+RAW-NOT: S_PUB32
+RAW-NEXT: Hash Records
+RAW-NEXT: off = 21, refcnt = 1
+RAW-NEXT: off = 1, refcnt = 1
+RAW-NEXT: Hash Buckets
+RAW-NEXT: 0x00000000
+RAW-NEXT: 0x0000000c
+RAW-NEXT: Address Map
+RAW-NEXT: off = 20
+RAW-NEXT: off = 0
RAW: Section Contributions
RAW-NEXT: ============================================================
RAW-NEXT: SC | mod = 0, 65535:1288, size = 14, data crc = 0, reloc crc = 0
More information about the llvm-commits
mailing list