mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
!3051 Enhance Return Stack for DFX
Merge pull request !3051 from 李晨帅/master
This commit is contained in:
commit
b0343f5d9d
@ -22,6 +22,7 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
#define IGNORE_BC_STUB(...)
|
||||
#define ASM_UNUSED_BC_STUB_LIST(T) \
|
||||
T(HandleOverflowD6) \
|
||||
T(HandleOverflowD7) \
|
||||
T(HandleOverflowD8) \
|
||||
T(HandleOverflowD9) \
|
||||
@ -58,8 +59,7 @@ namespace panda::ecmascript::kungfu {
|
||||
T(HandleOverflowF8) \
|
||||
T(HandleOverflowF9) \
|
||||
T(HandleOverflowFA) \
|
||||
T(HandleOverflowFB) \
|
||||
T(HandleOverflowFC)
|
||||
T(HandleOverflowFB)
|
||||
|
||||
|
||||
// V: Not Enabled, T: Enabled, D: Always Disable SingleStepDebugging
|
||||
|
@ -16,9 +16,11 @@
|
||||
#include "ecmascript/frames.h"
|
||||
|
||||
#include "ecmascript/aot_file_manager.h"
|
||||
#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/interpreter/frame_handler.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/platform/os.h"
|
||||
#include "ecmascript/stackmap/ark_stackmap_parser.h"
|
||||
#include "ecmascript/stackmap/llvm_stackmap_parser.h"
|
||||
@ -769,7 +771,7 @@ bool StepArkManagedNativeFrame(int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t
|
||||
LOG_ECMA(ERROR) << "FrameType ERROR, addr: " << currentPtr << ", frameType: " << frameType;
|
||||
return false;
|
||||
}
|
||||
if (frameType == (uintptr_t)(FrameType::ASM_INTERPRETER_ENTRY_FRAME)) {
|
||||
if (static_cast<FrameType>(frameType) == FrameType::ASM_INTERPRETER_ENTRY_FRAME) {
|
||||
break;
|
||||
}
|
||||
currentPtr -= typeOffset;
|
||||
@ -788,6 +790,99 @@ bool StepArkManagedNativeFrame(int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t
|
||||
*sp = currentPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyBytecodeInfoToBuffer(const char *prefix, uintptr_t fullBytecode, size_t &strIdx, char *outStr, size_t strLen)
|
||||
{
|
||||
// note: big endian
|
||||
for (size_t i = 0; prefix[i] != '\0' && strIdx < strLen - 1; i++) { // 1: last '\0'
|
||||
outStr[strIdx++] = prefix[i];
|
||||
}
|
||||
size_t start = GET_MESSAGE_STRING_ID(HandleLdundefined);
|
||||
size_t bytecode = fullBytecode & 0xff; // 0xff: last byte
|
||||
const char *bytecodeName = MessageString::GetMessageString(start + bytecode).c_str();
|
||||
for (size_t i = 0; bytecodeName[i] != '\0' && strIdx < strLen - 1; i++) { // 1: last '\0'
|
||||
outStr[strIdx++] = bytecodeName[i];
|
||||
}
|
||||
if (start + bytecode == GET_MESSAGE_STRING_ID(HandleDeprecated) ||
|
||||
start + bytecode == GET_MESSAGE_STRING_ID(HandleWide) ||
|
||||
start + bytecode == GET_MESSAGE_STRING_ID(HandleThrow)) {
|
||||
size_t startSecond = start;
|
||||
if (start + bytecode == GET_MESSAGE_STRING_ID(HandleDeprecated)) {
|
||||
startSecond = GET_MESSAGE_STRING_ID(HandleDeprecatedLdlexenvPrefNone);
|
||||
} else if (start + bytecode == GET_MESSAGE_STRING_ID(HandleWide)) {
|
||||
startSecond = GET_MESSAGE_STRING_ID(HandleWideCreateobjectwithexcludedkeysPrefImm16V8V8);
|
||||
} else if (start + bytecode == GET_MESSAGE_STRING_ID(HandleThrow)) {
|
||||
startSecond = GET_MESSAGE_STRING_ID(HandleThrowPrefNone);
|
||||
}
|
||||
size_t bytecodeSecond = (fullBytecode >> 8) & 0xff; // 8, 0xff: second last byte
|
||||
const char *bytecodeNameSecond = MessageString::GetMessageString(startSecond + bytecodeSecond).c_str();
|
||||
if (strIdx < strLen - 1) { // 1: last '\0'
|
||||
outStr[strIdx++] = '/';
|
||||
}
|
||||
for (size_t i = 0; bytecodeNameSecond[i] != '\0' && strIdx < strLen - 1; i++) { // 1: last '\0'
|
||||
outStr[strIdx++] = bytecodeNameSecond[i];
|
||||
}
|
||||
}
|
||||
outStr[strIdx] = '\0';
|
||||
}
|
||||
|
||||
bool GetArkJSHeapCrashInfo(int pid, uintptr_t *bytecodePc, uintptr_t *fp, bool outJSInfo, char *outStr, size_t strLen)
|
||||
{
|
||||
// bytecodePc: X20 in ARM
|
||||
// fp: X29 in ARM
|
||||
// outJSInfo: not async-safe, more info
|
||||
uintptr_t currentPtr = *fp;
|
||||
currentPtr -= sizeof(FrameType);
|
||||
uintptr_t frameType = 0;
|
||||
if (!ReadUintptrFromAddr(pid, currentPtr, frameType)) {
|
||||
return false;
|
||||
}
|
||||
if (static_cast<FrameType>(frameType) != FrameType::ASM_INTERPRETER_FRAME) {
|
||||
return false;
|
||||
}
|
||||
size_t strIndex = 0;
|
||||
uintptr_t registerBytecode = 0;
|
||||
if (!ReadUintptrFromAddr(pid, *bytecodePc, registerBytecode)) {
|
||||
return false;
|
||||
}
|
||||
CopyBytecodeInfoToBuffer("RegisterBytecode:", registerBytecode, strIndex, outStr, strLen);
|
||||
uintptr_t typeOffset = MEMBER_OFFSET(AsmInterpretedFrame, base) + MEMBER_OFFSET(InterpretedFrameBase, type);
|
||||
uintptr_t pcOffset = MEMBER_OFFSET(AsmInterpretedFrame, pc);
|
||||
currentPtr -= typeOffset;
|
||||
currentPtr += pcOffset;
|
||||
uintptr_t framePc = 0;
|
||||
uintptr_t frameBytecode = 0;
|
||||
if (!ReadUintptrFromAddr(pid, currentPtr, framePc)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadUintptrFromAddr(pid, framePc, frameBytecode)) {
|
||||
return false;
|
||||
}
|
||||
CopyBytecodeInfoToBuffer(" FrameBytecode:", frameBytecode, strIndex, outStr, strLen);
|
||||
if (outJSInfo) {
|
||||
uintptr_t functionOffset = MEMBER_OFFSET(AsmInterpretedFrame, function);
|
||||
currentPtr -= pcOffset;
|
||||
currentPtr += functionOffset;
|
||||
uintptr_t functionAddress = 0;
|
||||
if (!ReadUintptrFromAddr(pid, currentPtr, functionAddress)) {
|
||||
return false;
|
||||
}
|
||||
JSTaggedValue functionValue(static_cast<JSTaggedType>(functionAddress));
|
||||
Method *method = ECMAObject::Cast(functionValue.GetTaggedObject())->GetCallTarget();
|
||||
auto bytecodeOffset = static_cast<uint32_t>(reinterpret_cast<uint8_t *>(*bytecodePc) -
|
||||
method->GetBytecodeArray());
|
||||
std::string info = JsStackInfo::BuildMethodTrace(method, bytecodeOffset);
|
||||
const char *infoChar = info.c_str();
|
||||
if (strIndex < strLen - 1) { // 1: last '\0'
|
||||
outStr[strIndex++] = ' ';
|
||||
}
|
||||
for (size_t i = 0; infoChar[i] != '\0' && strIndex < strLen - 1; i++) { // 1: last '\0'
|
||||
outStr[strIndex++] = infoChar[i];
|
||||
}
|
||||
outStr[strIndex] = '\0';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
__attribute__((visibility("default"))) int step_ark_managed_native_frame(
|
||||
@ -798,3 +893,12 @@ __attribute__((visibility("default"))) int step_ark_managed_native_frame(
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int get_ark_js_heap_crash_info(
|
||||
int pid, uintptr_t *x20, uintptr_t *fp, int out_js_info, char *buf, size_t buf_sz)
|
||||
{
|
||||
if (panda::ecmascript::GetArkJSHeapCrashInfo(pid, x20, fp, out_js_info != 0, buf, buf_sz)) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -1428,4 +1428,6 @@ private:
|
||||
} // namespace panda::ecmascript
|
||||
extern "C" int step_ark_managed_native_frame(
|
||||
int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz);
|
||||
extern "C" int get_ark_js_heap_crash_info(
|
||||
int pid, uintptr_t *x20, uintptr_t *fp, int out_js_info, char *buf, size_t buf_sz);
|
||||
#endif // ECMASCRIPT_FRAMES_H
|
||||
|
@ -33,6 +33,7 @@ host_unittest_action("EcmaVm_001_Test") {
|
||||
"ecma_string_accessor_test.cpp",
|
||||
"ecma_string_table_test.cpp",
|
||||
"ecma_vm_test.cpp",
|
||||
"frame_test.cpp",
|
||||
"gc_test.cpp",
|
||||
"global_dictionary_test.cpp",
|
||||
"glue_regs_test.cpp",
|
||||
|
78
ecmascript/tests/frame_test.cpp
Normal file
78
ecmascript/tests/frame_test.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/frames.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
namespace panda::test {
|
||||
class FrameTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* @tc.name: GetArkJSHeapCrashInfoTest
|
||||
* @tc.desc: Test API get_ark_js_heap_crash_info
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:
|
||||
*/
|
||||
HWTEST_F_L0(FrameTest, GetArkJSHeapCrashInfoTest)
|
||||
{
|
||||
uint8_t bytecode[] = {
|
||||
12, // 12: HandleMul2Imm8V8
|
||||
34, // 34: HandleDecImm8
|
||||
56, // 56: HandleStobjbyvalueImm8V8V8
|
||||
78, // 78: HandleJmpImm16
|
||||
90, // 90: HandleJstrictequndefinedImm8
|
||||
254, // 254: HandleThrow
|
||||
8, // 8: HandleThrowIfsupernotcorrectcallPrefImm16
|
||||
};
|
||||
JSTaggedType frame[9]; // 9: size of AsmInterpretedFrame
|
||||
frame[0] = JSTaggedValue::Hole().GetRawData(); // 0: function
|
||||
frame[1] = JSTaggedValue::Hole().GetRawData(); // 1: thisObj
|
||||
frame[2] = JSTaggedValue::Hole().GetRawData(); // 2: acc
|
||||
frame[3] = JSTaggedValue::Hole().GetRawData(); // 3: env
|
||||
frame[4] = static_cast<JSTaggedType>(0); // 4: callSize
|
||||
frame[5] = static_cast<JSTaggedType>(0); // 5: fp
|
||||
frame[6] = reinterpret_cast<JSTaggedType>(&bytecode[2]); // 6: pc
|
||||
frame[7] = static_cast<JSTaggedType>(0); // 7: base.prev
|
||||
frame[8] = static_cast<JSTaggedType>(FrameType::ASM_INTERPRETER_FRAME); // 8: base.type
|
||||
uintptr_t x20 = reinterpret_cast<uintptr_t>(&bytecode[5]); // 5: HandleThrow offset
|
||||
uintptr_t fp = reinterpret_cast<uintptr_t>(&frame[9]); // 9: bottom of frame
|
||||
char buf[256]; // 256: buf size
|
||||
int result = get_ark_js_heap_crash_info(getpid(), &x20, &fp, 0, &buf[0], 256); // 256: buf size
|
||||
EXPECT_EQ(result, 1);
|
||||
EXPECT_EQ(std::string(buf), std::string("RegisterBytecode:HandleThrow/HandleThrowIfsupernotcorrectcallPrefImm16") +
|
||||
std::string(" FrameBytecode:HandleStobjbyvalueImm8V8V8"));
|
||||
}
|
||||
} // namespace panda::ecmascript
|
Loading…
Reference in New Issue
Block a user