1/* 2 * Copyright (c) 2024 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_ark.h" 22#include "dfx_log.h" 23 24using namespace testing; 25using namespace testing::ext; 26using namespace std; 27 28namespace OHOS { 29namespace HiviewDFX { 30namespace { 31const char ARK_LIB_NAME[] = "libark_jsruntime.so"; 32 33void* g_handle = nullptr; 34pthread_mutex_t g_mutex; 35int (*g_getArkNativeFrameInfoFn)(int, uintptr_t*, uintptr_t*, uintptr_t*, JsFrame*, size_t&); 36int (*g_stepArkFn)(void*, OHOS::HiviewDFX::ReadMemFunc, uintptr_t*, uintptr_t*, uintptr_t*, uintptr_t*, bool*); 37int (*g_stepArkWithJitFn)(OHOS::HiviewDFX::ArkUnwindParam*); 38int (*g_jitCodeWriteFileFn)(void*, OHOS::HiviewDFX::ReadMemFunc, int, const uintptr_t* const, const size_t); 39int (*g_parseArkFileInfoFn)(uintptr_t, uintptr_t, uintptr_t, const char*, uintptr_t, JsFunction*); 40int (*g_parseArkFrameInfoLocalFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, JsFunction*); 41int (*g_parseArkFrameInfoFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uint8_t*, uint64_t, uintptr_t, JsFunction*); 42int (*g_arkCreateJsSymbolExtractorFn)(uintptr_t*); 43int (*g_arkDestoryJsSymbolExtractorFn)(uintptr_t); 44int (*g_arkDestoryLocalFn)(); 45using RustDemangleFn = char*(*)(const char *); 46RustDemangleFn g_rustDemangleFn = nullptr; 47 48bool GetLibArkHandle() 49{ 50 if (g_handle != nullptr) { 51 return true; 52 } 53 g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY); 54 if (g_handle == nullptr) { 55 DFXLOGU("Failed to load library(%{public}s).", dlerror()); 56 return false; 57 } 58 return true; 59} 60} // namespace 61 62#define DLSYM_ARK_FUNC(FuncName, DlsymFuncName) { \ 63 pthread_mutex_lock(&g_mutex); \ 64 do { \ 65 if (!GetLibArkHandle()) { \ 66 break; \ 67 } \ 68 *reinterpret_cast<void**>(&(DlsymFuncName)) = dlsym(g_handle, (FuncName)); \ 69 } while (false); \ 70 pthread_mutex_unlock(&g_mutex); \ 71} 72 73class ArkTest : public testing::Test { 74public: 75 static void SetUpTestCase() {} 76 static void TearDownTestCase() {} 77 void SetUp() {} 78 void TearDown() {} 79}; 80 81/** 82 * @tc.name: ArkTest001 83 * @tc.desc: test ArkCreateJsSymbolExtractor functions 84 * @tc.type: FUNC 85 */ 86HWTEST_F(ArkTest, ArkTest001, TestSize.Level2) 87{ 88 GTEST_LOG_(INFO) << "ArkTest001: start."; 89 uintptr_t zero = 0; 90 uintptr_t* extractorPtr = &zero; 91 const char* arkFuncName = "ark_create_js_symbol_extractor"; 92 DLSYM_ARK_FUNC(arkFuncName, g_arkCreateJsSymbolExtractorFn) 93 ASSERT_NE(g_arkCreateJsSymbolExtractorFn, nullptr); 94 g_arkCreateJsSymbolExtractorFn(extractorPtr); 95 g_arkCreateJsSymbolExtractorFn = nullptr; 96 GTEST_LOG_(INFO) << "ArkTest001: end."; 97} 98 99/** 100 * @tc.name: ArkTest002 101 * @tc.desc: test ArkDestoryJsSymbolExtractor functions 102 * @tc.type: FUNC 103 */ 104HWTEST_F(ArkTest, ArkTest002, TestSize.Level2) 105{ 106 GTEST_LOG_(INFO) << "ArkTest002: start."; 107 uintptr_t extractorPtr = 0; 108 const char* arkFuncName = "ark_destory_js_symbol_extractor"; 109 DLSYM_ARK_FUNC(arkFuncName, g_arkDestoryJsSymbolExtractorFn) 110 ASSERT_NE(g_arkDestoryJsSymbolExtractorFn, nullptr); 111 g_arkDestoryJsSymbolExtractorFn(extractorPtr); 112 g_arkDestoryJsSymbolExtractorFn = nullptr; 113 GTEST_LOG_(INFO) << "ArkTest002: end."; 114} 115 116/** 117 * @tc.name: ArkTest003 118 * @tc.desc: test ParseArkFileInfo functions 119 * @tc.type: FUNC 120 */ 121HWTEST_F(ArkTest, ArkTest003, TestSize.Level2) 122{ 123 GTEST_LOG_(INFO) << "ArkTest003: start."; 124 uintptr_t byteCodePc = 0; 125 uintptr_t methodid = 0; 126 uintptr_t mapBase = 0; 127 const char* name = nullptr; 128 uintptr_t extractorPtr = 0; 129 JsFunction *jsFunction = nullptr; 130 const char* arkFuncName = "ark_parse_js_file_info"; 131 DLSYM_ARK_FUNC(arkFuncName, g_parseArkFileInfoFn) 132 ASSERT_NE(g_parseArkFileInfoFn, nullptr); 133 g_parseArkFileInfoFn(byteCodePc, methodid, mapBase, name, extractorPtr, jsFunction); 134 g_parseArkFileInfoFn = nullptr; 135 GTEST_LOG_(INFO) << "ArkTest003: end."; 136} 137 138/** 139 * @tc.name: ArkTest004 140 * @tc.desc: test ParseArkFrameInfoLocal functions 141 * @tc.type: FUNC 142 */ 143HWTEST_F(ArkTest, ArkTest004, TestSize.Level2) 144{ 145 GTEST_LOG_(INFO) << "ArkTest004: start."; 146 uintptr_t byteCodePc = 0; 147 uintptr_t methodid = 0; 148 uintptr_t mapBase = 0; 149 uintptr_t offset = 0; 150 JsFunction *jsFunction = nullptr; 151 const char* arkFuncName = "ark_parse_js_frame_info_local"; 152 DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoLocalFn) 153 ASSERT_NE(g_parseArkFrameInfoLocalFn, nullptr); 154 g_parseArkFrameInfoLocalFn(byteCodePc, methodid, mapBase, offset, jsFunction); 155 g_parseArkFrameInfoLocalFn = nullptr; 156 GTEST_LOG_(INFO) << "ArkTest004: end."; 157} 158 159/** 160 * @tc.name: ArkTest005 161 * @tc.desc: test ParseArkFrameInfo functions 162 * @tc.type: FUNC 163 */ 164HWTEST_F(ArkTest, ArkTest005, TestSize.Level2) 165{ 166 GTEST_LOG_(INFO) << "ArkTest005: start."; 167 uintptr_t byteCodePc = 0; 168 uintptr_t methodid = 0; 169 uintptr_t mapBase = 0; 170 uintptr_t loadOffset = 0; 171 uint8_t *data = nullptr; 172 uint64_t dataSize = 0; 173 uintptr_t extractorPtr = 0; 174 JsFunction *jsFunction = nullptr; 175 const char* arkFuncName = "ark_parse_js_frame_info"; 176 DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoFn) 177 ASSERT_NE(g_parseArkFrameInfoFn, nullptr); 178 g_parseArkFrameInfoFn(byteCodePc, methodid, mapBase, loadOffset, data, dataSize, extractorPtr, jsFunction); 179 g_parseArkFrameInfoFn = nullptr; 180 GTEST_LOG_(INFO) << "ArkTest005: end."; 181} 182 183/** 184 * @tc.name: ArkTest006 185 * @tc.desc: test StepArkFrame functions 186 * @tc.type: FUNC 187 */ 188HWTEST_F(ArkTest, ArkTest006, TestSize.Level2) 189{ 190 GTEST_LOG_(INFO) << "ArkTest006: start."; 191 pid_t pid = fork(); 192 if (pid == 0) { 193 uintptr_t zero = 0; 194 void *obj = nullptr; 195 OHOS::HiviewDFX::ReadMemFunc readMemFn = nullptr; 196 uintptr_t *fp = &zero; 197 uintptr_t *sp = &zero; 198 uintptr_t *pc = &zero; 199 uintptr_t* methodid = &zero; 200 bool *isJsFrame = nullptr; 201 const char* arkFuncName = "step_ark"; 202 DLSYM_ARK_FUNC(arkFuncName, g_stepArkFn) 203 ASSERT_NE(g_stepArkFn, nullptr); 204 g_stepArkFn(obj, readMemFn, fp, sp, pc, methodid, isJsFrame); 205 g_stepArkFn = nullptr; 206 ASSERT_NE(g_handle, nullptr); 207 const char* arkFuncName1 = "ark_destory_local"; 208 pthread_mutex_lock(&g_mutex); 209 *reinterpret_cast<void**>(&(g_arkDestoryLocalFn)) = dlsym(g_handle, arkFuncName1); 210 pthread_mutex_unlock(&g_mutex); 211 ASSERT_NE(g_arkDestoryLocalFn, nullptr); 212 g_arkDestoryLocalFn(); 213 g_arkDestoryLocalFn = nullptr; 214 exit(0); 215 } 216 int status; 217 bool isSuccess = waitpid(pid, &status, 0) != -1; 218 if (!isSuccess) { 219 ASSERT_FALSE(isSuccess); 220 return; 221 } 222 223 int exitCode = -1; 224 if (WIFEXITED(status)) { 225 exitCode = WEXITSTATUS(status); 226 printf("Exit status was %d\n", exitCode); 227 } 228 ASSERT_EQ(exitCode, 0); 229 GTEST_LOG_(INFO) << "ArkTest006: end."; 230} 231 232/** 233 * @tc.name: ArkTest007 234 * @tc.desc: test StepArkFrameWithJit functions 235 * @tc.type: FUNC 236 */ 237HWTEST_F(ArkTest, ArkTest007, TestSize.Level2) 238{ 239 GTEST_LOG_(INFO) << "ArkTest007: start."; 240 uintptr_t zero = 0; 241 void *ctx = &zero; 242 ReadMemFunc readMem = nullptr; 243 uintptr_t *fp = &zero; 244 uintptr_t *sp = &zero; 245 uintptr_t *pc = &zero; 246 uintptr_t *methodId = &zero; 247 bool *isJsFrame = nullptr; 248 std::vector<uintptr_t> vec; 249 std::vector<uintptr_t>& jitCache = vec; 250 OHOS::HiviewDFX::ArkUnwindParam ark(ctx, readMem, fp, sp, pc, methodId, isJsFrame, jitCache); 251 OHOS::HiviewDFX::ArkUnwindParam* arkPrama = &ark; 252 const char* const arkFuncName = "step_ark_with_record_jit"; 253 DLSYM_ARK_FUNC(arkFuncName, g_stepArkWithJitFn) 254 ASSERT_NE(g_stepArkWithJitFn, nullptr); 255 g_stepArkWithJitFn(arkPrama); 256 g_stepArkWithJitFn = nullptr; 257 GTEST_LOG_(INFO) << "ArkTest007: end."; 258} 259 260/** 261 * @tc.name: ArkTest008 262 * @tc.desc: test JitCodeWriteFile functions 263 * @tc.type: FUNC 264 */ 265HWTEST_F(ArkTest, ArkTest008, TestSize.Level2) 266{ 267 GTEST_LOG_(INFO) << "ArkTest008: start."; 268 void* ctx = nullptr; 269 OHOS::HiviewDFX::ReadMemFunc readMemFn = nullptr; 270 int fd = -1; 271 const uintptr_t* const jitCodeArray = nullptr; 272 const size_t jitSize = 0; 273 const char* const arkFuncName = "ark_write_jit_code"; 274 DLSYM_ARK_FUNC(arkFuncName, g_jitCodeWriteFileFn) 275 ASSERT_NE(g_jitCodeWriteFileFn, nullptr); 276 g_jitCodeWriteFileFn(ctx, readMemFn, fd, jitCodeArray, jitSize); 277 g_jitCodeWriteFileFn = nullptr; 278 GTEST_LOG_(INFO) << "ArkTest008: end."; 279} 280 281/** 282 * @tc.name: ArkTest009 283 * @tc.desc: test GetArkNativeFrameInfo functions 284 * @tc.type: FUNC 285 */ 286HWTEST_F(ArkTest, ArkTest009, TestSize.Level2) 287{ 288 GTEST_LOG_(INFO) << "ArkTest009: start."; 289 int pid = 0; 290 uintptr_t zero = 0; 291 uintptr_t& pc = zero; 292 uintptr_t& fp = zero; 293 uintptr_t& sp = zero; 294 JsFrame* frames = nullptr; 295 size_t& size = zero; 296 const char* arkFuncName = "get_ark_native_frame_info"; 297 DLSYM_ARK_FUNC(arkFuncName, g_getArkNativeFrameInfoFn) 298 ASSERT_NE(g_getArkNativeFrameInfoFn, nullptr); 299 g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size); 300 g_getArkNativeFrameInfoFn = nullptr; 301 GTEST_LOG_(INFO) << "ArkTest009: end."; 302} 303 304/** 305 * @tc.name: ArkTest010 306 * @tc.desc: test rustc_demangle functions 307 * @tc.type: FUNC 308 */ 309HWTEST_F(ArkTest, ArkTest010, TestSize.Level2) 310{ 311 GTEST_LOG_(INFO) << "ArkTest010: start."; 312 void* handle = dlopen("librustc_demangle.z.so", RTLD_LAZY | RTLD_NODELETE); 313 ASSERT_TRUE(handle) << "Failed to dlopen librustc_demangle"; 314 g_rustDemangleFn = (RustDemangleFn)dlsym(handle, "rustc_demangle"); 315 ASSERT_TRUE(g_rustDemangleFn) << "Failed to dlsym rustc_demangle"; 316 std::string reason = "reason"; 317 const char *bufStr = reason.c_str(); 318 g_rustDemangleFn(bufStr); 319 g_rustDemangleFn = nullptr; 320 GTEST_LOG_(INFO) << "ArkTest010: end."; 321} 322} 323}