1 /* 2 * Copyright (c) 2016 GitHub, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <algorithm> 19 #include <memory> 20 #include <string> 21 #include <sys/types.h> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <vector> 25 26 #include "bcc_proc.h" 27 #include "bcc_syms.h" 28 #include "file_desc.h" 29 30 class ProcStat { 31 std::string procfs_; 32 ino_t inode_; 33 ino_t getinode_(); 34 35 public: 36 ProcStat(int pid); 37 bool is_stale(); reset()38 void reset() { inode_ = getinode_(); } 39 }; 40 41 class SymbolCache { 42 public: 43 virtual ~SymbolCache() = default; 44 45 virtual void refresh() = 0; 46 virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) = 0; 47 virtual bool resolve_name(const char *module, const char *name, 48 uint64_t *addr) = 0; 49 }; 50 51 class KSyms : SymbolCache { 52 struct Symbol { SymbolSymbol53 Symbol(const char *name, const char *mod, uint64_t addr) : name(name), mod(mod), addr(addr) {} 54 std::string name; 55 std::string mod; 56 uint64_t addr; 57 58 bool operator<(const Symbol &rhs) const { return addr < rhs.addr; } 59 }; 60 61 std::vector<Symbol> syms_; 62 std::unordered_map<std::string, uint64_t> symnames_; 63 static void _add_symbol(const char *, const char *, uint64_t, void *); 64 65 public: 66 virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) override; 67 virtual bool resolve_name(const char *unused, const char *name, 68 uint64_t *addr) override; 69 virtual void refresh() override; 70 }; 71 72 class ProcSyms : SymbolCache { 73 struct NameIdx { 74 size_t section_idx; 75 size_t str_table_idx; 76 size_t str_len; 77 bool debugfile; 78 }; 79 80 struct Symbol { SymbolSymbol81 Symbol(const std::string *name, uint64_t start, uint64_t size) 82 : is_name_resolved(true), start(start), size(size) { 83 data.name = name; 84 } SymbolSymbol85 Symbol(size_t section_idx, size_t str_table_idx, size_t str_len, uint64_t start, 86 uint64_t size, bool debugfile) 87 : is_name_resolved(false), start(start), size(size) { 88 data.name_idx.section_idx = section_idx; 89 data.name_idx.str_table_idx = str_table_idx; 90 data.name_idx.str_len = str_len; 91 data.name_idx.debugfile = debugfile; 92 } 93 bool is_name_resolved; 94 union { 95 struct NameIdx name_idx; 96 const std::string *name{nullptr}; 97 } data; 98 uint64_t start; 99 uint64_t size; 100 101 bool operator<(const struct Symbol& rhs) const { 102 return start < rhs.start; 103 } 104 }; 105 106 enum class ModuleType { 107 UNKNOWN, 108 EXEC, 109 SO, 110 PERF_MAP, 111 VDSO 112 }; 113 114 struct Module { 115 struct Range { 116 uint64_t start; 117 uint64_t end; 118 uint64_t file_offset; RangeModule::Range119 Range(uint64_t s, uint64_t e, uint64_t f) 120 : start(s), end(e), file_offset(f) {} 121 }; 122 123 Module(const char *name, const char *path, struct bcc_symbol_option *option); 124 125 std::string name_; 126 std::string path_; 127 std::vector<Range> ranges_; 128 bool loaded_; 129 bcc_symbol_option *symbol_option_; 130 ModuleType type_; 131 132 // The file offset within the ELF of the SO's first text section. 133 uint64_t elf_so_offset_; 134 uint64_t elf_so_addr_; 135 136 std::unordered_set<std::string> symnames_; 137 std::vector<Symbol> syms_; 138 139 void load_sym_table(); 140 141 bool contains(uint64_t addr, uint64_t &offset) const; startModule142 uint64_t start() const { return ranges_.begin()->start; } 143 144 bool find_addr(uint64_t offset, struct bcc_symbol *sym); 145 bool find_name(const char *symname, uint64_t *addr); 146 147 static int _add_symbol(const char *symname, uint64_t start, uint64_t size, 148 void *p); 149 static int _add_symbol_lazy(size_t section_idx, size_t str_table_idx, 150 size_t str_len, uint64_t start, uint64_t size, 151 int debugfile, void *p); 152 }; 153 154 int pid_; 155 std::vector<Module> modules_; 156 ProcStat procstat_; 157 bcc_symbol_option symbol_option_; 158 159 static int _add_module(mod_info *, int, void *); 160 void load_modules(); 161 162 public: 163 ProcSyms(int pid, struct bcc_symbol_option *option = nullptr); 164 virtual void refresh() override; 165 virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true) override; 166 virtual bool resolve_name(const char *module, const char *name, 167 uint64_t *addr) override; 168 }; 169 170 class BuildSyms { 171 struct Symbol { SymbolSymbol172 Symbol(const std::string *name, uint64_t start, uint64_t size) 173 :name(name), start(start), size(size) {} 174 const std::string *name; 175 uint64_t start; 176 uint64_t size; 177 178 bool operator<(const struct Symbol &rhs) const { 179 return start < rhs.start; 180 } 181 }; 182 183 struct Module { ModuleModule184 Module(const char *module_name): 185 module_name_(module_name), 186 loaded_(false) {} 187 const std::string module_name_; 188 const std::string build_id_; 189 bool loaded_; 190 std::unordered_set<std::string> symnames_; 191 std::vector<Symbol> syms_; 192 bcc_symbol_option symbol_option_; 193 194 bool load_sym_table(); 195 static int _add_symbol(const char *symname, uint64_t start, uint64_t size, 196 void *p); 197 bool resolve_addr(uint64_t offset, struct bcc_symbol*, bool demangle=true); 198 }; 199 200 std::unordered_map<std::string, std::unique_ptr<Module> > buildmap_; 201 202 public: BuildSyms()203 BuildSyms() {} 204 virtual ~BuildSyms() = default; 205 virtual bool add_module(const std::string module_name); 206 virtual bool resolve_addr(std::string build_id, uint64_t offset, struct bcc_symbol *sym, bool demangle = true); 207 }; 208