hanchenye-llvm-project/lldb/source/Target/RegisterContext.cpp

398 lines
10 KiB
C++
Raw Normal View History

//===-- RegisterContext.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Endian.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StackFrame.h"
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-10 05:07:35 +08:00
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
Fixed issues with RegisterContext classes and the subclasses. There was an issue with the way the UnwindLLDB was handing out RegisterContexts: it was making shared pointers to register contexts and then handing out just the pointers (which would get put into shared pointers in the thread and stack frame classes) and cause double free issues. MallocScribble helped to find these issues after I did some other cleanup. To help avoid any RegisterContext issue in the future, all code that deals with them now returns shared pointers to the register contexts so we don't end up with multiple deletions. Also now that the RegisterContext class doesn't require a stack frame, we patched a memory leak where a StackFrame object was being created and leaked. Made the RegisterContext class not have a pointer to a StackFrame object as one register context class can be used for N inlined stack frames so there is not a 1 - 1 mapping. Updates the ExecutionContextScope part of the RegisterContext class to never return a stack frame to indicate this when it is asked to recreate the execution context. Now register contexts point to the concrete frame using a concrete frame index. Concrete frames are all of the frames that are actually formed on the stack of a thread. These concrete frames can be turned into one or more user visible frames due to inlining. Each inlined stack frame has the exact same register context (shared via shared pointers) as any parent inlined stack frames all the way up to the concrete frame itself. So now the stack frames and the register contexts should behave much better. llvm-svn: 122976
2011-01-07 06:15:06 +08:00
RegisterContext::RegisterContext (Thread &thread, uint32_t concrete_frame_idx) :
m_thread (thread),
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-10 05:07:35 +08:00
m_concrete_frame_idx (concrete_frame_idx),
m_stop_id (thread.GetProcess().GetStopID())
{
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
RegisterContext::~RegisterContext()
{
}
Put more smarts into the RegisterContext base class. Now the base class has a method: void RegisterContext::InvalidateIfNeeded (bool force); Each time this function is called, when "force" is false, it will only call the pure virtual "virtual void RegisterContext::InvalideAllRegisters()" if the register context's stop ID doesn't match that of the process. When the stop ID doesn't match, or "force" is true, the base class will clear its cached registers and the RegisterContext will update its stop ID to match that of the process. This helps make it easier to correctly flush the register context (possibly from multiple locations depending on when and where new registers are availabe) without inadvertently clearing the register cache when it doesn't need to be. Modified the ProcessGDBRemote plug-in to be much more efficient when it comes to: - caching the expedited registers in the stop reply packets (we were ignoring these before and it was causing us to read at least three registers every time we stopped that were already supplied in the stop reply packet). - When a thread has no stop reason, don't keep asking for the thread stopped info. Prior to this fix we would continually send a qThreadStopInfo packet over and over when any thread stop info was requested. We now note the stop ID that the stop info was requested for and avoid multiple requests. Cleaned up some of the expression code to not look for ClangExpressionVariable objects up by name since they are now shared pointers and we can just look for the exact pointer match and avoid possible errors. Fixed an bug in the ValueObject code that would cause children to not be displayed. llvm-svn: 123127
2011-01-10 05:07:35 +08:00
void
RegisterContext::InvalidateIfNeeded (bool force)
{
const uint32_t this_stop_id = GetStopID();
const uint32_t process_stop_id = m_thread.GetProcess().GetStopID();
if (force || process_stop_id != this_stop_id)
{
InvalidateAllRegisters ();
SetStopID (process_stop_id);
}
}
const RegisterInfo *
RegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx)
{
if (reg_name && reg_name[0])
{
const uint32_t num_registers = GetRegisterCount();
for (uint32_t reg = start_idx; reg < num_registers; ++reg)
{
const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
if ((reg_info->name != NULL && ::strcasecmp (reg_info->name, reg_name) == 0) ||
(reg_info->alt_name != NULL && ::strcasecmp (reg_info->alt_name, reg_name) == 0))
{
return reg_info;
}
}
}
return NULL;
}
const char *
RegisterContext::GetRegisterName (uint32_t reg)
{
const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
if (reg_info)
return reg_info->name;
return NULL;
}
uint64_t
RegisterContext::GetPC(uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
return ReadRegisterAsUnsigned (reg, fail_value);
}
bool
RegisterContext::SetPC(uint64_t pc)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
bool success = WriteRegisterFromUnsigned (reg, pc);
if (success)
{
Fixed issues with RegisterContext classes and the subclasses. There was an issue with the way the UnwindLLDB was handing out RegisterContexts: it was making shared pointers to register contexts and then handing out just the pointers (which would get put into shared pointers in the thread and stack frame classes) and cause double free issues. MallocScribble helped to find these issues after I did some other cleanup. To help avoid any RegisterContext issue in the future, all code that deals with them now returns shared pointers to the register contexts so we don't end up with multiple deletions. Also now that the RegisterContext class doesn't require a stack frame, we patched a memory leak where a StackFrame object was being created and leaked. Made the RegisterContext class not have a pointer to a StackFrame object as one register context class can be used for N inlined stack frames so there is not a 1 - 1 mapping. Updates the ExecutionContextScope part of the RegisterContext class to never return a stack frame to indicate this when it is asked to recreate the execution context. Now register contexts point to the concrete frame using a concrete frame index. Concrete frames are all of the frames that are actually formed on the stack of a thread. These concrete frames can be turned into one or more user visible frames due to inlining. Each inlined stack frame has the exact same register context (shared via shared pointers) as any parent inlined stack frames all the way up to the concrete frame itself. So now the stack frames and the register contexts should behave much better. llvm-svn: 122976
2011-01-07 06:15:06 +08:00
StackFrameSP frame_sp(m_thread.GetFrameWithConcreteFrameIndex (m_concrete_frame_idx));
if (frame_sp)
frame_sp->ChangePC(pc);
else
m_thread.ClearStackFrames ();
}
return success;
}
uint64_t
RegisterContext::GetSP(uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
return ReadRegisterAsUnsigned (reg, fail_value);
}
bool
RegisterContext::SetSP(uint64_t sp)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
return WriteRegisterFromUnsigned (reg, sp);
}
uint64_t
RegisterContext::GetFP(uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
return ReadRegisterAsUnsigned (reg, fail_value);
}
bool
RegisterContext::SetFP(uint64_t fp)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
return WriteRegisterFromUnsigned (reg, fp);
}
uint64_t
RegisterContext::GetReturnAddress (uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
return ReadRegisterAsUnsigned (reg, fail_value);
}
uint64_t
RegisterContext::GetFlags (uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
return ReadRegisterAsUnsigned (reg, fail_value);
}
uint64_t
RegisterContext::ReadRegisterAsUnsigned (uint32_t reg, uint64_t fail_value)
{
if (reg != LLDB_INVALID_REGNUM)
{
Scalar value;
if (ReadRegisterValue (reg, value))
return value.GetRawBits64(fail_value);
}
return fail_value;
}
bool
RegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval)
{
if (reg == LLDB_INVALID_REGNUM)
return false;
Scalar value(uval);
return WriteRegisterValue (reg, value);
}
lldb::tid_t
RegisterContext::GetThreadID() const
{
return m_thread.GetID();
}
uint32_t
RegisterContext::NumSupportedHardwareBreakpoints ()
{
return 0;
}
uint32_t
RegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
{
return LLDB_INVALID_INDEX32;
}
bool
RegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx)
{
return false;
}
uint32_t
RegisterContext::NumSupportedHardwareWatchpoints ()
{
return 0;
}
uint32_t
RegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
{
return LLDB_INVALID_INDEX32;
}
bool
RegisterContext::ClearHardwareWatchpoint (uint32_t hw_index)
{
return false;
}
bool
RegisterContext::HardwareSingleStep (bool enable)
{
return false;
}
Target *
RegisterContext::CalculateTarget ()
{
return m_thread.CalculateTarget();
}
Process *
RegisterContext::CalculateProcess ()
{
return m_thread.CalculateProcess ();
}
Thread *
RegisterContext::CalculateThread ()
{
return &m_thread;
}
StackFrame *
RegisterContext::CalculateStackFrame ()
{
Fixed issues with RegisterContext classes and the subclasses. There was an issue with the way the UnwindLLDB was handing out RegisterContexts: it was making shared pointers to register contexts and then handing out just the pointers (which would get put into shared pointers in the thread and stack frame classes) and cause double free issues. MallocScribble helped to find these issues after I did some other cleanup. To help avoid any RegisterContext issue in the future, all code that deals with them now returns shared pointers to the register contexts so we don't end up with multiple deletions. Also now that the RegisterContext class doesn't require a stack frame, we patched a memory leak where a StackFrame object was being created and leaked. Made the RegisterContext class not have a pointer to a StackFrame object as one register context class can be used for N inlined stack frames so there is not a 1 - 1 mapping. Updates the ExecutionContextScope part of the RegisterContext class to never return a stack frame to indicate this when it is asked to recreate the execution context. Now register contexts point to the concrete frame using a concrete frame index. Concrete frames are all of the frames that are actually formed on the stack of a thread. These concrete frames can be turned into one or more user visible frames due to inlining. Each inlined stack frame has the exact same register context (shared via shared pointers) as any parent inlined stack frames all the way up to the concrete frame itself. So now the stack frames and the register contexts should behave much better. llvm-svn: 122976
2011-01-07 06:15:06 +08:00
// Register contexts might belong to many frames if we have inlined
// functions inside a frame since all inlined functions share the
// same registers, so we can't definitively say which frame we come from...
return NULL;
}
void
There are now to new "settings set" variables that live in each debugger instance: settings set frame-format <string> settings set thread-format <string> This allows users to control the information that is seen when dumping threads and frames. The default values are set such that they do what they used to do prior to changing over the the user defined formats. This allows users with terminals that can display color to make different items different colors using the escape control codes. A few alias examples that will colorize your thread and frame prompts are: settings set frame-format 'frame #${frame.index}: \033[0;33m${frame.pc}\033[0m{ \033[1;4;36m${module.file.basename}\033[0;36m ${function.name}{${function.pc-offset}}\033[0m}{ \033[0;35mat \033[1;35m${line.file.basename}:${line.number}}\033[0m\n' settings set thread-format 'thread #${thread.index}: \033[1;33mtid\033[0;33m = ${thread.id}\033[0m{, \033[0;33m${frame.pc}\033[0m}{ \033[1;4;36m${module.file.basename}\033[0;36m ${function.name}{${function.pc-offset}}\033[0m}{, \033[1;35mstop reason\033[0;35m = ${thread.stop-reason}\033[0m}{, \033[1;36mname = \033[0;36m${thread.name}\033[0m}{, \033[1;32mqueue = \033[0;32m${thread.queue}}\033[0m\n' A quick web search for "colorize terminal output" should allow you to see what you can do to make your output look like you want it. The "settings set" commands above can of course be added to your ~/.lldbinit file for permanent use. Changed the pure virtual void ExecutionContextScope::Calculate (ExecutionContext&); To: void ExecutionContextScope::CalculateExecutionContext (ExecutionContext&); I did this because this is a class that anything in the execution context heirarchy inherits from and "target->Calculate (exe_ctx)" didn't always tell you what it was really trying to do unless you look at the parameter. llvm-svn: 115485
2010-10-04 09:05:56 +08:00
RegisterContext::CalculateExecutionContext (ExecutionContext &exe_ctx)
{
Fixed issues with RegisterContext classes and the subclasses. There was an issue with the way the UnwindLLDB was handing out RegisterContexts: it was making shared pointers to register contexts and then handing out just the pointers (which would get put into shared pointers in the thread and stack frame classes) and cause double free issues. MallocScribble helped to find these issues after I did some other cleanup. To help avoid any RegisterContext issue in the future, all code that deals with them now returns shared pointers to the register contexts so we don't end up with multiple deletions. Also now that the RegisterContext class doesn't require a stack frame, we patched a memory leak where a StackFrame object was being created and leaked. Made the RegisterContext class not have a pointer to a StackFrame object as one register context class can be used for N inlined stack frames so there is not a 1 - 1 mapping. Updates the ExecutionContextScope part of the RegisterContext class to never return a stack frame to indicate this when it is asked to recreate the execution context. Now register contexts point to the concrete frame using a concrete frame index. Concrete frames are all of the frames that are actually formed on the stack of a thread. These concrete frames can be turned into one or more user visible frames due to inlining. Each inlined stack frame has the exact same register context (shared via shared pointers) as any parent inlined stack frames all the way up to the concrete frame itself. So now the stack frames and the register contexts should behave much better. llvm-svn: 122976
2011-01-07 06:15:06 +08:00
m_thread.CalculateExecutionContext (exe_ctx);
}
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
bool
RegisterContext::ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t& target_regnum)
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
{
const uint32_t num_registers = GetRegisterCount();
for (uint32_t reg = 0; reg < num_registers; ++reg)
{
const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
The first part of an lldb native stack unwinder. The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
2010-09-10 15:49:16 +08:00
if (reg_info->kinds[source_rk] == source_regnum)
{
target_regnum = reg_info->kinds[target_rk];
if (target_regnum == LLDB_INVALID_REGNUM)
{
return false;
}
else
{
return true;
}
}
}
return false;
}
bool
RegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
{
DataExtractor data;
if (!ReadRegisterBytes (reg, data))
return false;
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
uint32_t offset = 0;
switch (reg_info->encoding)
{
case eEncodingInvalid:
case eEncodingVector:
break;
case eEncodingUint:
switch (reg_info->byte_size)
{
case 1:
{
value = data.GetU8 (&offset);
return true;
}
case 2:
{
value = data.GetU16 (&offset);
return true;
}
case 4:
{
value = data.GetU32 (&offset);
return true;
}
case 8:
{
value = data.GetU64 (&offset);
return true;
}
}
break;
case eEncodingSint:
switch (reg_info->byte_size)
{
case 1:
{
int8_t v;
if (data.ExtractBytes (0, sizeof (int8_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int8_t))
return false;
value = v;
return true;
}
case 2:
{
int16_t v;
if (data.ExtractBytes (0, sizeof (int16_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int16_t))
return false;
value = v;
return true;
}
case 4:
{
int32_t v;
if (data.ExtractBytes (0, sizeof (int32_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int32_t))
return false;
value = v;
return true;
}
case 8:
{
int64_t v;
if (data.ExtractBytes (0, sizeof (int64_t), lldb::endian::InlHostByteOrder(), &v) != sizeof (int64_t))
return false;
value = v;
return true;
}
}
break;
case eEncodingIEEE754:
switch (reg_info->byte_size)
{
case sizeof (float):
{
float v;
if (data.ExtractBytes (0, sizeof (float), lldb::endian::InlHostByteOrder(), &v) != sizeof (float))
return false;
value = v;
return true;
}
case sizeof (double):
{
double v;
if (data.ExtractBytes (0, sizeof (double), lldb::endian::InlHostByteOrder(), &v) != sizeof (double))
return false;
value = v;
return true;
}
case sizeof (long double):
{
double v;
if (data.ExtractBytes (0, sizeof (long double), lldb::endian::InlHostByteOrder(), &v) != sizeof (long double))
return false;
value = v;
return true;
}
}
break;
}
return false;
}
bool
RegisterContext::WriteRegisterValue (uint32_t reg, const Scalar &value)
{
DataExtractor data;
if (!value.IsValid())
return false;
if (!value.GetData (data))
return false;
return WriteRegisterBytes (reg, data);
}