2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-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/debugger/cmd/cmd_eval.h"
19 #include "hphp/runtime/base/array-init.h"
20 #include "hphp/runtime/debugger/debugger_client.h"
21 #include "hphp/runtime/vm/debugger-hook.h"
23 namespace HPHP
{ namespace Eval
{
24 ///////////////////////////////////////////////////////////////////////////////
26 TRACE_SET_MOD(debugger
);
28 void CmdEval::sendImpl(DebuggerThriftBuffer
&thrift
) {
29 DebuggerCommand::sendImpl(thrift
);
30 thrift
.write(m_output
);
31 thrift
.write(m_frame
);
32 thrift
.write(m_bypassAccessCheck
);
33 if (this->m_version
== 2) thrift
.write(m_failed
);
36 void CmdEval::recvImpl(DebuggerThriftBuffer
&thrift
) {
37 DebuggerCommand::recvImpl(thrift
);
38 thrift
.read(m_output
);
40 thrift
.read(m_bypassAccessCheck
);
41 if (this->m_version
== 2) thrift
.read(m_failed
);
42 // Old senders will set version to 0. A new sender sets it to 1
43 // and then expects an answer using version 2.
44 // Note that version 1 is the same format as version 0, so old
45 // receivers will not break when receiving a version 1 message.
46 // This code ensures that version 2 messages are received only
47 // by receivers that previously sent a version 1 message (thus
48 // indicating their ability to deal with version 2 messages).
49 if (this->m_version
== 1) this->m_version
= 2;
52 void CmdEval::onClient(DebuggerClient
&client
) {
53 m_body
= client
.getCode();
54 m_frame
= client
.getFrame();
55 m_bypassAccessCheck
= client
.getDebuggerClientBypassCheck();
56 auto res
= client
.xendWithNestedExecution
<CmdEval
>(this);
57 assertx(res
->is(DebuggerCommand::KindOfEval
));
58 auto eval
= std::static_pointer_cast
<CmdEval
>(res
);
59 eval
->handleReply(client
);
60 m_failed
= eval
->m_failed
;
63 void CmdEval::handleReply(DebuggerClient
&client
) {
64 if (this->failed() && client
.unknownCmdReceived()) {
66 "Notice: Attempted to interpret unknown debugger command as PHP!\n");
69 if (!m_output
.empty()) client
.print(m_output
);
72 // NB: unlike most other commands, the client expects that more interrupts
73 // can occur while we're doing the server-side work for an eval.
74 bool CmdEval::onServer(DebuggerProxy
&proxy
) {
76 RequestInjectionData
&rid
= ThreadInfo::s_threadInfo
->m_reqInjectionData
;
77 locSave
.swap(rid
.m_flowFilter
);
78 g_context
->debuggerSettings
.bypassCheck
= m_bypassAccessCheck
;
79 auto const result
= proxy
.ExecutePHP(
80 m_body
, m_output
, m_frame
,
81 DebuggerProxy::ExecutePHPFlagsAtInterrupt
|
82 (!proxy
.isLocal() ? DebuggerProxy::ExecutePHPFlagsLog
:
83 DebuggerProxy::ExecutePHPFlagsNone
)
85 m_failed
= result
.first
;
86 g_context
->debuggerSettings
.bypassCheck
= false;
87 locSave
.swap(rid
.m_flowFilter
);
88 return proxy
.sendToClient(this);
91 ///////////////////////////////////////////////////////////////////////////////