2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2017-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/base/file.h"
18 #include "hphp/runtime/base/unit-cache.h"
19 #include "hphp/runtime/ext/vsdebug/debugger.h"
20 #include "hphp/runtime/ext/vsdebug/command.h"
25 RunToLocationCommand::RunToLocationCommand(
27 folly::dynamic message
28 ) : VSCommand(debugger
, message
) {
31 RunToLocationCommand::~RunToLocationCommand() {
34 bool RunToLocationCommand::executeImpl(DebuggerSession
* session
,
35 folly::dynamic
* /*responseMsg*/
37 folly::dynamic
& message
= getMessage();
38 const folly::dynamic
& args
= tryGetObject(message
, "arguments", s_emptyArgs
);
39 const folly::dynamic
& source
= tryGetObject(args
, "source", s_emptyArgs
);
40 const std::string
& filePath
= tryGetString(source
, "path", "");
42 if (filePath
.empty()) {
43 throw DebuggerCommandException(
44 "Run to location source path not specified."
48 const ClientPreferences
& prefs
= m_debugger
->getClientPreferences();
49 const std::string
& path
= File::TranslatePath(String(filePath
)).toCppString();
50 BreakpointManager
* bpMgr
= session
->getBreakpointManager();
52 int line
= tryGetInt(args
, "line", -1);
53 if (!prefs
.linesStartAt1
) {
54 // If client lines start at 0, make them 1 based.
59 throw DebuggerCommandException(
60 "Invalid continue to line specified."
64 // See if there's already a breakpoint at this file + line.
65 const auto bpIds
= bpMgr
->getBreakpointIdsByFile(path
);
66 for (auto it
= bpIds
.begin(); it
!= bpIds
.end(); it
++) {
67 Breakpoint
* bp
= bpMgr
->getBreakpointById(*it
);
68 if (bp
->m_line
== line
) {
69 // There's already a breakpoint installed at the run to location.
70 // Just resume the request thread and let it hit.
75 // Find a compilation unit to place a temp bp in.
76 HPHP::String
unitPath(path
.c_str());
77 const auto compilationUnit
= lookupUnit(unitPath
.get(), "", nullptr);
78 if (compilationUnit
== nullptr) {
79 throw DebuggerCommandException(
80 "Could not find a loaded compilation unit to run to location in!"
84 std::pair
<int, int> runLocation
=
85 m_debugger
->calibrateBreakpointLineInUnit(compilationUnit
, line
);
87 if (runLocation
.first
< 0) {
88 throw DebuggerCommandException(
89 "Could not find a suitable location in the compilation unit to run to!"
93 if (!phpAddBreakPointLine(compilationUnit
, runLocation
.first
)) {
94 throw DebuggerCommandException(
95 "Failed to install temporary breakpoint at location."
99 RequestInfo
* ri
= m_debugger
->getRequestInfo();
100 ri
->m_runToLocationInfo
.path
= path
;
101 ri
->m_runToLocationInfo
.line
= line
;
103 // Tell the user where we're running to. Resolving the file path and
104 // calibrating the source line could have modified things a bit.
105 std::string userMsg
= "Resuming request ";
106 userMsg
+= std::to_string(targetThreadId(session
));
107 userMsg
+= " and running to resolved location ";
110 userMsg
+= std::to_string(runLocation
.second
);
111 m_debugger
->sendUserMessage(userMsg
.c_str(), DebugTransport::OutputLevelInfo
);
113 // Resume only this request thread.