This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG66902a32c838: [StopInfoMachException] Summarize arm64e 
BLRAx/LDRAx auth failures (authored by vsk).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102428/new/

https://reviews.llvm.org/D102428

Files:
  lldb/include/lldb/Core/Address.h
  lldb/include/lldb/Core/Disassembler.h
  lldb/source/Core/Address.cpp
  lldb/source/Core/Disassembler.cpp
  lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
  lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
  lldb/source/Plugins/Process/Utility/StopInfoMachException.h
  lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/Makefile
  
lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/TestPtrauthBLRAADiagnostic.py
  lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/blraa.c
  lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/Makefile
  
lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/TestPtrauthBRAADiagnostic.py
  lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/braa.c
  lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/Makefile
  
lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/TestPtrauthLDRAADiagnostic.py
  lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/ldraa.c
  lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/Makefile
  
lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/TestPtrauthBRKc47xDiagnostic.py
  lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/brkC47x.c
  lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/Makefile
  
lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/TestPtrauthBRKc47xX16Invalid.py
  
lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/brkC47x.c

Index: lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/brkC47x.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/brkC47x.c
@@ -0,0 +1,14 @@
+int main() {
+  //% self.filecheck("c", "brkC47x.c")
+  // CHECK: stop reason = EXC_BAD_ACCESS
+  // CHECK-NOT: Note: Possible pointer authentication failure detected.
+  asm volatile (
+      "mov x16, #0xbad \n"
+      "brk 0xc470 \n"
+      /* Outputs */  :
+      /* Inputs */   :
+      /* Clobbers */ : "x16"
+  );
+
+  return 1;
+}
Index: lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/TestPtrauthBRKc47xX16Invalid.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/TestPtrauthBRKc47xX16Invalid.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+        [decorators.skipIf(archs=decorators.no_match(['arm64e']))])
Index: lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := brkC47x.c
+include Makefile.rules
Index: lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/brkC47x.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/brkC47x.c
@@ -0,0 +1,17 @@
+void foo() {}
+
+int main() {
+  //% self.filecheck("c", "brkC47x.c")
+  // CHECK: stop reason = EXC_BAD_ACCESS
+  // CHECK-NEXT: Note: Possible pointer authentication failure detected.
+  // CHECK-NEXT: Found value that failed to authenticate at address=0x{{.*}} (brkC47x.c:1:13).
+  asm volatile (
+      "mov x16, %[target] \n"
+      "brk 0xc470 \n"
+      /* Outputs */  :
+      /* Inputs */   : [target] "r"(&foo)
+      /* Clobbers */ : "x16"
+  );
+
+  return 1;
+}
Index: lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/TestPtrauthBRKc47xDiagnostic.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/TestPtrauthBRKc47xDiagnostic.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+        [decorators.skipIf(archs=decorators.no_match(['arm64e']))])
Index: lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/brkC47x_code/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := brkC47x.c
+include Makefile.rules
Index: lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/ldraa.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/ldraa.c
@@ -0,0 +1,31 @@
+int main() {
+  //% self.filecheck("c", "ldraa.c")
+  // CHECK: EXC_BAD_ACCESS
+  // CHECK-NEXT: Note: Possible pointer authentication failure detected.
+  // CHECK-NEXT: Found authenticated load instruction at address=0x{{.*}} (ldraa.c:[[@LINE+3]]:3).
+  long long foo = 0;
+
+  asm volatile (
+      "ldraa x9, [%[target]] \n"
+      /* Outputs */  :
+      /* Inputs */   : [target] "r"(&foo)
+      /* Clobbers */ :
+  );
+
+  return 1;
+}
+
+// Expected codegen, register state, and exception message without ptrauth diagnostics:
+// * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2000016fdffc38)
+//     frame #0: 0x0000000100007fa8 ldraa`main + 12
+// ldraa`main:
+// ->  0x100007fa8 <+12>: ldraa  x9, [x8]
+//     0x100007fac <+16>: orr    w0, wzr, #0x1
+//     0x100007fb0 <+20>: add    sp, sp, #0x10             ; =0x10
+//     0x100007fb4 <+24>: ret
+// Target 0: (ldraa) stopped.
+// (lldb) p/x $x8
+// (unsigned long) $0 = 0x000000016fdffc38
+// (lldb) x/8 $x8
+// 0x16fdffc38: 0x00000000 0x00000000 0x80254f30 0x00000001
+// 0x16fdffc48: 0x00000000 0x00000000 0x00000000 0x00000000
Index: lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/TestPtrauthLDRAADiagnostic.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/TestPtrauthLDRAADiagnostic.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+        [decorators.skipIf(archs=decorators.no_match(['arm64e']))])
Index: lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/LDRAA_error/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := ldraa.c
+include Makefile.rules
Index: lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/braa.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/braa.c
@@ -0,0 +1,29 @@
+void foo() {}
+
+int main() {
+  //% self.filecheck("c", "braa.c")
+  // CHECK: stop reason = EXC_BAD_ACCESS
+  //
+  // TODO: We need call site info support for indirect calls to make this work.
+  // CHECK-NOT: pointer authentication failure
+  asm volatile (
+      "mov x9, #0xbad \n"
+      "braa %[target], x9 \n"
+      /* Outputs */  :
+      /* Inputs */   : [target] "r"(&foo)
+      /* Clobbers */ : "x9"
+  );
+
+  return 1;
+}
+
+// Expected codegen and exception message without ptrauth diagnostics:
+// * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2000000100007f9c)
+//     frame #0: 0x0000000100007f9c braa`foo
+// braa`foo:
+//     0x100007f9c <+0>: ret
+//
+// braa`main:
+//     0x100007fa0 <+0>: nop
+//     0x100007fa4 <+4>: ldr    x8, #0x5c
+//     0x100007fa8 <+8>: mov    x9, #0xbad
Index: lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/TestPtrauthBRAADiagnostic.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/TestPtrauthBRAADiagnostic.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+        [decorators.skipIf(archs=decorators.no_match(['arm64e']))])
Index: lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/BRAA_error/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := braa.c
+include Makefile.rules
Index: lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/blraa.c
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/blraa.c
@@ -0,0 +1,28 @@
+void foo() {}
+
+int main() {
+  //% self.filecheck("c", "blraa.c")
+  // CHECK: stop reason = EXC_BAD_ACCESS
+  // CHECK-NEXT: Note: Possible pointer authentication failure detected.
+  // CHECK-NEXT: Found authenticated indirect branch at address=0x{{.*}} (blraa.c:[[@LINE+1]]:3).
+  asm volatile (
+      "mov x9, #0xbad \n"
+      "blraa %[target], x9 \n"
+      /* Outputs */  :
+      /* Inputs */   : [target] "r"(&foo)
+      /* Clobbers */ : "x9"
+  );
+
+  return 1;
+}
+
+// Expected codegen and exception message without ptrauth diagnostics:
+// * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x2000000100007f9c)
+//     frame #0: 0x0000000100007f9c blraa2`foo
+// blraa2`foo:
+//     0x100007f9c <+0>: ret
+//
+// blraa2`main:
+//     0x100007fa0 <+0>: nop
+//     0x100007fa4 <+4>: ldr    x8, #0x5c
+//     0x100007fa8 <+8>: mov    x9, #0xbad
Index: lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/TestPtrauthBLRAADiagnostic.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/TestPtrauthBLRAADiagnostic.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+        [decorators.skipIf(archs=decorators.no_match(['arm64e']))])
Index: lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/ptrauth_diagnostics/BLRAA_error/Makefile
@@ -0,0 +1,2 @@
+C_SOURCES := blraa.c
+include Makefile.rules
Index: lldb/source/Plugins/Process/Utility/StopInfoMachException.h
===================================================================
--- lldb/source/Plugins/Process/Utility/StopInfoMachException.h
+++ lldb/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -16,6 +16,11 @@
 namespace lldb_private {
 
 class StopInfoMachException : public StopInfo {
+  /// Determine the pointer-authentication related failure that caused this
+  /// exception. Returns true and fills out the failure description if there
+  /// is auth-related failure, and returns false otherwise.
+  bool DeterminePtrauthFailure(ExecutionContext &exe_ctx);
+
 public:
   // Constructors and Destructors
   StopInfoMachException(Thread &thread, uint32_t exc_type,
Index: lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
===================================================================
--- lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -17,6 +17,7 @@
 
 #include "lldb/Breakpoint/Watchpoint.h"
 #include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ABI.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
@@ -30,6 +31,182 @@
 using namespace lldb;
 using namespace lldb_private;
 
+/// Information about a pointer-authentication related instruction.
+struct PtrauthInstructionInfo {
+  bool IsAuthenticated;
+  bool IsLoad;
+  bool DoesBranch;
+};
+
+/// Get any pointer-authentication related information about the instruction
+/// at address \p at_addr.
+static llvm::Optional<PtrauthInstructionInfo>
+GetPtrauthInstructionInfo(Target &target, const ArchSpec &arch,
+                          const Address &at_addr) {
+  const char *plugin_name = nullptr;
+  const char *flavor = nullptr;
+  AddressRange range_bounds(at_addr, 4);
+  const bool prefer_file_cache = true;
+  DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(
+      arch, plugin_name, flavor, target, range_bounds, prefer_file_cache);
+  if (!disassembler_sp)
+    return llvm::None;
+
+  InstructionList &insn_list = disassembler_sp->GetInstructionList();
+  InstructionSP insn = insn_list.GetInstructionAtIndex(0);
+  if (!insn)
+    return llvm::None;
+
+  return PtrauthInstructionInfo{insn->IsAuthenticated(), insn->IsLoad(),
+                                insn->DoesBranch()};
+}
+
+/// Describe the load address of \p addr using the format filename:line:col.
+static void DescribeAddressBriefly(Stream &strm, const Address &addr,
+                                   Target &target) {
+  strm.Printf("at address=0x%" PRIx64, addr.GetLoadAddress(&target));
+  StreamString s;
+  if (addr.GetDescription(s, target, eDescriptionLevelBrief))
+    strm.Printf(" %s", s.GetString().data());
+  strm.Printf(".\n");
+}
+
+bool StopInfoMachException::DeterminePtrauthFailure(ExecutionContext &exe_ctx) {
+  bool IsBreakpoint = m_value == 6; // EXC_BREAKPOINT
+  bool IsBadAccess = m_value == 1;  // EXC_BAD_ACCESS
+  if (!IsBreakpoint && !IsBadAccess)
+    return false;
+
+  // Check that we have a live process.
+  if (!exe_ctx.HasProcessScope() || !exe_ctx.HasThreadScope() ||
+      !exe_ctx.HasTargetScope())
+    return false;
+
+  Thread &thread = *exe_ctx.GetThreadPtr();
+  StackFrameSP current_frame = thread.GetStackFrameAtIndex(0);
+  if (!current_frame)
+    return false;
+
+  Target &target = *exe_ctx.GetTargetPtr();
+  Process &process = *exe_ctx.GetProcessPtr();
+  ABISP abi_sp = process.GetABI();
+  const ArchSpec &arch = target.GetArchitecture();
+  assert(abi_sp && "Missing ABI info");
+
+  // Check for a ptrauth-enabled target.
+  const bool ptrauth_enabled_target =
+      arch.GetCore() == ArchSpec::eCore_arm_arm64e;
+  if (!ptrauth_enabled_target)
+    return false;
+
+  // Set up a stream we can write a diagnostic into.
+  StreamString strm;
+  auto emit_ptrauth_prologue = [&](uint64_t at_address) {
+    strm.Printf("EXC_BAD_ACCESS (code=%" PRIu64 ", address=0x%" PRIx64 ")\n",
+                m_exc_code, at_address);
+    strm.Printf("Note: Possible pointer authentication failure detected.\n");
+  };
+
+  // Check if we have a "brk 0xc47x" trap, where the value that failed to
+  // authenticate is in x16.
+  Address current_address = current_frame->GetFrameCodeAddress();
+  if (IsBreakpoint) {
+    RegisterContext *reg_ctx = exe_ctx.GetRegisterContext();
+    if (!reg_ctx)
+      return false;
+
+    const RegisterInfo *X16Info = reg_ctx->GetRegisterInfoByName("x16");
+    RegisterValue X16Val;
+    if (!reg_ctx->ReadRegister(X16Info, X16Val))
+      return false;
+    uint64_t bad_address = X16Val.GetAsUInt64();
+
+    uint64_t fixed_bad_address = abi_sp->FixCodeAddress(bad_address);
+    Address brk_address;
+    if (!target.ResolveLoadAddress(fixed_bad_address, brk_address))
+      return false;
+
+    auto brk_ptrauth_info =
+        GetPtrauthInstructionInfo(target, arch, current_address);
+    if (brk_ptrauth_info && brk_ptrauth_info->IsAuthenticated) {
+      emit_ptrauth_prologue(bad_address);
+      strm.Printf("Found value that failed to authenticate ");
+      DescribeAddressBriefly(strm, brk_address, target);
+      m_description = std::string(strm.GetString());
+      return true;
+    }
+    return false;
+  }
+
+  assert(IsBadAccess && "Handle EXC_BAD_ACCESS only after this point");
+
+  // Check that we have the "bad address" from an EXC_BAD_ACCESS.
+  if (m_exc_data_count < 2)
+    return false;
+
+  // Ok, we know the Target is valid and that it describes a ptrauth-enabled
+  // device. Now, we need to determine whether this exception was caused by a
+  // ptrauth failure.
+
+  uint64_t bad_address = m_exc_subcode;
+  uint64_t fixed_bad_address = abi_sp->FixCodeAddress(bad_address);
+  uint64_t current_pc = current_address.GetLoadAddress(&target);
+
+  // Detect: LDRAA, LDRAB (Load Register, with pointer authentication).
+  //
+  // If an authenticated load results in an exception, the instruction at the
+  // current PC should be one of LDRAx.
+  if (bad_address != current_pc && fixed_bad_address != current_pc) {
+    auto ptrauth_info =
+        GetPtrauthInstructionInfo(target, arch, current_address);
+    if (ptrauth_info && ptrauth_info->IsAuthenticated && ptrauth_info->IsLoad) {
+      emit_ptrauth_prologue(bad_address);
+      strm.Printf("Found authenticated load instruction ");
+      DescribeAddressBriefly(strm, current_address, target);
+      m_description = std::string(strm.GetString());
+      return true;
+    }
+  }
+
+  // Detect: BLRAA, BLRAAZ, BLRAB, BLRABZ (Branch with Link to Register, with
+  // pointer authentication).
+  //
+  // TODO: Detect: BRAA, BRAAZ, BRAB, BRABZ (Branch to Register, with pointer
+  // authentication). At a minimum, this requires call site info support for
+  // indirect calls.
+  //
+  // If an authenticated call or tail call results in an exception, stripping
+  // the bad address should give the current PC, which points to the address
+  // we tried to branch to.
+  if (bad_address != current_pc && fixed_bad_address == current_pc) {
+    if (StackFrameSP parent_frame = thread.GetStackFrameAtIndex(1)) {
+      addr_t return_pc =
+          parent_frame->GetFrameCodeAddress().GetLoadAddress(&target);
+      Address blr_address;
+      if (!target.ResolveLoadAddress(return_pc - 4, blr_address))
+        return false;
+
+      auto blr_ptrauth_info =
+          GetPtrauthInstructionInfo(target, arch, blr_address);
+      if (blr_ptrauth_info && blr_ptrauth_info->IsAuthenticated &&
+          blr_ptrauth_info->DoesBranch) {
+        emit_ptrauth_prologue(bad_address);
+        strm.Printf("Found authenticated indirect branch ");
+        DescribeAddressBriefly(strm, blr_address, target);
+        m_description = std::string(strm.GetString());
+        return true;
+      }
+    }
+  }
+
+  // TODO: Detect: RETAA, RETAB (Return from subroutine, with pointer
+  // authentication).
+  //
+  // Is there a motivating, non-malicious code snippet that corrupts LR?
+
+  return false;
+}
+
 const char *StopInfoMachException::GetDescription() {
   if (!m_description.empty())
     return m_description.c_str();
@@ -79,6 +256,11 @@
       }
       break;
 
+    case llvm::Triple::aarch64:
+      if (DeterminePtrauthFailure(exe_ctx))
+        return m_description.c_str();
+      break;
+
     default:
       break;
     }
@@ -190,6 +372,11 @@
       }
       break;
 
+    case llvm::Triple::aarch64:
+      if (DeterminePtrauthFailure(exe_ctx))
+        return m_description.c_str();
+      break;
+
     default:
       break;
     }
