1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. 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 #include "hook_standalone.h"
16 
17 #include <csignal>
18 
19 #include "hook_common.h"
20 #include "hook_manager.h"
21 #include "logging.h"
22 #include "native_hook_config.pb.h"
23 #include "plugin_service_types.pb.h"
24 #include <cstdlib>
25 
26 
27 using namespace OHOS::Developtools::NativeDaemon;
28 namespace OHOS {
29 namespace Developtools {
30 namespace Profiler {
31 namespace Hook {
32 const int PAGE_BYTES = 4096;
33 std::shared_ptr<HookManager> g_hookManager;
34 NativeHookConfig g_nativeConfig;
35 
SetNativeHookConfig(const HookData& hookData)36 void SetNativeHookConfig(const HookData& hookData)
37 {
38     g_nativeConfig.set_fp_unwind(hookData.fpUnwind);
39     g_nativeConfig.set_smb_pages(hookData.smbSize / PAGE_BYTES);
40     g_nativeConfig.set_max_stack_depth(hookData.maxStackDepth);
41     g_nativeConfig.set_filter_size(hookData.filterSize);
42     g_nativeConfig.set_save_file(true);
43     g_nativeConfig.set_file_name(hookData.fileName);
44     g_nativeConfig.set_statistics_interval(hookData.statisticsInterval);
45     g_nativeConfig.set_offline_symbolization(hookData.offlineSymbolization);
46     g_nativeConfig.set_callframe_compress(hookData.callframeCompress);
47     g_nativeConfig.set_string_compressed(hookData.stringCompressed);
48     g_nativeConfig.set_clock("realtime");
49     g_nativeConfig.set_record_accurately(true);
50     g_nativeConfig.set_startup_mode(hookData.startupMode);
51     g_nativeConfig.set_process_name(hookData.processName);
52     g_nativeConfig.set_sample_interval(hookData.sampleInterval);
53     g_nativeConfig.set_response_library_mode(hookData.responseLibraryMode);
54     g_nativeConfig.set_js_stack_report(hookData.jsStackReport);
55     g_nativeConfig.set_max_js_stack_depth(hookData.maxJsStackdepth);
56     g_nativeConfig.set_filter_napi_name(hookData.filterNapiName);
57     g_nativeConfig.set_malloc_free_matching_interval(hookData.mallocFreeMatchingInterval);
58     for (const std::string& pid: hookData.pids) {
59         g_nativeConfig.add_expand_pids(atoi(pid.data()));
60     }
61     // statistical reporting must be callframe compressed and accurate.
62     if (g_nativeConfig.statistics_interval() > 0 ||
63         g_nativeConfig.malloc_free_matching_interval() > 0) {
64         g_nativeConfig.set_callframe_compress(true);
65         g_nativeConfig.set_record_accurately(true);
66     }
67     // offlinem symbolization, callframe must be compressed
68     if (g_nativeConfig.offline_symbolization()) {
69         g_nativeConfig.set_callframe_compress(true);
70     }
71 
72     // callframe compressed, string must be compressed.
73     if (g_nativeConfig.callframe_compress()) {
74         g_nativeConfig.set_string_compressed(true);
75     }
76 
77     if (g_nativeConfig.string_compressed() || hookData.rawString ||
78         g_nativeConfig.response_library_mode() || g_nativeConfig.js_stack_report() > 0) {
79         g_hookManager->SethookStandalone(true);
80     }
81     PROFILER_LOG_INFO(LOG_CORE, "hookData config = %s", hookData.ToString().c_str());
82 }
83 
StartHook(HookData& hookData)84 bool StartHook(HookData& hookData)
85 {
86     g_hookManager = std::make_shared<HookManager>();
87     std::vector<ProfilerPluginConfig> config;
88 #if defined(__arm__)
89     hookData.fpUnwind = false;
90     hookData.responseLibraryMode = false;
91 #endif
92     SetNativeHookConfig(hookData);
93     g_hookManager->SetHookConfig(g_nativeConfig);
94     CHECK_TRUE(g_hookManager->CreatePluginSession(config), false, "StartHook CreatePluginSession invalid");
95     g_hookManager->StartPluginSession();
96     return true;
97 }
98 
EndHook()99 void EndHook()
100 {
101     std::vector<uint32_t> pluginIds;
102     g_hookManager->StopPluginSession(pluginIds);
103     g_hookManager->DestroyPluginSession(pluginIds);
104 }
105 } // namespace Hook
106 } // namespace Profiler
107 } // namespace Developtools
108 } // namespace OHOS