blob: 6c2697cb9aa959e7abb8875e72470804596b9a6e [file] [edit]
from abc import ABCMeta, abstractmethod
from typing import Any, Optional, Union
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.
"""
capabilities: Optional[dict[str, bool]] = None
memory_regions: Optional[list[lldb.SBMemoryRegionInfo]] = None
loaded_images: Optional[list[dict]] = None
threads: Optional[dict[int, "lldb.plugins.scripted_process.ScriptedThread"]] = None
metadata: Optional[dict[str, Any]] = None
addressable_bits: Optional[dict[str, int]] = None
target: lldb.SBTarget
args: lldb.SBStructuredData
arch: str
dbg: lldb.SBDebugger
pid: int
@abstractmethod
def __init__(self, exe_ctx: lldb.SBExecutionContext, args: lldb.SBStructuredData):
"""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
self.arch = target.arch_name
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.addressable_bits = {}
self.pid = 42
def get_capabilities(self) -> dict[str, bool]:
"""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_addressable_bits(self) -> dict[str, int]:
"""Get the number of bits this process uses for addressing.
LLDB strips the remaining bits off every code and data address, the
way the `LC_NOTE "addrable bits"` corefile note and the `qHostInfo`
`addressing_bits` key do for corefiles and live processes.
This is queried before the first stop is reported, so the threads and
backtraces built from that stop already have the mask applied.
Returns:
Dict[str:int]: A dictionary with optional "lowmem" and "highmem"
keys, holding the number of bits used for addressing in low and
high memory. "highmem" defaults to "lowmem" when it is missing.
The dictionary can be empty, in which case no bits are stripped.
"""
return self.addressable_bits
def get_memory_region_containing_address(
self, addr: int
) -> Optional[lldb.SBMemoryRegionInfo]:
"""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) -> dict[int, "lldb.plugins.scripted_process.ScriptedThread"]:
"""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: int, size: int, error: lldb.SBError
) -> lldb.SBData:
"""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: int, data: lldb.SBData, error: lldb.SBError
) -> int:
"""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) -> Optional[list[dict]]:
"""Get the list of loaded images for the scripted process.
.. code-block:: python
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) -> int:
"""Get the scripted process identifier.
Returns:
int: The scripted process identifier.
"""
return self.pid
def launch(self) -> lldb.SBError:
"""Simulate the scripted process launch.
Returns:
lldb.SBError: An `lldb.SBError` with error code 0.
"""
return lldb.SBError()
def attach(self, attach_info: lldb.SBAttachInfo) -> lldb.SBError:
"""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: bool = True) -> lldb.SBError:
"""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) -> bool:
"""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) -> str:
"""Get scripted thread plugin name.
Returns:
str: Name of the scripted thread plugin.
"""
return None
def get_process_metadata(self) -> Optional[dict[str, Any]]:
"""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: int, error: lldb.SBError
) -> Union[lldb.SBBreakpoint, bool]:
"""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.
"""
target: lldb.SBTarget
arch: str
originating_process: Union["lldb.plugins.scripted_process.ScriptedProcess", lldb.SBProcess]
process: lldb.SBProcess
args: lldb.SBStructuredData
idx: int
tid: int
name: str
queue: str
state: int
stop_reason: dict[str, Any]
register_info: dict[str, Any]
register_ctx: dict[str, int]
frames: list[dict]
extended_info: list[dict]
@abstractmethod
def __init__(
self,
process: Union["lldb.plugins.scripted_process.ScriptedProcess", lldb.SBProcess],
args: Optional[lldb.SBStructuredData],
):
"""Construct a scripted thread.
Args:
process (ScriptedProcess/lldb.SBProcess): The process owning this thread.
args (lldb.SBStructuredData): A Dictionary holding arbitrary
key/value pairs used by the scripted thread.
"""
self.target = None
self.arch = None
self.originating_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(process, ScriptedProcess)
or isinstance(process, lldb.SBProcess)
and process.IsValid()
):
self.target = process.target
triple = self.target.triple
if triple:
self.arch = triple.split("-")[0]
self.originating_process = process
self.process = self.target.GetProcess()
self.get_register_info()
def get_thread_idx(self) -> int:
"""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) -> int:
"""Get the scripted thread identifier.
Returns:
int: The identifier of the scripted thread.
"""
return self.tid
def get_name(self) -> str:
"""Get the scripted thread name.
Returns:
str: The name of the scripted thread.
"""
return self.name
def get_state(self) -> int:
"""Get the scripted thread state type.
.. code-block:: python
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) -> str:
"""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) -> dict[str, Any]:
"""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) -> list[dict]:
"""Get the list of stack frames for the scripted thread.
.. code-block:: python
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) -> dict[str, Any]:
"""Get the register info dictionary describing the scripted thread's
registers. Lazily populated on first call from a per-architecture
general-purpose register layout keyed off `self.arch`.
Returns:
Dict: The register info dictionary with `sets` and `registers`
keys. `sets` is a list of register set names and `registers`
is a list of register descriptions.
Raises:
ValueError: If `self.arch` is not one of the architectures
the base class ships a register layout for.
"""
if self.register_info is None:
self.register_info = dict()
if "x86_64" in self.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = INTEL64_GPR
elif "arm64" in self.arch or self.arch == "aarch64":
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = ARM64_GPR
elif "arm" in self.arch or "thumb" in self.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = ARM32_GPR
elif "hexagon" in self.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = HEXAGON_GPR
else:
raise ValueError("Unknown architecture", self.arch)
return self.register_info
@abstractmethod
def get_register_context(self) -> str:
"""Get the scripted thread register context
Returns:
str: A byte representing all register's value.
"""
pass
def get_extended_info(self) -> list[dict]:
"""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
def get_scripted_frame_plugin(self) -> Optional[str]:
"""Get scripted frame plugin name.
Returns:
str: Name of the scripted frame plugin.
"""
return None
class ScriptedFrame(metaclass=ABCMeta):
"""
The base class for a scripted frame.
Most of the base class methods are `@abstractmethod` that need to be
overwritten by the inheriting class.
"""
target: lldb.SBTarget
arch: str
originating_thread: Union["lldb.plugins.scripted_process.ScriptedThread", lldb.SBThread]
thread: lldb.SBThread
process: lldb.SBProcess
args: lldb.SBStructuredData
id: int
name: str
register_info: dict[str, Any]
register_ctx: dict[str, int]
variables: list[lldb.SBValue]
@abstractmethod
def __init__(
self, thread: Union["lldb.plugins.scripted_process.ScriptedThread", lldb.SBThread], args: lldb.SBStructuredData
):
"""Construct a scripted frame.
Args:
thread (ScriptedThread/lldb.SBThread): The thread owning this frame.
args (lldb.SBStructuredData): A Dictionary holding arbitrary
key/value pairs used by the scripted frame.
"""
self.target = None
self.arch = None
self.originating_thread = None
self.thread = None
self.args = None
self.id = None
self.name = None
self.register_info = None
self.register_ctx = {}
self.variables = []
if isinstance(thread, ScriptedThread) or (
isinstance(thread, lldb.SBThread) and thread.IsValid()
):
self.process = thread.process
self.target = self.process.target
triple = self.target.triple
if triple:
self.arch = triple.split("-")[0]
tid = thread.tid if isinstance(thread, ScriptedThread) else thread.id
self.originating_thread = thread
self.thread = self.process.GetThreadByID(tid)
self.get_register_info()
@abstractmethod
def get_id(self) -> int:
"""Get the scripted frame identifier.
Returns:
int: The identifier of the scripted frame in the scripted thread.
"""
pass
def get_pc(self) -> Optional[int]:
"""Get the scripted frame address.
Returns:
int: The optional address of the scripted frame in the scripted thread.
"""
return None
def get_cfa(self) -> int:
"""Get the Call Frame Address for this frame.
By default pass the ID of this frame so the CFA's and the
ID's order the same way on this stop. This won't support
step-in and step-out, for those the frames have to have a
stable CFA.
"""
return self.get_id()
def get_symbol_context(self) -> Optional[lldb.SBSymbolContext]:
"""Get the scripted frame symbol context.
Returns:
lldb.SBSymbolContext: The symbol context of the scripted frame in the scripted thread.
"""
return None
def is_inlined(self) -> bool:
"""Check if the scripted frame is inlined.
Returns:
bool: True if scripted frame is inlined. False otherwise.
"""
return False
def is_artificial(self) -> bool:
"""Check if the scripted frame is artificial.
Returns:
bool: True if scripted frame is artificial. False otherwise.
"""
return True
def is_hidden(self) -> bool:
"""Check if the scripted frame is hidden.
Returns:
bool: True if scripted frame is hidden. False otherwise.
"""
return False
def get_function_name(self) -> str:
"""Get the scripted frame function name.
Returns:
str: The function name of the scripted frame.
"""
return self.name
def get_display_function_name(self) -> str:
"""Get the scripted frame display function name.
Returns:
str: The display function name of the scripted frame.
"""
return self.get_function_name()
def get_variables(
self, filters: lldb.SBVariablesOptions
) -> Optional[lldb.SBValueList]:
"""Get the scripted thread state type.
Args:
filter (lldb.SBVariablesOptions): The filter used to resolve the variables
Returns:
lldb.SBValueList: The SBValueList containing the SBValue for each resolved variable.
Returns None by default.
"""
return None
def get_register_info(self) -> dict[str, Any]:
"""Get the register info dictionary describing the scripted frame's
registers. Delegates to the originating scripted thread when there
is one; otherwise lazily populates a per-architecture
general-purpose register layout keyed off `self.arch`.
Returns:
Dict: The register info dictionary with `sets` and `registers`
keys. `sets` is a list of register set names and `registers`
is a list of register descriptions.
Raises:
ValueError: If `self.arch` is not one of the architectures
the base class ships a register layout for.
"""
if self.register_info is None:
if isinstance(self.originating_thread, ScriptedThread):
self.register_info = self.originating_thread.get_register_info()
elif isinstance(self.originating_thread, lldb.SBThread):
self.register_info = dict()
if "x86_64" in self.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = INTEL64_GPR
elif "arm64" in self.arch or self.arch == "aarch64":
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = ARM64_GPR
elif "arm" in self.arch or "thumb" in self.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = ARM32_GPR
elif "hexagon" in self.arch:
self.register_info["sets"] = ["General Purpose Registers"]
self.register_info["registers"] = HEXAGON_GPR
elif "wasm" in self.arch:
# WebAssembly is a stack machine with no general-purpose
# register file, so there is no GPR layout to expose. Leave
# the register info empty rather than raising, which would
# otherwise prevent the scripted frame from constructing.
self.register_info["sets"] = []
self.register_info["registers"] = []
else:
raise ValueError("Unknown architecture", self.arch)
return self.register_info
@abstractmethod
def get_register_context(self) -> str:
"""Get the scripted thread register context
Returns:
str: A byte representing all register's value.
"""
pass
# def get_plan_spec_for_step_type(self, step_type : lldb.StepType):
# """Optional method. If this ScriptedFrame can produce a ThreadPlan
# that implements the given step_type, then it should return a Python
# dictionary with the `class_name` key giving the name of a class that
# implements the step plan, and an optional extra_args dictionary that
# will be passed to the constructor of your step-plan class. If the
# class name is an empty string, that means use the standard stepping
# algorithms for this step.
# The body below tells lldb to fall back to the standard stepping
# algorithm. However, the method is commented out in the base class,
# since if you really don't intend to provide stepping support,
# it's simpler to just not implement this API."""
#
# dict = {"class_name" : "", extra_args : {"step_type" : str(step_type)}
# return dict
class PassthroughScriptedProcess(ScriptedProcess):
"""A reference `ScriptedProcess` subclass that forwards every request to
a "driving" process running in another target of the same debugger.
Useful as a starting point when the extension only needs to reshape or
filter data from a real underlying process."""
driving_target = None
driving_process = None
def __init__(
self,
exe_ctx: lldb.SBExecutionContext,
args: lldb.SBStructuredData,
launched_driving_process: bool = True,
):
"""Construct a passthrough scripted process by looking up the driving
target's index in `args["driving_target_idx"]` and (unless
`launched_driving_process` is `False`) mirroring its threads and
loaded images into `self`.
"""
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: int
) -> Optional[lldb.SBMemoryRegionInfo]:
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: int, size: int, error: lldb.SBError
) -> lldb.SBData:
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: int, data: lldb.SBData, error: lldb.SBError
) -> int:
return self.driving_process.WriteMemory(
addr, bytearray(data.uint8.all()), error
)
def get_process_id(self) -> int:
return self.driving_process.GetProcessID()
def is_alive(self) -> bool:
return True
def get_scripted_thread_plugin(self) -> str:
return f"{PassthroughScriptedThread.__module__}.{PassthroughScriptedThread.__name__}"
class PassthroughScriptedThread(ScriptedThread):
"""A reference `ScriptedThread` subclass that forwards every request to
a specific thread of a driving process. See `PassthroughScriptedProcess`
for the process-side counterpart."""
def __init__(
self,
process: Union["lldb.plugins.scripted_process.ScriptedProcess", lldb.SBProcess],
args: lldb.SBStructuredData,
):
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) -> int:
return self.id
def get_name(self) -> str:
return f"{PassthroughScriptedThread.__name__}.thread-{self.idx}"
def get_stop_reason(self) -> dict:
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.arch:
stop_reason["type"] = lldb.eStopReasonException
stop_reason["data"]["desc"] = (
self.driving_thread.GetStopDescription(100)
)
elif self.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) -> Optional[str]:
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())
ARM32_GPR = [
{
"name": "r0",
"bitsize": 32,
"offset": 0,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
"generic": "arg0",
"alt-name": "arg0",
},
{
"name": "r1",
"bitsize": 32,
"offset": 4,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 1,
"dwarf": 1,
"generic": "arg1",
"alt-name": "arg1",
},
{
"name": "r2",
"bitsize": 32,
"offset": 8,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 2,
"dwarf": 2,
"generic": "arg2",
"alt-name": "arg2",
},
{
"name": "r3",
"bitsize": 32,
"offset": 12,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 3,
"dwarf": 3,
"generic": "arg3",
"alt-name": "arg3",
},
{
"name": "r4",
"bitsize": 32,
"offset": 16,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 4,
"dwarf": 4,
},
{
"name": "r5",
"bitsize": 32,
"offset": 20,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 5,
"dwarf": 5,
},
{
"name": "r6",
"bitsize": 32,
"offset": 24,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 6,
"dwarf": 6,
},
{
"name": "r7",
"bitsize": 32,
"offset": 28,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 7,
"dwarf": 7,
},
{
"name": "r8",
"bitsize": 32,
"offset": 32,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 8,
"dwarf": 8,
},
{
"name": "r9",
"bitsize": 32,
"offset": 36,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 9,
"dwarf": 9,
},
{
"name": "r10",
"bitsize": 32,
"offset": 40,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 10,
"dwarf": 10,
},
{
"name": "r11",
"bitsize": 32,
"offset": 44,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 11,
"dwarf": 11,
"generic": "fp",
"alt-name": "fp",
},
{
"name": "r12",
"bitsize": 32,
"offset": 48,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 12,
"dwarf": 12,
},
{
"name": "sp",
"bitsize": 32,
"offset": 52,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 13,
"dwarf": 13,
"generic": "sp",
"alt-name": "r13",
},
{
"name": "lr",
"bitsize": 32,
"offset": 56,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 14,
"dwarf": 14,
"generic": "lr",
"alt-name": "r14",
},
{
"name": "pc",
"bitsize": 32,
"offset": 60,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 15,
"dwarf": 15,
"generic": "pc",
"alt-name": "r15",
},
{
"name": "cpsr",
"bitsize": 32,
"offset": 64,
"encoding": "uint",
"format": "hex",
"set": 0,
"dwarf": 128,
},
]
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,
},
]
HEXAGON_GPR = [
{
"name": "r0",
"bitsize": 32,
"offset": 0,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r1",
"bitsize": 32,
"offset": 4,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r2",
"bitsize": 32,
"offset": 8,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r3",
"bitsize": 32,
"offset": 12,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r4",
"bitsize": 32,
"offset": 16,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r5",
"bitsize": 32,
"offset": 20,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r6",
"bitsize": 32,
"offset": 24,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r7",
"bitsize": 32,
"offset": 28,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r8",
"bitsize": 32,
"offset": 32,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r9",
"bitsize": 32,
"offset": 36,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r10",
"bitsize": 32,
"offset": 40,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r11",
"bitsize": 32,
"offset": 44,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r12",
"bitsize": 32,
"offset": 48,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r13",
"bitsize": 32,
"offset": 52,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r14",
"bitsize": 32,
"offset": 56,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r15",
"bitsize": 32,
"offset": 60,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r16",
"bitsize": 32,
"offset": 64,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r17",
"bitsize": 32,
"offset": 68,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r18",
"bitsize": 32,
"offset": 72,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r19",
"bitsize": 32,
"offset": 76,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r20",
"bitsize": 32,
"offset": 80,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r21",
"bitsize": 32,
"offset": 84,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r22",
"bitsize": 32,
"offset": 88,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r23",
"bitsize": 32,
"offset": 92,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r24",
"bitsize": 32,
"offset": 96,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r25",
"bitsize": 32,
"offset": 100,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r26",
"bitsize": 32,
"offset": 104,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r27",
"bitsize": 32,
"offset": 108,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r28",
"bitsize": 32,
"offset": 112,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "r29",
"bitsize": 32,
"offset": 116,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
"alt-name": "sp",
},
{
"name": "r30",
"bitsize": 32,
"offset": 120,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
"alt-name": "fp",
},
{
"name": "r31",
"bitsize": 32,
"offset": 124,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
"alt-name": "lr",
},
{
"name": "sa0",
"bitsize": 32,
"offset": 128,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "lc0",
"bitsize": 32,
"offset": 132,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "sa1",
"bitsize": 32,
"offset": 136,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "lc1",
"bitsize": 32,
"offset": 140,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "p3_0",
"bitsize": 32,
"offset": 144,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "m0",
"bitsize": 32,
"offset": 148,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "m1",
"bitsize": 32,
"offset": 152,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "usr",
"bitsize": 32,
"offset": 156,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "pc",
"bitsize": 32,
"offset": 160,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
"generic": "pc",
"alt-name": "pc",
},
{
"name": "ugp",
"bitsize": 32,
"offset": 164,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "gp",
"bitsize": 32,
"offset": 168,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "cs0",
"bitsize": 32,
"offset": 172,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "cs1",
"bitsize": 32,
"offset": 176,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "framelimit",
"bitsize": 32,
"offset": 180,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
{
"name": "framekey",
"bitsize": 32,
"offset": 184,
"encoding": "uint",
"format": "hex",
"set": 0,
"gcc": 0,
"dwarf": 0,
},
]
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,
},
]