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:
parent
05834cd2ad
commit
6bf638e688
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue