[lld-macho] Support -no_function_starts

Pretty simple code-wise. Also threw in some refactoring:

* Put the functionStartSection under Writer instead of InStruct, since
  it doesn't need to be accessed outside of Writer
* Adjusted the test to put all files under the temp dir instead of at
  the top-level
* Added some CHECK-LABELs to make it clearer where the function starts
  data is

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

GitOrigin-RevId: 45cdceb40c5655618e3f0865e7056414bd001079
diff --git a/MachO/Config.h b/MachO/Config.h
index 60c20a3..c9c41a4 100644
--- a/MachO/Config.h
+++ b/MachO/Config.h
@@ -81,6 +81,7 @@
   bool searchDylibsFirst = false;
   bool saveTemps = false;
   bool adhocCodesign = false;
+  bool emitFunctionStarts = false;
   bool timeTraceEnabled = false;
   uint32_t headerPad;
   uint32_t dylibCompatibilityVersion = 0;
diff --git a/MachO/Driver.cpp b/MachO/Driver.cpp
index 35f3ddf..86ae732 100644
--- a/MachO/Driver.cpp
+++ b/MachO/Driver.cpp
@@ -905,6 +905,7 @@
   config->forceLoadObjC = args.hasArg(OPT_ObjC);
   config->demangle = args.hasArg(OPT_demangle);
   config->implicitDylibs = !args.hasArg(OPT_no_implicit_dylibs);
+  config->emitFunctionStarts = !args.hasArg(OPT_no_function_starts);
 
   if (const Arg *arg = args.getLastArg(OPT_install_name)) {
     if (config->outputType != MH_DYLIB)
diff --git a/MachO/Options.td b/MachO/Options.td
index cdb8a46..c6e6121 100644
--- a/MachO/Options.td
+++ b/MachO/Options.td
@@ -866,8 +866,7 @@
     Flags<[HelpHidden]>,
     Group<grp_rare>;
 def no_function_starts : Flag<["-"], "no_function_starts">,
-    HelpText<"Do not creates a compressed table of function start addresses">,
-    Flags<[HelpHidden]>,
+    HelpText<"Do not create a table of function start addresses">,
     Group<grp_rare>;
 def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
     HelpText<"Do not merge Objective-C categories into their classes">,
diff --git a/MachO/SyntheticSections.h b/MachO/SyntheticSections.h
index 9286947..8674e54 100644
--- a/MachO/SyntheticSections.h
+++ b/MachO/SyntheticSections.h
@@ -488,7 +488,6 @@
   WeakBindingSection *weakBinding = nullptr;
   LazyBindingSection *lazyBinding = nullptr;
   ExportSection *exports = nullptr;
-  FunctionStartsSection *functionStarts = nullptr;
   GotSection *got = nullptr;
   TlvPointerSection *tlvPointers = nullptr;
   LazyPointerSection *lazyPointers = nullptr;
diff --git a/MachO/Writer.cpp b/MachO/Writer.cpp
index 9a28ade..38a6627 100644
--- a/MachO/Writer.cpp
+++ b/MachO/Writer.cpp
@@ -70,6 +70,8 @@
   IndirectSymtabSection *indirectSymtabSection = nullptr;
   CodeSignatureSection *codeSignatureSection = nullptr;
   UnwindInfoSection *unwindInfoSection = nullptr;
+  FunctionStartsSection *functionStartsSection = nullptr;
+
   LCUuid *uuidCommand = nullptr;
   OutputSegment *linkEditSegment = nullptr;
 };
@@ -122,8 +124,8 @@
 
 class LCFunctionStarts : public LoadCommand {
 public:
-  explicit LCFunctionStarts(FunctionStartsSection *functionStarts)
-      : functionStarts(functionStarts) {}
+  explicit LCFunctionStarts(FunctionStartsSection *functionStartsSection)
+      : functionStartsSection(functionStartsSection) {}
 
   uint32_t getSize() const override { return sizeof(linkedit_data_command); }
 
@@ -131,12 +133,12 @@
     auto *c = reinterpret_cast<linkedit_data_command *>(buf);
     c->cmd = LC_FUNCTION_STARTS;
     c->cmdsize = getSize();
-    c->dataoff = functionStarts->fileOff;
-    c->datasize = functionStarts->getFileSize();
+    c->dataoff = functionStartsSection->fileOff;
+    c->datasize = functionStartsSection->getFileSize();
   }
 
 private:
