[lld-macho] Associate each Symbol with an InputFile

This makes our error messages more informative. But the bigger motivation is for
LTO symbol resolution, which will be in an upcoming diff. The changes in this
one are largely mechanical.

Reviewed By: #lld-macho, smeenai

Differential Revision: https://reviews.llvm.org/D94316
This commit is contained in:
Jez Ng 2021-02-03 13:31:40 -05:00
parent d886da042c
commit 163dcd8513
11 changed files with 84 additions and 69 deletions

View File

@ -285,7 +285,8 @@ static InputFile *addFile(StringRef path, bool forceLoadArchive) {
} else if (config->forceLoadObjC) { } else if (config->forceLoadObjC) {
for (const object::Archive::Symbol &sym : file->symbols()) for (const object::Archive::Symbol &sym : file->symbols())
if (sym.getName().startswith(objc::klass)) if (sym.getName().startswith(objc::klass))
symtab->addUndefined(sym.getName(), /*isWeakRef=*/false); symtab->addUndefined(sym.getName(), /*file=*/nullptr,
/*isWeakRef=*/false);
// TODO: no need to look for ObjC sections for a given archive member if // TODO: no need to look for ObjC sections for a given archive member if
// we already found that it contains an ObjC symbol. We should also // we already found that it contains an ObjC symbol. We should also
@ -510,7 +511,7 @@ static void replaceCommonSymbols() {
continue; continue;
auto *isec = make<InputSection>(); auto *isec = make<InputSection>();
isec->file = common->file; isec->file = common->getFile();
isec->name = section_names::common; isec->name = section_names::common;
isec->segname = segment_names::data; isec->segname = segment_names::data;
isec->align = common->align; isec->align = common->align;
@ -521,7 +522,7 @@ static void replaceCommonSymbols() {
isec->flags = S_ZEROFILL; isec->flags = S_ZEROFILL;
inputSections.push_back(isec); inputSections.push_back(isec);
replaceSymbol<Defined>(sym, sym->getName(), isec, /*value=*/0, replaceSymbol<Defined>(sym, sym->getName(), isec->file, isec, /*value=*/0,
/*isWeakDef=*/false, /*isWeakDef=*/false,
/*isExternal=*/true, common->privateExtern); /*isExternal=*/true, common->privateExtern);
} }
@ -721,6 +722,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
target = createTargetInfo(args); target = createTargetInfo(args);
config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main"), config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main"),
/*file=*/nullptr,
/*isWeakRef=*/false); /*isWeakRef=*/false);
config->outputFile = args.getLastArgValue(OPT_o, "a.out"); config->outputFile = args.getLastArgValue(OPT_o, "a.out");
config->installName = config->installName =

View File

