1 /* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #include <gtest/gtest.h> 16 17 #include <cstdio> 18 #include <dlfcn.h> 19 #include <cstdint> 20 21 #include "dfx_maps.h" 22 #include "dfx_memory.h" 23 #include "dfx_ptrace.h" 24 #include "dfx_regs.h" 25 #include "dfx_regs_get.h" 26 #include "dfx_test_util.h" 27 #include "unwind_context.h" 28 #include "unwind_define.h" 29 #include "unwind_entry_parser_factory.h" 30 31 32 using namespace testing; 33 using namespace testing::ext; 34 using namespace std; 35 36 namespace OHOS { 37 namespace HiviewDFX { 38 class UnwindEntryParserTest : public testing::Test { 39 public: SetUpTestCase()40 static void SetUpTestCase() {} TearDownTestCase()41 static void TearDownTestCase() {} SetUp()42 void SetUp() {} TearDown()43 void TearDown() {} 44 }; 45 46 /** 47 * @tc.name: UnwindEntryParser001 48 * @tc.desc: test UnwindEntryParser in local case 49 * @tc.type: FUNC 50 */ 51 HWTEST_F(UnwindEntryParserTest, UnwindEntryParseTest001, TestSize.Level2) 52 { 53 GTEST_LOG_(INFO) << "UnwindEntryParser001: start."; 54 auto regs = DfxRegs::Create(); 55 auto regsData = regs->RawData(); 56 GetLocalRegs(regsData); 57 UnwindContext context; 58 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_LOCAL); 59 memory->SetCtx(&context); 60 UnwindTableInfo uti; 61 ASSERT_TRUE(memory->FindUnwindTable(regs->GetPc(), uti) == UNW_ERROR_NONE); 62 auto unwindEntryParser = UnwindEntryParserFactory::CreateUnwindEntryParser(memory); 63 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>(); 64 ASSERT_TRUE(unwindEntryParser->Step(regs->GetPc(), uti, rs)); 65 GTEST_LOG_(INFO) << "UnwindEntryParser001: end."; 66 } 67 68 /** 69 * @tc.name: UnwindEntryParser002 70 * @tc.desc: test UnwindEntryParser in remote case 71 * @tc.type: FUNC 72 */ 73 HWTEST_F(UnwindEntryParserTest, UnwindEntryParseTest002, TestSize.Level2) 74 { 75 GTEST_LOG_(INFO) << "UnwindEntryParser002: start."; 76 pid_t childPid = fork(); 77 if (childPid != 0) { 78 ASSERT_TRUE(DfxPtrace::Attach(childPid)); 79 auto regs = DfxRegs::CreateRemoteRegs(childPid); 80 UnwindContext context; 81 context.pid = childPid; 82 context.regs = regs; 83 context.maps = DfxMaps::Create(childPid); 84 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_REMOTE); 85 memory->SetCtx(&context); 86 std::shared_ptr<DfxMap> map = nullptr; 87 uintptr_t pc = regs->GetPc(); 88 ASSERT_TRUE(memory->GetMapByPc(pc, map) == UNW_ERROR_NONE); 89 UnwindTableInfo uti; 90 ASSERT_TRUE(memory->FindUnwindTable(pc, uti) == UNW_ERROR_NONE); 91 auto unwindEntryParser = UnwindEntryParserFactory::CreateUnwindEntryParser(memory); 92 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>(); 93 ASSERT_TRUE(unwindEntryParser->Step(pc, uti, rs)); 94 DfxPtrace::Detach(childPid); 95 } else { 96 const int sleepTime = 2; 97 sleep(sleepTime); 98 _exit(0); 99 } 100 GTEST_LOG_(INFO) << "UnwindEntryParser002: end."; 101 } 102 103 /** 104 * @tc.name: UnwindEntryParser003 105 * @tc.desc: test UnwindEntryParser in abnomal case 106 * @tc.type: FUNC 107 */ 108 HWTEST_F(UnwindEntryParserTest, UnwindEntryParseTest003, TestSize.Level2) 109 { 110 GTEST_LOG_(INFO) << "UnwindEntryParser003: start."; 111 std::shared_ptr <DfxMemory> memory = nullptr; 112 int pc = 0; 113 auto unwindEntryParser = UnwindEntryParserFactory::CreateUnwindEntryParser(memory); 114 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>(); 115 UnwindTableInfo uti; 116 ASSERT_FALSE(unwindEntryParser->Step(pc, uti, rs)); 117 GTEST_LOG_(INFO) << "UnwindEntryParser003: end."; 118 } 119 120 /** 121 * @tc.name: UnwindEntryParser004 122 * @tc.desc: test UnwindEntryParser in abnomal pc case 123 * @tc.type: FUNC 124 */ 125 HWTEST_F(UnwindEntryParserTest, UnwindEntryParseTest004, TestSize.Level2) 126 { 127 GTEST_LOG_(INFO) << "UnwindEntryParser004: start."; 128 pid_t childPid = fork(); 129 if (childPid != 0) { 130 ASSERT_TRUE(DfxPtrace::Attach(childPid)); 131 auto regs = DfxRegs::CreateRemoteRegs(childPid); 132 UnwindContext context; 133 context.pid = childPid; 134 context.regs = regs; 135 context.maps = DfxMaps::Create(childPid); 136 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_REMOTE); 137 memory->SetCtx(&context); 138 uintptr_t pc = regs->GetPc(); 139 std::shared_ptr<DfxMap> map = nullptr; 140 ASSERT_TRUE(memory->GetMapByPc(pc, map) == UNW_ERROR_NONE); 141 UnwindTableInfo uti; 142 ASSERT_TRUE(memory->FindUnwindTable(pc, uti) == UNW_ERROR_NONE); 143 auto unwindEntryParser = UnwindEntryParserFactory::CreateUnwindEntryParser(memory); 144 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>(); 145 ASSERT_FALSE(unwindEntryParser->Step(0, uti, rs)); 146 DfxPtrace::Detach(childPid); 147 } else { 148 const int sleepTime = 2; 149 sleep(sleepTime); 150 _exit(0); 151 } 152 GTEST_LOG_(INFO) << "UnwindEntryParser004: end."; 153 } 154 155 /** 156 * @tc.name: UnwindEntryParser005 157 * @tc.desc: test UnwindEntryParser in abnomal UnwindTableInfo case 158 * @tc.type: FUNC 159 */ 160 HWTEST_F(UnwindEntryParserTest, UnwindEntryParseTest005, TestSize.Level2) 161 { 162 GTEST_LOG_(INFO) << "UnwindEntryParser005: start."; 163 pid_t childPid = fork(); 164 if (childPid != 0) { 165 ASSERT_TRUE(DfxPtrace::Attach(childPid)); 166 auto regs = DfxRegs::CreateRemoteRegs(childPid); 167 UnwindContext context; 168 context.pid = childPid; 169 context.regs = regs; 170 context.maps = DfxMaps::Create(childPid); 171 auto memory = std::make_shared<DfxMemory>(UNWIND_TYPE_REMOTE); 172 memory->SetCtx(&context); 173 auto unwindEntryParser = UnwindEntryParserFactory::CreateUnwindEntryParser(memory); 174 UnwindTableInfo uti; 175 std::shared_ptr<RegLocState> rs = std::make_shared<RegLocState>(); 176 ASSERT_FALSE(unwindEntryParser->Step(regs->GetPc(), uti, rs)); 177 DfxPtrace::Detach(childPid); 178 } else { 179 const int sleepTime = 2; 180 sleep(sleepTime); 181 _exit(0); 182 } 183 GTEST_LOG_(INFO) << "UnwindEntryParser005: end."; 184 } 185 } 186 }