[lld-macho] Sibling N_SO symbols must have the empty string

We had been giving them a string index of zero, which actually corresponds to a
string with a single space due to {D89639}.

This was far from obvious in the old test because llvm-nm doesn't quote the
symbol names, making the empty string look identical to a string of a single
space. `dsymutil -s` quotes its strings, so I've changed the test accordingly.

Fixes llvm.org/PR48714. Thanks @clayborg for the tips!

Reviewed By: clayborg

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

GitOrigin-RevId: 982e3c05108b606701d99d43098331357d9dd0ca
diff --git a/MachO/SyntheticSections.h b/MachO/SyntheticSections.h
index 632a8ba..cf9e2ca 100644
--- a/MachO/SyntheticSections.h
+++ b/MachO/SyntheticSections.h
@@ -379,9 +379,12 @@
   uint64_t getRawSize() const override { return size; }
   void writeTo(uint8_t *buf) const override;
 
+  static constexpr size_t emptyStringIndex = 1;
+
 private:
   // ld64 emits string tables which start with a space and a zero byte. We
   // match its behavior here since some tools depend on it.
+  // Consequently, the empty string will be at index 1, not zero.
   std::vector<StringRef> strings{" "};
   size_t size = 2;
 };
@@ -393,7 +396,7 @@
 
 struct StabsEntry {
   uint8_t type = 0;
-  uint32_t strx = 0;
+  uint32_t strx = StringTableSection::emptyStringIndex;
   uint8_t sect = 0;
   uint16_t desc = 0;
   uint64_t value = 0;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b254390..6bf0435 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -29,9 +29,9 @@
 set(LLD_TEST_DEPS lld)
 if (NOT LLD_BUILT_STANDALONE)
   list(APPEND LLD_TEST_DEPS
-    FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-cvtres
-    llvm-dis llvm-dwarfdump llvm-lib llvm-lipo llvm-mc llvm-nm llvm-objcopy
-    llvm-objdump llvm-pdbutil llvm-readelf llvm-readobj llvm-strip
+    FileCheck count dsymutil llc llvm-ar llvm-as llvm-bcanalyzer llvm-config
+    llvm-cvtres llvm-dis llvm-dwarfdump llvm-lib llvm-lipo llvm-mc llvm-nm
+    llvm-objcopy llvm-objdump llvm-pdbutil llvm-readelf llvm-readobj llvm-strip
     llvm-symbolizer not obj2yaml opt split-file yaml2obj
     )
 endif()
diff --git a/test/MachO/stabs.s b/test/MachO/stabs.s
index cf6f3ac..65d447b 100644
--- a/test/MachO/stabs.s
+++ b/test/MachO/stabs.s
@@ -10,23 +10,23 @@
 # RUN: llvm-ar rcsU %t/foo.a %t/foo.o
 
 # RUN: %lld -lSystem %t/test.o %t/foo.o %t/no-debug.o -o %t/test
-# RUN: (llvm-objdump --section-headers %t/test; llvm-nm -pa %t/test) | \
+# RUN: (llvm-objdump --section-headers %t/test; dsymutil -s %t/test) | \
 # RUN:   FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o
 
 ## Check that we emit the right modtime even when the object file is in an
 ## archive.
 # RUN: %lld -lSystem %t/test.o %t/foo.a %t/no-debug.o -o %t/test
-# RUN: (llvm-objdump --section-headers %t/test; llvm-nm -pa %t/test) | \
+# RUN: (llvm-objdump --section-headers %t/test; dsymutil -s %t/test) | \
 # RUN:   FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\)
 
 ## Check that we emit absolute paths to the object files in our OSO entries
 ## even if our inputs are relative paths.
 # RUN: cd %t && %lld -lSystem test.o foo.o no-debug.o -o test
-# RUN: (llvm-objdump --section-headers %t/test; llvm-nm -pa %t/test) | \
+# RUN: (llvm-objdump --section-headers %t/test; dsymutil -s %t/test) | \
 # RUN:   FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.o
 
 # RUN: cd %t && %lld -lSystem test.o foo.a no-debug.o -o %t/test
-# RUN: (llvm-objdump --section-headers %t/test; llvm-nm -pa %t/test) | \
+# RUN: (llvm-objdump --section-headers %t/test; dsymutil -s %t/test) | \
 # RUN:   FileCheck %s -DDIR=%t -DFOO_PATH=%t/foo.a\(foo.o\)
 
 # CHECK:       Sections:
@@ -37,46 +37,48 @@
 # CHECK-NEXT:  [[#COMM_ID:]]      __common
 # CHECK-NEXT:  [[#MORE_TEXT_ID:]] more_text
 
-# CHECK:       0000000000000000 - 00                     0000    SO /tmp/test.cpp
-# CHECK-NEXT:  0000000000000010 - 03                     0001   OSO [[DIR]]/test.o
-# CHECK-NEXT:  [[#%x, STATIC:]] - 0[[#MORE_DATA_ID + 1]] 0000 STSYM _static_var
-# CHECK-NEXT:  [[#%x, MAIN:]]   - 0[[#TEXT_ID + 1]]      0000   FUN _main
-# CHECK-NEXT:  0000000000000006 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, BAR:]]    - 0[[#TEXT_ID + 1]]      0000   FUN _bar
-# CHECK-NEXT:  0000000000000000 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, BAR2:]]   - 0[[#TEXT_ID + 1]]      0000   FUN _bar2
-# CHECK-NEXT:  0000000000000001 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, BAZ:]]    - 0[[#TEXT_ID + 1]]      0000   FUN _baz
-# CHECK-NEXT:  0000000000000000 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, BAZ2:]]   - 0[[#TEXT_ID + 1]]      0000   FUN _baz
-# CHECK-NEXT:  0000000000000002 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, QUX:]]    - 0[[#TEXT_ID + 1]]      0000   FUN _qux
-# CHECK-NEXT:  0000000000000003 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, QUUX:]]   - 0[[#TEXT_ID + 1]]      0000   FUN _quux
-# CHECK-NEXT:  0000000000000004 - 00                     0000   FUN
-# CHECK-NEXT:  [[#%x, GLOB:]]   - 0[[#DATA_ID + 1]]      0000  GSYM _global_var
-# CHECK-NEXT:  [[#%x, ZERO:]]   - 0[[#COMM_ID + 1]]      0000  GSYM _zero
-# CHECK-NEXT:  [[#%x, FUN:]]    - 0[[#MORE_TEXT_ID + 1]] 0000   FUN _fun
-# CHECK-NEXT:  0000000000000001 - 00                     0000   FUN
-# CHECK-NEXT:  0000000000000000 - 01                     0000    SO
-# CHECK-NEXT:  0000000000000000 - 00                     0000    SO /foo.cpp
-# CHECK-NEXT:  0000000000000020 - 03                     0001   OSO [[FOO_PATH]]
-# CHECK-NEXT:  [[#%x, FOO:]]    - 0[[#TEXT_ID + 1]]      0000   FUN _foo
-# CHECK-NEXT:  0000000000000001 - 00                     0000   FUN
-# CHECK-NEXT:  0000000000000000 - 01                     0000    SO
-# CHECK-DAG:   [[#STATIC]]      s _static_var
-# CHECK-DAG:   [[#MAIN]]        T _main
-# CHECK-DAG:   {{[0-9af]+}}     A _abs
-# CHECK-DAG:   [[#BAR]]         T _bar
-# CHECK-DAG:   [[#BAR2]]        T _bar2
-# CHECK-DAG:   [[#BAZ]]         T _baz
-# CHECK-DAG:   [[#BAZ2]]        T _baz2
-# CHECK-DAG:   [[#FUN]]         S _fun
-# CHECK-DAG:   [[#GLOB]]        D _global_var
-# CHECK-DAG:   [[#ZERO]]        S _zero
-# CHECK-DAG:   [[#FOO]]         T _foo
-# CHECK-DAG:   {{[0-9af]+}}     T _no_debug
-# CHECK-DAG:   {{0+}}           A __mh_execute_header
+# CHECK:      (N_SO         ) 00                         0000   0000000000000000   '/tmp/test.cpp'
+# CHECK-NEXT: (N_OSO        ) 03                         0001   0000000000000010   '[[DIR]]/test.o'
+# CHECK-NEXT: (N_STSYM      ) [[#%.2d,MORE_DATA_ID + 1]] 0000   [[#%.16x,STATIC:]] '_static_var'
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,MAIN:]]   '_main'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000006{{$}}
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,BAR:]]    '_bar'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000000{{$}}
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,BAR2:]]   '_bar2'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000001{{$}}
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,BAZ:]]    '_baz'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000000{{$}}
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,BAZ2:]]   '_baz2'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000002{{$}}
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,QUX:]]    '_qux'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000003{{$}}
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,QUUX:]]   '_quux'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000004{{$}}
+# CHECK-NEXT: (N_GSYM       ) [[#%.2d,DATA_ID + 1]]      0000   [[#%.16x,GLOB:]]   '_global_var'
+# CHECK-NEXT: (N_GSYM       ) [[#%.2d,COMM_ID + 1]]      0000   [[#%.16x,ZERO:]]   '_zero'
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,MORE_TEXT_ID + 1]] 0000   [[#%.16x,FUN:]]    '_fun'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000001{{$}}
+# CHECK-NEXT: (N_SO         ) 01                         0000   0000000000000000{{$}}
+# CHECK-NEXT: (N_SO         ) 00                         0000   0000000000000000   '/foo.cpp'
+# CHECK-NEXT: (N_OSO        ) 03                         0001   0000000000000020   '[[FOO_PATH]]'
+# CHECK-NEXT: (N_FUN        ) [[#%.2d,TEXT_ID + 1]]      0000   [[#%.16x,FOO:]]    '_foo'
+# CHECK-NEXT: (N_FUN        ) 00                         0000   0000000000000001{{$}}
+# CHECK-NEXT: (N_SO         ) 01                         0000   0000000000000000{{$}}
+# CHECK-DAG:  (     SECT    ) [[#%.2d,MORE_DATA_ID + 1]] 0000   [[#STATIC]]        '_static_var'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#MAIN]]          '_main'
+# CHECK-DAG:  (     ABS  EXT) 00                         0000   {{[0-9af]+}}       '_abs'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#FOO]]           '_foo'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#BAR]]           '_bar'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#BAR2]]          '_bar2'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#BAZ]]           '_baz'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#BAZ2]]          '_baz2'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#QUX]]           '_qux'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   [[#QUUX]]          '_quux'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,DATA_ID + 1]]      0000   [[#GLOB]]          '_global_var'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,COMM_ID + 1]]      0000   [[#ZERO]]          '_zero'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,MORE_TEXT_ID + 1]] 0000   [[#FUN]]           '_fun'
+# CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   {{[0-9a-f]+}}      '_no_debug'
+# CHECK-DAG:  (       {{.*}}) {{[0-9]+}}                 0000   {{[0-9a-f]+}}      '__mh_execute_header'
 # CHECK-EMPTY:
 
 ## Check that we don't attempt to emit rebase opcodes for the debug sections