• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
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 <iostream>
17 #include <vector>
18 #include <string>
19 #include <memory>
20 #include "hook_record.h"
21 
22 namespace OHOS::Developtools::NativeDaemon {
23 
GetType()24 uint16_t HookRecord::GetType()
25 {
26     return (IsValid()) ? rawStack_->stackContext->type : UNKNOWN;
27 }
28 
Reset()29 void HookRecord::Reset()
30 {
31     if (rawStack_ != nullptr) {
32         rawStack_->Reset();
33         rawStack_ = nullptr;
34     }
35 }
36 
GetAddr()37 uint64_t HookRecord::GetAddr()
38 {
39     return (IsValid()) ? reinterpret_cast<uint64_t>(rawStack_->stackContext->addr) : 0;
40 }
41 
SetAddr(uint64_t addr)42 void HookRecord::SetAddr(uint64_t addr)
43 {
44     if (IsValid()) {
45         rawStack_->stackContext->addr = reinterpret_cast<void*>(addr);
46     }
47 }
48 
IsValid()49 bool HookRecord::IsValid()
50 {
51     return (rawStack_ && rawStack_->stackContext);
52 }
53 
54 template <typename T>
SetEventFrame(T * event,SerializeInfo & hookInfo)55 void HookRecord::SetEventFrame(T* event, SerializeInfo& hookInfo)
56 {
57     if (!(event && IsValid())) {
58         PROFILER_LOG_ERROR(LOG_CORE, "hookRecord SetEventFrame get nullptr");
59         return;
60     }
61     // ignore the first two frame if dwarf unwind
62     size_t idx = hookInfo.config->fp_unwind() ? 0 : FILTER_STACK_DEPTH;
63     event->set_pid(rawStack_->stackContext->pid);
64     event->set_tid(rawStack_->stackContext->tid);
65     event->set_addr(GetAddr());
66 
67     if (hookInfo.config->callframe_compress() && hookInfo.stackMapId != 0) {
68         event->set_thread_name_id(rawStack_->stackContext->tid);
69         event->set_stack_id(hookInfo.stackMapId);
70         return;
71     }
72     for (; idx < (hookInfo.callFrames)->size(); ++idx) {
73         auto frame = event->add_frame_info();
74         SetFrameInfo(*frame, (*(hookInfo.callFrames))[idx], hookInfo.config);
75     }
76     event->set_thread_name_id(rawStack_->stackContext->tid);
77 }
78 
79 template <typename T>
SetFrameInfo(T & frame,CallFrame & callFrame,NativeHookConfig * config)80 void HookRecord::SetFrameInfo(T& frame, CallFrame& callFrame, NativeHookConfig* config)
81 {
82     if (config == nullptr) {
83         PROFILER_LOG_ERROR(LOG_CORE, "hookRecord SetFrameInfo invalid config");
84         return;
85     }
86     frame.set_ip(callFrame.ip_);
87     if (config->offline_symbolization()) {
88         // when js mixes offline symbols, the js call stack is reported according to the online symbolization
89         if (callFrame.isJsFrame_ && callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) {
90             frame.set_sp(callFrame.sp_);
91             frame.set_offset(callFrame.offset_);
92             frame.set_symbol_offset(callFrame.symbolOffset_);
93             frame.set_symbol_name_id(callFrame.symbolNameId_);
94             frame.set_file_path_id(callFrame.filePathId_);
95         }
96         return;
97     }
98     frame.set_sp(callFrame.sp_);
99     if (!(callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0)) {
100         frame.set_symbol_name(std::string(callFrame.symbolName_));
101         frame.set_file_path(std::string(callFrame.filePath_));
102     }
103     frame.set_offset(callFrame.offset_);
104     frame.set_symbol_offset(callFrame.symbolOffset_);
105     if (callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) {
106         frame.set_symbol_name_id(callFrame.symbolNameId_);
107         frame.set_file_path_id(callFrame.filePathId_);
108     }
109 }
110 
111 template <typename T>
SetSize(T * event)112 void HookRecord::SetSize(T* event)
113 {
114     if (event == nullptr) {
115         PROFILER_LOG_ERROR(LOG_CORE, "hookRecord SetSize invalid event");
116         return;
117     }
118     auto size = static_cast<uint64_t>(rawStack_->stackContext->mallocSize);
119 #ifdef USE_JEMALLOC
120     if (GetType() != MEMORY_USING_MSG) {
121         size = static_cast<uint64_t>(ComputeAlign(size));
122     }
123 #endif
124     event->set_size(size);
125 }
126 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)127 void FreeRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
128 {
129     std::visit([this, &hookInfo](auto protoData) {
130         auto freeEvent = protoData->mutable_free_event();
131         HookRecord::SetEventFrame(freeEvent, hookInfo);
132         }, stackData);
133 }
134 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)135 void MallocRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
136 {
137     std::visit([this, &hookInfo](auto protoData) {
138         auto allocEvent = protoData->mutable_alloc_event();
139         HookRecord::SetSize(allocEvent);
140         HookRecord::SetEventFrame(allocEvent, hookInfo);
141         }, stackData);
142 }
143 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)144 void MmapRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
145 {
146     std::visit([this, &hookInfo](auto protoData) {
147         auto mmapEvent = protoData->mutable_mmap_event();
148         if (hookInfo.tagName != "") {
149             mmapEvent->set_type(hookInfo.tagName);
150         }
151         HookRecord::SetSize(mmapEvent);
152         HookRecord::SetEventFrame(mmapEvent, hookInfo);
153         }, stackData);
154 }
155 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)156 void MmapFilePageRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
157 {
158     std::visit([this, &hookInfo](auto protoData) {
159         auto mmapEvent = protoData->mutable_mmap_event();
160         if (hookInfo.tagName != "") {
161             mmapEvent->set_type(MMAP_FILE_PAGE_PREFIX + hookInfo.tagName);
162         }
163         HookRecord::SetSize(mmapEvent);
164         HookRecord::SetEventFrame(mmapEvent, hookInfo);
165         }, stackData);
166 }
167 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)168 void MunmapRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
169 {
170     std::visit([this, &hookInfo](auto protoData) {
171         auto munmapEvent = protoData->mutable_munmap_event();
172         HookRecord::SetSize(munmapEvent);
173         HookRecord::SetEventFrame(munmapEvent, hookInfo);
174         }, stackData);
175 }
176 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)177 void PrSetVmaRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
178 {
179     std::visit([this](auto protoData) {
180         auto tagEvent = protoData->mutable_tag_event();
181         std::string tagName(reinterpret_cast<char*>(rawStack_->data));
182         tagEvent->set_addr(reinterpret_cast<uint64_t>(rawStack_->stackContext->addr));
183         tagEvent->set_size(rawStack_->stackContext->mallocSize);
184         tagEvent->set_tag(PR_SET_VMA_PREFIX + tagName);
185         tagEvent->set_pid(rawStack_->stackContext->pid);
186         }, stackData);
187 }
188 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)189 void MemoryUsingRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
190 {
191     std::visit([this, &hookInfo](auto protoData) {
192         auto memUsingEvent = protoData->mutable_mmap_event();
193         if (hookInfo.tagName != "") {
194             memUsingEvent->set_type(hookInfo.tagName);
195         }
196         HookRecord::SetSize(memUsingEvent);
197         HookRecord::SetEventFrame(memUsingEvent, hookInfo);
198         }, stackData);
199 }
200 
SerializeData(NativeHookProto stackData,SerializeInfo & hookInfo)201 void MemoryUnusingRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo)
202 {
203     std::visit([this, &hookInfo](auto protoData) {
204         auto munmapEvent = protoData->mutable_munmap_event();
205         HookRecord::SetSize(munmapEvent);
206         HookRecord::SetEventFrame(munmapEvent, hookInfo);
207         }, stackData);
208 }
209 }