-  FunctionStartsSection *functionStarts;
+  FunctionStartsSection *functionStartsSection;
 };
 
 class LCDysymtab : public LoadCommand {
@@ -563,7 +565,8 @@
   in.header->addLoadCommand(make<LCSymtab>(symtabSection, stringTableSection));
   in.header->addLoadCommand(
       make<LCDysymtab>(symtabSection, indirectSymtabSection));
-  in.header->addLoadCommand(make<LCFunctionStarts>(in.functionStarts));
+  if (functionStartsSection)
+    in.header->addLoadCommand(make<LCFunctionStarts>(functionStartsSection));
   for (StringRef path : config->runtimePaths)
     in.header->addLoadCommand(make<LCRPath>(path));
 
@@ -791,6 +794,8 @@
   indirectSymtabSection = make<IndirectSymtabSection>();
   if (config->adhocCodesign)
     codeSignatureSection = make<CodeSignatureSection>();
+  if (config->emitFunctionStarts)
+    functionStartsSection = make<FunctionStartsSection>();
 
   switch (config->outputType) {
   case MH_EXECUTE:
@@ -863,10 +868,12 @@
   in.weakBinding->finalizeContents();
   in.lazyBinding->finalizeContents();
   in.exports->finalizeContents();
-  in.functionStarts->finalizeContents();
   symtabSection->finalizeContents();
   indirectSymtabSection->finalizeContents();
 
+  if (functionStartsSection)
+    functionStartsSection->finalizeContents();
+
   // Now that __LINKEDIT is filled out, do a proper calculation of its
   // addresses and offsets.
   assignAddresses(linkEditSegment);
@@ -962,7 +969,6 @@
   in.weakBinding = make<WeakBindingSection>();
   in.lazyBinding = make<LazyBindingSection>();
   in.exports = make<ExportSection>();
-  in.functionStarts = make<FunctionStartsSection>();
   in.got = make<GotSection>();
   in.tlvPointers = make<TlvPointerSection>();
   in.lazyPointers = make<LazyPointerSection>();
diff --git a/test/MachO/function-starts.s b/test/MachO/function-starts.s
index ce2d429..d5168c6 100644
--- a/test/MachO/function-starts.s
+++ b/test/MachO/function-starts.s
@@ -1,33 +1,40 @@
 # REQUIRES: x86
 
-# RUN: split-file %s %t
+# RUN: rm -rf %t; split-file %s %t
 
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/basic.s -o %t.basic.o
-# RUN: %lld %t.basic.o -o %t.basic
-# RUN: llvm-objdump --syms %t.basic > %t.objdump
-# RUN: llvm-objdump --macho --function-starts %t.basic >> %t.objdump
-# RUN: FileCheck %s --check-prefix=BASIC < %t.objdump
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/basic.s -o %t/basic.o
+# RUN: %lld %t/basic.o -o %t/basic
+# RUN: llvm-objdump --syms %t/basic > %t/objdump
+# RUN: llvm-objdump --macho --function-starts %t/basic >> %t/objdump
+# RUN: FileCheck %s --check-prefix=BASIC < %t/objdump
 
-# BASIC:      SYMBOL TABLE:
-# BASIC-NEXT: [[#%x,MAIN:]] g F __TEXT,__text _main
-# BASIC-NEXT: [[#%x,F1:]] g F __TEXT,__text _f1
-# BASIC-NEXT: [[#%x,F2:]] g F __TEXT,__text _f2
-# BASIC:      [[#MAIN]]
-# BASIC:      [[#F1]]
-# BASIC:      [[#F2]]
+# BASIC-LABEL: SYMBOL TABLE:
+# BASIC-NEXT:  [[#%x,MAIN:]] g F __TEXT,__text _main
+# BASIC-NEXT:  [[#%x,F1:]] g F __TEXT,__text _f1
+# BASIC-NEXT:  [[#%x,F2:]] g F __TEXT,__text _f2
+# BASIC-LABEL: basic:
+# BASIC:       [[#MAIN]]
+# BASIC:       [[#F1]]
+# BASIC:       [[#F2]]
 
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/alias.s -o %t.alias.o
-# RUN: %lld %t.alias.o -o %t.alias
-# RUN: llvm-objdump --syms  %t.alias > %t.objdump
-# RUN: llvm-objdump --macho --function-starts %t.alias >> %t.objdump
-# RUN: FileCheck %s --check-prefix=ALIAS < %t.objdump
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/alias.s -o %t/alias.o
+# RUN: %lld %t/alias.o -o %t/alias
+# RUN: llvm-objdump --syms  %t/alias > %t/objdump
+# RUN: llvm-objdump --macho --function-starts %t/alias >> %t/objdump
+# RUN: FileCheck %s --check-prefix=ALIAS < %t/objdump
 
-# ALIAS:      SYMBOL TABLE:
-# ALIAS-NEXT: [[#%x,F2:]] l F __TEXT,__text _f2
-# ALIAS-NEXT: [[#%x,MAIN:]] g F __TEXT,__text _main
-# ALIAS-NEXT: [[#%x,F1:]] g F __TEXT,__text _f1
-# ALIAS:      [[#MAIN]]
-# ALIAS:      [[#F1]]
+# ALIAS-LABEL: SYMBOL TABLE:
+# ALIAS-NEXT:  [[#%x,F2:]] l F __TEXT,__text _f2
+# ALIAS-NEXT:  [[#%x,MAIN:]] g F __TEXT,__text _main
+# ALIAS-NEXT:  [[#%x,F1:]] g F __TEXT,__text _f1
+# ALIAS-LABEL: alias:
+# ALIAS:       [[#MAIN]]
+# ALIAS:       [[#F1]]
+
+# RUN: %lld %t/basic.o -no_function_starts -o %t/basic-no-function-starts
+# RUN: llvm-objdump --macho --function-starts %t/basic-no-function-starts | FileCheck %s --check-prefix=NO-FUNCTION-STARTS
+# NO-FUNCTION-STARTS: basic-no-function-starts:
+# NO-FUNCTION-STARTS-EMPTY:
 
 #--- basic.s
 .section  __TEXT,__text,regular,pure_instructions