aboutsummaryrefslogtreecommitdiffstats
path: root/COFF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-01-13 20:06:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-01-13 20:06:04 +0000
commitb289257c7f3ed78b7d3971c596d7c60a9050c705 (patch)
treed6b57e29a5a86347a020d6f0cae76cc2d0f3bf8d /COFF
parentfba2c04f31e119eacf142fcbbaabd5a9e63a39ed (diff)
downloadsrc-b289257c7f3ed78b7d3971c596d7c60a9050c705.tar.gz
src-b289257c7f3ed78b7d3971c596d7c60a9050c705.zip
Vendor import of lld trunk r257626:vendor/lld/lld-trunk-r257626
Notes
Notes: svn path=/vendor/lld/dist/; revision=293846 svn path=/vendor/lld/lld-trunk-r257626/; revision=293847; tag=vendor/lld/lld-trunk-r257626
Diffstat (limited to 'COFF')
-rw-r--r--COFF/CMakeLists.txt2
-rw-r--r--COFF/Chunks.cpp2
-rw-r--r--COFF/Chunks.h4
-rw-r--r--COFF/Config.h7
-rw-r--r--COFF/DLL.cpp21
-rw-r--r--COFF/Driver.cpp2
-rw-r--r--COFF/DriverUtils.cpp31
-rw-r--r--COFF/InputFiles.cpp1
-rw-r--r--COFF/Writer.cpp17
9 files changed, 67 insertions, 20 deletions
diff --git a/COFF/CMakeLists.txt b/COFF/CMakeLists.txt
index 78dc34eff96e..3f31ba9ba1fb 100644
--- a/COFF/CMakeLists.txt
+++ b/COFF/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(COFFOptionsTableGen)
-add_llvm_library(lldCOFF
+add_lld_library(lldCOFF
Chunks.cpp
DLL.cpp
Driver.cpp
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
index 50bf55be269b..f9f768d69866 100644
--- a/COFF/Chunks.cpp
+++ b/COFF/Chunks.cpp
@@ -310,7 +310,7 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const {
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
// Block header consists of 4 byte page RVA and 4 byte block size.
// Each entry is 2 byte. Last entry may be padding.
- Data.resize(RoundUpToAlignment((End - Begin) * 2 + 8, 4));
+ Data.resize(align((End - Begin) * 2 + 8, 4));
uint8_t *P = Data.data();
write32le(P, Page);
write32le(P + 4, Data.size());
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index 60b8e76f8230..274135516eb9 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -326,6 +326,10 @@ public:
uint8_t Type;
};
+inline uint64_t align(uint64_t Value, uint64_t Align) {
+ return llvm::RoundUpToAlignment(Value, Align);
+}
+
} // namespace coff
} // namespace lld
diff --git a/COFF/Config.h b/COFF/Config.h
index 409ede648636..9cfccadba5fa 100644
--- a/COFF/Config.h
+++ b/COFF/Config.h
@@ -25,6 +25,7 @@ using llvm::COFF::WindowsSubsystem;
using llvm::StringRef;
class DefinedAbsolute;
class DefinedRelative;
+class StringChunk;
class Undefined;
// Short aliases.
@@ -42,6 +43,12 @@ struct Export {
bool Data = false;
bool Private = false;
+ // If an export is a form of /export:foo=dllname.bar, that means
+ // that foo should be exported as an alias to bar in the DLL.
+ // ForwardTo is set to "dllname.bar" part. Usually empty.
+ StringRef ForwardTo;
+ StringChunk *ForwardChunk = nullptr;
+
// True if this /export option was in .drectves section.
bool Directives = false;
StringRef SymbolName;
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp
index 40ca5cf61dc2..8f3383d75c7b 100644
--- a/COFF/DLL.cpp
+++ b/COFF/DLL.cpp
@@ -45,7 +45,7 @@ public:
size_t getSize() const override {
// Starts with 2 byte Hint field, followed by a null-terminated string,
// ends with 0 or 1 byte padding.
- return RoundUpToAlignment(Name.size() + 3, 2);
+ return align(Name.size() + 3, 2);
}
void writeTo(uint8_t *Buf) const override {
@@ -320,8 +320,12 @@ public:
void writeTo(uint8_t *Buf) const override {
for (Export &E : Config->Exports) {
- auto *D = cast<Defined>(E.Sym->repl());
- write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
+ uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;
+ if (E.ForwardChunk) {
+ write32le(P, E.ForwardChunk->getRVA());
+ } else {
+ write32le(P, cast<Defined>(E.Sym->repl())->getRVA());
+ }
}
}
@@ -539,6 +543,15 @@ EdataContents::EdataContents() {
for (Export &E : Config->Exports)
if (!E.Noname)
Names.push_back(new StringChunk(E.ExportName));
+
+ std::vector<Chunk *> Forwards;
+ for (Export &E : Config->Exports) {
+ if (E.ForwardTo.empty())
+ continue;
+ E.ForwardChunk = new StringChunk(E.ForwardTo);
+ Forwards.push_back(E.ForwardChunk);
+ }
+
auto *NameTab = new NamePointersChunk(Names);
auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
@@ -550,6 +563,8 @@ EdataContents::EdataContents() {
Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
for (Chunk *C : Names)
Chunks.push_back(std::unique_ptr<Chunk>(C));
+ for (Chunk *C : Forwards)
+ Chunks.push_back(std::unique_ptr<Chunk>(C));
}
} // namespace coff
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index f528dafd9857..4cacf0ff552a 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -586,6 +586,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Windows specific -- Make sure we resolve all dllexported symbols.
for (Export &E : Config->Exports) {
+ if (!E.ForwardTo.empty())
+ continue;
E.Sym = addUndefined(E.Name);
if (!E.Directives)
Symtab.mangleMaybe(E.Sym);
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
index 391a8ab66420..014fee7fefd7 100644
--- a/COFF/DriverUtils.cpp
+++ b/COFF/DriverUtils.cpp
@@ -321,7 +321,8 @@ void createSideBySideManifest() {
}
// Parse a string in the form of
-// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]".
+// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]"
+// or "<name>=<dllname>.<name>".
// Used for parsing /export arguments.
Export parseExport(StringRef Arg) {
Export E;
@@ -329,12 +330,25 @@ Export parseExport(StringRef Arg) {
std::tie(E.Name, Rest) = Arg.split(",");
if (E.Name.empty())
goto err;
+
if (E.Name.find('=') != StringRef::npos) {
- std::tie(E.ExtName, E.Name) = E.Name.split("=");
+ StringRef X, Y;
+ std::tie(X, Y) = E.Name.split("=");
+
+ // If "<name>=<dllname>.<name>".
+ if (Y.find(".") != StringRef::npos) {
+ E.Name = X;
+ E.ForwardTo = Y;
+ return E;
+ }
+
+ E.ExtName = X;
+ E.Name = Y;
if (E.Name.empty())
goto err;
}
+ // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]"
while (!Rest.empty()) {
StringRef Tok;
std::tie(Tok, Rest) = Rest.split(",");
@@ -388,15 +402,22 @@ void fixupExports() {
}
for (Export &E : Config->Exports) {
- if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
+ if (!E.ForwardTo.empty()) {
+ E.SymbolName = E.Name;
+ } else if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
E.SymbolName = U->getName();
} else {
E.SymbolName = E.Sym->getName();
}
}
- for (Export &E : Config->Exports)
- E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+ for (Export &E : Config->Exports) {
+ if (!E.ForwardTo.empty()) {
+ E.ExportName = undecorate(E.Name);
+ } else {
+ E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+ }
+ }
// Uniquefy by name.
std::map<StringRef, Export *> Map;
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
index 23fc2a085122..23af1e89c34d 100644
--- a/COFF/InputFiles.cpp
+++ b/COFF/InputFiles.cpp
@@ -23,7 +23,6 @@
using namespace llvm::COFF;
using namespace llvm::object;
using namespace llvm::support::endian;
-using llvm::RoundUpToAlignment;
using llvm::Triple;
using llvm::support::ulittle32_t;
using llvm::sys::fs::file_magic;
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
index a74b316b87a4..5575c8d6b320 100644
--- a/COFF/Writer.cpp
+++ b/COFF/Writer.cpp
@@ -163,13 +163,13 @@ void OutputSection::addChunk(Chunk *C) {
Chunks.push_back(C);
C->setOutputSection(this);
uint64_t Off = Header.VirtualSize;
- Off = RoundUpToAlignment(Off, C->getAlign());
+ Off = align(Off, C->getAlign());
C->setRVA(Off);
C->setOutputSectionOff(Off);
Off += C->getSize();
Header.VirtualSize = Off;
if (C->hasData())
- Header.SizeOfRawData = RoundUpToAlignment(Off, SectorSize);
+ Header.SizeOfRawData = align(Off, SectorSize);
}
void OutputSection::addPermissions(uint32_t C) {
@@ -448,15 +448,14 @@ void Writer::createSymbolAndStringTable() {
OutputSection *LastSection = OutputSections.back();
// We position the symbol table to be adjacent to the end of the last section.
uint64_t FileOff =
- LastSection->getFileOff() +
- RoundUpToAlignment(LastSection->getRawSize(), SectorSize);
+ LastSection->getFileOff() + align(LastSection->getRawSize(), SectorSize);
if (!OutputSymtab.empty()) {
PointerToSymbolTable = FileOff;
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
}
if (!Strtab.empty())
FileOff += Strtab.size() + 4;
- FileSize = RoundUpToAlignment(FileOff, SectorSize);
+ FileSize = align(FileOff, SectorSize);
}
// Visits all sections to assign incremental, non-overlapping RVAs and
@@ -467,7 +466,7 @@ void Writer::assignAddresses() {
sizeof(coff_section) * OutputSections.size();
SizeOfHeaders +=
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
- SizeOfHeaders = RoundUpToAlignment(SizeOfHeaders, SectorSize);
+ SizeOfHeaders = align(SizeOfHeaders, SectorSize);
uint64_t RVA = 0x1000; // The first page is kept unmapped.
FileSize = SizeOfHeaders;
// Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
@@ -481,10 +480,10 @@ void Writer::assignAddresses() {
addBaserels(Sec);
Sec->setRVA(RVA);
Sec->setFileOffset(FileSize);
- RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
- FileSize += RoundUpToAlignment(Sec->getRawSize(), SectorSize);
+ RVA += align(Sec->getVirtualSize(), PageSize);
+ FileSize += align(Sec->getRawSize(), SectorSize);
}
- SizeOfImage = SizeOfHeaders + RoundUpToAlignment(RVA - 0x1000, PageSize);
+ SizeOfImage = SizeOfHeaders + align(RVA - 0x1000, PageSize);
}
template <typename PEHeaderTy> void Writer::writeHeader() {