• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #ifndef BPF_EVENT_RECEIVER_H
17 #define BPF_EVENT_RECEIVER_H
18 
19 #include <memory>
20 #include <thread>
21 #include <mutex>
22 #include <condition_variable>
23 
24 
25 #include "type_headers.h"
26 #include "ringbuffer.h"
27 #include "hiebpf_data_file.h"
28 #include "hhlog.h"
29 #include "hiebpf.skel.h"
30 #include "bpf.h"
31 #include "fstrace_args_converter.h"
32 #include "maps_info.h"
33 #include "elf_symbol_info.h"
34 #include <iostream>
35 
36 
37 #define FSTRACE_MAX_ARGS    4
38 #define MAX_TRACER_NAME_LEN 8
39 #define MAX_TYPE_NAME_LEN   16
40 #define MAX_BUSY_LOOPS      1000
41 #define PADDING(nbytes)     char reserve_[nbytes]
42 
43 struct FixedFSTraceTLVItem {
44     __u32 tracer_;
45     __u32 itemLen_;
46     __u32 pid_;
47     __u32 tid_;
48     char tracerName_[MAX_TRACER_NAME_LEN]; // MAX_TRACER_NAME_LEN = 8 bytes, which is 64 bits
49     __u64 stime_;
50     __u64 ctime_;
51     char typeName_[MAX_TYPE_NAME_LEN];      // MAX_TYPE_NAME_LEN = 16 bytes, which is 128 bits
52     int32_t  retval_;
53     uint16_t nips_;
54     uint16_t type_;
55     __u64 args_[FSTRACE_MAX_ARGS];
56     char comm_[MAX_COMM_LEN];           // MAX_COMM_LEN = 16 bytes, which 128 bits
57     /* the above members have been carefully aligned */
58 };
59 
60 struct FixedPFTraceTLVItem {
61     __u32 tracer_;
62     __u32 itemLen_;
63     __u32 pid_;
64     __u32 tid_;
65     char tracerName_[MAX_TRACER_NAME_LEN];
66     __u64 stime_;
67     __u64 ctime_;
68     char typeName_[MAX_TYPE_NAME_LEN];
69     __u64 addr_;
70     __u32 size_;
71     uint16_t nips_;
72     uint16_t type_;
73     char comm_[MAX_COMM_LEN];
74     /* the above members have been carefully aligned */
75 };
76 
77 struct FixedBIOTraceTLVItem {
78     __u32 tracer_;
79     __u32 itemLen_;
80     __u32 pid_;
81     __u32 tid_;
82     char comm_[MAX_COMM_LEN];
83     __u64 stime_;
84     __u64 ctime_;
85     __u32 prio_;
86     __u32 size_;
87     __u64 blkcnt_;
88     __u32 nips_;
89     __u32 type_;
90     char typeName_[MAX_TYPE_NAME_LEN];
91 };
92 
93 struct FixedSTRTraceTLVItem {
94     __u32 tracer_;
95     __u32 itemLen_;
96     __u32 pid_;
97     __u32 tid_;
98     __u64 stime_;
99     __u32 srcTracer_;
100     __u32 srcType_;
101     __u32 strLen_;
102     PADDING(sizeof(__u32));
103     /* the above members have been carefully aligned */
104 };
105 
106 struct FixedMapTLVItem {
107     uint32_t type = 0;
108     uint32_t len = 0;
109     uint64_t start = 0;
110     uint64_t end = 0;
111     uint32_t offset = 0;
112     uint32_t pid = 0;
113     uint32_t fileNameLen = 0;
114 }__attribute__((packed));
115 
116 struct FixedSymbolTLVItem {
117     uint32_t type = 0;
118     uint32_t len = 0;
119     uint64_t textVaddr = 0;
120     uint32_t textOffset = 0;
121     uint32_t strTabLen = 0;
122     uint32_t symTabLen = 0;
123     uint32_t fileNameLen = 0;
124     uint32_t symEntLen = 0;
125 }__attribute__((packed));
126 
127 class BPFEventReceiver {
128 public:
MakeShared(const std::weak_ptr<HiebpfDataFile> & file)129     static inline std::shared_ptr<BPFEventReceiver> MakeShared(const std::weak_ptr<HiebpfDataFile> &file)
130     {
131         std::shared_ptr<BPFEventReceiver> obj {new(std::nothrow) BPFEventReceiver {file}};
132         if (obj == nullptr) {
133             return nullptr;
134         }
135         if (obj->InitBuffer() != 0) {
136             return nullptr;
137         }
138         return obj;
139     }
140 
~BPFEventReceiver()141     ~BPFEventReceiver()
142     {
143         if (not stop_) {
144             stop_ = true;
145         }
146         if (workLoop_.joinable()) {
147             workLoop_.join();
148         }
149     }
150 
Put(void * data,const size_t dataSize)151     inline int Put(void *data, const size_t dataSize)
152     {
153         HHLOGF((data == nullptr or dataSize == 0), "invalid arguments: this should never happen");
154         HHLOGF(buf_ == nullptr, "receiver has no buffer: this should never happen");
155         int ret {-1};
156         ret = buf_->Put((const char*)data, dataSize);
157         if (ret == static_cast<int>(dataSize)) {
158             NotifyOne();
159         }
160         HHLOGF((0 <= ret and ret < static_cast<int>(dataSize)), "incomplete data received: this should never happen");
161         return ret;
162     }
163 
Start()164     inline int Start()
165     {
166         workLoop_ = std::thread(&BPFEventReceiver::WorkLoop, this);
167         return 0;
168     }
169 
Stop()170     inline void Stop()
171     {
172         if (Running()) {
173             stop_ = true;
174             NotifyOne();
175         }
176         if (workLoop_.joinable()) {
177             workLoop_.join();
178         }
179     }
180 
Running()181     inline bool Running() const
182     {
183         return (not stop_);
184     }
185 
186 private:
187     enum MemAlign:std::size_t {
188         ALIGNMENT_BYTES = 8,
189         ALIGNMENT_MASK = 7,
190     };
191     void DoWork();
192     void ReceiveFSTraceEvent();
193     void ReceivePFTraceEvent();
194     void ReceiveBIOTraceEvent();
195     void ReceiveSTRTraceEvent();
196     void ReceiveDlopenTraceEvent();
197     void WriteEventMaps(uint32_t pid);
198     void WriteSymbolInfo(const std::string &fileName);
199     void ReverseStr(char* left, char* right);
200     void DiscardEvent();
201     int EncodeFSTraceEvent(
202         const struct fstrace_cmplt_event_t *cmplt_event,
203         void* tlvItem,
204         const size_t itemLen);
205     int EncodePFTraceEvent(
206         const struct pftrace_cmplt_event_t *cmplt_event,
207         void* tlvItem,
208         const size_t itemLen);
209     int EncodeBIOTraceEvent(
210         const struct biotrace_cmplt_event_t *cmplt_event,
211         void* tlvItem,
212         const size_t itemLen);
213     int EncodeSTRTraceEvent(
214         const struct strtrace_cmplt_event_t *cmplt_event,
215         void* tlvItem,
216         const size_t itemLen);
ConvertFSTraceArgsToArray(__u64 * args,const struct fstrace_start_event_t * start_event)217     int ConvertFSTraceArgsToArray(__u64 *args, const struct fstrace_start_event_t *start_event)
218     {
219         int (*fn) (__u64*, const struct fstrace_start_event_t *) = g_argsConverterTable[start_event->type];
220         if (fn) {
221             return fn(args, start_event);
222         }
223         HHLOGE(true, "invalid converter for type = %u", start_event->type);
224         return -1;
225     }
226 
GetFSTraceTLVItemSize(const struct fstrace_cmplt_event_t & cmplt_event)227     inline __u32 GetFSTraceTLVItemSize(const struct fstrace_cmplt_event_t &cmplt_event)
228     {
229         __u32 size {sizeof(struct FixedFSTraceTLVItem)};
230         size += cmplt_event.nips * sizeof(__u64);
231         return size;
232     }
233 
GetPFTraceTLVItemSize(const struct pftrace_cmplt_event_t & cmplt_event)234     inline __u32 GetPFTraceTLVItemSize(const struct pftrace_cmplt_event_t &cmplt_event)
235     {
236         __u32 size {sizeof(struct FixedPFTraceTLVItem)};
237         size += cmplt_event.nips * sizeof(__u64);
238         return size;
239     }
240 
GetBIOTraceTLVItemSize(const struct biotrace_cmplt_event_t & cmplt_event)241     inline __u32 GetBIOTraceTLVItemSize(const struct biotrace_cmplt_event_t &cmplt_event)
242     {
243         __u32 size {sizeof(struct FixedBIOTraceTLVItem)};
244         size += cmplt_event.nips * sizeof(__u64);
245         return size;
246     }
247 
GetSTRTraceTLVItemSize(const struct strtrace_cmplt_event_t & cmplt_event)248     inline __u32 GetSTRTraceTLVItemSize(const struct strtrace_cmplt_event_t &cmplt_event)
249     {
250         __u32 size {sizeof(FixedSTRTraceTLVItem)};
251         size += cmplt_event.len;
252         size &= ~ALIGNMENT_MASK;
253         size += alignBytes_;
254         return size;
255     }
256 
WorkLoop()257     inline void WorkLoop()
258     {
259         while (not stop_) {
260             DoWork();
261         }
262     }
263 
BPFEventReceiver(const std::weak_ptr<HiebpfDataFile> & file)264     inline BPFEventReceiver(const std::weak_ptr<HiebpfDataFile> &file) : file_ {file} {}
265 
NotifyOne()266     inline void NotifyOne()
267     {
268         cond_.notify_one();
269     }
270 
InitBuffer()271     inline int InitBuffer()
272     {
273         constexpr std::size_t bufSize {1 << 20};
274         constexpr enum RingBuffer::MemAlignShift memAlign {RingBuffer::MemAlignShift::W_ALIGN_SHIFT};
275         buf_ = std::make_unique<RingBuffer>(bufSize, memAlign);
276         if (buf_ == nullptr or (not (*buf_))) {
277             return -1;
278         }
279         return 0;
280     }
281 
282     std::vector<std::string> gTracerTable {
283         "maptrace",
284         "symtrace",
285         "fstrace",
286         "pftrace",
287         "biotrace",
288         "strtrace",
289     };
290 
291     std::vector<std::string> gFSTraceTypeTable {
292         "",
293         "openat2",
294         "read",
295         "write",
296         "pread64",
297         "pwrite64",
298         "readv",
299         "writev",
300         "preadv",
301         "pwritev",
302         "close",
303     };
304 
305     std::vector<std::string> gPFTraceTypeTable {
306         "",
307         "FILE_BACKED_IN",
308         "PAGE_CACHE_HIT",
309         "SWAP_FROM_ZRAM",
310         "SWAP_FROM_DISK",
311         "ZERO_FILL_PAGE",
312         "FAKE_ZERO_PAGE",
313         "COPY_ON_WRITE",
314         "MAX_EVENT_TYPE",
315     };
316 
317     std::vector<std::string> gBIOTraceTypeTable {
318         "",
319         "DATA_READ",
320         "DATA_WRITE",
321         "METADATA_READ",
322         "METADATA_WRITE",
323         "PAGE_IN",
324         "PAGE_OUT",
325     };
326 
327     const std::size_t alignBytes_ {ALIGNMENT_BYTES};
328     bool stop_ {false};
329     std::mutex  mtx_ {};
330     std::condition_variable cond_ {};
331     std::thread workLoop_ {};
332     std::unique_ptr<RingBuffer> buf_ {nullptr};
333     std::weak_ptr<HiebpfDataFile> file_ {};
334     OHOS::Developtools::Hiebpf::MapsInfo mapsInfo_;
335     OHOS::Developtools::Hiebpf::ElfSymbolInfo elfSymbolInfo_;
336 };
337 #endif