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
27using namespace OHOS::Developtools::NativeDaemon;
28namespace OHOS {
29namespace Developtools {
30namespace Profiler {
31namespace Hook {
32const int PAGE_BYTES = 4096;
33std::shared_ptr<HookManager> g_hookManager;
34NativeHookConfig g_nativeConfig;
35
36void 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
84bool 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
99void 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