[wasm-ld] Add __global_base symbol to mark the value of --global-base

Summary:
This is needed for address sanitizer on Emscripten. As everything in
memory starts at the value passed to --global-base, everything before
that can be used as shadow memory.

This symbol is added so that the library for the ASan runtime can know
where the shadow memory ends and real memory begins.

This is split from D63742.

Reviewers: tlively, aheejin, sbc100

Subscribers: sunfish, llvm-commits

Tags: #llvm

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

llvm-svn: 364467
diff --git a/lld/test/wasm/global-base.test b/lld/test/wasm/global-base.test
new file mode 100644
index 0000000..07c8d63
--- /dev/null
+++ b/lld/test/wasm/global-base.test
@@ -0,0 +1,71 @@
+RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.o
+
+RUN: wasm-ld --export=__global_base --export=__data_end --allow-undefined -o %t.wasm %t.o
+RUN: obj2yaml %t.wasm | FileCheck %s  -check-prefix=CHECK-1024
+CHECK-1024:       - Type:            GLOBAL
+CHECK-1024-NEXT:    Globals:
+CHECK-1024-NEXT:      - Index:           0
+CHECK-1024-NEXT:        Type:            I32
+CHECK-1024-NEXT:        Mutable:         true
+CHECK-1024-NEXT:        InitExpr:
+CHECK-1024-NEXT:          Opcode:          I32_CONST
+CHECK-1024-NEXT:          Value:           66560
+CHECK-1024-NEXT:      - Index:           1
+CHECK-1024-NEXT:        Type:            I32
+CHECK-1024-NEXT:        Mutable:         false
+CHECK-1024-NEXT:        InitExpr:
+CHECK-1024-NEXT:          Opcode:          I32_CONST
+CHECK-1024-NEXT:          Value:           1024
+CHECK-1024-NEXT:      - Index:           2
+CHECK-1024-NEXT:        Type:            I32
+CHECK-1024-NEXT:        Mutable:         false
+CHECK-1024-NEXT:        InitExpr:
+CHECK-1024-NEXT:          Opcode:          I32_CONST
+CHECK-1024-NEXT:          Value:           1024
+
+CHECK-1024:       - Type:            EXPORT
+CHECK-1024-NEXT:    Exports:
+CHECK-1024-NEXT:      - Name:            memory
+CHECK-1024-NEXT:        Kind:            MEMORY
+CHECK-1024-NEXT:        Index:           0
+CHECK-1024-NEXT:      - Name:            __data_end
+CHECK-1024-NEXT:        Kind:            GLOBAL
+CHECK-1024-NEXT:        Index:           1
+CHECK-1024-NEXT:      - Name:            __global_base
+CHECK-1024-NEXT:        Kind:            GLOBAL
+CHECK-1024-NEXT:        Index:           2
+
+RUN: wasm-ld --export=__global_base --export=__data_end --allow-undefined --global-base=16777216 -o %t.wasm %t.o
+RUN: obj2yaml %t.wasm | FileCheck %s  -check-prefix=CHECK-16777216
+CHECK-16777216:       - Type:            GLOBAL
+CHECK-16777216-NEXT:    Globals:
+CHECK-16777216-NEXT:      - Index:           0
+CHECK-16777216-NEXT:        Type:            I32
+CHECK-16777216-NEXT:        Mutable:         true
+CHECK-16777216-NEXT:        InitExpr:
+CHECK-16777216-NEXT:          Opcode:          I32_CONST
+CHECK-16777216-NEXT:          Value:           16842752
+CHECK-16777216-NEXT:      - Index:           1
+CHECK-16777216-NEXT:        Type:            I32
+CHECK-16777216-NEXT:        Mutable:         false
+CHECK-16777216-NEXT:        InitExpr:
+CHECK-16777216-NEXT:          Opcode:          I32_CONST
+CHECK-16777216-NEXT:          Value:           16777216
+CHECK-16777216-NEXT:      - Index:           2
+CHECK-16777216-NEXT:        Type:            I32
+CHECK-16777216-NEXT:        Mutable:         false
+CHECK-16777216-NEXT:        InitExpr:
+CHECK-16777216-NEXT:          Opcode:          I32_CONST
+CHECK-16777216-NEXT:          Value:           16777216
+
+CHECK-16777216:       - Type:            EXPORT
+CHECK-16777216-NEXT:    Exports:
+CHECK-16777216-NEXT:      - Name:            memory
+CHECK-16777216-NEXT:        Kind:            MEMORY
+CHECK-16777216-NEXT:        Index:           0
+CHECK-16777216-NEXT:      - Name:            __data_end
+CHECK-16777216-NEXT:        Kind:            GLOBAL
+CHECK-16777216-NEXT:        Index:           1
+CHECK-16777216-NEXT:      - Name:            __global_base
+CHECK-16777216-NEXT:        Kind:            GLOBAL
+CHECK-16777216-NEXT:        Index:           2
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 2b9dd3c..6c5c72d 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -490,6 +490,7 @@
     WasmSym::StackPointer = Symtab->addSyntheticGlobal(
         "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
     WasmSym::DataEnd = Symtab->addOptionalDataSymbol("__data_end");
+    WasmSym::GlobalBase = Symtab->addOptionalDataSymbol("__global_base");
     WasmSym::HeapBase = Symtab->addOptionalDataSymbol("__heap_base");
   }
 
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index 284fafd..d6efc36 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -28,6 +28,7 @@
 DefinedFunction *WasmSym::ApplyRelocs;
 DefinedData *WasmSym::DsoHandle;
 DefinedData *WasmSym::DataEnd;
+DefinedData *WasmSym::GlobalBase;
 DefinedData *WasmSym::HeapBase;
 GlobalSymbol *WasmSym::StackPointer;
 UndefinedGlobal *WasmSym::TableBase;
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index 5c0f4b2..5a34035 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -415,6 +415,10 @@
 
 // linker-generated symbols
 struct WasmSym {
+  // __global_base
+  // Symbol marking the start of the global section.
+  static DefinedData *GlobalBase;
+
   // __stack_pointer
   // Global that holds the address of the top of the explicit value stack in
   // linear memory.
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 43a8c8d..7c91eac 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -224,6 +224,9 @@
     log("mem: global base = " + Twine(Config->GlobalBase));
   }
 
+  if (WasmSym::GlobalBase)
+    WasmSym::GlobalBase->setVirtualAddress(Config->GlobalBase);
+
   uint32_t DataStart = MemoryPtr;
 
   // Arbitrarily set __dso_handle handle to point to the start of the data