[lld] 875ee93 - [lld][WebAssembly] Handle TLS symbols in older object file

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 27 17:27:16 PST 2022


Author: Sam Clegg
Date: 2022-01-27T17:27:09-08:00
New Revision: 875ee937ae7c6588e0476edd15cf75185e70ac68

URL: https://github.com/llvm/llvm-project/commit/875ee937ae7c6588e0476edd15cf75185e70ac68
DIFF: https://github.com/llvm/llvm-project/commit/875ee937ae7c6588e0476edd15cf75185e70ac68.diff

LOG: [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: https://github.com/emscripten-core/emscripten/issues/15891

Differential Revision: https://reviews.llvm.org/D118414

Added: 
    lld/test/wasm/tls-implicit.yaml

Modified: 
    lld/wasm/InputChunks.h
    lld/wasm/InputFiles.cpp
    llvm/lib/ObjectYAML/WasmEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/tls-implicit.yaml b/lld/test/wasm/tls-implicit.yaml
new file mode 100644
index 0000000000000..13a1b382f96dc
--- /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
index ed86662e75692..73c5f4fb1f890 100644
--- a/lld/wasm/InputChunks.h
+++ b/lld/wasm/InputChunks.h
@@ -108,15 +108,11 @@ class InputChunk {
   // 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<uint8_t> data() const { return rawData; }
   uint64_t getTombstone() const;
 

diff  --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 3e3b31ab1ee5e..0758bb922a3bc 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -469,19 +469,17 @@ void ObjFile::parse(bool ignoreComdats) {
   // Populate `Segments`.
   for (const WasmSegment &s : wasmObj->dataSegments()) {
     InputChunk *seg;
-    if (shouldMerge(s)) {
+    if (shouldMerge(s))
       seg = make<MergeInputChunk>(s, this);
-    } else
+    else
       seg = make<InputSegment>(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 @@ Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
     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<DefinedData>(name, flags, this, seg, offset, size);
     if (seg->discarded)

diff  --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp
index 80a8c56f69122..2aa2ef3e55417 100644
--- a/llvm/lib/ObjectYAML/WasmEmitter.cpp
+++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp
@@ -585,19 +585,8 @@ void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
     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;
-    }
   }
 }
 


        


More information about the llvm-commits mailing list