mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 03:25:54 -04:00

Summary: A *.cpp file header in LLDB (and in LLDB) should like this: ``` //===-- TestUtilities.cpp -------------------------------------------------===// ``` However in LLDB most of our source files have arbitrary changes to this format and these changes are spreading through LLDB as folks usually just use the existing source files as templates for their new files (most notably the unnecessary editor language indicator `-*- C++ -*-` is spreading and in every review someone is pointing out that this is wrong, resulting in people pointing out that this is done in the same way in other files). This patch removes most of these inconsistencies including the editor language indicators, all the different missing/additional '-' characters, files that center the file name, missing trailing `===//` (mostly caused by clang-format breaking the line). Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere Reviewed By: JDevlieghere Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D73258
586 lines
19 KiB
C++
586 lines
19 KiB
C++
//===-- EmulateInstruction.cpp --------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Core/EmulateInstruction.h"
|
|
|
|
#include "lldb/Core/Address.h"
|
|
#include "lldb/Core/DumpRegisterValue.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Core/StreamFile.h"
|
|
#include "lldb/Symbol/UnwindPlan.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Target/RegisterContext.h"
|
|
#include "lldb/Target/StackFrame.h"
|
|
#include "lldb/Utility/ConstString.h"
|
|
#include "lldb/Utility/DataExtractor.h"
|
|
#include "lldb/Utility/RegisterValue.h"
|
|
#include "lldb/Utility/Status.h"
|
|
#include "lldb/Utility/Stream.h"
|
|
#include "lldb/Utility/StreamString.h"
|
|
#include "lldb/lldb-forward.h"
|
|
#include "lldb/lldb-private-interfaces.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include <cstring>
|
|
#include <memory>
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
|
|
namespace lldb_private {
|
|
class Target;
|
|
}
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
EmulateInstruction *
|
|
EmulateInstruction::FindPlugin(const ArchSpec &arch,
|
|
InstructionType supported_inst_type,
|
|
const char *plugin_name) {
|
|
EmulateInstructionCreateInstance create_callback = nullptr;
|
|
if (plugin_name) {
|
|
ConstString const_plugin_name(plugin_name);
|
|
create_callback =
|
|
PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
|
|
const_plugin_name);
|
|
if (create_callback) {
|
|
EmulateInstruction *emulate_insn_ptr =
|
|
create_callback(arch, supported_inst_type);
|
|
if (emulate_insn_ptr)
|
|
return emulate_insn_ptr;
|
|
}
|
|
} else {
|
|
for (uint32_t idx = 0;
|
|
(create_callback =
|
|
PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) !=
|
|
nullptr;
|
|
++idx) {
|
|
EmulateInstruction *emulate_insn_ptr =
|
|
create_callback(arch, supported_inst_type);
|
|
if (emulate_insn_ptr)
|
|
return emulate_insn_ptr;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
EmulateInstruction::EmulateInstruction(const ArchSpec &arch) : m_arch(arch) {}
|
|
|
|
bool EmulateInstruction::ReadRegister(const RegisterInfo *reg_info,
|
|
RegisterValue ®_value) {
|
|
if (m_read_reg_callback != nullptr)
|
|
return m_read_reg_callback(this, m_baton, reg_info, reg_value);
|
|
return false;
|
|
}
|
|
|
|
bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind,
|
|
uint32_t reg_num,
|
|
RegisterValue ®_value) {
|
|
RegisterInfo reg_info;
|
|
if (GetRegisterInfo(reg_kind, reg_num, reg_info))
|
|
return ReadRegister(®_info, reg_value);
|
|
return false;
|
|
}
|
|
|
|
uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind,
|
|
uint32_t reg_num,
|
|
uint64_t fail_value,
|
|
bool *success_ptr) {
|
|
RegisterValue reg_value;
|
|
if (ReadRegister(reg_kind, reg_num, reg_value))
|
|
return reg_value.GetAsUInt64(fail_value, success_ptr);
|
|
if (success_ptr)
|
|
*success_ptr = false;
|
|
return fail_value;
|
|
}
|
|
|
|
uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo *reg_info,
|
|
uint64_t fail_value,
|
|
bool *success_ptr) {
|
|
RegisterValue reg_value;
|
|
if (ReadRegister(reg_info, reg_value))
|
|
return reg_value.GetAsUInt64(fail_value, success_ptr);
|
|
if (success_ptr)
|
|
*success_ptr = false;
|
|
return fail_value;
|
|
}
|
|
|
|
bool EmulateInstruction::WriteRegister(const Context &context,
|
|
const RegisterInfo *reg_info,
|
|
const RegisterValue ®_value) {
|
|
if (m_write_reg_callback != nullptr)
|
|
return m_write_reg_callback(this, m_baton, context, reg_info, reg_value);
|
|
return false;
|
|
}
|
|
|
|
bool EmulateInstruction::WriteRegister(const Context &context,
|
|
lldb::RegisterKind reg_kind,
|
|
uint32_t reg_num,
|
|
const RegisterValue ®_value) {
|
|
RegisterInfo reg_info;
|
|
if (GetRegisterInfo(reg_kind, reg_num, reg_info))
|
|
return WriteRegister(context, ®_info, reg_value);
|
|
return false;
|
|
}
|
|
|
|
bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
|
|
lldb::RegisterKind reg_kind,
|
|
uint32_t reg_num,
|
|
uint64_t uint_value) {
|
|
RegisterInfo reg_info;
|
|
if (GetRegisterInfo(reg_kind, reg_num, reg_info)) {
|
|
RegisterValue reg_value;
|
|
if (reg_value.SetUInt(uint_value, reg_info.byte_size))
|
|
return WriteRegister(context, ®_info, reg_value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool EmulateInstruction::WriteRegisterUnsigned(const Context &context,
|
|
const RegisterInfo *reg_info,
|
|
uint64_t uint_value) {
|
|
if (reg_info != nullptr) {
|
|
RegisterValue reg_value;
|
|
if (reg_value.SetUInt(uint_value, reg_info->byte_size))
|
|
return WriteRegister(context, reg_info, reg_value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
size_t EmulateInstruction::ReadMemory(const Context &context, lldb::addr_t addr,
|
|
void *dst, size_t dst_len) {
|
|
if (m_read_mem_callback != nullptr)
|
|
return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) ==
|
|
dst_len;
|
|
return false;
|
|
}
|
|
|
|
uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context &context,
|
|
lldb::addr_t addr,
|
|
size_t byte_size,
|
|
uint64_t fail_value,
|
|
bool *success_ptr) {
|
|
uint64_t uval64 = 0;
|
|
bool success = false;
|
|
if (byte_size <= 8) {
|
|
uint8_t buf[sizeof(uint64_t)];
|
|
size_t bytes_read =
|
|
m_read_mem_callback(this, m_baton, context, addr, buf, byte_size);
|
|
if (bytes_read == byte_size) {
|
|
lldb::offset_t offset = 0;
|
|
DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize());
|
|
uval64 = data.GetMaxU64(&offset, byte_size);
|
|
success = true;
|
|
}
|
|
}
|
|
|
|
if (success_ptr)
|
|
*success_ptr = success;
|
|
|
|
if (!success)
|
|
uval64 = fail_value;
|
|
return uval64;
|
|
}
|
|
|
|
bool EmulateInstruction::WriteMemoryUnsigned(const Context &context,
|
|
lldb::addr_t addr, uint64_t uval,
|
|
size_t uval_byte_size) {
|
|
StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder());
|
|
strm.PutMaxHex64(uval, uval_byte_size);
|
|
|
|
size_t bytes_written = m_write_mem_callback(
|
|
this, m_baton, context, addr, strm.GetString().data(), uval_byte_size);
|
|
return (bytes_written == uval_byte_size);
|
|
}
|
|
|
|
bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr,
|
|
const void *src, size_t src_len) {
|
|
if (m_write_mem_callback != nullptr)
|
|
return m_write_mem_callback(this, m_baton, context, addr, src, src_len) ==
|
|
src_len;
|
|
return false;
|
|
}
|
|
|
|
void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; }
|
|
|
|
void EmulateInstruction::SetCallbacks(
|
|
ReadMemoryCallback read_mem_callback,
|
|
WriteMemoryCallback write_mem_callback,
|
|
ReadRegisterCallback read_reg_callback,
|
|
WriteRegisterCallback write_reg_callback) {
|
|
m_read_mem_callback = read_mem_callback;
|
|
m_write_mem_callback = write_mem_callback;
|
|
m_read_reg_callback = read_reg_callback;
|
|
m_write_reg_callback = write_reg_callback;
|
|
}
|
|
|
|
void EmulateInstruction::SetReadMemCallback(
|
|
ReadMemoryCallback read_mem_callback) {
|
|
m_read_mem_callback = read_mem_callback;
|
|
}
|
|
|
|
void EmulateInstruction::SetWriteMemCallback(
|
|
WriteMemoryCallback write_mem_callback) {
|
|
m_write_mem_callback = write_mem_callback;
|
|
}
|
|
|
|
void EmulateInstruction::SetReadRegCallback(
|
|
ReadRegisterCallback read_reg_callback) {
|
|
m_read_reg_callback = read_reg_callback;
|
|
}
|
|
|
|
void EmulateInstruction::SetWriteRegCallback(
|
|
WriteRegisterCallback write_reg_callback) {
|
|
m_write_reg_callback = write_reg_callback;
|
|
}
|
|
|
|
//
|
|
// Read & Write Memory and Registers callback functions.
|
|
//
|
|
|
|
size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction *instruction,
|
|
void *baton, const Context &context,
|
|
lldb::addr_t addr, void *dst,
|
|
size_t dst_len) {
|
|
if (baton == nullptr || dst == nullptr || dst_len == 0)
|
|
return 0;
|
|
|
|
StackFrame *frame = (StackFrame *)baton;
|
|
|
|
ProcessSP process_sp(frame->CalculateProcess());
|
|
if (process_sp) {
|
|
Status error;
|
|
return process_sp->ReadMemory(addr, dst, dst_len, error);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction *instruction,
|
|
void *baton, const Context &context,
|
|
lldb::addr_t addr, const void *src,
|
|
size_t src_len) {
|
|
if (baton == nullptr || src == nullptr || src_len == 0)
|
|
return 0;
|
|
|
|
StackFrame *frame = (StackFrame *)baton;
|
|
|
|
ProcessSP process_sp(frame->CalculateProcess());
|
|
if (process_sp) {
|
|
Status error;
|
|
return process_sp->WriteMemory(addr, src, src_len, error);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction,
|
|
void *baton,
|
|
const RegisterInfo *reg_info,
|
|
RegisterValue ®_value) {
|
|
if (baton == nullptr)
|
|
return false;
|
|
|
|
StackFrame *frame = (StackFrame *)baton;
|
|
return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value);
|
|
}
|
|
|
|
bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction *instruction,
|
|
void *baton, const Context &context,
|
|
const RegisterInfo *reg_info,
|
|
const RegisterValue ®_value) {
|
|
if (baton == nullptr)
|
|
return false;
|
|
|
|
StackFrame *frame = (StackFrame *)baton;
|
|
return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value);
|
|
}
|
|
|
|
size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction *instruction,
|
|
void *baton,
|
|
const Context &context,
|
|
lldb::addr_t addr, void *dst,
|
|
size_t length) {
|
|
StreamFile strm(stdout, false);
|
|
strm.Printf(" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64
|
|
", context = ",
|
|
addr, (uint64_t)length);
|
|
context.Dump(strm, instruction);
|
|
strm.EOL();
|
|
*((uint64_t *)dst) = 0xdeadbeef;
|
|
return length;
|
|
}
|
|
|
|
size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction *instruction,
|
|
void *baton,
|
|
const Context &context,
|
|
lldb::addr_t addr,
|
|
const void *dst, size_t length) {
|
|
StreamFile strm(stdout, false);
|
|
strm.Printf(" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64
|
|
", context = ",
|
|
addr, (uint64_t)length);
|
|
context.Dump(strm, instruction);
|
|
strm.EOL();
|
|
return length;
|
|
}
|
|
|
|
bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction *instruction,
|
|
void *baton,
|
|
const RegisterInfo *reg_info,
|
|
RegisterValue ®_value) {
|
|
StreamFile strm(stdout, false);
|
|
strm.Printf(" Read Register (%s)\n", reg_info->name);
|
|
lldb::RegisterKind reg_kind;
|
|
uint32_t reg_num;
|
|
if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num))
|
|
reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num);
|
|
else
|
|
reg_value.SetUInt64(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction,
|
|
void *baton,
|
|
const Context &context,
|
|
const RegisterInfo *reg_info,
|
|
const RegisterValue ®_value) {
|
|
StreamFile strm(stdout, false);
|
|
strm.Printf(" Write to Register (name = %s, value = ", reg_info->name);
|
|
DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
|
|
strm.PutCString(", context = ");
|
|
context.Dump(strm, instruction);
|
|
strm.EOL();
|
|
return true;
|
|
}
|
|
|
|
void EmulateInstruction::Context::Dump(Stream &strm,
|
|
EmulateInstruction *instruction) const {
|
|
switch (type) {
|
|
case eContextReadOpcode:
|
|
strm.PutCString("reading opcode");
|
|
break;
|
|
|
|
case eContextImmediate:
|
|
strm.PutCString("immediate");
|
|
break;
|
|
|
|
case eContextPushRegisterOnStack:
|
|
strm.PutCString("push register");
|
|
break;
|
|
|
|
case eContextPopRegisterOffStack:
|
|
strm.PutCString("pop register");
|
|
break;
|
|
|
|
case eContextAdjustStackPointer:
|
|
strm.PutCString("adjust sp");
|
|
break;
|
|
|
|
case eContextSetFramePointer:
|
|
strm.PutCString("set frame pointer");
|
|
break;
|
|
|
|
case eContextAdjustBaseRegister:
|
|
strm.PutCString("adjusting (writing value back to) a base register");
|
|
break;
|
|
|
|
case eContextRegisterPlusOffset:
|
|
strm.PutCString("register + offset");
|
|
break;
|
|
|
|
case eContextRegisterStore:
|
|
strm.PutCString("store register");
|
|
break;
|
|
|
|
case eContextRegisterLoad:
|
|
strm.PutCString("load register");
|
|
break;
|
|
|
|
case eContextRelativeBranchImmediate:
|
|
strm.PutCString("relative branch immediate");
|
|
break;
|
|
|
|
case eContextAbsoluteBranchRegister:
|
|
strm.PutCString("absolute branch register");
|
|
break;
|
|
|
|
case eContextSupervisorCall:
|
|
strm.PutCString("supervisor call");
|
|
break;
|
|
|
|
case eContextTableBranchReadMemory:
|
|
strm.PutCString("table branch read memory");
|
|
break;
|
|
|
|
case eContextWriteRegisterRandomBits:
|
|
strm.PutCString("write random bits to a register");
|
|
break;
|
|
|
|
case eContextWriteMemoryRandomBits:
|
|
strm.PutCString("write random bits to a memory address");
|
|
break;
|
|
|
|
case eContextArithmetic:
|
|
strm.PutCString("arithmetic");
|
|
break;
|
|
|
|
case eContextReturnFromException:
|
|
strm.PutCString("return from exception");
|
|
break;
|
|
|
|
default:
|
|
strm.PutCString("unrecognized context.");
|
|
break;
|
|
}
|
|
|
|
switch (info_type) {
|
|
case eInfoTypeRegisterPlusOffset:
|
|
strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")",
|
|
info.RegisterPlusOffset.reg.name,
|
|
info.RegisterPlusOffset.signed_offset);
|
|
break;
|
|
|
|
case eInfoTypeRegisterPlusIndirectOffset:
|
|
strm.Printf(" (reg_plus_reg = %s + %s)",
|
|
info.RegisterPlusIndirectOffset.base_reg.name,
|
|
info.RegisterPlusIndirectOffset.offset_reg.name);
|
|
break;
|
|
|
|
case eInfoTypeRegisterToRegisterPlusOffset:
|
|
strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)",
|
|
info.RegisterToRegisterPlusOffset.base_reg.name,
|
|
info.RegisterToRegisterPlusOffset.offset,
|
|
info.RegisterToRegisterPlusOffset.data_reg.name);
|
|
break;
|
|
|
|
case eInfoTypeRegisterToRegisterPlusIndirectOffset:
|
|
strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)",
|
|
info.RegisterToRegisterPlusIndirectOffset.base_reg.name,
|
|
info.RegisterToRegisterPlusIndirectOffset.offset_reg.name,
|
|
info.RegisterToRegisterPlusIndirectOffset.data_reg.name);
|
|
break;
|
|
|
|
case eInfoTypeRegisterRegisterOperands:
|
|
strm.Printf(" (register to register binary op: %s and %s)",
|
|
info.RegisterRegisterOperands.operand1.name,
|
|
info.RegisterRegisterOperands.operand2.name);
|
|
break;
|
|
|
|
case eInfoTypeOffset:
|
|
strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset);
|
|
break;
|
|
|
|
case eInfoTypeRegister:
|
|
strm.Printf(" (reg = %s)", info.reg.name);
|
|
break;
|
|
|
|
case eInfoTypeImmediate:
|
|
strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))",
|
|
info.unsigned_immediate, info.unsigned_immediate);
|
|
break;
|
|
|
|
case eInfoTypeImmediateSigned:
|
|
strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))",
|
|
info.signed_immediate, info.signed_immediate);
|
|
break;
|
|
|
|
case eInfoTypeAddress:
|
|
strm.Printf(" (address = 0x%" PRIx64 ")", info.address);
|
|
break;
|
|
|
|
case eInfoTypeISAAndImmediate:
|
|
strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))",
|
|
info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32,
|
|
info.ISAAndImmediate.unsigned_data32);
|
|
break;
|
|
|
|
case eInfoTypeISAAndImmediateSigned:
|
|
strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))",
|
|
info.ISAAndImmediateSigned.isa,
|
|
info.ISAAndImmediateSigned.signed_data32,
|
|
info.ISAAndImmediateSigned.signed_data32);
|
|
break;
|
|
|
|
case eInfoTypeISA:
|
|
strm.Printf(" (isa = %u)", info.isa);
|
|
break;
|
|
|
|
case eInfoTypeNoArgs:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool EmulateInstruction::SetInstruction(const Opcode &opcode,
|
|
const Address &inst_addr,
|
|
Target *target) {
|
|
m_opcode = opcode;
|
|
m_addr = LLDB_INVALID_ADDRESS;
|
|
if (inst_addr.IsValid()) {
|
|
if (target != nullptr)
|
|
m_addr = inst_addr.GetLoadAddress(target);
|
|
if (m_addr == LLDB_INVALID_ADDRESS)
|
|
m_addr = inst_addr.GetFileAddress();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool EmulateInstruction::GetBestRegisterKindAndNumber(
|
|
const RegisterInfo *reg_info, lldb::RegisterKind ®_kind,
|
|
uint32_t ®_num) {
|
|
// Generic and DWARF should be the two most popular register kinds when
|
|
// emulating instructions since they are the most platform agnostic...
|
|
reg_num = reg_info->kinds[eRegisterKindGeneric];
|
|
if (reg_num != LLDB_INVALID_REGNUM) {
|
|
reg_kind = eRegisterKindGeneric;
|
|
return true;
|
|
}
|
|
|
|
reg_num = reg_info->kinds[eRegisterKindDWARF];
|
|
if (reg_num != LLDB_INVALID_REGNUM) {
|
|
reg_kind = eRegisterKindDWARF;
|
|
return true;
|
|
}
|
|
|
|
reg_num = reg_info->kinds[eRegisterKindLLDB];
|
|
if (reg_num != LLDB_INVALID_REGNUM) {
|
|
reg_kind = eRegisterKindLLDB;
|
|
return true;
|
|
}
|
|
|
|
reg_num = reg_info->kinds[eRegisterKindEHFrame];
|
|
if (reg_num != LLDB_INVALID_REGNUM) {
|
|
reg_kind = eRegisterKindEHFrame;
|
|
return true;
|
|
}
|
|
|
|
reg_num = reg_info->kinds[eRegisterKindProcessPlugin];
|
|
if (reg_num != LLDB_INVALID_REGNUM) {
|
|
reg_kind = eRegisterKindProcessPlugin;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uint32_t
|
|
EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx,
|
|
const RegisterInfo ®_info) {
|
|
lldb::RegisterKind reg_kind;
|
|
uint32_t reg_num;
|
|
if (reg_ctx && GetBestRegisterKindAndNumber(®_info, reg_kind, reg_num))
|
|
return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
|
|
return LLDB_INVALID_REGNUM;
|
|
}
|
|
|
|
bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
|
|
unwind_plan.Clear();
|
|
return false;
|
|
}
|