Index: lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
===================================================================
--- lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
+++ lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp
@@ -61,6 +61,8 @@
   bool CanBranch(llvm::MCInst &mc_inst) const;
   bool HasDelaySlot(llvm::MCInst &mc_inst) const;
   bool IsCall(llvm::MCInst &mc_inst) const;
+  bool IsLoad(llvm::MCInst &mc_inst) const;
+  bool IsAuthenticated(llvm::MCInst &mc_inst) const;
 
 private:
   MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
@@ -102,6 +104,16 @@
     return m_has_delay_slot;
   }
 
+  bool IsLoad() override {
+    VisitInstruction();
+    return m_is_load;
+  }
+
+  bool IsAuthenticated() override {
+    VisitInstruction();
+    return m_is_authenticated;
+  }
+
   DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) {
     DisassemblerScope disasm(*this);
     return GetDisasmToUse(is_alternate_isa, disasm);
@@ -817,9 +829,13 @@
   //   - Might branch
   //   - Does not have a delay slot
   //   - Is not a call
+  //   - Is not a load
+  //   - Is not an authenticated instruction
   bool m_does_branch = true;
   bool m_has_delay_slot = false;
   bool m_is_call = false;
+  bool m_is_load = false;
+  bool m_is_authenticated = false;
 
   void VisitInstruction() {
     if (m_has_visited_instruction)
@@ -849,6 +865,8 @@
     m_does_branch = mc_disasm_ptr->CanBranch(inst);
     m_has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
     m_is_call = mc_disasm_ptr->IsCall(inst);
+    m_is_load = mc_disasm_ptr->IsLoad(inst);
+    m_is_authenticated = mc_disasm_ptr->IsAuthenticated(inst);
   }
 
 private:
@@ -1027,6 +1045,27 @@
   return m_instr_info_up->get(mc_inst.getOpcode()).isCall();
 }
 
