[llvm] afaa56d - Implement support for __llvm_addrsig for MachO in llvm-mc

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Tue May 3 15:19:37 PDT 2022


Author: Alex Borcan
Date: 2022-05-03T18:19:18-04:00
New Revision: afaa56df7a93f21cd1e49f7daa6a8970335744da

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

LOG: Implement support for __llvm_addrsig for MachO in llvm-mc

The __llvm_addrsig section is a section that the linker needs for safe icf.
This was not yet implemented for MachO - this is the implementation.
It has been tested with a safe deduplication implementation inside lld.

Reviewed By: MaskRay

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

Added: 
    llvm/test/CodeGen/AArch64/addrsig-macho.ll

Modified: 
    llvm/include/llvm/MC/MCMachObjectWriter.h
    llvm/include/llvm/MC/MCObjectFileInfo.h
    llvm/include/llvm/MC/MCObjectWriter.h
    llvm/lib/MC/ELFObjectWriter.cpp
    llvm/lib/MC/MCMachOStreamer.cpp
    llvm/lib/MC/MCObjectFileInfo.cpp
    llvm/lib/MC/MachObjectWriter.cpp
    llvm/lib/MC/WinCOFFObjectWriter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCMachObjectWriter.h b/llvm/include/llvm/MC/MCMachObjectWriter.h
index f4f9c474cdcd7..149373dd2b541 100644
--- a/llvm/include/llvm/MC/MCMachObjectWriter.h
+++ b/llvm/include/llvm/MC/MCMachObjectWriter.h
@@ -264,6 +264,8 @@ class MachObjectWriter : public MCObjectWriter {
                                               bool IsPCRel) const override;
 
   uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+
+  void writeAddrsigSection(MCAssembler &Asm);
 };
 
 /// Construct a new Mach-O writer instance.

