summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/test/wasm/signature-mismatch-unknown.ll19
-rw-r--r--lld/wasm/Driver.cpp2
-rw-r--r--lld/wasm/InputFiles.cpp34
-rw-r--r--lld/wasm/InputFiles.h9
-rw-r--r--lld/wasm/SymbolTable.cpp13
-rw-r--r--lld/wasm/SymbolTable.h3
-rw-r--r--lld/wasm/Symbols.h6
7 files changed, 65 insertions, 21 deletions
diff --git a/lld/test/wasm/signature-mismatch-unknown.ll b/lld/test/wasm/signature-mismatch-unknown.ll
new file mode 100644
index 00000000000..65bb31511d1
--- /dev/null
+++ b/lld/test/wasm/signature-mismatch-unknown.ll
@@ -0,0 +1,19 @@
+; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
+; RUN: llc -filetype=obj %s -o %t.main.o
+; RUN: wasm-ld --fatal-warnings -o %t.wasm %t.ret32.o %t.main.o
+; RUN: wasm-ld --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o
+
+target triple = "wasm32-unknown-unknown"
+
+; Function declartion with incorrect signature.
+declare dso_local void @ret32()
+
+; Simply taking the address of the function should *not* generate the
+; the signature mismatch warning.
+@ptr = dso_local global i8* bitcast (void ()* @ret32 to i8*), align 8
+
+define hidden void @_start() local_unnamed_addr {
+ %addr = load i32 ()*, i32 ()** bitcast (i8** @ptr to i32 ()**), align 8
+ call i32 %addr()
+ ret void
+}
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 4ac5aff2494..5d27ac4bec6 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -550,7 +550,7 @@ struct WrappedSymbol {
};
static Symbol *addUndefined(StringRef Name) {
- return Symtab->addUndefinedFunction(Name, "", "", 0, nullptr, nullptr);
+ return Symtab->addUndefinedFunction(Name, "", "", 0, nullptr, nullptr, false);
}
// Handles -wrap option.
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 185a865dcab..a9d6abff4ab 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -271,14 +271,16 @@ void ObjFile::parse(bool IgnoreComdats) {
}
}
- // Find the code and data sections. Wasm objects can have at most one code
- // and one data section.
uint32_t SectionIndex = 0;
+ SymbolIsCalledDirectly.resize(WasmObj->getNumberOfSymbols(), false);
for (const SectionRef &Sec : WasmObj->sections()) {
const WasmSection &Section = WasmObj->getWasmSection(Sec);
+ // Wasm objects can have at most one code and one data section.
if (Section.Type == WASM_SEC_CODE) {
+ assert(!CodeSection);
CodeSection = &Section;
} else if (Section.Type == WASM_SEC_DATA) {
+ assert(!DataSection);
DataSection = &Section;
} else if (Section.Type == WASM_SEC_CUSTOM) {
CustomSections.emplace_back(make<InputSection>(Section, this));
@@ -286,6 +288,11 @@ void ObjFile::parse(bool IgnoreComdats) {
CustomSectionsByIndex[SectionIndex] = CustomSections.back();
}
SectionIndex++;
+ // Scans relocations to dermine determine if a function symbol is called
+ // directly
+ for (const WasmRelocation &Reloc : Section.Relocations)
+ if (Reloc.Type == R_WASM_FUNCTION_INDEX_LEB)
+ SymbolIsCalledDirectly[Reloc.Index] = true;
}
TypeMap.resize(getWasmObj()->types().size());
@@ -326,10 +333,16 @@ void ObjFile::parse(bool IgnoreComdats) {
Symbols.reserve(WasmObj->getNumberOfSymbols());
for (const SymbolRef &Sym : WasmObj->symbols()) {
const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());
- if (Symbol *Sym = createDefined(WasmSym))
- Symbols.push_back(Sym);
- else
- Symbols.push_back(createUndefined(WasmSym));
+ if (WasmSym.isDefined()) {
+ // createDefined may fail if the symbol is comdat excluded in which case
+ // we fall back to creating an undefined symbol
+ if (Symbol *D = createDefined(WasmSym)) {
+ Symbols.push_back(D);
+ continue;
+ }
+ }
+ size_t Idx = Symbols.size();
+ Symbols.push_back(createUndefined(WasmSym, SymbolIsCalledDirectly[Idx]));
}
}
@@ -361,9 +374,6 @@ DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {
}
Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
- if (!Sym.isDefined())
- return nullptr;
-
StringRef Name = Sym.Info.Name;
uint32_t Flags = Sym.Info.Flags;
@@ -417,7 +427,7 @@ Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {
llvm_unreachable("unknown symbol kind");
}
-Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
+Symbol *ObjFile::createUndefined(const WasmSymbol &Sym, bool IsCalledDirectly) {
StringRef Name = Sym.Info.Name;
uint32_t Flags = Sym.Info.Flags;
@@ -425,7 +435,7 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
case WASM_SYMBOL_TYPE_FUNCTION:
return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName,
Sym.Info.ImportModule, Flags, this,
- Sym.Signature);
+ Sym.Signature, IsCalledDirectly);
case WASM_SYMBOL_TYPE_DATA:
return Symtab->addUndefinedData(Name, Flags, this);
case WASM_SYMBOL_TYPE_GLOBAL:
@@ -499,7 +509,7 @@ static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,
if (ObjSym.isUndefined() || ExcludedByComdat) {
if (ObjSym.isExecutable())
return Symtab->addUndefinedFunction(Name, Name, DefaultModule, Flags, &F,
- nullptr);
+ nullptr, true);
return Symtab->addUndefinedData(Name, Flags, &F);
}
diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h
index 7c8601e29f2..64ac208daa6 100644
--- a/lld/wasm/InputFiles.h
+++ b/lld/wasm/InputFiles.h
@@ -69,6 +69,13 @@ protected:
// List of all symbols referenced or defined by this file.
std::vector<Symbol *> Symbols;
+ // Bool for each symbol, true if called directly. This allows us to implement
+ // a weaker form of signature checking where undefined functions that are not
+ // called directly (i.e. only address taken) don't have to match the defined
+ // function's signature. We cannot do this for directly called functions
+ // because those signatures are checked at validation times.
+ // See https://bugs.llvm.org/show_bug.cgi?id=40412
+ std::vector<bool> SymbolIsCalledDirectly;
private:
const Kind FileKind;
@@ -138,7 +145,7 @@ public:
private:
Symbol *createDefined(const WasmSymbol &Sym);
- Symbol *createUndefined(const WasmSymbol &Sym);
+ Symbol *createUndefined(const WasmSymbol &Sym, bool IsCalledDirectly);
bool isExcludedByComdat(InputChunk *Chunk) const;
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 5328e9e7845..ae424749ffc 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -286,7 +286,11 @@ Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
return S;
}
- if (Function && !signatureMatches(ExistingFunction, &Function->Signature)) {
+ bool CheckSig = true;
+ if (auto UD = dyn_cast<UndefinedFunction>(ExistingFunction))
+ CheckSig = UD->IsCalledDirectly;
+
+ if (CheckSig && Function && !signatureMatches(ExistingFunction, &Function->Signature)) {
Symbol* Variant;
if (getFunctionVariant(S, &Function->Signature, File, &Variant))
// New variant, always replace
@@ -384,7 +388,8 @@ Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags,
Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName,
StringRef ImportModule,
uint32_t Flags, InputFile *File,
- const WasmSignature *Sig) {
+ const WasmSignature *Sig,
+ bool IsCalledDirectly) {
LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name <<
" [" << (Sig ? toString(*Sig) : "none") << "]\n");
@@ -396,7 +401,7 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName,
auto Replace = [&]() {
replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags,
- File, Sig);
+ File, Sig, IsCalledDirectly);
};
if (WasInserted)
@@ -409,7 +414,7 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName,
reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION);
return S;
}
- if (!signatureMatches(ExistingFunction, Sig))
+ if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig))
if (getFunctionVariant(S, Sig, File, &S))
Replace();
}
diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h
index d6cb13b43f8..8c96c616330 100644
--- a/lld/wasm/SymbolTable.h
+++ b/lld/wasm/SymbolTable.h
@@ -63,7 +63,8 @@ public:
Symbol *addUndefinedFunction(StringRef Name, StringRef ImportName,
StringRef ImportModule, uint32_t Flags,
- InputFile *File, const WasmSignature *Signature);
+ InputFile *File, const WasmSignature *Signature,
+ bool IsCalledDirectly);
Symbol *addUndefinedData(StringRef Name, uint32_t Flags, InputFile *File);
Symbol *addUndefinedGlobal(StringRef Name, StringRef ImportName,
StringRef ImportModule, uint32_t Flags,
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index 3691b3f48b4..98ff155fc5a 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -194,9 +194,10 @@ public:
UndefinedFunction(StringRef Name, StringRef ImportName,
StringRef ImportModule, uint32_t Flags,
InputFile *File = nullptr,
- const WasmSignature *Type = nullptr)
+ const WasmSignature *Type = nullptr,
+ bool IsCalledDirectly = true)
: FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type),
- ImportName(ImportName), ImportModule(ImportModule) {}
+ ImportName(ImportName), ImportModule(ImportModule), IsCalledDirectly(IsCalledDirectly) {}
static bool classof(const Symbol *S) {
return S->kind() == UndefinedFunctionKind;
@@ -204,6 +205,7 @@ public:
StringRef ImportName;
StringRef ImportModule;
+ bool IsCalledDirectly;
};
// Section symbols for output sections are different from those for input
OpenPOWER on IntegriCloud