Merge remote-tracking branch 'origin/GP-6353_d-millar_type_errors_RB260422--SQUASHED'

This commit is contained in:
Ryan Kurtz
2026-04-23 04:53:16 -04:00
8 changed files with 37 additions and 28 deletions
@@ -562,6 +562,8 @@ def ghidra_trace_putval(value: str, pages: bool = True, *, is_mi: bool,
STATE.require_tx() STATE.require_tx()
val = gdb.parse_and_eval(value) val = gdb.parse_and_eval(value)
if val.address is None:
raise gdb.GdbError(f"Value '{value}' has no address")
try: try:
start = int(val.address) start = int(val.address)
except gdb.error as e: except gdb.error as e:
@@ -1066,7 +1068,7 @@ def ghidra_trace_put_inferiors(*, is_mi: bool, **kwargs) -> None:
put_inferiors() put_inferiors()
def put_available() -> List[util.Available]: def put_available() -> None:
trace = STATE.require_trace() trace = STATE.require_trace()
availables = util.AVAILABLE_INFO_READER.get_availables() availables = util.AVAILABLE_INFO_READER.get_availables()
keys = [] keys = []
@@ -456,7 +456,7 @@ def on_breakpoint_deleted(b: gdb.Breakpoint) -> None:
@log_errors @log_errors
def on_before_prompt() -> object: def on_before_prompt(a: None) -> object:
HOOK_STATE.end_batch() HOOK_STATE.end_batch()
return None return None
@@ -18,7 +18,7 @@ from collections import namedtuple
import bisect import bisect
from dataclasses import dataclass from dataclasses import dataclass
import re import re
from typing import Callable, Dict, List, Optional, Set, Tuple, Union from typing import Callable, Dict, List, Optional, Sequence, Set, Tuple, Union
import gdb import gdb
@@ -305,9 +305,9 @@ REGION_INFO_READER = _choose_region_info_reader()
AVAILABLES_CMD = 'info os processes' AVAILABLES_CMD = 'info os processes'
AVAILABLE_PATTERN = re.compile("\\s*" + AVAILABLE_PATTERN = re.compile("\\s*" +
"(?P<pid>[0-9]+)\\s+" + "(?P<pid>[0-9]+)\\s+" +
"(?P<user>[0-9,A-Z,a-z]+)\\s+" + "(?P<user>[0-9,A-Z,a-z]+)\\s+" +
"(?P<command>.*)") "(?P<command>.*)")
class AvailableInfoReader(object): class AvailableInfoReader(object):
@@ -321,7 +321,7 @@ class AvailableInfoReader(object):
pid = mat['pid'] pid = mat['pid']
user = mat['user'] user = mat['user']
command = mat['command'] command = mat['command']
return Available(pid, user, command) return Available(int(pid), user, command)
def get_availables(self) -> List[Available]: def get_availables(self) -> List[Available]:
availables: List[Available] = [] availables: List[Available] = []
@@ -365,12 +365,12 @@ class BreakpointLocation:
# Quite a hack, but only needed for type annotations # Quite a hack, but only needed for type annotations
if not hasattr(gdb, 'BreakpointLocation'): if not hasattr(gdb, 'BreakpointLocation'):
gdb.BreakpointLocation = BreakpointLocation gdb.BreakpointLocation = BreakpointLocation # type: ignore
class BreakpointLocationInfoReader(object): class BreakpointLocationInfoReader(object):
@abstractmethod @abstractmethod
def get_locations(self, breakpoint: gdb.Breakpoint) -> List[Union[ def get_locations(self, breakpoint: gdb.Breakpoint) -> Sequence[Union[
BreakpointLocation, gdb.BreakpointLocation]]: BreakpointLocation, gdb.BreakpointLocation]]:
pass pass
@@ -396,8 +396,10 @@ class BreakpointLocationInfoReaderV9(BreakpointLocationInfoReader):
if breakpoint.location is None: if breakpoint.location is None:
return [] return []
try: try:
address = int(gdb.parse_and_eval( loc_eval = gdb.parse_and_eval(breakpoint.location)
breakpoint.location).address) & compute_max_addr() if loc_eval.address is None:
return []
address = int(loc_eval.address) & compute_max_addr()
loc = BreakpointLocation( loc = BreakpointLocation(
address, breakpoint.enabled, thread_groups) address, breakpoint.enabled, thread_groups)
return [loc] return [loc]
@@ -407,7 +409,7 @@ class BreakpointLocationInfoReaderV9(BreakpointLocationInfoReader):
class BreakpointLocationInfoReaderV13(BreakpointLocationInfoReader): class BreakpointLocationInfoReaderV13(BreakpointLocationInfoReader):
def get_locations(self, breakpoint: gdb.Breakpoint) -> List[Union[ def get_locations(self, breakpoint: gdb.Breakpoint) -> Sequence[Union[
BreakpointLocation, gdb.BreakpointLocation]]: BreakpointLocation, gdb.BreakpointLocation]]:
return breakpoint.locations return breakpoint.locations
@@ -15,7 +15,7 @@
## ##
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional, Tuple
from ghidratrace.client import Address, RegVal from ghidratrace.client import Address, RegVal
import lldb import lldb # type: ignore # no stubs available from upstream/SWIG
from . import util from . import util
@@ -30,7 +30,7 @@ from ghidratrace import sch
from ghidratrace.client import (Client, Address, AddressRange, Trace, Schedule, from ghidratrace.client import (Client, Address, AddressRange, Trace, Schedule,
TraceObject, Transaction) TraceObject, Transaction)
from ghidratrace.display import print_tabular_values, wait from ghidratrace.display import print_tabular_values, wait
import lldb import lldb # type: ignore # no stubs available from upstream/SWIG
from . import arch, hooks, methods, util from . import arch, hooks, methods, util
@@ -675,7 +675,7 @@ def put_bytes(start: int, end: int, result: lldb.SBCommandReturnObject,
raise RuntimeError(f"Cannot read memory at {start:x}") raise RuntimeError(f"Cannot read memory at {start:x}")
def eval_address(address: str) -> int: def eval_address(address: str) -> Optional[int]:
try: try:
return util.parse_and_eval(address) return util.parse_and_eval(address)
except BaseException as e: except BaseException as e:
@@ -684,7 +684,7 @@ def eval_address(address: str) -> int:
return None return None
def eval_range(address: str, length: str) -> Tuple[int, int]: def eval_range(address: str, length: str) -> Tuple[Optional[int], Optional[int]]:
start = eval_address(address) start = eval_address(address)
if start is None: if start is None:
return None, None return None, None
@@ -698,7 +698,7 @@ def eval_range(address: str, length: str) -> Tuple[int, int]:
def putmem(address: str, length: str, result: lldb.SBCommandReturnObject, def putmem(address: str, length: str, result: lldb.SBCommandReturnObject,
pages: bool = True) -> None: pages: bool = True) -> None:
start, end = eval_range(address, length) start, end = eval_range(address, length)
if start is not None: if start is not None and end is not None:
put_bytes(start, end, result, pages) put_bytes(start, end, result, pages)
@@ -783,7 +783,7 @@ def putmem_state(address: str, length: str, state: str,
trace = STATE.require_trace() trace = STATE.require_trace()
trace.validate_state(state) trace.validate_state(state)
start, end = eval_range(address, length) start, end = eval_range(address, length)
if start is None: if start is None or end is None:
return return
if pages: if pages:
start, end = quantize_pages(start, end) start, end = quantize_pages(start, end)
@@ -853,7 +853,7 @@ def ghidra_trace_delmem(debugger: lldb.SBDebugger, command: str,
STATE.require_tx() STATE.require_tx()
start, end = eval_range(address, length) start, end = eval_range(address, length)
if start is None: if start is None or end is None:
return return
proc = util.get_process() proc = util.get_process()
base, addr = trace.extra.require_mm().map(proc, start) base, addr = trace.extra.require_mm().map(proc, start)
@@ -1363,7 +1363,7 @@ def ghidra_trace_get_values_rng(debugger: lldb.SBDebugger, command: str,
trace = STATE.require_trace() trace = STATE.require_trace()
start, end = eval_range(address, length) start, end = eval_range(address, length)
if start is None: if start is None or end is None:
return return
proc = util.get_process() proc = util.get_process()
base, addr = trace.extra.require_mm().map(proc, start) base, addr = trace.extra.require_mm().map(proc, start)
@@ -1491,7 +1491,7 @@ def ghidra_trace_put_processes(debugger: lldb.SBDebugger, command: str,
put_processes() put_processes()
def put_available() -> List[util.Available]: def put_available() -> None:
trace = STATE.require_trace() trace = STATE.require_trace()
availables = util.AVAILABLE_INFO_READER.get_availables() availables = util.AVAILABLE_INFO_READER.get_availables()
keys = [] keys = []
@@ -18,7 +18,7 @@ import threading
import time import time
from typing import Any, Optional, Union from typing import Any, Optional, Union
import lldb import lldb # type: ignore # no stubs available from upstream/SWIG
from . import commands, util from . import commands, util
@@ -113,10 +113,11 @@ class ProcessState(object):
commands.put_processes() commands.put_processes()
commands.put_threads() commands.put_threads()
def record_exited(self, exit_code): def record_exited(self, exit_code: int):
proc = util.get_process() proc = util.get_process()
ipath = commands.PROCESS_PATTERN.format(procnum=proc.GetProcessID()) ipath = commands.PROCESS_PATTERN.format(procnum=proc.GetProcessID())
procobj = commands.STATE.trace.proxy_object_path(ipath) trace = commands.STATE.require_trace()
procobj = trace.proxy_object_path(ipath)
procobj.set_value('Exit Code', exit_code) procobj.set_value('Exit Code', exit_code)
procobj.set_value('State', 'TERMINATED') procobj.set_value('State', 'TERMINATED')
@@ -18,7 +18,7 @@ import re
import sys import sys
from typing import Annotated, Any, Optional, Tuple from typing import Annotated, Any, Optional, Tuple
import lldb import lldb # type: ignore # no stubs available from upstream/SWIG
from ghidratrace import sch from ghidratrace import sch
from ghidratrace.client import ( from ghidratrace.client import (
@@ -18,9 +18,9 @@ from dataclasses import dataclass
import os import os
import re import re
import sys import sys
from typing import Any, Dict, List, Optional, Union from typing import Any, Dict, Iterator, List, Optional, Union
import lldb import lldb # type: ignore # no stubs available from upstream/SWIG
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -45,6 +45,10 @@ def _compute_lldb_ver() -> LldbVersion:
LLDB_VERSION = _compute_lldb_ver() LLDB_VERSION = _compute_lldb_ver()
if LLDB_VERSION.major < 18: if LLDB_VERSION.major < 18:
import psutil import psutil
from psutil import Process
else:
class Process(): # type: ignore # dummy when we're not importing psutil
pass
GNU_DEBUGDATA_PREFIX = ".gnu_debugdata for " GNU_DEBUGDATA_PREFIX = ".gnu_debugdata for "
@@ -194,7 +198,7 @@ class AvailableInfoReader(object):
command = info.GetExecutableFile() command = info.GetExecutableFile()
return Available(pid, name, command) return Available(pid, name, command)
def get_availables(self) -> List[Available]: def get_availables(self) -> Union[List[Available], Iterator[Process]]:
availables = [] availables = []
platform = get_debugger().GetPlatformAtIndex(0) platform = get_debugger().GetPlatformAtIndex(0)
err = lldb.SBError() err = lldb.SBError()