This patch moves the `PassthroughScriptedProcess` & `PassthroughScriptedThread` classes from the `interactive_scripted_process.py` test implementation to the `lldb.scripted_process` python module. This class is very versatile so it makes more sense to ship it with the python module to make it easier for our adopters to derive their class from it instead of copying it. During the "migration", I've also noticed some bugs in the `PassthroughScriptedThread` creation and update, so I also fixed that as part of this patch. Differential Revision: https://reviews.llvm.org/D151044 Signed-off-by: Med Ismail Bennani <ismail@bennani.ma>
595 lines
25 KiB
Python
595 lines
25 KiB
Python
from abc import ABCMeta, abstractmethod
|
|
|
|
import lldb
|
|
import json, struct, signal
|
|
|
|
class ScriptedProcess(metaclass=ABCMeta):
|
|
|
|
"""
|
|
The base class for a scripted process.
|
|
|
|
Most of the base class methods are `@abstractmethod` that need to be
|
|
overwritten by the inheriting class.
|
|
|
|
DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE.
|
|
THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE.
|
|
"""
|
|
|
|
capabilities = None
|
|
memory_regions = None
|
|
loaded_images = None
|
|
threads = None
|
|
metadata = None
|
|
|
|
@abstractmethod
|
|
def __init__(self, exe_ctx, args):
|
|
""" Construct a scripted process.
|
|
|
|
Args:
|
|
exe_ctx (lldb.SBExecutionContext): The execution context for the scripted process.
|
|
args (lldb.SBStructuredData): A Dictionary holding arbitrary
|
|
key/value pairs used by the scripted process.
|
|
"""
|
|
target = None
|
|
self.target = None
|
|
self.args = None
|
|
self.arch = None
|
|
if isinstance(exe_ctx, lldb.SBExecutionContext):
|
|
target = exe_ctx.target
|
|
if isinstance(target, lldb.SBTarget) and target.IsValid():
|
|
self.target = target
|
|
triple = self.target.triple
|
|
if triple:
|
|
self.arch = triple.split('-')[0]
|
|
self.dbg = target.GetDebugger()
|
|
if isinstance(args, lldb.SBStructuredData) and args.IsValid():
|
|
self.args = args
|
|
self.threads = {}
|
|
self.loaded_images = []
|
|
self.metadata = {}
|
|
self.capabilities = {}
|
|
self.pid = 42
|
|
|
|
def get_capabilities(self):
|
|
""" Get a dictionary containing the process capabilities.
|
|
|
|
Returns:
|
|
Dict[str:bool]: The dictionary of capability, with the capability
|
|
name as the key and a boolean flag as the value.
|
|
The dictionary can be empty.
|
|
"""
|
|
return self.capabilities
|
|
|
|
def get_memory_region_containing_address(self, addr):
|
|
""" Get the memory region for the scripted process, containing a
|
|
specific address.
|
|
|
|
Args:
|
|
addr (int): Address to look for in the scripted process memory
|
|
regions.
|
|
|
|
Returns:
|
|
lldb.SBMemoryRegionInfo: The memory region containing the address.
|
|
None if out of bounds.
|
|
"""
|
|
return None
|
|
|
|
def get_threads_info(self):
|
|
""" Get the dictionary describing the process' Scripted Threads.
|
|
|
|
Returns:
|
|
Dict: The dictionary of threads, with the thread ID as the key and
|
|
a Scripted Thread instance as the value.
|
|
The dictionary can be empty.
|
|
"""
|
|
return self.threads
|
|
|
|
@abstractmethod
|
|
def read_memory_at_address(self, addr, size, error):
|
|
""" Get a memory buffer from the scripted process at a certain address,
|
|
of a certain size.
|
|
|
|
Args:
|
|
addr (int): Address from which we should start reading.
|
|
size (int): Size of the memory to read.
|
|
error (lldb.SBError): Error object.
|
|
|
|
Returns:
|
|
lldb.SBData: An `lldb.SBData` buffer with the target byte size and
|
|
byte order storing the memory read.
|
|
"""
|
|
pass
|
|
|
|
def write_memory_at_address(self, addr, data, error):
|
|
""" Write a buffer to the scripted process memory.
|
|
|
|
Args:
|
|
addr (int): Address from which we should start reading.
|
|
data (lldb.SBData): An `lldb.SBData` buffer to write to the
|
|
process memory.
|
|
error (lldb.SBError): Error object.
|
|
|
|
Returns:
|
|
size (int): Size of the memory to read.
|
|
"""
|
|
error.SetErrorString("%s doesn't support memory writes." % self.__class__.__name__)
|
|
return 0
|
|
|
|
def get_loaded_images(self):
|
|
""" Get the list of loaded images for the scripted process.
|
|
|
|
```
|
|
scripted_image = {
|
|
uuid = "c6ea2b64-f77c-3d27-9528-74f507b9078b",
|
|
path = "/usr/lib/dyld"
|
|
load_addr = 0xbadc0ffee
|
|
}
|
|
```
|
|
|
|
Returns:
|
|
List[scripted_image]: A list of `scripted_image` dictionaries
|
|
containing for each entry the library UUID or its file path
|
|
and its load address.
|
|
None if the list is empty.
|
|
"""
|
|
return self.loaded_images
|
|
|
|
def get_process_id(self):
|
|
""" Get the scripted process identifier.
|
|
|
|
Returns:
|
|
int: The scripted process identifier.
|
|
"""
|
|
return self.pid
|
|
|
|
def launch(self):
|
|
""" Simulate the scripted process launch.
|
|
|
|
Returns:
|
|
lldb.SBError: An `lldb.SBError` with error code 0.
|
|
"""
|
|
return lldb.SBError()
|
|
|
|
def attach(self, attach_info):
|
|
""" Simulate the scripted process attach.
|
|
|
|
Args:
|
|
attach_info (lldb.SBAttachInfo): The information related to the
|
|
process we're attaching to.
|
|
|
|
Returns:
|
|
lldb.SBError: An `lldb.SBError` with error code 0.
|
|
"""
|
|
return lldb.SBError()
|
|
|
|
def resume(self, should_stop=True):
|
|
""" Simulate the scripted process resume.
|
|
|
|
Args:
|
|
should_stop (bool): If True, resume will also force the process
|
|
state to stopped after running it.
|
|
|
|
Returns:
|
|
lldb.SBError: An `lldb.SBError` with error code 0.
|
|
"""
|
|
process = self.target.GetProcess()
|
|
if not process:
|
|
error = lldb.SBError()
|
|
error.SetErrorString("Invalid process.")
|
|
return error
|
|
|
|
process.ForceScriptedState(lldb.eStateRunning);
|
|
if (should_stop):
|
|
process.ForceScriptedState(lldb.eStateStopped);
|
|
return lldb.SBError()
|
|
|
|
@abstractmethod
|
|
def is_alive(self):
|
|
""" Check if the scripted process is alive.
|
|
|
|
Returns:
|
|
bool: True if scripted process is alive. False otherwise.
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_scripted_thread_plugin(self):
|
|
""" Get scripted thread plugin name.
|
|
|
|
Returns:
|
|
str: Name of the scripted thread plugin.
|
|
"""
|
|
return None
|
|
|
|
def get_process_metadata(self):
|
|
""" Get some metadata for the scripted process.
|
|
|
|
Returns:
|
|
Dict: A dictionary containing metadata for the scripted process.
|
|
None if the process as no metadata.
|
|
"""
|
|
return self.metadata
|
|
|
|
def create_breakpoint(self, addr, error):
|
|
""" Create a breakpoint in the scripted process from an address.
|
|
This is mainly used with interactive scripted process debugging.
|
|
|
|
Args:
|
|
addr (int): Address at which the breakpoint should be set.
|
|
error (lldb.SBError): Error object.
|
|
|
|
Returns:
|
|
SBBreakpoint: A valid breakpoint object that was created a the specified
|
|
address. None if the breakpoint creation failed.
|
|
"""
|
|
error.SetErrorString("%s doesn't support creating breakpoints."
|
|
% self.__class__.__name__)
|
|
return False
|
|
|
|
class ScriptedThread(metaclass=ABCMeta):
|
|
|
|
"""
|
|
The base class for a scripted thread.
|
|
|
|
Most of the base class methods are `@abstractmethod` that need to be
|
|
overwritten by the inheriting class.
|
|
|
|
DISCLAIMER: THIS INTERFACE IS STILL UNDER DEVELOPMENT AND NOT STABLE.
|
|
THE METHODS EXPOSED MIGHT CHANGE IN THE FUTURE.
|
|
"""
|
|
|
|
@abstractmethod
|
|
def __init__(self, scripted_process, args):
|
|
""" Construct a scripted thread.
|
|
|
|
Args:
|
|
process (ScriptedProcess): The scripted process owning this thread.
|
|
args (lldb.SBStructuredData): A Dictionary holding arbitrary
|
|
key/value pairs used by the scripted thread.
|
|
"""
|
|
self.target = None
|
|
self.scripted_process = None
|
|
self.process = None
|
|
self.args = None
|
|
self.idx = 0
|
|
self.tid = 0
|
|
self.idx = None
|
|
self.name = None
|
|
self.queue = None
|
|
self.state = None
|
|
self.stop_reason = None
|
|
self.register_info = None
|
|
self.register_ctx = {}
|
|
self.frames = []
|
|
self.extended_info = []
|
|
|
|
if isinstance(scripted_process, ScriptedProcess):
|
|
self.target = scripted_process.target
|
|
self.scripted_process = scripted_process
|
|
self.process = self.target.GetProcess()
|
|
self.get_register_info()
|
|
|
|
def get_thread_idx(self):
|
|
""" Get the scripted thread index.
|
|
|
|
Returns:
|
|
int: The index of the scripted thread in the scripted process.
|
|
"""
|
|
return self.idx
|
|
|
|
def get_thread_id(self):
|
|
""" Get the scripted thread identifier.
|
|
|
|
Returns:
|
|
int: The identifier of the scripted thread.
|
|
"""
|
|
return self.tid
|
|
|
|
def get_name(self):
|
|
""" Get the scripted thread name.
|
|
|
|
Returns:
|
|
str: The name of the scripted thread.
|
|
"""
|
|
return self.name
|
|
|
|
def get_state(self):
|
|
""" Get the scripted thread state type.
|
|
|
|
eStateStopped, ///< Process or thread is stopped and can be examined.
|
|
eStateRunning, ///< Process or thread is running and can't be examined.
|
|
eStateStepping, ///< Process or thread is in the process of stepping and can
|
|
/// not be examined.
|
|
eStateCrashed, ///< Process or thread has crashed and can be examined.
|
|
|
|
Returns:
|
|
int: The state type of the scripted thread.
|
|
Returns lldb.eStateStopped by default.
|
|
"""
|
|
return lldb.eStateStopped
|
|
|
|
def get_queue(self):
|
|
""" Get the scripted thread associated queue name.
|
|
This method is optional.
|
|
|
|
Returns:
|
|
str: The queue name associated with the scripted thread.
|
|
"""
|
|
return self.queue
|
|
|
|
@abstractmethod
|
|
def get_stop_reason(self):
|
|
""" Get the dictionary describing the stop reason type with some data.
|
|
This method is optional.
|
|
|
|
Returns:
|
|
Dict: The dictionary holding the stop reason type and the possibly
|
|
the stop reason data.
|
|
"""
|
|
pass
|
|
|
|
def get_stackframes(self):
|
|
""" Get the list of stack frames for the scripted thread.
|
|
|
|
```
|
|
scripted_frame = {
|
|
idx = 0,
|
|
pc = 0xbadc0ffee
|
|
}
|
|
```
|
|
|
|
Returns:
|
|
List[scripted_frame]: A list of `scripted_frame` dictionaries
|
|
containing at least for each entry, the frame index and
|
|
the program counter value for that frame.
|
|
The list can be empty.
|
|
"""
|
|
return self.frames
|
|
|
|
def get_register_info(self):
|
|
if self.register_info is None:
|
|
self.register_info = dict()
|
|
if self.scripted_process.arch == 'x86_64':
|
|
self.register_info['sets'] = ['General Purpose Registers']
|
|
self.register_info['registers'] = INTEL64_GPR
|
|
elif 'arm64' in self.scripted_process.arch:
|
|
self.register_info['sets'] = ['General Purpose Registers']
|
|
self.register_info['registers'] = ARM64_GPR
|
|
else: raise ValueError('Unknown architecture', self.scripted_process.arch)
|
|
return self.register_info
|
|
|
|
@abstractmethod
|
|
def get_register_context(self):
|
|
""" Get the scripted thread register context
|
|
|
|
Returns:
|
|
str: A byte representing all register's value.
|
|
"""
|
|
pass
|
|
|
|
def get_extended_info(self):
|
|
""" Get scripted thread extended information.
|
|
|
|
Returns:
|
|
List: A list containing the extended information for the scripted process.
|
|
None if the thread as no extended information.
|
|
"""
|
|
return self.extended_info
|
|
|
|
|
|
class PassthroughScriptedProcess(ScriptedProcess):
|
|
driving_target = None
|
|
driving_process = None
|
|
|
|
def __init__(self, exe_ctx, args, launched_driving_process=True):
|
|
super().__init__(exe_ctx, args)
|
|
|
|
self.driving_target = None
|
|
self.driving_process = None
|
|
|
|
self.driving_target_idx = args.GetValueForKey("driving_target_idx")
|
|
if self.driving_target_idx and self.driving_target_idx.IsValid():
|
|
idx = self.driving_target_idx.GetUnsignedIntegerValue(42)
|
|
self.driving_target = self.target.GetDebugger().GetTargetAtIndex(idx)
|
|
|
|
if launched_driving_process:
|
|
self.driving_process = self.driving_target.GetProcess()
|
|
for driving_thread in self.driving_process:
|
|
structured_data = lldb.SBStructuredData()
|
|
structured_data.SetFromJSON(
|
|
json.dumps(
|
|
{
|
|
"driving_target_idx": idx,
|
|
"thread_idx": driving_thread.GetIndexID(),
|
|
}
|
|
)
|
|
)
|
|
|
|
self.threads[
|
|
driving_thread.GetThreadID()
|
|
] = PassthroughScriptedThread(self, structured_data)
|
|
|
|
for module in self.driving_target.modules:
|
|
path = module.file.fullpath
|
|
load_addr = module.GetObjectFileHeaderAddress().GetLoadAddress(
|
|
self.driving_target
|
|
)
|
|
self.loaded_images.append({"path": path, "load_addr": load_addr})
|
|
|
|
def get_memory_region_containing_address(self, addr):
|
|
mem_region = lldb.SBMemoryRegionInfo()
|
|
error = self.driving_process.GetMemoryRegionInfo(addr, mem_region)
|
|
if error.Fail():
|
|
return None
|
|
return mem_region
|
|
|
|
def read_memory_at_address(self, addr, size, error):
|
|
data = lldb.SBData()
|
|
bytes_read = self.driving_process.ReadMemory(addr, size, error)
|
|
|
|
if error.Fail():
|
|
return data
|
|
|
|
data.SetDataWithOwnership(
|
|
error,
|
|
bytes_read,
|
|
self.driving_target.GetByteOrder(),
|
|
self.driving_target.GetAddressByteSize(),
|
|
)
|
|
|
|
return data
|
|
|
|
def write_memory_at_address(self, addr, data, error):
|
|
return self.driving_process.WriteMemory(
|
|
addr, bytearray(data.uint8.all()), error
|
|
)
|
|
|
|
def get_process_id(self):
|
|
return self.driving_process.GetProcessID()
|
|
|
|
def is_alive(self):
|
|
return True
|
|
|
|
def get_scripted_thread_plugin(self):
|
|
return f"{PassthroughScriptedThread.__module__}.{PassthroughScriptedThread.__name__}"
|
|
|
|
|
|
class PassthroughScriptedThread(ScriptedThread):
|
|
def __init__(self, process, args):
|
|
super().__init__(process, args)
|
|
driving_target_idx = args.GetValueForKey("driving_target_idx")
|
|
thread_idx = args.GetValueForKey("thread_idx")
|
|
|
|
# TODO: Change to Walrus operator (:=) with oneline if assignment
|
|
# Requires python 3.8
|
|
val = thread_idx.GetUnsignedIntegerValue()
|
|
if val is not None:
|
|
self.idx = val
|
|
|
|
self.driving_target = None
|
|
self.driving_process = None
|
|
self.driving_thread = None
|
|
|
|
# TODO: Change to Walrus operator (:=) with oneline if assignment
|
|
# Requires python 3.8
|
|
val = driving_target_idx.GetUnsignedIntegerValue()
|
|
if val is not None:
|
|
self.driving_target = self.target.GetDebugger().GetTargetAtIndex(val)
|
|
self.driving_process = self.driving_target.GetProcess()
|
|
self.driving_thread = self.driving_process.GetThreadByIndexID(self.idx)
|
|
|
|
if self.driving_thread:
|
|
self.id = self.driving_thread.GetThreadID()
|
|
|
|
def get_thread_id(self):
|
|
return self.id
|
|
|
|
def get_name(self):
|
|
return f"{PassthroughScriptedThread.__name__}.thread-{self.idx}"
|
|
|
|
def get_stop_reason(self):
|
|
stop_reason = {"type": lldb.eStopReasonInvalid, "data": {}}
|
|
|
|
if (
|
|
self.driving_thread
|
|
and self.driving_thread.IsValid()
|
|
and self.get_thread_id() == self.driving_thread.GetThreadID()
|
|
):
|
|
stop_reason["type"] = lldb.eStopReasonNone
|
|
|
|
# TODO: Passthrough stop reason from driving process
|
|
if self.driving_thread.GetStopReason() != lldb.eStopReasonNone:
|
|
if "arm64" in self.scripted_process.arch:
|
|
stop_reason["type"] = lldb.eStopReasonException
|
|
stop_reason["data"][
|
|
"desc"
|
|
] = self.driving_thread.GetStopDescription(100)
|
|
elif self.scripted_process.arch == "x86_64":
|
|
stop_reason["type"] = lldb.eStopReasonSignal
|
|
stop_reason["data"]["signal"] = signal.SIGTRAP
|
|
else:
|
|
stop_reason["type"] = self.driving_thread.GetStopReason()
|
|
|
|
return stop_reason
|
|
|
|
def get_register_context(self):
|
|
if not self.driving_thread or self.driving_thread.GetNumFrames() == 0:
|
|
return None
|
|
frame = self.driving_thread.GetFrameAtIndex(0)
|
|
|
|
GPRs = None
|
|
registerSet = frame.registers # Returns an SBValueList.
|
|
for regs in registerSet:
|
|
if "general purpose" in regs.name.lower():
|
|
GPRs = regs
|
|
break
|
|
|
|
if not GPRs:
|
|
return None
|
|
|
|
for reg in GPRs:
|
|
self.register_ctx[reg.name] = int(reg.value, base=16)
|
|
|
|
return struct.pack(f"{len(self.register_ctx)}Q", *self.register_ctx.values())
|
|
|
|
ARM64_GPR = [ {'name': 'x0', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0, 'generic': 'arg0', 'alt-name': 'arg0'},
|
|
{'name': 'x1', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg1', 'alt-name': 'arg1'},
|
|
{'name': 'x2', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg2', 'alt-name': 'arg2'},
|
|
{'name': 'x3', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3, 'generic': 'arg3', 'alt-name': 'arg3'},
|
|
{'name': 'x4', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg4', 'alt-name': 'arg4'},
|
|
{'name': 'x5', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg5', 'alt-name': 'arg5'},
|
|
{'name': 'x6', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'arg6', 'alt-name': 'arg6'},
|
|
{'name': 'x7', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'arg7', 'alt-name': 'arg7'},
|
|
{'name': 'x8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8 },
|
|
{'name': 'x9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9 },
|
|
{'name': 'x10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10},
|
|
{'name': 'x11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11},
|
|
{'name': 'x12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12},
|
|
{'name': 'x13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13},
|
|
{'name': 'x14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14},
|
|
{'name': 'x15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15},
|
|
{'name': 'x16', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16},
|
|
{'name': 'x17', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 17, 'dwarf': 17},
|
|
{'name': 'x18', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 18, 'dwarf': 18},
|
|
{'name': 'x19', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 19, 'dwarf': 19},
|
|
{'name': 'x20', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 20, 'dwarf': 20},
|
|
{'name': 'x21', 'bitsize': 64, 'offset': 168, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 21, 'dwarf': 21},
|
|
{'name': 'x22', 'bitsize': 64, 'offset': 176, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 22, 'dwarf': 22},
|
|
{'name': 'x23', 'bitsize': 64, 'offset': 184, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 23, 'dwarf': 23},
|
|
{'name': 'x24', 'bitsize': 64, 'offset': 192, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 24, 'dwarf': 24},
|
|
{'name': 'x25', 'bitsize': 64, 'offset': 200, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 25, 'dwarf': 25},
|
|
{'name': 'x26', 'bitsize': 64, 'offset': 208, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 26, 'dwarf': 26},
|
|
{'name': 'x27', 'bitsize': 64, 'offset': 216, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 27, 'dwarf': 27},
|
|
{'name': 'x28', 'bitsize': 64, 'offset': 224, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 28, 'dwarf': 28},
|
|
{'name': 'x29', 'bitsize': 64, 'offset': 232, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 29, 'dwarf': 29, 'generic': 'fp', 'alt-name': 'fp'},
|
|
{'name': 'x30', 'bitsize': 64, 'offset': 240, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 30, 'dwarf': 30, 'generic': 'lr', 'alt-name': 'lr'},
|
|
{'name': 'sp', 'bitsize': 64, 'offset': 248, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 31, 'dwarf': 31, 'generic': 'sp', 'alt-name': 'sp'},
|
|
{'name': 'pc', 'bitsize': 64, 'offset': 256, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 32, 'dwarf': 32, 'generic': 'pc', 'alt-name': 'pc'},
|
|
{'name': 'cpsr', 'bitsize': 32, 'offset': 264, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 33, 'dwarf': 33}
|
|
]
|
|
|
|
INTEL64_GPR = [ {'name': 'rax', 'bitsize': 64, 'offset': 0, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 0, 'dwarf': 0},
|
|
{'name': 'rbx', 'bitsize': 64, 'offset': 8, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 3, 'dwarf': 3},
|
|
{'name': 'rcx', 'bitsize': 64, 'offset': 16, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 2, 'dwarf': 2, 'generic': 'arg4', 'alt-name': 'arg4'},
|
|
{'name': 'rdx', 'bitsize': 64, 'offset': 24, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 1, 'dwarf': 1, 'generic': 'arg3', 'alt-name': 'arg3'},
|
|
{'name': 'rdi', 'bitsize': 64, 'offset': 32, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 5, 'dwarf': 5, 'generic': 'arg1', 'alt-name': 'arg1'},
|
|
{'name': 'rsi', 'bitsize': 64, 'offset': 40, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 4, 'dwarf': 4, 'generic': 'arg2', 'alt-name': 'arg2'},
|
|
{'name': 'rbp', 'bitsize': 64, 'offset': 48, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 6, 'dwarf': 6, 'generic': 'fp', 'alt-name': 'fp'},
|
|
{'name': 'rsp', 'bitsize': 64, 'offset': 56, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 7, 'dwarf': 7, 'generic': 'sp', 'alt-name': 'sp'},
|
|
{'name': 'r8', 'bitsize': 64, 'offset': 64, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 8, 'dwarf': 8, 'generic': 'arg5', 'alt-name': 'arg5'},
|
|
{'name': 'r9', 'bitsize': 64, 'offset': 72, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 9, 'dwarf': 9, 'generic': 'arg6', 'alt-name': 'arg6'},
|
|
{'name': 'r10', 'bitsize': 64, 'offset': 80, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 10, 'dwarf': 10},
|
|
{'name': 'r11', 'bitsize': 64, 'offset': 88, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 11, 'dwarf': 11},
|
|
{'name': 'r12', 'bitsize': 64, 'offset': 96, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 12, 'dwarf': 12},
|
|
{'name': 'r13', 'bitsize': 64, 'offset': 104, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 13, 'dwarf': 13},
|
|
{'name': 'r14', 'bitsize': 64, 'offset': 112, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 14, 'dwarf': 14},
|
|
{'name': 'r15', 'bitsize': 64, 'offset': 120, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 15, 'dwarf': 15},
|
|
{'name': 'rip', 'bitsize': 64, 'offset': 128, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'gcc': 16, 'dwarf': 16, 'generic': 'pc', 'alt-name': 'pc'},
|
|
{'name': 'rflags', 'bitsize': 64, 'offset': 136, 'encoding': 'uint', 'format': 'hex', 'set': 0, 'generic': 'flags', 'alt-name': 'flags'},
|
|
{'name': 'cs', 'bitsize': 64, 'offset': 144, 'encoding': 'uint', 'format': 'hex', 'set': 0},
|
|
{'name': 'fs', 'bitsize': 64, 'offset': 152, 'encoding': 'uint', 'format': 'hex', 'set': 0},
|
|
{'name': 'gs', 'bitsize': 64, 'offset': 160, 'encoding': 'uint', 'format': 'hex', 'set': 0}
|
|
]
|
|
|
|
|