diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py index fd0f50d2db..0eddc70ba9 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/commands.py @@ -562,6 +562,8 @@ def ghidra_trace_putval(value: str, pages: bool = True, *, is_mi: bool, STATE.require_tx() val = gdb.parse_and_eval(value) + if val.address is None: + raise gdb.GdbError(f"Value '{value}' has no address") try: start = int(val.address) except gdb.error as e: @@ -1066,7 +1068,7 @@ def ghidra_trace_put_inferiors(*, is_mi: bool, **kwargs) -> None: put_inferiors() -def put_available() -> List[util.Available]: +def put_available() -> None: trace = STATE.require_trace() availables = util.AVAILABLE_INFO_READER.get_availables() keys = [] diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py index 890f3ca8ea..dc7d31d3b3 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/hooks.py @@ -456,7 +456,7 @@ def on_breakpoint_deleted(b: gdb.Breakpoint) -> None: @log_errors -def on_before_prompt() -> object: +def on_before_prompt(a: None) -> object: HOOK_STATE.end_batch() return None diff --git a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/util.py b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/util.py index 5733ad7507..9cd311c358 100644 --- a/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/util.py +++ b/Ghidra/Debug/Debugger-agent-gdb/src/main/py/src/ghidragdb/util.py @@ -18,7 +18,7 @@ from collections import namedtuple import bisect from dataclasses import dataclass 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 @@ -305,9 +305,9 @@ REGION_INFO_READER = _choose_region_info_reader() AVAILABLES_CMD = 'info os processes' AVAILABLE_PATTERN = re.compile("\\s*" + - "(?P[0-9]+)\\s+" + - "(?P[0-9,A-Z,a-z]+)\\s+" + - "(?P.*)") + "(?P[0-9]+)\\s+" + + "(?P[0-9,A-Z,a-z]+)\\s+" + + "(?P.*)") class AvailableInfoReader(object): @@ -321,7 +321,7 @@ class AvailableInfoReader(object): pid = mat['pid'] user = mat['user'] command = mat['command'] - return Available(pid, user, command) + return Available(int(pid), user, command) def get_availables(self) -> List[Available]: availables: List[Available] = [] @@ -365,12 +365,12 @@ class BreakpointLocation: # Quite a hack, but only needed for type annotations if not hasattr(gdb, 'BreakpointLocation'): - gdb.BreakpointLocation = BreakpointLocation + gdb.BreakpointLocation = BreakpointLocation # type: ignore class BreakpointLocationInfoReader(object): @abstractmethod - def get_locations(self, breakpoint: gdb.Breakpoint) -> List[Union[ + def get_locations(self, breakpoint: gdb.Breakpoint) -> Sequence[Union[ BreakpointLocation, gdb.BreakpointLocation]]: pass @@ -396,8 +396,10 @@ class BreakpointLocationInfoReaderV9(BreakpointLocationInfoReader): if breakpoint.location is None: return [] try: - address = int(gdb.parse_and_eval( - breakpoint.location).address) & compute_max_addr() + loc_eval = gdb.parse_and_eval(breakpoint.location) + if loc_eval.address is None: + return [] + address = int(loc_eval.address) & compute_max_addr() loc = BreakpointLocation( address, breakpoint.enabled, thread_groups) return [loc] @@ -407,7 +409,7 @@ class BreakpointLocationInfoReaderV9(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]]: return breakpoint.locations diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/arch.py b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/arch.py index d82e6cb596..4b4a12baa8 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/arch.py +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/arch.py @@ -15,7 +15,7 @@ ## from typing import Dict, List, Optional, Tuple from ghidratrace.client import Address, RegVal -import lldb +import lldb # type: ignore # no stubs available from upstream/SWIG from . import util diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py index c2c18a33d9..49868e3930 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/commands.py @@ -30,7 +30,7 @@ from ghidratrace import sch from ghidratrace.client import (Client, Address, AddressRange, Trace, Schedule, TraceObject, Transaction) 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 @@ -675,7 +675,7 @@ def put_bytes(start: int, end: int, result: lldb.SBCommandReturnObject, raise RuntimeError(f"Cannot read memory at {start:x}") -def eval_address(address: str) -> int: +def eval_address(address: str) -> Optional[int]: try: return util.parse_and_eval(address) except BaseException as e: @@ -684,7 +684,7 @@ def eval_address(address: str) -> int: 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) if start is 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, pages: bool = True) -> None: 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) @@ -783,7 +783,7 @@ def putmem_state(address: str, length: str, state: str, trace = STATE.require_trace() trace.validate_state(state) start, end = eval_range(address, length) - if start is None: + if start is None or end is None: return if pages: start, end = quantize_pages(start, end) @@ -853,7 +853,7 @@ def ghidra_trace_delmem(debugger: lldb.SBDebugger, command: str, STATE.require_tx() start, end = eval_range(address, length) - if start is None: + if start is None or end is None: return proc = util.get_process() 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() start, end = eval_range(address, length) - if start is None: + if start is None or end is None: return proc = util.get_process() 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() -def put_available() -> List[util.Available]: +def put_available() -> None: trace = STATE.require_trace() availables = util.AVAILABLE_INFO_READER.get_availables() keys = [] diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/hooks.py b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/hooks.py index 1ecb6677e7..44cf65ecc1 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/hooks.py +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/hooks.py @@ -18,7 +18,7 @@ import threading import time from typing import Any, Optional, Union -import lldb +import lldb # type: ignore # no stubs available from upstream/SWIG from . import commands, util @@ -113,10 +113,11 @@ class ProcessState(object): commands.put_processes() commands.put_threads() - def record_exited(self, exit_code): + def record_exited(self, exit_code: int): proc = util.get_process() 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('State', 'TERMINATED') diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py index 9906151bce..17fe205779 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/methods.py @@ -18,7 +18,7 @@ import re import sys 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.client import ( diff --git a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/util.py b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/util.py index bd714ab6c7..3c356c2f96 100644 --- a/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/util.py +++ b/Ghidra/Debug/Debugger-agent-lldb/src/main/py/src/ghidralldb/util.py @@ -18,9 +18,9 @@ from dataclasses import dataclass import os import re 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) @@ -45,6 +45,10 @@ def _compute_lldb_ver() -> LldbVersion: LLDB_VERSION = _compute_lldb_ver() if LLDB_VERSION.major < 18: 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 " @@ -194,7 +198,7 @@ class AvailableInfoReader(object): command = info.GetExecutableFile() return Available(pid, name, command) - def get_availables(self) -> List[Available]: + def get_availables(self) -> Union[List[Available], Iterator[Process]]: availables = [] platform = get_debugger().GetPlatformAtIndex(0) err = lldb.SBError()