Remove some DAP helper functions

Now that DAP requests are normally run on the gdb thread, some DAP
helper functions are no longer needed.  Removing these simplifies the
code.
This commit is contained in:
Tom Tromey
2023-11-28 09:18:13 -07:00
parent e60675a228
commit dcdb91b3a6
6 changed files with 78 additions and 123 deletions

View File

@@ -16,31 +16,6 @@
import gdb import gdb
from .server import request, capability from .server import request, capability
from .startup import in_gdb_thread
@in_gdb_thread
def _disassemble(pc, skip_insns, count):
inf = gdb.selected_inferior()
try:
arch = gdb.selected_frame().architecture()
except gdb.error:
# Maybe there was no frame.
arch = inf.architecture()
result = []
total_count = skip_insns + count
for elt in arch.disassemble(pc, count=total_count)[skip_insns:]:
mem = inf.read_memory(elt["addr"], elt["length"])
result.append(
{
"address": hex(elt["addr"]),
"instruction": elt["asm"],
"instructionBytes": mem.hex(),
}
)
return {
"instructions": result,
}
@request("disassemble") @request("disassemble")
@@ -54,4 +29,23 @@ def disassemble(
**extra **extra
): ):
pc = int(memoryReference, 0) + offset pc = int(memoryReference, 0) + offset
return _disassemble(pc, instructionOffset, instructionCount) inf = gdb.selected_inferior()
try:
arch = gdb.selected_frame().architecture()
except gdb.error:
# Maybe there was no frame.
arch = inf.architecture()
result = []
total_count = instructionOffset + instructionCount
for elt in arch.disassemble(pc, count=total_count)[instructionOffset:]:
mem = inf.read_memory(elt["addr"], elt["length"])
result.append(
{
"address": hex(elt["addr"]),
"instruction": elt["asm"],
"instructionBytes": mem.hex(),
}
)
return {
"instructions": result,
}

View File

