• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "hook_standalone.h"
16 
17 #include <csignal>
18 #include <functional>
19 #include <linux/types.h>
20 #include <sys/mman.h>
21 
22 #include "common.h"
23 #include "epoll_event_poller.h"
24 #include "event_notifier.h"
25 #include "hook_common.h"
26 #include "hook_manager.h"
27 #include "hook_service.h"
28 #include "logging.h"
29 #include "native_hook_config.pb.h"
30 #include "share_memory_allocator.h"
31 #include "stack_data_repeater.h"
32 #include "stack_preprocess.h"
33 #include "virtual_runtime.h"
34 #include "hook_manager.h"
35 #include "utilities.h"
36 
37 using namespace OHOS::Developtools::NativeDaemon;
38 namespace OHOS {
39 namespace Developtools {
40 namespace Profiler {
41 namespace Hook {
42 const int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
43 const int MOVE_BIT_16 = 16;
44 const int MOVE_BIT_32 = 32;
45 std::string g_smbName = "hooknativesmb";
46 std::unique_ptr<EpollEventPoller> g_eventPoller_;
47 std::shared_ptr<ShareMemoryBlock> g_shareMemoryBlock;
48 std::shared_ptr<EventNotifier> g_eventNotifier;
49 std::shared_ptr<HookService> g_hookService;
50 std::shared_ptr<HookManager> g_hookManager;
51 std::shared_ptr<StackDataRepeater> g_stackDataRepeater;
52 std::shared_ptr<StackPreprocess> g_stackpreprocess;
53 uint32_t g_maxStackDepth;
54 bool g_unwindErrorFlag = false;
55 bool g_fpUnwind = false;
56 uint32_t g_statisticsinterval;
57 std::unique_ptr<FILE, decltype(&fclose)> g_fpHookFile(nullptr, nullptr);
58 
SignalHandl(int signo)59 static void SignalHandl(int signo)
60 {
61     HILOG_ERROR(LOG_CORE, "recv signal %d", signo);
62     g_stackpreprocess->StopTakeResults();
63     if (g_statisticsinterval > 0) {
64         g_stackpreprocess->FlushRecordStatistics();
65     }
66     exit(-1);
67 }
68 
GetClientConfig(const HookData & hookData,ClientConfig & clientConfig)69 void GetClientConfig(const HookData& hookData, ClientConfig& clientConfig)
70 {
71     clientConfig.shareMemroySize = hookData.smbSize;
72     clientConfig.filterSize = hookData.filterSize;
73     clientConfig.maxStackDepth = hookData.maxStackDepth;
74     clientConfig.mallocDisable = hookData.mallocDisable;
75     clientConfig.mmapDisable = hookData.mmapDisable;
76     clientConfig.freeStackData = hookData.freemsgstack;
77     clientConfig.munmapStackData = hookData.munmapmsgstack;
78     clientConfig.fpunwind = hookData.fpUnwind;
79     clientConfig.isBlocked = true;
80 }
81 
StartHook(HookData & hookData)82 bool StartHook(HookData& hookData)
83 {
84     // create smb and eventNotifier
85     g_shareMemoryBlock = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(g_smbName, hookData.smbSize);
86     g_eventNotifier = EventNotifier::Create(0, EventNotifier::NONBLOCK);
87     g_stackDataRepeater = std::make_shared<StackDataRepeater>(STACK_DATA_SIZE);
88     CHECK_TRUE(g_stackDataRepeater != nullptr, false, "Create StackDataRepeater FAIL");
89     g_hookManager = std::make_shared<HookManager>(g_shareMemoryBlock, g_eventNotifier, g_stackDataRepeater);
90     // start event poller task
91     g_eventPoller_ = std::make_unique<EpollEventPoller>(DEFAULT_EVENT_POLLING_INTERVAL);
92     g_eventPoller_->Init();
93     g_eventPoller_->Start();
94     g_eventPoller_->AddFileDescriptor(g_eventNotifier->GetFd(),
95                                       std::bind(&HookManager::ReadShareMemory, g_hookManager.get()));
96 
97     HILOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", g_shareMemoryBlock->GetfileDescriptor(),
98                g_eventNotifier->GetFd());
99 
100 #if defined(__arm__)
101     hookData.fpUnwind = false;
102 #endif
103     if (hookData.maxStackDepth < DLOPEN_MIN_UNWIND_DEPTH) {
104         // set default max depth
105         hookData.maxStackDepth = DLOPEN_MIN_UNWIND_DEPTH;
106     }
107 
108     HILOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n",
109         g_shareMemoryBlock->GetfileDescriptor(), g_eventNotifier->GetFd());
110 
111     ClientConfig clientConfig;
112     GetClientConfig(hookData, clientConfig);
113     std::string clientConfigStr = clientConfig.ToString();
114     HILOG_INFO(LOG_CORE, "send hook client config:%s\n", clientConfigStr.c_str());
115     g_hookService = std::make_shared<HookService>(g_shareMemoryBlock->GetfileDescriptor(),
116         g_eventNotifier->GetFd(), hookData.pid, hookData.processName, clientConfig);
117 
118     g_maxStackDepth = hookData.maxStackDepth;
119     g_fpUnwind = hookData.fpUnwind;
120     g_statisticsinterval = hookData.statisticsInterval;
121 
122     NativeHookConfig nativeConfig;
123     nativeConfig.set_fp_unwind(hookData.fpUnwind);
124     nativeConfig.set_max_stack_depth(hookData.maxStackDepth);
125     nativeConfig.set_filter_size(hookData.filterSize);
126     nativeConfig.set_save_file(true);
127     nativeConfig.set_file_name(hookData.fileName);
128     nativeConfig.set_statistics_interval(hookData.statisticsInterval);
129     nativeConfig.set_offline_symbolization(hookData.offlineSymbolization);
130     nativeConfig.set_callframe_compress(hookData.callframeCompress);
131     nativeConfig.set_string_compressed(hookData.stringCompressed);
132 #if defined(__arm__)
133     nativeConfig.set_fp_unwind(false); // if OS is 32-bit,set fp_unwind false.
134 #endif
135     bool isHookStandaloneSerialize = false;
136     // statistical reporting must be callframe compressed and accurate.
137     if (nativeConfig.statistics_interval() > 0) {
138         nativeConfig.set_callframe_compress(true);
139         nativeConfig.set_record_accurately(true);
140     }
141     // offlinem symbolization, callframe must be compressed
142     if (nativeConfig.offline_symbolization()) {
143         nativeConfig.set_callframe_compress(true);
144     }
145 
146     // callframe compressed, string must be compressed.
147     if (nativeConfig.callframe_compress()) {
148         nativeConfig.set_string_compressed(true);
149     }
150 
151     if (nativeConfig.string_compressed() || hookData.rawString) {
152         isHookStandaloneSerialize = true;
153     }
154     HILOG_INFO(LOG_CORE, "fp_unwind = %d", nativeConfig.fp_unwind());
155     HILOG_INFO(LOG_CORE, "offline_symbolization = %d", nativeConfig.offline_symbolization());
156     HILOG_INFO(LOG_CORE, "callframe_compress; = %d", nativeConfig.callframe_compress());
157     HILOG_INFO(LOG_CORE, "string_compressed; = %d", nativeConfig.string_compressed());
158     HILOG_INFO(LOG_CORE, "statistics_interval = %u", nativeConfig.statistics_interval());
159     HILOG_INFO(LOG_CORE, "isHookStandaloneSerialize = %d", isHookStandaloneSerialize);
160     HILOG_INFO(LOG_CORE, "rawString = %d", hookData.rawString);
161     clockid_t pluginDataClockId = COMMON::GetClockId("realtime");
162     g_stackpreprocess = std::make_shared<StackPreprocess>(g_stackDataRepeater, nativeConfig,
163                                                           pluginDataClockId, isHookStandaloneSerialize);
164     CHECK_TRUE(g_stackpreprocess != nullptr, false, "Create StackPreprocess FAIL");
165     g_hookManager->SetHookConfig(nativeConfig);
166     g_stackpreprocess->StartTakeResults();
167     signal(SIGINT, SignalHandl);
168     return true;
169 }
170 } // namespace Hook
171 } // namespace Profiler
172 } // namespace Developtools
173 } // namespace OHOS
174