Index: include/llvm/MC/MCDwarf.h =================================================================== --- include/llvm/MC/MCDwarf.h +++ include/llvm/MC/MCDwarf.h @@ -599,6 +599,7 @@ bool IsSignalFrame = false; bool IsSimple = false; unsigned RAReg = static_cast(INT_MAX); + bool IsBKeyFrame = false; }; class MCDwarfFrameEmitter { Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -797,6 +797,8 @@ Optional Source, unsigned CUID = 0); + virtual void EmitCFIBKeyFrame(); + /// This implements the DWARF2 '.loc fileno lineno ...' assembler /// directive. virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, Index: lib/DebugInfo/DWARF/DWARFDebugFrame.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -445,6 +445,8 @@ StartAugmentationOffset = Offset; EndAugmentationOffset = Offset + static_cast(*AugmentationLength); + case 'B': + break; } } Index: lib/MC/MCAsmStreamer.cpp =================================================================== --- lib/MC/MCAsmStreamer.cpp +++ lib/MC/MCAsmStreamer.cpp @@ -266,6 +266,7 @@ void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override; void EmitIdent(StringRef IdentString) override; + void EmitCFIBKeyFrame() override; void EmitCFISections(bool EH, bool Debug) override; void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; void EmitCFIDefCfaOffset(int64_t Offset) override; @@ -1577,6 +1578,14 @@ EmitEOL(); } +void MCAsmStreamer::EmitCFIBKeyFrame() +{ + MCStreamer::EmitCFIBKeyFrame(); + + OS << "\t.cfi_b_key_frame \"" << "\""; + EmitEOL(); +} + void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { MCStreamer::EmitWinCFIStartProc(Symbol, Loc); Index: lib/MC/MCDwarf.cpp =================================================================== --- lib/MC/MCDwarf.cpp +++ lib/MC/MCDwarf.cpp @@ -1560,9 +1560,8 @@ uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion()); Streamer.EmitIntValue(CIEVersion, 1); - // Augmentation String - SmallString<8> Augmentation; if (IsEH) { + SmallString<8> Augmentation; Augmentation += "z"; if (Frame.Personality) Augmentation += "P"; @@ -1571,6 +1570,8 @@ Augmentation += "R"; if (Frame.IsSignalFrame) Augmentation += "S"; + if (Frame.IsBKeyFrame) + Augmentation += "B"; Streamer.EmitBytes(Augmentation); } Streamer.EmitIntValue(0, 1); @@ -1725,25 +1726,27 @@ struct CIEKey { static const CIEKey getEmptyKey() { - return CIEKey(nullptr, 0, -1, false, false, static_cast(INT_MAX)); + return CIEKey(nullptr, 0, -1, false, false, static_cast(INT_MAX), false); } static const CIEKey getTombstoneKey() { - return CIEKey(nullptr, -1, 0, false, false, static_cast(INT_MAX)); + return CIEKey(nullptr, -1, 0, false, false, static_cast(INT_MAX), false); } CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding, unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple, - unsigned RAReg) + unsigned RAReg, bool IsBKeyFrame) : Personality(Personality), PersonalityEncoding(PersonalityEncoding), LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame), - IsSimple(IsSimple), RAReg(RAReg) {} + IsSimple(IsSimple), RAReg(RAReg), + IsBKeyFrame(IsBKeyFrame) {} explicit CIEKey(const MCDwarfFrameInfo &Frame) : Personality(Frame.Personality), PersonalityEncoding(Frame.PersonalityEncoding), LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame), - IsSimple(Frame.IsSimple), RAReg(Frame.RAReg) {} + IsSimple(Frame.IsSimple), RAReg(Frame.RAReg), + IsBKeyFrame(Frame.IsBKeyFrame) {} const MCSymbol *Personality; unsigned PersonalityEncoding; @@ -1751,6 +1754,7 @@ bool IsSignalFrame; bool IsSimple; unsigned RAReg; + bool IsBKeyFrame; }; } // end anonymous namespace @@ -1764,7 +1768,8 @@ static unsigned getHashValue(const CIEKey &Key) { return static_cast( hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding, - Key.IsSignalFrame, Key.IsSimple, Key.RAReg)); + Key.IsSignalFrame, Key.IsSimple, Key.RAReg, + Key.IsBKeyFrame)); } static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) { @@ -1773,7 +1778,8 @@ LHS.LsdaEncoding == RHS.LsdaEncoding && LHS.IsSignalFrame == RHS.IsSignalFrame && LHS.IsSimple == RHS.IsSimple && - LHS.RAReg == RHS.RAReg; + LHS.RAReg == RHS.RAReg && + LHS.IsBKeyFrame == RHS.IsBKeyFrame; } }; Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -492,6 +492,7 @@ DK_CFI_UNDEFINED, DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, + DK_CFI_B_KEY_FRAME, DK_MACROS_ON, DK_MACROS_OFF, DK_ALTMACRO, @@ -575,6 +576,8 @@ bool parseDirectiveCFISignalFrame(); bool parseDirectiveCFIUndefined(SMLoc DirectiveLoc); + bool parseDirectiveCFIBKeyFrame(); + // macro directives bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); bool parseDirectiveExitMacro(StringRef Directive); @@ -2083,6 +2086,8 @@ return parseDirectiveCFIRegister(IDLoc); case DK_CFI_WINDOW_SAVE: return parseDirectiveCFIWindowSave(); + case DK_CFI_B_KEY_FRAME: + return parseDirectiveCFIBKeyFrame(); case DK_MACROS_ON: case DK_MACROS_OFF: return parseDirectiveMacrosOnOff(IDVal); @@ -4175,6 +4180,18 @@ return false; } + +/// parseDirectiveCFIBKeyFrame +/// ::= .append_augmentation +bool AsmParser::parseDirectiveCFIBKeyFrame() { + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.cfi_b_key_frame'")) + return true; + + getStreamer().EmitCFIBKeyFrame(); + return false; +} + /// parseDirectiveAltmacro /// ::= .altmacro /// ::= .noaltmacro @@ -5284,6 +5301,7 @@ DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE; + DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME; DirectiveKindMap[".macros_on"] = DK_MACROS_ON; DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; DirectiveKindMap[".macro"] = DK_MACRO; Index: lib/MC/MCStreamer.cpp =================================================================== --- lib/MC/MCStreamer.cpp +++ lib/MC/MCStreamer.cpp @@ -209,6 +209,13 @@ Source); } +void MCStreamer::EmitCFIBKeyFrame() { + MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); + if (!CurFrame) + return; + CurFrame->IsBKeyFrame = true; +} + void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, Index: lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- lib/Target/AArch64/AArch64AsmPrinter.cpp +++ lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -683,6 +683,10 @@ case TargetOpcode::PATCHABLE_TAIL_CALL: LowerPATCHABLE_TAIL_CALL(*MI); return; + + case AArch64::EMITBKEY: + OutStreamer->EmitCFIBKeyFrame(); + return; } // Finally, do the automated lowerings for everything else. Index: lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64FrameLowering.cpp +++ lib/Target/AArch64/AArch64FrameLowering.cpp @@ -631,10 +631,16 @@ DebugLoc DL; if (ShouldSignReturnAddress(MF)) { - BuildMI( - MBB, MBBI, DL, - TII->get(ShouldSignWithAKey(MF) ? AArch64::PACIASP : AArch64::PACIBSP)) - .setMIFlag(MachineInstr::FrameSetup); + if (ShouldSignWithAKey(MF)) + BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIASP)) + .setMIFlag(MachineInstr::FrameSetup); + else + { + BuildMI(MBB, MBBI, DL, TII->get(AArch64::EMITBKEY)) + .setMIFlag(MachineInstr::FrameSetup); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACIBSP)) + .setMIFlag(MachineInstr::FrameSetup); + } unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr)); Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -1442,6 +1442,10 @@ let AsmString = ".tlsdesccall $sym"; } +// Pseudo instruction to tell the streamer to emit a 'B' character into the +// augmentation string. +def EMITBKEY : Pseudo<(outs), (ins), []>, Sched<[]> {} + // FIXME: maybe the scratch register used shouldn't be fixed to X1? // FIXME: can "hasSideEffects be dropped? let isCall = 1, Defs = [LR, X0, X1], hasSideEffects = 1, Index: test/CodeGen/MIR/AArch64/return-address-signing.mir =================================================================== --- test/CodeGen/MIR/AArch64/return-address-signing.mir +++ test/CodeGen/MIR/AArch64/return-address-signing.mir @@ -98,6 +98,7 @@ fixedStack: stack: constants: +#CHECK: frame-setup EMITBKEY #CHECK: frame-setup PACIBSP implicit-def $lr, implicit $lr, implicit $sp #CHECK: frame-setup CFI_INSTRUCTION negate_ra_sign_state #CHECK: RETAB Index: test/DebugInfo/AArch64/return-address-signing.ll =================================================================== --- /dev/null +++ test/DebugInfo/AArch64/return-address-signing.ll @@ -0,0 +1,15 @@ +; RUN: llc -mtriple=aarch64-arm-none-eabi < %s -filetype=obj -o - \ +; RUN: | llvm-dwarfdump -v - | FileCheck -check-prefix=CHECK %s + +;CHECK: CIE +;CHECK: Augmentation: "zR" +define i32 @foo() "sign-return-address"="all" { + ret i32 0 +} + +;CHECK: CIE +;CHECK: Augmentation: "zRB" + +define i32 @bar() "sign-return-address"="all" "sign-return-address-key"="b_key" { + ret i32 0 +} Index: test/MC/ELF/cfi-b-key-frame.s =================================================================== --- /dev/null +++ test/MC/ELF/cfi-b-key-frame.s @@ -0,0 +1,6 @@ +// RUN: llvm-mc -filetype=obj -triple aarch64-arm-none-eabi %s -o - | llvm-dwarfdump - -v | FileCheck %s +#CHECK: Augmentation: "zRB" +f1: + .cfi_startproc + .cfi_b_key_frame + .cfi_endproc