• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }