brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · eddf4b9 Raw
146 lines · cpp
1//===-- NativeProcessSoftwareSingleStep.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 "NativeProcessSoftwareSingleStep.h"10 11#include "lldb/Core/EmulateInstruction.h"12#include "lldb/Host/common/NativeRegisterContext.h"13#include "lldb/Utility/RegisterValue.h"14 15#include <unordered_map>16 17using namespace lldb;18using namespace lldb_private;19 20namespace {21 22struct EmulatorBaton {23  NativeProcessProtocol &m_process;24  NativeRegisterContext &m_reg_context;25 26  // eRegisterKindDWARF -> RegsiterValue27  std::unordered_map<uint32_t, RegisterValue> m_register_values;28 29  EmulatorBaton(NativeProcessProtocol &process,30                NativeRegisterContext &reg_context)31      : m_process(process), m_reg_context(reg_context) {}32};33 34} // anonymous namespace35 36static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,37                                 const EmulateInstruction::Context &context,38                                 lldb::addr_t addr, void *dst, size_t length) {39  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);40 41  size_t bytes_read;42  emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read);43  return bytes_read;44}45 46static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,47                                 const RegisterInfo *reg_info,48                                 RegisterValue &reg_value) {49  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);50 51  auto it = emulator_baton->m_register_values.find(52      reg_info->kinds[eRegisterKindDWARF]);53  if (it != emulator_baton->m_register_values.end()) {54    reg_value = it->second;55    return true;56  }57 58  // The emulator only fill in the dwarf regsiter numbers (and in some case the59  // generic register numbers). Get the full register info from the register60  // context based on the dwarf register numbers.61  const RegisterInfo *full_reg_info =62      emulator_baton->m_reg_context.GetRegisterInfo(63          eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);64 65  Status error =66      emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value);67  if (error.Success())68    return true;69 70  return false;71}72 73static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton,74                                  const EmulateInstruction::Context &context,75                                  const RegisterInfo *reg_info,76                                  const RegisterValue &reg_value) {77  EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton);78  emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] =79      reg_value;80  return true;81}82 83static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton,84                                  const EmulateInstruction::Context &context,85                                  lldb::addr_t addr, const void *dst,86                                  size_t length) {87  return length;88}89 90static Status SetSoftwareBreakpoint(lldb::addr_t bp_addr, unsigned bp_size,91                                    NativeProcessProtocol &process) {92  Status error;93  error = process.SetBreakpoint(bp_addr, bp_size, /*hardware=*/false);94 95  // If setting the breakpoint fails because pc is out of the address96  // space, ignore it and let the debugee segfault.97  if (error.GetError() == EIO || error.GetError() == EFAULT)98    return Status();99  if (error.Fail())100    return error;101 102  return Status();103}104 105Status NativeProcessSoftwareSingleStep::SetupSoftwareSingleStepping(106    NativeThreadProtocol &thread) {107  Status error;108  NativeProcessProtocol &process = thread.GetProcess();109  NativeRegisterContext &register_context = thread.GetRegisterContext();110  const ArchSpec &arch = process.GetArchitecture();111 112  std::unique_ptr<EmulateInstruction> emulator_up(113      EmulateInstruction::FindPlugin(arch, eInstructionTypePCModifying,114                                     nullptr));115  if (emulator_up == nullptr)116    return Status::FromErrorString("Instruction emulator not found!");117 118  EmulatorBaton baton(process, register_context);119  emulator_up->SetBaton(&baton);120  emulator_up->SetReadMemCallback(&ReadMemoryCallback);121  emulator_up->SetReadRegCallback(&ReadRegisterCallback);122  emulator_up->SetWriteMemCallback(&WriteMemoryCallback);123  emulator_up->SetWriteRegCallback(&WriteRegisterCallback);124 125  auto bp_locaions_predictor =126      EmulateInstruction::CreateBreakpointLocationPredictor(127          std::move(emulator_up));128 129  auto bp_locations = bp_locaions_predictor->GetBreakpointLocations(error);130  if (error.Fail())131    return error;132 133  for (auto &&bp_addr : bp_locations) {134    auto bp_size = bp_locaions_predictor->GetBreakpointSize(bp_addr);135    if (auto err = bp_size.takeError())136      return Status(toString(std::move(err)));137 138    error = SetSoftwareBreakpoint(bp_addr, *bp_size, process);139    if (error.Fail())140      return error;141  }142 143  m_threads_stepping_with_breakpoint.insert({thread.GetID(), bp_locations});144  return error;145}146