xref: /aosp_15_r20/external/bcc/src/cc/bcc_syms.cc (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 
17*387f9dfdSAndroid Build Coastguard Worker #include "bcc_syms.h"
18*387f9dfdSAndroid Build Coastguard Worker 
19*387f9dfdSAndroid Build Coastguard Worker #include <cxxabi.h>
20*387f9dfdSAndroid Build Coastguard Worker #include <fcntl.h>
21*387f9dfdSAndroid Build Coastguard Worker #include <limits.h>
22*387f9dfdSAndroid Build Coastguard Worker #include <linux/elf.h>
23*387f9dfdSAndroid Build Coastguard Worker #include <signal.h>
24*387f9dfdSAndroid Build Coastguard Worker #include <string.h>
25*387f9dfdSAndroid Build Coastguard Worker #include <sys/stat.h>
26*387f9dfdSAndroid Build Coastguard Worker #include <sys/sysmacros.h>
27*387f9dfdSAndroid Build Coastguard Worker #include <sys/types.h>
28*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
29*387f9dfdSAndroid Build Coastguard Worker 
30*387f9dfdSAndroid Build Coastguard Worker #include <cstdio>
31*387f9dfdSAndroid Build Coastguard Worker #include <cstring>
32*387f9dfdSAndroid Build Coastguard Worker 
33*387f9dfdSAndroid Build Coastguard Worker #include "bcc_elf.h"
34*387f9dfdSAndroid Build Coastguard Worker #include "bcc_perf_map.h"
35*387f9dfdSAndroid Build Coastguard Worker #include "bcc_proc.h"
36*387f9dfdSAndroid Build Coastguard Worker #include "common.h"
37*387f9dfdSAndroid Build Coastguard Worker #include "syms.h"
38*387f9dfdSAndroid Build Coastguard Worker #include "vendor/tinyformat.hpp"
39*387f9dfdSAndroid Build Coastguard Worker 
ModulePath(const std::string & ns_path,int root_fd,int pid,bool enter_ns)40*387f9dfdSAndroid Build Coastguard Worker ProcSyms::ModulePath::ModulePath(const std::string &ns_path, int root_fd,
41*387f9dfdSAndroid Build Coastguard Worker                                  int pid, bool enter_ns) {
42*387f9dfdSAndroid Build Coastguard Worker   if (!enter_ns) {
43*387f9dfdSAndroid Build Coastguard Worker     path_ = ns_path;
44*387f9dfdSAndroid Build Coastguard Worker     proc_root_path_ = ns_path;
45*387f9dfdSAndroid Build Coastguard Worker     return;
46*387f9dfdSAndroid Build Coastguard Worker   }
47*387f9dfdSAndroid Build Coastguard Worker   proc_root_path_ = tfm::format("/proc/%d/root%s", pid, ns_path);
48*387f9dfdSAndroid Build Coastguard Worker   // filename for openat must not contain any starting slashes, otherwise
49*387f9dfdSAndroid Build Coastguard Worker   // it would get treated as an absolute path
50*387f9dfdSAndroid Build Coastguard Worker   std::string trimmed_path;
51*387f9dfdSAndroid Build Coastguard Worker   size_t non_slash_pos;
52*387f9dfdSAndroid Build Coastguard Worker   for (non_slash_pos = 0;
53*387f9dfdSAndroid Build Coastguard Worker        non_slash_pos < ns_path.size() && ns_path[non_slash_pos] == '/';
54*387f9dfdSAndroid Build Coastguard Worker        non_slash_pos++)
55*387f9dfdSAndroid Build Coastguard Worker     ;
56*387f9dfdSAndroid Build Coastguard Worker   trimmed_path = ns_path.substr(non_slash_pos);
57*387f9dfdSAndroid Build Coastguard Worker   fd_ = openat(root_fd, trimmed_path.c_str(), O_RDONLY);
58*387f9dfdSAndroid Build Coastguard Worker   if (fd_ > 0)
59*387f9dfdSAndroid Build Coastguard Worker     path_ = tfm::format("/proc/self/fd/%d", fd_);
60*387f9dfdSAndroid Build Coastguard Worker   else
61*387f9dfdSAndroid Build Coastguard Worker     // openat failed, fall back to /proc/.../root path
62*387f9dfdSAndroid Build Coastguard Worker     path_ = proc_root_path_;
63*387f9dfdSAndroid Build Coastguard Worker }
64*387f9dfdSAndroid Build Coastguard Worker 
getinode_(ino_t & inode)65*387f9dfdSAndroid Build Coastguard Worker bool ProcStat::getinode_(ino_t &inode) {
66*387f9dfdSAndroid Build Coastguard Worker   struct stat s;
67*387f9dfdSAndroid Build Coastguard Worker   if (!stat(procfs_.c_str(), &s)) {
68*387f9dfdSAndroid Build Coastguard Worker     inode = s.st_ino;
69*387f9dfdSAndroid Build Coastguard Worker     return true;
70*387f9dfdSAndroid Build Coastguard Worker   } else {
71*387f9dfdSAndroid Build Coastguard Worker     return false;
72*387f9dfdSAndroid Build Coastguard Worker   }
73*387f9dfdSAndroid Build Coastguard Worker }
74*387f9dfdSAndroid Build Coastguard Worker 
refresh_root()75*387f9dfdSAndroid Build Coastguard Worker bool ProcStat::refresh_root() {
76*387f9dfdSAndroid Build Coastguard Worker   // try to current root and mount namespace for process
77*387f9dfdSAndroid Build Coastguard Worker   char current_root[PATH_MAX], current_mount_ns[PATH_MAX];
78*387f9dfdSAndroid Build Coastguard Worker   if (readlink(root_symlink_.c_str(), current_root, PATH_MAX) < 0 ||
79*387f9dfdSAndroid Build Coastguard Worker       readlink(mount_ns_symlink_.c_str(), current_mount_ns, PATH_MAX) < 0)
80*387f9dfdSAndroid Build Coastguard Worker     // readlink failed, process might not exist anymore; keep old fd
81*387f9dfdSAndroid Build Coastguard Worker     return false;
82*387f9dfdSAndroid Build Coastguard Worker 
83*387f9dfdSAndroid Build Coastguard Worker   // check if root fd is up to date
84*387f9dfdSAndroid Build Coastguard Worker   if (root_fd_ != -1 && current_root == root_ && current_mount_ns == mount_ns_)
85*387f9dfdSAndroid Build Coastguard Worker     return false;
86*387f9dfdSAndroid Build Coastguard Worker 
87*387f9dfdSAndroid Build Coastguard Worker   root_ = current_root;
88*387f9dfdSAndroid Build Coastguard Worker   mount_ns_ = current_mount_ns;
89*387f9dfdSAndroid Build Coastguard Worker 
90*387f9dfdSAndroid Build Coastguard Worker   // either root fd is invalid or process root and/or mount namespace changed;
91*387f9dfdSAndroid Build Coastguard Worker   // re-open root note: when /proc/.../root changes, the open file descriptor
92*387f9dfdSAndroid Build Coastguard Worker   // still refers to the old one
93*387f9dfdSAndroid Build Coastguard Worker   int original_root_fd = root_fd_;
94*387f9dfdSAndroid Build Coastguard Worker   root_fd_ = open(root_symlink_.c_str(), O_PATH);
95*387f9dfdSAndroid Build Coastguard Worker   if (root_fd_ == -1)
96*387f9dfdSAndroid Build Coastguard Worker     std::cerr << "Opening " << root_symlink_ << " failed: " << strerror(errno)
97*387f9dfdSAndroid Build Coastguard Worker               << std::endl;
98*387f9dfdSAndroid Build Coastguard Worker   if (original_root_fd > 0)
99*387f9dfdSAndroid Build Coastguard Worker     close(original_root_fd);
100*387f9dfdSAndroid Build Coastguard Worker   return original_root_fd != root_fd_;
101*387f9dfdSAndroid Build Coastguard Worker }
102*387f9dfdSAndroid Build Coastguard Worker 
is_stale()103*387f9dfdSAndroid Build Coastguard Worker bool ProcStat::is_stale() {
104*387f9dfdSAndroid Build Coastguard Worker   ino_t cur_inode;
105*387f9dfdSAndroid Build Coastguard Worker   return getinode_(cur_inode) && (cur_inode != inode_) && refresh_root();
106*387f9dfdSAndroid Build Coastguard Worker }
107*387f9dfdSAndroid Build Coastguard Worker 
ProcStat(int pid)108*387f9dfdSAndroid Build Coastguard Worker ProcStat::ProcStat(int pid)
109*387f9dfdSAndroid Build Coastguard Worker     : procfs_(tfm::format("/proc/%d/exe", pid)),
110*387f9dfdSAndroid Build Coastguard Worker       root_symlink_(tfm::format("/proc/%d/root", pid)),
111*387f9dfdSAndroid Build Coastguard Worker       mount_ns_symlink_(tfm::format("/proc/%d/ns/mnt", pid)) {
112*387f9dfdSAndroid Build Coastguard Worker   getinode_(inode_);
113*387f9dfdSAndroid Build Coastguard Worker   refresh_root();
114*387f9dfdSAndroid Build Coastguard Worker }
115*387f9dfdSAndroid Build Coastguard Worker 
_add_symbol(const char * symname,const char * modname,uint64_t addr,void * p)116*387f9dfdSAndroid Build Coastguard Worker void KSyms::_add_symbol(const char *symname, const char *modname, uint64_t addr, void *p) {
117*387f9dfdSAndroid Build Coastguard Worker   KSyms *ks = static_cast<KSyms *>(p);
118*387f9dfdSAndroid Build Coastguard Worker   ks->syms_.emplace_back(symname, modname, addr);
119*387f9dfdSAndroid Build Coastguard Worker }
120*387f9dfdSAndroid Build Coastguard Worker 
refresh()121*387f9dfdSAndroid Build Coastguard Worker void KSyms::refresh() {
122*387f9dfdSAndroid Build Coastguard Worker   if (syms_.empty()) {
123*387f9dfdSAndroid Build Coastguard Worker     bcc_procutils_each_ksym(_add_symbol, this);
124*387f9dfdSAndroid Build Coastguard Worker     std::sort(syms_.begin(), syms_.end());
125*387f9dfdSAndroid Build Coastguard Worker   }
126*387f9dfdSAndroid Build Coastguard Worker }
127*387f9dfdSAndroid Build Coastguard Worker 
resolve_addr(uint64_t addr,struct bcc_symbol * sym,bool demangle)128*387f9dfdSAndroid Build Coastguard Worker bool KSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym, bool demangle) {
129*387f9dfdSAndroid Build Coastguard Worker   refresh();
130*387f9dfdSAndroid Build Coastguard Worker 
131*387f9dfdSAndroid Build Coastguard Worker   std::vector<Symbol>::iterator it;
132*387f9dfdSAndroid Build Coastguard Worker 
133*387f9dfdSAndroid Build Coastguard Worker   if (syms_.empty())
134*387f9dfdSAndroid Build Coastguard Worker     goto unknown_symbol;
135*387f9dfdSAndroid Build Coastguard Worker 
136*387f9dfdSAndroid Build Coastguard Worker   it = std::upper_bound(syms_.begin(), syms_.end(), Symbol("", "", addr));
137*387f9dfdSAndroid Build Coastguard Worker   if (it != syms_.begin()) {
138*387f9dfdSAndroid Build Coastguard Worker     it--;
139*387f9dfdSAndroid Build Coastguard Worker     sym->name = (*it).name.c_str();
140*387f9dfdSAndroid Build Coastguard Worker     if (demangle)
141*387f9dfdSAndroid Build Coastguard Worker       sym->demangle_name = sym->name;
142*387f9dfdSAndroid Build Coastguard Worker     sym->module = (*it).mod.c_str();
143*387f9dfdSAndroid Build Coastguard Worker     sym->offset = addr - (*it).addr;
144*387f9dfdSAndroid Build Coastguard Worker     return true;
145*387f9dfdSAndroid Build Coastguard Worker   }
146*387f9dfdSAndroid Build Coastguard Worker 
147*387f9dfdSAndroid Build Coastguard Worker unknown_symbol:
148*387f9dfdSAndroid Build Coastguard Worker   memset(sym, 0, sizeof(struct bcc_symbol));
149*387f9dfdSAndroid Build Coastguard Worker   return false;
150*387f9dfdSAndroid Build Coastguard Worker }
151*387f9dfdSAndroid Build Coastguard Worker 
resolve_name(const char * _unused,const char * name,uint64_t * addr)152*387f9dfdSAndroid Build Coastguard Worker bool KSyms::resolve_name(const char *_unused, const char *name,
153*387f9dfdSAndroid Build Coastguard Worker                          uint64_t *addr) {
154*387f9dfdSAndroid Build Coastguard Worker   refresh();
155*387f9dfdSAndroid Build Coastguard Worker 
156*387f9dfdSAndroid Build Coastguard Worker   if (syms_.size() != symnames_.size()) {
157*387f9dfdSAndroid Build Coastguard Worker     symnames_.clear();
158*387f9dfdSAndroid Build Coastguard Worker     for (Symbol &sym : syms_) {
159*387f9dfdSAndroid Build Coastguard Worker       symnames_[sym.name] = sym.addr;
160*387f9dfdSAndroid Build Coastguard Worker     }
161*387f9dfdSAndroid Build Coastguard Worker   }
162*387f9dfdSAndroid Build Coastguard Worker 
163*387f9dfdSAndroid Build Coastguard Worker   auto it = symnames_.find(name);
164*387f9dfdSAndroid Build Coastguard Worker   if (it == symnames_.end())
165*387f9dfdSAndroid Build Coastguard Worker     return false;
166*387f9dfdSAndroid Build Coastguard Worker 
167*387f9dfdSAndroid Build Coastguard Worker   *addr = it->second;
168*387f9dfdSAndroid Build Coastguard Worker   return true;
169*387f9dfdSAndroid Build Coastguard Worker }
170*387f9dfdSAndroid Build Coastguard Worker 
ProcSyms(int pid,struct bcc_symbol_option * option)171*387f9dfdSAndroid Build Coastguard Worker ProcSyms::ProcSyms(int pid, struct bcc_symbol_option *option)
172*387f9dfdSAndroid Build Coastguard Worker     : pid_(pid), procstat_(pid) {
173*387f9dfdSAndroid Build Coastguard Worker   if (option)
174*387f9dfdSAndroid Build Coastguard Worker     std::memcpy(&symbol_option_, option, sizeof(bcc_symbol_option));
175*387f9dfdSAndroid Build Coastguard Worker   else
176*387f9dfdSAndroid Build Coastguard Worker     symbol_option_ = {
177*387f9dfdSAndroid Build Coastguard Worker       .use_debug_file = 1,
178*387f9dfdSAndroid Build Coastguard Worker       .check_debug_file_crc = 1,
179*387f9dfdSAndroid Build Coastguard Worker       .lazy_symbolize = 1,
180*387f9dfdSAndroid Build Coastguard Worker       .use_symbol_type = (1 << STT_FUNC) | (1 << STT_GNU_IFUNC)
181*387f9dfdSAndroid Build Coastguard Worker     };
182*387f9dfdSAndroid Build Coastguard Worker   load_modules();
183*387f9dfdSAndroid Build Coastguard Worker }
184*387f9dfdSAndroid Build Coastguard Worker 
load_modules()185*387f9dfdSAndroid Build Coastguard Worker void ProcSyms::load_modules() {
186*387f9dfdSAndroid Build Coastguard Worker   bcc_procutils_each_module(pid_, _add_module, this);
187*387f9dfdSAndroid Build Coastguard Worker }
188*387f9dfdSAndroid Build Coastguard Worker 
refresh()189*387f9dfdSAndroid Build Coastguard Worker void ProcSyms::refresh() {
190*387f9dfdSAndroid Build Coastguard Worker   modules_.clear();
191*387f9dfdSAndroid Build Coastguard Worker   load_modules();
192*387f9dfdSAndroid Build Coastguard Worker   procstat_.reset();
193*387f9dfdSAndroid Build Coastguard Worker }
194*387f9dfdSAndroid Build Coastguard Worker 
_add_module(mod_info * mod,int enter_ns,void * payload)195*387f9dfdSAndroid Build Coastguard Worker int ProcSyms::_add_module(mod_info *mod, int enter_ns, void *payload) {
196*387f9dfdSAndroid Build Coastguard Worker   ProcSyms *ps = static_cast<ProcSyms *>(payload);
197*387f9dfdSAndroid Build Coastguard Worker   std::shared_ptr<ModulePath> modpath =
198*387f9dfdSAndroid Build Coastguard Worker       std::make_shared<ModulePath>(mod->name, ps->procstat_.get_root_fd(),
199*387f9dfdSAndroid Build Coastguard Worker                                    ps->pid_, enter_ns && ps->pid_ != -1);
200*387f9dfdSAndroid Build Coastguard Worker   auto it = std::find_if(
201*387f9dfdSAndroid Build Coastguard Worker       ps->modules_.begin(), ps->modules_.end(),
202*387f9dfdSAndroid Build Coastguard Worker       [=](const ProcSyms::Module &m) { return m.name_ == mod->name; });
203*387f9dfdSAndroid Build Coastguard Worker   if (it == ps->modules_.end()) {
204*387f9dfdSAndroid Build Coastguard Worker     auto module = Module(
205*387f9dfdSAndroid Build Coastguard Worker         mod->name, modpath, &ps->symbol_option_);
206*387f9dfdSAndroid Build Coastguard Worker 
207*387f9dfdSAndroid Build Coastguard Worker     // pid/maps doesn't account for file_offset of text within the ELF.
208*387f9dfdSAndroid Build Coastguard Worker     // It only gives the mmap offset. We need the real offset for symbol
209*387f9dfdSAndroid Build Coastguard Worker     // lookup.
210*387f9dfdSAndroid Build Coastguard Worker     if (module.type_ == ModuleType::SO) {
211*387f9dfdSAndroid Build Coastguard Worker       if (bcc_elf_get_text_scn_info(modpath->path(), &module.elf_so_addr_,
212*387f9dfdSAndroid Build Coastguard Worker                                     &module.elf_so_offset_) < 0) {
213*387f9dfdSAndroid Build Coastguard Worker         fprintf(stderr, "WARNING: Couldn't find .text section in %s\n",
214*387f9dfdSAndroid Build Coastguard Worker                 modpath->alt_path());
215*387f9dfdSAndroid Build Coastguard Worker         fprintf(stderr, "WARNING: BCC can't handle sym look ups for %s",
216*387f9dfdSAndroid Build Coastguard Worker                 modpath->alt_path());
217*387f9dfdSAndroid Build Coastguard Worker       }
218*387f9dfdSAndroid Build Coastguard Worker     }
219*387f9dfdSAndroid Build Coastguard Worker 
220*387f9dfdSAndroid Build Coastguard Worker     if (!bcc_is_perf_map(modpath->path()) ||
221*387f9dfdSAndroid Build Coastguard Worker         module.type_ != ModuleType::UNKNOWN)
222*387f9dfdSAndroid Build Coastguard Worker       // Always add the module even if we can't read it, so that we could
223*387f9dfdSAndroid Build Coastguard Worker       // report correct module name. Unless it's a perf map that we only
224*387f9dfdSAndroid Build Coastguard Worker       // add readable ones.
225*387f9dfdSAndroid Build Coastguard Worker       it = ps->modules_.insert(ps->modules_.end(), std::move(module));
226*387f9dfdSAndroid Build Coastguard Worker     else
227*387f9dfdSAndroid Build Coastguard Worker       return 0;
228*387f9dfdSAndroid Build Coastguard Worker   }
229*387f9dfdSAndroid Build Coastguard Worker   it->ranges_.emplace_back(mod->start_addr, mod->end_addr, mod->file_offset);
230*387f9dfdSAndroid Build Coastguard Worker   // perf-PID map is added last. We try both inside the Process's mount
231*387f9dfdSAndroid Build Coastguard Worker   // namespace + chroot, and in global /tmp. Make sure we only add one.
232*387f9dfdSAndroid Build Coastguard Worker   if (it->type_ == ModuleType::PERF_MAP)
233*387f9dfdSAndroid Build Coastguard Worker     return -1;
234*387f9dfdSAndroid Build Coastguard Worker 
235*387f9dfdSAndroid Build Coastguard Worker   return 0;
236*387f9dfdSAndroid Build Coastguard Worker }
237*387f9dfdSAndroid Build Coastguard Worker 
resolve_addr(uint64_t addr,struct bcc_symbol * sym,bool demangle)238*387f9dfdSAndroid Build Coastguard Worker bool ProcSyms::resolve_addr(uint64_t addr, struct bcc_symbol *sym,
239*387f9dfdSAndroid Build Coastguard Worker                             bool demangle) {
240*387f9dfdSAndroid Build Coastguard Worker   if (procstat_.is_stale())
241*387f9dfdSAndroid Build Coastguard Worker     refresh();
242*387f9dfdSAndroid Build Coastguard Worker 
243*387f9dfdSAndroid Build Coastguard Worker   memset(sym, 0, sizeof(struct bcc_symbol));
244*387f9dfdSAndroid Build Coastguard Worker 
245*387f9dfdSAndroid Build Coastguard Worker   const char *original_module = nullptr;
246*387f9dfdSAndroid Build Coastguard Worker   uint64_t offset;
247*387f9dfdSAndroid Build Coastguard Worker   bool only_perf_map = false;
248*387f9dfdSAndroid Build Coastguard Worker   for (Module &mod : modules_) {
249*387f9dfdSAndroid Build Coastguard Worker     if (only_perf_map && (mod.type_ != ModuleType::PERF_MAP))
250*387f9dfdSAndroid Build Coastguard Worker       continue;
251*387f9dfdSAndroid Build Coastguard Worker     if (mod.contains(addr, offset)) {
252*387f9dfdSAndroid Build Coastguard Worker       if (mod.find_addr(offset, sym)) {
253*387f9dfdSAndroid Build Coastguard Worker         if (demangle) {
254*387f9dfdSAndroid Build Coastguard Worker           if (sym->name && (!strncmp(sym->name, "_Z", 2) || !strncmp(sym->name, "___Z", 4)))
255*387f9dfdSAndroid Build Coastguard Worker             sym->demangle_name =
256*387f9dfdSAndroid Build Coastguard Worker                 abi::__cxa_demangle(sym->name, nullptr, nullptr, nullptr);
257*387f9dfdSAndroid Build Coastguard Worker           if (!sym->demangle_name)
258*387f9dfdSAndroid Build Coastguard Worker             sym->demangle_name = sym->name;
259*387f9dfdSAndroid Build Coastguard Worker         }
260*387f9dfdSAndroid Build Coastguard Worker         return true;
261*387f9dfdSAndroid Build Coastguard Worker       } else if (mod.type_ != ModuleType::PERF_MAP) {
262*387f9dfdSAndroid Build Coastguard Worker         // In this case, we found the address in the range of a module, but
263*387f9dfdSAndroid Build Coastguard Worker         // not able to find a symbol of that address in the module.
264*387f9dfdSAndroid Build Coastguard Worker         // Thus, we would try to find the address in perf map, and
265*387f9dfdSAndroid Build Coastguard Worker         // save the module's name in case we will need it later.
266*387f9dfdSAndroid Build Coastguard Worker         original_module = mod.name_.c_str();
267*387f9dfdSAndroid Build Coastguard Worker         only_perf_map = true;
268*387f9dfdSAndroid Build Coastguard Worker       }
269*387f9dfdSAndroid Build Coastguard Worker     }
270*387f9dfdSAndroid Build Coastguard Worker   }
271*387f9dfdSAndroid Build Coastguard Worker   // If we didn't find the symbol anywhere, the module name is probably
272*387f9dfdSAndroid Build Coastguard Worker   // set to be the perf map's name as it would be the last we tried.
273*387f9dfdSAndroid Build Coastguard Worker   // In this case, if we have found the address previously in a module,
274*387f9dfdSAndroid Build Coastguard Worker   // report the saved original module name instead.
275*387f9dfdSAndroid Build Coastguard Worker   if (original_module)
276*387f9dfdSAndroid Build Coastguard Worker     sym->module = original_module;
277*387f9dfdSAndroid Build Coastguard Worker   return false;
278*387f9dfdSAndroid Build Coastguard Worker }
279*387f9dfdSAndroid Build Coastguard Worker 
resolve_name(const char * module,const char * name,uint64_t * addr)280*387f9dfdSAndroid Build Coastguard Worker bool ProcSyms::resolve_name(const char *module, const char *name,
281*387f9dfdSAndroid Build Coastguard Worker                             uint64_t *addr) {
282*387f9dfdSAndroid Build Coastguard Worker   if (procstat_.is_stale())
283*387f9dfdSAndroid Build Coastguard Worker     refresh();
284*387f9dfdSAndroid Build Coastguard Worker 
285*387f9dfdSAndroid Build Coastguard Worker   for (Module &mod : modules_) {
286*387f9dfdSAndroid Build Coastguard Worker     if (mod.name_ == module)
287*387f9dfdSAndroid Build Coastguard Worker       return mod.find_name(name, addr);
288*387f9dfdSAndroid Build Coastguard Worker   }
289*387f9dfdSAndroid Build Coastguard Worker   return false;
290*387f9dfdSAndroid Build Coastguard Worker }
291*387f9dfdSAndroid Build Coastguard Worker 
Module(const char * name,std::shared_ptr<ModulePath> path,struct bcc_symbol_option * option)292*387f9dfdSAndroid Build Coastguard Worker ProcSyms::Module::Module(const char *name, std::shared_ptr<ModulePath> path,
293*387f9dfdSAndroid Build Coastguard Worker                          struct bcc_symbol_option *option)
294*387f9dfdSAndroid Build Coastguard Worker     : name_(name),
295*387f9dfdSAndroid Build Coastguard Worker       path_(path),
296*387f9dfdSAndroid Build Coastguard Worker       loaded_(false),
297*387f9dfdSAndroid Build Coastguard Worker       symbol_option_(option),
298*387f9dfdSAndroid Build Coastguard Worker       type_(ModuleType::UNKNOWN) {
299*387f9dfdSAndroid Build Coastguard Worker   int elf_type = bcc_elf_get_type(path_->path());
300*387f9dfdSAndroid Build Coastguard Worker   // The Module is an ELF file
301*387f9dfdSAndroid Build Coastguard Worker   if (elf_type >= 0) {
302*387f9dfdSAndroid Build Coastguard Worker     if (elf_type == ET_EXEC)
303*387f9dfdSAndroid Build Coastguard Worker       type_ = ModuleType::EXEC;
304*387f9dfdSAndroid Build Coastguard Worker     else if (elf_type == ET_DYN)
305*387f9dfdSAndroid Build Coastguard Worker       type_ = ModuleType::SO;
306*387f9dfdSAndroid Build Coastguard Worker     return;
307*387f9dfdSAndroid Build Coastguard Worker   }
308*387f9dfdSAndroid Build Coastguard Worker   // Other symbol files
309*387f9dfdSAndroid Build Coastguard Worker   if (bcc_is_valid_perf_map(path_->path()) == 1)
310*387f9dfdSAndroid Build Coastguard Worker     type_ = ModuleType::PERF_MAP;
311*387f9dfdSAndroid Build Coastguard Worker   else if (bcc_elf_is_vdso(path_->path()) == 1)
312*387f9dfdSAndroid Build Coastguard Worker     type_ = ModuleType::VDSO;
313*387f9dfdSAndroid Build Coastguard Worker 
314*387f9dfdSAndroid Build Coastguard Worker   // Will be stored later
315*387f9dfdSAndroid Build Coastguard Worker   elf_so_offset_ = 0;
316*387f9dfdSAndroid Build Coastguard Worker   elf_so_addr_ = 0;
317*387f9dfdSAndroid Build Coastguard Worker }
318*387f9dfdSAndroid Build Coastguard Worker 
_add_symbol(const char * symname,uint64_t start,uint64_t size,void * p)319*387f9dfdSAndroid Build Coastguard Worker int ProcSyms::Module::_add_symbol(const char *symname, uint64_t start,
320*387f9dfdSAndroid Build Coastguard Worker                                   uint64_t size, void *p) {
321*387f9dfdSAndroid Build Coastguard Worker   Module *m = static_cast<Module *>(p);
322*387f9dfdSAndroid Build Coastguard Worker   auto res = m->symnames_.emplace(symname);
323*387f9dfdSAndroid Build Coastguard Worker   m->syms_.emplace_back(&*(res.first), start, size);
324*387f9dfdSAndroid Build Coastguard Worker   return 0;
325*387f9dfdSAndroid Build Coastguard Worker }
326*387f9dfdSAndroid Build Coastguard Worker 
_add_symbol_lazy(size_t section_idx,size_t str_table_idx,size_t str_len,uint64_t start,uint64_t size,int debugfile,void * p)327*387f9dfdSAndroid Build Coastguard Worker int ProcSyms::Module::_add_symbol_lazy(size_t section_idx, size_t str_table_idx,
328*387f9dfdSAndroid Build Coastguard Worker                                        size_t str_len, uint64_t start,
329*387f9dfdSAndroid Build Coastguard Worker                                        uint64_t size, int debugfile, void *p) {
330*387f9dfdSAndroid Build Coastguard Worker   Module *m = static_cast<Module *>(p);
331*387f9dfdSAndroid Build Coastguard Worker   m->syms_.emplace_back(
332*387f9dfdSAndroid Build Coastguard Worker       section_idx, str_table_idx, str_len, start, size, debugfile);
333*387f9dfdSAndroid Build Coastguard Worker   return 0;
334*387f9dfdSAndroid Build Coastguard Worker }
335*387f9dfdSAndroid Build Coastguard Worker 
load_sym_table()336*387f9dfdSAndroid Build Coastguard Worker void ProcSyms::Module::load_sym_table() {
337*387f9dfdSAndroid Build Coastguard Worker   if (loaded_)
338*387f9dfdSAndroid Build Coastguard Worker     return;
339*387f9dfdSAndroid Build Coastguard Worker   loaded_ = true;
340*387f9dfdSAndroid Build Coastguard Worker 
341*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::UNKNOWN)
342*387f9dfdSAndroid Build Coastguard Worker     return;
343*387f9dfdSAndroid Build Coastguard Worker 
344*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::PERF_MAP)
345*387f9dfdSAndroid Build Coastguard Worker     bcc_perf_map_foreach_sym(path_->path(), _add_symbol, this);
346*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::EXEC || type_ == ModuleType::SO) {
347*387f9dfdSAndroid Build Coastguard Worker     if (symbol_option_->lazy_symbolize)
348*387f9dfdSAndroid Build Coastguard Worker       bcc_elf_foreach_sym_lazy(path_->path(), _add_symbol_lazy, symbol_option_,
349*387f9dfdSAndroid Build Coastguard Worker                                this);
350*387f9dfdSAndroid Build Coastguard Worker     else
351*387f9dfdSAndroid Build Coastguard Worker       bcc_elf_foreach_sym(path_->path(), _add_symbol, symbol_option_, this);
352*387f9dfdSAndroid Build Coastguard Worker   }
353*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::VDSO)
354*387f9dfdSAndroid Build Coastguard Worker     bcc_elf_foreach_vdso_sym(_add_symbol, this);
355*387f9dfdSAndroid Build Coastguard Worker 
356*387f9dfdSAndroid Build Coastguard Worker   std::sort(syms_.begin(), syms_.end());
357*387f9dfdSAndroid Build Coastguard Worker }
358*387f9dfdSAndroid Build Coastguard Worker 
contains(uint64_t addr,uint64_t & offset) const359*387f9dfdSAndroid Build Coastguard Worker bool ProcSyms::Module::contains(uint64_t addr, uint64_t &offset) const {
360*387f9dfdSAndroid Build Coastguard Worker   for (const auto &range : ranges_) {
361*387f9dfdSAndroid Build Coastguard Worker     if (addr >= range.start && addr < range.end) {
362*387f9dfdSAndroid Build Coastguard Worker       if (type_ == ModuleType::SO || type_ == ModuleType::VDSO) {
363*387f9dfdSAndroid Build Coastguard Worker         offset = __so_calc_mod_offset(range.start, range.file_offset,
364*387f9dfdSAndroid Build Coastguard Worker                                       elf_so_addr_, elf_so_offset_, addr);
365*387f9dfdSAndroid Build Coastguard Worker       } else {
366*387f9dfdSAndroid Build Coastguard Worker         offset = addr;
367*387f9dfdSAndroid Build Coastguard Worker       }
368*387f9dfdSAndroid Build Coastguard Worker 
369*387f9dfdSAndroid Build Coastguard Worker       return true;
370*387f9dfdSAndroid Build Coastguard Worker     }
371*387f9dfdSAndroid Build Coastguard Worker   }
372*387f9dfdSAndroid Build Coastguard Worker 
373*387f9dfdSAndroid Build Coastguard Worker   return false;
374*387f9dfdSAndroid Build Coastguard Worker }
375*387f9dfdSAndroid Build Coastguard Worker 
find_name(const char * symname,uint64_t * addr)376*387f9dfdSAndroid Build Coastguard Worker bool ProcSyms::Module::find_name(const char *symname, uint64_t *addr) {
377*387f9dfdSAndroid Build Coastguard Worker   struct Payload {
378*387f9dfdSAndroid Build Coastguard Worker     const char *symname;
379*387f9dfdSAndroid Build Coastguard Worker     uint64_t *out;
380*387f9dfdSAndroid Build Coastguard Worker     bool found;
381*387f9dfdSAndroid Build Coastguard Worker   };
382*387f9dfdSAndroid Build Coastguard Worker 
383*387f9dfdSAndroid Build Coastguard Worker   Payload payload;
384*387f9dfdSAndroid Build Coastguard Worker   payload.symname = symname;
385*387f9dfdSAndroid Build Coastguard Worker   payload.out = addr;
386*387f9dfdSAndroid Build Coastguard Worker   payload.found = false;
387*387f9dfdSAndroid Build Coastguard Worker 
388*387f9dfdSAndroid Build Coastguard Worker   auto cb = [](const char *name, uint64_t start, uint64_t size, void *p) {
389*387f9dfdSAndroid Build Coastguard Worker     Payload *payload = static_cast<Payload*>(p);
390*387f9dfdSAndroid Build Coastguard Worker 
391*387f9dfdSAndroid Build Coastguard Worker     if (!strcmp(payload->symname, name)) {
392*387f9dfdSAndroid Build Coastguard Worker       payload->found = true;
393*387f9dfdSAndroid Build Coastguard Worker       *(payload->out) = start;
394*387f9dfdSAndroid Build Coastguard Worker       return -1;  // Stop iteration
395*387f9dfdSAndroid Build Coastguard Worker     }
396*387f9dfdSAndroid Build Coastguard Worker 
397*387f9dfdSAndroid Build Coastguard Worker     return 0;
398*387f9dfdSAndroid Build Coastguard Worker   };
399*387f9dfdSAndroid Build Coastguard Worker 
400*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::PERF_MAP)
401*387f9dfdSAndroid Build Coastguard Worker     bcc_perf_map_foreach_sym(path_->path(), cb, &payload);
402*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::EXEC || type_ == ModuleType::SO) {
403*387f9dfdSAndroid Build Coastguard Worker     bcc_elf_foreach_sym(path_->path(), cb, symbol_option_, &payload);
404*387f9dfdSAndroid Build Coastguard Worker     if (path_->path() != path_->alt_path())
405*387f9dfdSAndroid Build Coastguard Worker       // some features (e.g. some kinds of debug info) don't work with /proc/self/fd/... path
406*387f9dfdSAndroid Build Coastguard Worker       bcc_elf_foreach_sym(path_->alt_path(), cb, symbol_option_, &payload);
407*387f9dfdSAndroid Build Coastguard Worker   }
408*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::VDSO)
409*387f9dfdSAndroid Build Coastguard Worker     bcc_elf_foreach_vdso_sym(cb, &payload);
410*387f9dfdSAndroid Build Coastguard Worker 
411*387f9dfdSAndroid Build Coastguard Worker   if (!payload.found)
412*387f9dfdSAndroid Build Coastguard Worker     return false;
413*387f9dfdSAndroid Build Coastguard Worker 
414*387f9dfdSAndroid Build Coastguard Worker   if (type_ == ModuleType::SO)
415*387f9dfdSAndroid Build Coastguard Worker     *(payload.out) += start();
416*387f9dfdSAndroid Build Coastguard Worker 
417*387f9dfdSAndroid Build Coastguard Worker   return true;
418*387f9dfdSAndroid Build Coastguard Worker }
419*387f9dfdSAndroid Build Coastguard Worker 
find_addr(uint64_t offset,struct bcc_symbol * sym)420*387f9dfdSAndroid Build Coastguard Worker bool ProcSyms::Module::find_addr(uint64_t offset, struct bcc_symbol *sym) {
421*387f9dfdSAndroid Build Coastguard Worker   load_sym_table();
422*387f9dfdSAndroid Build Coastguard Worker 
423*387f9dfdSAndroid Build Coastguard Worker   sym->module = name_.c_str();
424*387f9dfdSAndroid Build Coastguard Worker   sym->offset = offset;
425*387f9dfdSAndroid Build Coastguard Worker 
426*387f9dfdSAndroid Build Coastguard Worker   auto it = std::upper_bound(syms_.begin(), syms_.end(), Symbol(nullptr, offset, 0));
427*387f9dfdSAndroid Build Coastguard Worker   if (it == syms_.begin())
428*387f9dfdSAndroid Build Coastguard Worker     return false;
429*387f9dfdSAndroid Build Coastguard Worker 
430*387f9dfdSAndroid Build Coastguard Worker   // 'it' points to the symbol whose start address is strictly greater than
431*387f9dfdSAndroid Build Coastguard Worker   // the address we're looking for. Start stepping backwards as long as the
432*387f9dfdSAndroid Build Coastguard Worker   // current symbol is still below the desired address, and see if the end
433*387f9dfdSAndroid Build Coastguard Worker   // of the current symbol (start + size) is above the desired address. Once
434*387f9dfdSAndroid Build Coastguard Worker   // we have a matching symbol, return it. Note that simply looking at '--it'
435*387f9dfdSAndroid Build Coastguard Worker   // is not enough, because symbols can be nested. For example, we could be
436*387f9dfdSAndroid Build Coastguard Worker   // looking for offset 0x12 with the following symbols available:
437*387f9dfdSAndroid Build Coastguard Worker   // SYMBOL   START   SIZE    END
438*387f9dfdSAndroid Build Coastguard Worker   // goo      0x0     0x6     0x0 + 0x6 = 0x6
439*387f9dfdSAndroid Build Coastguard Worker   // foo      0x6     0x10    0x6 + 0x10 = 0x16
440*387f9dfdSAndroid Build Coastguard Worker   // bar      0x8     0x4     0x8 + 0x4 = 0xc
441*387f9dfdSAndroid Build Coastguard Worker   // baz      0x16    0x10    0x16 + 0x10 = 0x26
442*387f9dfdSAndroid Build Coastguard Worker   // The upper_bound lookup will return baz, and then going one symbol back
443*387f9dfdSAndroid Build Coastguard Worker   // brings us to bar, which does not contain offset 0x12 and is nested inside
444*387f9dfdSAndroid Build Coastguard Worker   // foo. Going back one more symbol brings us to foo, which contains 0x12
445*387f9dfdSAndroid Build Coastguard Worker   // and is a match.
446*387f9dfdSAndroid Build Coastguard Worker   // However, we also don't want to walk through the entire symbol list for
447*387f9dfdSAndroid Build Coastguard Worker   // unknown / missing symbols. So we will break if we reach a function that
448*387f9dfdSAndroid Build Coastguard Worker   // doesn't cover the function immediately before 'it', which means it is
449*387f9dfdSAndroid Build Coastguard Worker   // not possibly a nested function containing the address we're looking for.
450*387f9dfdSAndroid Build Coastguard Worker   --it;
451*387f9dfdSAndroid Build Coastguard Worker   uint64_t limit = it->start;
452*387f9dfdSAndroid Build Coastguard Worker   for (; offset >= it->start; --it) {
453*387f9dfdSAndroid Build Coastguard Worker     if (offset < it->start + it->size) {
454*387f9dfdSAndroid Build Coastguard Worker       // Resolve and cache the symbol name if necessary
455*387f9dfdSAndroid Build Coastguard Worker       if (!it->is_name_resolved) {
456*387f9dfdSAndroid Build Coastguard Worker         std::string sym_name(it->data.name_idx.str_len + 1, '\0');
457*387f9dfdSAndroid Build Coastguard Worker         if (bcc_elf_symbol_str(path_->path(), it->data.name_idx.section_idx,
458*387f9dfdSAndroid Build Coastguard Worker                                it->data.name_idx.str_table_idx, &sym_name[0],
459*387f9dfdSAndroid Build Coastguard Worker                                sym_name.size(), it->data.name_idx.debugfile))
460*387f9dfdSAndroid Build Coastguard Worker           break;
461*387f9dfdSAndroid Build Coastguard Worker 
462*387f9dfdSAndroid Build Coastguard Worker         it->data.name = &*(symnames_.emplace(std::move(sym_name)).first);
463*387f9dfdSAndroid Build Coastguard Worker         it->is_name_resolved = true;
464*387f9dfdSAndroid Build Coastguard Worker       }
465*387f9dfdSAndroid Build Coastguard Worker 
466*387f9dfdSAndroid Build Coastguard Worker       sym->name = it->data.name->c_str();
467*387f9dfdSAndroid Build Coastguard Worker       sym->offset = (offset - it->start);
468*387f9dfdSAndroid Build Coastguard Worker       return true;
469*387f9dfdSAndroid Build Coastguard Worker     }
470*387f9dfdSAndroid Build Coastguard Worker     if (limit > it->start + it->size)
471*387f9dfdSAndroid Build Coastguard Worker       break;
472*387f9dfdSAndroid Build Coastguard Worker     // But don't step beyond begin()!
473*387f9dfdSAndroid Build Coastguard Worker     if (it == syms_.begin())
474*387f9dfdSAndroid Build Coastguard Worker       break;
475*387f9dfdSAndroid Build Coastguard Worker   }
476*387f9dfdSAndroid Build Coastguard Worker 
477*387f9dfdSAndroid Build Coastguard Worker   return false;
478*387f9dfdSAndroid Build Coastguard Worker }
479*387f9dfdSAndroid Build Coastguard Worker 
load_sym_table()480*387f9dfdSAndroid Build Coastguard Worker bool BuildSyms::Module::load_sym_table()
481*387f9dfdSAndroid Build Coastguard Worker {
482*387f9dfdSAndroid Build Coastguard Worker   if (loaded_)
483*387f9dfdSAndroid Build Coastguard Worker     return true;
484*387f9dfdSAndroid Build Coastguard Worker 
485*387f9dfdSAndroid Build Coastguard Worker   symbol_option_ = {
486*387f9dfdSAndroid Build Coastguard Worker     .use_debug_file = 1,
487*387f9dfdSAndroid Build Coastguard Worker     .check_debug_file_crc = 1,
488*387f9dfdSAndroid Build Coastguard Worker     .lazy_symbolize = 1,
489*387f9dfdSAndroid Build Coastguard Worker     .use_symbol_type = (1 << STT_FUNC) | (1 << STT_GNU_IFUNC)
490*387f9dfdSAndroid Build Coastguard Worker   };
491*387f9dfdSAndroid Build Coastguard Worker 
492*387f9dfdSAndroid Build Coastguard Worker   bcc_elf_foreach_sym(module_name_.c_str(), _add_symbol, &symbol_option_, this);
493*387f9dfdSAndroid Build Coastguard Worker   std::sort(syms_.begin(), syms_.end());
494*387f9dfdSAndroid Build Coastguard Worker 
495*387f9dfdSAndroid Build Coastguard Worker   for(std::vector<Symbol>::iterator it = syms_.begin();
496*387f9dfdSAndroid Build Coastguard Worker       it != syms_.end(); ++it++) {
497*387f9dfdSAndroid Build Coastguard Worker   }
498*387f9dfdSAndroid Build Coastguard Worker   loaded_ = true;
499*387f9dfdSAndroid Build Coastguard Worker   return true;
500*387f9dfdSAndroid Build Coastguard Worker }
501*387f9dfdSAndroid Build Coastguard Worker 
_add_symbol(const char * symname,uint64_t start,uint64_t size,void * p)502*387f9dfdSAndroid Build Coastguard Worker int BuildSyms::Module::_add_symbol(const char *symname, uint64_t start,
503*387f9dfdSAndroid Build Coastguard Worker                                    uint64_t size, void *p)
504*387f9dfdSAndroid Build Coastguard Worker {
505*387f9dfdSAndroid Build Coastguard Worker   BuildSyms::Module *m = static_cast<BuildSyms::Module *> (p);
506*387f9dfdSAndroid Build Coastguard Worker   auto res = m->symnames_.emplace(symname);
507*387f9dfdSAndroid Build Coastguard Worker   m->syms_.emplace_back(&*(res.first), start, size);
508*387f9dfdSAndroid Build Coastguard Worker   return 0;
509*387f9dfdSAndroid Build Coastguard Worker }
510*387f9dfdSAndroid Build Coastguard Worker 
resolve_addr(uint64_t offset,struct bcc_symbol * sym,bool demangle)511*387f9dfdSAndroid Build Coastguard Worker bool BuildSyms::Module::resolve_addr(uint64_t offset, struct bcc_symbol* sym,
512*387f9dfdSAndroid Build Coastguard Worker                                      bool demangle)
513*387f9dfdSAndroid Build Coastguard Worker {
514*387f9dfdSAndroid Build Coastguard Worker   std::vector<Symbol>::iterator it;
515*387f9dfdSAndroid Build Coastguard Worker 
516*387f9dfdSAndroid Build Coastguard Worker   load_sym_table();
517*387f9dfdSAndroid Build Coastguard Worker 
518*387f9dfdSAndroid Build Coastguard Worker   if (syms_.empty())
519*387f9dfdSAndroid Build Coastguard Worker     goto unknown_symbol;
520*387f9dfdSAndroid Build Coastguard Worker 
521*387f9dfdSAndroid Build Coastguard Worker   it = std::upper_bound(syms_.begin(), syms_.end(), Symbol(nullptr, offset, 0));
522*387f9dfdSAndroid Build Coastguard Worker   if (it != syms_.begin()) {
523*387f9dfdSAndroid Build Coastguard Worker     it--;
524*387f9dfdSAndroid Build Coastguard Worker     sym->name = (*it).name->c_str();
525*387f9dfdSAndroid Build Coastguard Worker     if (demangle)
526*387f9dfdSAndroid Build Coastguard Worker       sym->demangle_name = sym->name;
527*387f9dfdSAndroid Build Coastguard Worker     sym->offset = offset - (*it).start;
528*387f9dfdSAndroid Build Coastguard Worker     sym->module = module_name_.c_str();
529*387f9dfdSAndroid Build Coastguard Worker     return true;
530*387f9dfdSAndroid Build Coastguard Worker   }
531*387f9dfdSAndroid Build Coastguard Worker 
532*387f9dfdSAndroid Build Coastguard Worker unknown_symbol:
533*387f9dfdSAndroid Build Coastguard Worker   memset(sym, 0, sizeof(struct bcc_symbol));
534*387f9dfdSAndroid Build Coastguard Worker   return false;
535*387f9dfdSAndroid Build Coastguard Worker }
536*387f9dfdSAndroid Build Coastguard Worker 
add_module(const std::string module_name)537*387f9dfdSAndroid Build Coastguard Worker bool BuildSyms::add_module(const std::string module_name)
538*387f9dfdSAndroid Build Coastguard Worker {
539*387f9dfdSAndroid Build Coastguard Worker   struct stat s;
540*387f9dfdSAndroid Build Coastguard Worker   char buildid[BPF_BUILD_ID_SIZE*2+1];
541*387f9dfdSAndroid Build Coastguard Worker 
542*387f9dfdSAndroid Build Coastguard Worker   if (stat(module_name.c_str(), &s) < 0)
543*387f9dfdSAndroid Build Coastguard Worker      return false;
544*387f9dfdSAndroid Build Coastguard Worker 
545*387f9dfdSAndroid Build Coastguard Worker   if (bcc_elf_get_buildid(module_name.c_str(), buildid) < 0)
546*387f9dfdSAndroid Build Coastguard Worker       return false;
547*387f9dfdSAndroid Build Coastguard Worker 
548*387f9dfdSAndroid Build Coastguard Worker   std::string elf_buildid(buildid);
549*387f9dfdSAndroid Build Coastguard Worker   std::unique_ptr<BuildSyms::Module> ptr(new BuildSyms::Module(module_name.c_str()));
550*387f9dfdSAndroid Build Coastguard Worker   buildmap_[elf_buildid] = std::move(ptr);
551*387f9dfdSAndroid Build Coastguard Worker   return true;
552*387f9dfdSAndroid Build Coastguard Worker }
553*387f9dfdSAndroid Build Coastguard Worker 
resolve_addr(std::string build_id,uint64_t offset,struct bcc_symbol * sym,bool demangle)554*387f9dfdSAndroid Build Coastguard Worker bool BuildSyms::resolve_addr(std::string build_id, uint64_t offset,
555*387f9dfdSAndroid Build Coastguard Worker                              struct bcc_symbol *sym, bool demangle)
556*387f9dfdSAndroid Build Coastguard Worker {
557*387f9dfdSAndroid Build Coastguard Worker   std::unordered_map<std::string,std::unique_ptr<BuildSyms::Module> >::iterator it;
558*387f9dfdSAndroid Build Coastguard Worker 
559*387f9dfdSAndroid Build Coastguard Worker   it = buildmap_.find(build_id);
560*387f9dfdSAndroid Build Coastguard Worker   if (it == buildmap_.end())
561*387f9dfdSAndroid Build Coastguard Worker     /*build-id not added to the BuildSym*/
562*387f9dfdSAndroid Build Coastguard Worker     return false;
563*387f9dfdSAndroid Build Coastguard Worker 
564*387f9dfdSAndroid Build Coastguard Worker   BuildSyms::Module *mod = it->second.get();
565*387f9dfdSAndroid Build Coastguard Worker   return mod->resolve_addr(offset, sym, demangle);
566*387f9dfdSAndroid Build Coastguard Worker }
567*387f9dfdSAndroid Build Coastguard Worker 
568*387f9dfdSAndroid Build Coastguard Worker extern "C" {
569*387f9dfdSAndroid Build Coastguard Worker 
bcc_symcache_new(int pid,struct bcc_symbol_option * option)570*387f9dfdSAndroid Build Coastguard Worker void *bcc_symcache_new(int pid, struct bcc_symbol_option *option) {
571*387f9dfdSAndroid Build Coastguard Worker   if (pid < 0)
572*387f9dfdSAndroid Build Coastguard Worker     return static_cast<void *>(new KSyms());
573*387f9dfdSAndroid Build Coastguard Worker   return static_cast<void *>(new ProcSyms(pid, option));
574*387f9dfdSAndroid Build Coastguard Worker }
575*387f9dfdSAndroid Build Coastguard Worker 
bcc_free_symcache(void * symcache,int pid)576*387f9dfdSAndroid Build Coastguard Worker void bcc_free_symcache(void *symcache, int pid) {
577*387f9dfdSAndroid Build Coastguard Worker   if (pid < 0)
578*387f9dfdSAndroid Build Coastguard Worker     delete static_cast<KSyms*>(symcache);
579*387f9dfdSAndroid Build Coastguard Worker   else
580*387f9dfdSAndroid Build Coastguard Worker     delete static_cast<ProcSyms*>(symcache);
581*387f9dfdSAndroid Build Coastguard Worker }
582*387f9dfdSAndroid Build Coastguard Worker 
bcc_symbol_free_demangle_name(struct bcc_symbol * sym)583*387f9dfdSAndroid Build Coastguard Worker void bcc_symbol_free_demangle_name(struct bcc_symbol *sym) {
584*387f9dfdSAndroid Build Coastguard Worker   if (sym->demangle_name && (sym->demangle_name != sym->name))
585*387f9dfdSAndroid Build Coastguard Worker     free(const_cast<char*>(sym->demangle_name));
586*387f9dfdSAndroid Build Coastguard Worker }
587*387f9dfdSAndroid Build Coastguard Worker 
bcc_symcache_resolve(void * resolver,uint64_t addr,struct bcc_symbol * sym)588*387f9dfdSAndroid Build Coastguard Worker int bcc_symcache_resolve(void *resolver, uint64_t addr,
589*387f9dfdSAndroid Build Coastguard Worker                          struct bcc_symbol *sym) {
590*387f9dfdSAndroid Build Coastguard Worker   SymbolCache *cache = static_cast<SymbolCache *>(resolver);
591*387f9dfdSAndroid Build Coastguard Worker   return cache->resolve_addr(addr, sym) ? 0 : -1;
592*387f9dfdSAndroid Build Coastguard Worker }
593*387f9dfdSAndroid Build Coastguard Worker 
bcc_symcache_resolve_no_demangle(void * resolver,uint64_t addr,struct bcc_symbol * sym)594*387f9dfdSAndroid Build Coastguard Worker int bcc_symcache_resolve_no_demangle(void *resolver, uint64_t addr,
595*387f9dfdSAndroid Build Coastguard Worker                                      struct bcc_symbol *sym) {
596*387f9dfdSAndroid Build Coastguard Worker   SymbolCache *cache = static_cast<SymbolCache *>(resolver);
597*387f9dfdSAndroid Build Coastguard Worker   return cache->resolve_addr(addr, sym, false) ? 0 : -1;
598*387f9dfdSAndroid Build Coastguard Worker }
599*387f9dfdSAndroid Build Coastguard Worker 
bcc_symcache_resolve_name(void * resolver,const char * module,const char * name,uint64_t * addr)600*387f9dfdSAndroid Build Coastguard Worker int bcc_symcache_resolve_name(void *resolver, const char *module,
601*387f9dfdSAndroid Build Coastguard Worker                               const char *name, uint64_t *addr) {
602*387f9dfdSAndroid Build Coastguard Worker   SymbolCache *cache = static_cast<SymbolCache *>(resolver);
603*387f9dfdSAndroid Build Coastguard Worker   return cache->resolve_name(module, name, addr) ? 0 : -1;
604*387f9dfdSAndroid Build Coastguard Worker }
605*387f9dfdSAndroid Build Coastguard Worker 
bcc_symcache_refresh(void * resolver)606*387f9dfdSAndroid Build Coastguard Worker void bcc_symcache_refresh(void *resolver) {
607*387f9dfdSAndroid Build Coastguard Worker   SymbolCache *cache = static_cast<SymbolCache *>(resolver);
608*387f9dfdSAndroid Build Coastguard Worker   cache->refresh();
609*387f9dfdSAndroid Build Coastguard Worker }
610*387f9dfdSAndroid Build Coastguard Worker 
bcc_buildsymcache_new(void)611*387f9dfdSAndroid Build Coastguard Worker void *bcc_buildsymcache_new(void) {
612*387f9dfdSAndroid Build Coastguard Worker   return static_cast<void *>(new BuildSyms());
613*387f9dfdSAndroid Build Coastguard Worker }
614*387f9dfdSAndroid Build Coastguard Worker 
bcc_free_buildsymcache(void * symcache)615*387f9dfdSAndroid Build Coastguard Worker void bcc_free_buildsymcache(void *symcache) {
616*387f9dfdSAndroid Build Coastguard Worker   delete static_cast<BuildSyms*>(symcache);
617*387f9dfdSAndroid Build Coastguard Worker }
618*387f9dfdSAndroid Build Coastguard Worker 
bcc_buildsymcache_add_module(void * resolver,const char * module_name)619*387f9dfdSAndroid Build Coastguard Worker int  bcc_buildsymcache_add_module(void *resolver, const char *module_name)
620*387f9dfdSAndroid Build Coastguard Worker {
621*387f9dfdSAndroid Build Coastguard Worker   BuildSyms *bsym = static_cast<BuildSyms *>(resolver);
622*387f9dfdSAndroid Build Coastguard Worker   return  bsym->add_module(module_name) ? 0 : -1;
623*387f9dfdSAndroid Build Coastguard Worker }
624*387f9dfdSAndroid Build Coastguard Worker 
bcc_buildsymcache_resolve(void * resolver,struct bpf_stack_build_id * trace,struct bcc_symbol * sym)625*387f9dfdSAndroid Build Coastguard Worker int bcc_buildsymcache_resolve(void *resolver,
626*387f9dfdSAndroid Build Coastguard Worker                               struct bpf_stack_build_id *trace,
627*387f9dfdSAndroid Build Coastguard Worker                               struct bcc_symbol *sym)
628*387f9dfdSAndroid Build Coastguard Worker {
629*387f9dfdSAndroid Build Coastguard Worker   std::string build_id;
630*387f9dfdSAndroid Build Coastguard Worker   unsigned char *c = &trace->build_id[0];
631*387f9dfdSAndroid Build Coastguard Worker   int idx = 0;
632*387f9dfdSAndroid Build Coastguard Worker 
633*387f9dfdSAndroid Build Coastguard Worker   /*cannot resolve in case of fallback*/
634*387f9dfdSAndroid Build Coastguard Worker   if (trace->status == BPF_STACK_BUILD_ID_EMPTY ||
635*387f9dfdSAndroid Build Coastguard Worker       trace->status == BPF_STACK_BUILD_ID_IP)
636*387f9dfdSAndroid Build Coastguard Worker     return 0;
637*387f9dfdSAndroid Build Coastguard Worker 
638*387f9dfdSAndroid Build Coastguard Worker   while( idx < 20) {
639*387f9dfdSAndroid Build Coastguard Worker     int nib1 = (c[idx]&0xf0)>>4;
640*387f9dfdSAndroid Build Coastguard Worker     int nib2 = (c[idx]&0x0f);
641*387f9dfdSAndroid Build Coastguard Worker     build_id += "0123456789abcdef"[nib1];
642*387f9dfdSAndroid Build Coastguard Worker     build_id += "0123456789abcdef"[nib2];
643*387f9dfdSAndroid Build Coastguard Worker     idx++;
644*387f9dfdSAndroid Build Coastguard Worker   }
645*387f9dfdSAndroid Build Coastguard Worker 
646*387f9dfdSAndroid Build Coastguard Worker   BuildSyms *bsym = static_cast<BuildSyms *>(resolver);
647*387f9dfdSAndroid Build Coastguard Worker   return bsym->resolve_addr(build_id, trace->offset, sym) ? 0 : -1;
648*387f9dfdSAndroid Build Coastguard Worker }
649*387f9dfdSAndroid Build Coastguard Worker 
650*387f9dfdSAndroid Build Coastguard Worker struct mod_search {
651*387f9dfdSAndroid Build Coastguard Worker   const char *name;
652*387f9dfdSAndroid Build Coastguard Worker   uint64_t inode;
653*387f9dfdSAndroid Build Coastguard Worker   uint64_t dev_major;
654*387f9dfdSAndroid Build Coastguard Worker   uint64_t dev_minor;
655*387f9dfdSAndroid Build Coastguard Worker   uint64_t addr;
656*387f9dfdSAndroid Build Coastguard Worker   uint8_t inode_match_only;
657*387f9dfdSAndroid Build Coastguard Worker 
658*387f9dfdSAndroid Build Coastguard Worker   uint64_t start;
659*387f9dfdSAndroid Build Coastguard Worker   uint64_t file_offset;
660*387f9dfdSAndroid Build Coastguard Worker };
661*387f9dfdSAndroid Build Coastguard Worker 
_bcc_syms_find_module(mod_info * info,int enter_ns,void * p)662*387f9dfdSAndroid Build Coastguard Worker int _bcc_syms_find_module(mod_info *info, int enter_ns, void *p) {
663*387f9dfdSAndroid Build Coastguard Worker   struct mod_search *mod = (struct mod_search *)p;
664*387f9dfdSAndroid Build Coastguard Worker   // use inode + dev to determine match if inode set
665*387f9dfdSAndroid Build Coastguard Worker   if (mod->inode) {
666*387f9dfdSAndroid Build Coastguard Worker     if (mod->inode != info->inode)
667*387f9dfdSAndroid Build Coastguard Worker       return 0;
668*387f9dfdSAndroid Build Coastguard Worker 
669*387f9dfdSAndroid Build Coastguard Worker     // look at comment on USDT::set_probe_matching_kludge
670*387f9dfdSAndroid Build Coastguard Worker     // in api/BPF.h for explanation of why this might be
671*387f9dfdSAndroid Build Coastguard Worker     // necessary
672*387f9dfdSAndroid Build Coastguard Worker     if (mod->inode_match_only)
673*387f9dfdSAndroid Build Coastguard Worker       goto file_match;
674*387f9dfdSAndroid Build Coastguard Worker 
675*387f9dfdSAndroid Build Coastguard Worker     if(mod->dev_major == info->dev_major
676*387f9dfdSAndroid Build Coastguard Worker         && mod->dev_minor == info->dev_minor)
677*387f9dfdSAndroid Build Coastguard Worker       goto file_match;
678*387f9dfdSAndroid Build Coastguard Worker 
679*387f9dfdSAndroid Build Coastguard Worker     return 0;
680*387f9dfdSAndroid Build Coastguard Worker   }
681*387f9dfdSAndroid Build Coastguard Worker 
682*387f9dfdSAndroid Build Coastguard Worker   // fallback to name match
683*387f9dfdSAndroid Build Coastguard Worker   if (!strcmp(info->name, mod->name))
684*387f9dfdSAndroid Build Coastguard Worker     goto file_match;
685*387f9dfdSAndroid Build Coastguard Worker 
686*387f9dfdSAndroid Build Coastguard Worker   return 0;
687*387f9dfdSAndroid Build Coastguard Worker 
688*387f9dfdSAndroid Build Coastguard Worker file_match:
689*387f9dfdSAndroid Build Coastguard Worker   mod->start = info->start_addr;
690*387f9dfdSAndroid Build Coastguard Worker   mod->file_offset = info->file_offset;
691*387f9dfdSAndroid Build Coastguard Worker   return -1;
692*387f9dfdSAndroid Build Coastguard Worker }
693*387f9dfdSAndroid Build Coastguard Worker 
__so_calc_global_addr(uint64_t mod_start_addr,uint64_t mod_file_offset,uint64_t elf_sec_start_addr,uint64_t elf_sec_file_offset,uint64_t offset)694*387f9dfdSAndroid Build Coastguard Worker uint64_t __so_calc_global_addr(uint64_t mod_start_addr,
695*387f9dfdSAndroid Build Coastguard Worker                                uint64_t mod_file_offset,
696*387f9dfdSAndroid Build Coastguard Worker                                uint64_t elf_sec_start_addr,
697*387f9dfdSAndroid Build Coastguard Worker                                uint64_t elf_sec_file_offset, uint64_t offset) {
698*387f9dfdSAndroid Build Coastguard Worker   return offset + (mod_start_addr - mod_file_offset) -
699*387f9dfdSAndroid Build Coastguard Worker          (elf_sec_start_addr - elf_sec_file_offset);
700*387f9dfdSAndroid Build Coastguard Worker }
701*387f9dfdSAndroid Build Coastguard Worker 
__so_calc_mod_offset(uint64_t mod_start_addr,uint64_t mod_file_offset,uint64_t elf_sec_start_addr,uint64_t elf_sec_file_offset,uint64_t global_addr)702*387f9dfdSAndroid Build Coastguard Worker uint64_t __so_calc_mod_offset(uint64_t mod_start_addr, uint64_t mod_file_offset,
703*387f9dfdSAndroid Build Coastguard Worker                               uint64_t elf_sec_start_addr,
704*387f9dfdSAndroid Build Coastguard Worker                               uint64_t elf_sec_file_offset,
705*387f9dfdSAndroid Build Coastguard Worker                               uint64_t global_addr) {
706*387f9dfdSAndroid Build Coastguard Worker   return global_addr - (mod_start_addr - mod_file_offset) +
707*387f9dfdSAndroid Build Coastguard Worker          (elf_sec_start_addr - elf_sec_file_offset);
708*387f9dfdSAndroid Build Coastguard Worker }
709*387f9dfdSAndroid Build Coastguard Worker 
bcc_resolve_global_addr(int pid,const char * module,const uint64_t address,uint8_t inode_match_only,uint64_t * global)710*387f9dfdSAndroid Build Coastguard Worker int bcc_resolve_global_addr(int pid, const char *module, const uint64_t address,
711*387f9dfdSAndroid Build Coastguard Worker                             uint8_t inode_match_only, uint64_t *global) {
712*387f9dfdSAndroid Build Coastguard Worker   struct stat s;
713*387f9dfdSAndroid Build Coastguard Worker   uint64_t elf_so_addr, elf_so_offset;
714*387f9dfdSAndroid Build Coastguard Worker   if (stat(module, &s))
715*387f9dfdSAndroid Build Coastguard Worker     return -1;
716*387f9dfdSAndroid Build Coastguard Worker 
717*387f9dfdSAndroid Build Coastguard Worker   struct mod_search mod = {module, s.st_ino, major(s.st_dev), minor(s.st_dev),
718*387f9dfdSAndroid Build Coastguard Worker                            address, inode_match_only,
719*387f9dfdSAndroid Build Coastguard Worker                            0x0, 0x0};
720*387f9dfdSAndroid Build Coastguard Worker   if (bcc_procutils_each_module(pid, _bcc_syms_find_module, &mod) < 0 ||
721*387f9dfdSAndroid Build Coastguard Worker       mod.start == 0x0)
722*387f9dfdSAndroid Build Coastguard Worker     return -1;
723*387f9dfdSAndroid Build Coastguard Worker 
724*387f9dfdSAndroid Build Coastguard Worker   if (bcc_elf_get_text_scn_info(module, &elf_so_addr, &elf_so_offset) < 0)
725*387f9dfdSAndroid Build Coastguard Worker     return -1;
726*387f9dfdSAndroid Build Coastguard Worker 
727*387f9dfdSAndroid Build Coastguard Worker   *global = __so_calc_global_addr(mod.start, mod.file_offset, elf_so_addr,
728*387f9dfdSAndroid Build Coastguard Worker                                   elf_so_offset, address);
729*387f9dfdSAndroid Build Coastguard Worker   return 0;
730*387f9dfdSAndroid Build Coastguard Worker }
731*387f9dfdSAndroid Build Coastguard Worker 
_sym_cb_wrapper(const char * symname,uint64_t addr,uint64_t,void * payload)732*387f9dfdSAndroid Build Coastguard Worker static int _sym_cb_wrapper(const char *symname, uint64_t addr, uint64_t,
733*387f9dfdSAndroid Build Coastguard Worker                            void *payload) {
734*387f9dfdSAndroid Build Coastguard Worker   SYM_CB cb = (SYM_CB) payload;
735*387f9dfdSAndroid Build Coastguard Worker   return cb(symname, addr);
736*387f9dfdSAndroid Build Coastguard Worker }
737*387f9dfdSAndroid Build Coastguard Worker 
bcc_foreach_function_symbol(const char * module,SYM_CB cb)738*387f9dfdSAndroid Build Coastguard Worker int bcc_foreach_function_symbol(const char *module, SYM_CB cb) {
739*387f9dfdSAndroid Build Coastguard Worker   if (module == 0 || cb == 0)
740*387f9dfdSAndroid Build Coastguard Worker     return -1;
741*387f9dfdSAndroid Build Coastguard Worker 
742*387f9dfdSAndroid Build Coastguard Worker   static struct bcc_symbol_option default_option = {
743*387f9dfdSAndroid Build Coastguard Worker     .use_debug_file = 1,
744*387f9dfdSAndroid Build Coastguard Worker     .check_debug_file_crc = 1,
745*387f9dfdSAndroid Build Coastguard Worker     .lazy_symbolize = 1,
746*387f9dfdSAndroid Build Coastguard Worker     .use_symbol_type = (1 << STT_FUNC) | (1 << STT_GNU_IFUNC)
747*387f9dfdSAndroid Build Coastguard Worker   };
748*387f9dfdSAndroid Build Coastguard Worker 
749*387f9dfdSAndroid Build Coastguard Worker   return bcc_elf_foreach_sym(
750*387f9dfdSAndroid Build Coastguard Worker       module, _sym_cb_wrapper, &default_option, (void *)cb);
751*387f9dfdSAndroid Build Coastguard Worker }
752*387f9dfdSAndroid Build Coastguard Worker 
_find_sym(const char * symname,uint64_t addr,uint64_t,void * payload)753*387f9dfdSAndroid Build Coastguard Worker static int _find_sym(const char *symname, uint64_t addr, uint64_t,
754*387f9dfdSAndroid Build Coastguard Worker                      void *payload) {
755*387f9dfdSAndroid Build Coastguard Worker   struct bcc_symbol *sym = (struct bcc_symbol *)payload;
756*387f9dfdSAndroid Build Coastguard Worker   if (!strcmp(sym->name, symname)) {
757*387f9dfdSAndroid Build Coastguard Worker     sym->offset = addr;
758*387f9dfdSAndroid Build Coastguard Worker     return -1;
759*387f9dfdSAndroid Build Coastguard Worker   }
760*387f9dfdSAndroid Build Coastguard Worker   return 0;
761*387f9dfdSAndroid Build Coastguard Worker }
762*387f9dfdSAndroid Build Coastguard Worker 
763*387f9dfdSAndroid Build Coastguard Worker struct load_addr_t {
764*387f9dfdSAndroid Build Coastguard Worker   uint64_t target_addr;
765*387f9dfdSAndroid Build Coastguard Worker   uint64_t binary_addr;
766*387f9dfdSAndroid Build Coastguard Worker };
_find_load(uint64_t v_addr,uint64_t mem_sz,uint64_t file_offset,void * payload)767*387f9dfdSAndroid Build Coastguard Worker int _find_load(uint64_t v_addr, uint64_t mem_sz, uint64_t file_offset,
768*387f9dfdSAndroid Build Coastguard Worker                        void *payload) {
769*387f9dfdSAndroid Build Coastguard Worker   struct load_addr_t *addr = static_cast<load_addr_t *>(payload);
770*387f9dfdSAndroid Build Coastguard Worker   if (addr->target_addr >= v_addr && addr->target_addr < (v_addr + mem_sz)) {
771*387f9dfdSAndroid Build Coastguard Worker     addr->binary_addr = addr->target_addr - v_addr + file_offset;
772*387f9dfdSAndroid Build Coastguard Worker     return -1;
773*387f9dfdSAndroid Build Coastguard Worker   }
774*387f9dfdSAndroid Build Coastguard Worker   return 0;
775*387f9dfdSAndroid Build Coastguard Worker }
776*387f9dfdSAndroid Build Coastguard Worker 
bcc_resolve_symname(const char * module,const char * symname,const uint64_t addr,int pid,struct bcc_symbol_option * option,struct bcc_symbol * sym)777*387f9dfdSAndroid Build Coastguard Worker int bcc_resolve_symname(const char *module, const char *symname,
778*387f9dfdSAndroid Build Coastguard Worker                         const uint64_t addr, int pid,
779*387f9dfdSAndroid Build Coastguard Worker                         struct bcc_symbol_option *option,
780*387f9dfdSAndroid Build Coastguard Worker                         struct bcc_symbol *sym) {
781*387f9dfdSAndroid Build Coastguard Worker   int module_type;
782*387f9dfdSAndroid Build Coastguard Worker   static struct bcc_symbol_option default_option = {
783*387f9dfdSAndroid Build Coastguard Worker     .use_debug_file = 1,
784*387f9dfdSAndroid Build Coastguard Worker     .check_debug_file_crc = 1,
785*387f9dfdSAndroid Build Coastguard Worker     .lazy_symbolize = 1,
786*387f9dfdSAndroid Build Coastguard Worker #if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
787*387f9dfdSAndroid Build Coastguard Worker     .use_symbol_type = BCC_SYM_ALL_TYPES | (1 << STT_PPC64_ELFV2_SYM_LEP),
788*387f9dfdSAndroid Build Coastguard Worker #else
789*387f9dfdSAndroid Build Coastguard Worker     .use_symbol_type = BCC_SYM_ALL_TYPES,
790*387f9dfdSAndroid Build Coastguard Worker #endif
791*387f9dfdSAndroid Build Coastguard Worker   };
792*387f9dfdSAndroid Build Coastguard Worker 
793*387f9dfdSAndroid Build Coastguard Worker   if (module == NULL)
794*387f9dfdSAndroid Build Coastguard Worker     return -1;
795*387f9dfdSAndroid Build Coastguard Worker 
796*387f9dfdSAndroid Build Coastguard Worker   memset(sym, 0, sizeof(bcc_symbol));
797*387f9dfdSAndroid Build Coastguard Worker 
798*387f9dfdSAndroid Build Coastguard Worker   if (strchr(module, '/')) {
799*387f9dfdSAndroid Build Coastguard Worker     sym->module = strdup(module);
800*387f9dfdSAndroid Build Coastguard Worker   } else {
801*387f9dfdSAndroid Build Coastguard Worker     sym->module = bcc_procutils_which_so(module, pid);
802*387f9dfdSAndroid Build Coastguard Worker   }
803*387f9dfdSAndroid Build Coastguard Worker   if (sym->module == NULL)
804*387f9dfdSAndroid Build Coastguard Worker     return -1;
805*387f9dfdSAndroid Build Coastguard Worker   if (pid != 0 && pid != -1 && strstr(sym->module, "/proc") != sym->module){
806*387f9dfdSAndroid Build Coastguard Worker     char *temp = (char*)sym->module;
807*387f9dfdSAndroid Build Coastguard Worker     sym->module = strdup(tfm::format("/proc/%d/root%s", pid, sym->module).c_str());
808*387f9dfdSAndroid Build Coastguard Worker     free(temp);
809*387f9dfdSAndroid Build Coastguard Worker   }
810*387f9dfdSAndroid Build Coastguard Worker 
811*387f9dfdSAndroid Build Coastguard Worker   sym->name = symname;
812*387f9dfdSAndroid Build Coastguard Worker   sym->offset = addr;
813*387f9dfdSAndroid Build Coastguard Worker   if (option == NULL)
814*387f9dfdSAndroid Build Coastguard Worker     option = &default_option;
815*387f9dfdSAndroid Build Coastguard Worker 
816*387f9dfdSAndroid Build Coastguard Worker   if (sym->name && sym->offset == 0x0)
817*387f9dfdSAndroid Build Coastguard Worker     if (bcc_elf_foreach_sym(sym->module, _find_sym, option, sym) < 0)
818*387f9dfdSAndroid Build Coastguard Worker       goto invalid_module;
819*387f9dfdSAndroid Build Coastguard Worker   if (sym->offset == 0x0)
820*387f9dfdSAndroid Build Coastguard Worker     goto invalid_module;
821*387f9dfdSAndroid Build Coastguard Worker 
822*387f9dfdSAndroid Build Coastguard Worker   // For executable (ET_EXEC) binaries and shared objects (ET_DYN), translate
823*387f9dfdSAndroid Build Coastguard Worker   // the virtual address to physical address in the binary file.
824*387f9dfdSAndroid Build Coastguard Worker   module_type = bcc_elf_get_type(sym->module);
825*387f9dfdSAndroid Build Coastguard Worker   if (module_type == ET_EXEC || module_type == ET_DYN) {
826*387f9dfdSAndroid Build Coastguard Worker     struct load_addr_t addr = {
827*387f9dfdSAndroid Build Coastguard Worker       .target_addr = sym->offset,
828*387f9dfdSAndroid Build Coastguard Worker       .binary_addr = 0x0,
829*387f9dfdSAndroid Build Coastguard Worker     };
830*387f9dfdSAndroid Build Coastguard Worker     if (bcc_elf_foreach_load_section(sym->module, &_find_load, &addr) < 0)
831*387f9dfdSAndroid Build Coastguard Worker       goto invalid_module;
832*387f9dfdSAndroid Build Coastguard Worker     if (!addr.binary_addr)
833*387f9dfdSAndroid Build Coastguard Worker       goto invalid_module;
834*387f9dfdSAndroid Build Coastguard Worker     sym->offset = addr.binary_addr;
835*387f9dfdSAndroid Build Coastguard Worker   }
836*387f9dfdSAndroid Build Coastguard Worker   return 0;
837*387f9dfdSAndroid Build Coastguard Worker 
838*387f9dfdSAndroid Build Coastguard Worker invalid_module:
839*387f9dfdSAndroid Build Coastguard Worker   if (sym->module) {
840*387f9dfdSAndroid Build Coastguard Worker     ::free(const_cast<char*>(sym->module));
841*387f9dfdSAndroid Build Coastguard Worker     sym->module = NULL;
842*387f9dfdSAndroid Build Coastguard Worker   }
843*387f9dfdSAndroid Build Coastguard Worker   return -1;
844*387f9dfdSAndroid Build Coastguard Worker }
845*387f9dfdSAndroid Build Coastguard Worker }
846