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/ucli-lib.cc
2023-11-26 22:09:56 -05:00

199 lines
5.4 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 <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fstream>
#include "symbol.h"
#include "ucli.h"
#include "unwind.h"
using namespace std;
class pid_cmdline {
private:
std::map<int, std::string> cmdlines;
public:
void clear(void);
std::string &get_pid_cmdline(int pid);
};
class pid_cmdline pid_cmdline;
static string unknow_symbol("UNKNOWN");
void pid_cmdline::clear(void) { cmdlines.clear(); }
std::string &pid_cmdline::get_pid_cmdline(int pid) {
if (cmdlines.count(pid) == 0) {
int i;
char buf[255];
char file[255];
std::fstream ifs;
snprintf(file, sizeof(file), "/proc/%d/cmdline", pid);
ifs.open(file, ios::binary | ios::in);
ifs.getline(buf, 255);
for (i = 0; i < ifs.gcount() && i < 255; i++) {
if (buf[i] < ' ') {
buf[i] = ' ';
}
}
cmdlines[pid] = buf;
}
return cmdlines[pid];
}
/**
* @brief 调用ioctl
*/
long diag_call_ioctl(unsigned long request, unsigned long arg) {
long ret = 0;
int fd;
fd = open(DEVICE, O_RDWR, 0);
if (fd < 0) {
printf("open %s error!\n", DEVICE);
return -EEXIST;
}
ret = ioctl(fd, request, arg);
if (ret < 0) {
printf("call cmd %lx fail, ret is %ld\n", request, ret);
goto err;
}
err:
close(fd);
return ret;
}
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;
}
void extract_variant_buffer(char *buf, unsigned int len,
int (*func)(void *, unsigned int, void *),
void *arg) {
unsigned int pos = 0;
struct diag_variant_buffer_head *head;
void *rec;
int rec_len;
char *ret;
char dir[1024] = {0};
ret = getcwd(dir, sizeof(dir));
while (pos < len) {
head = (struct diag_variant_buffer_head *)(buf + pos);
if (pos + sizeof(struct diag_variant_buffer_head) >= len) break;
if (head->magic != DIAG_VARIANT_BUFFER_HEAD_MAGIC_SEALED) break;
if (head->len < sizeof(struct diag_variant_buffer_head)) break;
rec = (void *)(buf + pos + sizeof(struct diag_variant_buffer_head));
rec_len = head->len - sizeof(struct diag_variant_buffer_head);
func(rec, rec_len, arg);
pos += head->len;
}
if (ret) {
(void)chdir(dir);
}
}
void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
raw_stack_detail *raw_stack) {
struct perf_sample stack_sample;
entry_cb_arg_t unwind_arg;
static u64 regs_buf[3];
printf("##C++ pid %d\n", pid);
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);
fflush(stdout);
}
void printk_task_brief(task_detail *detail) {
printf(" 进程信息: [%s / %s] PID %d / %d\n", detail->cgroup_buf,
detail->comm, detail->tgid, detail->pid);
}
void diag_printf_kern_stack(kern_stack_detail *kern_stack) {
int i;
symbol sym;
printf(" 内核态堆栈:\n");
for (i = 0; i < BACKTRACE_DEPTH; i++) {
if (kern_stack->stack[i] == (size_t)-1 || kern_stack->stack[i] == 0) {
break;
}
sym.reset(kern_stack->stack[i]);
if (g_symbol_parser.find_kernel_symbol(sym)) {
printf("#@ 0x%lx %s ([kernel.kallsyms])\n", kern_stack->stack[i],
sym.name.c_str());
} else {
printf("#@ 0x%lx %s\n", kern_stack->stack[i], "UNKNOWN");
}
}
}
void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
int detail = 1;
int i;
printf(" 进程链信息:\n");
for (i = 0; i < PROCESS_CHAINS_COUNT; i++) {
if (proc_chains->chains[i][0] == 0) break;
if (proc_chains->full_argv[i] == 0 && detail) {
string cmdline = pid_cmdline.get_pid_cmdline(proc_chains->tgid[i]);
if (cmdline.length() > 0)
printf("#^ 0xffffffffffffff %s (UNKNOWN)\n", cmdline.c_str());
else
printf("#^ 0xffffffffffffff %s (UNKNOWN)\n",
proc_chains->chains[i]);
} else {
printf("#^ 0xffffffffffffff %s (UNKNOWN)\n",
proc_chains->chains[i]);
}
}
}