+bool DisassemblerLLVMC::MCDisasmInstance::IsLoad(llvm::MCInst &mc_inst) const {
+  return m_instr_info_up->get(mc_inst.getOpcode()).mayLoad();
+}
+
+bool DisassemblerLLVMC::MCDisasmInstance::IsAuthenticated(
+    llvm::MCInst &mc_inst) const {
+  auto InstrDesc = m_instr_info_up->get(mc_inst.getOpcode());
+
+  // Treat software auth traps (brk 0xc470 + aut key, where 0x70 == 'p', 0xc4
+  // == 'a' + 'c') as authenticated instructions for reporting purposes, in
+  // addition to the standard authenticated instructions specified in ARMv8.3.
+  bool IsBrkC47x = false;
+  if (InstrDesc.isTrap() && mc_inst.getNumOperands() == 1) {
+    const llvm::MCOperand &Op0 = mc_inst.getOperand(0);
+    if (Op0.isImm() && Op0.getImm() >= 0xc470 && Op0.getImm() <= 0xc474)
+      IsBrkC47x = true;
+  }
+
+  return InstrDesc.isAuthenticated() || IsBrkC47x;
+}
+
 DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
                                      const char *flavor_string)
     : Disassembler(arch, flavor_string), m_exe_ctx(nullptr), m_inst(nullptr),
