aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2023-12-12 09:29:43 -0700
committerTom Tromey <tromey@adacore.com>2023-12-22 09:57:30 -0700
commit2a89c9508eac42395ff622492b2653e1b833cb9a (patch)
tree29c48b45162a09ff21c5b5fa62de5251024c9d08 /gdb
parent9b9e5c09b1879766af959d276e99780982f4350b (diff)
downloadfsf-binutils-gdb-2a89c9508eac42395ff622492b2653e1b833cb9a.zip
fsf-binutils-gdb-2a89c9508eac42395ff622492b2653e1b833cb9a.tar.gz
fsf-binutils-gdb-2a89c9508eac42395ff622492b2653e1b833cb9a.tar.bz2
Introduce and use DAPException
This introduces a new DAPException class, and then changes various spots in the DAP implementation to wrap "expected" exceptions in this. This class will help detect rogue exceptions caused by bugs in the implementation. Reviewed-By: Kévin Le Gouguec <legouguec@adacore.com>
Diffstat (limited to 'gdb')
-rw-r--r--gdb/python/lib/gdb/dap/breakpoint.py8
-rw-r--r--gdb/python/lib/gdb/dap/evaluate.py12
-rw-r--r--gdb/python/lib/gdb/dap/launch.py4
-rw-r--r--gdb/python/lib/gdb/dap/sources.py6
-rw-r--r--gdb/python/lib/gdb/dap/startup.py18
-rw-r--r--gdb/python/lib/gdb/dap/varref.py6
6 files changed, 37 insertions, 17 deletions
diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py
index 33aa18e..c67bb47 100644
--- a/gdb/python/lib/gdb/dap/breakpoint.py
+++ b/gdb/python/lib/gdb/dap/breakpoint.py
@@ -24,7 +24,7 @@ from typing import Optional, Sequence
from .server import request, capability, send_event
from .sources import make_source
-from .startup import in_gdb_thread, log_stack
+from .startup import in_gdb_thread, log_stack, parse_and_eval, DAPException
from .typecheck import type_check
@@ -168,7 +168,7 @@ def _set_breakpoints_callback(kind, specs, creator):
bp.ignore_count = 0
else:
bp.ignore_count = int(
- gdb.parse_and_eval(hit_condition, global_context=True)
+ parse_and_eval(hit_condition, global_context=True)
)
# Reaching this spot means success.
@@ -212,6 +212,7 @@ class _PrintBreakpoint(gdb.Breakpoint):
# have already been stripped by the placement of the
# regex capture in the 'split' call.
try:
+ # No real need to use the DAP parse_and_eval here.
val = gdb.parse_and_eval(item)
output += str(val)
except Exception as e:
@@ -360,12 +361,13 @@ def _catch_exception(filterId, **args):
if filterId in ("assert", "exception", "throw", "rethrow", "catch"):
cmd = "-catch-" + filterId
else:
- raise Exception("Invalid exception filterID: " + str(filterId))
+ raise DAPException("Invalid exception filterID: " + str(filterId))
result = gdb.execute_mi(cmd)
# A little lame that there's no more direct way.
for bp in gdb.breakpoints():
if bp.number == result["bkptno"]:
return bp
+ # Not a DAPException because this is definitely unexpected.
raise Exception("Could not find catchpoint after creating")
diff --git a/gdb/python/lib/gdb/dap/evaluate.py b/gdb/python/lib/gdb/dap/evaluate.py
index d39e787..eb38baf 100644
--- a/gdb/python/lib/gdb/dap/evaluate.py
+++ b/gdb/python/lib/gdb/dap/evaluate.py
@@ -20,7 +20,7 @@ from typing import Optional
from .frames import select_frame
from .server import capability, request, client_bool_capability
-from .startup import in_gdb_thread
+from .startup import in_gdb_thread, parse_and_eval, DAPException
from .varref import find_variable, VariableReference, apply_format
@@ -37,7 +37,7 @@ def _evaluate(expr, frame_id, value_format):
if frame_id is not None:
select_frame(frame_id)
global_context = False
- val = gdb.parse_and_eval(expr, global_context=global_context)
+ val = parse_and_eval(expr, global_context=global_context)
ref = EvaluateResult(val)
return ref.to_object()
@@ -89,7 +89,7 @@ def eval_request(
# Ignore the format for repl evaluation.
return _repl(expression, frameId)
else:
- raise Exception('unknown evaluate context "' + context + '"')
+ raise DAPException('unknown evaluate context "' + context + '"')
@request("variables")
@@ -119,8 +119,8 @@ def set_expression(
if frameId is not None:
select_frame(frameId)
global_context = False
- lhs = gdb.parse_and_eval(expression, global_context=global_context)
- rhs = gdb.parse_and_eval(value, global_context=global_context)
+ lhs = parse_and_eval(expression, global_context=global_context)
+ rhs = parse_and_eval(value, global_context=global_context)
lhs.assign(rhs)
return _SetResult(lhs).to_object()
@@ -133,6 +133,6 @@ def set_variable(
with apply_format(format):
var = find_variable(variablesReference)
lhs = var.find_child_by_name(name)
- rhs = gdb.parse_and_eval(value)
+ rhs = parse_and_eval(value)
lhs.assign(rhs)
return lhs.to_object()
diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py
index 675542c..5f95bfd 100644
--- a/gdb/python/lib/gdb/dap/launch.py
+++ b/gdb/python/lib/gdb/dap/launch.py
@@ -20,7 +20,7 @@ from typing import Mapping, Optional, Sequence
from .events import exec_and_expect_stop, expect_process
from .server import request, capability
-from .startup import exec_and_log
+from .startup import exec_and_log, DAPException
# The program being launched, or None. This should only be accessed
@@ -86,7 +86,7 @@ def attach(
elif target is not None:
cmd = "target remote " + target
else:
- raise Exception("attach requires either 'pid' or 'target'")
+ raise DAPException("attach requires either 'pid' or 'target'")
expect_process("attach")
exec_and_log(cmd)
diff --git a/gdb/python/lib/gdb/dap/sources.py b/gdb/python/lib/gdb/dap/sources.py
index 821205c..d73a3f8 100644
--- a/gdb/python/lib/gdb/dap/sources.py
+++ b/gdb/python/lib/gdb/dap/sources.py
@@ -18,7 +18,7 @@ import os
import gdb
from .server import request, capability
-from .startup import in_gdb_thread
+from .startup import in_gdb_thread, DAPException
# The next available source reference ID. Must be greater than 0.
@@ -68,11 +68,11 @@ def decode_source(source):
if "path" in source:
return source["path"]
if "sourceReference" not in source:
- raise Exception("either 'path' or 'sourceReference' must appear in Source")
+ raise DAPException("either 'path' or 'sourceReference' must appear in Source")
ref = source["sourceReference"]
global _id_map
if ref not in _id_map:
- raise Exception("no sourceReference " + str(ref))
+ raise DAPException("no sourceReference " + str(ref))
return _id_map[ref]["path"]
diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py
index 1d3b947..64a4659 100644
--- a/gdb/python/lib/gdb/dap/startup.py
+++ b/gdb/python/lib/gdb/dap/startup.py
@@ -39,6 +39,24 @@ _gdb_thread = threading.current_thread()
_dap_thread = None
+# "Known" exceptions are wrapped in a DAP exception, so that, by
+# default, only rogue exceptions are logged -- this is then used by
+# the test suite.
+class DAPException(Exception):
+ pass
+
+
+# Wrapper for gdb.parse_and_eval that turns exceptions into
+# DAPException.
+def parse_and_eval(expression, global_context=False):
+ try:
+ return gdb.parse_and_eval(expression, global_context=global_context)
+ except Exception as e:
+ # Be sure to preserve the summary, as this can propagate to
+ # the client.
+ raise DAPException(str(e)) from e
+
+
def start_thread(name, target, args=()):
"""Start a new thread, invoking TARGET with *ARGS there.
This is a helper function that ensures that any GDB signals are
diff --git a/gdb/python/lib/gdb/dap/varref.py b/gdb/python/lib/gdb/dap/varref.py
index 8f0a070..c75afe3 100644
--- a/gdb/python/lib/gdb/dap/varref.py
+++ b/gdb/python/lib/gdb/dap/varref.py
@@ -14,7 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gdb
-from .startup import in_gdb_thread
+from .startup import in_gdb_thread, DAPException
from .server import client_bool_capability
from abc import ABC, abstractmethod
from collections import defaultdict
@@ -165,7 +165,7 @@ class BaseReference(ABC):
# map here.
if name in self.by_name:
return self.by_name[name]
- raise Exception("no variable named '" + name + "'")
+ raise DAPException("no variable named '" + name + "'")
class VariableReference(BaseReference):
@@ -271,5 +271,5 @@ def find_variable(ref):
# Variable references are offset by 1.
ref = ref - 1
if ref < 0 or ref > len(all_variables):
- raise Exception("invalid variablesReference")
+ raise DAPException("invalid variablesReference")
return all_variables[ref]