brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · 69d4cfd Raw
164 lines · cpp
1//===-- ThreadKDP.cpp -----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ThreadKDP.h"10 11#include "lldb/Host/SafeMachO.h"12 13#include "lldb/Breakpoint/Watchpoint.h"14#include "lldb/Target/Process.h"15#include "lldb/Target/RegisterContext.h"16#include "lldb/Target/StopInfo.h"17#include "lldb/Target/Target.h"18#include "lldb/Target/Unwind.h"19#include "lldb/Utility/ArchSpec.h"20#include "lldb/Utility/DataExtractor.h"21#include "lldb/Utility/State.h"22#include "lldb/Utility/StreamString.h"23 24#include "Plugins/Process/Utility/StopInfoMachException.h"25#include "ProcessKDP.h"26#include "ProcessKDPLog.h"27#include "RegisterContextKDP_arm.h"28#include "RegisterContextKDP_arm64.h"29#include "RegisterContextKDP_x86_64.h"30 31#include <memory>32 33using namespace lldb;34using namespace lldb_private;35 36// Thread Registers37 38ThreadKDP::ThreadKDP(Process &process, lldb::tid_t tid)39    : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(),40      m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS) {41  Log *log = GetLog(KDPLog::Thread);42  LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID());43}44 45ThreadKDP::~ThreadKDP() {46  Log *log = GetLog(KDPLog::Thread);47  LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID());48  DestroyThread();49}50 51const char *ThreadKDP::GetName() {52  if (m_thread_name.empty())53    return nullptr;54  return m_thread_name.c_str();55}56 57const char *ThreadKDP::GetQueueName() { return nullptr; }58 59void ThreadKDP::RefreshStateAfterStop() {60  // Invalidate all registers in our register context. We don't set "force" to61  // true because the stop reply packet might have had some register values62  // that were expedited and these will already be copied into the register63  // context by the time this function gets called. The KDPRegisterContext64  // class has been made smart enough to detect when it needs to invalidate65  // which registers are valid by putting hooks in the register read and66  // register supply functions where they check the process stop ID and do the67  // right thing.68  const bool force = false;69  lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());70  if (reg_ctx_sp)71    reg_ctx_sp->InvalidateIfNeeded(force);72}73 74bool ThreadKDP::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }75 76void ThreadKDP::Dump(Log *log, uint32_t index) {}77 78bool ThreadKDP::ShouldStop(bool &step_more) { return true; }79lldb::RegisterContextSP ThreadKDP::GetRegisterContext() {80  if (!m_reg_context_sp)81    m_reg_context_sp = CreateRegisterContextForFrame(nullptr);82  return m_reg_context_sp;83}84 85lldb::RegisterContextSP86ThreadKDP::CreateRegisterContextForFrame(StackFrame *frame) {87  lldb::RegisterContextSP reg_ctx_sp;88  uint32_t concrete_frame_idx = 0;89 90  if (frame)91    concrete_frame_idx = frame->GetConcreteFrameIndex();92 93  if (concrete_frame_idx == 0) {94    ProcessSP process_sp(CalculateProcess());95    if (process_sp) {96      switch (static_cast<ProcessKDP *>(process_sp.get())97                  ->GetCommunication()98                  .GetCPUType()) {99      case llvm::MachO::CPU_TYPE_ARM:100        reg_ctx_sp =101            std::make_shared<RegisterContextKDP_arm>(*this, concrete_frame_idx);102        break;103      case llvm::MachO::CPU_TYPE_ARM64:104        reg_ctx_sp = std::make_shared<RegisterContextKDP_arm64>(105            *this, concrete_frame_idx);106        break;107      case llvm::MachO::CPU_TYPE_X86_64:108        reg_ctx_sp = std::make_shared<RegisterContextKDP_x86_64>(109            *this, concrete_frame_idx);110        break;111      default:112        llvm_unreachable("Add CPU type support in KDP");113      }114    }115  } else {116    reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);117  }118  return reg_ctx_sp;119}120 121bool ThreadKDP::CalculateStopInfo() {122  ProcessSP process_sp(GetProcess());123  if (process_sp) {124    if (m_cached_stop_info_sp) {125      SetStopInfo(m_cached_stop_info_sp);126    } else {127      SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP));128    }129    return true;130  }131  return false;132}133 134void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION(135    const DataExtractor &exc_reply_packet) {136  lldb::offset_t offset = 0;137  uint8_t reply_command = exc_reply_packet.GetU8(&offset);138  if (reply_command == CommunicationKDP::KDP_EXCEPTION) {139    offset = 8;140    const uint32_t count = exc_reply_packet.GetU32(&offset);141    if (count >= 1) {142      // const uint32_t cpu = exc_reply_packet.GetU32 (&offset);143      offset += 4; // Skip the useless CPU field144      const uint32_t exc_type = exc_reply_packet.GetU32(&offset);145      const uint32_t exc_code = exc_reply_packet.GetU32(&offset);146      const uint32_t exc_subcode = exc_reply_packet.GetU32(&offset);147      // We have to make a copy of the stop info because the thread list will148      // iterate through the threads and clear all stop infos..149 150      // Let the StopInfoMachException::CreateStopReasonWithMachException()151      // function update the PC if needed as we might hit a software breakpoint152      // and need to decrement the PC (i386 and x86_64 need this) and KDP153      // doesn't do this for us.154      const bool pc_already_adjusted = false;155      const bool adjust_pc_if_needed = true;156 157      m_cached_stop_info_sp =158          StopInfoMachException::CreateStopReasonWithMachException(159              *this, exc_type, 2, exc_code, exc_subcode, 0, pc_already_adjusted,160              adjust_pc_if_needed);161    }162  }163}164