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