summaryrefslogtreecommitdiffstats
path: root/lld/wasm/InputFiles.cpp
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2019-05-24 22:45:08 +0000
committerSam Clegg <sbc@chromium.org>2019-05-24 22:45:08 +0000
commit59f959ff333bf42962287957b51d0da285087e41 (patch)
tree513c1f708555b856fffe5824955237f53246aceb /lld/wasm/InputFiles.cpp
parentbede937b1678503215f7add86fb52aacefa280c3 (diff)
downloadbcm5719-llvm-59f959ff333bf42962287957b51d0da285087e41.tar.gz
bcm5719-llvm-59f959ff333bf42962287957b51d0da285087e41.zip
[WebAssembly] Relax signature checking for undefined functions that are not called directly
When function signatures don't match and the undefined function is not called directly (i.e. only has its address taken) we don't issue a warning or create a runtime thunk for the undefined function. Instead in this case we simply use the defined version of the function. This is possible since checking signatures of dynamic calls happens at runtime so any invalid usage will still result in a runtime error. This is needed to allow C++ programs to link without generating warnings. Its not uncommon in C++ for vtables to be populated by function address whee the signature of the function is not known in the compilation unit. In this case clang declares the method as void(void) and relies on the vtable caller casting the data back to the correct signature. Fixes: https://bugs.llvm.org/show_bug.cgi?id=40412 Differential Revision: https://reviews.llvm.org/D62153 llvm-svn: 361678
Diffstat (limited to 'lld/wasm/InputFiles.cpp')
-rw-r--r--lld/wasm/InputFiles.cpp34
1 files changed, 22 insertions, 12 deletions
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);
}
OpenPOWER on IntegriCloud