1 /* 2 * Copyright (c) 2022 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 16 #include <gtest/gtest.h> 17 #include <ctime> 18 #include <securec.h> 19 #include <string> 20 #include <vector> 21 #include <iostream> 22 #include <filesystem> 23 #include "elf_factory.h" 24 #include "elf_imitate.h" 25 #include "unwinder_config.h" 26 27 using namespace OHOS::HiviewDFX; 28 using namespace testing::ext; 29 using namespace std; 30 31 #define ELF32_FILE "/data/test/resource/testdata/elf32_test" 32 #define ELF64_FILE "/data/test/resource/testdata/elf_test" 33 #define DUMPCATCHER_ELF_FILE "/system/bin/dumpcatcher" 34 namespace OHOS { 35 namespace HiviewDFX { 36 class DfxSymbolsTest : public testing::Test { 37 public: SetUpTestCase(void)38 static void SetUpTestCase(void) {} TearDownTestCase(void)39 static void TearDownTestCase(void) {} SetUp()40 void SetUp() {} TearDown()41 void TearDown() {} 42 }; 43 44 45 /** 46 * @tc.name: DfxSymbolsTest001 47 * @tc.desc: test DfxSymbols functions with 32 bit ELF 48 * @tc.type: FUNC 49 */ 50 HWTEST_F(DfxSymbolsTest, DfxSymbolsTest001, TestSize.Level2) 51 { 52 GTEST_LOG_(INFO) << "DfxSymbolsTest001: start."; 53 RegularElfFactory factory(ELF32_FILE); 54 auto elf = factory.Create(); 55 ASSERT_TRUE(elf->IsValid()); 56 ElfImitate elfImitate; 57 elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF32); 58 std::string funcName; 59 uint64_t funcOffset; 60 ASSERT_TRUE(DfxSymbols::GetFuncNameAndOffsetByPc(0x00001786, elf, funcName, funcOffset)); 61 GTEST_LOG_(INFO) << funcName << " " << funcOffset; 62 std::vector<DfxSymbol> symbols; 63 std::vector<DfxSymbol> symbolsImitate; 64 ASSERT_TRUE(DfxSymbols::ParseSymbols(symbols, elf, ELF32_FILE)); 65 ASSERT_TRUE(elfImitate.ParseSymbols(symbolsImitate, ELF32_FILE)); 66 ASSERT_EQ(symbols.size(), symbolsImitate.size()); 67 for (size_t i = 0; i < symbolsImitate.size(); ++i) { 68 symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_; 69 symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_; 70 symbols[i].name_ = symbolsImitate[i].name_; 71 symbols[i].demangle_ = symbolsImitate[i].demangle_; 72 symbols[i].module_ = symbolsImitate[i].module_; 73 } 74 75 DfxSymbols::AddSymbolsByPlt(symbols, elf, ELF32_FILE); 76 elfImitate.AddSymbolsByPlt(symbolsImitate, ELF32_FILE); 77 ASSERT_EQ(symbols.size(), symbolsImitate.size()); 78 for (size_t i = 0; i < symbolsImitate.size(); ++i) { 79 symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_; 80 symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_; 81 symbols[i].name_ = symbolsImitate[i].name_; 82 symbols[i].demangle_ = symbolsImitate[i].demangle_; 83 symbols[i].module_ = symbolsImitate[i].module_; 84 } 85 ASSERT_FALSE(DfxSymbols::ParseSymbols(symbols, nullptr, ELF32_FILE)); 86 elf->SetBaseOffset(0x1000); 87 ASSERT_TRUE(DfxSymbols::ParseSymbols(symbols, elf, ELF32_FILE)); 88 ASSERT_FALSE(DfxSymbols::AddSymbolsByPlt(symbols, nullptr, ELF32_FILE)); 89 GTEST_LOG_(INFO) << symbols[0].module_; 90 GTEST_LOG_(INFO) << "DfxSymbolsTest001: end."; 91 } 92 93 /** 94 * @tc.name: DfxSymbolsTest002 95 * @tc.desc: test DfxSymbols functions with 64 bit ELF 96 * @tc.type: FUNC 97 */ 98 HWTEST_F(DfxSymbolsTest, DfxSymbolsTest002, TestSize.Level2) 99 { 100 GTEST_LOG_(INFO) << "DfxSymbolsTest002: start."; 101 RegularElfFactory factory(ELF64_FILE); 102 auto elf = factory.Create(); 103 ASSERT_TRUE(elf->IsValid()); 104 ElfImitate elfImitate; 105 elfImitate.ParseAllHeaders(ElfImitate::ElfFileType::ELF64); 106 std::string funcName; 107 uint64_t funcOffset; 108 ASSERT_TRUE(DfxSymbols::GetFuncNameAndOffsetByPc(0x00002a08, elf, funcName, funcOffset)); 109 GTEST_LOG_(INFO) << funcName << " " << funcOffset; 110 std::vector<DfxSymbol> symbols; 111 std::vector<DfxSymbol> symbolsImitate; 112 ASSERT_TRUE(DfxSymbols::ParseSymbols(symbols, elf, ELF64_FILE)); 113 ASSERT_TRUE(elfImitate.ParseSymbols(symbolsImitate, ELF64_FILE)); 114 ASSERT_EQ(symbols.size(), symbolsImitate.size()); 115 for (size_t i = 0; i < symbolsImitate.size(); ++i) { 116 symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_; 117 symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_; 118 symbols[i].name_ = symbolsImitate[i].name_; 119 symbols[i].demangle_ = symbolsImitate[i].demangle_; 120 symbols[i].module_ = symbolsImitate[i].module_; 121 } 122 123 DfxSymbols::AddSymbolsByPlt(symbols, elf, ELF64_FILE); 124 elfImitate.AddSymbolsByPlt(symbolsImitate, ELF64_FILE); 125 ASSERT_EQ(symbols.size(), symbolsImitate.size()); 126 for (size_t i = 0; i < symbolsImitate.size(); ++i) { 127 symbols[i].fileVaddr_ = symbolsImitate[i].fileVaddr_; 128 symbols[i].funcVaddr_ = symbolsImitate[i].funcVaddr_; 129 symbols[i].name_ = symbolsImitate[i].name_; 130 symbols[i].demangle_ = symbolsImitate[i].demangle_; 131 symbols[i].module_ = symbolsImitate[i].module_; 132 } 133 ASSERT_FALSE(DfxSymbols::ParseSymbols(symbols, nullptr, ELF64_FILE)); 134 elf->SetBaseOffset(0x1000); 135 ASSERT_TRUE(DfxSymbols::ParseSymbols(symbols, elf, ELF64_FILE)); 136 ASSERT_FALSE(DfxSymbols::AddSymbolsByPlt(symbols, nullptr, ELF64_FILE)); 137 GTEST_LOG_(INFO) << symbols[0].module_; 138 GTEST_LOG_(INFO) << "DfxSymbolsTest002: end."; 139 } 140 141 #if defined(ENABLE_MINIDEBUGINFO) 142 /** 143 * @tc.name: DfxSymbolsTest003 144 * @tc.desc: test DfxSymbols functions with minidebuginfo elf 145 * @tc.type: FUNC 146 */ 147 HWTEST_F(DfxSymbolsTest, DfxSymbolsTest003, TestSize.Level2) 148 { 149 GTEST_LOG_(INFO) << "DfxSymbolsTest003: start."; 150 UnwinderConfig::SetEnableMiniDebugInfo(true); 151 std::vector<DfxSymbol> dfxSymbols; 152 RegularElfFactory factory(DUMPCATCHER_ELF_FILE); 153 auto elf = factory.Create(); 154 ASSERT_TRUE(elf->IsValid()); 155 DfxSymbols::ParseSymbols(dfxSymbols, elf, DUMPCATCHER_ELF_FILE); 156 GTEST_LOG_(INFO) << "DfxSymbolsTest003: symbols size:" << dfxSymbols.size(); 157 ASSERT_GE(dfxSymbols.size(), 0); 158 for (auto dfxSymbol : dfxSymbols) { 159 GTEST_LOG_(INFO) << "DfxSymbolsTest003: dfxSymbol.demangle_: "<< dfxSymbol.demangle_; 160 } 161 GTEST_LOG_(INFO) << "DfxSymbolsTest003: end."; 162 } 163 #endif 164 165 /** 166 * @tc.name: DfxDemangleTest001 167 * @tc.desc: test DfxSymbols demangle functions 168 * @tc.type: FUNC 169 */ 170 HWTEST_F(DfxSymbolsTest, DfxDemangleTest001, TestSize.Level2) 171 { 172 GTEST_LOG_(INFO) << "DfxDemangleTest001: start."; 173 EXPECT_EQ("", DfxSymbols::Demangle("")); 174 EXPECT_EQ("a", DfxSymbols::Demangle("a")); 175 EXPECT_EQ("_", DfxSymbols::Demangle("_")); 176 EXPECT_EQ("ab", DfxSymbols::Demangle("ab")); 177 EXPECT_EQ("abc", DfxSymbols::Demangle("abc")); 178 EXPECT_EQ("_R", DfxSymbols::Demangle("_R")); 179 EXPECT_EQ("_Z", DfxSymbols::Demangle("_Z")); 180 GTEST_LOG_(INFO) << "DfxDemangleTest001: end."; 181 } 182 183 /** 184 * @tc.name: DfxDemangleTest002 185 * @tc.desc: test DfxSymbols demangle functions with cxx 186 * @tc.type: FUNC 187 */ 188 HWTEST_F(DfxSymbolsTest, DfxDemangleTest002, TestSize.Level2) 189 { 190 GTEST_LOG_(INFO) << "DfxDemangleTest002: start."; 191 EXPECT_EQ("fake(bool)", DfxSymbols::Demangle("_Z4fakeb")); 192 EXPECT_EQ("demangle(int)", DfxSymbols::Demangle("_Z8demanglei")); 193 GTEST_LOG_(INFO) << "DfxDemangleTest002: end."; 194 } 195 196 /** 197 * @tc.name: DfxDemangleTest003 198 * @tc.desc: test DfxSymbols demangle functions with rust 199 * @tc.type: FUNC 200 */ 201 HWTEST_F(DfxSymbolsTest, DfxDemangleTest003, TestSize.Level2) 202 { 203 GTEST_LOG_(INFO) << "DfxDemangleTest003: start."; 204 EXPECT_EQ("std::rt::lang_start_internal", 205 DfxSymbols::Demangle("_RNvNtCs2WRBrrl1bb1_3std2rt19lang_start_internal")); 206 EXPECT_EQ("profcollectd::main", DfxSymbols::Demangle("_RNvCs4VPobU5SDH_12profcollectd4main")); 207 GTEST_LOG_(INFO) << "DfxDemangleTest003: end."; 208 } 209 210 /** 211 * @tc.name: DfxDemangleTest004 212 * @tc.desc: test DfxSymbols demangle functions with cangjie 213 * @tc.type: FUNC 214 */ 215 HWTEST_F(DfxSymbolsTest, DfxDemangleTest004, TestSize.Level2) 216 { 217 GTEST_LOG_(INFO) << "DfxDemangleTest004: start."; 218 std::filesystem::path runtimePath("/system/lib64/chipset-sdk/libcangjie-demangle.so"); 219 if (std::filesystem::exists(runtimePath)) { 220 EXPECT_EQ("std.time.initLocalDefault()", 221 DfxSymbols::Demangle("_CN8std.time16initLocalDefaultHv")); 222 EXPECT_EQ("std.core.Error::init()", DfxSymbols::Demangle("_CN8std.core5Error6<init>Hv")); 223 } else { 224 EXPECT_EQ("_CN8std.time16initLocalDefaultHv", 225 DfxSymbols::Demangle("_CN8std.time16initLocalDefaultHv")); 226 EXPECT_EQ("_CN8std.core5Error6<init>Hv", 227 DfxSymbols::Demangle("_CN8std.core5Error6<init>Hv")); 228 } 229 GTEST_LOG_(INFO) << "DfxDemangleTest004: end."; 230 } 231 232 /** 233 * @tc.name: DfxDemangleTest005 234 * @tc.desc: test DfxSymbols demangle functions with cangjie 235 * @tc.type: FUNC 236 */ 237 HWTEST_F(DfxSymbolsTest, DfxDemangleTest005, TestSize.Level2) 238 { 239 GTEST_LOG_(INFO) << "DfxDemangleTest005: start."; 240 CompressHapElfFactory compress1("", nullptr); 241 std::shared_ptr<DfxElf> res = compress1.Create(); 242 EXPECT_EQ(res, nullptr); 243 auto prevMap = std::shared_ptr<DfxMap>(); 244 CompressHapElfFactory compress2("", prevMap); 245 res = compress2.Create(); 246 EXPECT_EQ(res, nullptr); 247 CompressHapElfFactory compress3("/proc/", prevMap); 248 res = compress3.Create(); 249 EXPECT_EQ(res, nullptr); 250 CompressHapElfFactory compress4("/proc/123/test.hap", prevMap); 251 res = compress4.Create(); 252 EXPECT_EQ(res, nullptr); 253 GTEST_LOG_(INFO) << "DfxDemangleTest005: end."; 254 } 255 } // namespace HiviewDFX 256 } // namespace OHOS 257 258