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_py/libunwind/unwind.cc

131 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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) {
//! todo: 未实现
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);
}
void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
raw_stack_detail *raw_stack, int attach){
struct perf_sample stack_sample;
entry_cb_arg_t unwind_arg;
static u64 regs_buf[3];
printf(" 用户态堆栈SP%lx, BP:%lx, IP:%lx\n", raw_stack->sp,
raw_stack->bp, raw_stack->ip);
stack_sample.user_stack.offset = 0;
stack_sample.user_stack.size = raw_stack->stack_size;
stack_sample.user_stack.data = (char *)&raw_stack->stack[0];
stack_sample.user_regs.regs = regs_buf;
stack_sample.user_regs.regs[PERF_REG_IP] = raw_stack->ip;
stack_sample.user_regs.regs[PERF_REG_SP] = raw_stack->sp;
stack_sample.user_regs.regs[PERF_REG_BP] = raw_stack->bp;
unwind__get_entries(unwind_frame_callback, &unwind_arg, &g_symbol_parser, pid,
ns_pid, &stack_sample);
}