]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/python/lib/gdb/dap/evaluate.py
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / python / lib / gdb / dap / evaluate.py
1 # Copyright 2022-2024 Free Software Foundation, Inc.
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
16 import gdb
17
18 # This is deprecated in 3.9, but required in older versions.
19 from typing import Optional
20
21 from .frames import select_frame
22 from .server import capability, request, client_bool_capability
23 from .startup import in_gdb_thread, parse_and_eval, DAPException
24 from .varref import find_variable, VariableReference, apply_format
25
26
27 class EvaluateResult(VariableReference):
28 def __init__(self, value):
29 super().__init__(None, value, "result")
30
31
32 # Helper function to evaluate an expression in a certain frame.
33 @in_gdb_thread
34 def _evaluate(expr, frame_id, value_format):
35 with apply_format(value_format):
36 global_context = True
37 if frame_id is not None:
38 select_frame(frame_id)
39 global_context = False
40 val = parse_and_eval(expr, global_context=global_context)
41 ref = EvaluateResult(val)
42 return ref.to_object()
43
44
45 # Like _evaluate but ensure that the expression cannot cause side
46 # effects.
47 @in_gdb_thread
48 def _eval_for_hover(expr, frame_id, value_format):
49 with gdb.with_parameter("may-write-registers", "off"):
50 with gdb.with_parameter("may-write-memory", "off"):
51 with gdb.with_parameter("may-call-functions", "off"):
52 return _evaluate(expr, frame_id, value_format)
53
54
55 class _SetResult(VariableReference):
56 def __init__(self, value):
57 super().__init__(None, value, "value")
58
59
60 # Helper function to evaluate a gdb command in a certain frame.
61 @in_gdb_thread
62 def _repl(command, frame_id):
63 if frame_id is not None:
64 select_frame(frame_id)
65 val = gdb.execute(command, from_tty=True, to_string=True)
66 return {
67 "result": val,
68 "variablesReference": 0,
69 }
70
71
72 @request("evaluate")
73 @capability("supportsEvaluateForHovers")
74 @capability("supportsValueFormattingOptions")
75 def eval_request(
76 *,
77 expression: str,
78 frameId: Optional[int] = None,
79 context: str = "variables",
80 format=None,
81 **args,
82 ):
83 if context in ("watch", "variables"):
84 # These seem to be expression-like.
85 return _evaluate(expression, frameId, format)
86 elif context == "hover":
87 return _eval_for_hover(expression, frameId, format)
88 elif context == "repl":
89 # Ignore the format for repl evaluation.
90 return _repl(expression, frameId)
91 else:
92 raise DAPException('unknown evaluate context "' + context + '"')
93
94
95 @request("variables")
96 # Note that we ignore the 'filter' field. That seems to be
97 # specific to javascript.
98 def variables(
99 *, variablesReference: int, start: int = 0, count: int = 0, format=None, **args
100 ):
101 # This behavior was clarified here:
102 # https://github.com/microsoft/debug-adapter-protocol/pull/394
103 if not client_bool_capability("supportsVariablePaging"):
104 start = 0
105 count = 0
106 with apply_format(format):
107 var = find_variable(variablesReference)
108 children = var.fetch_children(start, count)
109 return {"variables": [x.to_object() for x in children]}
110
111
112 @capability("supportsSetExpression")
113 @request("setExpression")
114 def set_expression(
115 *, expression: str, value: str, frameId: Optional[int] = None, format=None, **args
116 ):
117 with apply_format(format):
118 global_context = True
119 if frameId is not None:
120 select_frame(frameId)
121 global_context = False
122 lhs = parse_and_eval(expression, global_context=global_context)
123 rhs = parse_and_eval(value, global_context=global_context)
124 lhs.assign(rhs)
125 return _SetResult(lhs).to_object()
126
127
128 @capability("supportsSetVariable")
129 @request("setVariable")
130 def set_variable(
131 *, variablesReference: int, name: str, value: str, format=None, **args
132 ):
133 with apply_format(format):
134 var = find_variable(variablesReference)
135 lhs = var.find_child_by_name(name)
136 rhs = parse_and_eval(value)
137 lhs.assign(rhs)
138 return lhs.to_object()