[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