[LLD][COFF] Clarify EC vs. native symbols in diagnostics on ARM64X (#130857)
On ARM64X, symbol names alone are ambiguous as they may refer to either a native or an EC symbol. Append '(EC symbol)' or '(native symbol)' in diagnostic messages to distinguish them.
This commit is contained in:
@@ -705,9 +705,9 @@ void ObjFile::handleComdatSelection(
|
|||||||
// seems better though.
|
// seems better though.
|
||||||
// (This behavior matches ModuleLinker::getComdatResult().)
|
// (This behavior matches ModuleLinker::getComdatResult().)
|
||||||
if (selection != leaderSelection) {
|
if (selection != leaderSelection) {
|
||||||
Log(ctx) << "conflicting comdat type for " << leader << ": "
|
Log(ctx) << "conflicting comdat type for " << symtab.printSymbol(leader)
|
||||||
<< (int)leaderSelection << " in " << leader->getFile() << " and "
|
<< ": " << (int)leaderSelection << " in " << leader->getFile()
|
||||||
<< (int)selection << " in " << this;
|
<< " and " << (int)selection << " in " << this;
|
||||||
symtab.reportDuplicate(leader, this);
|
symtab.reportDuplicate(leader, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,10 +214,9 @@ struct UndefinedDiag {
|
|||||||
std::vector<File> files;
|
std::vector<File> files;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void reportUndefinedSymbol(COFFLinkerContext &ctx,
|
void SymbolTable::reportUndefinedSymbol(const UndefinedDiag &undefDiag) {
|
||||||
const UndefinedDiag &undefDiag) {
|
|
||||||
auto diag = errorOrWarn(ctx);
|
auto diag = errorOrWarn(ctx);
|
||||||
diag << "undefined symbol: " << undefDiag.sym;
|
diag << "undefined symbol: " << printSymbol(undefDiag.sym);
|
||||||
|
|
||||||
const size_t maxUndefReferences = 3;
|
const size_t maxUndefReferences = 3;
|
||||||
size_t numDisplayedRefs = 0, numRefs = 0;
|
size_t numDisplayedRefs = 0, numRefs = 0;
|
||||||
@@ -363,12 +362,12 @@ void SymbolTable::reportProblemSymbols(
|
|||||||
|
|
||||||
for (Symbol *b : ctx.config.gcroot) {
|
for (Symbol *b : ctx.config.gcroot) {
|
||||||
if (undefs.count(b))
|
if (undefs.count(b))
|
||||||
errorOrWarn(ctx) << "<root>: undefined symbol: " << b;
|
errorOrWarn(ctx) << "<root>: undefined symbol: " << printSymbol(b);
|
||||||
if (localImports)
|
if (localImports)
|
||||||
if (Symbol *imp = localImports->lookup(b))
|
if (Symbol *imp = localImports->lookup(b))
|
||||||
Warn(ctx) << "<root>: locally defined symbol imported: " << imp
|
Warn(ctx) << "<root>: locally defined symbol imported: "
|
||||||
<< " (defined in " << toString(imp->getFile())
|
<< printSymbol(imp) << " (defined in "
|
||||||
<< ") [LNK4217]";
|
<< toString(imp->getFile()) << ") [LNK4217]";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<UndefinedDiag> undefDiags;
|
std::vector<UndefinedDiag> undefDiags;
|
||||||
@@ -389,7 +388,8 @@ void SymbolTable::reportProblemSymbols(
|
|||||||
}
|
}
|
||||||
if (localImports)
|
if (localImports)
|
||||||
if (Symbol *imp = localImports->lookup(sym))
|
if (Symbol *imp = localImports->lookup(sym))
|
||||||
Warn(ctx) << file << ": locally defined symbol imported: " << imp
|
Warn(ctx) << file
|
||||||
|
<< ": locally defined symbol imported: " << printSymbol(imp)
|
||||||
<< " (defined in " << imp->getFile() << ") [LNK4217]";
|
<< " (defined in " << imp->getFile() << ") [LNK4217]";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -402,7 +402,7 @@ void SymbolTable::reportProblemSymbols(
|
|||||||
processFile(file, file->getSymbols());
|
processFile(file, file->getSymbols());
|
||||||
|
|
||||||
for (const UndefinedDiag &undefDiag : undefDiags)
|
for (const UndefinedDiag &undefDiag : undefDiags)
|
||||||
reportUndefinedSymbol(ctx, undefDiag);
|
reportUndefinedSymbol(undefDiag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolTable::reportUnresolvable() {
|
void SymbolTable::reportUnresolvable() {
|
||||||
@@ -822,7 +822,7 @@ void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile,
|
|||||||
uint32_t newSectionOffset) {
|
uint32_t newSectionOffset) {
|
||||||
COFFSyncStream diag(ctx, ctx.config.forceMultiple ? DiagLevel::Warn
|
COFFSyncStream diag(ctx, ctx.config.forceMultiple ? DiagLevel::Warn
|
||||||
: DiagLevel::Err);
|
: DiagLevel::Err);
|
||||||
diag << "duplicate symbol: " << existing;
|
diag << "duplicate symbol: " << printSymbol(existing);
|
||||||
|
|
||||||
DefinedRegular *d = dyn_cast<DefinedRegular>(existing);
|
DefinedRegular *d = dyn_cast<DefinedRegular>(existing);
|
||||||
if (d && isa<ObjFile>(d->getFile())) {
|
if (d && isa<ObjFile>(d->getFile())) {
|
||||||
@@ -1350,6 +1350,13 @@ Symbol *SymbolTable::addUndefined(StringRef name) {
|
|||||||
return addUndefined(name, nullptr, false);
|
return addUndefined(name, nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SymbolTable::printSymbol(Symbol *sym) const {
|
||||||
|
std::string name = maybeDemangleSymbol(ctx, sym->getName());
|
||||||
|
if (ctx.hybridSymtab)
|
||||||
|
return name + (isEC() ? " (EC symbol)" : " (native symbol)");
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
void SymbolTable::compileBitcodeFiles() {
|
void SymbolTable::compileBitcodeFiles() {
|
||||||
if (bitcodeFileInstances.empty())
|
if (bitcodeFileInstances.empty())
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ struct WrappedSymbol {
|
|||||||
Symbol *wrap;
|
Symbol *wrap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UndefinedDiag;
|
||||||
|
|
||||||
// SymbolTable is a bucket of all known symbols, including defined,
|
// SymbolTable is a bucket of all known symbols, including defined,
|
||||||
// undefined, or lazy symbols (the last one is symbols in archive
|
// undefined, or lazy symbols (the last one is symbols in archive
|
||||||
// files whose archive members are not yet loaded).
|
// files whose archive members are not yet loaded).
|
||||||
@@ -195,6 +197,8 @@ public:
|
|||||||
uint32_t loadConfigSize = 0;
|
uint32_t loadConfigSize = 0;
|
||||||
void initializeLoadConfig();
|
void initializeLoadConfig();
|
||||||
|
|
||||||
|
std::string printSymbol(Symbol *sym) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Given a name without "__imp_" prefix, returns a defined symbol
|
/// Given a name without "__imp_" prefix, returns a defined symbol
|
||||||
/// with the "__imp_" prefix, if it exists.
|
/// with the "__imp_" prefix, if it exists.
|
||||||
@@ -216,6 +220,7 @@ private:
|
|||||||
reportProblemSymbols(const llvm::SmallPtrSetImpl<Symbol *> &undefs,
|
reportProblemSymbols(const llvm::SmallPtrSetImpl<Symbol *> &undefs,
|
||||||
const llvm::DenseMap<Symbol *, Symbol *> *localImports,
|
const llvm::DenseMap<Symbol *, Symbol *> *localImports,
|
||||||
bool needBitcodeFiles);
|
bool needBitcodeFiles);
|
||||||
|
void reportUndefinedSymbol(const UndefinedDiag &undefDiag);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex);
|
std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex);
|
||||||
|
|||||||
@@ -60,10 +60,6 @@ coff::operator<<(const COFFSyncStream &s,
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
const COFFSyncStream &coff::operator<<(const COFFSyncStream &s, Symbol *sym) {
|
|
||||||
return s << maybeDemangleSymbol(s.ctx, sym->getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace coff {
|
namespace coff {
|
||||||
|
|
||||||
void Symbol::computeName() {
|
void Symbol::computeName() {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ class SymbolTable;
|
|||||||
|
|
||||||
const COFFSyncStream &operator<<(const COFFSyncStream &,
|
const COFFSyncStream &operator<<(const COFFSyncStream &,
|
||||||
const llvm::object::Archive::Symbol *);
|
const llvm::object::Archive::Symbol *);
|
||||||
const COFFSyncStream &operator<<(const COFFSyncStream &, Symbol *);
|
|
||||||
|
|
||||||
// The base class for real symbol classes.
|
// The base class for real symbol classes.
|
||||||
class Symbol {
|
class Symbol {
|
||||||
|
|||||||
@@ -1282,12 +1282,13 @@ void Writer::createImportTables() {
|
|||||||
ctx.config.dllOrder[dll] = ctx.config.dllOrder.size();
|
ctx.config.dllOrder[dll] = ctx.config.dllOrder.size();
|
||||||
|
|
||||||
if (file->impSym && !isa<DefinedImportData>(file->impSym))
|
if (file->impSym && !isa<DefinedImportData>(file->impSym))
|
||||||
Fatal(ctx) << file->impSym << " was replaced";
|
Fatal(ctx) << file->symtab.printSymbol(file->impSym) << " was replaced";
|
||||||
DefinedImportData *impSym = cast_or_null<DefinedImportData>(file->impSym);
|
DefinedImportData *impSym = cast_or_null<DefinedImportData>(file->impSym);
|
||||||
if (ctx.config.delayLoads.count(StringRef(file->dllName).lower())) {
|
if (ctx.config.delayLoads.count(StringRef(file->dllName).lower())) {
|
||||||
if (!file->thunkSym)
|
if (!file->thunkSym)
|
||||||
Fatal(ctx) << "cannot delay-load " << toString(file)
|
Fatal(ctx) << "cannot delay-load " << toString(file)
|
||||||
<< " due to import of data: " << impSym;
|
<< " due to import of data: "
|
||||||
|
<< file->symtab.printSymbol(impSym);
|
||||||
delayIdata.add(impSym);
|
delayIdata.add(impSym);
|
||||||
} else {
|
} else {
|
||||||
idata.add(impSym);
|
idata.add(impSym);
|
||||||
@@ -1306,7 +1307,8 @@ void Writer::appendImportThunks() {
|
|||||||
|
|
||||||
if (file->thunkSym) {
|
if (file->thunkSym) {
|
||||||
if (!isa<DefinedImportThunk>(file->thunkSym))
|
if (!isa<DefinedImportThunk>(file->thunkSym))
|
||||||
Fatal(ctx) << file->thunkSym << " was replaced";
|
Fatal(ctx) << file->symtab.printSymbol(file->thunkSym)
|
||||||
|
<< " was replaced";
|
||||||
auto *chunk = cast<DefinedImportThunk>(file->thunkSym)->getChunk();
|
auto *chunk = cast<DefinedImportThunk>(file->thunkSym)->getChunk();
|
||||||
if (chunk->live)
|
if (chunk->live)
|
||||||
textSec->addChunk(chunk);
|
textSec->addChunk(chunk);
|
||||||
@@ -1314,7 +1316,8 @@ void Writer::appendImportThunks() {
|
|||||||
|
|
||||||
if (file->auxThunkSym) {
|
if (file->auxThunkSym) {
|
||||||
if (!isa<DefinedImportThunk>(file->auxThunkSym))
|
if (!isa<DefinedImportThunk>(file->auxThunkSym))
|
||||||
Fatal(ctx) << file->auxThunkSym << " was replaced";
|
Fatal(ctx) << file->symtab.printSymbol(file->auxThunkSym)
|
||||||
|
<< " was replaced";
|
||||||
auto *chunk = cast<DefinedImportThunk>(file->auxThunkSym)->getChunk();
|
auto *chunk = cast<DefinedImportThunk>(file->auxThunkSym)->getChunk();
|
||||||
if (chunk->live)
|
if (chunk->live)
|
||||||
textSec->addChunk(chunk);
|
textSec->addChunk(chunk);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
// RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s
|
// RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s
|
||||||
|
|
||||||
// ERR-NATIVE-NOT: test-arm64ec.obj
|
// ERR-NATIVE-NOT: test-arm64ec.obj
|
||||||
// ERR-NATIVE: lld-link: error: undefined symbol: sym
|
// ERR-NATIVE: lld-link: error: undefined symbol: sym (native symbol)
|
||||||
// ERR-NATIVE-NEXT: >>> referenced by test-arm64.obj:(.test)
|
// ERR-NATIVE-NEXT: >>> referenced by test-arm64.obj:(.test)
|
||||||
// ERR-NATIVE-NOT: test-arm64ec.obj
|
// ERR-NATIVE-NOT: test-arm64ec.obj
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
// RUN: 2>&1 | FileCheck --check-prefix=ERR-EC %s
|
// RUN: 2>&1 | FileCheck --check-prefix=ERR-EC %s
|
||||||
|
|
||||||
// ERR-EC-NOT: test-arm64.obj
|
// ERR-EC-NOT: test-arm64.obj
|
||||||
// ERR-EC: lld-link: error: undefined symbol: sym
|
// ERR-EC: lld-link: error: undefined symbol: sym (EC symbol)
|
||||||
// ERR-EC-NEXT: >>> referenced by test-arm64ec.obj:(.test)
|
// ERR-EC-NEXT: >>> referenced by test-arm64ec.obj:(.test)
|
||||||
// ERR-EC-NOT: test-arm64.obj
|
// ERR-EC-NOT: test-arm64.obj
|
||||||
|
|
||||||
|
|||||||
@@ -40,14 +40,15 @@
|
|||||||
// Check that including a missing symbol results in an error.
|
// Check that including a missing symbol results in an error.
|
||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -out:err.dll -dll -noentry loadconfig-arm64.obj loadconfig-arm64ec.obj -include:sym sym-aarch64.obj \
|
// RUN: not lld-link -machine:arm64x -out:err.dll -dll -noentry loadconfig-arm64.obj loadconfig-arm64ec.obj -include:sym sym-aarch64.obj \
|
||||||
// RUN: 2>&1 | FileCheck --check-prefix=ERR %s
|
// RUN: 2>&1 | FileCheck --check-prefix=ERR-EC %s
|
||||||
// ERR: lld-link: error: <root>: undefined symbol: sym
|
// ERR-EC: lld-link: error: <root>: undefined symbol: sym (EC symbol)
|
||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -out:err.dll -dll -noentry loadconfig-arm64.obj loadconfig-arm64ec.obj drectve-arm64ec.obj sym-aarch64.obj \
|
// RUN: not lld-link -machine:arm64x -out:err.dll -dll -noentry loadconfig-arm64.obj loadconfig-arm64ec.obj drectve-arm64ec.obj sym-aarch64.obj \
|
||||||
// RUN: 2>&1 | FileCheck --check-prefix=ERR %s
|
// RUN: 2>&1 | FileCheck --check-prefix=ERR-EC %s
|
||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -out:err.dll -dll -noentry loadconfig-arm64.obj loadconfig-arm64ec.obj drectve-aarch64.obj sym-arm64ec.obj \
|
// RUN: not lld-link -machine:arm64x -out:err.dll -dll -noentry loadconfig-arm64.obj loadconfig-arm64ec.obj drectve-aarch64.obj sym-arm64ec.obj \
|
||||||
// RUN: 2>&1 | FileCheck --check-prefix=ERR %s
|
// RUN: 2>&1 | FileCheck --check-prefix=ERR-NATIVE %s
|
||||||
|
// ERR-NATIVE: lld-link: error: <root>: undefined symbol: sym (native symbol)
|
||||||
|
|
||||||
#--- sym-aarch64.s
|
#--- sym-aarch64.s
|
||||||
.section ".test","dr"
|
.section ".test","dr"
|
||||||
|
|||||||
@@ -18,19 +18,19 @@
|
|||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -dll -noentry -out:err1.dll symref-aarch64.obj sym-arm64ec.obj \
|
// RUN: not lld-link -machine:arm64x -dll -noentry -out:err1.dll symref-aarch64.obj sym-arm64ec.obj \
|
||||||
// RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s
|
// RUN: 2>&1 | FileCheck --check-prefix=UNDEF %s
|
||||||
// UNDEF: lld-link: error: undefined symbol: sym
|
// UNDEF: lld-link: error: undefined symbol: sym (native symbol)
|
||||||
// UNDEF-NEXT: >>> referenced by symref-aarch64.obj:(.data)
|
// UNDEF-NEXT: >>> referenced by symref-aarch64.obj:(.data)
|
||||||
|
|
||||||
// Check that EC object files can't reference native symbols.
|
// Check that EC object files can't reference native symbols.
|
||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -dll -noentry -out:out.dll symref-arm64ec.obj sym-aarch64.obj \
|
// RUN: not lld-link -machine:arm64x -dll -noentry -out:out.dll symref-arm64ec.obj sym-aarch64.obj \
|
||||||
// RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s
|
// RUN: 2>&1 | FileCheck --check-prefix=UNDEFEC %s
|
||||||
// UNDEFEC: lld-link: error: undefined symbol: sym
|
// UNDEFEC: lld-link: error: undefined symbol: sym (EC symbol)
|
||||||
// UNDEFEC-NEXT: >>> referenced by symref-arm64ec.obj:(.data)
|
// UNDEFEC-NEXT: >>> referenced by symref-arm64ec.obj:(.data)
|
||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -dll -noentry -out:out.dll symref-x86_64.obj sym-aarch64.obj \
|
// RUN: not lld-link -machine:arm64x -dll -noentry -out:out.dll symref-x86_64.obj sym-aarch64.obj \
|
||||||
// RUN: 2>&1 | FileCheck --check-prefix=UNDEFX86 %s
|
// RUN: 2>&1 | FileCheck --check-prefix=UNDEFX86 %s
|
||||||
// UNDEFX86: lld-link: error: undefined symbol: sym
|
// UNDEFX86: lld-link: error: undefined symbol: sym (EC symbol)
|
||||||
// UNDEFX86-NEXT: >>> referenced by symref-x86_64.obj:(.data)
|
// UNDEFX86-NEXT: >>> referenced by symref-x86_64.obj:(.data)
|
||||||
|
|
||||||
// RUN: not lld-link -machine:arm64x -dll -noentry -out:err2.dll symref-aarch64.obj sym-x86_64.obj \
|
// RUN: not lld-link -machine:arm64x -dll -noentry -out:err2.dll symref-aarch64.obj sym-x86_64.obj \
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %s -o %t.arm64ec.obj
|
// RUN: llvm-mc -filetype=obj -triple=arm64ec-windows %s -o %t.arm64ec.obj
|
||||||
|
|
||||||
// RUN: lld-link -machine:arm64x -dll -noentry %t.arm64.obj %t.arm64ec.obj -out:%t.dll 2>&1 | FileCheck --check-prefix=WARN %s
|
// RUN: lld-link -machine:arm64x -dll -noentry %t.arm64.obj %t.arm64ec.obj -out:%t.dll 2>&1 | FileCheck --check-prefix=WARN %s
|
||||||
// WARN: lld-link: warning: {{.*}}.arm64.obj: locally defined symbol imported: func
|
// WARN: lld-link: warning: {{.*}}.arm64.obj: locally defined symbol imported: func (native symbol)
|
||||||
// WARN-NEXT: lld-link: warning: {{.*}}.arm64ec.obj: locally defined symbol imported: func
|
// WARN-NEXT: lld-link: warning: {{.*}}.arm64ec.obj: locally defined symbol imported: func (EC symbol)
|
||||||
|
|
||||||
// RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck --check-prefix=TEST %s
|
// RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck --check-prefix=TEST %s
|
||||||
// TEST: 0x180005000 00300000 08300000
|
// TEST: 0x180005000 00300000 08300000
|
||||||
|
|||||||
Reference in New Issue
Block a user