summaryrefslogtreecommitdiff
path: root/lib/Object
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Object')
-rw-r--r--lib/Object/ArchiveWriter.cpp3
-rw-r--r--lib/Object/COFFImportFile.cpp144
-rw-r--r--lib/Object/COFFModuleDefinition.cpp36
-rw-r--r--lib/Object/COFFObjectFile.cpp5
4 files changed, 146 insertions, 42 deletions
diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp
index 4034f9039ddaa..b052c76d1fed4 100644
--- a/lib/Object/ArchiveWriter.cpp
+++ b/lib/Object/ArchiveWriter.cpp
@@ -318,7 +318,8 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
continue;
if (!(Symflags & object::SymbolRef::SF_Global))
continue;
- if (Symflags & object::SymbolRef::SF_Undefined)
+ if (Symflags & object::SymbolRef::SF_Undefined &&
+ !(Symflags & object::SymbolRef::SF_Indirect))
continue;
unsigned NameOffset = NameOS.tell();
diff --git a/lib/Object/COFFImportFile.cpp b/lib/Object/COFFImportFile.cpp
index 740bf94d40e08..d1f46fdfa292e 100644
--- a/lib/Object/COFFImportFile.cpp
+++ b/lib/Object/COFFImportFile.cpp
@@ -131,14 +131,14 @@ class ObjectFactory {
using u32 = support::ulittle32_t;
MachineTypes Machine;
BumpPtrAllocator Alloc;
- StringRef DLLName;
+ StringRef ImportName;
StringRef Library;
std::string ImportDescriptorSymbolName;
std::string NullThunkSymbolName;
public:
ObjectFactory(StringRef S, MachineTypes M)
- : Machine(M), DLLName(S), Library(S.drop_back(4)),
+ : Machine(M), ImportName(S), Library(S.drop_back(4)),
ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
@@ -162,14 +162,17 @@ public:
// Library Format.
NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
ImportType Type, ImportNameType NameType);
+
+ // Create a weak external file which is described in PE/COFF Aux Format 3.
+ NewArchiveMember createWeakExternal(StringRef Sym, StringRef Weak, bool Imp);
};
} // namespace
NewArchiveMember
ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
- static const uint32_t NumberOfSections = 2;
- static const uint32_t NumberOfSymbols = 7;
- static const uint32_t NumberOfRelocations = 3;
+ const uint32_t NumberOfSections = 2;
+ const uint32_t NumberOfSymbols = 7;
+ const uint32_t NumberOfRelocations = 3;
// COFF Header
coff_file_header Header{
@@ -181,7 +184,7 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
sizeof(coff_import_directory_table_entry) +
NumberOfRelocations * sizeof(coff_relocation) +
// .idata$4
- (DLLName.size() + 1)),
+ (ImportName.size() + 1)),
u32(NumberOfSymbols),
u16(0),
u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
@@ -189,7 +192,7 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
append(Buffer, Header);
// Section Header Table
- static const coff_section SectionTable[NumberOfSections] = {
+ const coff_section SectionTable[NumberOfSections] = {
{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
u32(0),
u32(0),
@@ -205,7 +208,7 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
u32(0),
u32(0),
- u32(DLLName.size() + 1),
+ u32(ImportName.size() + 1),
u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
sizeof(coff_import_directory_table_entry) +
NumberOfRelocations * sizeof(coff_relocation)),
@@ -219,12 +222,12 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
append(Buffer, SectionTable);
// .idata$2
- static const coff_import_directory_table_entry ImportDescriptor{
+ const coff_import_directory_table_entry ImportDescriptor{
u32(0), u32(0), u32(0), u32(0), u32(0),
};
append(Buffer, ImportDescriptor);
- static const coff_relocation RelocationTable[NumberOfRelocations] = {
+ const coff_relocation RelocationTable[NumberOfRelocations] = {
{u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
u16(getImgRelRelocation(Machine))},
{u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
@@ -236,9 +239,9 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
// .idata$6
auto S = Buffer.size();
- Buffer.resize(S + DLLName.size() + 1);
- memcpy(&Buffer[S], DLLName.data(), DLLName.size());
- Buffer[S + DLLName.size()] = '\0';
+ Buffer.resize(S + ImportName.size() + 1);
+ memcpy(&Buffer[S], ImportName.data(), ImportName.size());
+ Buffer[S + ImportName.size()] = '\0';
// Symbol Table
coff_symbol16 SymbolTable[NumberOfSymbols] = {
@@ -302,13 +305,13 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
NullThunkSymbolName});
StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
- return {MemoryBufferRef(F, DLLName)};
+ return {MemoryBufferRef(F, ImportName)};
}
NewArchiveMember
ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
- static const uint32_t NumberOfSections = 1;
- static const uint32_t NumberOfSymbols = 1;
+ const uint32_t NumberOfSections = 1;
+ const uint32_t NumberOfSymbols = 1;
// COFF Header
coff_file_header Header{
@@ -325,7 +328,7 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
append(Buffer, Header);
// Section Header Table
- static const coff_section SectionTable[NumberOfSections] = {
+ const coff_section SectionTable[NumberOfSections] = {
{{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
u32(0),
u32(0),
@@ -342,7 +345,7 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
append(Buffer, SectionTable);
// .idata$3
- static const coff_import_directory_table_entry ImportDescriptor{
+ const coff_import_directory_table_entry ImportDescriptor{
u32(0), u32(0), u32(0), u32(0), u32(0),
};
append(Buffer, ImportDescriptor);
@@ -363,12 +366,12 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
writeStringTable(Buffer, {NullImportDescriptorSymbolName});
StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
- return {MemoryBufferRef(F, DLLName)};
+ return {MemoryBufferRef(F, ImportName)};
}
NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
- static const uint32_t NumberOfSections = 2;
- static const uint32_t NumberOfSymbols = 1;
+ const uint32_t NumberOfSections = 2;
+ const uint32_t NumberOfSymbols = 1;
uint32_t VASize = is32bit(Machine) ? 4 : 8;
// COFF Header
@@ -388,7 +391,7 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
append(Buffer, Header);
// Section Header Table
- static const coff_section SectionTable[NumberOfSections] = {
+ const coff_section SectionTable[NumberOfSections] = {
{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
u32(0),
u32(0),
@@ -445,14 +448,14 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
writeStringTable(Buffer, {NullThunkSymbolName});
StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
- return {MemoryBufferRef{F, DLLName}};
+ return {MemoryBufferRef{F, ImportName}};
}
NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
uint16_t Ordinal,
ImportType ImportType,
ImportNameType NameType) {
- size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
+ size_t ImpSize = ImportName.size() + Sym.size() + 2; // +2 for NULs
size_t Size = sizeof(coff_import_header) + ImpSize;
char *Buf = Alloc.Allocate<char>(Size);
memset(Buf, 0, Size);
@@ -471,17 +474,96 @@ NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
// Write symbol name and DLL name.
memcpy(P, Sym.data(), Sym.size());
P += Sym.size() + 1;
- memcpy(P, DLLName.data(), DLLName.size());
+ memcpy(P, ImportName.data(), ImportName.size());
- return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
+ return {MemoryBufferRef(StringRef(Buf, Size), ImportName)};
}
-std::error_code writeImportLibrary(StringRef DLLName, StringRef Path,
+NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
+ StringRef Weak, bool Imp) {
+ std::vector<uint8_t> Buffer;
+ const uint32_t NumberOfSections = 1;
+ const uint32_t NumberOfSymbols = 5;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(0),
+ u16(NumberOfSections),
+ u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))),
+ u32(NumberOfSymbols),
+ u16(0),
+ u16(0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'},
+ u32(0),
+ u32(0),
+ u32(0),
+ u32(0),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)}};
+ append(Buffer, SectionTable);
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}},
+ u32(0),
+ u16(0xFFFF),
+ u16(0),
+ IMAGE_SYM_CLASS_STATIC,
+ 0},
+ {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}},
+ u32(0),
+ u16(0xFFFF),
+ u16(0),
+ IMAGE_SYM_CLASS_STATIC,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_WEAK_EXTERNAL,
+ 1},
+ {{{2, 0, 0, 0, 3, 0, 0, 0}}, u32(0), u16(0), u16(0), uint8_t(0), 0},
+ };
+ SymbolTable[2].Name.Offset.Offset = sizeof(uint32_t);
+
+ //__imp_ String Table
+ if (Imp) {
+ SymbolTable[3].Name.Offset.Offset = sizeof(uint32_t) + Sym.size() + 7;
+ writeStringTable(Buffer, {std::string("__imp_").append(Sym),
+ std::string("__imp_").append(Weak)});
+ } else {
+ SymbolTable[3].Name.Offset.Offset = sizeof(uint32_t) + Sym.size() + 1;
+ writeStringTable(Buffer, {Sym, Weak});
+ }
+ append(Buffer, SymbolTable);
+
+ // Copied here so we can still use writeStringTable
+ char *Buf = Alloc.Allocate<char>(Buffer.size());
+ memcpy(Buf, Buffer.data(), Buffer.size());
+ return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
+}
+
+std::error_code writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
MachineTypes Machine) {
std::vector<NewArchiveMember> Members;
- ObjectFactory OF(llvm::sys::path::filename(DLLName), Machine);
+ ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
std::vector<uint8_t> ImportDescriptor;
Members.push_back(OF.createImportDescriptor(ImportDescriptor));
@@ -496,6 +578,12 @@ std::error_code writeImportLibrary(StringRef DLLName, StringRef Path,
if (E.Private)
continue;
+ if (E.isWeak()) {
+ Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, false));
+ Members.push_back(OF.createWeakExternal(E.Name, E.ExtName, true));
+ continue;
+ }
+
ImportType ImportType = IMPORT_CODE;
if (E.Data)
ImportType = IMPORT_DATA;
diff --git a/lib/Object/COFFModuleDefinition.cpp b/lib/Object/COFFModuleDefinition.cpp
index 0d69cb6b709c8..ed9140d1fe08b 100644
--- a/lib/Object/COFFModuleDefinition.cpp
+++ b/lib/Object/COFFModuleDefinition.cpp
@@ -22,6 +22,7 @@
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm::COFF;
@@ -55,8 +56,10 @@ struct Token {
StringRef Value;
};
-static bool isDecorated(StringRef Sym) {
- return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
+static bool isDecorated(StringRef Sym, bool MingwDef) {
+ // mingw does not prepend "_".
+ return (!MingwDef && Sym.startswith("_")) || Sym.startswith("@") ||
+ Sym.startswith("?");
}
static Error createError(const Twine &Err) {
@@ -83,6 +86,9 @@ public:
}
case '=':
Buf = Buf.drop_front();
+ // GNU dlltool accepts both = and ==.
+ if (Buf.startswith("="))
+ Buf = Buf.drop_front();
return Token(Equal, "=");
case ',':
Buf = Buf.drop_front();
@@ -120,7 +126,8 @@ private:
class Parser {
public:
- explicit Parser(StringRef S, MachineTypes M) : Lex(S), Machine(M) {}
+ explicit Parser(StringRef S, MachineTypes M, bool B)
+ : Lex(S), Machine(M), MingwDef(B) {}
Expected<COFFModuleDefinition> parse() {
do {
@@ -181,14 +188,17 @@ private:
std::string Name;
if (Error Err = parseName(&Name, &Info.ImageBase))
return Err;
- // Append the appropriate file extension if not already present.
- StringRef Ext = IsDll ? ".dll" : ".exe";
- if (!StringRef(Name).endswith_lower(Ext))
- Name += Ext;
+
+ Info.ImportName = Name;
// Set the output file, but don't override /out if it was already passed.
- if (Info.OutputFile.empty())
+ if (Info.OutputFile.empty()) {
Info.OutputFile = Name;
+ // Append the appropriate file extension if not already present.
+ if (!sys::path::has_extension(Name))
+ Info.OutputFile += IsDll ? ".dll" : ".exe";
+ }
+
return Error::success();
}
case KwVersion:
@@ -213,9 +223,9 @@ private:
}
if (Machine == IMAGE_FILE_MACHINE_I386) {
- if (!isDecorated(E.Name))
+ if (!isDecorated(E.Name, MingwDef))
E.Name = (std::string("_").append(E.Name));
- if (!E.ExtName.empty() && !isDecorated(E.ExtName))
+ if (!E.ExtName.empty() && !isDecorated(E.ExtName, MingwDef))
E.ExtName = (std::string("_").append(E.ExtName));
}
@@ -308,11 +318,13 @@ private:
std::vector<Token> Stack;
MachineTypes Machine;
COFFModuleDefinition Info;
+ bool MingwDef;
};
Expected<COFFModuleDefinition> parseCOFFModuleDefinition(MemoryBufferRef MB,
- MachineTypes Machine) {
- return Parser(MB.getBuffer(), Machine).parse();
+ MachineTypes Machine,
+ bool MingwDef) {
+ return Parser(MB.getBuffer(), Machine, MingwDef).parse();
}
} // namespace object
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 1e9b0c5b04546..0a2053477caf1 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/lib/Object/COFFObjectFile.cpp
@@ -227,8 +227,11 @@ uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
if (Symb.isExternal() || Symb.isWeakExternal())
Result |= SymbolRef::SF_Global;
- if (Symb.isWeakExternal())
+ if (Symb.isWeakExternal()) {
Result |= SymbolRef::SF_Weak;
+ // We use indirect to allow the archiver to write weak externs
+ Result |= SymbolRef::SF_Indirect;
+ }
if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
Result |= SymbolRef::SF_Absolute;