mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 14:49:38 +08:00
Introduce sourceReference handling in DAP
This changes the gdb DAP implementation to emit a real sourceReference, rather than emitting 0. Sources are tracked in some maps in sources.py, and a new helper function is introduced to compute the "Source" object that can be sent to the client.
This commit is contained in:
@ -23,6 +23,7 @@ from contextlib import contextmanager
|
||||
from typing import Optional, Sequence
|
||||
|
||||
from .server import request, capability, send_event
|
||||
from .sources import make_source
|
||||
from .startup import send_gdb_with_response, in_gdb_thread, log_stack
|
||||
from .typecheck import type_check
|
||||
|
||||
@ -105,15 +106,10 @@ def _breakpoint_descriptor(bp):
|
||||
# multiple locations. See
|
||||
# https://github.com/microsoft/debug-adapter-protocol/issues/13
|
||||
loc = bp.locations[0]
|
||||
(basename, line) = loc.source
|
||||
(filename, line) = loc.source
|
||||
result.update(
|
||||
{
|
||||
"source": {
|
||||
"name": os.path.basename(basename),
|
||||
# We probably don't need this but it doesn't hurt to
|
||||
# be explicit.
|
||||
"sourceReference": 0,
|
||||
},
|
||||
"source": make_source(filename, os.path.basename(filename)),
|
||||
"line": line,
|
||||
"instructionReference": hex(loc.address),
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ from gdb.frames import frame_iterator
|
||||
from .frames import frame_id
|
||||
from .modules import module_id
|
||||
from .server import request, capability
|
||||
from .sources import make_source
|
||||
from .startup import send_gdb_with_response, in_gdb_thread
|
||||
from .state import set_thread
|
||||
from .varref import apply_format
|
||||
@ -61,13 +62,7 @@ def _backtrace(thread_id, levels, startFrame, value_format):
|
||||
newframe["line"] = line
|
||||
filename = current_frame.filename()
|
||||
if filename is not None:
|
||||
newframe["source"] = {
|
||||
"name": os.path.basename(filename),
|
||||
"path": filename,
|
||||
# We probably don't need this but it doesn't hurt
|
||||
# to be explicit.
|
||||
"sourceReference": 0,
|
||||
}
|
||||
newframe["source"] = make_source(filename, os.path.basename(filename))
|
||||
frames.append(newframe)
|
||||
# Note that we do not calculate totalFrames here. Its absence
|
||||
# tells the client that it may simply ask for frames until a
|
||||
|
@ -19,16 +19,46 @@ from .server import request, capability
|
||||
from .startup import send_gdb_with_response, in_gdb_thread
|
||||
|
||||
|
||||
# The next available source reference ID. Must be greater than 0.
|
||||
_next_source = 1
|
||||
|
||||
# Map from full paths to Source dictionaries.
|
||||
_source_map = {}
|
||||
|
||||
# Map from a source reference ID back to the same Source that is
|
||||
# stored in _source_map.
|
||||
_id_map = {}
|
||||
|
||||
|
||||
@in_gdb_thread
|
||||
def make_source(fullname, filename):
|
||||
"""Return the Source for a given file name.
|
||||
|
||||
FULLNAME is the full name. This is used as the key.
|
||||
FILENAME is the base name.
|
||||
"""
|
||||
global _source_map
|
||||
if fullname in _source_map:
|
||||
result = _source_map[fullname]
|
||||
else:
|
||||
global _next_source
|
||||
result = {
|
||||
"name": filename,
|
||||
"path": fullname,
|
||||
"sourceReference": _next_source,
|
||||
}
|
||||
_source_map[fullname] = result
|
||||
global _id_map
|
||||
_id_map[_next_source] = result
|
||||
_next_source += 1
|
||||
return result
|
||||
|
||||
|
||||
@in_gdb_thread
|
||||
def _sources():
|
||||
result = []
|
||||
for elt in gdb.execute_mi("-file-list-exec-source-files")["files"]:
|
||||
result.append(
|
||||
{
|
||||
"name": elt["file"],
|
||||
"path": elt["fullname"],
|
||||
}
|
||||
)
|
||||
result.append(make_source(elt["fullname"], elt["file"]))
|
||||
return {
|
||||
"sources": result,
|
||||
}
|
||||
|
Reference in New Issue
Block a user