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 
16 #include <cinttypes>
17 #include <securec.h>
18 
19 #include "ark_crash_holder.h"
20 #include "utils/log.h"
21 
22 #if defined(OHOS_STANDARD_PLATFORM) && (defined(NAPI_TARGET_ARM64) || defined(NAPI_TARGET_ARM))
23 /* dfx interface, type 0 for string */
24 extern "C" uintptr_t DFX_SetCrashObj(uint8_t type, uintptr_t addr);
25 extern "C" uintptr_t DFX_ResetCrashObj(uintptr_t addr);
26 #endif
27 
28 constexpr size_t FORMATED_FUNCPTR_LENGTH = 24; // length of dec function pointer
29 
~CrashHolder()30 CrashHolder::~CrashHolder()
31 {
32 #if defined(OHOS_STANDARD_PLATFORM) && (defined(NAPI_TARGET_ARM64) || defined(NAPI_TARGET_ARM))
33     DFX_ResetCrashObj(handle_);
34 #endif
35     if (data_ != nullptr) {
36         delete [] data_;
37         data_ = nullptr;
38     }
39 }
40 
SetCrashObj(const char * info)41 void CrashHolder::SetCrashObj(const char* info)
42 {
43     std::string data = "[NAPI] Crash occured on ";
44     data += info;
45     data += ", callback: ";
46 
47     size_ = data.length();
48     const size_t bufSize = size_ + FORMATED_FUNCPTR_LENGTH;
49     data_ = new char[bufSize];
50 
51     if (memcpy_s(data_, bufSize, data.c_str(), size_) != EOK) {
52         HILOG_WARN("Failed to init crash holder.");
53         size_ = 0;
54         data_[0] = '\0';
55     };
56 
57 #if defined(OHOS_STANDARD_PLATFORM) && (defined(NAPI_TARGET_ARM64) || defined(NAPI_TARGET_ARM))
58     handle_ = DFX_SetCrashObj(static_cast<uint8_t>(DFXObjectType::STRING),
59                               reinterpret_cast<uintptr_t>(data_));
60 #else
61     handle_ = 0;
62 #endif
63 }
64 
UpdateCallbackPtr(uintptr_t addr)65 void CrashHolder::UpdateCallbackPtr(uintptr_t addr)
66 {
67     if (sprintf_s(data_ + size_, FORMATED_FUNCPTR_LENGTH, "%" PRIuPTR, addr) < 0) {
68         HILOG_ERROR("Failed to update callback info: %{public}" PRIuPTR, addr);
69     }
70 }
71