Index: lldb/source/Core/Disassembler.cpp
===================================================================
--- lldb/source/Core/Disassembler.cpp
+++ lldb/source/Core/Disassembler.cpp
@@ -1123,6 +1123,10 @@
   return false;
 }
 
+bool PseudoInstruction::IsLoad() { return false; }
+
+bool PseudoInstruction::IsAuthenticated() { return false; }
+
 size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler,
                                  const lldb_private::DataExtractor &data,
                                  lldb::offset_t data_offset) {
Index: lldb/source/Core/Address.cpp
===================================================================
--- lldb/source/Core/Address.cpp
+++ lldb/source/Core/Address.cpp
@@ -389,6 +389,19 @@
   return false;
 }
 
+bool Address::GetDescription(Stream &s, Target &target,
+                             DescriptionLevel level) const {
+  assert(level == eDescriptionLevelBrief &&
+         "Non-brief descriptions not implemented");
+  LineEntry line_entry;
+  if (CalculateSymbolContextLineEntry(line_entry)) {
+    s.Printf(" (%s:%u:%u)", line_entry.file.GetFilename().GetCString(),
+             line_entry.line, line_entry.column);
+    return true;
+  }
+  return false;
+}
+
 bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
                    DumpStyle fallback_style, uint32_t addr_size) const {
   // If the section was nullptr, only load address is going to work unless we
Index: lldb/include/lldb/Core/Disassembler.h
===================================================================
--- lldb/include/lldb/Core/Disassembler.h
+++ lldb/include/lldb/Core/Disassembler.h
@@ -150,6 +150,10 @@
 
   virtual bool HasDelaySlot();
 
+  virtual bool IsLoad() = 0;
+
+  virtual bool IsAuthenticated() = 0;
+
   bool CanSetBreakpoint ();
 
   virtual size_t Decode(const Disassembler &disassembler,
@@ -336,6 +340,10 @@
 
   bool HasDelaySlot() override;
 
+  bool IsLoad() override;
+
+  bool IsAuthenticated() override;
+
   void CalculateMnemonicOperandsAndComment(
       const ExecutionContext *exe_ctx) override {
     // TODO: fill this in and put opcode name into Instruction::m_opcode_name,
Index: lldb/include/lldb/Core/Address.h
===================================================================
--- lldb/include/lldb/Core/Address.h
+++ lldb/include/lldb/Core/Address.h
@@ -210,6 +210,10 @@
     }
   };
 
+  /// Write a description of this object to a Stream.
+  bool GetDescription(Stream &s, Target &target,
+                      lldb::DescriptionLevel level) const;
+
   /// Dump a description of this object to a Stream.
   ///
   /// Dump a description of the contents of this object to the supplied stream
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to