xref: /aosp_15_r20/external/bcc/src/cc/bpf_module.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) 2015 PLUMgrid, Inc.
3*387f9dfdSAndroid Build Coastguard Worker  *
4*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker  *
8*387f9dfdSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker  *
10*387f9dfdSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker  * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker  */
16*387f9dfdSAndroid Build Coastguard Worker #include "bpf_module.h"
17*387f9dfdSAndroid Build Coastguard Worker 
18*387f9dfdSAndroid Build Coastguard Worker #include <fcntl.h>
19*387f9dfdSAndroid Build Coastguard Worker #include <linux/bpf.h>
20*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR <= 16
21*387f9dfdSAndroid Build Coastguard Worker #include <llvm-c/Transforms/IPO.h>
22*387f9dfdSAndroid Build Coastguard Worker #endif
23*387f9dfdSAndroid Build Coastguard Worker #include <llvm/ExecutionEngine/MCJIT.h>
24*387f9dfdSAndroid Build Coastguard Worker #include <llvm/ExecutionEngine/SectionMemoryManager.h>
25*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 16
26*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IRPrinter/IRPrintingPasses.h>
27*387f9dfdSAndroid Build Coastguard Worker #else
28*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/IRPrintingPasses.h>
29*387f9dfdSAndroid Build Coastguard Worker #endif
30*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/LLVMContext.h>
31*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/Module.h>
32*387f9dfdSAndroid Build Coastguard Worker 
33*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 15
34*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Pass.h>
35*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/PassManager.h>
36*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Passes/PassBuilder.h>
37*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Transforms/IPO/AlwaysInliner.h>
38*387f9dfdSAndroid Build Coastguard Worker #else
39*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/LegacyPassManager.h>
40*387f9dfdSAndroid Build Coastguard Worker #endif
41*387f9dfdSAndroid Build Coastguard Worker 
42*387f9dfdSAndroid Build Coastguard Worker #include <llvm/IR/Verifier.h>
43*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Object/ObjectFile.h>
44*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Object/ELFObjectFile.h>
45*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Object/SymbolSize.h>
46*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Support/TargetSelect.h>
47*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Transforms/IPO.h>
48*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR <= 16
49*387f9dfdSAndroid Build Coastguard Worker #include <llvm/Transforms/IPO/PassManagerBuilder.h>
50*387f9dfdSAndroid Build Coastguard Worker #endif
51*387f9dfdSAndroid Build Coastguard Worker #include <net/if.h>
52*387f9dfdSAndroid Build Coastguard Worker #include <sys/stat.h>
53*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
54*387f9dfdSAndroid Build Coastguard Worker 
55*387f9dfdSAndroid Build Coastguard Worker #include <map>
56*387f9dfdSAndroid Build Coastguard Worker #include <set>
57*387f9dfdSAndroid Build Coastguard Worker #include <string>
58*387f9dfdSAndroid Build Coastguard Worker #include <iostream>
59*387f9dfdSAndroid Build Coastguard Worker #include <vector>
60*387f9dfdSAndroid Build Coastguard Worker 
61*387f9dfdSAndroid Build Coastguard Worker #include "bcc_btf.h"
62*387f9dfdSAndroid Build Coastguard Worker #include "bcc_debug.h"
63*387f9dfdSAndroid Build Coastguard Worker #include "bcc_elf.h"
64*387f9dfdSAndroid Build Coastguard Worker #include "bcc_libbpf_inc.h"
65*387f9dfdSAndroid Build Coastguard Worker #include "common.h"
66*387f9dfdSAndroid Build Coastguard Worker #include "exported_files.h"
67*387f9dfdSAndroid Build Coastguard Worker #include "frontends/clang/b_frontend_action.h"
68*387f9dfdSAndroid Build Coastguard Worker #include "frontends/clang/loader.h"
69*387f9dfdSAndroid Build Coastguard Worker #include "libbpf.h"
70*387f9dfdSAndroid Build Coastguard Worker 
71*387f9dfdSAndroid Build Coastguard Worker namespace ebpf {
72*387f9dfdSAndroid Build Coastguard Worker 
73*387f9dfdSAndroid Build Coastguard Worker using std::get;
74*387f9dfdSAndroid Build Coastguard Worker using std::make_tuple;
75*387f9dfdSAndroid Build Coastguard Worker using std::map;
76*387f9dfdSAndroid Build Coastguard Worker using std::move;
77*387f9dfdSAndroid Build Coastguard Worker using std::string;
78*387f9dfdSAndroid Build Coastguard Worker using std::tuple;
79*387f9dfdSAndroid Build Coastguard Worker using std::unique_ptr;
80*387f9dfdSAndroid Build Coastguard Worker using std::vector;
81*387f9dfdSAndroid Build Coastguard Worker using namespace llvm;
82*387f9dfdSAndroid Build Coastguard Worker 
83*387f9dfdSAndroid Build Coastguard Worker // Snooping class to remember the sections as the JIT creates them
84*387f9dfdSAndroid Build Coastguard Worker class MyMemoryManager : public SectionMemoryManager {
85*387f9dfdSAndroid Build Coastguard Worker  public:
MyMemoryManager(sec_map_def * sections,ProgFuncInfo * prog_func_info)86*387f9dfdSAndroid Build Coastguard Worker   explicit MyMemoryManager(sec_map_def *sections, ProgFuncInfo *prog_func_info)
87*387f9dfdSAndroid Build Coastguard Worker       : sections_(sections), prog_func_info_(prog_func_info) {}
88*387f9dfdSAndroid Build Coastguard Worker 
~MyMemoryManager()89*387f9dfdSAndroid Build Coastguard Worker   virtual ~MyMemoryManager() {}
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName)90*387f9dfdSAndroid Build Coastguard Worker   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
91*387f9dfdSAndroid Build Coastguard Worker                                unsigned SectionID,
92*387f9dfdSAndroid Build Coastguard Worker                                StringRef SectionName) override {
93*387f9dfdSAndroid Build Coastguard Worker     // The programs need to change from fake fd to real map fd, so not allocate ReadOnly regions.
94*387f9dfdSAndroid Build Coastguard Worker     uint8_t *Addr = SectionMemoryManager::allocateDataSection(Size, Alignment, SectionID, SectionName, false);
95*387f9dfdSAndroid Build Coastguard Worker     (*sections_)[SectionName.str()] = make_tuple(Addr, Size, SectionID);
96*387f9dfdSAndroid Build Coastguard Worker     return Addr;
97*387f9dfdSAndroid Build Coastguard Worker   }
allocateDataSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName,bool isReadOnly)98*387f9dfdSAndroid Build Coastguard Worker   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
99*387f9dfdSAndroid Build Coastguard Worker                                unsigned SectionID, StringRef SectionName,
100*387f9dfdSAndroid Build Coastguard Worker                                bool isReadOnly) override {
101*387f9dfdSAndroid Build Coastguard Worker     // The lines in .BTF.ext line_info, if corresponding to remapped files, will have empty source line.
102*387f9dfdSAndroid Build Coastguard Worker     // The line_info will be fixed in place, so not allocate ReadOnly regions.
103*387f9dfdSAndroid Build Coastguard Worker     uint8_t *Addr = SectionMemoryManager::allocateDataSection(Size, Alignment, SectionID, SectionName, false);
104*387f9dfdSAndroid Build Coastguard Worker     (*sections_)[SectionName.str()] = make_tuple(Addr, Size, SectionID);
105*387f9dfdSAndroid Build Coastguard Worker     return Addr;
106*387f9dfdSAndroid Build Coastguard Worker   }
107*387f9dfdSAndroid Build Coastguard Worker 
notifyObjectLoaded(ExecutionEngine * EE,const object::ObjectFile & o)108*387f9dfdSAndroid Build Coastguard Worker   void notifyObjectLoaded(ExecutionEngine *EE,
109*387f9dfdSAndroid Build Coastguard Worker                           const object::ObjectFile &o) override {
110*387f9dfdSAndroid Build Coastguard Worker     auto sizes = llvm::object::computeSymbolSizes(o);
111*387f9dfdSAndroid Build Coastguard Worker     for (auto ss : sizes) {
112*387f9dfdSAndroid Build Coastguard Worker       auto maybe_name = ss.first.getName();
113*387f9dfdSAndroid Build Coastguard Worker       if (!maybe_name)
114*387f9dfdSAndroid Build Coastguard Worker         continue;
115*387f9dfdSAndroid Build Coastguard Worker 
116*387f9dfdSAndroid Build Coastguard Worker       std::string name = maybe_name->str();
117*387f9dfdSAndroid Build Coastguard Worker       auto info = prog_func_info_->get_func(name);
118*387f9dfdSAndroid Build Coastguard Worker       if (!info)
119*387f9dfdSAndroid Build Coastguard Worker         continue;
120*387f9dfdSAndroid Build Coastguard Worker 
121*387f9dfdSAndroid Build Coastguard Worker       auto section = ss.first.getSection();
122*387f9dfdSAndroid Build Coastguard Worker       if (!section)
123*387f9dfdSAndroid Build Coastguard Worker         continue;
124*387f9dfdSAndroid Build Coastguard Worker 
125*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 10
126*387f9dfdSAndroid Build Coastguard Worker       auto sec_name = section.get()->getName();
127*387f9dfdSAndroid Build Coastguard Worker       if (!sec_name)
128*387f9dfdSAndroid Build Coastguard Worker         continue;
129*387f9dfdSAndroid Build Coastguard Worker #else
130*387f9dfdSAndroid Build Coastguard Worker       llvm::StringRef sec_name_obj;
131*387f9dfdSAndroid Build Coastguard Worker       if (!section.get()->getName(sec_name_obj))
132*387f9dfdSAndroid Build Coastguard Worker         continue;
133*387f9dfdSAndroid Build Coastguard Worker 
134*387f9dfdSAndroid Build Coastguard Worker       auto sec_name = &sec_name_obj;
135*387f9dfdSAndroid Build Coastguard Worker #endif
136*387f9dfdSAndroid Build Coastguard Worker       info->section_ = sec_name->str();
137*387f9dfdSAndroid Build Coastguard Worker       info->size_ = ss.second;
138*387f9dfdSAndroid Build Coastguard Worker     }
139*387f9dfdSAndroid Build Coastguard Worker   }
140*387f9dfdSAndroid Build Coastguard Worker 
141*387f9dfdSAndroid Build Coastguard Worker   sec_map_def *sections_;
142*387f9dfdSAndroid Build Coastguard Worker   ProgFuncInfo *prog_func_info_;
143*387f9dfdSAndroid Build Coastguard Worker };
144*387f9dfdSAndroid Build Coastguard Worker 
BPFModule(unsigned flags,TableStorage * ts,bool rw_engine_enabled,const std::string & maps_ns,bool allow_rlimit,const char * dev_name)145*387f9dfdSAndroid Build Coastguard Worker BPFModule::BPFModule(unsigned flags, TableStorage *ts, bool rw_engine_enabled,
146*387f9dfdSAndroid Build Coastguard Worker                      const std::string &maps_ns, bool allow_rlimit,
147*387f9dfdSAndroid Build Coastguard Worker                      const char *dev_name)
148*387f9dfdSAndroid Build Coastguard Worker     : flags_(flags),
149*387f9dfdSAndroid Build Coastguard Worker       rw_engine_enabled_(rw_engine_enabled && bpf_module_rw_engine_enabled()),
150*387f9dfdSAndroid Build Coastguard Worker       used_b_loader_(false),
151*387f9dfdSAndroid Build Coastguard Worker       allow_rlimit_(allow_rlimit),
152*387f9dfdSAndroid Build Coastguard Worker       ctx_(new LLVMContext),
153*387f9dfdSAndroid Build Coastguard Worker       id_(std::to_string((uintptr_t)this)),
154*387f9dfdSAndroid Build Coastguard Worker       maps_ns_(maps_ns),
155*387f9dfdSAndroid Build Coastguard Worker       ts_(ts), btf_(nullptr) {
156*387f9dfdSAndroid Build Coastguard Worker   ifindex_ = dev_name ? if_nametoindex(dev_name) : 0;
157*387f9dfdSAndroid Build Coastguard Worker   initialize_rw_engine();
158*387f9dfdSAndroid Build Coastguard Worker   LLVMInitializeBPFTarget();
159*387f9dfdSAndroid Build Coastguard Worker   LLVMInitializeBPFTargetMC();
160*387f9dfdSAndroid Build Coastguard Worker   LLVMInitializeBPFTargetInfo();
161*387f9dfdSAndroid Build Coastguard Worker   LLVMInitializeBPFAsmPrinter();
162*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 6
163*387f9dfdSAndroid Build Coastguard Worker   LLVMInitializeBPFAsmParser();
164*387f9dfdSAndroid Build Coastguard Worker   if (flags & DEBUG_SOURCE)
165*387f9dfdSAndroid Build Coastguard Worker     LLVMInitializeBPFDisassembler();
166*387f9dfdSAndroid Build Coastguard Worker #endif
167*387f9dfdSAndroid Build Coastguard Worker   LLVMLinkInMCJIT(); /* call empty function to force linking of MCJIT */
168*387f9dfdSAndroid Build Coastguard Worker   if (!ts_) {
169*387f9dfdSAndroid Build Coastguard Worker     local_ts_ = createSharedTableStorage();
170*387f9dfdSAndroid Build Coastguard Worker     ts_ = &*local_ts_;
171*387f9dfdSAndroid Build Coastguard Worker   }
172*387f9dfdSAndroid Build Coastguard Worker   prog_func_info_ = ebpf::make_unique<ProgFuncInfo>();
173*387f9dfdSAndroid Build Coastguard Worker }
174*387f9dfdSAndroid Build Coastguard Worker 
unimplemented_sscanf(const char *,void *)175*387f9dfdSAndroid Build Coastguard Worker static StatusTuple unimplemented_sscanf(const char *, void *) {
176*387f9dfdSAndroid Build Coastguard Worker   return StatusTuple(-1, "sscanf unimplemented");
177*387f9dfdSAndroid Build Coastguard Worker }
unimplemented_snprintf(char *,size_t,const void *)178*387f9dfdSAndroid Build Coastguard Worker static StatusTuple unimplemented_snprintf(char *, size_t, const void *) {
179*387f9dfdSAndroid Build Coastguard Worker   return StatusTuple(-1, "snprintf unimplemented");
180*387f9dfdSAndroid Build Coastguard Worker }
181*387f9dfdSAndroid Build Coastguard Worker 
~BPFModule()182*387f9dfdSAndroid Build Coastguard Worker BPFModule::~BPFModule() {
183*387f9dfdSAndroid Build Coastguard Worker   for (auto &v : tables_) {
184*387f9dfdSAndroid Build Coastguard Worker     v->key_sscanf = unimplemented_sscanf;
185*387f9dfdSAndroid Build Coastguard Worker     v->leaf_sscanf = unimplemented_sscanf;
186*387f9dfdSAndroid Build Coastguard Worker     v->key_snprintf = unimplemented_snprintf;
187*387f9dfdSAndroid Build Coastguard Worker     v->leaf_snprintf = unimplemented_snprintf;
188*387f9dfdSAndroid Build Coastguard Worker   }
189*387f9dfdSAndroid Build Coastguard Worker 
190*387f9dfdSAndroid Build Coastguard Worker   if (!rw_engine_enabled_) {
191*387f9dfdSAndroid Build Coastguard Worker     prog_func_info_->for_each_func(
192*387f9dfdSAndroid Build Coastguard Worker         [&](std::string name, FuncInfo &info) {
193*387f9dfdSAndroid Build Coastguard Worker       if (!info.start_)
194*387f9dfdSAndroid Build Coastguard Worker         return;
195*387f9dfdSAndroid Build Coastguard Worker       delete[] info.start_;
196*387f9dfdSAndroid Build Coastguard Worker     });
197*387f9dfdSAndroid Build Coastguard Worker     for (auto &section : sections_) {
198*387f9dfdSAndroid Build Coastguard Worker       delete[] std::get<0>(section.second);
199*387f9dfdSAndroid Build Coastguard Worker     }
200*387f9dfdSAndroid Build Coastguard Worker   }
201*387f9dfdSAndroid Build Coastguard Worker 
202*387f9dfdSAndroid Build Coastguard Worker   engine_.reset();
203*387f9dfdSAndroid Build Coastguard Worker   cleanup_rw_engine();
204*387f9dfdSAndroid Build Coastguard Worker   ctx_.reset();
205*387f9dfdSAndroid Build Coastguard Worker   prog_func_info_.reset();
206*387f9dfdSAndroid Build Coastguard Worker 
207*387f9dfdSAndroid Build Coastguard Worker   if (btf_)
208*387f9dfdSAndroid Build Coastguard Worker     delete btf_;
209*387f9dfdSAndroid Build Coastguard Worker 
210*387f9dfdSAndroid Build Coastguard Worker   ts_->DeletePrefix(Path({id_}));
211*387f9dfdSAndroid Build Coastguard Worker }
212*387f9dfdSAndroid Build Coastguard Worker 
free_bcc_memory()213*387f9dfdSAndroid Build Coastguard Worker int BPFModule::free_bcc_memory() {
214*387f9dfdSAndroid Build Coastguard Worker   return bcc_free_memory();
215*387f9dfdSAndroid Build Coastguard Worker }
216*387f9dfdSAndroid Build Coastguard Worker 
217*387f9dfdSAndroid Build Coastguard Worker // load an entire c file as a module
load_cfile(const string & file,bool in_memory,const char * cflags[],int ncflags)218*387f9dfdSAndroid Build Coastguard Worker int BPFModule::load_cfile(const string &file, bool in_memory, const char *cflags[], int ncflags) {
219*387f9dfdSAndroid Build Coastguard Worker   ClangLoader clang_loader(&*ctx_, flags_);
220*387f9dfdSAndroid Build Coastguard Worker   if (clang_loader.parse(&mod_, *ts_, file, in_memory, cflags, ncflags, id_,
221*387f9dfdSAndroid Build Coastguard Worker                          *prog_func_info_, mod_src_, maps_ns_, fake_fd_map_,
222*387f9dfdSAndroid Build Coastguard Worker                          perf_events_))
223*387f9dfdSAndroid Build Coastguard Worker     return -1;
224*387f9dfdSAndroid Build Coastguard Worker   return 0;
225*387f9dfdSAndroid Build Coastguard Worker }
226*387f9dfdSAndroid Build Coastguard Worker 
227*387f9dfdSAndroid Build Coastguard Worker // NOTE: this is a duplicate of the above, but planning to deprecate if we
228*387f9dfdSAndroid Build Coastguard Worker // settle on clang as the frontend
229*387f9dfdSAndroid Build Coastguard Worker 
230*387f9dfdSAndroid Build Coastguard Worker // Load in a pre-built list of functions into the initial Module object, then
231*387f9dfdSAndroid Build Coastguard Worker // build an ExecutionEngine.
load_includes(const string & text)232*387f9dfdSAndroid Build Coastguard Worker int BPFModule::load_includes(const string &text) {
233*387f9dfdSAndroid Build Coastguard Worker   ClangLoader clang_loader(&*ctx_, flags_);
234*387f9dfdSAndroid Build Coastguard Worker   const char *cflags[] = {"-DB_WORKAROUND"};
235*387f9dfdSAndroid Build Coastguard Worker   if (clang_loader.parse(&mod_, *ts_, text, true, cflags, 1, "",
236*387f9dfdSAndroid Build Coastguard Worker                          *prog_func_info_, mod_src_, "", fake_fd_map_,
237*387f9dfdSAndroid Build Coastguard Worker                          perf_events_))
238*387f9dfdSAndroid Build Coastguard Worker     return -1;
239*387f9dfdSAndroid Build Coastguard Worker   return 0;
240*387f9dfdSAndroid Build Coastguard Worker }
241*387f9dfdSAndroid Build Coastguard Worker 
annotate_light()242*387f9dfdSAndroid Build Coastguard Worker void BPFModule::annotate_light() {
243*387f9dfdSAndroid Build Coastguard Worker   for (auto fn = mod_->getFunctionList().begin(); fn != mod_->getFunctionList().end(); ++fn)
244*387f9dfdSAndroid Build Coastguard Worker     if (!fn->hasFnAttribute(Attribute::NoInline))
245*387f9dfdSAndroid Build Coastguard Worker       fn->addFnAttr(Attribute::AlwaysInline);
246*387f9dfdSAndroid Build Coastguard Worker 
247*387f9dfdSAndroid Build Coastguard Worker   size_t id = 0;
248*387f9dfdSAndroid Build Coastguard Worker   Path path({id_});
249*387f9dfdSAndroid Build Coastguard Worker   for (auto it = ts_->lower_bound(path), up = ts_->upper_bound(path); it != up; ++it) {
250*387f9dfdSAndroid Build Coastguard Worker     TableDesc &table = it->second;
251*387f9dfdSAndroid Build Coastguard Worker     tables_.push_back(&it->second);
252*387f9dfdSAndroid Build Coastguard Worker     table_names_[table.name] = id++;
253*387f9dfdSAndroid Build Coastguard Worker   }
254*387f9dfdSAndroid Build Coastguard Worker }
255*387f9dfdSAndroid Build Coastguard Worker 
dump_ir(Module & mod)256*387f9dfdSAndroid Build Coastguard Worker void BPFModule::dump_ir(Module &mod) {
257*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 15
258*387f9dfdSAndroid Build Coastguard Worker   // Create the analysis managers
259*387f9dfdSAndroid Build Coastguard Worker   LoopAnalysisManager LAM;
260*387f9dfdSAndroid Build Coastguard Worker   FunctionAnalysisManager FAM;
261*387f9dfdSAndroid Build Coastguard Worker   CGSCCAnalysisManager CGAM;
262*387f9dfdSAndroid Build Coastguard Worker   ModuleAnalysisManager MAM;
263*387f9dfdSAndroid Build Coastguard Worker 
264*387f9dfdSAndroid Build Coastguard Worker   // Create the pass manager
265*387f9dfdSAndroid Build Coastguard Worker   PassBuilder PB;
266*387f9dfdSAndroid Build Coastguard Worker   PB.registerModuleAnalyses(MAM);
267*387f9dfdSAndroid Build Coastguard Worker   PB.registerCGSCCAnalyses(CGAM);
268*387f9dfdSAndroid Build Coastguard Worker   PB.registerFunctionAnalyses(FAM);
269*387f9dfdSAndroid Build Coastguard Worker   PB.registerLoopAnalyses(LAM);
270*387f9dfdSAndroid Build Coastguard Worker   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
271*387f9dfdSAndroid Build Coastguard Worker   auto MPM = PB.buildPerModuleDefaultPipeline(OptimizationLevel::O2);
272*387f9dfdSAndroid Build Coastguard Worker 
273*387f9dfdSAndroid Build Coastguard Worker   // Add passes and run
274*387f9dfdSAndroid Build Coastguard Worker   MPM.addPass(PrintModulePass(errs()));
275*387f9dfdSAndroid Build Coastguard Worker   MPM.run(mod, MAM);
276*387f9dfdSAndroid Build Coastguard Worker #else
277*387f9dfdSAndroid Build Coastguard Worker   legacy::PassManager PM;
278*387f9dfdSAndroid Build Coastguard Worker   PM.add(createPrintModulePass(errs()));
279*387f9dfdSAndroid Build Coastguard Worker   PM.run(mod);
280*387f9dfdSAndroid Build Coastguard Worker #endif
281*387f9dfdSAndroid Build Coastguard Worker }
282*387f9dfdSAndroid Build Coastguard Worker 
run_pass_manager(Module & mod)283*387f9dfdSAndroid Build Coastguard Worker int BPFModule::run_pass_manager(Module &mod) {
284*387f9dfdSAndroid Build Coastguard Worker   if (verifyModule(mod, &errs())) {
285*387f9dfdSAndroid Build Coastguard Worker     if (flags_ & DEBUG_LLVM_IR)
286*387f9dfdSAndroid Build Coastguard Worker       dump_ir(mod);
287*387f9dfdSAndroid Build Coastguard Worker     return -1;
288*387f9dfdSAndroid Build Coastguard Worker   }
289*387f9dfdSAndroid Build Coastguard Worker 
290*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 15
291*387f9dfdSAndroid Build Coastguard Worker   // Create the analysis managers
292*387f9dfdSAndroid Build Coastguard Worker   LoopAnalysisManager LAM;
293*387f9dfdSAndroid Build Coastguard Worker   FunctionAnalysisManager FAM;
294*387f9dfdSAndroid Build Coastguard Worker   CGSCCAnalysisManager CGAM;
295*387f9dfdSAndroid Build Coastguard Worker   ModuleAnalysisManager MAM;
296*387f9dfdSAndroid Build Coastguard Worker 
297*387f9dfdSAndroid Build Coastguard Worker   // Create the pass manager
298*387f9dfdSAndroid Build Coastguard Worker   PassBuilder PB;
299*387f9dfdSAndroid Build Coastguard Worker   PB.registerModuleAnalyses(MAM);
300*387f9dfdSAndroid Build Coastguard Worker   PB.registerCGSCCAnalyses(CGAM);
301*387f9dfdSAndroid Build Coastguard Worker   PB.registerFunctionAnalyses(FAM);
302*387f9dfdSAndroid Build Coastguard Worker   PB.registerLoopAnalyses(LAM);
303*387f9dfdSAndroid Build Coastguard Worker   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
304*387f9dfdSAndroid Build Coastguard Worker   auto MPM = PB.buildPerModuleDefaultPipeline(OptimizationLevel::O3);
305*387f9dfdSAndroid Build Coastguard Worker 
306*387f9dfdSAndroid Build Coastguard Worker   // Add passes and run
307*387f9dfdSAndroid Build Coastguard Worker   MPM.addPass(AlwaysInlinerPass());
308*387f9dfdSAndroid Build Coastguard Worker   if (flags_ & DEBUG_LLVM_IR)
309*387f9dfdSAndroid Build Coastguard Worker     MPM.addPass(PrintModulePass(outs()));
310*387f9dfdSAndroid Build Coastguard Worker   MPM.run(mod, MAM);
311*387f9dfdSAndroid Build Coastguard Worker #else
312*387f9dfdSAndroid Build Coastguard Worker   legacy::PassManager PM;
313*387f9dfdSAndroid Build Coastguard Worker   PassManagerBuilder PMB;
314*387f9dfdSAndroid Build Coastguard Worker   PMB.OptLevel = 3;
315*387f9dfdSAndroid Build Coastguard Worker   PM.add(createFunctionInliningPass());
316*387f9dfdSAndroid Build Coastguard Worker   /*
317*387f9dfdSAndroid Build Coastguard Worker    * llvm < 4.0 needs
318*387f9dfdSAndroid Build Coastguard Worker    * PM.add(createAlwaysInlinerPass());
319*387f9dfdSAndroid Build Coastguard Worker    * llvm >= 4.0 needs
320*387f9dfdSAndroid Build Coastguard Worker    * PM.add(createAlwaysInlinerLegacyPass());
321*387f9dfdSAndroid Build Coastguard Worker    * use below 'stable' workaround
322*387f9dfdSAndroid Build Coastguard Worker    */
323*387f9dfdSAndroid Build Coastguard Worker   LLVMAddAlwaysInlinerPass(reinterpret_cast<LLVMPassManagerRef>(&PM));
324*387f9dfdSAndroid Build Coastguard Worker   PMB.populateModulePassManager(PM);
325*387f9dfdSAndroid Build Coastguard Worker   if (flags_ & DEBUG_LLVM_IR)
326*387f9dfdSAndroid Build Coastguard Worker     PM.add(createPrintModulePass(outs()));
327*387f9dfdSAndroid Build Coastguard Worker   PM.run(mod);
328*387f9dfdSAndroid Build Coastguard Worker #endif
329*387f9dfdSAndroid Build Coastguard Worker 
330*387f9dfdSAndroid Build Coastguard Worker   return 0;
331*387f9dfdSAndroid Build Coastguard Worker }
332*387f9dfdSAndroid Build Coastguard Worker 
load_btf(sec_map_def & sections)333*387f9dfdSAndroid Build Coastguard Worker void BPFModule::load_btf(sec_map_def &sections) {
334*387f9dfdSAndroid Build Coastguard Worker   uint8_t *btf_sec = nullptr, *btf_ext_sec = nullptr;
335*387f9dfdSAndroid Build Coastguard Worker   uintptr_t btf_sec_size = 0, btf_ext_sec_size = 0;
336*387f9dfdSAndroid Build Coastguard Worker 
337*387f9dfdSAndroid Build Coastguard Worker   for (auto section: sections) {
338*387f9dfdSAndroid Build Coastguard Worker     auto sname = section.first;
339*387f9dfdSAndroid Build Coastguard Worker     uint8_t *addr = get<0>(section.second);
340*387f9dfdSAndroid Build Coastguard Worker     uintptr_t size = get<1>(section.second);
341*387f9dfdSAndroid Build Coastguard Worker 
342*387f9dfdSAndroid Build Coastguard Worker     if (strcmp(".BTF", sname.c_str()) == 0) {
343*387f9dfdSAndroid Build Coastguard Worker       btf_sec = addr;
344*387f9dfdSAndroid Build Coastguard Worker       btf_sec_size = size;
345*387f9dfdSAndroid Build Coastguard Worker     }
346*387f9dfdSAndroid Build Coastguard Worker 
347*387f9dfdSAndroid Build Coastguard Worker     if (strcmp(".BTF.ext", sname.c_str()) == 0) {
348*387f9dfdSAndroid Build Coastguard Worker       btf_ext_sec = addr;
349*387f9dfdSAndroid Build Coastguard Worker       btf_ext_sec_size = size;
350*387f9dfdSAndroid Build Coastguard Worker     }
351*387f9dfdSAndroid Build Coastguard Worker   }
352*387f9dfdSAndroid Build Coastguard Worker 
353*387f9dfdSAndroid Build Coastguard Worker   if (btf_sec == nullptr || btf_ext_sec == nullptr)
354*387f9dfdSAndroid Build Coastguard Worker     return;
355*387f9dfdSAndroid Build Coastguard Worker 
356*387f9dfdSAndroid Build Coastguard Worker   // Both .BTF and .BTF.ext ELF sections are present.
357*387f9dfdSAndroid Build Coastguard Worker   // The remapped files (the main file and /virtual/include/bcc/helpers.h)
358*387f9dfdSAndroid Build Coastguard Worker   // will provide missing source codes in the .BTF.ext line_info table.
359*387f9dfdSAndroid Build Coastguard Worker   auto helpers_h = ExportedFiles::headers().find("/virtual/include/bcc/helpers.h");
360*387f9dfdSAndroid Build Coastguard Worker   if (helpers_h == ExportedFiles::headers().end()) {
361*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "Internal error: missing bcc/helpers.h");
362*387f9dfdSAndroid Build Coastguard Worker     return;
363*387f9dfdSAndroid Build Coastguard Worker   }
364*387f9dfdSAndroid Build Coastguard Worker   std::map<std::string, std::string> remapped_sources;
365*387f9dfdSAndroid Build Coastguard Worker   remapped_sources["/virtual/main.c"] = mod_src_;
366*387f9dfdSAndroid Build Coastguard Worker   remapped_sources["/virtual/include/bcc/helpers.h"] = helpers_h->second;
367*387f9dfdSAndroid Build Coastguard Worker 
368*387f9dfdSAndroid Build Coastguard Worker   BTF *btf = new BTF(flags_ & DEBUG_BTF, sections);
369*387f9dfdSAndroid Build Coastguard Worker   int ret = btf->load(btf_sec, btf_sec_size, btf_ext_sec, btf_ext_sec_size,
370*387f9dfdSAndroid Build Coastguard Worker                        remapped_sources);
371*387f9dfdSAndroid Build Coastguard Worker   if (ret) {
372*387f9dfdSAndroid Build Coastguard Worker     delete btf;
373*387f9dfdSAndroid Build Coastguard Worker     return;
374*387f9dfdSAndroid Build Coastguard Worker   }
375*387f9dfdSAndroid Build Coastguard Worker   btf_ = btf;
376*387f9dfdSAndroid Build Coastguard Worker }
377*387f9dfdSAndroid Build Coastguard Worker 
create_maps(std::map<std::string,std::pair<int,int>> & map_tids,std::map<int,int> & map_fds,std::map<std::string,int> & inner_map_fds,bool for_inner_map)378*387f9dfdSAndroid Build Coastguard Worker int BPFModule::create_maps(std::map<std::string, std::pair<int, int>> &map_tids,
379*387f9dfdSAndroid Build Coastguard Worker                            std::map<int, int> &map_fds,
380*387f9dfdSAndroid Build Coastguard Worker                            std::map<std::string, int> &inner_map_fds,
381*387f9dfdSAndroid Build Coastguard Worker                            bool for_inner_map) {
382*387f9dfdSAndroid Build Coastguard Worker   std::set<std::string> inner_maps;
383*387f9dfdSAndroid Build Coastguard Worker   if (for_inner_map) {
384*387f9dfdSAndroid Build Coastguard Worker     for (auto map : fake_fd_map_) {
385*387f9dfdSAndroid Build Coastguard Worker       std::string inner_map_name = get<7>(map.second);
386*387f9dfdSAndroid Build Coastguard Worker       if (inner_map_name.size())
387*387f9dfdSAndroid Build Coastguard Worker         inner_maps.insert(inner_map_name);
388*387f9dfdSAndroid Build Coastguard Worker     }
389*387f9dfdSAndroid Build Coastguard Worker   }
390*387f9dfdSAndroid Build Coastguard Worker 
391*387f9dfdSAndroid Build Coastguard Worker   for (auto map : fake_fd_map_) {
392*387f9dfdSAndroid Build Coastguard Worker     int fd, fake_fd, map_type, key_size, value_size, max_entries, map_flags;
393*387f9dfdSAndroid Build Coastguard Worker     int pinned_id;
394*387f9dfdSAndroid Build Coastguard Worker     const char *map_name;
395*387f9dfdSAndroid Build Coastguard Worker     const char *pinned;
396*387f9dfdSAndroid Build Coastguard Worker     std::string inner_map_name;
397*387f9dfdSAndroid Build Coastguard Worker     int inner_map_fd = 0;
398*387f9dfdSAndroid Build Coastguard Worker 
399*387f9dfdSAndroid Build Coastguard Worker     fake_fd     = map.first;
400*387f9dfdSAndroid Build Coastguard Worker     map_type    = get<0>(map.second);
401*387f9dfdSAndroid Build Coastguard Worker     map_name    = get<1>(map.second).c_str();
402*387f9dfdSAndroid Build Coastguard Worker     key_size    = get<2>(map.second);
403*387f9dfdSAndroid Build Coastguard Worker     value_size  = get<3>(map.second);
404*387f9dfdSAndroid Build Coastguard Worker     max_entries = get<4>(map.second);
405*387f9dfdSAndroid Build Coastguard Worker     map_flags   = get<5>(map.second);
406*387f9dfdSAndroid Build Coastguard Worker     pinned_id   = get<6>(map.second);
407*387f9dfdSAndroid Build Coastguard Worker     inner_map_name = get<7>(map.second);
408*387f9dfdSAndroid Build Coastguard Worker 
409*387f9dfdSAndroid Build Coastguard Worker     if (for_inner_map) {
410*387f9dfdSAndroid Build Coastguard Worker       if (inner_maps.find(map_name) == inner_maps.end())
411*387f9dfdSAndroid Build Coastguard Worker         continue;
412*387f9dfdSAndroid Build Coastguard Worker       if (inner_map_name.size()) {
413*387f9dfdSAndroid Build Coastguard Worker         fprintf(stderr, "inner map %s has inner map %s\n",
414*387f9dfdSAndroid Build Coastguard Worker                 map_name, inner_map_name.c_str());
415*387f9dfdSAndroid Build Coastguard Worker         return -1;
416*387f9dfdSAndroid Build Coastguard Worker       }
417*387f9dfdSAndroid Build Coastguard Worker     } else {
418*387f9dfdSAndroid Build Coastguard Worker       if (inner_map_fds.find(map_name) != inner_map_fds.end())
419*387f9dfdSAndroid Build Coastguard Worker         continue;
420*387f9dfdSAndroid Build Coastguard Worker       if (inner_map_name.size())
421*387f9dfdSAndroid Build Coastguard Worker         inner_map_fd = inner_map_fds[inner_map_name];
422*387f9dfdSAndroid Build Coastguard Worker     }
423*387f9dfdSAndroid Build Coastguard Worker 
424*387f9dfdSAndroid Build Coastguard Worker     if (pinned_id <= 0) {
425*387f9dfdSAndroid Build Coastguard Worker       struct bcc_create_map_attr attr = {};
426*387f9dfdSAndroid Build Coastguard Worker       attr.map_type = (enum bpf_map_type)map_type;
427*387f9dfdSAndroid Build Coastguard Worker       attr.name = map_name;
428*387f9dfdSAndroid Build Coastguard Worker       attr.key_size = key_size;
429*387f9dfdSAndroid Build Coastguard Worker       attr.value_size = value_size;
430*387f9dfdSAndroid Build Coastguard Worker       attr.max_entries = max_entries;
431*387f9dfdSAndroid Build Coastguard Worker       attr.map_flags = map_flags;
432*387f9dfdSAndroid Build Coastguard Worker       attr.map_ifindex = ifindex_;
433*387f9dfdSAndroid Build Coastguard Worker       attr.inner_map_fd = inner_map_fd;
434*387f9dfdSAndroid Build Coastguard Worker 
435*387f9dfdSAndroid Build Coastguard Worker       if (map_tids.find(map_name) != map_tids.end()) {
436*387f9dfdSAndroid Build Coastguard Worker         attr.btf_fd = btf_->get_fd();
437*387f9dfdSAndroid Build Coastguard Worker         attr.btf_key_type_id = map_tids[map_name].first;
438*387f9dfdSAndroid Build Coastguard Worker         attr.btf_value_type_id = map_tids[map_name].second;
439*387f9dfdSAndroid Build Coastguard Worker       }
440*387f9dfdSAndroid Build Coastguard Worker 
441*387f9dfdSAndroid Build Coastguard Worker       fd = bcc_create_map_xattr(&attr, allow_rlimit_);
442*387f9dfdSAndroid Build Coastguard Worker     } else {
443*387f9dfdSAndroid Build Coastguard Worker       fd = bpf_map_get_fd_by_id(pinned_id);
444*387f9dfdSAndroid Build Coastguard Worker     }
445*387f9dfdSAndroid Build Coastguard Worker 
446*387f9dfdSAndroid Build Coastguard Worker     if (fd < 0) {
447*387f9dfdSAndroid Build Coastguard Worker       fprintf(stderr, "could not open bpf map: %s, error: %s\n",
448*387f9dfdSAndroid Build Coastguard Worker               map_name, strerror(errno));
449*387f9dfdSAndroid Build Coastguard Worker       return -1;
450*387f9dfdSAndroid Build Coastguard Worker     }
451*387f9dfdSAndroid Build Coastguard Worker 
452*387f9dfdSAndroid Build Coastguard Worker     if (pinned_id == -1) {
453*387f9dfdSAndroid Build Coastguard Worker       pinned = get<8>(map.second).c_str();
454*387f9dfdSAndroid Build Coastguard Worker       if (bpf_obj_pin(fd, pinned)) {
455*387f9dfdSAndroid Build Coastguard Worker         fprintf(stderr, "failed to pin map: %s, error: %s\n",
456*387f9dfdSAndroid Build Coastguard Worker                 pinned, strerror(errno));
457*387f9dfdSAndroid Build Coastguard Worker         return -1;
458*387f9dfdSAndroid Build Coastguard Worker       }
459*387f9dfdSAndroid Build Coastguard Worker     }
460*387f9dfdSAndroid Build Coastguard Worker 
461*387f9dfdSAndroid Build Coastguard Worker     if (for_inner_map)
462*387f9dfdSAndroid Build Coastguard Worker       inner_map_fds[map_name] = fd;
463*387f9dfdSAndroid Build Coastguard Worker 
464*387f9dfdSAndroid Build Coastguard Worker     map_fds[fake_fd] = fd;
465*387f9dfdSAndroid Build Coastguard Worker   }
466*387f9dfdSAndroid Build Coastguard Worker 
467*387f9dfdSAndroid Build Coastguard Worker   return 0;
468*387f9dfdSAndroid Build Coastguard Worker }
469*387f9dfdSAndroid Build Coastguard Worker 
load_maps(sec_map_def & sections)470*387f9dfdSAndroid Build Coastguard Worker int BPFModule::load_maps(sec_map_def &sections) {
471*387f9dfdSAndroid Build Coastguard Worker   // find .maps.<table_name> sections and retrieve all map key/value type id's
472*387f9dfdSAndroid Build Coastguard Worker   std::map<std::string, std::pair<int, int>> map_tids;
473*387f9dfdSAndroid Build Coastguard Worker   if (btf_) {
474*387f9dfdSAndroid Build Coastguard Worker     for (auto section : sections) {
475*387f9dfdSAndroid Build Coastguard Worker       auto sec_name = section.first;
476*387f9dfdSAndroid Build Coastguard Worker       if (strncmp(".maps.", sec_name.c_str(), 6) == 0) {
477*387f9dfdSAndroid Build Coastguard Worker         std::string map_name = sec_name.substr(6);
478*387f9dfdSAndroid Build Coastguard Worker         unsigned key_tid = 0, value_tid = 0;
479*387f9dfdSAndroid Build Coastguard Worker         unsigned expected_ksize = 0, expected_vsize = 0;
480*387f9dfdSAndroid Build Coastguard Worker 
481*387f9dfdSAndroid Build Coastguard Worker         // skip extern maps, which won't be in fake_fd_map_ as they do not
482*387f9dfdSAndroid Build Coastguard Worker         // require explicit bpf_create_map.
483*387f9dfdSAndroid Build Coastguard Worker         bool is_extern = false;
484*387f9dfdSAndroid Build Coastguard Worker         for (auto &t : tables_) {
485*387f9dfdSAndroid Build Coastguard Worker           if (t->name == map_name) {
486*387f9dfdSAndroid Build Coastguard Worker             is_extern = t->is_extern;
487*387f9dfdSAndroid Build Coastguard Worker             break;
488*387f9dfdSAndroid Build Coastguard Worker           }
489*387f9dfdSAndroid Build Coastguard Worker         }
490*387f9dfdSAndroid Build Coastguard Worker         if (is_extern)
491*387f9dfdSAndroid Build Coastguard Worker           continue;
492*387f9dfdSAndroid Build Coastguard Worker 
493*387f9dfdSAndroid Build Coastguard Worker         for (auto map : fake_fd_map_) {
494*387f9dfdSAndroid Build Coastguard Worker           std::string name;
495*387f9dfdSAndroid Build Coastguard Worker 
496*387f9dfdSAndroid Build Coastguard Worker           name = get<1>(map.second);
497*387f9dfdSAndroid Build Coastguard Worker           if (map_name == name) {
498*387f9dfdSAndroid Build Coastguard Worker             expected_ksize = get<2>(map.second);
499*387f9dfdSAndroid Build Coastguard Worker             expected_vsize = get<3>(map.second);
500*387f9dfdSAndroid Build Coastguard Worker             break;
501*387f9dfdSAndroid Build Coastguard Worker           }
502*387f9dfdSAndroid Build Coastguard Worker         }
503*387f9dfdSAndroid Build Coastguard Worker 
504*387f9dfdSAndroid Build Coastguard Worker         int ret = btf_->get_map_tids(map_name, expected_ksize,
505*387f9dfdSAndroid Build Coastguard Worker                                      expected_vsize, &key_tid, &value_tid);
506*387f9dfdSAndroid Build Coastguard Worker         if (ret)
507*387f9dfdSAndroid Build Coastguard Worker           continue;
508*387f9dfdSAndroid Build Coastguard Worker 
509*387f9dfdSAndroid Build Coastguard Worker         map_tids[map_name] = std::make_pair(key_tid, value_tid);
510*387f9dfdSAndroid Build Coastguard Worker       }
511*387f9dfdSAndroid Build Coastguard Worker     }
512*387f9dfdSAndroid Build Coastguard Worker   }
513*387f9dfdSAndroid Build Coastguard Worker 
514*387f9dfdSAndroid Build Coastguard Worker   // create maps
515*387f9dfdSAndroid Build Coastguard Worker   std::map<std::string, int> inner_map_fds;
516*387f9dfdSAndroid Build Coastguard Worker   std::map<int, int> map_fds;
517*387f9dfdSAndroid Build Coastguard Worker   if (create_maps(map_tids, map_fds, inner_map_fds, true) < 0)
518*387f9dfdSAndroid Build Coastguard Worker     return -1;
519*387f9dfdSAndroid Build Coastguard Worker   if (create_maps(map_tids, map_fds, inner_map_fds, false) < 0)
520*387f9dfdSAndroid Build Coastguard Worker     return -1;
521*387f9dfdSAndroid Build Coastguard Worker 
522*387f9dfdSAndroid Build Coastguard Worker   // update map table fd's
523*387f9dfdSAndroid Build Coastguard Worker   for (auto it = ts_->begin(), up = ts_->end(); it != up; ++it) {
524*387f9dfdSAndroid Build Coastguard Worker     TableDesc &table = it->second;
525*387f9dfdSAndroid Build Coastguard Worker     if (map_fds.find(table.fake_fd) != map_fds.end()) {
526*387f9dfdSAndroid Build Coastguard Worker       table.fd = map_fds[table.fake_fd];
527*387f9dfdSAndroid Build Coastguard Worker       table.fake_fd = 0;
528*387f9dfdSAndroid Build Coastguard Worker     }
529*387f9dfdSAndroid Build Coastguard Worker   }
530*387f9dfdSAndroid Build Coastguard Worker 
531*387f9dfdSAndroid Build Coastguard Worker   // update instructions
532*387f9dfdSAndroid Build Coastguard Worker   prog_func_info_->for_each_func([&](std::string name, FuncInfo &info) {
533*387f9dfdSAndroid Build Coastguard Worker     struct bpf_insn *insns = (struct bpf_insn *)info.start_;
534*387f9dfdSAndroid Build Coastguard Worker     uint32_t i, num_insns = info.size_ / sizeof(struct bpf_insn);
535*387f9dfdSAndroid Build Coastguard Worker     for (i = 0; i < num_insns; i++) {
536*387f9dfdSAndroid Build Coastguard Worker       if (insns[i].code == (BPF_LD | BPF_DW | BPF_IMM)) {
537*387f9dfdSAndroid Build Coastguard Worker         // change map_fd is it is a ld_pseudo
538*387f9dfdSAndroid Build Coastguard Worker         if (insns[i].src_reg == BPF_PSEUDO_MAP_FD &&
539*387f9dfdSAndroid Build Coastguard Worker             map_fds.find(insns[i].imm) != map_fds.end())
540*387f9dfdSAndroid Build Coastguard Worker           insns[i].imm = map_fds[insns[i].imm];
541*387f9dfdSAndroid Build Coastguard Worker         i++;
542*387f9dfdSAndroid Build Coastguard Worker       }
543*387f9dfdSAndroid Build Coastguard Worker     }
544*387f9dfdSAndroid Build Coastguard Worker   });
545*387f9dfdSAndroid Build Coastguard Worker 
546*387f9dfdSAndroid Build Coastguard Worker   return 0;
547*387f9dfdSAndroid Build Coastguard Worker }
548*387f9dfdSAndroid Build Coastguard Worker 
finalize()549*387f9dfdSAndroid Build Coastguard Worker int BPFModule::finalize() {
550*387f9dfdSAndroid Build Coastguard Worker   Module *mod = &*mod_;
551*387f9dfdSAndroid Build Coastguard Worker   sec_map_def tmp_sections,
552*387f9dfdSAndroid Build Coastguard Worker       *sections_p;
553*387f9dfdSAndroid Build Coastguard Worker 
554*387f9dfdSAndroid Build Coastguard Worker   mod->setTargetTriple("bpf-pc-linux");
555*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11
556*387f9dfdSAndroid Build Coastguard Worker #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
557*387f9dfdSAndroid Build Coastguard Worker   mod->setDataLayout("e-m:e-p:64:64-i64:64-i128:128-n32:64-S128");
558*387f9dfdSAndroid Build Coastguard Worker #else
559*387f9dfdSAndroid Build Coastguard Worker   mod->setDataLayout("E-m:e-p:64:64-i64:64-i128:128-n32:64-S128");
560*387f9dfdSAndroid Build Coastguard Worker #endif
561*387f9dfdSAndroid Build Coastguard Worker #else
562*387f9dfdSAndroid Build Coastguard Worker #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
563*387f9dfdSAndroid Build Coastguard Worker   mod->setDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128");
564*387f9dfdSAndroid Build Coastguard Worker #else
565*387f9dfdSAndroid Build Coastguard Worker   mod->setDataLayout("E-m:e-p:64:64-i64:64-n32:64-S128");
566*387f9dfdSAndroid Build Coastguard Worker #endif
567*387f9dfdSAndroid Build Coastguard Worker #endif
568*387f9dfdSAndroid Build Coastguard Worker   sections_p = rw_engine_enabled_ ? &sections_ : &tmp_sections;
569*387f9dfdSAndroid Build Coastguard Worker 
570*387f9dfdSAndroid Build Coastguard Worker   string err;
571*387f9dfdSAndroid Build Coastguard Worker   EngineBuilder builder(move(mod_));
572*387f9dfdSAndroid Build Coastguard Worker   builder.setErrorStr(&err);
573*387f9dfdSAndroid Build Coastguard Worker   builder.setMCJITMemoryManager(
574*387f9dfdSAndroid Build Coastguard Worker       ebpf::make_unique<MyMemoryManager>(sections_p, &*prog_func_info_));
575*387f9dfdSAndroid Build Coastguard Worker   builder.setMArch("bpf");
576*387f9dfdSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR <= 11
577*387f9dfdSAndroid Build Coastguard Worker   builder.setUseOrcMCJITReplacement(false);
578*387f9dfdSAndroid Build Coastguard Worker #endif
579*387f9dfdSAndroid Build Coastguard Worker   engine_ = unique_ptr<ExecutionEngine>(builder.create());
580*387f9dfdSAndroid Build Coastguard Worker   if (!engine_) {
581*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
582*387f9dfdSAndroid Build Coastguard Worker     return -1;
583*387f9dfdSAndroid Build Coastguard Worker   }
584*387f9dfdSAndroid Build Coastguard Worker 
585*387f9dfdSAndroid Build Coastguard Worker   engine_->setProcessAllSections(true);
586*387f9dfdSAndroid Build Coastguard Worker 
587*387f9dfdSAndroid Build Coastguard Worker   if (int rc = run_pass_manager(*mod))
588*387f9dfdSAndroid Build Coastguard Worker     return rc;
589*387f9dfdSAndroid Build Coastguard Worker 
590*387f9dfdSAndroid Build Coastguard Worker   engine_->finalizeObject();
591*387f9dfdSAndroid Build Coastguard Worker   prog_func_info_->for_each_func([&](std::string name, FuncInfo &info) {
592*387f9dfdSAndroid Build Coastguard Worker     info.start_ = (uint8_t *)engine_->getFunctionAddress(name);
593*387f9dfdSAndroid Build Coastguard Worker   });
594*387f9dfdSAndroid Build Coastguard Worker   finalize_prog_func_info();
595*387f9dfdSAndroid Build Coastguard Worker 
596*387f9dfdSAndroid Build Coastguard Worker   if (flags_ & DEBUG_SOURCE) {
597*387f9dfdSAndroid Build Coastguard Worker     SourceDebugger src_debugger(mod, *sections_p, *prog_func_info_, mod_src_,
598*387f9dfdSAndroid Build Coastguard Worker                                 src_dbg_fmap_);
599*387f9dfdSAndroid Build Coastguard Worker     src_debugger.dump();
600*387f9dfdSAndroid Build Coastguard Worker   }
601*387f9dfdSAndroid Build Coastguard Worker 
602*387f9dfdSAndroid Build Coastguard Worker   load_btf(*sections_p);
603*387f9dfdSAndroid Build Coastguard Worker   if (load_maps(*sections_p))
604*387f9dfdSAndroid Build Coastguard Worker     return -1;
605*387f9dfdSAndroid Build Coastguard Worker 
606*387f9dfdSAndroid Build Coastguard Worker   if (!rw_engine_enabled_) {
607*387f9dfdSAndroid Build Coastguard Worker     // Setup sections_ correctly and then free llvm internal memory
608*387f9dfdSAndroid Build Coastguard Worker     for (auto section : tmp_sections) {
609*387f9dfdSAndroid Build Coastguard Worker       auto fname = section.first;
610*387f9dfdSAndroid Build Coastguard Worker       uintptr_t size = get<1>(section.second);
611*387f9dfdSAndroid Build Coastguard Worker       uint8_t *tmp_p = NULL;
612*387f9dfdSAndroid Build Coastguard Worker       // Only copy data for non-map sections
613*387f9dfdSAndroid Build Coastguard Worker       if (strncmp("maps/", section.first.c_str(), 5)) {
614*387f9dfdSAndroid Build Coastguard Worker         uint8_t *addr = get<0>(section.second);
615*387f9dfdSAndroid Build Coastguard Worker         tmp_p = new uint8_t[size];
616*387f9dfdSAndroid Build Coastguard Worker         memcpy(tmp_p, addr, size);
617*387f9dfdSAndroid Build Coastguard Worker       }
618*387f9dfdSAndroid Build Coastguard Worker       sections_[fname] = make_tuple(tmp_p, size, get<2>(section.second));
619*387f9dfdSAndroid Build Coastguard Worker     }
620*387f9dfdSAndroid Build Coastguard Worker 
621*387f9dfdSAndroid Build Coastguard Worker     prog_func_info_->for_each_func([](std::string name, FuncInfo &info) {
622*387f9dfdSAndroid Build Coastguard Worker       uint8_t *tmp_p = new uint8_t[info.size_];
623*387f9dfdSAndroid Build Coastguard Worker       memcpy(tmp_p, info.start_, info.size_);
624*387f9dfdSAndroid Build Coastguard Worker       info.start_ = tmp_p;
625*387f9dfdSAndroid Build Coastguard Worker     });
626*387f9dfdSAndroid Build Coastguard Worker     engine_.reset();
627*387f9dfdSAndroid Build Coastguard Worker     ctx_.reset();
628*387f9dfdSAndroid Build Coastguard Worker   }
629*387f9dfdSAndroid Build Coastguard Worker 
630*387f9dfdSAndroid Build Coastguard Worker   return 0;
631*387f9dfdSAndroid Build Coastguard Worker }
632*387f9dfdSAndroid Build Coastguard Worker 
finalize_prog_func_info()633*387f9dfdSAndroid Build Coastguard Worker void BPFModule::finalize_prog_func_info() {
634*387f9dfdSAndroid Build Coastguard Worker   // prog_func_info_'s FuncInfo data is gradually populated (first in frontend
635*387f9dfdSAndroid Build Coastguard Worker   // action, then bpf_module). It's possible for a FuncInfo to have been
636*387f9dfdSAndroid Build Coastguard Worker   // created by FrontendAction but no corresponding start location found in
637*387f9dfdSAndroid Build Coastguard Worker   // bpf_module - filter out these functions
638*387f9dfdSAndroid Build Coastguard Worker   //
639*387f9dfdSAndroid Build Coastguard Worker   // The numeric function ids in the new prog_func_info_ are considered
640*387f9dfdSAndroid Build Coastguard Worker   // canonical
641*387f9dfdSAndroid Build Coastguard Worker   std::unique_ptr<ProgFuncInfo> finalized = ebpf::make_unique<ProgFuncInfo>();
642*387f9dfdSAndroid Build Coastguard Worker   prog_func_info_->for_each_func([&](std::string name, FuncInfo &info) {
643*387f9dfdSAndroid Build Coastguard Worker     if(info.start_) {
644*387f9dfdSAndroid Build Coastguard Worker       auto i = finalized->add_func(name);
645*387f9dfdSAndroid Build Coastguard Worker       if (i) { // should always be true
646*387f9dfdSAndroid Build Coastguard Worker         *i = info;
647*387f9dfdSAndroid Build Coastguard Worker       }
648*387f9dfdSAndroid Build Coastguard Worker     }
649*387f9dfdSAndroid Build Coastguard Worker   });
650*387f9dfdSAndroid Build Coastguard Worker   prog_func_info_.swap(finalized);
651*387f9dfdSAndroid Build Coastguard Worker }
652*387f9dfdSAndroid Build Coastguard Worker 
num_functions() const653*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::num_functions() const { return prog_func_info_->num_funcs(); }
654*387f9dfdSAndroid Build Coastguard Worker 
function_name(size_t id) const655*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::function_name(size_t id) const {
656*387f9dfdSAndroid Build Coastguard Worker   auto name = prog_func_info_->func_name(id);
657*387f9dfdSAndroid Build Coastguard Worker   if (name)
658*387f9dfdSAndroid Build Coastguard Worker     return name->c_str();
659*387f9dfdSAndroid Build Coastguard Worker   return nullptr;
660*387f9dfdSAndroid Build Coastguard Worker }
661*387f9dfdSAndroid Build Coastguard Worker 
function_start(size_t id) const662*387f9dfdSAndroid Build Coastguard Worker uint8_t * BPFModule::function_start(size_t id) const {
663*387f9dfdSAndroid Build Coastguard Worker   auto fn = prog_func_info_->get_func(id);
664*387f9dfdSAndroid Build Coastguard Worker   if (fn)
665*387f9dfdSAndroid Build Coastguard Worker     return fn->start_;
666*387f9dfdSAndroid Build Coastguard Worker   return nullptr;
667*387f9dfdSAndroid Build Coastguard Worker }
668*387f9dfdSAndroid Build Coastguard Worker 
function_start(const string & name) const669*387f9dfdSAndroid Build Coastguard Worker uint8_t * BPFModule::function_start(const string &name) const {
670*387f9dfdSAndroid Build Coastguard Worker   auto fn = prog_func_info_->get_func(name);
671*387f9dfdSAndroid Build Coastguard Worker   if (fn)
672*387f9dfdSAndroid Build Coastguard Worker     return fn->start_;
673*387f9dfdSAndroid Build Coastguard Worker   return nullptr;
674*387f9dfdSAndroid Build Coastguard Worker }
675*387f9dfdSAndroid Build Coastguard Worker 
function_source(const string & name) const676*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::function_source(const string &name) const {
677*387f9dfdSAndroid Build Coastguard Worker   auto fn = prog_func_info_->get_func(name);
678*387f9dfdSAndroid Build Coastguard Worker   if (fn)
679*387f9dfdSAndroid Build Coastguard Worker     return fn->src_.c_str();
680*387f9dfdSAndroid Build Coastguard Worker   return "";
681*387f9dfdSAndroid Build Coastguard Worker }
682*387f9dfdSAndroid Build Coastguard Worker 
function_source_rewritten(const string & name) const683*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::function_source_rewritten(const string &name) const {
684*387f9dfdSAndroid Build Coastguard Worker   auto fn = prog_func_info_->get_func(name);
685*387f9dfdSAndroid Build Coastguard Worker   if (fn)
686*387f9dfdSAndroid Build Coastguard Worker     return fn->src_rewritten_.c_str();
687*387f9dfdSAndroid Build Coastguard Worker   return "";
688*387f9dfdSAndroid Build Coastguard Worker }
689*387f9dfdSAndroid Build Coastguard Worker 
annotate_prog_tag(const string & name,int prog_fd,struct bpf_insn * insns,int prog_len)690*387f9dfdSAndroid Build Coastguard Worker int BPFModule::annotate_prog_tag(const string &name, int prog_fd,
691*387f9dfdSAndroid Build Coastguard Worker                                  struct bpf_insn *insns, int prog_len) {
692*387f9dfdSAndroid Build Coastguard Worker   unsigned long long tag1, tag2;
693*387f9dfdSAndroid Build Coastguard Worker   int err;
694*387f9dfdSAndroid Build Coastguard Worker 
695*387f9dfdSAndroid Build Coastguard Worker   err = bpf_prog_compute_tag(insns, prog_len, &tag1);
696*387f9dfdSAndroid Build Coastguard Worker   if (err)
697*387f9dfdSAndroid Build Coastguard Worker     return err;
698*387f9dfdSAndroid Build Coastguard Worker   err = bpf_prog_get_tag(prog_fd, &tag2);
699*387f9dfdSAndroid Build Coastguard Worker   if (err)
700*387f9dfdSAndroid Build Coastguard Worker     return err;
701*387f9dfdSAndroid Build Coastguard Worker   if (tag1 != tag2) {
702*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "prog tag mismatch %llx %llx\n", tag1, tag2);
703*387f9dfdSAndroid Build Coastguard Worker     return -1;
704*387f9dfdSAndroid Build Coastguard Worker   }
705*387f9dfdSAndroid Build Coastguard Worker 
706*387f9dfdSAndroid Build Coastguard Worker   err = mkdir(BCC_PROG_TAG_DIR, 0777);
707*387f9dfdSAndroid Build Coastguard Worker   if (err && errno != EEXIST) {
708*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "cannot create " BCC_PROG_TAG_DIR "\n");
709*387f9dfdSAndroid Build Coastguard Worker     return -1;
710*387f9dfdSAndroid Build Coastguard Worker   }
711*387f9dfdSAndroid Build Coastguard Worker 
712*387f9dfdSAndroid Build Coastguard Worker   char buf[128];
713*387f9dfdSAndroid Build Coastguard Worker   ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx", tag1);
714*387f9dfdSAndroid Build Coastguard Worker   err = mkdir(buf, 0777);
715*387f9dfdSAndroid Build Coastguard Worker   if (err && errno != EEXIST) {
716*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "cannot create %s\n", buf);
717*387f9dfdSAndroid Build Coastguard Worker     return -1;
718*387f9dfdSAndroid Build Coastguard Worker   }
719*387f9dfdSAndroid Build Coastguard Worker 
720*387f9dfdSAndroid Build Coastguard Worker   ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx/%s.c",
721*387f9dfdSAndroid Build Coastguard Worker              tag1, name.data());
722*387f9dfdSAndroid Build Coastguard Worker   FileDesc fd(open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0644));
723*387f9dfdSAndroid Build Coastguard Worker   if (fd < 0) {
724*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "cannot create %s\n", buf);
725*387f9dfdSAndroid Build Coastguard Worker     return -1;
726*387f9dfdSAndroid Build Coastguard Worker   }
727*387f9dfdSAndroid Build Coastguard Worker 
728*387f9dfdSAndroid Build Coastguard Worker   const char *src = function_source(name);
729*387f9dfdSAndroid Build Coastguard Worker   write(fd, src, strlen(src));
730*387f9dfdSAndroid Build Coastguard Worker 
731*387f9dfdSAndroid Build Coastguard Worker   ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx/%s.rewritten.c",
732*387f9dfdSAndroid Build Coastguard Worker              tag1, name.data());
733*387f9dfdSAndroid Build Coastguard Worker   fd = open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0644);
734*387f9dfdSAndroid Build Coastguard Worker   if (fd < 0) {
735*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "cannot create %s\n", buf);
736*387f9dfdSAndroid Build Coastguard Worker     return -1;
737*387f9dfdSAndroid Build Coastguard Worker   }
738*387f9dfdSAndroid Build Coastguard Worker 
739*387f9dfdSAndroid Build Coastguard Worker   src = function_source_rewritten(name);
740*387f9dfdSAndroid Build Coastguard Worker   write(fd, src, strlen(src));
741*387f9dfdSAndroid Build Coastguard Worker 
742*387f9dfdSAndroid Build Coastguard Worker   if (!src_dbg_fmap_[name].empty()) {
743*387f9dfdSAndroid Build Coastguard Worker     ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx/%s.dis.txt",
744*387f9dfdSAndroid Build Coastguard Worker                tag1, name.data());
745*387f9dfdSAndroid Build Coastguard Worker     fd = open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0644);
746*387f9dfdSAndroid Build Coastguard Worker     if (fd < 0) {
747*387f9dfdSAndroid Build Coastguard Worker       fprintf(stderr, "cannot create %s\n", buf);
748*387f9dfdSAndroid Build Coastguard Worker       return -1;
749*387f9dfdSAndroid Build Coastguard Worker     }
750*387f9dfdSAndroid Build Coastguard Worker 
751*387f9dfdSAndroid Build Coastguard Worker     const char *src = src_dbg_fmap_[name].c_str();
752*387f9dfdSAndroid Build Coastguard Worker     write(fd, src, strlen(src));
753*387f9dfdSAndroid Build Coastguard Worker   }
754*387f9dfdSAndroid Build Coastguard Worker 
755*387f9dfdSAndroid Build Coastguard Worker   return 0;
756*387f9dfdSAndroid Build Coastguard Worker }
757*387f9dfdSAndroid Build Coastguard Worker 
function_size(size_t id) const758*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::function_size(size_t id) const {
759*387f9dfdSAndroid Build Coastguard Worker   auto fn = prog_func_info_->get_func(id);
760*387f9dfdSAndroid Build Coastguard Worker   if (fn)
761*387f9dfdSAndroid Build Coastguard Worker     return fn->size_;
762*387f9dfdSAndroid Build Coastguard Worker   return 0;
763*387f9dfdSAndroid Build Coastguard Worker }
764*387f9dfdSAndroid Build Coastguard Worker 
function_size(const string & name) const765*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::function_size(const string &name) const {
766*387f9dfdSAndroid Build Coastguard Worker   auto fn = prog_func_info_->get_func(name);
767*387f9dfdSAndroid Build Coastguard Worker   if (fn)
768*387f9dfdSAndroid Build Coastguard Worker     return fn->size_;
769*387f9dfdSAndroid Build Coastguard Worker   return 0;
770*387f9dfdSAndroid Build Coastguard Worker }
771*387f9dfdSAndroid Build Coastguard Worker 
license() const772*387f9dfdSAndroid Build Coastguard Worker char * BPFModule::license() const {
773*387f9dfdSAndroid Build Coastguard Worker   auto section = sections_.find("license");
774*387f9dfdSAndroid Build Coastguard Worker   if (section == sections_.end())
775*387f9dfdSAndroid Build Coastguard Worker     return nullptr;
776*387f9dfdSAndroid Build Coastguard Worker 
777*387f9dfdSAndroid Build Coastguard Worker   return (char *)get<0>(section->second);
778*387f9dfdSAndroid Build Coastguard Worker }
779*387f9dfdSAndroid Build Coastguard Worker 
kern_version() const780*387f9dfdSAndroid Build Coastguard Worker unsigned BPFModule::kern_version() const {
781*387f9dfdSAndroid Build Coastguard Worker   auto section = sections_.find("version");
782*387f9dfdSAndroid Build Coastguard Worker   if (section == sections_.end())
783*387f9dfdSAndroid Build Coastguard Worker     return 0;
784*387f9dfdSAndroid Build Coastguard Worker 
785*387f9dfdSAndroid Build Coastguard Worker   return *(unsigned *)get<0>(section->second);
786*387f9dfdSAndroid Build Coastguard Worker }
787*387f9dfdSAndroid Build Coastguard Worker 
num_tables() const788*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::num_tables() const { return tables_.size(); }
789*387f9dfdSAndroid Build Coastguard Worker 
perf_event_fields(const char * event) const790*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::perf_event_fields(const char *event) const {
791*387f9dfdSAndroid Build Coastguard Worker   auto it = perf_events_.find(event);
792*387f9dfdSAndroid Build Coastguard Worker   if (it == perf_events_.end())
793*387f9dfdSAndroid Build Coastguard Worker     return 0;
794*387f9dfdSAndroid Build Coastguard Worker   return it->second.size();
795*387f9dfdSAndroid Build Coastguard Worker }
796*387f9dfdSAndroid Build Coastguard Worker 
perf_event_field(const char * event,size_t i) const797*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::perf_event_field(const char *event, size_t i) const {
798*387f9dfdSAndroid Build Coastguard Worker   auto it = perf_events_.find(event);
799*387f9dfdSAndroid Build Coastguard Worker   if (it == perf_events_.end() || i >= it->second.size())
800*387f9dfdSAndroid Build Coastguard Worker     return nullptr;
801*387f9dfdSAndroid Build Coastguard Worker   return it->second[i].c_str();
802*387f9dfdSAndroid Build Coastguard Worker }
803*387f9dfdSAndroid Build Coastguard Worker 
table_id(const string & name) const804*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_id(const string &name) const {
805*387f9dfdSAndroid Build Coastguard Worker   auto it = table_names_.find(name);
806*387f9dfdSAndroid Build Coastguard Worker   if (it == table_names_.end()) return ~0ull;
807*387f9dfdSAndroid Build Coastguard Worker   return it->second;
808*387f9dfdSAndroid Build Coastguard Worker }
809*387f9dfdSAndroid Build Coastguard Worker 
table_fd(const string & name) const810*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_fd(const string &name) const {
811*387f9dfdSAndroid Build Coastguard Worker   return table_fd(table_id(name));
812*387f9dfdSAndroid Build Coastguard Worker }
813*387f9dfdSAndroid Build Coastguard Worker 
table_fd(size_t id) const814*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_fd(size_t id) const {
815*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
816*387f9dfdSAndroid Build Coastguard Worker     return -1;
817*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->fd;
818*387f9dfdSAndroid Build Coastguard Worker }
819*387f9dfdSAndroid Build Coastguard Worker 
table_type(const string & name) const820*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_type(const string &name) const {
821*387f9dfdSAndroid Build Coastguard Worker   return table_type(table_id(name));
822*387f9dfdSAndroid Build Coastguard Worker }
823*387f9dfdSAndroid Build Coastguard Worker 
table_type(size_t id) const824*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_type(size_t id) const {
825*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
826*387f9dfdSAndroid Build Coastguard Worker     return -1;
827*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->type;
828*387f9dfdSAndroid Build Coastguard Worker }
829*387f9dfdSAndroid Build Coastguard Worker 
table_max_entries(const string & name) const830*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_max_entries(const string &name) const {
831*387f9dfdSAndroid Build Coastguard Worker   return table_max_entries(table_id(name));
832*387f9dfdSAndroid Build Coastguard Worker }
833*387f9dfdSAndroid Build Coastguard Worker 
table_max_entries(size_t id) const834*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_max_entries(size_t id) const {
835*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
836*387f9dfdSAndroid Build Coastguard Worker     return 0;
837*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->max_entries;
838*387f9dfdSAndroid Build Coastguard Worker }
839*387f9dfdSAndroid Build Coastguard Worker 
table_flags(const string & name) const840*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_flags(const string &name) const {
841*387f9dfdSAndroid Build Coastguard Worker   return table_flags(table_id(name));
842*387f9dfdSAndroid Build Coastguard Worker }
843*387f9dfdSAndroid Build Coastguard Worker 
table_flags(size_t id) const844*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_flags(size_t id) const {
845*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
846*387f9dfdSAndroid Build Coastguard Worker     return -1;
847*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->flags;
848*387f9dfdSAndroid Build Coastguard Worker }
849*387f9dfdSAndroid Build Coastguard Worker 
table_name(size_t id) const850*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::table_name(size_t id) const {
851*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
852*387f9dfdSAndroid Build Coastguard Worker     return nullptr;
853*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->name.c_str();
854*387f9dfdSAndroid Build Coastguard Worker }
855*387f9dfdSAndroid Build Coastguard Worker 
table_key_desc(size_t id) const856*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::table_key_desc(size_t id) const {
857*387f9dfdSAndroid Build Coastguard Worker   if (used_b_loader_) return nullptr;
858*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
859*387f9dfdSAndroid Build Coastguard Worker     return nullptr;
860*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->key_desc.c_str();
861*387f9dfdSAndroid Build Coastguard Worker }
862*387f9dfdSAndroid Build Coastguard Worker 
table_key_desc(const string & name) const863*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::table_key_desc(const string &name) const {
864*387f9dfdSAndroid Build Coastguard Worker   return table_key_desc(table_id(name));
865*387f9dfdSAndroid Build Coastguard Worker }
866*387f9dfdSAndroid Build Coastguard Worker 
table_leaf_desc(size_t id) const867*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::table_leaf_desc(size_t id) const {
868*387f9dfdSAndroid Build Coastguard Worker   if (used_b_loader_) return nullptr;
869*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
870*387f9dfdSAndroid Build Coastguard Worker     return nullptr;
871*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->leaf_desc.c_str();
872*387f9dfdSAndroid Build Coastguard Worker }
873*387f9dfdSAndroid Build Coastguard Worker 
table_leaf_desc(const string & name) const874*387f9dfdSAndroid Build Coastguard Worker const char * BPFModule::table_leaf_desc(const string &name) const {
875*387f9dfdSAndroid Build Coastguard Worker   return table_leaf_desc(table_id(name));
876*387f9dfdSAndroid Build Coastguard Worker }
table_key_size(size_t id) const877*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_key_size(size_t id) const {
878*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
879*387f9dfdSAndroid Build Coastguard Worker     return 0;
880*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->key_size;
881*387f9dfdSAndroid Build Coastguard Worker }
table_key_size(const string & name) const882*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_key_size(const string &name) const {
883*387f9dfdSAndroid Build Coastguard Worker   return table_key_size(table_id(name));
884*387f9dfdSAndroid Build Coastguard Worker }
885*387f9dfdSAndroid Build Coastguard Worker 
table_leaf_size(size_t id) const886*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_leaf_size(size_t id) const {
887*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
888*387f9dfdSAndroid Build Coastguard Worker     return 0;
889*387f9dfdSAndroid Build Coastguard Worker   return tables_[id]->leaf_size;
890*387f9dfdSAndroid Build Coastguard Worker }
table_leaf_size(const string & name) const891*387f9dfdSAndroid Build Coastguard Worker size_t BPFModule::table_leaf_size(const string &name) const {
892*387f9dfdSAndroid Build Coastguard Worker   return table_leaf_size(table_id(name));
893*387f9dfdSAndroid Build Coastguard Worker }
894*387f9dfdSAndroid Build Coastguard Worker 
895*387f9dfdSAndroid Build Coastguard Worker struct TableIterator {
TableIteratorebpf::TableIterator896*387f9dfdSAndroid Build Coastguard Worker   TableIterator(size_t key_size, size_t leaf_size)
897*387f9dfdSAndroid Build Coastguard Worker       : key(new uint8_t[key_size]), leaf(new uint8_t[leaf_size]) {
898*387f9dfdSAndroid Build Coastguard Worker   }
899*387f9dfdSAndroid Build Coastguard Worker   unique_ptr<uint8_t[]> key;
900*387f9dfdSAndroid Build Coastguard Worker   unique_ptr<uint8_t[]> leaf;
901*387f9dfdSAndroid Build Coastguard Worker   uint8_t keyb[512];
902*387f9dfdSAndroid Build Coastguard Worker };
903*387f9dfdSAndroid Build Coastguard Worker 
table_key_printf(size_t id,char * buf,size_t buflen,const void * key)904*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void *key) {
905*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
906*387f9dfdSAndroid Build Coastguard Worker     return -1;
907*387f9dfdSAndroid Build Coastguard Worker   const TableDesc &desc = *tables_[id];
908*387f9dfdSAndroid Build Coastguard Worker   StatusTuple rc = desc.key_snprintf(buf, buflen, key);
909*387f9dfdSAndroid Build Coastguard Worker   if (rc.code() < 0) {
910*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", rc.msg().c_str());
911*387f9dfdSAndroid Build Coastguard Worker     return -1;
912*387f9dfdSAndroid Build Coastguard Worker   }
913*387f9dfdSAndroid Build Coastguard Worker   return 0;
914*387f9dfdSAndroid Build Coastguard Worker }
915*387f9dfdSAndroid Build Coastguard Worker 
table_leaf_printf(size_t id,char * buf,size_t buflen,const void * leaf)916*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf) {
917*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
918*387f9dfdSAndroid Build Coastguard Worker     return -1;
919*387f9dfdSAndroid Build Coastguard Worker   const TableDesc &desc = *tables_[id];
920*387f9dfdSAndroid Build Coastguard Worker   StatusTuple rc = desc.leaf_snprintf(buf, buflen, leaf);
921*387f9dfdSAndroid Build Coastguard Worker   if (rc.code() < 0) {
922*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", rc.msg().c_str());
923*387f9dfdSAndroid Build Coastguard Worker     return -1;
924*387f9dfdSAndroid Build Coastguard Worker   }
925*387f9dfdSAndroid Build Coastguard Worker   return 0;
926*387f9dfdSAndroid Build Coastguard Worker }
927*387f9dfdSAndroid Build Coastguard Worker 
table_key_scanf(size_t id,const char * key_str,void * key)928*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) {
929*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
930*387f9dfdSAndroid Build Coastguard Worker     return -1;
931*387f9dfdSAndroid Build Coastguard Worker   const TableDesc &desc = *tables_[id];
932*387f9dfdSAndroid Build Coastguard Worker   StatusTuple rc = desc.key_sscanf(key_str, key);
933*387f9dfdSAndroid Build Coastguard Worker   if (rc.code() < 0) {
934*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", rc.msg().c_str());
935*387f9dfdSAndroid Build Coastguard Worker     return -1;
936*387f9dfdSAndroid Build Coastguard Worker   }
937*387f9dfdSAndroid Build Coastguard Worker   return 0;
938*387f9dfdSAndroid Build Coastguard Worker }
939*387f9dfdSAndroid Build Coastguard Worker 
table_leaf_scanf(size_t id,const char * leaf_str,void * leaf)940*387f9dfdSAndroid Build Coastguard Worker int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) {
941*387f9dfdSAndroid Build Coastguard Worker   if (id >= tables_.size())
942*387f9dfdSAndroid Build Coastguard Worker     return -1;
943*387f9dfdSAndroid Build Coastguard Worker   const TableDesc &desc = *tables_[id];
944*387f9dfdSAndroid Build Coastguard Worker   StatusTuple rc = desc.leaf_sscanf(leaf_str, leaf);
945*387f9dfdSAndroid Build Coastguard Worker   if (rc.code() < 0) {
946*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "%s\n", rc.msg().c_str());
947*387f9dfdSAndroid Build Coastguard Worker     return -1;
948*387f9dfdSAndroid Build Coastguard Worker   }
949*387f9dfdSAndroid Build Coastguard Worker   return 0;
950*387f9dfdSAndroid Build Coastguard Worker }
951*387f9dfdSAndroid Build Coastguard Worker 
952*387f9dfdSAndroid Build Coastguard Worker // load a C file
load_c(const string & filename,const char * cflags[],int ncflags)953*387f9dfdSAndroid Build Coastguard Worker int BPFModule::load_c(const string &filename, const char *cflags[], int ncflags) {
954*387f9dfdSAndroid Build Coastguard Worker   if (!sections_.empty()) {
955*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "Program already initialized\n");
956*387f9dfdSAndroid Build Coastguard Worker     return -1;
957*387f9dfdSAndroid Build Coastguard Worker   }
958*387f9dfdSAndroid Build Coastguard Worker   if (filename.empty()) {
959*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "Invalid filename\n");
960*387f9dfdSAndroid Build Coastguard Worker     return -1;
961*387f9dfdSAndroid Build Coastguard Worker   }
962*387f9dfdSAndroid Build Coastguard Worker   if (int rc = load_cfile(filename, false, cflags, ncflags))
963*387f9dfdSAndroid Build Coastguard Worker     return rc;
964*387f9dfdSAndroid Build Coastguard Worker   if (rw_engine_enabled_) {
965*387f9dfdSAndroid Build Coastguard Worker     if (int rc = annotate())
966*387f9dfdSAndroid Build Coastguard Worker       return rc;
967*387f9dfdSAndroid Build Coastguard Worker   } else {
968*387f9dfdSAndroid Build Coastguard Worker     annotate_light();
969*387f9dfdSAndroid Build Coastguard Worker   }
970*387f9dfdSAndroid Build Coastguard Worker   if (int rc = finalize())
971*387f9dfdSAndroid Build Coastguard Worker     return rc;
972*387f9dfdSAndroid Build Coastguard Worker   return 0;
973*387f9dfdSAndroid Build Coastguard Worker }
974*387f9dfdSAndroid Build Coastguard Worker 
975*387f9dfdSAndroid Build Coastguard Worker // load a C text string
load_string(const string & text,const char * cflags[],int ncflags)976*387f9dfdSAndroid Build Coastguard Worker int BPFModule::load_string(const string &text, const char *cflags[], int ncflags) {
977*387f9dfdSAndroid Build Coastguard Worker   if (!sections_.empty()) {
978*387f9dfdSAndroid Build Coastguard Worker     fprintf(stderr, "Program already initialized\n");
979*387f9dfdSAndroid Build Coastguard Worker     return -1;
980*387f9dfdSAndroid Build Coastguard Worker   }
981*387f9dfdSAndroid Build Coastguard Worker   if (int rc = load_cfile(text, true, cflags, ncflags))
982*387f9dfdSAndroid Build Coastguard Worker     return rc;
983*387f9dfdSAndroid Build Coastguard Worker   if (rw_engine_enabled_) {
984*387f9dfdSAndroid Build Coastguard Worker     if (int rc = annotate())
985*387f9dfdSAndroid Build Coastguard Worker       return rc;
986*387f9dfdSAndroid Build Coastguard Worker   } else {
987*387f9dfdSAndroid Build Coastguard Worker     annotate_light();
988*387f9dfdSAndroid Build Coastguard Worker   }
989*387f9dfdSAndroid Build Coastguard Worker 
990*387f9dfdSAndroid Build Coastguard Worker   if (int rc = finalize())
991*387f9dfdSAndroid Build Coastguard Worker     return rc;
992*387f9dfdSAndroid Build Coastguard Worker   return 0;
993*387f9dfdSAndroid Build Coastguard Worker }
994*387f9dfdSAndroid Build Coastguard Worker 
bcc_func_load(int prog_type,const char * name,const struct bpf_insn * insns,int prog_len,const char * license,unsigned kern_version,int log_level,char * log_buf,unsigned log_buf_size,const char * dev_name,unsigned flags,int expected_attach_type)995*387f9dfdSAndroid Build Coastguard Worker int BPFModule::bcc_func_load(int prog_type, const char *name,
996*387f9dfdSAndroid Build Coastguard Worker                 const struct bpf_insn *insns, int prog_len,
997*387f9dfdSAndroid Build Coastguard Worker                 const char *license, unsigned kern_version,
998*387f9dfdSAndroid Build Coastguard Worker                 int log_level, char *log_buf, unsigned log_buf_size,
999*387f9dfdSAndroid Build Coastguard Worker                 const char *dev_name, unsigned flags, int expected_attach_type) {
1000*387f9dfdSAndroid Build Coastguard Worker   struct bpf_prog_load_opts opts = {};
1001*387f9dfdSAndroid Build Coastguard Worker   unsigned func_info_cnt, line_info_cnt, finfo_rec_size, linfo_rec_size;
1002*387f9dfdSAndroid Build Coastguard Worker   void *func_info = NULL, *line_info = NULL;
1003*387f9dfdSAndroid Build Coastguard Worker   int ret;
1004*387f9dfdSAndroid Build Coastguard Worker 
1005*387f9dfdSAndroid Build Coastguard Worker   if (expected_attach_type != -1) {
1006*387f9dfdSAndroid Build Coastguard Worker     opts.expected_attach_type = (enum bpf_attach_type)expected_attach_type;
1007*387f9dfdSAndroid Build Coastguard Worker   }
1008*387f9dfdSAndroid Build Coastguard Worker   if (prog_type != BPF_PROG_TYPE_TRACING &&
1009*387f9dfdSAndroid Build Coastguard Worker       prog_type != BPF_PROG_TYPE_EXT) {
1010*387f9dfdSAndroid Build Coastguard Worker     opts.kern_version = kern_version;
1011*387f9dfdSAndroid Build Coastguard Worker   }
1012*387f9dfdSAndroid Build Coastguard Worker   opts.prog_flags = flags;
1013*387f9dfdSAndroid Build Coastguard Worker   opts.log_level = log_level;
1014*387f9dfdSAndroid Build Coastguard Worker   if (dev_name)
1015*387f9dfdSAndroid Build Coastguard Worker     opts.prog_ifindex = if_nametoindex(dev_name);
1016*387f9dfdSAndroid Build Coastguard Worker 
1017*387f9dfdSAndroid Build Coastguard Worker   if (btf_) {
1018*387f9dfdSAndroid Build Coastguard Worker     int btf_fd = btf_->get_fd();
1019*387f9dfdSAndroid Build Coastguard Worker     char secname[256];
1020*387f9dfdSAndroid Build Coastguard Worker 
1021*387f9dfdSAndroid Build Coastguard Worker     ::snprintf(secname, sizeof(secname), "%s%s", BPF_FN_PREFIX, name);
1022*387f9dfdSAndroid Build Coastguard Worker     ret = btf_->get_btf_info(secname, &func_info, &func_info_cnt,
1023*387f9dfdSAndroid Build Coastguard Worker                              &finfo_rec_size, &line_info,
1024*387f9dfdSAndroid Build Coastguard Worker                              &line_info_cnt, &linfo_rec_size);
1025*387f9dfdSAndroid Build Coastguard Worker     if (!ret) {
1026*387f9dfdSAndroid Build Coastguard Worker       opts.prog_btf_fd = btf_fd;
1027*387f9dfdSAndroid Build Coastguard Worker       opts.func_info = func_info;
1028*387f9dfdSAndroid Build Coastguard Worker       opts.func_info_cnt = func_info_cnt;
1029*387f9dfdSAndroid Build Coastguard Worker       opts.func_info_rec_size = finfo_rec_size;
1030*387f9dfdSAndroid Build Coastguard Worker       opts.line_info = line_info;
1031*387f9dfdSAndroid Build Coastguard Worker       opts.line_info_cnt = line_info_cnt;
1032*387f9dfdSAndroid Build Coastguard Worker       opts.line_info_rec_size = linfo_rec_size;
1033*387f9dfdSAndroid Build Coastguard Worker     }
1034*387f9dfdSAndroid Build Coastguard Worker   }
1035*387f9dfdSAndroid Build Coastguard Worker 
1036*387f9dfdSAndroid Build Coastguard Worker   ret = bcc_prog_load_xattr((enum bpf_prog_type)prog_type, name, license, insns, &opts, prog_len, log_buf, log_buf_size, allow_rlimit_);
1037*387f9dfdSAndroid Build Coastguard Worker   if (btf_) {
1038*387f9dfdSAndroid Build Coastguard Worker     free(func_info);
1039*387f9dfdSAndroid Build Coastguard Worker     free(line_info);
1040*387f9dfdSAndroid Build Coastguard Worker   }
1041*387f9dfdSAndroid Build Coastguard Worker 
1042*387f9dfdSAndroid Build Coastguard Worker   return ret;
1043*387f9dfdSAndroid Build Coastguard Worker }
1044*387f9dfdSAndroid Build Coastguard Worker 
bcc_func_attach(int prog_fd,int attachable_fd,int attach_type,unsigned int flags)1045*387f9dfdSAndroid Build Coastguard Worker int BPFModule::bcc_func_attach(int prog_fd, int attachable_fd,
1046*387f9dfdSAndroid Build Coastguard Worker                                int attach_type, unsigned int flags) {
1047*387f9dfdSAndroid Build Coastguard Worker   return bpf_prog_attach(prog_fd, attachable_fd,
1048*387f9dfdSAndroid Build Coastguard Worker                          (enum bpf_attach_type)attach_type, flags);
1049*387f9dfdSAndroid Build Coastguard Worker }
1050*387f9dfdSAndroid Build Coastguard Worker 
bcc_func_detach(int prog_fd,int attachable_fd,int attach_type)1051*387f9dfdSAndroid Build Coastguard Worker int BPFModule::bcc_func_detach(int prog_fd, int attachable_fd,
1052*387f9dfdSAndroid Build Coastguard Worker                                int attach_type) {
1053*387f9dfdSAndroid Build Coastguard Worker   return bpf_prog_detach2(prog_fd, attachable_fd,
1054*387f9dfdSAndroid Build Coastguard Worker                           (enum bpf_attach_type)attach_type);
1055*387f9dfdSAndroid Build Coastguard Worker }
1056*387f9dfdSAndroid Build Coastguard Worker 
1057*387f9dfdSAndroid Build Coastguard Worker } // namespace ebpf
1058