@@ -57,20 +57,6 @@ class _SetResult(VariableReference):
super().__init__(None, value, "value") super().__init__(None, value, "value")
# Helper function to perform an assignment.
@in_gdb_thread
def _set_expression(expression, value, frame_id, value_format):
with apply_format(value_format):
global_context = True
if frame_id is not None:
select_frame(frame_id)
global_context = False
lhs = gdb.parse_and_eval(expression, global_context=global_context)
rhs = gdb.parse_and_eval(value, global_context=global_context)
lhs.assign(rhs)
return _SetResult(lhs).to_object()
# Helper function to evaluate a gdb command in a certain frame. # Helper function to evaluate a gdb command in a certain frame.
@in_gdb_thread @in_gdb_thread
def _repl(command, frame_id): def _repl(command, frame_id):
@@ -106,14 +92,6 @@ def eval_request(
raise Exception('unknown evaluate context "' + context + '"') raise Exception('unknown evaluate context "' + context + '"')
@in_gdb_thread
def _variables(ref, start, count, value_format):
with apply_format(value_format):
var = find_variable(ref)
children = var.fetch_children(start, count)
return [x.to_object() for x in children]
@request("variables") @request("variables")
# Note that we ignore the 'filter' field. That seems to be # Note that we ignore the 'filter' field. That seems to be
# specific to javascript. # specific to javascript.
@@ -125,7 +103,10 @@ def variables(
if not client_bool_capability("supportsVariablePaging"): if not client_bool_capability("supportsVariablePaging"):
start = 0 start = 0
count = 0 count = 0
return {"variables": _variables(variablesReference, start, count, format)} with apply_format(format):
var = find_variable(variablesReference)
children = var.fetch_children(start, count)
return {"variables": [x.to_object() for x in children]}
@capability("supportsSetExpression") @capability("supportsSetExpression")
@@ -133,18 +114,15 @@ def variables(
def set_expression( def set_expression(
*, expression: str, value: str, frameId: Optional[int] = None, format=None, **args *, expression: str, value: str, frameId: Optional[int] = None, format=None, **args
): ):
return _set_expression(expression, value, frameId, format) with apply_format(format):
global_context = True
if frameId is not None:
# Helper function to perform an assignment. select_frame(frameId)
@in_gdb_thread global_context = False
def _set_variable(ref, name, value, value_format): lhs = gdb.parse_and_eval(expression, global_context=global_context)
with apply_format(value_format): rhs = gdb.parse_and_eval(value, global_context=global_context)
var = find_variable(ref)
lhs = var.find_child_by_name(name)
rhs = gdb.parse_and_eval(value)
lhs.assign(rhs) lhs.assign(rhs)
return lhs.to_object() return _SetResult(lhs).to_object()
@capability("supportsSetVariable") @capability("supportsSetVariable")
@@ -152,4 +130,9 @@ def _set_variable(ref, name, value, value_format):
def set_variable( def set_variable(
*, variablesReference: int, name: str, value: str, format=None, **args *, variablesReference: int, name: str, value: str, format=None, **args
): ):
return _set_variable(variablesReference, name, value, format) with apply_format(format):
var = find_variable(variablesReference)
lhs = var.find_child_by_name(name)
rhs = gdb.parse_and_eval(value)
lhs.assign(rhs)
return lhs.to_object()

View File

@@ -20,7 +20,7 @@ from typing import Mapping, Optional, Sequence
from .events import exec_and_expect_stop, expect_process from .events import exec_and_expect_stop, expect_process
from .server import request, capability from .server import request, capability
from .startup import in_gdb_thread, exec_and_log from .startup import exec_and_log
# The program being launched, or None. This should only be accessed # The program being launched, or None. This should only be accessed
@@ -28,24 +28,6 @@ from .startup import in_gdb_thread, exec_and_log
_program = None _program = None
@in_gdb_thread
def _launch_setup(program, cwd, args, env, stopAtBeginningOfMainSubprogram):
if cwd is not None:
exec_and_log("cd " + cwd)
if program is not None:
exec_and_log("file " + program)
inf = gdb.selected_inferior()
if stopAtBeginningOfMainSubprogram:
main = inf.main_name
if main is not None:
exec_and_log("tbreak " + main)
inf.arguments = args
if env is not None:
inf.clear_env()
for name, value in env.items():
inf.set_env(name, value)
# Any parameters here are necessarily extensions -- DAP requires this # Any parameters here are necessarily extensions -- DAP requires this
# from implementations. Any additions or changes here should be # from implementations. Any additions or changes here should be
# documented in the gdb manual. # documented in the gdb manual.
@@ -61,7 +43,20 @@ def launch(
): ):
global _program global _program
_program = program _program = program
_launch_setup(program, cwd, args, env, stopAtBeginningOfMainSubprogram) if cwd is not None:
exec_and_log("cd " + cwd)
if program is not None:
exec_and_log("file " + program)
inf = gdb.selected_inferior()
if stopAtBeginningOfMainSubprogram:
main = inf.main_name
if main is not None:
exec_and_log("tbreak " + main)
inf.arguments = args
if env is not None:
inf.clear_env()
for name, value in env.items():
inf.set_env(name, value)
@request("attach") @request("attach")

View File

@@ -20,18 +20,6 @@ from typing import Optional
from .server import capability, request from .server import capability, request
from .sources import decode_source from .sources import decode_source
from .startup import in_gdb_thread
@in_gdb_thread
def _find_lines(source, start_line, end_line):
filename = decode_source(source)
lines = set()
for entry in gdb.execute_mi("-symbol-list-lines", filename)["lines"]:
line = entry["line"]
if line >= start_line and line <= end_line:
lines.add(line)
return {"breakpoints": [{"line": x} for x in sorted(lines)]}
# Note that the spec says that the arguments to this are optional. # Note that the spec says that the arguments to this are optional.
@@ -46,4 +34,10 @@ def _find_lines(source, start_line, end_line):
def breakpoint_locations(*, source, line: int, endLine: Optional[int] = None, **extra): def breakpoint_locations(*, source, line: int, endLine: Optional[int] = None, **extra):
if endLine is None: if endLine is None:
endLine = line endLine = line
return _find_lines(source, line, endLine) filename = decode_source(source)
lines = set()
for entry in gdb.execute_mi("-symbol-list-lines", filename)["lines"]:
this_line = entry["line"]
if this_line >= line and this_line <= endLine:
lines.add(this_line)
return {"breakpoints": [{"line": x} for x in sorted(lines)]}

View File

@@ -45,22 +45,17 @@ def make_module(objf):
return result return result
@in_gdb_thread
def _modules(start, count):
# Don't count invalid objfiles or separate debug objfiles.
objfiles = [x for x in gdb.objfiles() if is_module(x)]
if count == 0:
# Use all items.
last = len(objfiles)
else:
last = start + count
return {
"modules": [make_module(x) for x in objfiles[start:last]],
"totalModules": len(objfiles),
}
@capability("supportsModulesRequest") @capability("supportsModulesRequest")
@request("modules") @request("modules")
def modules(*, startModule: int = 0, moduleCount: int = 0, **args): def modules(*, startModule: int = 0, moduleCount: int = 0, **args):
return _modules(startModule, moduleCount) # Don't count invalid objfiles or separate debug objfiles.
objfiles = [x for x in gdb.objfiles() if is_module(x)]
if moduleCount == 0:
# Use all items.
last = len(objfiles)
else:
last = startModule + moduleCount
return {
"modules": [make_module(x) for x in objfiles[startModule:last]],
"totalModules": len(objfiles),
}

View File

@@ -107,14 +107,13 @@ class _RegisterReference(_ScopeReference):
) )
# Helper function to create a DAP scopes for a given frame ID. @request("scopes")
@in_gdb_thread def scopes(*, frameId: int, **extra):
def _get_scope(id):
global frame_to_scope global frame_to_scope
if id in frame_to_scope: if frameId in frame_to_scope:
scopes = frame_to_scope[id] scopes = frame_to_scope[frameId]
else: else:
frame = frame_for_id(id) frame = frame_for_id(frameId)
scopes = [] scopes = []
# Make sure to handle the None case as well as the empty # Make sure to handle the None case as well as the empty
# iterator case. # iterator case.
@@ -127,10 +126,5 @@ def _get_scope(id):
if locs: if locs:
scopes.append(_ScopeReference("Locals", "locals", frame, locs)) scopes.append(_ScopeReference("Locals", "locals", frame, locs))
scopes.append(_RegisterReference("Registers", frame)) scopes.append(_RegisterReference("Registers", frame))
frame_to_scope[id] = scopes frame_to_scope[frameId] = scopes
return [x.to_object() for x in scopes] return {"scopes": [x.to_object() for x in scopes]}
@request("scopes")
def scopes(*, frameId: int, **extra):
return {"scopes": _get_scope(frameId)}