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/unwind.cc
2023-12-12 11:55:44 +08:00

119 lines
3.0 KiB
C++

#include "unwind.h"
#include <errno.h>
#include <stdio.h>
#include <string>
static std::string unknow_symbol("UNKNOWN");
// static int unwind_frame_callback(struct unwind_entry *entry, void *arg) {
// symbol sym;
// std::string symbol; // Use std::string instead of string
// elf_file file;
// sym.reset(entry->ip);
// if (g_symbol_parser.find_symbol_in_cache(entry->pid, entry->ip, symbol)) {
// printf("#~ 0x%lx %s ([symbol])\n", entry->ip, symbol.c_str());
// return 0;
// }
// if (g_symbol_parser.get_symbol_info(entry->pid, sym, file)) {
// if (g_symbol_parser.find_elf_symbol(sym, file, entry->pid,
// entry->pid_ns)) {
// printf("#~ 0x%lx %s ([symbol])\n", entry->ip, sym.name.c_str());
// g_symbol_parser.putin_symbol_cache(entry->pid, entry->ip, sym.name);
// } else {
// printf("#~ 0x%lx %s ([symbol])\n", entry->ip,
// "(unknown)[symbol]"); g_symbol_parser.putin_symbol_cache(entry->pid,
// entry->ip, unknow_symbol);
// }
// } else {
// printf("#~ 0x%lx %s ([symbol])\n", entry->ip,
// "(unknown)[vma,elf]"); g_symbol_parser.putin_symbol_cache(entry->pid,
// entry->ip, unknow_symbol);
// }
// return 0;
// }
/*
* Optimization point.
*/
static int reg_value(unw_word_t *valp, struct regs_dump *regs, int id) {
/* we only support 3 registers. RIP, RSP and RBP */
if (id < 0 || id > 2)
return -EINVAL;
*valp = regs->regs[id];
return 0;
}
static int entry(u64 ip, int pid, int pid_ns, unwind_entry_cb_t cb, void *arg) {
struct unwind_entry e;
e.ip = ip;
e.pid = pid;
e.pid_ns = pid_ns;
return cb(&e, arg);
}
static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
void *arg) {
unw_addr_space_t addr_space;
unw_cursor_t c;
entry_cb_arg_t *cb_arg = (entry_cb_arg_t *)arg;
int ret;
int loops = 0;
addr_space = unw_create_addr_space(&accessors, 0);
if (!addr_space) {
// pr_err("unwind: Can't create unwind address space.\n");
return -ENOMEM;
}
unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
ret = unw_init_remote(&c, addr_space, ui); /* @ui is args */
while (!ret && (unw_step(&c) > 0)) {
unw_word_t ip;
unw_get_reg(&c, UNW_REG_IP, &ip); // get IP from current step;
cb_arg->arg = &c;
ret = entry(ip, ui->pid, ui->pid_ns, cb, cb_arg);
loops++;
if (loops >= 50)
break;
}
unw_destroy_addr_space(addr_space);
return ret;
}
int unwind__get_entries(unwind_entry_cb_t cb, void *arg, symbol_parser *sp,
int pid, int pid_ns, struct perf_sample *data) {
unw_word_t ip;
struct unwind_info ui = {
.sample = data,
.pid = pid,
.pid_ns = pid_ns,
.sp = sp,
};
int ret;
if (!data->user_regs.regs)
return -EINVAL;
ret = reg_value(&ip, &data->user_regs, PERF_REG_IP);
if (ret)
return ret;
ret = entry(ip, pid, pid_ns, cb, arg);
if (ret)
return -ENOMEM;
return get_entries(&ui, cb, arg);
}