Skip to content

Commit 875ee93

Browse files
committed
[lld][WebAssembly] Handle TLS symbols in older object file
In older versions of llvm (e.g. llvm 13), symbols were not individually flagged as TLS. In this case, the indent was to implicitly mark any symbols defined in TLS segments as TLS. However, we were not performing this implicit conversion if the segment was explicitly marked as TLS As it happens, llvm 13 was branched between the addition of the segment flag and the addition of the symbol flag. See: - segment flag added: https://reviews.llvm.org/D102202 - symbol flag added: https://reviews.llvm.org/D109426 Testing this is tricky because the assembler will imply the TLS status of the symbol based on the segment its declared in, so we are forced to use a yaml file here. Fixes: emscripten-core/emscripten#15891 Differential Revision: https://reviews.llvm.org/D118414
1 parent 35ece3b commit 875ee93

File tree

4 files changed

+87
-24
lines changed

4 files changed

+87
-24
lines changed

lld/test/wasm/tls-implicit.yaml

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# RUN: yaml2obj %s -o %t.o
2+
# RUN: wasm-ld --shared-memory -o %t.wasm %t.o
3+
4+
# Verify compatability with older object files that didn't mark individual
5+
# symbols as TLS. In this case the symbol `bar` is being used in a TLS-only
6+
# relocation (R_WASM_MEMORY_ADDR_TLS_SLEB) but is not itself marked as TLS.
7+
# However, because it is defined in a section (`.mydata`) that *is* marked as
8+
# TLS we implicitly mark bar as TLS.
9+
#
10+
# We had a regression where llvm-13-generated object files were being rejected
11+
# with: "R_WASM_MEMORY_ADDR_TLS_SLEB cannot be used against non-TLS symbol"
12+
# This test verifies that this error is not triggered.
13+
14+
--- !WASM
15+
FileHeader:
16+
Version: 0x1
17+
Sections:
18+
- Type: TYPE
19+
Signatures:
20+
- Index: 0
21+
ParamTypes: []
22+
ReturnTypes: []
23+
- Type: IMPORT
24+
Imports:
25+
- Module: env
26+
Field: __linear_memory
27+
Kind: MEMORY
28+
Memory:
29+
Minimum: 0x1
30+
- Type: FUNCTION
31+
FunctionTypes: [ 0 ]
32+
- Type: DATACOUNT
33+
Count: 1
34+
- Type: CODE
35+
Relocations:
36+
- Type: R_WASM_MEMORY_ADDR_TLS_SLEB
37+
Index: 1
38+
Offset: 0x4
39+
Functions:
40+
- Index: 0
41+
Locals: []
42+
Body: 4180808080001A0B
43+
- Type: DATA
44+
Segments:
45+
- SectionOffset: 6
46+
InitFlags: 0
47+
Offset:
48+
Opcode: I32_CONST
49+
Value: 0
50+
Content: '00000000'
51+
- Type: CUSTOM
52+
Name: linking
53+
Version: 2
54+
SymbolTable:
55+
- Index: 0
56+
Kind: FUNCTION
57+
Name: _start
58+
Flags: [ ]
59+
Function: 0
60+
- Index: 1
61+
Kind: DATA
62+
Name: bar
63+
Flags: [ ]
64+
Segment: 0
65+
Size: 4
66+
SegmentInfo:
67+
- Index: 0
68+
Name: .mydata
69+
Alignment: 0
70+
Flags: [ TLS ]
71+
- Type: CUSTOM
72+
Name: target_features
73+
Features:
74+
- Prefix: USED
75+
Name: "atomics"
76+
- Prefix: USED
77+
Name: "bulk-memory"
78+
...

