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: + std::vector AddrsigSyms; + bool EmitAddrsigSection = false; + 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 @@ -131,6 +131,7 @@ void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE); void finalizeCGProfile(); + void createAddrSigSection(); }; } // end anonymous namespace. @@ -530,6 +531,7 @@ finalizeCGProfile(); + createAddrSigSection(); this->MCObjectStreamer::finishImpl(); } @@ -580,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 @@ -182,6 +182,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,24 @@ 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(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 @@ // 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/CodeGen/AArch64/addrsig-macho.ll b/llvm/test/CodeGen/AArch64/addrsig-macho.ll new file mode 100644 --- /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" + +@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 + +@g1 = global i32 0 +@g2 = internal local_unnamed_addr global i32 0 +@g3 = external unnamed_addr global i32 + +@unref = external global i32 + +@dllimport = external dllimport global i32 + +@tls = thread_local global i32 0 + +@a1 = alias i32, i32* @g1 +@a2 = internal local_unnamed_addr alias i32, i32* @g2 + +@i1 = ifunc void(), void()* ()* @f1 +@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)