COFF: Simplify and rename findMangle. NFC.

Occasionally we have to resolve an undefined symbol to its
mangled symbol. Previously, we did that on calling side of
findMangle by explicitly updating SymbolBody.
In this patch, mangled symbols are handled as weak aliases
for undefined symbols.

llvm-svn: 241213
This commit is contained in:
Rui Ueyama 2015-07-02 00:04:14 +00:00
parent 05834cd2ad
commit 6bf638e688
7 changed files with 51 additions and 75 deletions

View File

@ -22,13 +22,13 @@ namespace coff {
using llvm::COFF::WindowsSubsystem;
using llvm::StringRef;
struct Symbol;
class Undefined;
// Represents an /export option.
struct Export {
StringRef Name;
StringRef ExtName;
Symbol *Sym = nullptr;
Undefined *Sym = nullptr;
uint16_t Ordinal = 0;
bool Noname = false;
bool Data = false;
@ -42,7 +42,7 @@ struct Configuration {
llvm::COFF::MachineTypes MachineType = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
bool Verbose = false;
WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
StringRef EntryName;
Undefined *Entry = nullptr;
bool NoEntry = false;
std::string OutputFile;
bool DoGC = true;

View File

@ -420,7 +420,7 @@ public:
void writeTo(uint8_t *Buf) override {
for (Export &E : Config->Exports) {
auto *D = cast<Defined>(E.Sym->Body);
auto *D = cast<Defined>(E.Sym->getReplacement());
write32le(Buf + FileOff + E.Ordinal * 4, D->getRVA());
}
}

View File

@ -202,9 +202,10 @@ void LinkerDriver::addLibSearchPaths() {
}
}
void LinkerDriver::addUndefined(StringRef Sym) {
Symtab.addUndefined(Sym);
Config->GCRoots.insert(Sym);
Undefined *LinkerDriver::addUndefined(StringRef Name) {
Undefined *U = Symtab.addUndefined(Name);
Config->GCRoots.insert(Name);
return U;
}
// Windows specific -- find default entry point name.
@ -286,10 +287,8 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
Config->Force = true;
// Handle /entry
if (auto *Arg = Args.getLastArg(OPT_entry)) {
Config->EntryName = Arg->getValue();
addUndefined(Config->EntryName);
}
if (auto *Arg = Args.getLastArg(OPT_entry))
Config->Entry = addUndefined(Arg->getValue());
// Handle /noentry
if (Args.hasArg(OPT_noentry)) {
@ -304,10 +303,8 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (Args.hasArg(OPT_dll)) {
Config->DLL = true;
Config->ManifestID = 2;
if (Config->EntryName.empty() && !Config->NoEntry) {
Config->EntryName = "_DllMainCRTStartup";
addUndefined("_DllMainCRTStartup");
}
if (Config->Entry == nullptr && !Config->NoEntry)
Config->Entry = addUndefined("_DllMainCRTStartup");
}
// Handle /fixed
@ -544,14 +541,13 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Windows specific -- If entry point name is not given, we need to
// infer that from user-defined entry name.
if (Config->EntryName.empty() && !Config->NoEntry) {
if (Config->Entry == nullptr && !Config->NoEntry) {
StringRef S = findDefaultEntry();
if (S.empty()) {
llvm::errs() << "entry point must be defined\n";
return false;
}
Config->EntryName = S;
addUndefined(S);
Config->Entry = addUndefined(S);
}
// Resolve auxiliary symbols until converge.
@ -561,9 +557,16 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
for (;;) {
size_t Ver = Symtab.getVersion();
// Windows specific -- if entry point is not found,
// search for its mangled names.
if (Config->Entry)
Symtab.mangleMaybe(Config->Entry);
// Windows specific -- Make sure we resolve all dllexported symbols.
for (Export &E : Config->Exports)
addUndefined(E.Name);
for (Export &E : Config->Exports) {
E.Sym = addUndefined(E.Name);
Symtab.mangleMaybe(E.Sym);
}
// Add weak aliases. Weak aliases is a mechanism to give remaining
// undefined symbols final chance to be resolved successfully.
@ -585,30 +588,6 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
break;
}
// Windows specific -- if entry point is not found,
// search for its mangled names.
if (!Config->EntryName.empty() && !Symtab.find(Config->EntryName)) {
StringRef Name;
Symbol *Sym;
std::tie(Name, Sym) = Symtab.findMangled(Config->EntryName);
if (Sym)
Symtab.rename(Config->EntryName, Name);
}
// Windows specific -- resolve dllexported symbols.
for (Export &E : Config->Exports) {
StringRef Name;
Symbol *Sym;
std::tie(Name, Sym) = Symtab.findMangled(E.Name);
if (!Sym) {
llvm::errs() << "exported symbol is not defined: " << E.Name << "\n";
return false;
}
if (E.Name != Name)
Symtab.rename(E.Name, Name);
E.Sym = Sym;
}
// Make sure we have resolved all symbols.
if (Symtab.reportRemainingUndefines())
return false;

View File

@ -92,7 +92,7 @@ private:
std::vector<StringRef> SearchPaths;
std::set<std::string> VisitedFiles;
void addUndefined(StringRef Sym);
Undefined *addUndefined(StringRef Sym);
// Windows specific -- "main" is not the only main function in Windows.
// You can choose one from these four -- {w,}{WinMain,main}.

View File

@ -25,8 +25,6 @@ namespace coff {
SymbolTable::SymbolTable() {
addSymbol(new (Alloc) DefinedAbsolute("__ImageBase", Config->ImageBase));
if (!Config->EntryName.empty())
addSymbol(new (Alloc) Undefined(Config->EntryName));
}
void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
@ -123,9 +121,11 @@ bool SymbolTable::reportRemainingUndefines() {
continue;
StringRef Name = Undef->getName();
// The weak alias may have been resovled, so check for that.
if (auto *D = dyn_cast_or_null<Defined>(Undef->WeakAlias)) {
Sym->Body = D;
continue;
if (SymbolBody *Alias = Undef->WeakAlias) {
if (auto *D = dyn_cast<Defined>(Alias->getReplacement())) {
Sym->Body = D;
continue;
}
}
// If we can resolve a symbol by removing __imp_ prefix, do that.
// This odd rule is for compatibility with MSVC linker.
@ -245,34 +245,30 @@ Symbol *SymbolTable::findSymbol(StringRef Name) {
return It->second;
}
// Find a given symbol or its mangled symbol.
std::pair<StringRef, Symbol *> SymbolTable::findMangled(StringRef S) {
auto It = Symtab.find(S);
if (It != Symtab.end()) {
Symbol *Sym = It->second;
if (isa<Defined>(Sym->Body))
return std::make_pair(S, Sym);
}
void SymbolTable::mangleMaybe(Undefined *U) {
if (U->WeakAlias)
return;
if (!isa<Undefined>(U->getReplacement()))
return;
// In Microsoft ABI, a non-member function name is mangled this way.
std::string Prefix = ("?" + S + "@@Y").str();
std::string Prefix = ("?" + U->getName() + "@@Y").str();
for (auto I : Symtab) {
StringRef Name = I.first;
Symbol *Sym = I.second;
Symbol *New = I.second;
if (!Name.startswith(Prefix))
continue;
if (auto *B = dyn_cast<Lazy>(Sym->Body)) {
addMemberFile(B);
run();
}
if (isa<Defined>(Sym->Body))
return std::make_pair(Name, Sym);
U->WeakAlias = New->Body;
if (auto *L = dyn_cast<Lazy>(New->Body))
addMemberFile(L);
return;
}
return std::make_pair(S, nullptr);
}
std::error_code SymbolTable::addUndefined(StringRef Name) {
return addSymbol(new (Alloc) Undefined(Name));
Undefined *SymbolTable::addUndefined(StringRef Name) {
auto *U = new (Alloc) Undefined(Name);
addSymbol(U);
return U;
}
// Resolve To, and make From an alias to To.

View File

@ -61,10 +61,11 @@ public:
Defined *find(StringRef Name);
Symbol *findSymbol(StringRef Name);
// Find a symbol assuming that Name is a function name.
// Not only a given string but its mangled names (in MSVC C++ manner)
// will be searched.
std::pair<StringRef, Symbol *> findMangled(StringRef Name);
// Occasionally we have to resolve an undefined symbol to its
// mangled symbol. This function tries to find a mangled name
// for U from the symbol table, and if found, set the symbol as
// a weak alias for U.
void mangleMaybe(Undefined *U);
// Print a layout map to OS.
void printMap(llvm::raw_ostream &OS);
@ -82,7 +83,7 @@ public:
std::vector<ObjectFile *> ObjectFiles;
// Creates an Undefined symbol for a given name.
std::error_code addUndefined(StringRef Name);
Undefined *addUndefined(StringRef Name);
// Rename From -> To in the symbol table.
std::error_code rename(StringRef From, StringRef To);

View File

@ -348,7 +348,7 @@ void Writer::writeHeader() {
PE->SizeOfImage = SizeOfImage;
PE->SizeOfHeaders = SizeOfHeaders;
if (!Config->NoEntry) {
Defined *Entry = cast<Defined>(Symtab->find(Config->EntryName));
Defined *Entry = cast<Defined>(Config->Entry->getReplacement());
PE->AddressOfEntryPoint = Entry->getRVA();
}
PE->SizeOfStackReserve = Config->StackReserve;