diff --git a/llvm/include/llvm/MC/MCMachObjectWriter.h b/llvm/include/llvm/MC/MCMachObjectWriter.h --- a/llvm/include/llvm/MC/MCMachObjectWriter.h +++ b/llvm/include/llvm/MC/MCMachObjectWriter.h @@ -264,6 +264,8 @@ 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 --- a/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -213,6 +213,7 @@ MCSection *LazySymbolPointerSection = nullptr; MCSection *NonLazySymbolPointerSection = nullptr; MCSection *ThreadLocalPointerSection = nullptr; + MCSection *AddrSigSection = nullptr; /// COFF specific sections. MCSection *DrectveSection = nullptr; @@ -410,6 +411,7 @@ 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 --- 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 namespace llvm { @@ -32,6 +33,9 @@ /// should be emitted as part of writeObject(). class MCObjectWriter { protected: + bool EmitAddrsigSection = false; + std::vector AddrsigSyms; + MCObjectWriter() = default; public: @@ -91,11 +95,15 @@ /// 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 &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 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -221,8 +221,6 @@ DenseMap Renames; bool SeenGnuAbi = false; - bool EmitAddrsigSection = false; - std::vector AddrsigSyms; bool hasRelocationAddend() const; @@ -262,10 +260,6 @@ 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 --- a/llvm/lib/MC/MCMachOStreamer.cpp +++ b/llvm/lib/MC/MCMachOStreamer.cpp @@ -31,6 +31,7 @@ #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -131,6 +132,7 @@ void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE); void finalizeCGProfile(); + void createAddrSigSection(); }; } // end anonymous namespace. @@ -529,6 +531,7 @@ finalizeCGProfile(); + createAddrSigSection(); this->MCObjectStreamer::finishImpl(); } @@ -579,3 +582,16 @@ 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 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -181,6 +181,9 @@ 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 --- 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 @@ -751,6 +753,26 @@ 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(); + auto &fragmentList = AddrSigSection->getFragmentList(); + if (!fragmentList.size()) return; + + assert(fragmentList.size() == 1); + + MCFragment *pFragment = &*fragmentList.begin(); + assert(pFragment); + MCDataFragment *pDataFragment = dyn_cast_or_null(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 +780,7 @@ // 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 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -154,9 +154,7 @@ bool UseBigObj; bool UseOffsetLabels = false; - bool EmitAddrsigSection = false; MCSectionCOFF *AddrsigSection; - std::vector AddrsigSyms; MCSectionCOFF *CGProfileSection = nullptr; @@ -220,11 +218,6 @@ 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/MC/MachO/addrsig-macho.ll b/llvm/test/MC/MachO/addrsig-macho.ll new file mode 100644 --- /dev/null +++ b/llvm/test/MC/MachO/addrsig-macho.ll @@ -0,0 +1,117 @@ +; 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 + + + +source_filename = "file1.c" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-ios7.0.0" + +@nr1 = local_unnamed_addr global i32 0 +@nr2 = local_unnamed_addr global i32 0 +@nr3 = local_unnamed_addr global i32 0 +@result = global i32 0 + +; Function Attrs: minsize mustprogress nofree noinline norecurse nosync nounwind optsize readonly ssp willreturn uwtable +define i32 @func01() local_unnamed_addr #0 { +entry: + %0 = load i32, ptr @nr1 + %1 = load i32, ptr @nr2 + %2 = load i32, ptr @nr3 + %mul = mul nsw i32 %2, %1 + %add = add nsw i32 %mul, %0 + ret i32 %add +} + +; Function Attrs: minsize mustprogress nofree noinline norecurse nosync nounwind optsize readonly ssp willreturn uwtable +define i32 @func02() #0 { +entry: + %0 = load i32, ptr @nr1 + %1 = load i32, ptr @nr2 + %2 = load i32, ptr @nr3 + %mul = mul nsw i32 %2, %1 + %add = add nsw i32 %mul, %0 + ret i32 %add +} + +; Function Attrs: minsize mustprogress nofree noinline norecurse nosync nounwind optsize readonly ssp willreturn uwtable +define i32 @func03() local_unnamed_addr #0 { +entry: + %0 = load i32, ptr @nr1 + %1 = load i32, ptr @nr2 + %2 = load i32, ptr @nr3 + %mul = mul nsw i32 %2, %1 + %add = add nsw i32 %mul, %0 + ret i32 %add +} + +; Function Attrs: minsize mustprogress nofree noinline norecurse nosync nounwind optsize readonly ssp willreturn uwtable +define i32 @func04() local_unnamed_addr #0 { +entry: + %0 = load i32, ptr @nr1 + %1 = load i32, ptr @nr2 + %2 = load i32, ptr @nr3 + %mul = mul nsw i32 %2, %1 + %add = add nsw i32 %mul, %0 + ret i32 %add +} + +; Function Attrs: minsize mustprogress nofree noinline norecurse nosync nounwind optsize readonly ssp willreturn uwtable +define i32 @func05() local_unnamed_addr #0 { +entry: + %0 = load i32, ptr @nr1 + %1 = load i32, ptr @nr2 + %2 = load i32, ptr @nr3 + %mul = mul nsw i32 %2, %1 + %add = add nsw i32 %mul, %0 + ret i32 %add +} + +; Function Attrs: minsize nofree norecurse nounwind optsize ssp uwtable +define i32 @main() local_unnamed_addr #1 { +entry: + %call = tail call i32 @func01() #2 + %0 = load volatile i32, ptr @result + %add = add nsw i32 %0, %call + store volatile i32 %add, ptr @result + %call1 = tail call i32 @func02() #2 + %1 = load volatile i32, ptr @result + %add2 = add nsw i32 %1, %call1 + store volatile i32 %add2, ptr @result + %2 = load volatile i32, ptr @result + %add3 = add nsw i32 %2, ptrtoint (ptr @func02 to i32) + store volatile i32 %add3, ptr @result + %call4 = tail call i32 @func03() #2 + %3 = load volatile i32, ptr @result + %add5 = add nsw i32 %3, %call4 + store volatile i32 %add5, ptr @result + %call6 = tail call i32 @func04() #2 + %4 = load volatile i32, ptr @result + %add7 = add nsw i32 %4, %call6 + store volatile i32 %add7, ptr @result + %call8 = tail call i32 @func05() #2 + %5 = load volatile i32, ptr @result + %add9 = add nsw i32 %5, %call8 + store volatile i32 %add9, ptr @result + ret i32 0 +} + +; Function Attrs: minsize nofree norecurse nounwind optsize ssp uwtable +define void @_start() local_unnamed_addr #1 { +entry: + %call = tail call i32 @main() #2 + ret void +} + +attributes #0 = { minsize mustprogress nofree noinline norecurse nosync nounwind optsize readonly ssp willreturn uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a7" "target-features"="+aes,+crypto,+fp-armv8,+neon,+sha2,+v8a,+zcm,+zcz" } +attributes #1 = { minsize nofree norecurse nounwind optsize ssp uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a7" "target-features"="+aes,+crypto,+fp-armv8,+neon,+sha2,+v8a,+zcm,+zcz" } +attributes #2 = { minsize optsize } + + +; CHECK: .addrsig +; CHECK-NEXT: .addrsig_sym _func02 +; CHECK-NEXT: .addrsig_sym _result + +; OBJ: Hex dump of section '__llvm_addrsig': +; OBJ-NEXT:0x{{[0-9a-f]*}}