lld/wasm/InputChunks.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,11 @@ class InputChunk {
108108
// Signals the chunk was discarded by COMDAT handling.
109109
unsigned discarded : 1;
110110

111-
// Signals that the chuck was implicitly marked as TLS based on its name
112-
// alone. This is a compatibility mechanism to support older object files.
113-
unsigned implicitTLS : 1;
114-
115111
protected:
116112
InputChunk(ObjFile *f, Kind k, StringRef name, uint32_t alignment = 0,
117113
uint32_t flags = 0)
118114
: name(name), file(f), alignment(alignment), flags(flags), sectionKind(k),
119-
live(!config->gcSections), discarded(false), implicitTLS(false) {}
115+
live(!config->gcSections), discarded(false) {}
120116
ArrayRef<uint8_t> data() const { return rawData; }
121117
uint64_t getTombstone() const;
122118

lld/wasm/InputFiles.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -469,19 +469,17 @@ void ObjFile::parse(bool ignoreComdats) {
469469
// Populate `Segments`.
470470
for (const WasmSegment &s : wasmObj->dataSegments()) {
471471
InputChunk *seg;
472-
if (shouldMerge(s)) {
472+
if (shouldMerge(s))
473473
seg = make<MergeInputChunk>(s, this);
474-
} else
474+
else
475475
seg = make<InputSegment>(s, this);
476476
seg->discarded = isExcludedByComdat(seg);
477477
// Older object files did not include WASM_SEG_FLAG_TLS and instead
478478
// relied on the naming convention. To maintain compat with such objects
479479
// we still imply the TLS flag based on the name of the segment.
480480
if (!seg->isTLS() &&
481-
(seg->name.startswith(".tdata") || seg->name.startswith(".tbss"))) {
481+
(seg->name.startswith(".tdata") || seg->name.startswith(".tbss")))
482482
seg->flags |= WASM_SEG_FLAG_TLS;
483-
seg->implicitTLS = true;
484-
}
485483
segments.emplace_back(seg);
486484
}
487485
setRelocs(segments, dataSection);
@@ -581,9 +579,11 @@ Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
581579
InputChunk *seg = segments[sym.Info.DataRef.Segment];
582580
auto offset = sym.Info.DataRef.Offset;
583581
auto size = sym.Info.DataRef.Size;
584-
if (seg->implicitTLS) {
582+
// Support older (e.g. llvm 13) object files that pre-date the per-symbol
583+
// TLS flag, and symbols were assumed to be TLS by being defined in a TLS
584+
// segment.
585+
if (!(flags & WASM_SYMBOL_TLS) && seg->isTLS())
585586
flags |= WASM_SYMBOL_TLS;
586-
}
587587
if (sym.isBindingLocal())
588588
return make<DefinedData>(name, flags, this, seg, offset, size);
589589
if (seg->discarded)

llvm/lib/ObjectYAML/WasmEmitter.cpp

+1-12
Original file line numberDiff line numberDiff line change
@@ -585,19 +585,8 @@ void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
585585
writeUint8(OS, Reloc.Type);
586586
encodeULEB128(Reloc.Offset, OS);
587587
encodeULEB128(Reloc.Index, OS);
588-
switch (Reloc.Type) {
589-
case wasm::R_WASM_MEMORY_ADDR_LEB:
590-
case wasm::R_WASM_MEMORY_ADDR_LEB64:
591-
case wasm::R_WASM_MEMORY_ADDR_SLEB:
592-
case wasm::R_WASM_MEMORY_ADDR_SLEB64:
593-
case wasm::R_WASM_MEMORY_ADDR_I32:
594-
case wasm::R_WASM_MEMORY_ADDR_I64:
595-
case wasm::R_WASM_FUNCTION_OFFSET_I32:
596-
case wasm::R_WASM_FUNCTION_OFFSET_I64:
597-
case wasm::R_WASM_SECTION_OFFSET_I32:
588+
if (wasm::relocTypeHasAddend(Reloc.Type))
598589
encodeSLEB128(Reloc.Addend, OS);
599-
break;
600-
}
601590
}
602591
}
603592

0 commit comments

Comments
 (0)