mirror of
https://gitee.com/openharmony/arkcompiler_toolchain
synced 2024-11-23 15:40:03 +00:00
Mixed debug support stepOut
Issue:#I83IAI Signed-off-by: yang-19970325 <yangyang585@huawei.com> Change-Id: I390b6dd75b54b7b9274ddba791296284a7aa7623
This commit is contained in:
parent
3b2297df11
commit
75e1a26c9c
@ -51,8 +51,10 @@ DebuggerImpl::DebuggerImpl(const EcmaVM *vm, ProtocolChannel *channel, RuntimeIm
|
||||
DebuggerExecutor::Initialize(vm_);
|
||||
updaterFunc_ = std::bind(&DebuggerImpl::UpdateScopeObject, this, _1, _2, _3);
|
||||
stepperFunc_ = std::bind(&DebuggerImpl::ClearSingleStepper, this);
|
||||
returnNative_ = std::bind(&DebuggerImpl::NotifyReturnNative, this);
|
||||
vm_->GetJsDebuggerManager()->SetLocalScopeUpdater(&updaterFunc_);
|
||||
vm_->GetJsDebuggerManager()->SetStepperFunc(&stepperFunc_);
|
||||
vm_->GetJsDebuggerManager()->SetJSReturnNativeFunc(&returnNative_);
|
||||
}
|
||||
|
||||
DebuggerImpl::~DebuggerImpl()
|
||||
@ -109,6 +111,15 @@ bool DebuggerImpl::NotifyScriptParsed(ScriptId scriptId, const std::string &file
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DebuggerImpl::NotifyNativeOut()
|
||||
{
|
||||
if (nativeOutPause_) {
|
||||
nativeOutPause_ = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DebuggerImpl::NotifySingleStep(const JSPtLocation &location)
|
||||
{
|
||||
if (UNLIKELY(pauseOnNextByteCode_)) {
|
||||
@ -253,9 +264,10 @@ void DebuggerImpl::NotifyPaused(std::optional<JSPtLocation> location, PauseReaso
|
||||
paused.SetData(std::move(tmpException));
|
||||
}
|
||||
frontend_.Paused(vm_, paused);
|
||||
if (reason != BREAK_ON_START) {
|
||||
if (reason != BREAK_ON_START && reason != NATIVE_OUT) {
|
||||
singleStepper_.reset();
|
||||
}
|
||||
nativeOutPause_ = false;
|
||||
debuggerState_ = DebuggerState::PAUSED;
|
||||
frontend_.WaitForDebugger(vm_);
|
||||
DebuggerApi::SetException(vm_, exception);
|
||||
@ -263,16 +275,14 @@ void DebuggerImpl::NotifyPaused(std::optional<JSPtLocation> location, PauseReaso
|
||||
|
||||
void DebuggerImpl::NotifyNativeCalling(const void *nativeAddress)
|
||||
{
|
||||
if (mixStackEnabled_) {
|
||||
tooling::MixedStack mixedStack;
|
||||
nativePointer_ = DebuggerApi::GetNativePointer(vm_);
|
||||
mixedStack.SetNativePointers(nativePointer_);
|
||||
std::vector<std::unique_ptr<CallFrame>> callFrames;
|
||||
if (GenerateCallFrames(&callFrames)) {
|
||||
mixedStack.SetCallFrames(std::move(callFrames));
|
||||
}
|
||||
frontend_.MixedStack(vm_, mixedStack);
|
||||
tooling::MixedStack mixedStack;
|
||||
nativePointer_ = DebuggerApi::GetNativePointer(vm_);
|
||||
mixedStack.SetNativePointers(nativePointer_);
|
||||
std::vector<std::unique_ptr<CallFrame>> callFrames;
|
||||
if (GenerateCallFrames(&callFrames)) {
|
||||
mixedStack.SetCallFrames(std::move(callFrames));
|
||||
}
|
||||
frontend_.MixedStack(vm_, mixedStack);
|
||||
|
||||
// native calling only after step into should be reported
|
||||
if (singleStepper_ != nullptr &&
|
||||
@ -283,6 +293,43 @@ void DebuggerImpl::NotifyNativeCalling(const void *nativeAddress)
|
||||
frontend_.NativeCalling(vm_, nativeCalling);
|
||||
frontend_.WaitForDebugger(vm_);
|
||||
}
|
||||
|
||||
bool isNativeCalling = false;
|
||||
uint64_t nativeEntry = reinterpret_cast<uint64_t>(nativeAddress);
|
||||
for (const auto &nativeRange : nativeRanges_) {
|
||||
if (nativeEntry >= nativeRange.GetStart() && nativeEntry <= nativeRange.GetEnd()) {
|
||||
isNativeCalling = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isNativeCalling) {
|
||||
return;
|
||||
}
|
||||
|
||||
checkNeedPause_ = true;
|
||||
}
|
||||
|
||||
void DebuggerImpl::NotifyNativeReturnJS()
|
||||
{
|
||||
if (checkNeedPause_) {
|
||||
nativeOutPause_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerImpl::NotifyReturnNative()
|
||||
{
|
||||
if (vm_->GetJsDebuggerManager()->IsMixedDebugEnabled()) {
|
||||
tooling::MixedStack mixedStack;
|
||||
nativePointer_ = DebuggerApi::GetNativePointer(vm_);
|
||||
mixedStack.SetNativePointers(nativePointer_);
|
||||
std::vector<std::unique_ptr<CallFrame>> callFrames;
|
||||
if (GenerateCallFrames(&callFrames)) {
|
||||
mixedStack.SetCallFrames(std::move(callFrames));
|
||||
}
|
||||
if (!nativePointer_.empty()) {
|
||||
frontend_.MixedStack(vm_, mixedStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only use for test case
|
||||
@ -321,7 +368,9 @@ void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request)
|
||||
{ "setBlackboxPatterns", &DebuggerImpl::DispatcherImpl::SetBlackboxPatterns },
|
||||
{ "replyNativeCalling", &DebuggerImpl::DispatcherImpl::ReplyNativeCalling },
|
||||
{ "getPossibleAndSetBreakpointByUrl", &DebuggerImpl::DispatcherImpl::GetPossibleAndSetBreakpointByUrl },
|
||||
{ "dropFrame", &DebuggerImpl::DispatcherImpl::DropFrame }
|
||||
{ "dropFrame", &DebuggerImpl::DispatcherImpl::DropFrame },
|
||||
{ "setNativeRange", &DebuggerImpl::DispatcherImpl::SetNativeRange },
|
||||
{ "resetSingleStepper", &DebuggerImpl::DispatcherImpl::ResetSingleStepper },
|
||||
};
|
||||
|
||||
const std::string &method = request.GetMethod();
|
||||
@ -511,6 +560,28 @@ void DebuggerImpl::DispatcherImpl::SetSkipAllPauses(const DispatchRequest &reque
|
||||
SendResponse(request, response);
|
||||
}
|
||||
|
||||
void DebuggerImpl::DispatcherImpl::SetNativeRange(const DispatchRequest &request)
|
||||
{
|
||||
std::unique_ptr<SetNativeRangeParams> params = SetNativeRangeParams::Create(request.GetParams());
|
||||
if (params == nullptr) {
|
||||
SendResponse(request, DispatchResponse::Fail("wrong params"));
|
||||
return;
|
||||
}
|
||||
DispatchResponse response = debugger_->SetNativeRange(*params);
|
||||
SendResponse(request, response);
|
||||
}
|
||||
|
||||
void DebuggerImpl::DispatcherImpl::ResetSingleStepper(const DispatchRequest &request)
|
||||
{
|
||||
std::unique_ptr<ResetSingleStepperParams> params = ResetSingleStepperParams::Create(request.GetParams());
|
||||
if (params == nullptr) {
|
||||
SendResponse(request, DispatchResponse::Fail("wrong params"));
|
||||
return;
|
||||
}
|
||||
DispatchResponse response = debugger_->ResetSingleStepper(*params);
|
||||
SendResponse(request, response);
|
||||
}
|
||||
|
||||
void DebuggerImpl::DispatcherImpl::StepInto(const DispatchRequest &request)
|
||||
{
|
||||
std::unique_ptr<StepIntoParams> params = StepIntoParams::Create(request.GetParams());
|
||||
@ -986,6 +1057,21 @@ bool DebuggerImpl::ProcessSingleBreakpoint(const BreakpointInfo &breakpoint,
|
||||
return true;
|
||||
}
|
||||
|
||||
DispatchResponse DebuggerImpl::SetNativeRange(const SetNativeRangeParams ¶ms)
|
||||
{
|
||||
nativeRanges_ = params.GetNativeRange();
|
||||
return DispatchResponse::Ok();
|
||||
}
|
||||
|
||||
DispatchResponse DebuggerImpl::ResetSingleStepper(const ResetSingleStepperParams ¶ms)
|
||||
{
|
||||
// if JS to C++ and C++ has breakpoint; it need to clear singleStepper_
|
||||
if (params.GetResetSingleStepper()) {
|
||||
singleStepper_.reset();
|
||||
}
|
||||
return DispatchResponse::Ok();
|
||||
}
|
||||
|
||||
DispatchResponse DebuggerImpl::SetPauseOnExceptions(const SetPauseOnExceptionsParams ¶ms)
|
||||
{
|
||||
pauseOnException_ = params.GetState();
|
||||
|
@ -42,8 +42,11 @@ public:
|
||||
std::string_view entryPoint = "func_main_0");
|
||||
bool NotifySingleStep(const JSPtLocation &location);
|
||||
void NotifyPaused(std::optional<JSPtLocation> location, PauseReason reason);
|
||||
bool NotifyNativeOut();
|
||||
void NotifyHandleProtocolCommand();
|
||||
void NotifyNativeCalling(const void *nativeAddress);
|
||||
void NotifyNativeReturnJS();
|
||||
void NotifyReturnNative();
|
||||
void SetDebuggerState(DebuggerState debuggerState);
|
||||
|
||||
DispatchResponse ContinueToLocation(const ContinueToLocationParams ¶ms);
|
||||
@ -65,6 +68,8 @@ public:
|
||||
std::vector<std::unique_ptr<BreakpointReturnInfo>> &outLocations);
|
||||
DispatchResponse SetPauseOnExceptions(const SetPauseOnExceptionsParams ¶ms);
|
||||
DispatchResponse SetSkipAllPauses(const SetSkipAllPausesParams ¶ms);
|
||||
DispatchResponse SetNativeRange(const SetNativeRangeParams ¶ms);
|
||||
DispatchResponse ResetSingleStepper(const ResetSingleStepperParams ¶ms);
|
||||
DispatchResponse StepInto(const StepIntoParams ¶ms);
|
||||
DispatchResponse StepOut();
|
||||
DispatchResponse StepOver(const StepOverParams ¶ms);
|
||||
@ -150,6 +155,8 @@ public:
|
||||
void SetBreakpointsActive(const DispatchRequest &request);
|
||||
void SetPauseOnExceptions(const DispatchRequest &request);
|
||||
void SetSkipAllPauses(const DispatchRequest &request);
|
||||
void SetNativeRange(const DispatchRequest &request);
|
||||
void ResetSingleStepper(const DispatchRequest &request);
|
||||
void StepInto(const DispatchRequest &request);
|
||||
void StepOut(const DispatchRequest &request);
|
||||
void StepOver(const DispatchRequest &request);
|
||||
@ -248,12 +255,18 @@ private:
|
||||
bool mixStackEnabled_ {false};
|
||||
std::unique_ptr<SingleStepper> singleStepper_ {nullptr};
|
||||
Location location_ {};
|
||||
|
||||
std::unique_ptr<SingleStepper> nativeOut_ {nullptr};
|
||||
std::vector<void *> nativePointer_;
|
||||
|
||||
bool nativeOutPause_ {false};
|
||||
bool checkNeedPause_ {false};
|
||||
std::vector<NativeRange> nativeRanges_ {};
|
||||
std::unordered_map<JSTaggedType *, RemoteObjectId> scopeObjects_ {};
|
||||
std::vector<std::shared_ptr<FrameHandler>> callFrameHandlers_;
|
||||
JsDebuggerManager::ObjectUpdaterFunc updaterFunc_ {nullptr};
|
||||
JsDebuggerManager::SingleStepperFunc stepperFunc_ {nullptr};
|
||||
JsDebuggerManager::ReturnNativeFunc returnNative_ {nullptr};
|
||||
|
||||
friend class JSPtHooks;
|
||||
friend class test::TestHooks;
|
||||
|
@ -66,6 +66,19 @@ bool JSPtHooks::SingleStep(const JSPtLocation &location)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSPtHooks::NativeOut()
|
||||
{
|
||||
LOG_DEBUGGER(VERBOSE) << "JSPtHooks: NativeOut";
|
||||
|
||||
[[maybe_unused]] LocalScope scope(debugger_->vm_);
|
||||
if (debugger_->NotifyNativeOut()) {
|
||||
debugger_->NotifyPaused({}, NATIVE_OUT);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void JSPtHooks::LoadModule(std::string_view pandaFileName, std::string_view entryPoint)
|
||||
{
|
||||
LOG_DEBUGGER(VERBOSE) << "JSPtHooks: LoadModule: " << pandaFileName;
|
||||
@ -86,4 +99,13 @@ void JSPtHooks::NativeCalling(const void *nativeAddress)
|
||||
|
||||
debugger_->NotifyNativeCalling(nativeAddress);
|
||||
}
|
||||
|
||||
void JSPtHooks::NativeReturnJS()
|
||||
{
|
||||
LOG_DEBUGGER(INFO) << "JSPtHooks: NativeReturnJS";
|
||||
|
||||
[[maybe_unused]] LocalScope scope(debugger_->vm_);
|
||||
|
||||
debugger_->NotifyNativeReturnJS();
|
||||
}
|
||||
} // namespace panda::ecmascript::tooling
|
||||
|
@ -35,7 +35,9 @@ public:
|
||||
void LoadModule(std::string_view pandaFileName, std::string_view entryPoint) override;
|
||||
void Exception(const JSPtLocation &location) override;
|
||||
bool SingleStep(const JSPtLocation &location) override;
|
||||
bool NativeOut() override;
|
||||
void NativeCalling(const void *nativeAddress) override;
|
||||
void NativeReturnJS() override;
|
||||
void VmStart() override {}
|
||||
void VmDeath() override {}
|
||||
|
||||
|
@ -156,6 +156,9 @@ public:
|
||||
case STEP: {
|
||||
return "Step";
|
||||
}
|
||||
case NATIVE_OUT: {
|
||||
return "Native out";
|
||||
}
|
||||
default: {
|
||||
LOG_DEBUGGER(ERROR) << "Unknown paused reason: " << reason;
|
||||
}
|
||||
|
@ -562,6 +562,41 @@ std::unique_ptr<DropFrameParams> DropFrameParams::Create(const PtJson ¶ms)
|
||||
return paramsObject;
|
||||
}
|
||||
|
||||
std::unique_ptr<SetNativeRangeParams> SetNativeRangeParams::Create(const PtJson ¶ms)
|
||||
{
|
||||
auto paramsObject = std::make_unique<SetNativeRangeParams>();
|
||||
std::string error;
|
||||
Result ret;
|
||||
|
||||
std::unique_ptr<PtJson> nativeRange;
|
||||
ret = params.GetArray("nativeRange", &nativeRange);
|
||||
if (ret == Result::SUCCESS) {
|
||||
int32_t len = nativeRange->GetSize();
|
||||
std::vector<NativeRange> vectorNativeRange;
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
std::unique_ptr<NativeRange> obj = NativeRange::Create(*nativeRange->Get(i));
|
||||
if (obj == nullptr) {
|
||||
error += "'nativeRange' is invalid;";
|
||||
break;
|
||||
} else {
|
||||
vectorNativeRange.emplace_back(std::move(*obj));
|
||||
}
|
||||
}
|
||||
if (vectorNativeRange.size()) {
|
||||
paramsObject->nativeRange_ = std::move(vectorNativeRange);
|
||||
}
|
||||
} else if (ret == Result::TYPE_ERROR) {
|
||||
error += "Unknown 'nativeRange';";
|
||||
}
|
||||
|
||||
if (!error.empty()) {
|
||||
LOG_DEBUGGER(ERROR) << "SetNativeRangeParams::Create " << error;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return paramsObject;
|
||||
}
|
||||
|
||||
std::unique_ptr<SetMixedDebugParams> SetMixedDebugParams::Create(const PtJson ¶ms)
|
||||
{
|
||||
auto paramsObject = std::make_unique<SetMixedDebugParams>();
|
||||
@ -592,6 +627,28 @@ std::unique_ptr<SetMixedDebugParams> SetMixedDebugParams::Create(const PtJson &p
|
||||
return paramsObject;
|
||||
}
|
||||
|
||||
std::unique_ptr<ResetSingleStepperParams> ResetSingleStepperParams::Create(const PtJson ¶ms)
|
||||
{
|
||||
auto paramsObject = std::make_unique<ResetSingleStepperParams>();
|
||||
std::string error;
|
||||
Result ret;
|
||||
|
||||
bool resetSingleStepper = false;
|
||||
ret = params.GetBool("resetSingleStepper", &resetSingleStepper);
|
||||
if (ret == Result::SUCCESS) {
|
||||
paramsObject->resetSingleStepper_ = resetSingleStepper;
|
||||
} else if (ret == Result::TYPE_ERROR) {
|
||||
error += "Wrong type of 'resetSingleStepper';";
|
||||
}
|
||||
|
||||
if (!error.empty()) {
|
||||
LOG_DEBUGGER(ERROR) << "ResetSingleStepperParams::Create " << error;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return paramsObject;
|
||||
}
|
||||
|
||||
std::unique_ptr<ReplyNativeCallingParams> ReplyNativeCallingParams::Create(const PtJson ¶ms)
|
||||
{
|
||||
auto paramsObject = std::make_unique<ReplyNativeCallingParams>();
|
||||
|
@ -521,6 +521,38 @@ private:
|
||||
std::optional<uint32_t> droppedDepth_ {};
|
||||
};
|
||||
|
||||
class SetNativeRangeParams {
|
||||
public:
|
||||
SetNativeRangeParams() = default;
|
||||
~SetNativeRangeParams() = default;
|
||||
static std::unique_ptr<SetNativeRangeParams> Create(const PtJson ¶ms);
|
||||
|
||||
std::vector<NativeRange> GetNativeRange() const
|
||||
{
|
||||
return nativeRange_;
|
||||
}
|
||||
private:
|
||||
|
||||
std::vector<NativeRange> nativeRange_ {};
|
||||
};
|
||||
|
||||
class ResetSingleStepperParams : public PtBaseParams {
|
||||
public:
|
||||
ResetSingleStepperParams() = default;
|
||||
~ResetSingleStepperParams() = default;
|
||||
static std::unique_ptr<ResetSingleStepperParams> Create(const PtJson ¶ms);
|
||||
|
||||
bool GetResetSingleStepper() const
|
||||
{
|
||||
return resetSingleStepper_;
|
||||
}
|
||||
private:
|
||||
NO_COPY_SEMANTIC(ResetSingleStepperParams);
|
||||
NO_MOVE_SEMANTIC(ResetSingleStepperParams);
|
||||
|
||||
bool resetSingleStepper_ {false};
|
||||
};
|
||||
|
||||
class SetMixedDebugParams : public PtBaseParams {
|
||||
public:
|
||||
SetMixedDebugParams() = default;
|
||||
|
@ -1680,6 +1680,36 @@ std::unique_ptr<PtJson> LocationRange::ToJson() const
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<NativeRange> NativeRange::Create(const PtJson ¶ms)
|
||||
{
|
||||
std::string error;
|
||||
auto nativeRange = std::make_unique<NativeRange>();
|
||||
Result ret;
|
||||
|
||||
uint32_t start;
|
||||
ret = params.GetUInt("start", &start);
|
||||
if (ret == Result::SUCCESS) {
|
||||
nativeRange->start_ = std::move(start);
|
||||
} else {
|
||||
error += "Unknown 'start';";
|
||||
}
|
||||
|
||||
uint32_t end;
|
||||
ret = params.GetUInt("end", &end);
|
||||
if (ret == Result::SUCCESS) {
|
||||
nativeRange->end_ = std::move(end);
|
||||
} else {
|
||||
error += "Unknown 'end';";
|
||||
}
|
||||
|
||||
if (!error.empty()) {
|
||||
LOG_DEBUGGER(ERROR) << "NativeRange::Create " << error;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nativeRange;
|
||||
}
|
||||
|
||||
std::unique_ptr<BreakLocation> BreakLocation::Create(const PtJson ¶ms)
|
||||
{
|
||||
std::string error;
|
||||
|
@ -1301,6 +1301,41 @@ private:
|
||||
std::unique_ptr<ScriptPosition> end_ {nullptr};
|
||||
};
|
||||
|
||||
class NativeRange {
|
||||
public:
|
||||
NativeRange() = default;
|
||||
~NativeRange() = default;
|
||||
|
||||
static std::unique_ptr<NativeRange> Create(const PtJson ¶ms);
|
||||
|
||||
uint32_t GetStart() const
|
||||
{
|
||||
return start_;
|
||||
}
|
||||
|
||||
NativeRange &SetStart(uint32_t start)
|
||||
{
|
||||
start_ = std::move(start);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint32_t GetEnd() const
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
||||
NativeRange &SetEnd(uint32_t end)
|
||||
{
|
||||
end_ = std::move(end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t start_ {0};
|
||||
uint32_t end_ {0};
|
||||
};
|
||||
|
||||
// Debugger.BreakLocation
|
||||
class BreakLocation final : public PtBaseTypes {
|
||||
public:
|
||||
|
@ -28,6 +28,7 @@ using BreakpointCallback = std::function<bool(const JSPtLocation &)>;
|
||||
using LoadModuleCallback = std::function<bool(std::string_view)>;
|
||||
using ExceptionCallback = std::function<bool(const JSPtLocation &)>;
|
||||
using SingleStepCallback = std::function<bool(const JSPtLocation &)>;
|
||||
using NativeOutCallback = std::function<bool()>;
|
||||
using VmStartCallback = std::function<bool()>;
|
||||
using VmDeathCallback = std::function<bool()>;
|
||||
using Scenario = std::function<bool()>;
|
||||
@ -56,6 +57,7 @@ struct TestEvents {
|
||||
LoadModuleCallback loadModule;
|
||||
ExceptionCallback exception;
|
||||
SingleStepCallback singleStep;
|
||||
NativeOutCallback nativeOut;
|
||||
VmStartCallback vmStart;
|
||||
VmDeathCallback vmDeath;
|
||||
|
||||
|
@ -87,6 +87,15 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeOut() override
|
||||
{
|
||||
if (test_->nativeOut) {
|
||||
return test_->nativeOut();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void VmDeath() override
|
||||
{
|
||||
if (test_->vmDeath) {
|
||||
@ -105,6 +114,8 @@ public:
|
||||
|
||||
void NativeCalling([[maybe_unused]] const void *nativeAddress) override {}
|
||||
|
||||
void NativeReturnJS() override {}
|
||||
|
||||
void TerminateTest()
|
||||
{
|
||||
debugInterface_->UnregisterHooks();
|
||||
|
Loading…
Reference in New Issue
Block a user