diff --git a/debuginfo-tests/dexter/dex/command/ParseCommand.py b/debuginfo-tests/dexter/dex/command/ParseCommand.py --- a/debuginfo-tests/dexter/dex/command/ParseCommand.py +++ b/debuginfo-tests/dexter/dex/command/ParseCommand.py @@ -209,7 +209,7 @@ labels[label.eval()] = label.get_line() -def _find_all_commands_in_file(path, file_lines, valid_commands): +def _find_all_commands_in_file(path, file_lines, valid_commands, source_root_dir): labels = {} # dict of {name: line}. cmd_path = path declared_files = set() @@ -278,7 +278,8 @@ elif type(command) is DexDeclareFile: cmd_path = command.declared_file if not os.path.isabs(cmd_path): - source_dir = os.path.dirname(path) + source_dir = (source_root_dir if source_root_dir else + os.path.dirname(path)) cmd_path = os.path.join(source_dir, cmd_path) # TODO: keep stored paths as PurePaths for 'longer'. cmd_path = str(PurePath(cmd_path)) @@ -295,25 +296,25 @@ raise format_parse_err(msg, path, file_lines, err_point) return dict(commands), declared_files -def _find_all_commands(test_files): +def _find_all_commands(test_files, source_root_dir): commands = defaultdict(dict) valid_commands = _get_valid_commands() new_source_files = set() for test_file in test_files: with open(test_file) as fp: lines = fp.readlines() - file_commands, declared_files = _find_all_commands_in_file(test_file, - lines, valid_commands) + file_commands, declared_files = _find_all_commands_in_file( + test_file, lines, valid_commands, source_root_dir) for command_name in file_commands: commands[command_name].update(file_commands[command_name]) new_source_files |= declared_files return dict(commands), new_source_files -def get_command_infos(test_files): +def get_command_infos(test_files, source_root_dir): with Timer('parsing commands'): try: - commands, new_source_files = _find_all_commands(test_files) + commands, new_source_files = _find_all_commands(test_files, source_root_dir) command_infos = OrderedDict() for command_type in commands: for command in commands[command_type].values(): @@ -358,7 +359,7 @@ Returns: { cmd_name: { (path, line): command_obj } } """ - cmds, declared_files = _find_all_commands_in_file(__file__, lines, self.valid_commands) + cmds, declared_files = _find_all_commands_in_file(__file__, lines, self.valid_commands, None) return cmds diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py --- a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py +++ b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py @@ -206,6 +206,8 @@ pass def _external_to_debug_path(self, path): + if not self.options.debugger_use_relative_paths: + return path root_dir = self.options.source_root_dir if not root_dir or not path: return path @@ -213,6 +215,8 @@ return path[len(root_dir):].lstrip(os.path.sep) def _debug_to_external_path(self, path): + if not self.options.debugger_use_relative_paths: + return path if not path or not self.options.source_root_dir: return path for file in self.options.source_files: @@ -255,32 +259,38 @@ return [frame.loc.path for frame in step.frames] def test_add_breakpoint_no_source_root_dir(self): + self.options.debugger_use_relative_paths = True 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.debugger_use_relative_paths = True 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.debugger_use_relative_paths = True 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.options.debugger_use_relative_paths = True 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.debugger_use_relative_paths = True 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.debugger_use_relative_paths = True self.options.source_root_dir = '/my_root' self.options.source_files = ['/my_root/some_file'] self.dbg.step_info = self._new_step( diff --git a/debuginfo-tests/dexter/dex/debugger/Debuggers.py b/debuginfo-tests/dexter/dex/debugger/Debuggers.py --- a/debuginfo-tests/dexter/dex/debugger/Debuggers.py +++ b/debuginfo-tests/dexter/dex/debugger/Debuggers.py @@ -105,9 +105,15 @@ defaults.source_root_dir = '' parser.add_argument( '--source-root-dir', + type=str, + metavar='', default=None, - help='prefix path to ignore when matching debug info and source files.') - + help='source root directory') + parser.add_argument( + '--debugger-use-relative-paths', + action='store_true', + default=False, + help='pass the debugger paths relative to --source-root-dir') def handle_debugger_tool_base_options(context, defaults): # noqa options = context.options @@ -141,6 +147,15 @@ if options.debugger == 'lldb': _warn_meaningless_option(context, '--show-debugger') + if options.source_root_dir != None: + if not os.path.isabs(options.source_root_dir): + raise ToolArgumentError(f'--source-root-dir: expected absolute path, got "{options.source_root_dir}"') + if not os.path.isdir(options.source_root_dir): + raise ToolArgumentError(f'--source-root-dir: could not find directory "{options.source_root_dir}"') + + if options.debugger_use_relative_paths: + if not options.source_root_dir: + raise ToolArgumentError(f'--debugger-relative-paths requires --source-root-dir') def run_debugger_subprocess(debugger_controller, working_dir_path): with NamedTemporaryFile( diff --git a/debuginfo-tests/dexter/dex/tools/clang_opt_bisect/Tool.py b/debuginfo-tests/dexter/dex/tools/clang_opt_bisect/Tool.py --- a/debuginfo-tests/dexter/dex/tools/clang_opt_bisect/Tool.py +++ b/debuginfo-tests/dexter/dex/tools/clang_opt_bisect/Tool.py @@ -92,9 +92,11 @@ executable_path=self.context.options.executable, source_paths=self.context.options.source_files, dexter_version=self.context.version) + step_collection.commands, new_source_files = get_command_infos( - self.context.options.test_files) + self.context.options.source_files, self.context.options.source_root_dir) self.context.options.source_files.extend(list(new_source_files)) + debugger_controller = DefaultController(self.context, step_collection) return debugger_controller diff --git a/debuginfo-tests/dexter/dex/tools/test/Tool.py b/debuginfo-tests/dexter/dex/tools/test/Tool.py --- a/debuginfo-tests/dexter/dex/tools/test/Tool.py +++ b/debuginfo-tests/dexter/dex/tools/test/Tool.py @@ -139,7 +139,7 @@ dexter_version=self.context.version) step_collection.commands, new_source_files = get_command_infos( - self.context.options.test_files) + self.context.options.test_files, self.context.options.source_root_dir) self.context.options.source_files.extend(list(new_source_files)) diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_file/precompiled_binary_different_dir/dex_commands/source_root_dir.dex b/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_file/precompiled_binary_different_dir/dex_commands/source_root_dir.dex new file mode 100644 --- /dev/null +++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/dex_declare_file/precompiled_binary_different_dir/dex_commands/source_root_dir.dex @@ -0,0 +1,23 @@ +## Purpose: +## Check that \DexDeclareFile's file declaration can be made relative to the +## --source-root-dir path. + +# REQUIRES: lldb +# UNSUPPORTED: system-darwin + +# RUN: %clang %S/../source/test.cpp -O0 -g -o %t +# RUN: %dexter_regression_test --binary %t \ +# RUN: --source-root-dir="%S/../source" -- %s | FileCheck %s +# RUN: rm %t + +# CHECK: source_root_dir.dex: (1.0000) + +## ../source/test.cpp +## 1. int main() { +## 2. int result = 0; +## 3. return result; +## 4. } + +## test.cpp is found in ../source, which we set as the source-root-dir. +DexDeclareFile('test.cpp') +DexExpectWatchValue('result', 0, on_line=3) 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 --- a/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp +++ b/debuginfo-tests/dexter/feature_tests/subtools/test/source-root-dir.cpp @@ -4,7 +4,7 @@ // 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 +// RUN: --source-root-dir=%S --debugger-use-relative-paths -- %s #include int main() {