diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/builder/ParserOptions.py b/cross-project-tests/debuginfo-tests/dexter/dex/builder/ParserOptions.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/builder/ParserOptions.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/builder/ParserOptions.py @@ -48,6 +48,8 @@ type=str, choices=sorted(_find_build_scripts().keys()), help='test builder to use') + build_group.add_argument('--vs-solution', metavar="", + help='provide a path to an already existing visual studio solution.') parser.add_argument( '--cflags', type=str, default='', help='compiler flags') parser.add_argument('--ldflags', type=str, default='', help='linker flags') diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py @@ -16,7 +16,6 @@ from dex.command.CommandBase import StepExpectInfo 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 def watch_is_active(watch_info: StepExpectInfo, path, frame_idx, line_no): @@ -44,11 +43,10 @@ self._interface = None self.has_loaded = False - self._loading_error = NotYetLoadedDebuggerException() + self._loading_error = None try: self._interface = self._load_interface() self.has_loaded = True - self._loading_error = None except DebuggerException: self._loading_error = sys.exc_info() diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py @@ -21,7 +21,9 @@ """ self.debugger = debugger with self.debugger: - self._run_debugger_custom() + if not self.debugger.loading_error: + self._run_debugger_custom() + # We may need to pickle this debugger controller after running the # debugger. Debuggers are not picklable objects, so set to None. self.debugger = None diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py @@ -67,6 +67,23 @@ super(VisualStudio, self).__init__(*args) + def _create_solution(self): + self._solution.Create(self.context.working_directory.path, + 'DexterSolution') + try: + self._solution.AddFromFile(self._project_file) + except OSError: + raise LoadDebuggerException( + 'could not debug the specified executable', sys.exc_info()) + + def _load_solution(self): + try: + self._solution.Open(self.context.options.vs_solution) + except: + raise LoadDebuggerException( + 'could not load specified vs solution at {}'. + format(self.context.options.vs_solution), sys.exc_info()) + def _custom_init(self): try: self._debugger = self._interface.Debugger @@ -76,14 +93,10 @@ self.context.options.show_debugger) self._solution = self._interface.Solution - self._solution.Create(self.context.working_directory.path, - 'DexterSolution') - - try: - self._solution.AddFromFile(self._project_file) - except OSError: - raise LoadDebuggerException( - 'could not debug the specified executable', sys.exc_info()) + if self.context.options.vs_solution is None: + self._create_solution() + else: + self._load_solution() self._fn_step = self._debugger.StepInto self._fn_go = self._debugger.Go diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/tools/TestToolBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/tools/TestToolBase.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/tools/TestToolBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/tools/TestToolBase.py @@ -58,7 +58,12 @@ warn(self.context, '--cflags and --ldflags will be ignored when not' ' using --builder') - if options.binary: + if options.vs_solution: + options.vs_solution = os.path.abspath(options.vs_solution) + if not os.path.isfile(options.vs_solution): + raise Error('could not find VS solution file "{}"' + .format(options.vs_solution)) + elif options.binary: options.binary = os.path.abspath(options.binary) if not os.path.isfile(options.binary): raise Error('could not find binary file "{}"' diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/tools/run_debugger_internal_/Tool.py b/cross-project-tests/debuginfo-tests/dexter/dex/tools/run_debugger_internal_/Tool.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/tools/run_debugger_internal_/Tool.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/tools/run_debugger_internal_/Tool.py @@ -42,20 +42,26 @@ self.options = self.context.options Timer.display = self.options.time_report + def raise_debugger_error(self, action, debugger): + msg = 'could not {} {} ({})\n'.format( + action, debugger.name, debugger.loading_error) + if self.options.verbose: + msg = '{}\n {}'.format( + msg, ' '.join(debugger.loading_error_trace)) + raise Error(msg) + def go(self) -> ReturnCode: with Timer('loading debugger'): debugger = Debuggers(self.context).load(self.options.debugger) with Timer('running debugger'): if not debugger.is_available: - msg = 'could not load {} ({})\n'.format( - debugger.name, debugger.loading_error) - if self.options.verbose: - msg = '{}\n {}'.format( - msg, ' '.join(debugger.loading_error_trace)) - raise Error(msg) - - self.debugger_controller.run_debugger(debugger) + self.raise_debugger_error('load', debugger) + + self.debugger_controller.run_debugger(debugger) + + if debugger.loading_error: + self.raise_debugger_error('run', debugger) with open(self.controller_path, 'wb') as fp: pickle.dump(self.debugger_controller, fp) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py b/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py --- a/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/tools/test/Tool.py @@ -108,9 +108,13 @@ """Build an executable from the test source with the given --builder script and flags (--cflags, --ldflags) in the working directory. Or, if the --binary option has been given, copy the executable provided - into the working directory and rename it to match the --builder output. + into the working directory and rename it to match the --builder output + or skip if --vs-solution was passed on the command line. """ + if self.context.options.vs_solution: + return + options = self.context.options if options.binary: # Copy user's binary into the tmp working directory