diff --git a/llvm/include/llvm/MC/MCWasmObjectWriter.h b/llvm/include/llvm/MC/MCWasmObjectWriter.h --- a/llvm/include/llvm/MC/MCWasmObjectWriter.h +++ b/llvm/include/llvm/MC/MCWasmObjectWriter.h @@ -15,6 +15,7 @@ namespace llvm { class MCFixup; +class MCSectionWasm; class MCValue; class raw_pwrite_stream; @@ -34,6 +35,7 @@ } virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + const MCSectionWasm &FixupSection, bool IsLocRel) const = 0; /// \name Accessors diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -497,20 +497,31 @@ // LLVM expects wrapping, in contrast to wasm's immediates which can't // be negative and don't wrap. FixedValue = 0; - - unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup, IsLocRel); + errs() << "FixupSection " << FixupSection.getName() << "\n"; + errs() << " sym " << *SymA << " "; + errs() << (SymA->isData() ? "data\n" + : SymA->isSection() ? "section\n" + : SymA->isGlobal() ? "global\n" + : SymA->isFunction() ? "function\n" + : SymA->isTable() ? "table\n" + : "???\n"); + //<< SymA->getType().getValue() << "\n"; + unsigned Type = + TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel); // Absolute offset within a section or a function. // Currently only supported for for metadata sections. // See: test/MC/WebAssembly/blockaddress.ll - if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || - Type == wasm::R_WASM_FUNCTION_OFFSET_I64 || - Type == wasm::R_WASM_SECTION_OFFSET_I32) { + if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || + Type == wasm::R_WASM_FUNCTION_OFFSET_I64 || + Type == wasm::R_WASM_SECTION_OFFSET_I32) && + !SymA->isFunction()) { if (!FixupSection.getKind().isMetadata()) report_fatal_error("relocations for function or section offsets are " "only supported in metadata sections"); const MCSymbol *SectionSymbol = nullptr; + // Oh noes, fixup against an undefined symbol, with no section! const MCSection &SecA = SymA->getSection(); if (SecA.getKind().isText()) { auto SecSymIt = SectionFunctions.find(&SecA); @@ -620,6 +631,8 @@ case wasm::R_WASM_FUNCTION_OFFSET_I32: case wasm::R_WASM_FUNCTION_OFFSET_I64: case wasm::R_WASM_SECTION_OFFSET_I32: { + if (!RelEntry.Symbol->isInSection()) + return 0; const auto &Section = static_cast(RelEntry.Symbol->getSection()); return Section.getSectionOffset() + RelEntry.Addend; diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -35,6 +35,7 @@ private: unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, + const MCSectionWasm &FixupSection, bool IsLocRel) const override; }; } // end anonymous namespace @@ -43,7 +44,7 @@ bool IsEmscripten) : MCWasmObjectTargetWriter(Is64Bit, IsEmscripten) {} -static const MCSection *getFixupSection(const MCExpr *Expr) { +static const MCSection *getTargetSection(const MCExpr *Expr) { if (auto SyExp = dyn_cast(Expr)) { if (SyExp->getSymbol().isInSection()) return &SyExp->getSymbol().getSection(); @@ -51,20 +52,20 @@ } if (auto BinOp = dyn_cast(Expr)) { - auto SectionLHS = getFixupSection(BinOp->getLHS()); - auto SectionRHS = getFixupSection(BinOp->getRHS()); + auto SectionLHS = getTargetSection(BinOp->getLHS()); + auto SectionRHS = getTargetSection(BinOp->getRHS()); return SectionLHS == SectionRHS ? nullptr : SectionLHS; } if (auto UnOp = dyn_cast(Expr)) - return getFixupSection(UnOp->getSubExpr()); + return getTargetSection(UnOp->getSubExpr()); return nullptr; } -unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target, - const MCFixup &Fixup, - bool IsLocRel) const { +unsigned WebAssemblyWasmObjectWriter::getRelocType( + const MCValue &Target, const MCFixup &Fixup, + const MCSectionWasm &FixupSection, bool IsLocRel) const { const MCSymbolRefExpr *RefA = Target.getSymA(); assert(RefA); auto& SymA = cast(RefA->getSymbol()); @@ -89,7 +90,10 @@ default: break; } - + auto *fs = getTargetSection(Fixup.getValue()); + errs() << "inner TargetSection " << fs << "\n"; + if (fs) + errs() << " name " << fs->getName() << "\n"; switch (unsigned(Fixup.getKind())) { case WebAssembly::fixup_sleb128_i32: if (SymA.isFunction()) @@ -113,12 +117,16 @@ assert(SymA.isData()); return wasm::R_WASM_MEMORY_ADDR_LEB64; case FK_Data_4: - if (SymA.isFunction()) + if (SymA.isFunction()) { + if (FixupSection.getKind().isMetadata()) + return wasm::R_WASM_FUNCTION_OFFSET_I32; + assert(FixupSection.isWasmData()); return wasm::R_WASM_TABLE_INDEX_I32; + } if (SymA.isGlobal()) return wasm::R_WASM_GLOBAL_INDEX_I32; if (auto Section = static_cast( - getFixupSection(Fixup.getValue()))) { + getTargetSection(Fixup.getValue()))) { if (Section->getKind().isText()) return wasm::R_WASM_FUNCTION_OFFSET_I32; else if (!Section->isWasmData()) @@ -127,12 +135,15 @@ return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 : wasm::R_WASM_MEMORY_ADDR_I32; case FK_Data_8: - if (SymA.isFunction()) + if (SymA.isFunction()) { + if (FixupSection.getKind().isMetadata()) + return wasm::R_WASM_FUNCTION_OFFSET_I64; return wasm::R_WASM_TABLE_INDEX_I64; + } if (SymA.isGlobal()) llvm_unreachable("unimplemented R_WASM_GLOBAL_INDEX_I64"); if (auto Section = static_cast( - getFixupSection(Fixup.getValue()))) { + getTargetSection(Fixup.getValue()))) { if (Section->getKind().isText()) return wasm::R_WASM_FUNCTION_OFFSET_I64; else if (!Section->isWasmData())