[lld][WebAssembly] Fix __start/__stop symbols when combining input segments

We should be generating one __start/__stop pair per output segment
not per input segment.  The test wasn't catching this because it was
only linking a single object file.

Fixes PR41565

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

llvm-svn: 365308
diff --git a/lld/test/wasm/Inputs/explicit-section.ll b/lld/test/wasm/Inputs/explicit-section.ll
new file mode 100644
index 0000000..6d3e66a
--- /dev/null
+++ b/lld/test/wasm/Inputs/explicit-section.ll
@@ -0,0 +1,4 @@
+target triple = "wasm32-unknown-unknown"
+
+@var1 = global i32 42, section "mysection", align 4
+@var2 = global i32 43, section "mysection", align 4
diff --git a/lld/test/wasm/startstop.ll b/lld/test/wasm/startstop.ll
index f83d1ac..6339460 100644
--- a/lld/test/wasm/startstop.ll
+++ b/lld/test/wasm/startstop.ll
@@ -1,5 +1,6 @@
 ; RUN: llc -filetype=obj -o %t.o %s
-; RUN: wasm-ld --no-gc-sections %t.o -o %t.wasm
+; RUN: llc -filetype=obj %p/Inputs/explicit-section.ll -o %t2.o
+; RUN: wasm-ld --export=get_start --export=get_end --export=foo --export=var1 %t.o %t2.o -o %t.wasm
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
 target triple = "wasm32-unknown-unknown"
@@ -26,15 +27,12 @@
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:          []
-; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:         Body:            4180888080000B
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Locals:          []
-; CHECK-NEXT:         Body:            4180888080000B
+; CHECK-NEXT:         Body:            4190888080000B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:          []
-; CHECK-NEXT:         Body:            4188888080000B
-; CHECK-NEXT:       - Index:           3
-; CHECK-NEXT:         Locals:          []
 ; CHECK-NEXT:         Body:            0B
 ; CHECK-NEXT:   - Type:            DATA
 ; CHECK-NEXT:     Segments:
@@ -43,15 +41,13 @@
 ; CHECK-NEXT:         Offset:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           1024
-; CHECK-NEXT:         Content:         '0300000004000000'
+; CHECK-NEXT:         Content:         03000000040000002A0000002B000000
 ; CHECK-NEXT:   - Type:            CUSTOM
 ; CHECK-NEXT:     Name:            name
 ; CHECK-NEXT:     FunctionNames:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Name:            __wasm_call_ctors
-; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Name:            get_start
-; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         Name:            get_end
-; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Name:            _start
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index efb8d31..cb62f96 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -107,8 +107,10 @@
   for (const WasmRelocation &Rel : Relocations) {
     uint8_t *Loc = Buf + Rel.Offset + Off;
     uint32_t Value = File->calcNewValue(Rel);
-    LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(Rel.Type)
-                      << " addend=" << Rel.Addend << " index=" << Rel.Index
+    LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(Rel.Type));
+    if (Rel.Type != R_WASM_TYPE_INDEX_LEB)
+      LLVM_DEBUG(dbgs() << " sym=" << File->getSymbols()[Rel.Index]->getName());
+    LLVM_DEBUG(dbgs() << " addend=" << Rel.Addend << " index=" << Rel.Index
                       << " value=" << Value << " offset=" << Rel.Offset
                       << "\n");
 
diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 74d3132..aab3724 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -228,6 +228,7 @@
   LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n");
   auto *rtn = replaceSymbol<DefinedData>(S, Name, Flags);
   rtn->setVirtualAddress(Value);
+  rtn->Referenced = true;
   return rtn;
 }
 
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index 128ea93..cb46913 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -131,9 +131,10 @@
   uint32_t OutputSymbolIndex = INVALID_INDEX;
   uint32_t GOTIndex = INVALID_INDEX;
   Kind SymbolKind;
-  bool Referenced : 1;
 
 public:
+  bool Referenced : 1;
+
   // True if the symbol was used for linking and thus need to be added to the
   // output file's symbol table. This is true for all symbols except for
   // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 09a1430..cbf173e 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -74,7 +74,6 @@
   void addSection(OutputSection *Sec);
 
   void addSections();
-  void addStartStopSymbols(const InputSegment *Seg);
 
   void createCustomSections();
   void createSyntheticSections();
@@ -303,15 +302,15 @@
 // __stop_<secname> symbols. They are at beginning and end of the section,
 // respectively. This is not requested by the ELF standard, but GNU ld and
 // gold provide the feature, and used by many programs.
-void Writer::addStartStopSymbols(const InputSegment *Seg) {
-  StringRef S = Seg->getName();
-  LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << S << "\n");
-  if (!isValidCIdentifier(S))
+static void addStartStopSymbols(const OutputSegment *Seg) {
+  StringRef Name = Seg->Name;
+  LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << Name << "\n");
+  if (!isValidCIdentifier(Name))
     return;
-  uint32_t Start = Seg->OutputSeg->StartVA + Seg->OutputSegmentOffset;
-  uint32_t Stop = Start + Seg->getSize();
-  Symtab->addOptionalDataSymbol(Saver.save("__start_" + S), Start);
-  Symtab->addOptionalDataSymbol(Saver.save("__stop_" + S), Stop);
+  uint32_t Start = Seg->StartVA;
+  uint32_t Stop = Start + Seg->Size;
+  Symtab->addOptionalDataSymbol(Saver.save("__start_" + Name), Start);
+  Symtab->addOptionalDataSymbol(Saver.save("__stop_" + Name), Stop);
 }
 
 void Writer::addSections() {
@@ -811,8 +810,7 @@
     // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
     // This has to be done after memory layout is performed.
     for (const OutputSegment *Seg : Segments)
-      for (const InputSegment *S : Seg->InputSegments)
-        addStartStopSymbols(S);
+      addStartStopSymbols(Seg);
   }
 
   log("-- scanRelocations");