================
@@ -150,3 +158,161 @@ addr_t ArchitectureArm::GetOpcodeLoadAddress(addr_t 
opcode_addr,
   }
   return opcode_addr & ~(1ull);
 }
+
+// The ARM M-Profile Armv7-M Architecture Reference Manual
+// "Exception return behavior" describes how the processor
+// saves registers to the stack, decrements the stack pointer,
+// puts a special value in $lr, and then calls a registered
+// exception handler routine.
+//
+// Detect that special value in $lr, and if present, add
+// unwind rules for the registers that were saved above this
+// stack frame's CFA.  Overwrite any register locations that
+// the current_unwindplan has for these registers; they are
+// not correct when we're invoked this way.
+UnwindPlanSP ArchitectureArm::GetArchitectureUnwindPlan(
+    Thread &thread, RegisterContextUnwind *regctx,
+    std::shared_ptr<const UnwindPlan> current_unwindplan) {
+
+  ProcessSP process_sp = thread.GetProcess();
+  if (!process_sp)
+    return {};
+
+  const ArchSpec arch = process_sp->GetTarget().GetArchitecture();
+  if (!arch.GetTriple().isArmMClass() || arch.GetAddressByteSize() != 4)
+    return {};
+
+  // Get the caller's LR value from regctx (the LR value
+  // at function entry to this function).
+  RegisterNumber ra_regnum(thread, eRegisterKindGeneric,
+                           LLDB_REGNUM_GENERIC_RA);
+  uint32_t ra_regnum_lldb = ra_regnum.GetAsKind(eRegisterKindLLDB);
+
+  if (ra_regnum_lldb == LLDB_INVALID_REGNUM)
+    return {};
+
+  UnwindLLDB::ConcreteRegisterLocation regloc = {};
+  bool got_concrete_location = false;
+  if (regctx->SavedLocationForRegister(ra_regnum_lldb, regloc) ==
+      UnwindLLDB::RegisterSearchResult::eRegisterFound) {
+    got_concrete_location = true;
+  } else {
+    RegisterNumber pc_regnum(thread, eRegisterKindGeneric,
+                             LLDB_REGNUM_GENERIC_PC);
+    uint32_t pc_regnum_lldb = pc_regnum.GetAsKind(eRegisterKindLLDB);
+    if (regctx->SavedLocationForRegister(pc_regnum_lldb, regloc) ==
+        UnwindLLDB::RegisterSearchResult::eRegisterFound)
+      got_concrete_location = true;
+  }
+
+  addr_t callers_return_address = LLDB_INVALID_ADDRESS;
+  if (got_concrete_location) {
+    const RegisterInfo *reg_info =
+        regctx->GetRegisterInfoAtIndex(ra_regnum_lldb);
+    if (reg_info) {
+      RegisterValue reg_value;
+      if (regctx->ReadRegisterValueFromRegisterLocation(regloc, reg_info,
+                                                        reg_value)) {
+        callers_return_address = reg_value.GetAsUInt32();
+      }
+    }
+  }
+
+  if (callers_return_address == LLDB_INVALID_ADDRESS)
+    return {};
+
+  if (callers_return_address != 0xFFFFFFF1 &&
+      callers_return_address != 0xFFFFFFF9 &&
+      callers_return_address != 0xFFFFFFFD &&
+      callers_return_address != 0xFFFFFFE1 &&
+      callers_return_address != 0xFFFFFFE9 &&
+      callers_return_address != 0xFFFFFFED)
+    return {};
+
+  const RegisterKind plan_regkind = current_unwindplan->GetRegisterKind();
+  UnwindPlanSP new_plan = std::make_shared<UnwindPlan>(plan_regkind);
+  new_plan->SetSourceName("Arm Cortex-M exception return UnwindPlan");
+  new_plan->SetSourcedFromCompiler(eLazyBoolNo);
+  new_plan->SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
+  new_plan->SetUnwindPlanForSignalTrap(eLazyBoolYes);
+
+  // bit 4 will be 1 if only the general purpose registers were saved.
+  // bit 4 will be 0 if the GPRs + floating point registers were saved.
+  const bool fp_regs_saved = (callers_return_address & 0x10) == 0;
+
+  int stored_regs_size = 0x20;
+  if (fp_regs_saved)
+    stored_regs_size = 0x68;
+
+  uint32_t gpr_regs[] = {dwarf_r0,  dwarf_r1, dwarf_r2, dwarf_r3,
+                         dwarf_r12, dwarf_lr, dwarf_pc, dwarf_cpsr};
+  const int gpr_reg_count = sizeof(gpr_regs) / sizeof(uint32_t);
----------------
DavidSpickett wrote:

You can use https://en.cppreference.com/w/cpp/iterator/size.html for this.

I thought we had a macro for it, must have been replaced with std::size some 
time ago.

https://github.com/llvm/llvm-project/pull/153922
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to