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#ifndef STACK_DATA_REPEATER_H
16#define STACK_DATA_REPEATER_H
17
18#include <condition_variable>
19#include <deque>
20#include <memory>
21#include <mutex>
22#include "logging.h"
23#include "nocopyable.h"
24#include "native_hook_result.pb.h"
25#include "hook_common.h"
26#include "utilities.h"
27
28using BatchNativeHookDataPtr = STD_PTR(shared, BatchNativeHookData);
29constexpr const int CACHE_DATA_SIZE = 40000;
30constexpr const int32_t CACHE_ARRAY_SIZE = 10;
31
32class StackDataRepeater {
33public:
34    struct RawStack {
35        std::unique_ptr<uint8_t[]> baseStackData = nullptr; // save the shared memory data
36        BaseStackRawData* stackConext = nullptr; // points to the foundation type data
37        union {
38            uint8_t* stackData;
39            const char* jsStackData = nullptr;
40        };
41        uint8_t* data = nullptr; // fp mode data is ip, dwarf mode data is regs
42        uint64_t freeData = 0;
43        uint32_t stackSize = 0;
44        uint8_t fpDepth = 0; // fp mode fpDepth is ip depth, dwarf mode is invalid
45        bool reportFlag = false;
46        bool reduceStackFlag = false;
47        void Reset()
48        {
49            baseStackData = nullptr;
50            stackConext = nullptr;
51            data = nullptr;
52            stackData = nullptr;
53            freeData = 0;
54            stackSize = 0;
55            fpDepth = 0;
56            reportFlag = false;
57            reduceStackFlag = false;
58        }
59    };
60
61    explicit StackDataRepeater(size_t maxSize);
62    ~StackDataRepeater();
63    bool PutRawStack(const std::shared_ptr<RawStack>& rawData, bool isRecordAccurately);
64    bool PutRawStackArray(std::array<std::shared_ptr<RawStack>, CACHE_ARRAY_SIZE>& rawDataArray, uint32_t batchCount);
65    std::shared_ptr<RawStack> TakeRawData(uint32_t during, clockid_t clockId, uint32_t batchCount,
66        std::shared_ptr<RawStack> batchRawStack[], uint32_t statInterval, bool& isTimeOut);
67    void Close();
68    void Reset();
69    std::shared_ptr<RawStack> GetRawStack();
70    void ReturnRawStack(std::shared_ptr<RawStack> rawStack);
71    size_t Size();
72    void ClearCache()
73    {
74        std::unique_lock<std::mutex> lock(cacheMutex_);
75        rawDataCacheQueue_.clear();
76    }
77
78private:
79    std::mutex mutex_;
80    std::mutex cacheMutex_;
81    std::deque<std::shared_ptr<RawStack>> rawDataCacheQueue_;
82    std::condition_variable slotCondVar_;
83    std::condition_variable itemCondVar_;
84    std::deque<std::shared_ptr<RawStack>> rawDataQueue_;
85    std::unordered_map<void *, std::shared_ptr<RawStack>> mallocMap_ = {};
86    size_t maxSize_;
87    uint64_t reducedStackCount_;
88    std::atomic_bool closed_;
89
90    DISALLOW_COPY_AND_MOVE(StackDataRepeater);
91};
92
93using RawStackPtr = STD_PTR(shared, StackDataRepeater::RawStack);
94
95using StackDataRepeaterPtr = STD_PTR(shared, StackDataRepeater);
96
97#endif // STACK_DATA_REPEATER_H