This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
zhangyang-variable-monitor/source/ucli/symbol.cc
2023-11-26 20:34:52 -05:00

228 lines
5.2 KiB
C++

#include <elf.h>
#include <string.h>
#include "elf.h"
symbol_parser g_symbol_parser;
vma *symbol_parser::find_vma(pid_t pid, size_t pc) {
std::map<int, proc_vma>::iterator it;
it = machine_vma.find(pid);
if (it == machine_vma.end()) {
return NULL;
}
proc_vma::iterator vma_iter = it->second.upper_bound(pc);
if (vma_iter == it->second.end() || vma_iter->second.end < pc) {
return NULL;
}
if (vma_iter != it->second.begin()) {
--vma_iter;
}
return &vma_iter->second;
}
bool symbol_parser::find_vma(pid_t pid, vma &vm) {
std::map<int, proc_vma>::iterator proc_vma_map;
proc_vma_map = machine_vma.find(pid);
if (proc_vma_map == machine_vma.end()) {
return false;
}
proc_vma::const_iterator vma_iter = proc_vma_map->second.upper_bound(vm.pc);
if (vma_iter == proc_vma_map->second.end()) {
return false;
}
if (vma_iter->second.end < vm.pc) {
return false;
}
if (vma_iter != proc_vma_map->second.begin()) {
--vma_iter;
}
vm.start = vma_iter->second.start;
vm.end = vma_iter->second.end;
vm.name = vma_iter->second.name;
vm.offset = vma_iter->second.offset;
return true;
}
bool symbol_parser::load_pid_maps(int pid) {
std::map<int, proc_vma>::iterator it;
it = machine_vma.find(pid);
if (it != machine_vma.end()) {
return true;
}
proc_vma proc;
char fn[256];
sprintf(fn, "/proc/%d/maps", pid);
FILE *fp = fopen(fn, "r");
if (!fp) {
return false;
}
char buf[4096];
char exename[4096];
size_t start, end, offset;
while (fgets(buf, sizeof(buf), fp) != NULL) {
start = end = offset = 0;
exename[0] = '\0';
sscanf(buf, "%lx-%lx %*s %lx %*x:%*x %*u %s %*s\n", &start, &end, &offset,
exename);
if (exename[0] == '\0') {
strcpy(exename, "[anon]");
}
vma vm(start, end, offset, exename);
proc.insert(std::make_pair(vm.start, std::move(vm)));
}
fclose(fp);
machine_vma.insert(std::make_pair(pid, std::move(proc)));
it = machine_vma.find(pid);
if (it == machine_vma.end()) {
return false;
}
return true;
}
bool symbol_parser::find_symbol_in_cache(int tgid, unsigned long addr,
std::string &symbol) {
std::map<int, std::map<unsigned long, std::string> >::const_iterator it_pid =
symbols_cache.find(tgid);
if (it_pid != symbols_cache.end()) {
std::map<unsigned long, std::string> map = symbols_cache[tgid];
std::map<unsigned long, std::string>::const_iterator it_symbol =
map.find(addr);
if (it_symbol != map.end()) {
symbol = map[addr];
return true;
}
}
return false;
}
bool symbol_parser::get_symbol_info(int pid, symbol &sym, elf_file &file) {
std::map<int, proc_vma>::iterator proc_vma_info;
if (java_only) {
file.type = UNKNOWN;
return true;
}
proc_vma_info = machine_vma.find(pid);
if (proc_vma_info == machine_vma.end()) {
if (!load_pid_maps(pid)) {
return false;
}
}
vma area(sym.ip);
if (!find_vma(pid, area)) {
return false;
}
if (area.name == "[anon]") {
file.type = JIT_TYPE;
}
file.reset(area.name);
if (file.type != JIT_TYPE) {
sym.reset(area.map(sym.ip));
}
return true;
}
bool symbol_parser::putin_symbol_cache(int tgid, unsigned long addr,
std::string &symbol) {
std::map<int, std::map<unsigned long, std::string> >::const_iterator it_pid =
symbols_cache.find(tgid);
if (it_pid == symbols_cache.end()) {
std::map<unsigned long, std::string> map;
symbols_cache.insert(std::make_pair(tgid, map));
}
std::map<unsigned long, std::string> &map = symbols_cache[tgid];
std::map<unsigned long, std::string>::const_iterator it_symbol =
map.find(addr);
if (it_symbol == map.end()) {
map[addr] = symbol;
return true;
}
return false;
}
bool search_symbol(const std::set<symbol> &ss, symbol &sym) {
std::set<symbol>::const_iterator it = ss.find(sym);
if (it != ss.end()) {
sym.end = it->end;
sym.start = it->start;
sym.name = it->name;
return true;
}
return false;
}
bool symbol_parser::load_elf(pid_t pid, const elf_file &file) {
std::map<elf_file, std::set<symbol> >::iterator it;
it = file_symbols.find(file);
std::set<symbol> tmp;
std::set<symbol> &syms = tmp;
if (it != file_symbols.end()) {
return true;
}
if (get_symbol_from_elf(syms, file.filename.c_str())) {
file_symbols.insert(make_pair(file, std::move(syms)));
return true;
}
return false;
}
bool symbol_parser::find_elf_symbol(symbol &sym, const elf_file &file, int pid,
int pid_ns) {
std::map<elf_file, std::set<symbol> >::iterator it;
it = file_symbols.find(file);
std::set<symbol> ss;
if (it == file_symbols.end()) {
if (!load_elf(pid, file)) {
return false;
}
it = file_symbols.find(file);
return search_symbol(it->second, sym);
} else {
return search_symbol(it->second, sym);
}
return true;
}
bool symbol_parser::find_kernel_symbol(symbol &sym)
{
load_kernel();
sym.end = sym.start = 0;
std::set<symbol>::iterator it = kernel_symbols.find(sym);
if (it != kernel_symbols.end()) {
sym.end = it->end;
sym.start = it->start;
sym.name = it->name;
return true;
}
return false;
}