diff  --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index a4cb21636b57b..f1e63e0ba7be3 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -213,6 +213,7 @@ class MCObjectFileInfo {
   MCSection *LazySymbolPointerSection = nullptr;
   MCSection *NonLazySymbolPointerSection = nullptr;
   MCSection *ThreadLocalPointerSection = nullptr;
+  MCSection *AddrSigSection = nullptr;
 
   /// COFF specific sections.
   MCSection *DrectveSection = nullptr;
@@ -410,6 +411,7 @@ class MCObjectFileInfo {
   MCSection *getThreadLocalPointerSection() const {
     return ThreadLocalPointerSection;
   }
+  MCSection *getAddrSigSection() const { return AddrSigSection; }
 
   // COFF specific sections.
   MCSection *getDrectveSection() const { return DrectveSection; }

diff  --git a/llvm/include/llvm/MC/MCObjectWriter.h b/llvm/include/llvm/MC/MCObjectWriter.h
index d2a2f1a13ff5e..a8e24a0c56ba8 100644
--- a/llvm/include/llvm/MC/MCObjectWriter.h
+++ b/llvm/include/llvm/MC/MCObjectWriter.h
@@ -10,6 +10,7 @@
 #define LLVM_MC_MCOBJECTWRITER_H
 
 #include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCSymbol.h"
 #include <cstdint>
 
 namespace llvm {
@@ -32,6 +33,9 @@ class MCValue;
 /// should be emitted as part of writeObject().
 class MCObjectWriter {
 protected:
+  std::vector<const MCSymbol *> AddrsigSyms;
+  bool EmitAddrsigSection = false;
+
   MCObjectWriter() = default;
 
 public:
@@ -91,11 +95,15 @@ class MCObjectWriter {
   /// Tell the object writer to emit an address-significance table during
   /// writeObject(). If this function is not called, all symbols are treated as
   /// address-significant.
-  virtual void emitAddrsigSection() {}
+  void emitAddrsigSection() { EmitAddrsigSection = true; }
+
+  bool getEmitAddrsigSection() { return EmitAddrsigSection; }
 
   /// Record the given symbol in the address-significance table to be written
   /// diring writeObject().
-  virtual void addAddrsigSymbol(const MCSymbol *Sym) {}
+  void addAddrsigSymbol(const MCSymbol *Sym) { AddrsigSyms.push_back(Sym); }
+
+  std::vector<const MCSymbol *> &getAddrsigSyms() { return AddrsigSyms; }
 
   /// Write the object file and returns the number of bytes written.
   ///

diff  --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp
index 08d1b12395e0d..eda495693595d 100644
--- a/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/llvm/lib/MC/ELFObjectWriter.cpp
@@ -221,8 +221,6 @@ class ELFObjectWriter : public MCObjectWriter {
   DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
 
   bool SeenGnuAbi = false;
-  bool EmitAddrsigSection = false;
-  std::vector<const MCSymbol *> AddrsigSyms;
 
   bool hasRelocationAddend() const;
 
@@ -262,10 +260,6 @@ class ELFObjectWriter : public MCObjectWriter {
 
   void markGnuAbi() override { SeenGnuAbi = true; }
   bool seenGnuAbi() const { return SeenGnuAbi; }
-  void emitAddrsigSection() override { EmitAddrsigSection = true; }
-  void addAddrsigSymbol(const MCSymbol *Sym) override {
-    AddrsigSyms.push_back(Sym);
-  }
 
   friend struct ELFWriter;
 };

diff  --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index f5c40fa0cdfb3..a060fa90e66c7 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -131,6 +131,7 @@ class MCMachOStreamer : public MCObjectStreamer {
 
   void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE);
   void finalizeCGProfile();
+  void createAddrSigSection();
 };
 
 } // end anonymous namespace.
@@ -530,6 +531,7 @@ void MCMachOStreamer::finishImpl() {
 
   finalizeCGProfile();
 
+  createAddrSigSection();
   this->MCObjectStreamer::finishImpl();
 }
 
@@ -580,3 +582,16 @@ MCStreamer *llvm::createMachOStreamer(MCContext &Context,
     S->getAssembler().setRelaxAll(true);
   return S;
 }
+
+// Create the AddrSig section and first data fragment here as its layout needs
+// to be computed immediately after in order for it to be exported correctly.
+void MCMachOStreamer::createAddrSigSection() {
+  MCAssembler &Asm = getAssembler();
+  MCObjectWriter &writer = Asm.getWriter();
+  if (!writer.getEmitAddrsigSection())
+    return;
+  MCSection *AddrSigSection =
+      Asm.getContext().getObjectFileInfo()->getAddrSigSection();
+  Asm.registerSection(*AddrSigSection);
+  new MCDataFragment(AddrSigSection);
+}

diff  --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 5bd3fcceadb94..3ee8167c38326 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -182,6 +182,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
                            MachO::S_THREAD_LOCAL_VARIABLE_POINTERS,
                            SectionKind::getMetadata());
 
+  AddrSigSection = Ctx->getMachOSection("__DATA", "__llvm_addrsig", 0,
+                                        SectionKind::getData());
+
   // Exception Handling.
   LSDASection = Ctx->getMachOSection("__TEXT", "__gcc_except_tab", 0,
                                      SectionKind::getReadOnlyWithRel());

diff  --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp
index 56bb03ad8d420..173755df2b85c 100644
--- a/llvm/lib/MC/MachObjectWriter.cpp
+++ b/llvm/lib/MC/MachObjectWriter.cpp
@@ -19,6 +19,7 @@
 #include "llvm/MC/MCFixupKindInfo.h"
 #include "llvm/MC/MCFragment.h"
 #include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/MC/MCSectionMachO.h"
@@ -29,6 +30,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -751,6 +753,24 @@ static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
   llvm_unreachable("Invalid mc version min type");
 }
 
+// Encode addrsig data as symbol indexes in variable length encoding.
+void MachObjectWriter::writeAddrsigSection(MCAssembler &Asm) {
+  MCSection *AddrSigSection =
+      Asm.getContext().getObjectFileInfo()->getAddrSigSection();
+  MCSection::FragmentListType &fragmentList = AddrSigSection->getFragmentList();
+  if (!fragmentList.size())
+    return;
+
+  assert(fragmentList.size() == 1);
+  MCFragment *pFragment = &*fragmentList.begin();
+  MCDataFragment *pDataFragment = dyn_cast_or_null<MCDataFragment>(pFragment);
+  assert(pDataFragment);
+
+  raw_svector_ostream OS(pDataFragment->getContents());
+  for (const MCSymbol *sym : this->getAddrsigSyms())
+    encodeULEB128(sym->getIndex(), OS);
+}
+
 uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
                                        const MCAsmLayout &Layout) {
   uint64_t StartOffset = W.OS.tell();
@@ -758,6 +778,7 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
   // Compute symbol table information and bind symbol indices.
   computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
                      UndefinedSymbolData);
+  writeAddrsigSection(Asm);
 
   if (!Asm.CGProfile.empty()) {
     MCSection *CGProfileSection = Asm.getContext().getMachOSection(

diff  --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 2af94b4f69a7b..1de1532ea38c5 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -154,9 +154,7 @@ class WinCOFFObjectWriter : public MCObjectWriter {
   bool UseBigObj;
   bool UseOffsetLabels = false;
 
-  bool EmitAddrsigSection = false;
   MCSectionCOFF *AddrsigSection;
-  std::vector<const MCSymbol *> AddrsigSyms;
 
   MCSectionCOFF *CGProfileSection = nullptr;
 
@@ -220,11 +218,6 @@ class WinCOFFObjectWriter : public MCObjectWriter {
   void assignSectionNumbers();
   void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
 
-  void emitAddrsigSection() override { EmitAddrsigSection = true; }
-  void addAddrsigSymbol(const MCSymbol *Sym) override {
-    AddrsigSyms.push_back(Sym);
-  }
-
   uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
 };
 

diff  --git a/llvm/test/CodeGen/AArch64/addrsig-macho.ll b/llvm/test/CodeGen/AArch64/addrsig-macho.ll
new file mode 100644
index 0000000000000..f16ccf117558b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/addrsig-macho.ll
@@ -0,0 +1,116 @@
+; RUN: llc -filetype=asm %s -o - -mtriple arm64-apple-ios -addrsig | FileCheck %s
+; RUN: llc -filetype=obj %s -o %t -mtriple arm64-apple-ios -addrsig
+; RUN: llvm-readobj --hex-dump='__llvm_addrsig' %t | FileCheck %s --check-prefix=OBJ
+
+; CHECK:			.addrsig{{$}}
+; CHECK-NEXT:	.addrsig_sym _func03_takeaddr
+; CHECK-NEXT:	.addrsig_sym _f1
+; CHECK-NEXT:	.addrsig_sym _metadata_f2
+; CHECK-NEXT:	.addrsig_sym _result
+; CHECK-NEXT:	.addrsig_sym _g1
+; CHECK-NEXT:	.addrsig_sym _a1
+; CHECK-NEXT:	.addrsig_sym _i1
+
+; OBJ: Hex dump of section '__llvm_addrsig':
+; OBJ-NEXT:0x{{[0-9a-f]*}}
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "arm64-apple-ios7.0.0"
+
+ at result = global i32 0, align 4
+
+; Function Attrs: minsize nofree noinline norecurse nounwind optsize ssp uwtable
+define void @func01() local_unnamed_addr #0 {
+entry:
+  %0 = load volatile i32, ptr @result, align 4
+  %add = add nsw i32 %0, 1
+  store volatile i32 %add, ptr @result, align 4
+  ret void
+}
+
+; Function Attrs: minsize nofree noinline norecurse nounwind optsize ssp uwtable
+define void @func02() local_unnamed_addr #0 {
+entry:
+  %0 = load volatile i32, ptr @result, align 4
+  %add = add nsw i32 %0, 1
+  store volatile i32 %add, ptr @result, align 4
+  ret void
+}
+
+; Function Attrs: minsize nofree noinline norecurse nounwind optsize ssp uwtable
+define void @func03_takeaddr() #0 {
+entry:
+  %0 = load volatile i32, ptr @result, align 4
+  %add = add nsw i32 %0, 1
+  store volatile i32 %add, ptr @result, align 4
+  ret void
+}
+
+; Function Attrs: minsize nofree norecurse nounwind optsize ssp uwtable
+define void @callAllFunctions() local_unnamed_addr {
+entry:
+  tail call void @func01()
+  tail call void @func02()
+  tail call void @func03_takeaddr()
+  %0 = load volatile i32, ptr @result, align 4
+  %add = add nsw i32 %0, ptrtoint (ptr @func03_takeaddr to i32)
+  store volatile i32 %add, ptr @result, align 4
+  ret void
+}
+
+
+define void()* @f1() {
+  %f1 = bitcast void()* ()* @f1 to i8*
+  %f2 = bitcast void()* ()* @f2 to i8*
+  %f3 = bitcast void()* @f3 to i8*
+  %g1 = bitcast i32* @g1 to i8*
+  %g2 = bitcast i32* @g2 to i8*
+  %g3 = bitcast i32* @g3 to i8*
+  %dllimport = bitcast i32* @dllimport to i8*
+  %tls = bitcast i32* @tls to i8*
+  %a1 = bitcast i32* @a1 to i8*
+  %a2 = bitcast i32* @a2 to i8*
+  %i1 = bitcast void()* @i1 to i8*
+  %i2 = bitcast void()* @i2 to i8*
+  call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f1 to i8*), metadata !5, metadata !DIExpression()), !dbg !7
+  call void @llvm.dbg.value(metadata i8* bitcast (void()* @metadata_f2 to i8*), metadata !5, metadata !DIExpression()), !dbg !7
+  call void @f4(i8* bitcast (void()* @metadata_f2 to i8*))
+  unreachable
+}
+
+declare void @f4(i8*) unnamed_addr
+
+declare void @metadata_f1()
+declare void @metadata_f2()
+
+define internal void()* @f2() local_unnamed_addr {
+  unreachable
+}
+
+declare void @f3() unnamed_addr
+
+ at g1 = global i32 0
+ at g2 = internal local_unnamed_addr global i32 0
+ at g3 = external unnamed_addr global i32
+
+ at unref = external global i32
+
+ at dllimport = external dllimport global i32
+
+ at tls = thread_local global i32 0
+
+ at a1 = alias i32, i32* @g1
+ at a2 = internal local_unnamed_addr alias i32, i32* @g2
+
+ at i1 = ifunc void(), void()* ()* @f1
+ at i2 = internal local_unnamed_addr ifunc void(), void()* ()* @f2
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+attributes #0 = { noinline }
+
+!3 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false)
+!4 = !DILocation(line: 0, scope: !3)
+!5 = !DILocalVariable(scope: !6)
+!6 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true, isOptimized: false)
+!7 = !DILocation(line: 0, scope: !6, inlinedAt: !4)


        


More information about the llvm-commits mailing list