@ -44,7 +44,6 @@
#include "llvm/Support/LEB128.h" #include "llvm/Support/LEB128.h"
using namespace llvm; using namespace llvm;
using namespace llvm::MachO;
using namespace lld; using namespace lld;
using namespace lld::macho; using namespace lld::macho;
@ -62,6 +61,7 @@ struct ExportInfo {
uint8_t flags = 0; uint8_t flags = 0;
ExportInfo(const Symbol &sym, uint64_t imageBase) ExportInfo(const Symbol &sym, uint64_t imageBase)
: address(sym.getVA() - imageBase) { : address(sym.getVA() - imageBase) {
using namespace llvm::MachO;
// Set the symbol type. // Set the symbol type.
if (sym.isWeakDef()) if (sym.isWeakDef())
flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;

View File

@ -336,23 +336,23 @@ static macho::Symbol *createDefined(const structs::nlist_64 &sym,
if (sym.n_type & (N_EXT | N_PEXT)) { if (sym.n_type & (N_EXT | N_PEXT)) {
assert((sym.n_type & N_EXT) && "invalid input"); assert((sym.n_type & N_EXT) && "invalid input");
return symtab->addDefined(name, isec, value, sym.n_desc & N_WEAK_DEF, return symtab->addDefined(name, isec->file, isec, value,
sym.n_type & N_PEXT); sym.n_desc & N_WEAK_DEF, sym.n_type & N_PEXT);
} }
return make<Defined>(name, isec, value, sym.n_desc & N_WEAK_DEF, return make<Defined>(name, isec->file, isec, value, sym.n_desc & N_WEAK_DEF,
/*isExternal=*/false, /*isPrivateExtern=*/false); /*isExternal=*/false, /*isPrivateExtern=*/false);
} }
// Absolute symbols are defined symbols that do not have an associated // Absolute symbols are defined symbols that do not have an associated
// InputSection. They cannot be weak. // InputSection. They cannot be weak.
static macho::Symbol *createAbsolute(const structs::nlist_64 &sym, static macho::Symbol *createAbsolute(const structs::nlist_64 &sym,
StringRef name) { InputFile *file, StringRef name) {
if (sym.n_type & (N_EXT | N_PEXT)) { if (sym.n_type & (N_EXT | N_PEXT)) {
assert((sym.n_type & N_EXT) && "invalid input"); assert((sym.n_type & N_EXT) && "invalid input");
return symtab->addDefined(name, nullptr, sym.n_value, /*isWeakDef=*/false, return symtab->addDefined(name, file, nullptr, sym.n_value,
sym.n_type & N_PEXT); /*isWeakDef=*/false, sym.n_type & N_PEXT);
} }
return make<Defined>(name, nullptr, sym.n_value, /*isWeakDef=*/false, return make<Defined>(name, file, nullptr, sym.n_value, /*isWeakDef=*/false,
/*isExternal=*/false, /*isPrivateExtern=*/false); /*isExternal=*/false, /*isPrivateExtern=*/false);
} }
@ -362,12 +362,12 @@ macho::Symbol *ObjFile::parseNonSectionSymbol(const structs::nlist_64 &sym,
switch (type) { switch (type) {
case N_UNDF: case N_UNDF:
return sym.n_value == 0 return sym.n_value == 0
? symtab->addUndefined(name, sym.n_desc & N_WEAK_REF) ? symtab->addUndefined(name, this, sym.n_desc & N_WEAK_REF)
: symtab->addCommon(name, this, sym.n_value, : symtab->addCommon(name, this, sym.n_value,
1 << GET_COMM_ALIGN(sym.n_desc), 1 << GET_COMM_ALIGN(sym.n_desc),
sym.n_type & N_PEXT); sym.n_type & N_PEXT);
case N_ABS: case N_ABS:
return createAbsolute(sym, name); return createAbsolute(sym, this, name);
case N_PBUD: case N_PBUD:
case N_INDR: case N_INDR:
error("TODO: support symbols of type " + std::to_string(type)); error("TODO: support symbols of type " + std::to_string(type));

View File

@ -37,9 +37,9 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {
return {sym, true}; return {sym, true};
} }
Symbol *SymbolTable::addDefined(StringRef name, InputSection *isec, Symbol *SymbolTable::addDefined(StringRef name, InputFile *file,
uint32_t value, bool isWeakDef, InputSection *isec, uint32_t value,
bool isPrivateExtern) { bool isWeakDef, bool isPrivateExtern) {
Symbol *s; Symbol *s;
bool wasInserted; bool wasInserted;
bool overridesWeakDef = false; bool overridesWeakDef = false;
@ -54,8 +54,11 @@ Symbol *SymbolTable::addDefined(StringRef name, InputSection *isec,
defined->privateExtern &= isPrivateExtern; defined->privateExtern &= isPrivateExtern;
return s; return s;
} }
if (!defined->isWeakDef()) if (!defined->isWeakDef()) {
error("duplicate symbol: " + name); error("duplicate symbol: " + name + "\n>>> defined in " +
toString(defined->getFile()) + "\n>>> defined in " +
toString(file));
}
} else if (auto *dysym = dyn_cast<DylibSymbol>(s)) { } else if (auto *dysym = dyn_cast<DylibSymbol>(s)) {
overridesWeakDef = !isWeakDef && dysym->isWeakDef(); overridesWeakDef = !isWeakDef && dysym->isWeakDef();
} }
@ -64,13 +67,14 @@ Symbol *SymbolTable::addDefined(StringRef name, InputSection *isec,
} }
Defined *defined = Defined *defined =
replaceSymbol<Defined>(s, name, isec, value, isWeakDef, replaceSymbol<Defined>(s, name, file, isec, value, isWeakDef,
/*isExternal=*/true, isPrivateExtern); /*isExternal=*/true, isPrivateExtern);
defined->overridesWeakDef = overridesWeakDef; defined->overridesWeakDef = overridesWeakDef;
return s; return s;
} }
Symbol *SymbolTable::addUndefined(StringRef name, bool isWeakRef) { Symbol *SymbolTable::addUndefined(StringRef name, InputFile *file,
bool isWeakRef) {
Symbol *s; Symbol *s;
bool wasInserted; bool wasInserted;
std::tie(s, wasInserted) = insert(name); std::tie(s, wasInserted) = insert(name);
@ -78,7 +82,7 @@ Symbol *SymbolTable::addUndefined(StringRef name, bool isWeakRef) {
auto refState = isWeakRef ? RefState::Weak : RefState::Strong; auto refState = isWeakRef ? RefState::Weak : RefState::Strong;
if (wasInserted) if (wasInserted)
replaceSymbol<Undefined>(s, name, refState); replaceSymbol<Undefined>(s, name, file, refState);
else if (auto *lazy = dyn_cast<LazySymbol>(s)) else if (auto *lazy = dyn_cast<LazySymbol>(s))
lazy->fetchArchiveMember(); lazy->fetchArchiveMember();
else if (auto *dynsym = dyn_cast<DylibSymbol>(s)) else if (auto *dynsym = dyn_cast<DylibSymbol>(s))
@ -162,11 +166,12 @@ Symbol *SymbolTable::addDSOHandle(const MachHeaderSection *header) {
return s; return s;
} }
void lld::macho::treatUndefinedSymbol(StringRef symbolName, void lld::macho::treatUndefinedSymbol(const Undefined &sym) {
StringRef fileName) { std::string message = "undefined symbol: " + toString(sym);
std::string message = ("undefined symbol: " + symbolName).str(); std::string fileName = toString(sym.getFile());
if (!fileName.empty()) if (!fileName.empty())
message += ("\n>>> referenced by " + fileName).str(); message += "\n>>> referenced by " + fileName;
switch (config->undefinedSymbolTreatment) { switch (config->undefinedSymbolTreatment) {
case UndefinedSymbolTreatment::suppress: case UndefinedSymbolTreatment::suppress:
break; break;

View File

@ -20,9 +20,11 @@ namespace macho {
class ArchiveFile; class ArchiveFile;
class DylibFile; class DylibFile;
class InputFile; class InputFile;
class ObjFile;
class InputSection; class InputSection;
class MachHeaderSection; class MachHeaderSection;
class Symbol; class Symbol;
class Undefined;
/* /*
* Note that the SymbolTable handles name collisions by calling * Note that the SymbolTable handles name collisions by calling
@ -32,10 +34,10 @@ class Symbol;
*/ */
class SymbolTable { class SymbolTable {
public: public:
Symbol *addDefined(StringRef name, InputSection *isec, uint32_t value, Symbol *addDefined(StringRef name, InputFile *, InputSection *,
bool isWeakDef, bool isPrivateExtern); uint32_t value, bool isWeakDef, bool isPrivateExtern);
Symbol *addUndefined(StringRef name, bool isWeakRef); Symbol *addUndefined(StringRef name, InputFile *, bool isWeakRef);
Symbol *addCommon(StringRef name, InputFile *, uint64_t size, uint32_t align, Symbol *addCommon(StringRef name, InputFile *, uint64_t size, uint32_t align,
bool isPrivateExtern); bool isPrivateExtern);
@ -56,7 +58,7 @@ private:
std::vector<Symbol *> symVector; std::vector<Symbol *> symVector;
}; };
extern void treatUndefinedSymbol(StringRef symbolName, StringRef fileName); void treatUndefinedSymbol(const Undefined &);
extern SymbolTable *symtab; extern SymbolTable *symtab;

View File

@ -44,7 +44,7 @@ uint64_t Defined::getFileOffset() const {
return isec->getFileOffset() + value; return isec->getFileOffset() + value;
} }
void LazySymbol::fetchArchiveMember() { file->fetch(sym); } void LazySymbol::fetchArchiveMember() { getFile()->fetch(sym); }
uint64_t DSOHandle::getVA() const { return header->addr; } uint64_t DSOHandle::getVA() const { return header->addr; }

View File

@ -9,6 +9,7 @@
#ifndef LLD_MACHO_SYMBOLS_H #ifndef LLD_MACHO_SYMBOLS_H
#define LLD_MACHO_SYMBOLS_H #define LLD_MACHO_SYMBOLS_H
#include "InputFiles.h"
#include "InputSection.h" #include "InputSection.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h" #include "lld/Common/ErrorHandler.h"
@ -21,8 +22,6 @@ namespace macho {
class InputSection; class InputSection;
class MachHeaderSection; class MachHeaderSection;
class DylibFile;
class ArchiveFile;
struct StringRefZ { struct StringRefZ {
StringRefZ(const char *s) : data(s), size(-1) {} StringRefZ(const char *s) : data(s), size(-1) {}
@ -83,20 +82,23 @@ public:
uint32_t symtabIndex = UINT32_MAX; uint32_t symtabIndex = UINT32_MAX;
InputFile *getFile() const { return file; }
protected: protected:
Symbol(Kind k, StringRefZ name) Symbol(Kind k, StringRefZ name, InputFile *file)
: symbolKind(k), nameData(name.data), nameSize(name.size) {} : symbolKind(k), nameData(name.data), nameSize(name.size), file(file) {}
Kind symbolKind; Kind symbolKind;
const char *nameData; const char *nameData;
mutable uint32_t nameSize; mutable uint32_t nameSize;
InputFile *file;
}; };
class Defined : public Symbol { class Defined : public Symbol {
public: public:
Defined(StringRefZ name, InputSection *isec, uint32_t value, bool isWeakDef, Defined(StringRefZ name, InputFile *file, InputSection *isec, uint32_t value,
bool isExternal, bool isPrivateExtern) bool isWeakDef, bool isExternal, bool isPrivateExtern)
: Symbol(DefinedKind, name), isec(isec), value(value), : Symbol(DefinedKind, name, file), isec(isec), value(value),
overridesWeakDef(false), privateExtern(isPrivateExtern), overridesWeakDef(false), privateExtern(isPrivateExtern),
weakDef(isWeakDef), external(isExternal) {} weakDef(isWeakDef), external(isExternal) {}
@ -116,6 +118,7 @@ public:
static bool classof(const Symbol *s) { return s->kind() == DefinedKind; } static bool classof(const Symbol *s) { return s->kind() == DefinedKind; }
InputFile *file;
InputSection *isec; InputSection *isec;
uint32_t value; uint32_t value;
@ -136,8 +139,8 @@ enum class RefState : uint8_t { Unreferenced = 0, Weak = 1, Strong = 2 };
class Undefined : public Symbol { class Undefined : public Symbol {
public: public:
Undefined(StringRefZ name, RefState refState) Undefined(StringRefZ name, InputFile *file, RefState refState)
: Symbol(UndefinedKind, name), refState(refState) { : Symbol(UndefinedKind, name, file), refState(refState) {
assert(refState != RefState::Unreferenced); assert(refState != RefState::Unreferenced);
} }
@ -167,7 +170,7 @@ class CommonSymbol : public Symbol {
public: public:
CommonSymbol(StringRefZ name, InputFile *file, uint64_t size, uint32_t align, CommonSymbol(StringRefZ name, InputFile *file, uint64_t size, uint32_t align,
bool isPrivateExtern) bool isPrivateExtern)
: Symbol(CommonKind, name), file(file), size(size), : Symbol(CommonKind, name, file), size(size),
align(align != 1 ? align : llvm::PowerOf2Ceil(size)), align(align != 1 ? align : llvm::PowerOf2Ceil(size)),
privateExtern(isPrivateExtern) { privateExtern(isPrivateExtern) {
// TODO: cap maximum alignment // TODO: cap maximum alignment
@ -175,7 +178,6 @@ public:
static bool classof(const Symbol *s) { return s->kind() == CommonKind; } static bool classof(const Symbol *s) { return s->kind() == CommonKind; }
InputFile *const file;
const uint64_t size; const uint64_t size;
const uint32_t align; const uint32_t align;
const bool privateExtern; const bool privateExtern;
@ -185,18 +187,18 @@ class DylibSymbol : public Symbol {
public: public:
DylibSymbol(DylibFile *file, StringRefZ name, bool isWeakDef, DylibSymbol(DylibFile *file, StringRefZ name, bool isWeakDef,
RefState refState, bool isTlv) RefState refState, bool isTlv)
: Symbol(DylibKind, name), file(file), refState(refState), : Symbol(DylibKind, name, file), refState(refState), weakDef(isWeakDef),
weakDef(isWeakDef), tlv(isTlv) {} tlv(isTlv) {}
bool isWeakDef() const override { return weakDef; } bool isWeakDef() const override { return weakDef; }
bool isWeakRef() const override { return refState == RefState::Weak; } bool isWeakRef() const override { return refState == RefState::Weak; }
bool isReferenced() const { return refState != RefState::Unreferenced; } bool isReferenced() const { return refState != RefState::Unreferenced; }
bool isTlv() const override { return tlv; } bool isTlv() const override { return tlv; }
bool hasStubsHelper() const { return stubsHelperIndex != UINT32_MAX; } bool hasStubsHelper() const { return stubsHelperIndex != UINT32_MAX; }
DylibFile *getFile() const { return cast<DylibFile>(file); }
static bool classof(const Symbol *s) { return s->kind() == DylibKind; } static bool classof(const Symbol *s) { return s->kind() == DylibKind; }
DylibFile *file;
uint32_t stubsHelperIndex = UINT32_MAX; uint32_t stubsHelperIndex = UINT32_MAX;
uint32_t lazyBindOffset = UINT32_MAX; uint32_t lazyBindOffset = UINT32_MAX;
@ -210,14 +212,14 @@ private:
class LazySymbol : public Symbol { class LazySymbol : public Symbol {
public: public:
LazySymbol(ArchiveFile *file, const llvm::object::Archive::Symbol &sym) LazySymbol(ArchiveFile *file, const llvm::object::Archive::Symbol &sym)
: Symbol(LazyKind, sym.getName()), file(file), sym(sym) {} : Symbol(LazyKind, sym.getName(), file), sym(sym) {}
ArchiveFile *getFile() const { return cast<ArchiveFile>(file); }
void fetchArchiveMember();
static bool classof(const Symbol *s) { return s->kind() == LazyKind; } static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
void fetchArchiveMember();
private: private:
ArchiveFile *file;
const llvm::object::Archive::Symbol sym; const llvm::object::Archive::Symbol sym;
}; };
@ -235,7 +237,7 @@ private:
class DSOHandle : public Symbol { class DSOHandle : public Symbol {
public: public:
DSOHandle(const MachHeaderSection *header) DSOHandle(const MachHeaderSection *header)
: Symbol(DSOHandleKind, name), header(header) {} : Symbol(DSOHandleKind, name, nullptr), header(header) {}
const MachHeaderSection *header; const MachHeaderSection *header;

View File

@ -265,15 +265,15 @@ static void encodeBinding(const Symbol *sym, const OutputSection *osec,
static void encodeDylibOrdinal(const DylibSymbol *dysym, Binding &lastBinding, static void encodeDylibOrdinal(const DylibSymbol *dysym, Binding &lastBinding,
raw_svector_ostream &os) { raw_svector_ostream &os) {
using namespace llvm::MachO; using namespace llvm::MachO;
if (lastBinding.ordinal != dysym->file->ordinal) { if (lastBinding.ordinal != dysym->getFile()->ordinal) {
if (dysym->file->ordinal <= BIND_IMMEDIATE_MASK) { if (dysym->getFile()->ordinal <= BIND_IMMEDIATE_MASK) {
os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
dysym->file->ordinal); dysym->getFile()->ordinal);
} else { } else {
os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); os << static_cast<uint8_t>(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
encodeULEB128(dysym->file->ordinal, os); encodeULEB128(dysym->getFile()->ordinal, os);
} }
lastBinding.ordinal = dysym->file->ordinal; lastBinding.ordinal = dysym->getFile()->ordinal;
} }
} }
@ -442,10 +442,9 @@ void StubHelperSection::setup() {
in.got->addEntry(stubBinder); in.got->addEntry(stubBinder);
inputSections.push_back(in.imageLoaderCache); inputSections.push_back(in.imageLoaderCache);
dyldPrivate = dyldPrivate = make<Defined>("__dyld_private", nullptr, in.imageLoaderCache, 0,
make<Defined>("__dyld_private", in.imageLoaderCache, 0, /*isWeakDef=*/false,
/*isWeakDef=*/false, /*isExternal=*/false, /*isPrivateExtern=*/false);
/*isExternal=*/false, /*isPrivateExtern=*/false);
} }
ImageLoaderCacheSection::ImageLoaderCacheSection() { ImageLoaderCacheSection::ImageLoaderCacheSection() {
@ -522,12 +521,12 @@ uint32_t LazyBindingSection::encode(const DylibSymbol &sym) {
uint64_t offset = in.lazyPointers->addr - dataSeg->firstSection()->addr + uint64_t offset = in.lazyPointers->addr - dataSeg->firstSection()->addr +
sym.stubsIndex * WordSize; sym.stubsIndex * WordSize;
encodeULEB128(offset, os); encodeULEB128(offset, os);
if (sym.file->ordinal <= MachO::BIND_IMMEDIATE_MASK) { if (sym.getFile()->ordinal <= MachO::BIND_IMMEDIATE_MASK) {
os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
sym.file->ordinal); sym.getFile()->ordinal);
} else { } else {
os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB); os << static_cast<uint8_t>(MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
encodeULEB128(sym.file->ordinal, os); encodeULEB128(sym.getFile()->ordinal, os);
} }
uint8_t flags = MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM; uint8_t flags = MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM;
@ -786,7 +785,7 @@ void SymtabSection::writeTo(uint8_t *buf) const {
nList->n_desc |= defined->isExternalWeakDef() ? MachO::N_WEAK_DEF : 0; nList->n_desc |= defined->isExternalWeakDef() ? MachO::N_WEAK_DEF : 0;
} else if (auto *dysym = dyn_cast<DylibSymbol>(entry.sym)) { } else if (auto *dysym = dyn_cast<DylibSymbol>(entry.sym)) {
uint16_t n_desc = nList->n_desc; uint16_t n_desc = nList->n_desc;
MachO::SET_LIBRARY_ORDINAL(n_desc, dysym->file->ordinal); MachO::SET_LIBRARY_ORDINAL(n_desc, dysym->getFile()->ordinal);
nList->n_type = MachO::N_EXT; nList->n_type = MachO::N_EXT;
n_desc |= dysym->isWeakRef() ? MachO::N_WEAK_REF : 0; n_desc |= dysym->isWeakRef() ? MachO::N_WEAK_REF : 0;
nList->n_desc = n_desc; nList->n_desc = n_desc;

View File

@ -439,8 +439,8 @@ void Writer::scanRelocations() {
if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND)) if (target->hasAttr(r.type, RelocAttrBits::SUBTRAHEND))
continue; continue;
if (auto *sym = r.referent.dyn_cast<lld::macho::Symbol *>()) { if (auto *sym = r.referent.dyn_cast<lld::macho::Symbol *>()) {
if (isa<Undefined>(sym)) if (auto *undefined = dyn_cast<Undefined>(sym))
treatUndefinedSymbol(toString(*sym), toString(isec->file)); treatUndefinedSymbol(*undefined);
else if (target->validateSymbolRelocation(sym, isec, r)) else if (target->validateSymbolRelocation(sym, isec, r))
prepareSymbolRelocation(sym, isec, r); prepareSymbolRelocation(sym, isec, r);
} else { } else {
@ -458,7 +458,8 @@ void Writer::scanSymbols() {
if (defined->overridesWeakDef) if (defined->overridesWeakDef)
in.weakBinding->addNonWeakDefinition(defined); in.weakBinding->addNonWeakDefinition(defined);
} else if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) { } else if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) {
dysym->file->refState = std::max(dysym->file->refState, dysym->refState); dysym->getFile()->refState =
std::max(dysym->getFile()->refState, dysym->refState);
} }
} }
} }

View File

@ -4,7 +4,9 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weakfoo.s -o %t/weakfoo.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weakfoo.s -o %t/weakfoo.o
# RUN: not %lld -lSystem %t/test.o %t/weakfoo.o -o %t/test 2>&1 | FileCheck %s # RUN: not %lld -lSystem %t/test.o %t/weakfoo.o -o %t/test 2>&1 | FileCheck %s
# CHECK: lld: error: duplicate symbol: _weakfoo # CHECK: error: duplicate symbol: _weakfoo
# CHECK-NEXT: >>> defined in {{.*}}/test.o
# CHECK-NEXT: >>> defined in {{.*}}/weakfoo.o
#--- weakfoo.s #--- weakfoo.s
.globl _weakfoo .globl _weakfoo

View File

@ -1,10 +1,12 @@
# REQUIRES: x86 # REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t-dup.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t-dup.o
# RUN: not %lld -o /dev/null %t-dup.o %t.o 2>&1 | FileCheck %s # RUN: not %lld -o /dev/null %t-dup.o %t.o 2>&1 | FileCheck %s -DFILE_1=%t-dup.o -DFILE_2=%t.o
# RUN: not %lld -o /dev/null %t.o %t.o 2>&1 | FileCheck %s # RUN: not %lld -o /dev/null %t.o %t.o 2>&1 | FileCheck %s -DFILE_1=%t.o -DFILE_2=%t.o
# CHECK: error: duplicate symbol: _main # CHECK: error: duplicate symbol: _main
# CHECK-NEXT: >>> defined in [[FILE_1]]
# CHECK-NEXT: >>> defined in [[FILE_2]]
.text .text
.global _main .global _main