xref: /aosp_15_r20/external/bcc/src/cc/syms.h (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) 2016 GitHub, 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 #pragma once
17*387f9dfdSAndroid Build Coastguard Worker 
18*387f9dfdSAndroid Build Coastguard Worker #include <algorithm>
19*387f9dfdSAndroid Build Coastguard Worker #include <memory>
20*387f9dfdSAndroid Build Coastguard Worker #include <string>
21*387f9dfdSAndroid Build Coastguard Worker #include <sys/types.h>
22*387f9dfdSAndroid Build Coastguard Worker #include <unordered_map>
23*387f9dfdSAndroid Build Coastguard Worker #include <unordered_set>
24*387f9dfdSAndroid Build Coastguard Worker #include <vector>
25*387f9dfdSAndroid Build Coastguard Worker 
26*387f9dfdSAndroid Build Coastguard Worker #include "bcc_proc.h"
27*387f9dfdSAndroid Build Coastguard Worker #include "bcc_syms.h"
28*387f9dfdSAndroid Build Coastguard Worker #include "file_desc.h"
29*387f9dfdSAndroid Build Coastguard Worker 
30*387f9dfdSAndroid Build Coastguard Worker class ProcStat {
31*387f9dfdSAndroid Build Coastguard Worker   std::string procfs_;
32*387f9dfdSAndroid Build Coastguard Worker   std::string root_symlink_;
33*387f9dfdSAndroid Build Coastguard Worker   std::string mount_ns_symlink_;
34*387f9dfdSAndroid Build Coastguard Worker   // file descriptor of /proc/<pid>/root open with O_PATH used to get into root
35*387f9dfdSAndroid Build Coastguard Worker   // of process after it exits; unlike a dereferenced root symlink, *at calls
36*387f9dfdSAndroid Build Coastguard Worker   // to this use the process's mount namespace
37*387f9dfdSAndroid Build Coastguard Worker   int root_fd_ = -1;
38*387f9dfdSAndroid Build Coastguard Worker   // store also root path and mount namespace pair to detect its changes
39*387f9dfdSAndroid Build Coastguard Worker   std::string root_, mount_ns_;
40*387f9dfdSAndroid Build Coastguard Worker   ino_t inode_;
41*387f9dfdSAndroid Build Coastguard Worker   bool getinode_(ino_t &inode);
42*387f9dfdSAndroid Build Coastguard Worker 
43*387f9dfdSAndroid Build Coastguard Worker  public:
44*387f9dfdSAndroid Build Coastguard Worker   ProcStat(int pid);
~ProcStat()45*387f9dfdSAndroid Build Coastguard Worker   ~ProcStat() {
46*387f9dfdSAndroid Build Coastguard Worker     if (root_fd_ > 0)
47*387f9dfdSAndroid Build Coastguard Worker       close(root_fd_);
48*387f9dfdSAndroid Build Coastguard Worker   }
49*387f9dfdSAndroid Build Coastguard Worker   bool refresh_root();
get_root_fd()50*387f9dfdSAndroid Build Coastguard Worker   int get_root_fd() { return root_fd_; }
51*387f9dfdSAndroid Build Coastguard Worker   bool is_stale();
reset()52*387f9dfdSAndroid Build Coastguard Worker   void reset() { getinode_(inode_); }
53*387f9dfdSAndroid Build Coastguard Worker };
54*387f9dfdSAndroid Build Coastguard Worker 
55*387f9dfdSAndroid Build Coastguard Worker class SymbolCache {
56*387f9dfdSAndroid Build Coastguard Worker public:
57*387f9dfdSAndroid Build Coastguard Worker   virtual ~SymbolCache() = default;
58*387f9dfdSAndroid Build Coastguard Worker 
59*387f9dfdSAndroid Build Coastguard Worker   virtual void refresh() = 0;
60*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) = 0;
61*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_name(const char *module, const char *name,
62*387f9dfdSAndroid Build Coastguard Worker                             uint64_t *addr) = 0;
63*387f9dfdSAndroid Build Coastguard Worker };
64*387f9dfdSAndroid Build Coastguard Worker 
65*387f9dfdSAndroid Build Coastguard Worker class KSyms : SymbolCache {
66*387f9dfdSAndroid Build Coastguard Worker   struct Symbol {
SymbolSymbol67*387f9dfdSAndroid Build Coastguard Worker     Symbol(const char *name, const char *mod, uint64_t addr) : name(name), mod(mod), addr(addr) {}
68*387f9dfdSAndroid Build Coastguard Worker     std::string name;
69*387f9dfdSAndroid Build Coastguard Worker     std::string mod;
70*387f9dfdSAndroid Build Coastguard Worker     uint64_t addr;
71*387f9dfdSAndroid Build Coastguard Worker 
72*387f9dfdSAndroid Build Coastguard Worker     bool operator<(const Symbol &rhs) const { return addr < rhs.addr; }
73*387f9dfdSAndroid Build Coastguard Worker   };
74*387f9dfdSAndroid Build Coastguard Worker 
75*387f9dfdSAndroid Build Coastguard Worker   std::vector<Symbol> syms_;
76*387f9dfdSAndroid Build Coastguard Worker   std::unordered_map<std::string, uint64_t> symnames_;
77*387f9dfdSAndroid Build Coastguard Worker   static void _add_symbol(const char *, const char *, uint64_t, void *);
78*387f9dfdSAndroid Build Coastguard Worker 
79*387f9dfdSAndroid Build Coastguard Worker public:
80*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) override;
81*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_name(const char *unused, const char *name,
82*387f9dfdSAndroid Build Coastguard Worker                             uint64_t *addr) override;
83*387f9dfdSAndroid Build Coastguard Worker   virtual void refresh() override;
84*387f9dfdSAndroid Build Coastguard Worker };
85*387f9dfdSAndroid Build Coastguard Worker 
86*387f9dfdSAndroid Build Coastguard Worker class ProcSyms : SymbolCache {
87*387f9dfdSAndroid Build Coastguard Worker   struct NameIdx {
88*387f9dfdSAndroid Build Coastguard Worker     size_t section_idx;
89*387f9dfdSAndroid Build Coastguard Worker     size_t str_table_idx;
90*387f9dfdSAndroid Build Coastguard Worker     size_t str_len;
91*387f9dfdSAndroid Build Coastguard Worker     bool debugfile;
92*387f9dfdSAndroid Build Coastguard Worker   };
93*387f9dfdSAndroid Build Coastguard Worker 
94*387f9dfdSAndroid Build Coastguard Worker   struct Symbol {
SymbolSymbol95*387f9dfdSAndroid Build Coastguard Worker     Symbol(const std::string *name, uint64_t start, uint64_t size)
96*387f9dfdSAndroid Build Coastguard Worker         : is_name_resolved(true), start(start), size(size) {
97*387f9dfdSAndroid Build Coastguard Worker       data.name = name;
98*387f9dfdSAndroid Build Coastguard Worker     }
SymbolSymbol99*387f9dfdSAndroid Build Coastguard Worker     Symbol(size_t section_idx, size_t str_table_idx, size_t str_len, uint64_t start,
100*387f9dfdSAndroid Build Coastguard Worker            uint64_t size, bool debugfile)
101*387f9dfdSAndroid Build Coastguard Worker         : is_name_resolved(false), start(start), size(size) {
102*387f9dfdSAndroid Build Coastguard Worker       data.name_idx.section_idx = section_idx;
103*387f9dfdSAndroid Build Coastguard Worker       data.name_idx.str_table_idx = str_table_idx;
104*387f9dfdSAndroid Build Coastguard Worker       data.name_idx.str_len = str_len;
105*387f9dfdSAndroid Build Coastguard Worker       data.name_idx.debugfile = debugfile;
106*387f9dfdSAndroid Build Coastguard Worker     }
107*387f9dfdSAndroid Build Coastguard Worker     bool is_name_resolved;
108*387f9dfdSAndroid Build Coastguard Worker     union {
109*387f9dfdSAndroid Build Coastguard Worker       struct NameIdx name_idx;
110*387f9dfdSAndroid Build Coastguard Worker       const std::string *name{nullptr};
111*387f9dfdSAndroid Build Coastguard Worker     } data;
112*387f9dfdSAndroid Build Coastguard Worker     uint64_t start;
113*387f9dfdSAndroid Build Coastguard Worker     uint64_t size;
114*387f9dfdSAndroid Build Coastguard Worker 
115*387f9dfdSAndroid Build Coastguard Worker     bool operator<(const struct Symbol& rhs) const {
116*387f9dfdSAndroid Build Coastguard Worker       return start < rhs.start;
117*387f9dfdSAndroid Build Coastguard Worker     }
118*387f9dfdSAndroid Build Coastguard Worker   };
119*387f9dfdSAndroid Build Coastguard Worker 
120*387f9dfdSAndroid Build Coastguard Worker   enum class ModuleType {
121*387f9dfdSAndroid Build Coastguard Worker     UNKNOWN,
122*387f9dfdSAndroid Build Coastguard Worker     EXEC,
123*387f9dfdSAndroid Build Coastguard Worker     SO,
124*387f9dfdSAndroid Build Coastguard Worker     PERF_MAP,
125*387f9dfdSAndroid Build Coastguard Worker     VDSO
126*387f9dfdSAndroid Build Coastguard Worker   };
127*387f9dfdSAndroid Build Coastguard Worker 
128*387f9dfdSAndroid Build Coastguard Worker   class ModulePath {
129*387f9dfdSAndroid Build Coastguard Worker     // helper class to get a usable module path independent of the running
130*387f9dfdSAndroid Build Coastguard Worker     // process by storing a file descriptor created from openat(2) if possible
131*387f9dfdSAndroid Build Coastguard Worker     // if openat fails, falls back to process-dependent path with /proc/.../root
132*387f9dfdSAndroid Build Coastguard Worker    private:
133*387f9dfdSAndroid Build Coastguard Worker     int fd_;
134*387f9dfdSAndroid Build Coastguard Worker     std::string proc_root_path_;
135*387f9dfdSAndroid Build Coastguard Worker     std::string path_;
136*387f9dfdSAndroid Build Coastguard Worker 
137*387f9dfdSAndroid Build Coastguard Worker    public:
138*387f9dfdSAndroid Build Coastguard Worker     ModulePath(const std::string &ns_path, int root_fd, int pid, bool enter_ns);
alt_path()139*387f9dfdSAndroid Build Coastguard Worker     const char *alt_path() { return proc_root_path_.c_str(); }
path()140*387f9dfdSAndroid Build Coastguard Worker     const char *path() {
141*387f9dfdSAndroid Build Coastguard Worker       if (path_ == proc_root_path_ || access(proc_root_path_.c_str(), F_OK) < 0)
142*387f9dfdSAndroid Build Coastguard Worker         // cannot stat /proc/.../root/<path>, pid might not exist anymore; use /proc/self/fd/...
143*387f9dfdSAndroid Build Coastguard Worker         return path_.c_str();
144*387f9dfdSAndroid Build Coastguard Worker       return proc_root_path_.c_str();
145*387f9dfdSAndroid Build Coastguard Worker     }
~ModulePath()146*387f9dfdSAndroid Build Coastguard Worker     ~ModulePath() {
147*387f9dfdSAndroid Build Coastguard Worker       if (fd_ > 0)
148*387f9dfdSAndroid Build Coastguard Worker         close(fd_);
149*387f9dfdSAndroid Build Coastguard Worker     }
150*387f9dfdSAndroid Build Coastguard Worker   };
151*387f9dfdSAndroid Build Coastguard Worker 
152*387f9dfdSAndroid Build Coastguard Worker   struct Module {
153*387f9dfdSAndroid Build Coastguard Worker     struct Range {
154*387f9dfdSAndroid Build Coastguard Worker       uint64_t start;
155*387f9dfdSAndroid Build Coastguard Worker       uint64_t end;
156*387f9dfdSAndroid Build Coastguard Worker       uint64_t file_offset;
RangeModule::Range157*387f9dfdSAndroid Build Coastguard Worker       Range(uint64_t s, uint64_t e, uint64_t f)
158*387f9dfdSAndroid Build Coastguard Worker           : start(s), end(e), file_offset(f) {}
159*387f9dfdSAndroid Build Coastguard Worker     };
160*387f9dfdSAndroid Build Coastguard Worker 
161*387f9dfdSAndroid Build Coastguard Worker     Module(const char *name, std::shared_ptr<ModulePath> path,
162*387f9dfdSAndroid Build Coastguard Worker            struct bcc_symbol_option *option);
163*387f9dfdSAndroid Build Coastguard Worker 
164*387f9dfdSAndroid Build Coastguard Worker     std::string name_;
165*387f9dfdSAndroid Build Coastguard Worker     std::shared_ptr<ModulePath> path_;
166*387f9dfdSAndroid Build Coastguard Worker     std::vector<Range> ranges_;
167*387f9dfdSAndroid Build Coastguard Worker     bool loaded_;
168*387f9dfdSAndroid Build Coastguard Worker     bcc_symbol_option *symbol_option_;
169*387f9dfdSAndroid Build Coastguard Worker     ModuleType type_;
170*387f9dfdSAndroid Build Coastguard Worker 
171*387f9dfdSAndroid Build Coastguard Worker     // The file offset within the ELF of the SO's first text section.
172*387f9dfdSAndroid Build Coastguard Worker     uint64_t elf_so_offset_;
173*387f9dfdSAndroid Build Coastguard Worker     uint64_t elf_so_addr_;
174*387f9dfdSAndroid Build Coastguard Worker 
175*387f9dfdSAndroid Build Coastguard Worker     std::unordered_set<std::string> symnames_;
176*387f9dfdSAndroid Build Coastguard Worker     std::vector<Symbol> syms_;
177*387f9dfdSAndroid Build Coastguard Worker 
178*387f9dfdSAndroid Build Coastguard Worker     void load_sym_table();
179*387f9dfdSAndroid Build Coastguard Worker 
180*387f9dfdSAndroid Build Coastguard Worker     bool contains(uint64_t addr, uint64_t &offset) const;
startModule181*387f9dfdSAndroid Build Coastguard Worker     uint64_t start() const { return ranges_.begin()->start; }
182*387f9dfdSAndroid Build Coastguard Worker 
183*387f9dfdSAndroid Build Coastguard Worker     bool find_addr(uint64_t offset, struct bcc_symbol *sym);
184*387f9dfdSAndroid Build Coastguard Worker     bool find_name(const char *symname, uint64_t *addr);
185*387f9dfdSAndroid Build Coastguard Worker 
186*387f9dfdSAndroid Build Coastguard Worker     static int _add_symbol(const char *symname, uint64_t start, uint64_t size,
187*387f9dfdSAndroid Build Coastguard Worker                            void *p);
188*387f9dfdSAndroid Build Coastguard Worker     static int _add_symbol_lazy(size_t section_idx, size_t str_table_idx,
189*387f9dfdSAndroid Build Coastguard Worker                                 size_t str_len, uint64_t start, uint64_t size,
190*387f9dfdSAndroid Build Coastguard Worker                                 int debugfile, void *p);
191*387f9dfdSAndroid Build Coastguard Worker   };
192*387f9dfdSAndroid Build Coastguard Worker 
193*387f9dfdSAndroid Build Coastguard Worker   int pid_;
194*387f9dfdSAndroid Build Coastguard Worker   std::vector<Module> modules_;
195*387f9dfdSAndroid Build Coastguard Worker   ProcStat procstat_;
196*387f9dfdSAndroid Build Coastguard Worker   bcc_symbol_option symbol_option_;
197*387f9dfdSAndroid Build Coastguard Worker 
198*387f9dfdSAndroid Build Coastguard Worker   static int _add_module(mod_info *, int, void *);
199*387f9dfdSAndroid Build Coastguard Worker   void load_modules();
200*387f9dfdSAndroid Build Coastguard Worker 
201*387f9dfdSAndroid Build Coastguard Worker public:
202*387f9dfdSAndroid Build Coastguard Worker   ProcSyms(int pid, struct bcc_symbol_option *option = nullptr);
203*387f9dfdSAndroid Build Coastguard Worker   virtual void refresh() override;
204*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) override;
205*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_name(const char *module, const char *name,
206*387f9dfdSAndroid Build Coastguard Worker                             uint64_t *addr) override;
207*387f9dfdSAndroid Build Coastguard Worker };
208*387f9dfdSAndroid Build Coastguard Worker 
209*387f9dfdSAndroid Build Coastguard Worker class BuildSyms {
210*387f9dfdSAndroid Build Coastguard Worker   struct Symbol {
SymbolSymbol211*387f9dfdSAndroid Build Coastguard Worker     Symbol(const std::string *name, uint64_t start, uint64_t size)
212*387f9dfdSAndroid Build Coastguard Worker       :name(name), start(start), size(size) {}
213*387f9dfdSAndroid Build Coastguard Worker     const std::string *name;
214*387f9dfdSAndroid Build Coastguard Worker     uint64_t start;
215*387f9dfdSAndroid Build Coastguard Worker     uint64_t size;
216*387f9dfdSAndroid Build Coastguard Worker 
217*387f9dfdSAndroid Build Coastguard Worker     bool operator<(const struct Symbol &rhs) const {
218*387f9dfdSAndroid Build Coastguard Worker       return start < rhs.start;
219*387f9dfdSAndroid Build Coastguard Worker     }
220*387f9dfdSAndroid Build Coastguard Worker   };
221*387f9dfdSAndroid Build Coastguard Worker 
222*387f9dfdSAndroid Build Coastguard Worker   struct Module {
ModuleModule223*387f9dfdSAndroid Build Coastguard Worker     Module(const char *module_name):
224*387f9dfdSAndroid Build Coastguard Worker       module_name_(module_name),
225*387f9dfdSAndroid Build Coastguard Worker       loaded_(false) {}
226*387f9dfdSAndroid Build Coastguard Worker     const std::string module_name_;
227*387f9dfdSAndroid Build Coastguard Worker     const std::string build_id_;
228*387f9dfdSAndroid Build Coastguard Worker     bool loaded_;
229*387f9dfdSAndroid Build Coastguard Worker     std::unordered_set<std::string> symnames_;
230*387f9dfdSAndroid Build Coastguard Worker     std::vector<Symbol> syms_;
231*387f9dfdSAndroid Build Coastguard Worker     bcc_symbol_option symbol_option_;
232*387f9dfdSAndroid Build Coastguard Worker 
233*387f9dfdSAndroid Build Coastguard Worker     bool load_sym_table();
234*387f9dfdSAndroid Build Coastguard Worker     static int _add_symbol(const char *symname, uint64_t start, uint64_t size,
235*387f9dfdSAndroid Build Coastguard Worker                             void *p);
236*387f9dfdSAndroid Build Coastguard Worker     bool resolve_addr(uint64_t offset, struct bcc_symbol*, bool demangle=true);
237*387f9dfdSAndroid Build Coastguard Worker   };
238*387f9dfdSAndroid Build Coastguard Worker 
239*387f9dfdSAndroid Build Coastguard Worker   std::unordered_map<std::string, std::unique_ptr<Module> > buildmap_;
240*387f9dfdSAndroid Build Coastguard Worker 
241*387f9dfdSAndroid Build Coastguard Worker public:
BuildSyms()242*387f9dfdSAndroid Build Coastguard Worker   BuildSyms() {}
243*387f9dfdSAndroid Build Coastguard Worker   virtual ~BuildSyms() = default;
244*387f9dfdSAndroid Build Coastguard Worker   virtual bool add_module(const std::string module_name);
245*387f9dfdSAndroid Build Coastguard Worker   virtual bool resolve_addr(std::string build_id, uint64_t offset, struct bcc_symbol *sym, bool demangle = true);
246*387f9dfdSAndroid Build Coastguard Worker };
247