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_syms.h" 27 #include "file_desc.h" 28 #include "ns_guard.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, uint64_t addr) : name(name), addr(addr) {} 54 std::string name; 55 uint64_t addr; 56 57 bool operator<(const Symbol &rhs) const { return addr < rhs.addr; } 58 }; 59 60 std::vector<Symbol> syms_; 61 std::unordered_map<std::string, uint64_t> symnames_; 62 static void _add_symbol(const char *, uint64_t, void *); 63 64 public: 65 virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true); 66 virtual bool resolve_name(const char *unused, const char *name, 67 uint64_t *addr); 68 virtual void refresh(); 69 }; 70 71 class ProcSyms : SymbolCache { 72 struct Symbol { SymbolSymbol73 Symbol(const std::string *name, uint64_t start, uint64_t size) 74 : name(name), start(start), size(size) {} 75 const std::string *name; 76 uint64_t start; 77 uint64_t size; 78 79 bool operator<(const struct Symbol& rhs) const { 80 return start < rhs.start; 81 } 82 }; 83 84 enum class ModuleType { 85 UNKNOWN, 86 EXEC, 87 SO, 88 PERF_MAP, 89 VDSO 90 }; 91 92 struct Module { 93 struct Range { 94 uint64_t start; 95 uint64_t end; 96 uint64_t file_offset; RangeModule::Range97 Range(uint64_t s, uint64_t e, uint64_t f) 98 : start(s), end(e), file_offset(f) {} 99 }; 100 101 Module(const char *name, ProcMountNS *mount_ns, 102 struct bcc_symbol_option *option); 103 104 std::string name_; 105 std::vector<Range> ranges_; 106 bool loaded_; 107 ProcMountNS *mount_ns_; 108 bcc_symbol_option *symbol_option_; 109 ModuleType type_; 110 111 // The file offset within the ELF of the SO's first text section. 112 uint64_t elf_so_offset_; 113 uint64_t elf_so_addr_; 114 115 std::unordered_set<std::string> symnames_; 116 std::vector<Symbol> syms_; 117 118 void load_sym_table(); 119 120 bool contains(uint64_t addr, uint64_t &offset) const; startModule121 uint64_t start() const { return ranges_.begin()->start; } 122 123 bool find_addr(uint64_t offset, struct bcc_symbol *sym); 124 bool find_name(const char *symname, uint64_t *addr); 125 126 static int _add_symbol(const char *symname, uint64_t start, uint64_t size, 127 void *p); 128 }; 129 130 int pid_; 131 std::vector<Module> modules_; 132 ProcStat procstat_; 133 std::unique_ptr<ProcMountNS> mount_ns_instance_; 134 bcc_symbol_option symbol_option_; 135 136 static int _add_load_sections(uint64_t v_addr, uint64_t mem_sz, 137 uint64_t file_offset, void *payload); 138 static int _add_module(const char *, uint64_t, uint64_t, uint64_t, bool, 139 void *); 140 void load_exe(); 141 void load_modules(); 142 143 public: 144 ProcSyms(int pid, struct bcc_symbol_option *option = nullptr); 145 virtual void refresh(); 146 virtual bool resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle = true); 147 virtual bool resolve_name(const char *module, const char *name, 148 uint64_t *addr); 149 }; 150