MarkLive.cpp
ModuleDef.cpp
PDB.cpp
+ Strings.cpp
SymbolTable.cpp
Symbols.cpp
Writer.cpp
continue;
}
if (Config->Machine != MT)
- fatal(File->getShortName() + ": machine type " + machineToStr(MT) +
+ fatal(toString(File.get()) + ": machine type " + machineToStr(MT) +
" conflicts with " + machineToStr(Config->Machine));
}
if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
int InputFile::NextIndex = 0;
llvm::LLVMContext BitcodeFile::Context;
-
-// Returns the last element of a path, which is supposed to be a filename.
-static StringRef getBasename(StringRef Path) {
- size_t Pos = Path.find_last_of("\\/");
- if (Pos == StringRef::npos)
- return Path;
- return Path.substr(Pos + 1);
-}
-
-// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
-std::string InputFile::getShortName() {
- if (ParentName == "")
- return getName().lower();
- std::string Res = (getBasename(ParentName) + "(" +
- getBasename(getName()) + ")").str();
- return StringRef(Res).lower();
-}
+std::mutex BitcodeFile::Mu;
ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
void ArchiveFile::parse() {
// Parse a MemoryBufferRef as an archive file.
- File = check(Archive::create(MB), getShortName());
+ File = check(Archive::create(MB), toString(this));
// Allocate a buffer for Lazy objects.
size_t NumSyms = File->getNumberOfSymbols();
for (auto &Child : File->children(Err))
Seen[Child.getChildOffset()].clear();
if (Err)
- fatal(Err, getShortName());
+ fatal(Err, toString(this));
}
// Returns a buffer pointing to a member file containing a given symbol.
void ObjectFile::parse() {
// Parse a memory buffer as a COFF file.
- std::unique_ptr<Binary> Bin =
- check(createBinary(MB), getShortName());
+ std::unique_ptr<Binary> Bin = check(createBinary(MB), toString(this));
if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {
Bin.release();
COFFObj.reset(Obj);
} else {
- fatal(getShortName() + " is not a COFF file");
+ fatal(toString(this) + " is not a COFF file");
}
// Read section and symbol tables.
for (uint32_t I = 0; I < NumSymbols; ++I) {
// Get a COFFSymbolRef object.
COFFSymbolRef Sym =
- check(COFFObj->getSymbol(I), "broken object file: " + getShortName());
+ check(COFFObj->getSymbol(I), "broken object file: " + toString(this));
const void *AuxP = nullptr;
if (Sym.getNumberOfAuxSymbols())
// Reserved sections numbers don't have contents.
if (llvm::COFF::isReservedSectionNumber(SectionNumber))
- fatal("broken object file: " + getShortName());
+ fatal("broken object file: " + toString(this));
// This symbol references a section which is not present in the section
// header.
if ((uint32_t)SectionNumber >= SparseChunks.size())
- fatal("broken object file: " + getShortName());
+ fatal("broken object file: " + toString(this));
// Nothing else to do without a section chunk.
auto *SC = cast_or_null<SectionChunk>(SparseChunks[SectionNumber]);
}
}
-std::mutex BitcodeFile::Mu;
+// Returns the last element of a path, which is supposed to be a filename.
+static StringRef getBasename(StringRef Path) {
+ size_t Pos = Path.find_last_of("\\/");
+ if (Pos == StringRef::npos)
+ return Path;
+ return Path.substr(Pos + 1);
+}
+
+// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
+std::string toString(InputFile *File) {
+ if (!File)
+ return "(internal)";
+ if (File->ParentName.empty())
+ return File->getName().lower();
+
+ std::string Res =
+ (getBasename(File->ParentName) + "(" + getBasename(File->getName()) + ")")
+ .str();
+ return StringRef(Res).lower();
+}
} // namespace coff
} // namespace lld
// Returns the CPU type this file was compiled to.
virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }
- // Returns a short, human-friendly filename. If this is a member of
- // an archive file, a returned value includes parent's filename.
- // Used for logging or debugging.
- std::string getShortName();
-
- // Sets a parent filename if this file is created from an archive.
- void setParentName(StringRef N) { ParentName = N; }
+ // An archive file name if this file is created from an archive.
+ StringRef ParentName;
// Returns .drectve section contents if exist.
StringRef getDirectives() { return StringRef(Directives).trim(); }
private:
const Kind FileKind;
- StringRef ParentName;
};
// .lib or .a file.
static std::mutex Mu;
};
+std::string toString(InputFile *File);
+
} // namespace coff
} // namespace lld
--- /dev/null
+//===- Strings.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Strings.h"
+
+#if defined(_MSC_VER)
+#include <DbgHelp.h>
+#include <Windows.h>
+#pragma comment(lib, "dbghelp.lib")
+#endif
+
+using namespace lld;
+using namespace lld::coff;
+using namespace llvm;
+
+Optional<std::string> coff::demangle(StringRef S) {
+#if defined(_MSC_VER)
+ char Buf[4096];
+ if (S.startswith("?"))
+ if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0))
+ return std::string(Buf, Len);
+#endif
+ return None;
+}
--- /dev/null
+//===- Strings.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COFF_STRINGS_H
+#define LLD_COFF_STRINGS_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace lld {
+namespace coff {
+llvm::Optional<std::string> demangle(llvm::StringRef S);
+}
+}
+
+#endif
for (std::future<ArchiveFile *> &Future : ArchiveQueue) {
ArchiveFile *File = Future.get();
if (Config->Verbose)
- llvm::outs() << "Reading " << File->getShortName() << "\n";
+ llvm::outs() << "Reading " << toString(File) << "\n";
for (Lazy &Sym : File->getLazySymbols())
addLazy(&Sym, &LazySyms);
}
for (size_t I = 0; I < ObjectQueue.size(); ++I) {
InputFile *File = ObjectQueue[I].get();
if (Config->Verbose)
- llvm::outs() << "Reading " << File->getShortName() << "\n";
+ llvm::outs() << "Reading " << toString(File) << "\n";
// Adding symbols may add more files to ObjectQueue
// (but not to ArchiveQueue).
for (SymbolBody *Sym : File->getSymbols())
if (!S.empty()) {
Directives.push_back(S);
if (Config->Verbose)
- llvm::outs() << "Directives: " << File->getShortName()
- << ": " << S << "\n";
+ llvm::outs() << "Directives: " << toString(File) << ": " << S << "\n";
}
}
ObjectQueue.clear();
if (!isa<ArchiveFile>(File.get()))
for (SymbolBody *Sym : File->getSymbols())
if (Undefs.count(Sym->repl()))
- llvm::errs() << File->getShortName() << ": undefined symbol: "
- << Sym->getName() << "\n";
+ llvm::errs() << toString(File.get())
+ << ": undefined symbol: " << Sym->getName() << "\n";
if (!Config->Force)
fatal("link failed");
}
// equivalent (conflicting), or more preferable, respectively.
int Comp = Existing->compare(New);
if (Comp == 0)
- fatal("duplicate symbol: " + Existing->getDebugName() + " and " +
- New->getDebugName());
+ fatal("duplicate symbol: " + toString(*Existing) + " in " +
+ toString(Existing->getFile()) + " and in " +
+ toString(New->getFile()));
if (Comp < 0)
Sym->Body = New;
}
if (!File)
return;
if (Config->Verbose)
- llvm::outs() << "Loaded " << File->getShortName() << " for "
+ llvm::outs() << "Loaded " << toString(File.get()) << " for "
<< Body->getName() << "\n";
addFile(std::move(File));
}
void SymbolTable::printMap(llvm::raw_ostream &OS) {
for (ObjectFile *File : ObjectFiles) {
- OS << File->getShortName() << ":\n";
+ OS << toString(File) << ":\n";
for (SymbolBody *Body : File->getSymbols())
if (auto *R = dyn_cast<DefinedRegular>(Body))
if (R->getChunk()->isLive())
//
//===----------------------------------------------------------------------===//
+#include "Symbols.h"
#include "Error.h"
#include "InputFiles.h"
-#include "Symbols.h"
+#include "Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
using namespace llvm::object;
using llvm::sys::fs::identify_magic;
using llvm::sys::fs::file_magic;
return Name;
}
+InputFile *SymbolBody::getFile() {
+ if (auto *Sym = dyn_cast<DefinedCOFF>(this))
+ return Sym->File;
+ if (auto *Sym = dyn_cast<DefinedBitcode>(this))
+ return Sym->File;
+ if (auto *Sym = dyn_cast<Lazy>(this))
+ return Sym->File;
+ return nullptr;
+}
+
// Returns 1, 0 or -1 if this symbol should take precedence
// over the Other, tie or lose, respectively.
int SymbolBody::compare(SymbolBody *Other) {
llvm_unreachable("unknown symbol kind");
}
-std::string SymbolBody::getDebugName() {
- std::string N = getName().str();
- if (auto *D = dyn_cast<DefinedCOFF>(this)) {
- N += " ";
- N += D->File->getShortName();
- } else if (auto *D = dyn_cast<DefinedBitcode>(this)) {
- N += " ";
- N += D->File->getShortName();
- }
- return N;
-}
-
COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize();
if (SymSize == sizeof(coff_symbol16))
else
fatal("unknown file type: " + File->getName());
- Obj->setParentName(File->getName());
+ Obj->ParentName = File->getName();
return Obj;
}
return nullptr;
}
+// Returns a symbol name for an error message.
+std::string toString(SymbolBody &B) {
+ if (Optional<std::string> S = demangle(B.getName()))
+ return ("\"" + *S + "\" (" + B.getName() + ")").str();
+ return B.getName();
+}
+
} // namespace coff
} // namespace lld
// Returns the symbol name.
StringRef getName();
+ // Returns the file from which this symbol was created.
+ InputFile *getFile();
+
// A SymbolBody has a backreference to a Symbol. Originally they are
// doubly-linked. A backreference will never change. But the pointer
// in the Symbol may be mutated by the resolver. If you have a
// they are duplicate (conflicting) symbols.
int compare(SymbolBody *Other);
- // Returns a name of this symbol including source file name.
- // Used only for debugging and logging.
- std::string getDebugName();
-
protected:
explicit SymbolBody(Kind K, StringRef N = "")
: SymbolKind(K), IsExternal(true), IsCOMDAT(false),
return S->kind() <= LastDefinedCOFFKind;
}
+ ObjectFile *getFile() { return File; }
int getFileIndex() { return File->Index; }
COFFSymbolRef getCOFFSymbol();
-protected:
ObjectFile *File;
+
+protected:
const coff_symbol_generic *Sym;
};
int getFileIndex() { return File->Index; }
-private:
ArchiveFile *File;
+
+private:
const Archive::Symbol Sym;
};
return S->kind() == DefinedBitcodeKind;
}
-private:
BitcodeFile *File;
};
llvm_unreachable("unknown symbol kind");
}
+std::string toString(SymbolBody &B);
+
} // namespace coff
} // namespace lld
--- /dev/null
+# REQUIRES: system-windows
+# RUN: yaml2obj < %s > %t1.obj
+# RUN: yaml2obj < %s > %t2.obj
+# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log
+# RUN: FileCheck %s < %t.log
+
+# CHECK: duplicate symbol: "int __cdecl mangled(void)" (?mangled@@YAHXZ) in {{.+}}1.obj and in {{.+}}2.obj
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '?mangled@@YAHXZ'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
# RUN: not lld-link /out:%t.exe %t.lto1.obj %t.lto2.obj >& %t.log
# RUN: FileCheck %s < %t.log
-# CHECK: duplicate symbol: foo {{.+}}1.obj and foo {{.+}}2.obj
+# CHECK: duplicate symbol: foo in {{.+}}1.obj and in {{.+}}2.obj
--- !COFF
header: