]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/python/lib/gdb/dap/sources.py
gdb: add Aaron Griffith to gdb/MAINTAINERS
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / dap / sources.py
CommitLineData
d01e8234 1# Copyright 2023-2025 Free Software Foundation, Inc.
a0b70d99
TT
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
0b7de6d3
GA
16import os
17
c2cf30e7 18from .server import capability, request
0341f276 19from .startup import DAPException, exec_mi_and_log, in_gdb_thread
a0b70d99 20
c64cba1b
TT
21# The next available source reference ID. Must be greater than 0.
22_next_source = 1
23
24# Map from full paths to Source dictionaries.
25_source_map = {}
26
27# Map from a source reference ID back to the same Source that is
28# stored in _source_map.
29_id_map = {}
30
31
32@in_gdb_thread
4b09134a 33def make_source(fullname, filename=None):
c64cba1b
TT
34 """Return the Source for a given file name.
35
36 FULLNAME is the full name. This is used as the key.
4b09134a
TT
37 FILENAME is the base name; if None (the default), then it is
38 computed from FULLNAME.
c64cba1b 39 """
c64cba1b
TT
40 if fullname in _source_map:
41 result = _source_map[fullname]
42 else:
4b09134a
TT
43 if filename is None:
44 filename = os.path.basename(fullname)
45
c64cba1b
TT
46 result = {
47 "name": filename,
48 "path": fullname,
c64cba1b 49 }
0b7de6d3
GA
50
51 if not os.path.exists(fullname):
52 global _next_source
53 result["sourceReference"] = _next_source
54
0b7de6d3
GA
55 _id_map[_next_source] = result
56 _next_source += 1
57
c64cba1b 58 _source_map[fullname] = result
c64cba1b
TT
59 return result
60
61
4b6521cf
TT
62@in_gdb_thread
63def decode_source(source):
64 """Decode a Source object.
65
66 Finds and returns the filename of a given Source object."""
b33b677b 67 if "sourceReference" not in source or source["sourceReference"] <= 0:
68 if "path" in source:
69 return source["path"]
2a89c950 70 raise DAPException("either 'path' or 'sourceReference' must appear in Source")
4b6521cf 71 ref = source["sourceReference"]
4b6521cf 72 if ref not in _id_map:
2a89c950 73 raise DAPException("no sourceReference " + str(ref))
4b6521cf
TT
74 return _id_map[ref]["path"]
75
76
c98921b2
TT
77@request("loadedSources")
78@capability("supportsLoadedSourcesRequest")
79def loaded_sources(**extra):
a0b70d99 80 result = []
0341f276 81 for elt in exec_mi_and_log("-file-list-exec-source-files")["files"]:
c64cba1b 82 result.append(make_source(elt["fullname"], elt["file"]))
a0b70d99
TT
83 return {
84 "sources": result,
85 }
86
87
13bd1a91
TT
88@request("source")
89def source(*, source=None, sourceReference: int, **extra):
90 # The 'sourceReference' parameter is required by the spec, but is
91 # for backward compatibility, which I take to mean that the
92 # 'source' is preferred.
93 if source is None:
94 source = {"sourceReference": sourceReference}
c98921b2
TT
95 filename = decode_source(source)
96 with open(filename) as f:
97 content = f.read()
98 return {
99 "content": content,
100 }