1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 #include "ebpf_converter.h"
16
17 #include <algorithm>
18 #include <cstring>
19 #include <cxxabi.h>
20 #include <fcntl.h>
21 #include <getopt.h>
22 #include <iostream>
23 #include <unistd.h>
24 #include <memory>
25 #include <securec.h>
26 #include <climits>
27
28 #define CHK(expr) \
29 do { \
30 if (!(expr)) { \
31 std::cout << __FUNCTION__ << ": "; \
32 std::cout << __LINE__ << ", "; \
33 std::cout << "read data failed" << std::endl; \
34 return; \
35 } \
36 } while (0)
37
38 namespace OHOS {
39 namespace EBPF_TOOLS {
40 namespace {
41 constexpr uint8_t HEADER_MAGIC = 8;
42 constexpr uint8_t ARGS_NUM = 4;
43 constexpr uint8_t SYM_ENT_LEN_64 = 24;
44 constexpr uint8_t SYM_ENT_LEN_32 = 16;
45 constexpr uint8_t STT_FUNC = 2;
46 constexpr uint8_t EVENT_FS_FIXED_SIZE = 64;
47 constexpr uint8_t EVENT_MAPS_FIXED_SIZE = 36;
48 constexpr uint8_t EVENT_SYM_FIXED_SIZE = 36;
49 constexpr uint8_t EVENT_MEM_FIXED_SIZE = 88;
50 constexpr uint8_t EVENT_STR_FIXED_SIZE = 40;
51 constexpr uint8_t EVENT_BIO_FIXED_SIZE = 88;
52 constexpr uint32_t MAX_SIZE = INT_MAX;
53 constexpr uint8_t SHIFT = 32;
54 } // namespace
EbpfConverter(const std::string & inputPath,const std::string & outPath)55 EbpfConverter::EbpfConverter(const std::string& inputPath, const std::string& outPath)
56 : inputPath_(inputPath), outputPath_(outPath) {}
57
CheckNotExistsFilePath(const std::string & filePath)58 std::pair<bool, std::string> EbpfConverter::CheckNotExistsFilePath(const std::string &filePath)
59 {
60 size_t pos = filePath.rfind('/');
61 std::string pathDir = "";
62 if (pos != std::string::npos) {
63 pathDir = filePath.substr(0, pos);
64 } else {
65 pathDir = ".";
66 }
67 std::unique_ptr<char[]> pathDirRealPath = std::make_unique<char[]>(PATH_MAX);
68 if ((pathDir.length() >= PATH_MAX - 1) || (realpath(pathDir.c_str(), pathDirRealPath.get()) == nullptr)) {
69 std::cout << "path is invalid:" << pathDir << std::endl;
70 return {false, ""};
71 }
72 if (access(pathDir.c_str(), F_OK) != 0) {
73 std::cout << "Fail to access path:" << pathDir << std::endl;
74 return {false, ""};
75 }
76 return {true, std::string(pathDirRealPath.get()) + "/" + filePath.substr(pos + 1)};
77 }
78
~EbpfConverter()79 EbpfConverter::~EbpfConverter()
80 {
81 std::map<std::string, SymbolInfo>::iterator iter;
82 for (iter = symbolInfo_.begin(); iter != symbolInfo_.end(); iter++) {
83 if (iter->second.symTab != nullptr) {
84 delete[] iter->second.symTab;
85 iter->second.symTab = nullptr;
86 }
87 if (iter->second.strTab != nullptr) {
88 delete[] iter->second.strTab;
89 iter->second.strTab = nullptr;
90 }
91 }
92 }
93
StartParsing()94 void EbpfConverter::StartParsing()
95 {
96 if (access(inputPath_.c_str(), R_OK) != 0) {
97 std::cout << "the input file path is invalid" << std::endl;
98 return;
99 }
100 fd_ = open(inputPath_.c_str(), O_RDONLY);
101 if (fd_ < 0) {
102 std::cout << "open " << inputPath_ << " failed" << std::endl;
103 return;
104 }
105 char magic[HEADER_MAGIC + 1];
106 (void)memset_s(magic, sizeof(magic), 0, sizeof(magic));
107 CHK(Read(reinterpret_cast<void*>(&magic), sizeof(magic) - 1));
108 outData_ << "magic: " << magic << '\n';
109 HeaderDataItem header = {};
110 CHK(Read(reinterpret_cast<void*>(&header), sizeof(header)));
111 outData_ << "headSize: " << header.headSize << '\n' << "version: " << header.version << '\n'
112 << "clock: " << header.clock << '\n' << "cmdLineLen: " << header.cmdLineLen;
113
114 char cmdline[header.cmdLineLen + 1];
115 if (header.cmdLineLen > 0) {
116 size_t dataLen = sizeof(cmdline) > 1 ? static_cast<size_t>(sizeof(cmdline) - 1) : 0;
117 CHK(Read(reinterpret_cast<void*>(cmdline), dataLen));
118 outData_ << "\ncmdline: " << cmdline << '\n';
119 }
120 fileSize_ = lseek(fd_, header.headSize, SEEK_SET);
121
122 FILE *file = fopen(outputPath_.c_str(), "w");
123 if (file == nullptr) {
124 std::cout << "create " << outputPath_ << " failed" << std::endl;
125 return;
126 }
127
128 while (true) {
129 uint32_t type = 0;
130 if (read(fd_, reinterpret_cast<void*>(&type), sizeof(type)) <= 0) {
131 break;
132 }
133 switch (type) {
134 case MAPSTRACE: {
135 EventMapsParsing();
136 break;
137 }
138 case SYMBOLTRACE: {
139 SymbolInfoParsing();
140 break;
141 }
142 case FSTRACE: {
143 EventFsParsing();
144 break;
145 }
146 case PFTRACE: {
147 EventMemParsing();
148 break;
149 }
150 case BIOTRACE: {
151 EventBIOParsing();
152 break;
153 }
154 case STRTRACE: {
155 EventStrParsing();
156 break;
157 }
158 default: {
159 std::cout << "Invalid type: " << type << std::endl;
160 if (fd_ >= 0) {
161 close(fd_);
162 }
163 fd_ = -1;
164 fileSize_ = 0;
165 fclose(file);
166 return;
167 }
168 }
169 }
170 if (fd_ >= 0) {
171 close(fd_);
172 }
173 fd_ = -1;
174 fileSize_ = 0;
175 std::cout << "Data read successfully, output..." << std::endl;
176 size_t len = outData_.str().size();
177 if (fwrite(outData_.str().c_str(), 1, len, file) != len) {
178 std::cout << "write data failed" << std::endl;
179 fclose(file);
180 return;
181 }
182 fclose(file);
183 std::cout << "Data parsing success..." << std::endl;
184 }
185
Read(void * buffer,size_t size)186 bool EbpfConverter::Read(void* buffer, size_t size)
187 {
188 if (fd_ < 0) {
189 return false;
190 }
191 ssize_t ret = read(fd_, buffer, size);
192 if (ret <= 0) {
193 close(fd_);
194 fd_ = -1;
195 fileSize_ = 0;
196 return false;
197 }
198 return true;
199 }
200
EventFsParsing()201 void EbpfConverter::EventFsParsing()
202 {
203 lseek(fd_, fileSize_, SEEK_SET);
204 EventFs efs = {};
205 CHK(Read(reinterpret_cast<void*>(&efs), EVENT_FS_FIXED_SIZE));
206 uint64_t args[ARGS_NUM] = { 0 };
207 CHK(Read(reinterpret_cast<void*>(args), sizeof(args)));
208 efs.args = std::vector<uint64_t>(args, args + ARGS_NUM);
209 CHK(Read(reinterpret_cast<void*>(&efs.comm), sizeof(efs.comm)));
210 uint64_t userIPs[efs.nrUserIPs];
211 if (efs.nrUserIPs > 0) {
212 CHK(Read(reinterpret_cast<void*>(userIPs), sizeof(userIPs)));
213 efs.userIPs = std::vector<uint64_t>(userIPs, userIPs + efs.nrUserIPs);
214 }
215 fileSize_ = lseek(fd_, 0, SEEK_CUR);
216
217 outData_ << "\nEventFs:\n"
218 << " type: " << efs.tag << '\n'
219 << " len: " << efs.len << '\n'
220 << " pid: " << efs.pid << '\n'
221 << " tid: " << efs.tid << '\n'
222 << " tracerName: " << efs.tracerName << '\n'
223 << " start: " << efs.start << '\n'
224 << " end: " << efs.end << '\n'
225 << " typeName: " << efs.typeName << '\n'
226 << " ret: " << efs.ret << '\n'
227 << " nrUserIPs: " << efs.nrUserIPs << '\n'
228 << " type: " << efs.type << '\n'
229 << " args: ";
230 for (const auto &arg : efs.args) {
231 outData_ << arg << ", ";
232 }
233
234 outData_ << "\n userIPs:\n";
235 for (const auto &ip : efs.userIPs) {
236 if (ip == 0) {
237 continue;
238 }
239 outData_ << " 0x" << std::hex << ip << std::dec << ":";
240 auto itm = GetSymbolInfo(efs.pid, ip);
241 outData_ << "\n vAddr_: 0x" << std::hex << vAddr_[ip] << std::dec << '\n';
242 for (const auto &sym : itm.second) {
243 outData_ << " symbol: " << sym << '\n';
244 }
245 outData_ << " fileName: " << itm.first << '\n';
246 }
247 outData_ << " comm: " << std::string(efs.comm) << '\n';
248 }
249
EventMapsParsing()250 void EbpfConverter::EventMapsParsing()
251 {
252 lseek(fd_, fileSize_, SEEK_SET);
253 EventMaps maps = {};
254 CHK(Read(reinterpret_cast<void*>(&maps), EVENT_MAPS_FIXED_SIZE));
255 char fileName[maps.fileNameLen + 1];
256 (void)memset_s(fileName, sizeof(fileName), 0, sizeof(fileName));
257 if (maps.fileNameLen > 0) {
258 size_t dataLen = sizeof(fileName) > 1 ? sizeof(fileName) - 1 : 0;
259 CHK(Read(reinterpret_cast<void*>(fileName), dataLen));
260 maps.fileName = fileName;
261 }
262 auto iter = maps_.find(maps.pid);
263 if (iter == maps_.end()) {
264 maps_[maps.pid] = std::vector<EventMaps>({ maps });
265 } else {
266 iter->second.push_back(maps);
267 }
268 fileSize_ = lseek(fd_, 0, SEEK_CUR);
269
270 // put output
271 outData_ << "\nEventMaps:\n"
272 << " type: " << maps.type << '\n'
273 << " len: " << maps.len << '\n'
274 << " start: 0x" << std::hex << maps.start << std::dec << '\n'
275 << " end: 0x" << std::hex << maps.end << std::dec << '\n'
276 << " offset: 0x" << std::hex << maps.offset << std::dec << '\n'
277 << " pid: " << maps.pid << '\n'
278 << " fileNameLen: " << maps.fileNameLen << '\n'
279 << " fileName: " << maps.fileName << '\n';
280 }
281
SymbolInfoParsing()282 void EbpfConverter::SymbolInfoParsing()
283 {
284 lseek(fd_, fileSize_, SEEK_SET);
285 uint64_t strAddr = 0;
286 uint64_t symAddr = 0;
287 SymbolInfo info = {};
288 CHK(Read(reinterpret_cast<void*>(&info), EVENT_SYM_FIXED_SIZE));
289 if (info.strTabLen + 1 >= MAX_SIZE) {
290 std::cout << "info size exceeds max size" << std::endl;
291 return;
292 }
293 info.strTab = new char[info.strTabLen + 1];
294 if (memset_s(info.strTab, info.strTabLen + 1, 0, info.strTabLen + 1) != EOK) {
295 std::cout << "memset string table failed" << std::endl;
296 delete[] info.strTab;
297 info.strTab = nullptr;
298 return;
299 }
300 if (info.strTabLen > 0) {
301 auto ret = lseek(fd_, 0, SEEK_CUR);
302 if (ret >= 0) {
303 strAddr = (uint64_t)ret;
304 }
305 if (!Read(reinterpret_cast<void *>(info.strTab), info.strTabLen)) {
306 std::cout << "read string table failed" << std::endl;
307 delete[] info.strTab;
308 info.strTab = nullptr;
309 return;
310 }
311 }
312 if (info.symTabLen + 1 >= MAX_SIZE) {
313 std::cout << "info size exceeds max size" << std::endl;
314 return;
315 }
316 info.symTab = new char[info.symTabLen + 1];
317 if (memset_s(info.symTab, info.symTabLen + 1, 0, info.symTabLen + 1) != EOK) {
318 std::cout << "memset symbol table failed" << std::endl;
319 delete[] info.symTab;
320 info.symTab = nullptr;
321 return;
322 }
323 if (info.symTabLen > 0) {
324 auto ret = lseek(fd_, 0, SEEK_CUR);
325 if (ret >= 0) {
326 symAddr = (uint64_t)ret;
327 }
328 if (!Read(reinterpret_cast<void *>(info.symTab), info.symTabLen)) {
329 std::cout << "read symbol table failed" << std::endl;
330 delete[] info.symTab;
331 info.symTab = nullptr;
332 return;
333 }
334 }
335 char fileName[info.fileNameSize + 1];
336 (void)memset_s(fileName, sizeof(fileName), 0, sizeof(fileName));
337 if (info.fileNameSize > 0) {
338 size_t dataLen = sizeof(fileName) > 1 ? sizeof(fileName) - 1 : 0;
339 if (!Read(reinterpret_cast<void*>(&fileName), dataLen)) {
340 std::cout << "read file name failed" << std::endl;
341 delete[] info.symTab;
342 info.symTab = nullptr;
343 delete[] info.strTab;
344 info.strTab = nullptr;
345 return;
346 }
347 info.fileName = fileName;
348 }
349 record_[std::string(fileName)] = Record(fileName, symAddr, strAddr);
350 symbolInfo_[fileName] = info;
351 fileSize_ = lseek(fd_, 0, SEEK_CUR);
352
353 // put output
354 outData_ << "\nSymbolInfo:\n"
355 << " tag: " << info.type << '\n'
356 << " len: " << info.len << '\n'
357 << " textVaddr: 0x" << std::hex << info.textVaddr << std::dec << '\n'
358 << " textOffset: 0x" << std::hex << info.textOffset << std::dec << '\n'
359 << " strTabLen: 0x" << std::hex << info.strTabLen << std::dec <<'\n'
360 << " symTabLen: 0x" << std::hex << info.symTabLen << std::dec << '\n'
361 << " fileNameSize: " << info.fileNameSize << '\n'
362 << " fileName: " << info.fileName << '\n'
363 << " strTabAddr: 0x" << std::hex << record_[info.fileName].strTabAddr << std::dec << '\n'
364 << " symTabAddr: 0x" << std::hex << record_[info.fileName].symTabAddr << std::dec << '\n';
365 }
366
EventMemParsing()367 void EbpfConverter::EventMemParsing()
368 {
369 lseek(fd_, fileSize_, SEEK_SET);
370 EventMem mem = {};
371 CHK(Read(reinterpret_cast<void*>(&mem), EVENT_MEM_FIXED_SIZE));
372 uint64_t userIPs[mem.nips];
373 if (mem.nips > 0) {
374 CHK(Read(reinterpret_cast<void*>(&userIPs), sizeof(userIPs)));
375 mem.userIPs = std::vector<uint64_t>(userIPs, userIPs + mem.nips);
376 }
377 fileSize_ = lseek(fd_, 0, SEEK_CUR);
378
379 outData_ << "\nEventMem:\n"
380 << " tag: " << mem.tag << '\n'
381 << " len: " << mem.len << '\n'
382 << " pid: " << mem.pid << '\n'
383 << " tid: " << mem.tid << '\n'
384 << " tagName: " << mem.tagName << '\n'
385 << " start: " << mem.start << '\n'
386 << " end: " << mem.end << '\n'
387 << " typeName: " << mem.typeName << '\n'
388 << " addr: " << mem.addr << '\n'
389 << " size: " << mem.size << '\n'
390 << " nips: " << mem.nips << '\n'
391 << " type: " << mem.type << '\n'
392 << " comm: " << mem.comm << '\n'
393 << " userIPs:\n";
394 for (const auto &ip : mem.userIPs) {
395 if (ip == 0) {
396 continue;
397 }
398 outData_ << " 0x" << std::hex << ip << std::dec << ":";
399 auto itm = GetSymbolInfo(mem.pid, ip);
400 outData_ << "\n vAddr_: 0x" << std::hex << vAddr_[ip] << std::dec << '\n';
401 for (const auto &sym : itm.second) {
402 outData_ << " symbol: " << sym << '\n';
403 }
404 outData_ << " fileName: " << itm.first << '\n';
405 }
406 }
407
EventStrParsing()408 void EbpfConverter::EventStrParsing()
409 {
410 lseek(fd_, fileSize_, SEEK_SET);
411 EventStr str = {};
412 CHK(Read(reinterpret_cast<void*>(&str), EVENT_STR_FIXED_SIZE));
413 char fileName[str.strLen + 1];
414 if (str.strLen > 0) {
415 size_t dataLen = sizeof(fileName) > 1 ? static_cast<size_t>(sizeof(fileName) - 1) : 0;
416 CHK(Read(reinterpret_cast<void*>(&fileName), dataLen));
417 str.fileName = fileName;
418 }
419 str_.push_back(str);
420 int32_t newPos = static_cast<int32_t>(str.len - SHIFT - str.strLen);
421 fileSize_ = lseek(fd_, lseek(fd_, 0, SEEK_CUR) + newPos, SEEK_SET);
422
423 outData_ << "\nEventStr:\n"
424 << " tag: " << str.tag << '\n'
425 << " len: " << str.len << '\n'
426 << " pid: " << str.pid << '\n'
427 << " tid: " << str.tid << '\n'
428 << " start: " << str.start << '\n'
429 << " srcTracer: " << str.srcTracer << '\n'
430 << " srcType: " << str.srcType << '\n'
431 << " strLen: " << str.strLen << '\n'
432 << " fileName: " << str.fileName << '\n';
433 }
434
EventBIOParsing()435 void EbpfConverter::EventBIOParsing()
436 {
437 lseek(fd_, fileSize_, SEEK_SET);
438 EventBIO bio = {};
439 CHK(Read(reinterpret_cast<void*>(&bio), EVENT_BIO_FIXED_SIZE));
440 uint64_t userIPs[bio.nips];
441 if (bio.nips > 0) {
442 CHK(Read(reinterpret_cast<void*>(userIPs), sizeof(userIPs)));
443 bio.userIPs = std::vector<uint64_t>(userIPs, userIPs + bio.nips);
444 }
445 fileSize_ = lseek(fd_, 0, SEEK_CUR);
446
447 outData_ << "\nEventBIO:\n"
448 << " tag: " << bio.tag << '\n'
449 << " len: " << bio.len << '\n'
450 << " pid: " << bio.pid << '\n'
451 << " tid: " << bio.tid << '\n'
452 << " comm: " << bio.comm << '\n'
453 << " start: " << bio.start << '\n'
454 << " end: " << bio.end << '\n'
455 << " prio: " << bio.prio << '\n'
456 << " size: " << bio.size << '\n'
457 << " type: " << bio.type << '\n'
458 << " typeName: " << bio.typeName << '\n';
459
460 for (const auto &ip : bio.userIPs) {
461 if (ip == 0) {
462 continue;
463 }
464 outData_ << " 0x" << std::hex << ip << std::dec << ":";
465 auto itm = GetSymbolInfo(bio.pid, ip);
466 outData_ << "\n vAddr_: 0x" << std::hex << vAddr_[ip] << std::dec << '\n';
467 for (const auto &sym : itm.second) {
468 outData_ << " symbol: " << sym << '\n';
469 }
470 outData_ << " fileName: " << itm.first << '\n';
471 }
472 }
473
GetSymbolInfo(uint64_t pid,uint64_t ip)474 std::pair<std::string, std::vector<std::string>> EbpfConverter::GetSymbolInfo(uint64_t pid, uint64_t ip)
475 {
476 auto mapIter = maps_.find(pid);
477 if (mapIter == maps_.end()) {
478 return std::pair<std::string, std::vector<std::string>>();
479 }
480
481 std::string fileName;
482 uint64_t start = 0;
483 uint32_t offset = 0;
484 std::any_of(mapIter->second.begin(), mapIter->second.end(), [&](const EventMaps &maps) {
485 if (ip >= maps.start && ip <= maps.end) {
486 fileName = maps.fileName;
487 start = maps.start;
488 offset = maps.offset;
489 return true;
490 }
491 return false;
492 });
493 if (fileName.empty()) {
494 return std::pair<std::string, std::vector<std::string>>();
495 }
496
497 auto symItem = symbolInfo_.find(fileName);
498 if (symItem == symbolInfo_.end()) {
499 return std::pair<std::string, std::vector<std::string>>();
500 }
501 uint64_t vaddr = ip - start + offset - symItem->second.textOffset + symItem->second.textVaddr;
502 vAddr_[ip] = vaddr;
503 std::pair<std::string, std::vector<std::string>> symbolInfos;
504 symbolInfos.first = fileName;
505 if (symItem->second.symEntlen == SYM_ENT_LEN_64) {
506 uint32_t count = 0;
507 while (count < symItem->second.symTabLen) {
508 Elf64_Sym sym;
509 if (memcpy_s(&sym, sizeof(sym), symItem->second.symTab + count, SYM_ENT_LEN_64) != EOK) {
510 std::cout << "copy symTab failed" << std::endl;
511 return std::pair<std::string, std::vector<std::string>>();
512 }
513 if (vaddr >= sym.st_value &&
514 vaddr <= sym.st_value + sym.st_size &&
515 (sym.st_info & STT_FUNC) &&
516 sym.st_value != 0) {
517 char *ret = abi::__cxa_demangle(static_cast<char *>(symItem->second.strTab + sym.st_name),
518 nullptr, nullptr, nullptr);
519 ret == nullptr ? symbolInfos.second.push_back(std::string(symItem->second.strTab + sym.st_name))
520 : symbolInfos.second.push_back(std::string(ret));
521 }
522 count += SYM_ENT_LEN_64;
523 }
524 } else if (symItem->second.symEntlen == SYM_ENT_LEN_32) {
525 uint32_t count = 0;
526 while (count < symItem->second.symTabLen) {
527 Elf32_Sym sym;
528 if (memcpy_s(&sym, sizeof(sym), symItem->second.strTab + count, SYM_ENT_LEN_32) != EOK) {
529 std::cout << "copy symTab failed" << std::endl;
530 return std::pair<std::string, std::vector<std::string>>();
531 }
532 if (vaddr >= sym.st_value &&
533 vaddr <= sym.st_value + sym.st_size &&
534 (sym.st_info & STT_FUNC) &&
535 sym.st_value != 0) {
536 char *ret = abi::__cxa_demangle(symItem->second.strTab + sym.st_name, nullptr, nullptr, nullptr);
537 ret == nullptr ? symbolInfos.second.push_back(std::string(symItem->second.strTab + sym.st_name))
538 : symbolInfos.second.push_back(std::string(ret));
539 }
540 count += SYM_ENT_LEN_32;
541 }
542 } else {
543 std::cout << "Invalid symEntlen" << std::endl;
544 }
545 return symbolInfos;
546 }
547 } // EBPF_TOOLS
548 } // OHOS
549
main(int32_t argc,char * argv[])550 int32_t main(int32_t argc, char* argv[])
551 {
552 std::ios::sync_with_stdio(false);
553 std::cin.tie(nullptr);
554 struct option long_options[] = {
555 {"input", required_argument, nullptr, 'i'},
556 {"out", required_argument, nullptr, 'o'},
557 {"help", no_argument, nullptr, 'h'},
558 {0, 0, 0, 0}
559 };
560 int32_t opt;
561 std::string inputPath, outputPath;
562 while ((opt = getopt_long(argc, argv, "i:o:h", long_options, nullptr)) != -1) {
563 switch (opt) {
564 case 'i': {
565 inputPath = optarg;
566 continue;
567 }
568 case 'o': {
569 outputPath = optarg;
570 continue;
571 }
572 case 'h': {
573 std::cout << " --input" << " " << "-i" << " :" << "input file name" << std::endl;
574 std::cout << " --out" << " " << "-o" << " :" << "out file name" << std::endl;
575 break;
576 }
577 default: {
578 std::cout << "Parameter error" << std::endl;
579 break;
580 }
581 }
582 }
583 auto retFileInput = OHOS::EBPF_TOOLS::EbpfConverter::CheckNotExistsFilePath(inputPath);
584 auto retFileOutput = OHOS::EBPF_TOOLS::EbpfConverter::CheckNotExistsFilePath(outputPath);
585 if (!retFileInput.first) {
586 std::cout << "check input file path" << inputPath << " fail!" << std::endl;
587 return 0;
588 }
589 if (!retFileOutput.first) {
590 std::cout << "check output file path" << outputPath << " fail!" << std::endl;
591 return 0;
592 }
593 OHOS::EBPF_TOOLS::EbpfConverter ec(retFileInput.second, retFileOutput.second);
594 ec.StartParsing();
595 return 0;
596 }