1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include <gtest/gtest.h> 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <cstdio> 19800b99b8Sopenharmony_ci#include <malloc.h> 20800b99b8Sopenharmony_ci#include <map> 21800b99b8Sopenharmony_ci#include <securec.h> 22800b99b8Sopenharmony_ci#include <thread> 23800b99b8Sopenharmony_ci#include <unistd.h> 24800b99b8Sopenharmony_ci 25800b99b8Sopenharmony_ci#include "dfx_config.h" 26800b99b8Sopenharmony_ci#include "dfx_frame_formatter.h" 27800b99b8Sopenharmony_ci#include "dfx_ptrace.h" 28800b99b8Sopenharmony_ci#include "dfx_regs_get.h" 29800b99b8Sopenharmony_ci#include "dfx_test_util.h" 30800b99b8Sopenharmony_ci#include "elapsed_time.h" 31800b99b8Sopenharmony_ci#include "unwinder.h" 32800b99b8Sopenharmony_ci 33800b99b8Sopenharmony_ci#if defined(__x86_64__) 34800b99b8Sopenharmony_ci#include <unwind.h> // GCC's internal unwinder, part of libgcc 35800b99b8Sopenharmony_ci#endif 36800b99b8Sopenharmony_ci 37800b99b8Sopenharmony_ciusing namespace testing; 38800b99b8Sopenharmony_ciusing namespace testing::ext; 39800b99b8Sopenharmony_ci 40800b99b8Sopenharmony_cinamespace OHOS { 41800b99b8Sopenharmony_cinamespace HiviewDFX { 42800b99b8Sopenharmony_ci#undef LOG_DOMAIN 43800b99b8Sopenharmony_ci#undef LOG_TAG 44800b99b8Sopenharmony_ci#define LOG_TAG "DfxUnwinderTest" 45800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 46800b99b8Sopenharmony_ci#define TIME_SLEEP 3 47800b99b8Sopenharmony_ci 48800b99b8Sopenharmony_ciclass UnwinderTest : public testing::Test { 49800b99b8Sopenharmony_cipublic: 50800b99b8Sopenharmony_ci static void SetUpTestCase() {} 51800b99b8Sopenharmony_ci static void TearDownTestCase() {} 52800b99b8Sopenharmony_ci void SetUp() {} 53800b99b8Sopenharmony_ci void TearDown() {} 54800b99b8Sopenharmony_ci 55800b99b8Sopenharmony_ci std::map<int, std::shared_ptr<Unwinder>> unwinders_; 56800b99b8Sopenharmony_ci const size_t skipFrameNum = 2; 57800b99b8Sopenharmony_ci}; 58800b99b8Sopenharmony_ci 59800b99b8Sopenharmony_ci/** 60800b99b8Sopenharmony_ci * @tc.name: GetStackRangeTest001 61800b99b8Sopenharmony_ci * @tc.desc: test unwinder GetStackRange interface in pid == tid 62800b99b8Sopenharmony_ci * @tc.type: FUNC 63800b99b8Sopenharmony_ci */ 64800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, GetStackRangeTest001, TestSize.Level2) 65800b99b8Sopenharmony_ci{ 66800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetStackRangeTest001: start."; 67800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 68800b99b8Sopenharmony_ci uintptr_t stackBottom = 1; 69800b99b8Sopenharmony_ci uintptr_t stackTop = static_cast<uintptr_t>(-1); 70800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "when pid == tid and maps_ != null, GetStackRange(stackBottom, stackTop) is true"; 71800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop)); 72800b99b8Sopenharmony_ci // When the param is less than -1, maps_ = null when method Unwinder is constructed 73800b99b8Sopenharmony_ci auto unwinderNegative = std::make_shared<Unwinder>(-2); 74800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "when pid == tid and maps_ == null, GetStackRange(stackBottom, stackTop) is false"; 75800b99b8Sopenharmony_ci ASSERT_TRUE(unwinderNegative->GetStackRange(stackBottom, stackTop)); 76800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetStackRangeTest001: end."; 77800b99b8Sopenharmony_ci} 78800b99b8Sopenharmony_ci 79800b99b8Sopenharmony_ci/** 80800b99b8Sopenharmony_ci * @tc.name: GetStackRangeTest002 81800b99b8Sopenharmony_ci * @tc.desc: test unwinder GetStackRange interface in pid != tid 82800b99b8Sopenharmony_ci * @tc.type: FUNC 83800b99b8Sopenharmony_ci */ 84800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, GetStackRangeTest002, TestSize.Level2) 85800b99b8Sopenharmony_ci{ 86800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetStackRangeTest002: start."; 87800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 88800b99b8Sopenharmony_ci uintptr_t stackBottom = 1; 89800b99b8Sopenharmony_ci uintptr_t stackTop = static_cast<uintptr_t>(-1); 90800b99b8Sopenharmony_ci bool result = false; 91800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Run the function with thread will get pid != tid, " 92800b99b8Sopenharmony_ci "GetStackRange(stackBottom, stackTop) is true"; 93800b99b8Sopenharmony_ci std::thread th([unwinder, &stackBottom, &stackTop, &result] { 94800b99b8Sopenharmony_ci result = unwinder->GetStackRange(stackBottom, stackTop); 95800b99b8Sopenharmony_ci }); 96800b99b8Sopenharmony_ci if (th.joinable()) { 97800b99b8Sopenharmony_ci th.join(); 98800b99b8Sopenharmony_ci } 99800b99b8Sopenharmony_ci ASSERT_TRUE(result); 100800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetStackRangeTest002: end."; 101800b99b8Sopenharmony_ci} 102800b99b8Sopenharmony_ci 103800b99b8Sopenharmony_ci/** 104800b99b8Sopenharmony_ci * @tc.name: UnwinderLocalTest001 105800b99b8Sopenharmony_ci * @tc.desc: test unwinder local unwind 106800b99b8Sopenharmony_ci * @tc.type: FUNC 107800b99b8Sopenharmony_ci */ 108800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderLocalTest001, TestSize.Level2) 109800b99b8Sopenharmony_ci{ 110800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest001: start."; 111800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 112800b99b8Sopenharmony_ci ElapsedTime counter; 113800b99b8Sopenharmony_ci MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal(); 114800b99b8Sopenharmony_ci unwinder->EnableMethodIdLocal(true); 115800b99b8Sopenharmony_ci time_t elapsed1 = counter.Elapsed(); 116800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderLocalTest001: Unwind:" << unwRet; 117800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 118800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 119800b99b8Sopenharmony_ci time_t elapsed2 = counter.Elapsed(); 120800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2; 121800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest001: frames:\n" << Unwinder::GetFramesStr(frames); 122800b99b8Sopenharmony_ci unwRet = unwinder->UnwindLocal(false, false, DEFAULT_MAX_FRAME_NUM, skipFrameNum); 123800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderLocalTest001: Unwind:" << unwRet; 124800b99b8Sopenharmony_ci auto frames2 = unwinder->GetFrames(); 125800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), frames2.size()); 126800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest001: frames2:\n" << Unwinder::GetFramesStr(frames2); 127800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest001: end."; 128800b99b8Sopenharmony_ci} 129800b99b8Sopenharmony_ci 130800b99b8Sopenharmony_ci/** 131800b99b8Sopenharmony_ci * @tc.name: UnwinderLocalTest002 132800b99b8Sopenharmony_ci * @tc.desc: test unwinder local unwind n counts 133800b99b8Sopenharmony_ci * @tc.type: FUNC 134800b99b8Sopenharmony_ci */ 135800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderLocalTest002, TestSize.Level2) 136800b99b8Sopenharmony_ci{ 137800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest002: start."; 138800b99b8Sopenharmony_ci unwinders_.clear(); 139800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder = nullptr; 140800b99b8Sopenharmony_ci pid_t pid = getpid(); 141800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "pid: " << pid; 142800b99b8Sopenharmony_ci for (int i = 0; i < 10; ++i) { 143800b99b8Sopenharmony_ci auto it = unwinders_.find(pid); 144800b99b8Sopenharmony_ci if (it != unwinders_.end()) { 145800b99b8Sopenharmony_ci unwinder = it->second; 146800b99b8Sopenharmony_ci } else { 147800b99b8Sopenharmony_ci unwinder = std::make_shared<Unwinder>(); 148800b99b8Sopenharmony_ci } 149800b99b8Sopenharmony_ci ElapsedTime counter; 150800b99b8Sopenharmony_ci MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal(); 151800b99b8Sopenharmony_ci time_t elapsed1 = counter.Elapsed(); 152800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderLocalTest002: Unwind:" << unwRet; 153800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 154800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 155800b99b8Sopenharmony_ci time_t elapsed2 = counter.Elapsed(); 156800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2; 157800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest002: frames:\n" << Unwinder::GetFramesStr(frames); 158800b99b8Sopenharmony_ci unwinders_[pid] = unwinder; 159800b99b8Sopenharmony_ci sleep(1); 160800b99b8Sopenharmony_ci }; 161800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest002: end."; 162800b99b8Sopenharmony_ci} 163800b99b8Sopenharmony_ci 164800b99b8Sopenharmony_ci/** 165800b99b8Sopenharmony_ci * @tc.name: UnwinderLocalTest003 166800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocal interface 167800b99b8Sopenharmony_ci * @tc.type: FUNC 168800b99b8Sopenharmony_ci */ 169800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderLocalTest003, TestSize.Level2) 170800b99b8Sopenharmony_ci{ 171800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest003: start."; 172800b99b8Sopenharmony_ci // When the param is less than -1, maps_ = null when method Unwinder is constructed 173800b99b8Sopenharmony_ci auto unwinderNegative = std::make_shared<Unwinder>(-2); 174800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "when pid == tid and maps_ == null, " 175800b99b8Sopenharmony_ci "UnwindLocal(maxFrameNum, skipFrameNum) is false"; 176800b99b8Sopenharmony_ci ASSERT_FALSE(unwinderNegative->UnwindLocal()); 177800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 178800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "when pid == tid and maps_ != null, " 179800b99b8Sopenharmony_ci "UnwindLocal(maxFrameNum, skipFrameNum) is true"; 180800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->UnwindLocal()); 181800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderLocalTest003: end."; 182800b99b8Sopenharmony_ci} 183800b99b8Sopenharmony_ci 184800b99b8Sopenharmony_ci/** 185800b99b8Sopenharmony_ci * @tc.name: UnwinderRemoteTest001 186800b99b8Sopenharmony_ci * @tc.desc: test unwinder remote unwind 187800b99b8Sopenharmony_ci * @tc.type: FUNC 188800b99b8Sopenharmony_ci */ 189800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderRemoteTest001, TestSize.Level2) 190800b99b8Sopenharmony_ci{ 191800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest001: start."; 192800b99b8Sopenharmony_ci pid_t child = fork(); 193800b99b8Sopenharmony_ci if (child == 0) { 194800b99b8Sopenharmony_ci sleep(TIME_SLEEP); 195800b99b8Sopenharmony_ci _exit(0); 196800b99b8Sopenharmony_ci } 197800b99b8Sopenharmony_ci 198800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid(); 199800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(child); 200800b99b8Sopenharmony_ci bool unwRet = DfxPtrace::Attach(child); 201800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: Attach:" << unwRet; 202800b99b8Sopenharmony_ci ElapsedTime counter; 203800b99b8Sopenharmony_ci unwRet = unwinder->UnwindRemote(child); 204800b99b8Sopenharmony_ci time_t elapsed1 = counter.Elapsed(); 205800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: unwRet:" << unwRet; 206800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 207800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 208800b99b8Sopenharmony_ci time_t elapsed2 = counter.Elapsed(); 209800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2; 210800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest001: frames:\n" << Unwinder::GetFramesStr(frames); 211800b99b8Sopenharmony_ci unwRet = unwinder->UnwindRemote(child, false, DEFAULT_MAX_FRAME_NUM, skipFrameNum); 212800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest001: unwRet:" << unwRet; 213800b99b8Sopenharmony_ci auto frames2 = unwinder->GetFrames(); 214800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), frames2.size()); 215800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest001: frames2:\n" << Unwinder::GetFramesStr(frames2); 216800b99b8Sopenharmony_ci DfxPtrace::Detach(child); 217800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest001: end."; 218800b99b8Sopenharmony_ci} 219800b99b8Sopenharmony_ci 220800b99b8Sopenharmony_ci/** 221800b99b8Sopenharmony_ci * @tc.name: UnwinderRemoteTest002 222800b99b8Sopenharmony_ci * @tc.desc: test unwinder remote unwind n counts 223800b99b8Sopenharmony_ci * @tc.type: FUNC 224800b99b8Sopenharmony_ci */ 225800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderRemoteTest002, TestSize.Level2) 226800b99b8Sopenharmony_ci{ 227800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest002: start."; 228800b99b8Sopenharmony_ci pid_t child = fork(); 229800b99b8Sopenharmony_ci if (child == 0) { 230800b99b8Sopenharmony_ci sleep(TIME_SLEEP); 231800b99b8Sopenharmony_ci _exit(0); 232800b99b8Sopenharmony_ci } 233800b99b8Sopenharmony_ci 234800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid(); 235800b99b8Sopenharmony_ci unwinders_.clear(); 236800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder = nullptr; 237800b99b8Sopenharmony_ci bool unwRet = DfxPtrace::Attach(child); 238800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest002: Attach:" << unwRet; 239800b99b8Sopenharmony_ci for (int i = 0; i < 10; ++i) { 240800b99b8Sopenharmony_ci auto it = unwinders_.find(child); 241800b99b8Sopenharmony_ci if (it != unwinders_.end()) { 242800b99b8Sopenharmony_ci unwinder = it->second; 243800b99b8Sopenharmony_ci } else { 244800b99b8Sopenharmony_ci unwinder = std::make_shared<Unwinder>(child); 245800b99b8Sopenharmony_ci } 246800b99b8Sopenharmony_ci ElapsedTime counter; 247800b99b8Sopenharmony_ci unwRet = unwinder->UnwindRemote(child); 248800b99b8Sopenharmony_ci time_t elapsed1 = counter.Elapsed(); 249800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwinderRemoteTest002: Unwind:" << unwRet; 250800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 251800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 252800b99b8Sopenharmony_ci time_t elapsed2 = counter.Elapsed(); 253800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2; 254800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest002: frames:\n" << Unwinder::GetFramesStr(frames); 255800b99b8Sopenharmony_ci unwinders_[child] = unwinder; 256800b99b8Sopenharmony_ci sleep(1); 257800b99b8Sopenharmony_ci } 258800b99b8Sopenharmony_ci DfxPtrace::Detach(child); 259800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest002: end."; 260800b99b8Sopenharmony_ci} 261800b99b8Sopenharmony_ci 262800b99b8Sopenharmony_ci/** 263800b99b8Sopenharmony_ci * @tc.name: UnwinderRemoteTest003 264800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindRemote interface 265800b99b8Sopenharmony_ci * @tc.type: FUNC 266800b99b8Sopenharmony_ci */ 267800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderRemoteTest003, TestSize.Level2) 268800b99b8Sopenharmony_ci{ 269800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest003: start."; 270800b99b8Sopenharmony_ci // When the param is less than -1, pid_ < 0 when method Unwinder is constructed 271800b99b8Sopenharmony_ci auto unwinderNegative = std::make_shared<Unwinder>(-2); 272800b99b8Sopenharmony_ci size_t maxFrameNum = 64; 273800b99b8Sopenharmony_ci size_t skipFrameNum = 0; 274800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "when pid <= 0, UnwindRemote(maxFrameNum, skipFrameNum) is false"; 275800b99b8Sopenharmony_ci ASSERT_FALSE(unwinderNegative->UnwindRemote(-2, maxFrameNum, skipFrameNum)); 276800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderRemoteTest003: end."; 277800b99b8Sopenharmony_ci} 278800b99b8Sopenharmony_ci 279800b99b8Sopenharmony_ci/** 280800b99b8Sopenharmony_ci * @tc.name: UnwindTest001 281800b99b8Sopenharmony_ci * @tc.desc: test unwinder unwind interface in remote case 282800b99b8Sopenharmony_ci * @tc.type: FUNC 283800b99b8Sopenharmony_ci */ 284800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest001, TestSize.Level2) 285800b99b8Sopenharmony_ci{ 286800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest001: start."; 287800b99b8Sopenharmony_ci pid_t child = fork(); 288800b99b8Sopenharmony_ci if (child == 0) { 289800b99b8Sopenharmony_ci sleep(TIME_SLEEP); 290800b99b8Sopenharmony_ci _exit(0); 291800b99b8Sopenharmony_ci } 292800b99b8Sopenharmony_ci 293800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid(); 294800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(child); 295800b99b8Sopenharmony_ci bool unwRet = DfxPtrace::Attach(child); 296800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwindTest001: Attach:" << unwRet; 297800b99b8Sopenharmony_ci auto regs = DfxRegs::CreateRemoteRegs(child); 298800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 299800b99b8Sopenharmony_ci auto maps = DfxMaps::Create(child); 300800b99b8Sopenharmony_ci UnwindContext context; 301800b99b8Sopenharmony_ci context.pid = child; 302800b99b8Sopenharmony_ci context.regs = regs; 303800b99b8Sopenharmony_ci context.maps = maps; 304800b99b8Sopenharmony_ci ElapsedTime counter; 305800b99b8Sopenharmony_ci unwRet = unwinder->Unwind(&context); 306800b99b8Sopenharmony_ci time_t elapsed1 = counter.Elapsed(); 307800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwindTest001: Unwind:" << unwRet; 308800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 309800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 310800b99b8Sopenharmony_ci time_t elapsed2 = counter.Elapsed(); 311800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "Elapsed-: " << elapsed1 << "\tElapsed+: " << elapsed2; 312800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest001: frames:\n" << Unwinder::GetFramesStr(frames); 313800b99b8Sopenharmony_ci DfxPtrace::Detach(child); 314800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest001: end."; 315800b99b8Sopenharmony_ci} 316800b99b8Sopenharmony_ci 317800b99b8Sopenharmony_ci/** 318800b99b8Sopenharmony_ci * @tc.name: UnwindTest002 319800b99b8Sopenharmony_ci * @tc.desc: test unwinder unwind interface in local case 320800b99b8Sopenharmony_ci * @tc.type: FUNC 321800b99b8Sopenharmony_ci */ 322800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest002, TestSize.Level2) 323800b99b8Sopenharmony_ci{ 324800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest002: start."; 325800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 326800b99b8Sopenharmony_ci uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1); 327800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop)); 328800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest002: GetStackRange."; 329800b99b8Sopenharmony_ci UnwindContext context; 330800b99b8Sopenharmony_ci context.stackCheck = false; 331800b99b8Sopenharmony_ci context.stackBottom = stackBottom; 332800b99b8Sopenharmony_ci context.stackTop = stackTop; 333800b99b8Sopenharmony_ci 334800b99b8Sopenharmony_ci auto regs = DfxRegs::Create(); 335800b99b8Sopenharmony_ci auto regsData = regs->RawData(); 336800b99b8Sopenharmony_ci GetLocalRegs(regsData); 337800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 338800b99b8Sopenharmony_ci auto maps = DfxMaps::Create(getpid()); 339800b99b8Sopenharmony_ci context.pid = UNWIND_TYPE_LOCAL; 340800b99b8Sopenharmony_ci context.regs = regs; 341800b99b8Sopenharmony_ci context.maps = maps; 342800b99b8Sopenharmony_ci bool unwRet = unwinder->Unwind(&context); 343800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwindTest002: unwRet:" << unwRet; 344800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 345800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 346800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest002:frames:\n" << Unwinder::GetFramesStr(frames); 347800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest002: end."; 348800b99b8Sopenharmony_ci} 349800b99b8Sopenharmony_ci 350800b99b8Sopenharmony_ci/** 351800b99b8Sopenharmony_ci * @tc.name: UnwindTest003 352800b99b8Sopenharmony_ci * @tc.desc: test GetLastErrorCode GetLastErrorAddr functions 353800b99b8Sopenharmony_ci * in local case 354800b99b8Sopenharmony_ci * @tc.type: FUNC 355800b99b8Sopenharmony_ci */ 356800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest003, TestSize.Level2) 357800b99b8Sopenharmony_ci{ 358800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest003: start."; 359800b99b8Sopenharmony_ci 360800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 361800b99b8Sopenharmony_ci unwinder->IgnoreMixstack(true); 362800b99b8Sopenharmony_ci MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal(); 363800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "UnwindTest003: Unwind ret:" << unwRet; 364800b99b8Sopenharmony_ci unwinder->EnableFillFrames(false); 365800b99b8Sopenharmony_ci const auto& frames = unwinder->GetFrames(); 366800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1) << "frames.size() error"; 367800b99b8Sopenharmony_ci 368800b99b8Sopenharmony_ci uint16_t errorCode = unwinder->GetLastErrorCode(); 369800b99b8Sopenharmony_ci uint64_t errorAddr = unwinder->GetLastErrorAddr(); 370800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "errorCode:" << errorCode; 371800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "errorAddr:" << errorAddr; 372800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest003: end."; 373800b99b8Sopenharmony_ci} 374800b99b8Sopenharmony_ci 375800b99b8Sopenharmony_ci/** 376800b99b8Sopenharmony_ci * @tc.name: UnwindTest004 377800b99b8Sopenharmony_ci * @tc.desc: test unwinder local unwind for 378800b99b8Sopenharmony_ci * GetFramesStr(const std::vector<std::shared_ptr<DfxFrame>>& frames) 379800b99b8Sopenharmony_ci * @tc.type: FUNC 380800b99b8Sopenharmony_ci */ 381800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindTest004, TestSize.Level2) 382800b99b8Sopenharmony_ci{ 383800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest004: start."; 384800b99b8Sopenharmony_ci 385800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 386800b99b8Sopenharmony_ci ElapsedTime counter; 387800b99b8Sopenharmony_ci MAYBE_UNUSED bool unwRet = unwinder->UnwindLocal(); 388800b99b8Sopenharmony_ci ASSERT_EQ(true, unwRet) << "UnwindTest004: Unwind:" << unwRet; 389800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 390800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 391800b99b8Sopenharmony_ci 392800b99b8Sopenharmony_ci auto framesVec = DfxFrameFormatter::ConvertFrames(frames); 393800b99b8Sopenharmony_ci std::string framesStr = DfxFrameFormatter::GetFramesStr(framesVec); 394800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest004: frames:\n" << framesStr; 395800b99b8Sopenharmony_ci 396800b99b8Sopenharmony_ci string log[] = {"pc", "test_unwind", "#00", "#01", "#02"}; 397800b99b8Sopenharmony_ci int len = sizeof(log) / sizeof(log[0]); 398800b99b8Sopenharmony_ci int count = GetKeywordsNum(framesStr, log, len); 399800b99b8Sopenharmony_ci ASSERT_EQ(count, len) << "UnwindTest004 Failed"; 400800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindTest004: end."; 401800b99b8Sopenharmony_ci} 402800b99b8Sopenharmony_ci 403800b99b8Sopenharmony_ci/** 404800b99b8Sopenharmony_ci * @tc.name: StepTest001 405800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in remote case 406800b99b8Sopenharmony_ci * @tc.type: FUNC 407800b99b8Sopenharmony_ci */ 408800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest001, TestSize.Level2) 409800b99b8Sopenharmony_ci{ 410800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest001: start."; 411800b99b8Sopenharmony_ci pid_t child = fork(); 412800b99b8Sopenharmony_ci if (child == 0) { 413800b99b8Sopenharmony_ci sleep(TIME_SLEEP); 414800b99b8Sopenharmony_ci _exit(0); 415800b99b8Sopenharmony_ci } 416800b99b8Sopenharmony_ci 417800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid(); 418800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(child); 419800b99b8Sopenharmony_ci bool unwRet = DfxPtrace::Attach(child); 420800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "StepTest001: Attach:" << unwRet; 421800b99b8Sopenharmony_ci auto regs = DfxRegs::CreateRemoteRegs(child); 422800b99b8Sopenharmony_ci auto maps = DfxMaps::Create(child); 423800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 424800b99b8Sopenharmony_ci UnwindContext context; 425800b99b8Sopenharmony_ci context.pid = child; 426800b99b8Sopenharmony_ci context.regs = regs; 427800b99b8Sopenharmony_ci context.maps = maps; 428800b99b8Sopenharmony_ci 429800b99b8Sopenharmony_ci uintptr_t pc, sp; 430800b99b8Sopenharmony_ci pc = regs->GetPc(); 431800b99b8Sopenharmony_ci sp = regs->GetSp(); 432800b99b8Sopenharmony_ci std::shared_ptr<DfxMap> map = nullptr; 433800b99b8Sopenharmony_ci ASSERT_TRUE(maps->FindMapByAddr(pc, map)); 434800b99b8Sopenharmony_ci context.map = map; 435800b99b8Sopenharmony_ci unwRet = unwinder->Step(pc, sp, &context); 436800b99b8Sopenharmony_ci ASSERT_TRUE(unwRet) << "StepTest001: Unwind:" << unwRet; 437800b99b8Sopenharmony_ci DfxPtrace::Detach(child); 438800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest001: end."; 439800b99b8Sopenharmony_ci} 440800b99b8Sopenharmony_ci 441800b99b8Sopenharmony_ci/** 442800b99b8Sopenharmony_ci * @tc.name: StepTest002 443800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in local case 444800b99b8Sopenharmony_ci * @tc.type: FUNC 445800b99b8Sopenharmony_ci */ 446800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest002, TestSize.Level2) 447800b99b8Sopenharmony_ci{ 448800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest002: start."; 449800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 450800b99b8Sopenharmony_ci uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1); 451800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop)); 452800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest002: GetStackRange."; 453800b99b8Sopenharmony_ci auto maps = DfxMaps::Create(getpid()); 454800b99b8Sopenharmony_ci UnwindContext context; 455800b99b8Sopenharmony_ci context.pid = UNWIND_TYPE_LOCAL; 456800b99b8Sopenharmony_ci context.stackCheck = false; 457800b99b8Sopenharmony_ci context.stackBottom = stackBottom; 458800b99b8Sopenharmony_ci context.stackTop = stackTop; 459800b99b8Sopenharmony_ci 460800b99b8Sopenharmony_ci auto regs = DfxRegs::Create(); 461800b99b8Sopenharmony_ci auto regsData = regs->RawData(); 462800b99b8Sopenharmony_ci GetLocalRegs(regsData); 463800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 464800b99b8Sopenharmony_ci context.regs = regs; 465800b99b8Sopenharmony_ci context.maps = maps; 466800b99b8Sopenharmony_ci 467800b99b8Sopenharmony_ci uintptr_t pc, sp; 468800b99b8Sopenharmony_ci pc = regs->GetPc(); 469800b99b8Sopenharmony_ci sp = regs->GetSp(); 470800b99b8Sopenharmony_ci bool unwRet = unwinder->Step(pc, sp, &context); 471800b99b8Sopenharmony_ci ASSERT_TRUE(unwRet) << "StepTest002: unwRet:" << unwRet; 472800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest002: end."; 473800b99b8Sopenharmony_ci} 474800b99b8Sopenharmony_ci 475800b99b8Sopenharmony_ci#if defined(__aarch64__) 476800b99b8Sopenharmony_ci/** 477800b99b8Sopenharmony_ci * @tc.name: StepTest003 478800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindByFp interface in remote case 479800b99b8Sopenharmony_ci * @tc.type: FUNC 480800b99b8Sopenharmony_ci */ 481800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest003, TestSize.Level2) 482800b99b8Sopenharmony_ci{ 483800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest003: start."; 484800b99b8Sopenharmony_ci pid_t child = fork(); 485800b99b8Sopenharmony_ci if (child == 0) { 486800b99b8Sopenharmony_ci sleep(TIME_SLEEP); 487800b99b8Sopenharmony_ci _exit(0); 488800b99b8Sopenharmony_ci } 489800b99b8Sopenharmony_ci 490800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "pid: " << child << ", ppid:" << getpid(); 491800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(child); 492800b99b8Sopenharmony_ci bool unwRet = DfxPtrace::Attach(child); 493800b99b8Sopenharmony_ci EXPECT_EQ(true, unwRet) << "StepTest003: Attach:" << unwRet; 494800b99b8Sopenharmony_ci auto regs = DfxRegs::CreateRemoteRegs(child); 495800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 496800b99b8Sopenharmony_ci UnwindContext context; 497800b99b8Sopenharmony_ci context.pid = child; 498800b99b8Sopenharmony_ci ElapsedTime counter; 499800b99b8Sopenharmony_ci unwRet = unwinder->UnwindByFp(&context); 500800b99b8Sopenharmony_ci ASSERT_TRUE(unwRet) << "StepTest003: unwind:" << unwRet; 501800b99b8Sopenharmony_ci DfxPtrace::Detach(child); 502800b99b8Sopenharmony_ci time_t elapsed = counter.Elapsed(); 503800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest003: Elapsed: " << elapsed; 504800b99b8Sopenharmony_ci auto pcs = unwinder->GetPcs(); 505800b99b8Sopenharmony_ci std::vector<DfxFrame> frames; 506800b99b8Sopenharmony_ci unwinder->GetFramesByPcs(frames, pcs); 507800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 508800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest003: frames:\n" << Unwinder::GetFramesStr(frames); 509800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest003: end."; 510800b99b8Sopenharmony_ci} 511800b99b8Sopenharmony_ci 512800b99b8Sopenharmony_ci/** 513800b99b8Sopenharmony_ci * @tc.name: StepTest004 514800b99b8Sopenharmony_ci * @tc.desc: test unwinder FpStep interface in local case 515800b99b8Sopenharmony_ci * @tc.type: FUNC 516800b99b8Sopenharmony_ci */ 517800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest004, TestSize.Level2) 518800b99b8Sopenharmony_ci{ 519800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest004: start."; 520800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 521800b99b8Sopenharmony_ci ElapsedTime counter; 522800b99b8Sopenharmony_ci uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1); 523800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop)); 524800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest004: GetStackRange."; 525800b99b8Sopenharmony_ci 526800b99b8Sopenharmony_ci auto regs = DfxRegs::Create(); 527800b99b8Sopenharmony_ci auto regsData = regs->RawData(); 528800b99b8Sopenharmony_ci GetLocalRegs(regsData); 529800b99b8Sopenharmony_ci UnwindContext context; 530800b99b8Sopenharmony_ci context.pid = UNWIND_TYPE_LOCAL; 531800b99b8Sopenharmony_ci context.stackCheck = false; 532800b99b8Sopenharmony_ci context.stackBottom = stackBottom; 533800b99b8Sopenharmony_ci context.stackTop = stackTop; 534800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 535800b99b8Sopenharmony_ci 536800b99b8Sopenharmony_ci bool unwRet = unwinder->UnwindByFp(&context); 537800b99b8Sopenharmony_ci ASSERT_TRUE(unwRet) << "StepTest004: unwRet:" << unwRet; 538800b99b8Sopenharmony_ci auto unwSize = unwinder->GetPcs().size(); 539800b99b8Sopenharmony_ci ASSERT_GT(unwSize, 1) << "pcs.size() error"; 540800b99b8Sopenharmony_ci 541800b99b8Sopenharmony_ci uintptr_t miniRegs[FP_MINI_REGS_SIZE] = {0}; 542800b99b8Sopenharmony_ci GetFramePointerMiniRegs(miniRegs, sizeof(miniRegs) / sizeof(miniRegs[0])); 543800b99b8Sopenharmony_ci regs = DfxRegs::CreateFromRegs(UnwindMode::FRAMEPOINTER_UNWIND, miniRegs, sizeof(miniRegs) / sizeof(miniRegs[0])); 544800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 545800b99b8Sopenharmony_ci size_t idx = 0; 546800b99b8Sopenharmony_ci uintptr_t pc, fp; 547800b99b8Sopenharmony_ci while (true) { 548800b99b8Sopenharmony_ci pc = regs->GetPc(); 549800b99b8Sopenharmony_ci fp = regs->GetFp(); 550800b99b8Sopenharmony_ci idx++; 551800b99b8Sopenharmony_ci if (!unwinder->FpStep(fp, pc, &context) || (pc == 0)) { 552800b99b8Sopenharmony_ci break; 553800b99b8Sopenharmony_ci } 554800b99b8Sopenharmony_ci }; 555800b99b8Sopenharmony_ci ASSERT_EQ(idx, unwSize) << "StepTest004: idx:" << idx; 556800b99b8Sopenharmony_ci time_t elapsed = counter.Elapsed(); 557800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest004: Elapsed: " << elapsed; 558800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest004: end."; 559800b99b8Sopenharmony_ci} 560800b99b8Sopenharmony_ci#endif 561800b99b8Sopenharmony_ci 562800b99b8Sopenharmony_ci#if defined(__arm__) || defined(__aarch64__) 563800b99b8Sopenharmony_ci/** 564800b99b8Sopenharmony_ci * @tc.name: StepTest005 565800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in lr callback with apply failed case 566800b99b8Sopenharmony_ci * @tc.type: FUNC 567800b99b8Sopenharmony_ci */ 568800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest005, TestSize.Level2) 569800b99b8Sopenharmony_ci{ 570800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest005: start."; 571800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 572800b99b8Sopenharmony_ci uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1); 573800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop)); 574800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest005: GetStackRange."; 575800b99b8Sopenharmony_ci 576800b99b8Sopenharmony_ci UnwindContext context; 577800b99b8Sopenharmony_ci context.pid = UNWIND_TYPE_LOCAL; 578800b99b8Sopenharmony_ci context.stackCheck = false; 579800b99b8Sopenharmony_ci context.stackBottom = stackBottom; 580800b99b8Sopenharmony_ci context.stackTop = stackTop; 581800b99b8Sopenharmony_ci 582800b99b8Sopenharmony_ci auto regs = DfxRegs::Create(); 583800b99b8Sopenharmony_ci auto regsData = regs->RawData(); 584800b99b8Sopenharmony_ci GetLocalRegs(regsData); 585800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 586800b99b8Sopenharmony_ci context.regs = regs; 587800b99b8Sopenharmony_ci context.maps = unwinder->GetMaps(); 588800b99b8Sopenharmony_ci 589800b99b8Sopenharmony_ci uintptr_t lr = *(regs->GetReg(REG_LR)); 590800b99b8Sopenharmony_ci uintptr_t pc = regs->GetPc(); 591800b99b8Sopenharmony_ci uintptr_t failSp = stackTop + 1; // arm cfa get from sp 592800b99b8Sopenharmony_ci regs->SetSp(failSp); 593800b99b8Sopenharmony_ci uintptr_t failFp = stackTop + 1; // arm64 cfa get from fp 594800b99b8Sopenharmony_ci regs->SetFp(failFp); 595800b99b8Sopenharmony_ci bool unwRet = unwinder->Step(pc, failSp, &context); 596800b99b8Sopenharmony_ci ASSERT_TRUE(unwRet) << "StepTest005: unwRet:" << unwRet; 597800b99b8Sopenharmony_ci ASSERT_EQ(lr, pc) << "StepTest005: lr callback"; 598800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest005: end."; 599800b99b8Sopenharmony_ci} 600800b99b8Sopenharmony_ci 601800b99b8Sopenharmony_ci/** 602800b99b8Sopenharmony_ci * @tc.name: StepTest006 603800b99b8Sopenharmony_ci * @tc.desc: test unwinder Step interface in lr callback with step failed case 604800b99b8Sopenharmony_ci * @tc.type: FUNC 605800b99b8Sopenharmony_ci */ 606800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, StepTest006, TestSize.Level2) 607800b99b8Sopenharmony_ci{ 608800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest006: start."; 609800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 610800b99b8Sopenharmony_ci uintptr_t stackBottom = 1, stackTop = static_cast<uintptr_t>(-1); 611800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->GetStackRange(stackBottom, stackTop)); 612800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest006: GetStackRange."; 613800b99b8Sopenharmony_ci 614800b99b8Sopenharmony_ci UnwindContext context; 615800b99b8Sopenharmony_ci context.pid = UNWIND_TYPE_LOCAL; 616800b99b8Sopenharmony_ci context.stackCheck = true; 617800b99b8Sopenharmony_ci context.stackBottom = stackBottom; 618800b99b8Sopenharmony_ci context.stackTop = stackTop; 619800b99b8Sopenharmony_ci 620800b99b8Sopenharmony_ci auto regs = DfxRegs::Create(); 621800b99b8Sopenharmony_ci auto regsData = regs->RawData(); 622800b99b8Sopenharmony_ci GetLocalRegs(regsData); 623800b99b8Sopenharmony_ci unwinder->SetRegs(regs); 624800b99b8Sopenharmony_ci context.regs = regs; 625800b99b8Sopenharmony_ci context.maps = unwinder->GetMaps(); 626800b99b8Sopenharmony_ci 627800b99b8Sopenharmony_ci uintptr_t lr = *(regs->GetReg(REG_LR)); 628800b99b8Sopenharmony_ci uintptr_t sp = regs->GetSp(); 629800b99b8Sopenharmony_ci uintptr_t failPc = stackTop + 1; 630800b99b8Sopenharmony_ci regs->SetPc(failPc); 631800b99b8Sopenharmony_ci bool unwRet = unwinder->Step(failPc, sp, &context); 632800b99b8Sopenharmony_ci ASSERT_TRUE(unwRet) << "StepTest006: unwRet:" << unwRet; 633800b99b8Sopenharmony_ci ASSERT_EQ(lr, failPc) << "StepTest006: lr callback"; 634800b99b8Sopenharmony_ci 635800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "StepTest006: end."; 636800b99b8Sopenharmony_ci} 637800b99b8Sopenharmony_ci#endif 638800b99b8Sopenharmony_ci 639800b99b8Sopenharmony_ci/** 640800b99b8Sopenharmony_ci * @tc.name: DfxConfigTest001 641800b99b8Sopenharmony_ci * @tc.desc: test DfxConfig class functions 642800b99b8Sopenharmony_ci * @tc.type: FUNC 643800b99b8Sopenharmony_ci */ 644800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, DfxConfigTest001, TestSize.Level2) 645800b99b8Sopenharmony_ci{ 646800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "DfxConfigTest001: start."; 647800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().displayRegister, true); 648800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().displayBacktrace, true); 649800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().displayMaps, true); 650800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().displayFaultStack, true); 651800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().dumpOtherThreads, true); 652800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().highAddressStep, 512); 653800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().lowAddressStep, 16); 654800b99b8Sopenharmony_ci ASSERT_EQ(DfxConfig::GetConfig().maxFrameNums, 256); 655800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "DfxConfigTest001: end."; 656800b99b8Sopenharmony_ci} 657800b99b8Sopenharmony_ci 658800b99b8Sopenharmony_ci/** 659800b99b8Sopenharmony_ci * @tc.name: FillFrameTest001 660800b99b8Sopenharmony_ci * @tc.desc: test unwinder FillFrame interface 661800b99b8Sopenharmony_ci * in local case 662800b99b8Sopenharmony_ci * @tc.type: FUNC 663800b99b8Sopenharmony_ci */ 664800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, FillFrameTest001, TestSize.Level2) 665800b99b8Sopenharmony_ci{ 666800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FillFrameTest001: start."; 667800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 668800b99b8Sopenharmony_ci DfxFrame frame; 669800b99b8Sopenharmony_ci unwinder->FillFrame(frame); 670800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << " when DfxFrame::map is null, frame.buildId.size() is 0"; 671800b99b8Sopenharmony_ci ASSERT_EQ(frame.buildId.size(), 0); 672800b99b8Sopenharmony_ci string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so.noexit"; 673800b99b8Sopenharmony_ci auto map = DfxMap::Create(testMap, sizeof(testMap)); 674800b99b8Sopenharmony_ci frame.map = map; 675800b99b8Sopenharmony_ci unwinder->FillFrame(frame); 676800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file not exist, frame.buildId.size() is 0"; 677800b99b8Sopenharmony_ci ASSERT_EQ(frame.buildId.size(), 0); 678800b99b8Sopenharmony_ci#ifdef __arm__ 679800b99b8Sopenharmony_ci testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so"; 680800b99b8Sopenharmony_ci#else 681800b99b8Sopenharmony_ci testMap = "7f0ab40000-7f0ab41000 r--p 00000000 b3:07 1882 /system/lib64/init/libinit_context.z.so"; 682800b99b8Sopenharmony_ci#endif 683800b99b8Sopenharmony_ci map = DfxMap::Create(testMap, sizeof(testMap)); 684800b99b8Sopenharmony_ci frame.map = map; 685800b99b8Sopenharmony_ci unwinder->FillFrame(frame); 686800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file exist, frame.buildId.size() is bigger than 0"; 687800b99b8Sopenharmony_ci ASSERT_EQ(frame.buildId.size() == 0, false); 688800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FillFrameTest001: end."; 689800b99b8Sopenharmony_ci} 690800b99b8Sopenharmony_ci 691800b99b8Sopenharmony_ci/** 692800b99b8Sopenharmony_ci * @tc.name: FillJsFrameTest001 693800b99b8Sopenharmony_ci * @tc.desc: test unwinder FillJsFrame interface 694800b99b8Sopenharmony_ci * in local case 695800b99b8Sopenharmony_ci * @tc.type: FUNC 696800b99b8Sopenharmony_ci */ 697800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, FillJsFrameTest001, TestSize.Level2) 698800b99b8Sopenharmony_ci{ 699800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FillJsFrameTest001: start."; 700800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 701800b99b8Sopenharmony_ci DfxFrame frame; 702800b99b8Sopenharmony_ci unwinder->FillJsFrame(frame); 703800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << " when DfxFrame::map is null, frame.map is nullptr"; 704800b99b8Sopenharmony_ci ASSERT_EQ(frame.map, nullptr); 705800b99b8Sopenharmony_ci string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so"; 706800b99b8Sopenharmony_ci auto map = DfxMap::Create(testMap, sizeof(testMap)); 707800b99b8Sopenharmony_ci frame.map = map; 708800b99b8Sopenharmony_ci unwinder->FillJsFrame(frame); 709800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << " when DfxFrame::map is not null and file exist, frame.map.GetHap is not nullptr"; 710800b99b8Sopenharmony_ci ASSERT_NE(frame.map->GetHap(), nullptr); 711800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FillJsFrameTest001: end."; 712800b99b8Sopenharmony_ci} 713800b99b8Sopenharmony_ci 714800b99b8Sopenharmony_ci/** 715800b99b8Sopenharmony_ci * @tc.name: FillFramesTest001 716800b99b8Sopenharmony_ci * @tc.desc: test unwinder FillFrames interface 717800b99b8Sopenharmony_ci * in local case 718800b99b8Sopenharmony_ci * @tc.type: FUNC 719800b99b8Sopenharmony_ci */ 720800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, FillFramesTest001, TestSize.Level2) 721800b99b8Sopenharmony_ci{ 722800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FillFramesTest001: start."; 723800b99b8Sopenharmony_ci#ifdef __arm__ 724800b99b8Sopenharmony_ci const string testMap = "f6d83000-f6d84000 r--p 00001000 b3:07 1892 /system/lib/init/libinit_context.z.so"; 725800b99b8Sopenharmony_ci#else 726800b99b8Sopenharmony_ci const string testMap = "7f0ab40000-7f0ab41000 r--p 00000000 b3:07 1882 /system/lib64/init/libinit_context.z.so"; 727800b99b8Sopenharmony_ci#endif 728800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 729800b99b8Sopenharmony_ci std::vector<DfxFrame> frames; 730800b99b8Sopenharmony_ci DfxFrame frame; 731800b99b8Sopenharmony_ci auto map = DfxMap::Create(testMap, sizeof(testMap)); 732800b99b8Sopenharmony_ci frame.map = map; 733800b99b8Sopenharmony_ci frames.push_back(frame); 734800b99b8Sopenharmony_ci ASSERT_EQ(frames[0].buildId.size(), 0); 735800b99b8Sopenharmony_ci unwinder->FillFrames(frames); 736800b99b8Sopenharmony_ci ASSERT_EQ(frames[0].buildId.size() == 0, false); 737800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "FillFramesTest001: end."; 738800b99b8Sopenharmony_ci} 739800b99b8Sopenharmony_ci 740800b99b8Sopenharmony_ci#if defined(__arm__) || defined(__aarch64__) 741800b99b8Sopenharmony_ci/** 742800b99b8Sopenharmony_ci * @tc.name: UnwindLocalWithContextTest001 743800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocalWithContext interface 744800b99b8Sopenharmony_ci * in local case 745800b99b8Sopenharmony_ci * @tc.type: FUNC 746800b99b8Sopenharmony_ci */ 747800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindLocalWithContextTest001, TestSize.Level2) 748800b99b8Sopenharmony_ci{ 749800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: start."; 750800b99b8Sopenharmony_ci auto regs = DfxRegs::Create(); 751800b99b8Sopenharmony_ci auto regsData = regs->RawData(); 752800b99b8Sopenharmony_ci GetLocalRegs(regsData); 753800b99b8Sopenharmony_ci ucontext_t context; 754800b99b8Sopenharmony_ci (void)memset_s(&context, sizeof(context), 0, sizeof(context)); 755800b99b8Sopenharmony_ci#ifdef __arm__ 756800b99b8Sopenharmony_ci context.uc_mcontext.arm_r0 = *(regs->GetReg(REG_ARM_R0)); 757800b99b8Sopenharmony_ci context.uc_mcontext.arm_r1 = *(regs->GetReg(REG_ARM_R1)); 758800b99b8Sopenharmony_ci context.uc_mcontext.arm_r2 = *(regs->GetReg(REG_ARM_R2)); 759800b99b8Sopenharmony_ci context.uc_mcontext.arm_r3 = *(regs->GetReg(REG_ARM_R3)); 760800b99b8Sopenharmony_ci context.uc_mcontext.arm_r4 = *(regs->GetReg(REG_ARM_R4)); 761800b99b8Sopenharmony_ci context.uc_mcontext.arm_r5 = *(regs->GetReg(REG_ARM_R5)); 762800b99b8Sopenharmony_ci context.uc_mcontext.arm_r6 = *(regs->GetReg(REG_ARM_R6)); 763800b99b8Sopenharmony_ci context.uc_mcontext.arm_r7 = *(regs->GetReg(REG_ARM_R7)); 764800b99b8Sopenharmony_ci context.uc_mcontext.arm_r8 = *(regs->GetReg(REG_ARM_R8)); 765800b99b8Sopenharmony_ci context.uc_mcontext.arm_r9 = *(regs->GetReg(REG_ARM_R9)); 766800b99b8Sopenharmony_ci context.uc_mcontext.arm_r10 = *(regs->GetReg(REG_ARM_R10)); 767800b99b8Sopenharmony_ci context.uc_mcontext.arm_fp = *(regs->GetReg(REG_ARM_R11)); 768800b99b8Sopenharmony_ci context.uc_mcontext.arm_ip = *(regs->GetReg(REG_ARM_R12)); 769800b99b8Sopenharmony_ci context.uc_mcontext.arm_sp = *(regs->GetReg(REG_ARM_R13)); 770800b99b8Sopenharmony_ci context.uc_mcontext.arm_lr = *(regs->GetReg(REG_ARM_R14)); 771800b99b8Sopenharmony_ci context.uc_mcontext.arm_pc = *(regs->GetReg(REG_ARM_R15)); 772800b99b8Sopenharmony_ci#else 773800b99b8Sopenharmony_ci for (int i = 0; i < REG_LAST; ++i) { 774800b99b8Sopenharmony_ci context.uc_mcontext.regs[i] = *(regs->GetReg(i)); 775800b99b8Sopenharmony_ci } 776800b99b8Sopenharmony_ci#endif 777800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 778800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->UnwindLocalWithContext(context)); 779800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 780800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 781800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: frames:\n" << Unwinder::GetFramesStr(frames); 782800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalWithContextTest001: end."; 783800b99b8Sopenharmony_ci} 784800b99b8Sopenharmony_ci#endif 785800b99b8Sopenharmony_ci 786800b99b8Sopenharmony_cistatic int32_t g_tid = 0; 787800b99b8Sopenharmony_cistatic std::mutex g_mutex; 788800b99b8Sopenharmony_ci__attribute__((noinline)) void ThreadTest002() 789800b99b8Sopenharmony_ci{ 790800b99b8Sopenharmony_ci printf("ThreadTest002\n"); 791800b99b8Sopenharmony_ci g_mutex.lock(); 792800b99b8Sopenharmony_ci g_mutex.unlock(); 793800b99b8Sopenharmony_ci} 794800b99b8Sopenharmony_ci 795800b99b8Sopenharmony_ci__attribute__((noinline)) void ThreadTest001() 796800b99b8Sopenharmony_ci{ 797800b99b8Sopenharmony_ci g_tid = gettid(); 798800b99b8Sopenharmony_ci printf("ThreadTest001: tid: %d\n", g_tid); 799800b99b8Sopenharmony_ci ThreadTest002(); 800800b99b8Sopenharmony_ci} 801800b99b8Sopenharmony_ci 802800b99b8Sopenharmony_ci/** 803800b99b8Sopenharmony_ci * @tc.name: UnwindLocalWithTidTest001 804800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocalWithTid interface 805800b99b8Sopenharmony_ci * in local case 806800b99b8Sopenharmony_ci * @tc.type: FUNC 807800b99b8Sopenharmony_ci */ 808800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindLocalWithTidTest001, TestSize.Level2) 809800b99b8Sopenharmony_ci{ 810800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalWithTidTest001: start."; 811800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 812800b99b8Sopenharmony_ci g_mutex.lock(); 813800b99b8Sopenharmony_ci std::thread unwThread(ThreadTest001); 814800b99b8Sopenharmony_ci sleep(1); 815800b99b8Sopenharmony_ci if (g_tid <= 0) { 816800b99b8Sopenharmony_ci FAIL() << "UnwindLocalWithTidTest001: Failed to create child thread.\n"; 817800b99b8Sopenharmony_ci } 818800b99b8Sopenharmony_ci ASSERT_TRUE(unwinder->UnwindLocalWithTid(g_tid)); 819800b99b8Sopenharmony_ci#if defined(__aarch64__) 820800b99b8Sopenharmony_ci auto pcs = unwinder->GetPcs(); 821800b99b8Sopenharmony_ci std::vector<DfxFrame> frames; 822800b99b8Sopenharmony_ci unwinder->GetFramesByPcs(frames, pcs); 823800b99b8Sopenharmony_ci#else 824800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 825800b99b8Sopenharmony_ci#endif 826800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 1); 827800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalWithTidTest001: frames:\n" << Unwinder::GetFramesStr(frames); 828800b99b8Sopenharmony_ci g_mutex.unlock(); 829800b99b8Sopenharmony_ci g_tid = 0; 830800b99b8Sopenharmony_ci if (unwThread.joinable()) { 831800b99b8Sopenharmony_ci unwThread.join(); 832800b99b8Sopenharmony_ci } 833800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalWithTidTest001: end."; 834800b99b8Sopenharmony_ci} 835800b99b8Sopenharmony_ci 836800b99b8Sopenharmony_ci#if defined(__x86_64__) 837800b99b8Sopenharmony_cistatic _Unwind_Reason_Code TraceFunc(_Unwind_Context *ctx, void *d) 838800b99b8Sopenharmony_ci{ 839800b99b8Sopenharmony_ci int *depth = (int*)d; 840800b99b8Sopenharmony_ci printf("\t#%d: program counter at %p\n", *depth, reinterpret_cast<void *>(_Unwind_GetIP(ctx))); 841800b99b8Sopenharmony_ci (*depth)++; 842800b99b8Sopenharmony_ci return _URC_NO_REASON; 843800b99b8Sopenharmony_ci} 844800b99b8Sopenharmony_ci 845800b99b8Sopenharmony_cistatic void PrintUnwindBacktrace() 846800b99b8Sopenharmony_ci{ 847800b99b8Sopenharmony_ci int depth = 0; 848800b99b8Sopenharmony_ci _Unwind_Backtrace(&TraceFunc, &depth); 849800b99b8Sopenharmony_ci} 850800b99b8Sopenharmony_ci 851800b99b8Sopenharmony_ci/** 852800b99b8Sopenharmony_ci * @tc.name: UnwindLocalX86_64Test001 853800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindLocal interface 854800b99b8Sopenharmony_ci * @tc.type: FUNC 855800b99b8Sopenharmony_ci */ 856800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindLocalX86_64Test001, TestSize.Level2) 857800b99b8Sopenharmony_ci{ 858800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalX86_64Test001: start."; 859800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 860800b99b8Sopenharmony_ci if (unwinder->UnwindLocal()) { 861800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 862800b99b8Sopenharmony_ci printf("Unwinder frame size: %zu\n", frames.size()); 863800b99b8Sopenharmony_ci auto framesStr = Unwinder::GetFramesStr(frames); 864800b99b8Sopenharmony_ci printf("Unwinder frames:\n%s\n", framesStr.c_str()); 865800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 0); 866800b99b8Sopenharmony_ci } 867800b99b8Sopenharmony_ci 868800b99b8Sopenharmony_ci PrintUnwindBacktrace(); 869800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalX86_64Test001: end."; 870800b99b8Sopenharmony_ci} 871800b99b8Sopenharmony_ci 872800b99b8Sopenharmony_ci/** 873800b99b8Sopenharmony_ci * @tc.name: UnwindRemoteX86_64Test001 874800b99b8Sopenharmony_ci * @tc.desc: test unwinder UnwindRemote interface 875800b99b8Sopenharmony_ci * @tc.type: FUNC 876800b99b8Sopenharmony_ci */ 877800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwindRemoteX86_64Test001, TestSize.Level2) 878800b99b8Sopenharmony_ci{ 879800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindLocalX86_64Test001: start."; 880800b99b8Sopenharmony_ci const pid_t initPid = 1; 881800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(initPid); 882800b99b8Sopenharmony_ci DfxPtrace::Attach(initPid); 883800b99b8Sopenharmony_ci if (unwinder->UnwindRemote(initPid)) { 884800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 885800b99b8Sopenharmony_ci printf("Unwinder frame size: %zu\n", frames.size()); 886800b99b8Sopenharmony_ci auto framesStr = Unwinder::GetFramesStr(frames); 887800b99b8Sopenharmony_ci printf("Unwinder frames:\n%s\n", framesStr.c_str()); 888800b99b8Sopenharmony_ci ASSERT_GT(frames.size(), 0); 889800b99b8Sopenharmony_ci } 890800b99b8Sopenharmony_ci DfxPtrace::Detach(initPid); 891800b99b8Sopenharmony_ci 892800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwindRemoteX86_64Test001: end."; 893800b99b8Sopenharmony_ci} 894800b99b8Sopenharmony_ci#endif 895800b99b8Sopenharmony_ci 896800b99b8Sopenharmony_ci/** 897800b99b8Sopenharmony_ci * @tc.name: GetSymbolByPcTest001 898800b99b8Sopenharmony_ci * @tc.desc: test unwinder GetSymbolByPc interface 899800b99b8Sopenharmony_ci * in local case 900800b99b8Sopenharmony_ci * @tc.type: FUNC 901800b99b8Sopenharmony_ci */ 902800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, GetSymbolByPcTest001, TestSize.Level2) 903800b99b8Sopenharmony_ci{ 904800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetSymbolByPcTest001: start."; 905800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 906800b99b8Sopenharmony_ci unwinder->UnwindLocal(); 907800b99b8Sopenharmony_ci auto frames = unwinder->GetFrames(); 908800b99b8Sopenharmony_ci uintptr_t pc0 = static_cast<uintptr_t>(frames[0].pc); 909800b99b8Sopenharmony_ci std::string funcName; 910800b99b8Sopenharmony_ci uint64_t funcOffset; 911800b99b8Sopenharmony_ci std::shared_ptr<DfxMaps> maps = std::make_shared<DfxMaps>(); 912800b99b8Sopenharmony_ci ASSERT_FALSE(unwinder->GetSymbolByPc(0x00000000, maps, funcName, funcOffset)); // Find map is null 913800b99b8Sopenharmony_ci ASSERT_FALSE(unwinder->GetSymbolByPc(pc0, maps, funcName, funcOffset)); // Get elf is null 914800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "GetSymbolByPcTest001: end."; 915800b99b8Sopenharmony_ci} 916800b99b8Sopenharmony_ci 917800b99b8Sopenharmony_ci/** 918800b99b8Sopenharmony_ci * @tc.name: AccessMemTest001 919800b99b8Sopenharmony_ci * @tc.desc: test unwinder AccessMem interface 920800b99b8Sopenharmony_ci * @tc.type: FUNC 921800b99b8Sopenharmony_ci */ 922800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, AccessMemTest001, TestSize.Level2) 923800b99b8Sopenharmony_ci{ 924800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "AccessMemTest001: start."; 925800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(); 926800b99b8Sopenharmony_ci auto acc = std::make_shared<DfxAccessorsLocal>(); 927800b99b8Sopenharmony_ci auto memory = std::make_shared<DfxMemory>(acc); 928800b99b8Sopenharmony_ci uintptr_t val; 929800b99b8Sopenharmony_ci EXPECT_FALSE(memory->ReadReg(0, &val)); 930800b99b8Sopenharmony_ci uintptr_t regs[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa}; 931800b99b8Sopenharmony_ci UnwindContext ctx; 932800b99b8Sopenharmony_ci ctx.regs = DfxRegs::CreateFromRegs(UnwindMode::DWARF_UNWIND, regs, sizeof(regs) / sizeof(regs[0])); 933800b99b8Sopenharmony_ci memory->SetCtx(&ctx); 934800b99b8Sopenharmony_ci EXPECT_FALSE(memory->ReadReg(-1, &val)); 935800b99b8Sopenharmony_ci 936800b99b8Sopenharmony_ci uint8_t values[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}; 937800b99b8Sopenharmony_ci uintptr_t addr = reinterpret_cast<uintptr_t>(&values[0]); 938800b99b8Sopenharmony_ci EXPECT_FALSE(unwinder->AccessMem(&memory, addr, nullptr)); 939800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "AccessMemTest001: end."; 940800b99b8Sopenharmony_ci} 941800b99b8Sopenharmony_ci 942800b99b8Sopenharmony_ci/** 943800b99b8Sopenharmony_ci * @tc.name: UnwinderTest001 944800b99b8Sopenharmony_ci * @tc.desc: test Unwinder::xxxx interface 945800b99b8Sopenharmony_ci * @tc.type: FUNC 946800b99b8Sopenharmony_ci */ 947800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderTest001, TestSize.Level2) 948800b99b8Sopenharmony_ci{ 949800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderTest001: start."; 950800b99b8Sopenharmony_ci auto unwinder = std::make_shared<Unwinder>(getpid()); 951800b99b8Sopenharmony_ci unwinder->EnableUnwindCache(false); 952800b99b8Sopenharmony_ci unwinder->EnableFpCheckMapExec(false); 953800b99b8Sopenharmony_ci auto regs = unwinder->GetRegs(); 954800b99b8Sopenharmony_ci ASSERT_EQ(regs, nullptr); 955800b99b8Sopenharmony_ci DfxFrame frame; 956800b99b8Sopenharmony_ci unwinder->FillFrame(frame); 957800b99b8Sopenharmony_ci unwinder->AddFrame(frame); 958800b99b8Sopenharmony_ci unwinder->ArkWriteJitCodeToFile(1); 959800b99b8Sopenharmony_ci auto jitCache = unwinder->GetJitCache(); 960800b99b8Sopenharmony_ci ASSERT_EQ(jitCache.size(), 0); 961800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderTest001: end."; 962800b99b8Sopenharmony_ci} 963800b99b8Sopenharmony_ci 964800b99b8Sopenharmony_ci/** 965800b99b8Sopenharmony_ci * @tc.name: UnwinderTest002 966800b99b8Sopenharmony_ci * @tc.desc: test DfxFrameFormatter GetFrameStr 967800b99b8Sopenharmony_ci * @tc.type: FUNC 968800b99b8Sopenharmony_ci */ 969800b99b8Sopenharmony_ciHWTEST_F(UnwinderTest, UnwinderTest002, TestSize.Level2) 970800b99b8Sopenharmony_ci{ 971800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderTest002: start."; 972800b99b8Sopenharmony_ci std::shared_ptr<DfxFrame> frame = nullptr; 973800b99b8Sopenharmony_ci std::string str = DfxFrameFormatter::GetFrameStr(frame); 974800b99b8Sopenharmony_ci ASSERT_EQ(str, ""); 975800b99b8Sopenharmony_ci std::vector<std::shared_ptr<DfxFrame>> frames; 976800b99b8Sopenharmony_ci str = DfxFrameFormatter::GetFramesStr(frames); 977800b99b8Sopenharmony_ci ASSERT_EQ(str, ""); 978800b99b8Sopenharmony_ci GTEST_LOG_(INFO) << "UnwinderTest002: end."; 979800b99b8Sopenharmony_ci} 980800b99b8Sopenharmony_ci} // namespace HiviewDFX 981800b99b8Sopenharmony_ci} // namepsace OHOS 982800b99b8Sopenharmony_ci 983