[debuginfo-tests] 53d6bfe - [Dexter] Add --source-dir-root flag
Tobias Bosch via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 18 09:29:33 PDT 2020
Author: Tobias Bosch
Date: 2020-06-18T09:29:08-07:00
New Revision: 53d6bfef32e371fb984a40b52208c6e34bd54e05
URL: https://github.com/llvm/llvm-project/commit/53d6bfef32e371fb984a40b52208c6e34bd54e05
DIFF: https://github.com/llvm/llvm-project/commit/53d6bfef32e371fb984a40b52208c6e34bd54e05.diff
LOG: [Dexter] Add --source-dir-root flag
Summary:
This allows to run dexter tests with separately compiled
binaries that are specified via --binary if the source file
location changed between compilation and dexter test run.
Reviewers: TWeaver, jmorse, probinson, #debug-info
Reviewed By: jmorse
Subscribers: #debug-info, cmtice, llvm-commits
Tags: #llvm, #debug-info
Differential Revision: https://reviews.llvm.org/D81319
Added:
debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp
Modified:
debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
debuginfo-tests/dexter/dex/debugger/Debuggers.py
debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
Removed:
################################################################################
diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
index 12f4f4ab7a02..37aaffe48898 100644
--- a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py
@@ -7,10 +7,13 @@
"""Base class for all debugger interface implementations."""
import abc
+import os
import sys
import traceback
+import unittest
-from dex.dextIR import DebuggerIR, ValueIR
+from types import SimpleNamespace
+from dex.dextIR import DebuggerIR, FrameIR, LocIR, StepIR, ValueIR
from dex.utils.Exceptions import DebuggerException
from dex.utils.Exceptions import NotYetLoadedDebuggerException
from dex.utils.ReturnCode import ReturnCode
@@ -19,6 +22,11 @@
class DebuggerBase(object, metaclass=abc.ABCMeta):
def __init__(self, context):
self.context = context
+ # Note: We can't already read values from options
+ # as DebuggerBase is created before we initialize options
+ # to read potential_debuggers.
+ self.options = self.context.options
+
self._interface = None
self.has_loaded = False
self._loading_error = NotYetLoadedDebuggerException()
@@ -116,16 +124,27 @@ def version(self):
def clear_breakpoints(self):
pass
- @abc.abstractmethod
def add_breakpoint(self, file_, line):
- pass
+ return self._add_breakpoint(self._external_to_debug_path(file_), line)
@abc.abstractmethod
- def add_conditional_breakpoint(self, file_, line, condition):
+ def _add_breakpoint(self, file_, line):
pass
+ def add_conditional_breakpoint(self, file_, line, condition):
+ return self._add_conditional_breakpoint(
+ self._external_to_debug_path(file_), line, condition)
+
@abc.abstractmethod
+ def _add_conditional_breakpoint(self, file_, line, condition):
+ pass
+
def delete_conditional_breakpoint(self, file_, line, condition):
+ return self._delete_conditional_breakpoint(
+ self._external_to_debug_path(file_), line, condition)
+
+ @abc.abstractmethod
+ def _delete_conditional_breakpoint(self, file_, line, condition):
pass
@abc.abstractmethod
@@ -140,8 +159,14 @@ def step(self):
def go(self) -> ReturnCode:
pass
- @abc.abstractmethod
def get_step_info(self, watches, step_index):
+ step_info = self._get_step_info(watches, step_index)
+ for frame in step_info.frames:
+ frame.loc.path = self._debug_to_external_path(frame.loc.path)
+ return step_info
+
+ @abc.abstractmethod
+ def _get_step_info(self, watches, step_index):
pass
@abc.abstractproperty
@@ -159,3 +184,86 @@ def frames_below_main(self):
@abc.abstractmethod
def evaluate_expression(self, expression, frame_idx=0) -> ValueIR:
pass
+
+ def _external_to_debug_path(self, path):
+ root_dir = self.options.source_root_dir
+ if not root_dir or not path:
+ return path
+ assert path.startswith(root_dir)
+ return path[len(root_dir):].lstrip(os.path.sep)
+
+ def _debug_to_external_path(self, path):
+ if not path or not self.options.source_root_dir:
+ return path
+ for file in self.options.source_files:
+ if path.endswith(self._external_to_debug_path(file)):
+ return file
+ return path
+
+class TestDebuggerBase(unittest.TestCase):
+
+ class MockDebugger(DebuggerBase):
+
+ def __init__(self, context, *args):
+ super().__init__(context, *args)
+ self.step_info = None
+ self.breakpoint_file = None
+
+ def _add_breakpoint(self, file, line):
+ self.breakpoint_file = file
+
+ def _get_step_info(self, watches, step_index):
+ return self.step_info
+
+ def __init__(self, *args):
+ super().__init__(*args)
+ TestDebuggerBase.MockDebugger.__abstractmethods__ = set()
+ self.options = SimpleNamespace(source_root_dir = '', source_files = [])
+ context = SimpleNamespace(options = self.options)
+ self.dbg = TestDebuggerBase.MockDebugger(context)
+
+ def _new_step(self, paths):
+ frames = [
+ FrameIR(
+ function=None,
+ is_inlined=False,
+ loc=LocIR(path=path, lineno=0, column=0)) for path in paths
+ ]
+ return StepIR(step_index=0, stop_reason=None, frames=frames)
+
+ def _step_paths(self, step):
+ return [frame.loc.path for frame in step.frames]
+
+ def test_add_breakpoint_no_source_root_dir(self):
+ self.options.source_root_dir = ''
+ self.dbg.add_breakpoint('/root/some_file', 12)
+ self.assertEqual('/root/some_file', self.dbg.breakpoint_file)
+
+ def test_add_breakpoint_with_source_root_dir(self):
+ self.options.source_root_dir = '/my_root'
+ self.dbg.add_breakpoint('/my_root/some_file', 12)
+ self.assertEqual('some_file', self.dbg.breakpoint_file)
+
+ def test_add_breakpoint_with_source_root_dir_slash_suffix(self):
+ self.options.source_root_dir = '/my_root/'
+ self.dbg.add_breakpoint('/my_root/some_file', 12)
+ self.assertEqual('some_file', self.dbg.breakpoint_file)
+
+ def test_get_step_info_no_source_root_dir(self):
+ self.dbg.step_info = self._new_step(['/root/some_file'])
+ self.assertEqual(['/root/some_file'],
+ self._step_paths(self.dbg.get_step_info([], 0)))
+
+ def test_get_step_info_no_frames(self):
+ self.options.source_root_dir = '/my_root'
+ self.dbg.step_info = self._new_step([])
+ self.assertEqual([],
+ self._step_paths(self.dbg.get_step_info([], 0)))
+
+ def test_get_step_info(self):
+ self.options.source_root_dir = '/my_root'
+ self.options.source_files = ['/my_root/some_file']
+ self.dbg.step_info = self._new_step(
+ [None, '/other/file', '/dbg/some_file'])
+ self.assertEqual([None, '/other/file', '/my_root/some_file'],
+ self._step_paths(self.dbg.get_step_info([], 0)))
diff --git a/debuginfo-tests/dexter/dex/debugger/Debuggers.py b/debuginfo-tests/dexter/dex/debugger/Debuggers.py
index f69169f27980..06c115d85bf1 100644
--- a/debuginfo-tests/dexter/dex/debugger/Debuggers.py
+++ b/debuginfo-tests/dexter/dex/debugger/Debuggers.py
@@ -100,6 +100,11 @@ def add_debugger_tool_arguments(parser, context, defaults):
default=None,
display_default=defaults.arch,
help='target architecture')
+ defaults.source_root_dir = ''
+ parser.add_argument(
+ '--source-root-dir',
+ default=None,
+ help='prefix path to ignore when matching debug info and source files.')
def handle_debugger_tool_base_options(context, defaults): # noqa
diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
index d812fd974f79..69e4b3b1267a 100644
--- a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
+++ b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py
@@ -76,18 +76,18 @@ def clear_breakpoints(self):
x.RemoveFlags(breakpoint.BreakpointFlags.DEBUG_BREAKPOINT_ENABLED)
self.client.Control.RemoveBreakpoint(x)
- def add_breakpoint(self, file_, line):
+ def _add_breakpoint(self, file_, line):
# Breakpoint setting/deleting is not supported by dbgeng at this moment
# but is something that should be considered in the future.
# TODO: this method is called in the DefaultController but has no effect.
pass
- def add_conditional_breakpoint(self, file_, line, condition):
+ def _add_conditional_breakpoint(self, file_, line, condition):
# breakpoint setting/deleting is not supported by dbgeng at this moment
# but is something that should be considered in the future.
raise NotImplementedError('add_conditional_breakpoint is not yet implemented by dbgeng')
- def delete_conditional_breakpoint(self, file_, line, condition):
+ def _delete_conditional_breakpoint(self, file_, line, condition):
# breakpoint setting/deleting is not supported by dbgeng at this moment
# but is something that should be considered in the future.
raise NotImplementedError('delete_conditional_breakpoint is not yet implemented by dbgeng')
@@ -106,7 +106,7 @@ def go(self):
# We never go -- we always single step.
pass
- def get_step_info(self, watches, step_index):
+ def _get_step_info(self, watches, step_index):
frames = self.step_info
state_frames = []
diff --git a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
index c7bb74681d9f..5fc8fd3e95f8 100644
--- a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
+++ b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py
@@ -103,12 +103,12 @@ def version(self):
def clear_breakpoints(self):
self._target.DeleteAllBreakpoints()
- def add_breakpoint(self, file_, line):
+ def _add_breakpoint(self, file_, line):
if not self._target.BreakpointCreateByLocation(file_, line):
raise DebuggerException(
'could not add breakpoint [{}:{}]'.format(file_, line))
- def add_conditional_breakpoint(self, file_, line, condition):
+ def _add_conditional_breakpoint(self, file_, line, condition):
bp = self._target.BreakpointCreateByLocation(file_, line)
if bp:
bp.SetCondition(condition)
@@ -116,7 +116,7 @@ def add_conditional_breakpoint(self, file_, line, condition):
raise DebuggerException(
'could not add breakpoint [{}:{}]'.format(file_, line))
- def delete_conditional_breakpoint(self, file_, line, condition):
+ def _delete_conditional_breakpoint(self, file_, line, condition):
bp_count = self._target.GetNumBreakpoints()
bps = [self._target.GetBreakpointAtIndex(ix) for ix in range(0, bp_count)]
@@ -163,7 +163,7 @@ def go(self) -> ReturnCode:
self._process.Continue()
return ReturnCode.OK
- def get_step_info(self, watches, step_index):
+ def _get_step_info(self, watches, step_index):
frames = []
state_frames = []
diff --git a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
index 40a902bd2059..6585a4938c12 100644
--- a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
+++ b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py
@@ -111,14 +111,14 @@ def clear_breakpoints(self):
for bp in self._debugger.Breakpoints:
bp.Delete()
- def add_breakpoint(self, file_, line):
+ def _add_breakpoint(self, file_, line):
self._debugger.Breakpoints.Add('', file_, line)
- def add_conditional_breakpoint(self, file_, line, condition):
+ def _add_conditional_breakpoint(self, file_, line, condition):
column = 1
self._debugger.Breakpoints.Add('', file_, line, column, condition)
- def delete_conditional_breakpoint(self, file_, line, condition):
+ def _delete_conditional_breakpoint(self, file_, line, condition):
for bp in self._debugger.Breakpoints:
for bound_bp in bp.Children:
if (bound_bp.File == file_ and bound_bp.FileLine == line and
@@ -146,7 +146,7 @@ def set_current_stack_frame(self, idx: int = 0):
raise Error('attempted to access stack frame {} out of {}'
.format(idx, len(stack_frames)))
- def get_step_info(self, watches, step_index):
+ def _get_step_info(self, watches, step_index):
thread = self._debugger.CurrentThread
stackframes = thread.StackFrames
diff --git a/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp b/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp
new file mode 100644
index 000000000000..cbea80a18240
--- /dev/null
+++ b/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp
@@ -0,0 +1,15 @@
+// REQUIRES: lldb
+// UNSUPPORTED: system-windows
+//
+// RUN: %dexter --fail-lt 1.0 -w \
+// RUN: --builder 'clang' --debugger 'lldb' \
+// RUN: --cflags "-O0 -glldb -fdebug-prefix-map=%S=/changed" \
+// RUN: --source-root-dir=%S -- %s
+
+#include <stdio.h>
+int main() {
+ int x = 42;
+ printf("hello world: %d\n", x); // DexLabel('check')
+}
+
+// DexExpectWatchValue('x', 42, on_line='check')
More information about the llvm-commits
mailing list