diff --git a/lld/test/wasm/tls-implicit.yaml b/lld/test/wasm/tls-implicit.yaml new file mode 100644 --- /dev/null +++ b/lld/test/wasm/tls-implicit.yaml @@ -0,0 +1,78 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: wasm-ld --shared-memory -o %t.wasm %t.o + +# Verify compatability with older object files that didn't mark individual +# symbols as TLS. In this case the symbol `bar` is being used in a TLS-only +# relocation (R_WASM_MEMORY_ADDR_TLS_SLEB) but is not itself marked as TLS. +# However, because it is defined in a section (`.mydata`) that *is* marked as +# TLS we implicitly mark bar as TLS. +# +# We had a regression where llvm-13-generated object files were being rejected +# with: "R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol" +# This test verifies that this error is not triggered. + +--- !WASM +FileHeader: + Version: 0x1 +Sections: + - Type: TYPE + Signatures: + - Index: 0 + ParamTypes: [] + ReturnTypes: [] + - Type: IMPORT + Imports: + - Module: env + Field: __linear_memory + Kind: MEMORY + Memory: + Minimum: 0x1 + - Type: FUNCTION + FunctionTypes: [ 0 ] + - Type: DATACOUNT + Count: 1 + - Type: CODE + Relocations: + - Type: R_WASM_MEMORY_ADDR_TLS_SLEB + Index: 1 + Offset: 0x4 + Functions: + - Index: 0 + Locals: [] + Body: 4180808080001A0B + - Type: DATA + Segments: + - SectionOffset: 6 + InitFlags: 0 + Offset: + Opcode: I32_CONST + Value: 0 + Content: '00000000' + - Type: CUSTOM + Name: linking + Version: 2 + SymbolTable: + - Index: 0 + Kind: FUNCTION + Name: _start + Flags: [ ] + Function: 0 + - Index: 1 + Kind: DATA + Name: bar + Flags: [ ] + Segment: 0 + Size: 4 + SegmentInfo: + - Index: 0 + Name: .mydata + Alignment: 0 + Flags: [ TLS ] + - Type: CUSTOM + Name: target_features + Features: + - Prefix: USED + Name: "atomics" + - Prefix: USED + Name: "bulk-memory" +... diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -108,15 +108,11 @@ // Signals the chunk was discarded by COMDAT handling. unsigned discarded : 1; - // Signals that the chuck was implicitly marked as TLS based on its name - // alone. This is a compatibility mechanism to support older object files. - unsigned implicitTLS : 1; - protected: InputChunk(ObjFile *f, Kind k, StringRef name, uint32_t alignment = 0, uint32_t flags = 0) : name(name), file(f), alignment(alignment), flags(flags), sectionKind(k), - live(!config->gcSections), discarded(false), implicitTLS(false) {} + live(!config->gcSections), discarded(false) {} ArrayRef data() const { return rawData; } uint64_t getTombstone() const; diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -469,19 +469,17 @@ // Populate `Segments`. for (const WasmSegment &s : wasmObj->dataSegments()) { InputChunk *seg; - if (shouldMerge(s)) { + if (shouldMerge(s)) seg = make(s, this); - } else + else seg = make(s, this); seg->discarded = isExcludedByComdat(seg); // Older object files did not include WASM_SEG_FLAG_TLS and instead // relied on the naming convention. To maintain compat with such objects // we still imply the TLS flag based on the name of the segment. if (!seg->isTLS() && - (seg->name.startswith(".tdata") || seg->name.startswith(".tbss"))) { + (seg->name.startswith(".tdata") || seg->name.startswith(".tbss"))) seg->flags |= WASM_SEG_FLAG_TLS; - seg->implicitTLS = true; - } segments.emplace_back(seg); } setRelocs(segments, dataSection); @@ -581,9 +579,11 @@ InputChunk *seg = segments[sym.Info.DataRef.Segment]; auto offset = sym.Info.DataRef.Offset; auto size = sym.Info.DataRef.Size; - if (seg->implicitTLS) { + // Support older (e.g. llvm 13) object files that pre-date the per-symbol + // TLS flag, and symbols were assumed to be TLS by being defined in a TLS + // segment. + if (!(flags & WASM_SYMBOL_TLS) && seg->isTLS()) flags |= WASM_SYMBOL_TLS; - } if (sym.isBindingLocal()) return make(name, flags, this, seg, offset, size); if (seg->discarded) diff --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp --- a/llvm/lib/ObjectYAML/WasmEmitter.cpp +++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp @@ -585,19 +585,8 @@ writeUint8(OS, Reloc.Type); encodeULEB128(Reloc.Offset, OS); encodeULEB128(Reloc.Index, OS); - switch (Reloc.Type) { - case wasm::R_WASM_MEMORY_ADDR_LEB: - case wasm::R_WASM_MEMORY_ADDR_LEB64: - case wasm::R_WASM_MEMORY_ADDR_SLEB: - case wasm::R_WASM_MEMORY_ADDR_SLEB64: - case wasm::R_WASM_MEMORY_ADDR_I32: - case wasm::R_WASM_MEMORY_ADDR_I64: - case wasm::R_WASM_FUNCTION_OFFSET_I32: - case wasm::R_WASM_FUNCTION_OFFSET_I64: - case wasm::R_WASM_SECTION_OFFSET_I32: + if (wasm::relocTypeHasAddend(Reloc.Type)) encodeSLEB128(Reloc.Addend, OS); - break; - } } }