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
2023-12-12 02:59:48 -05:00

274 lines
6.8 KiB
C++
Raw Permalink 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 <fstream>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <assert.h>
#include <ctype.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include "symbol.h"
#include "ucli.h"
#include "unwind.h"
#define BUF_LEN 4096
#define WHITESPACE " \t\n\r"
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
#define streq(a, b) (strcmp((a), (b)) == 0)
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];
}
// 根据 sys_task 取值返回对应的字符串
static const char *sys_task_str(int sys_task) {
switch (sys_task) {
case 0:
return "USER_TASK";
case 1:
return "SYSTEM_TASK";
case 2:
return "IDLE_TASK";
default:
return "UNKNOWN_TASK";
}
}
/**
* @brief call 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,try to open %s\n", DEVICE, DEVICE_BAK);
fd = open(DEVICE_BAK, O_RDWR, 0);
if (fd < 0) {
printf("open %s error!\n", DEVICE_BAK);
return EEXIST;
} else {
printf("open %s success!\n", DEVICE_BAK);
}
}
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;
}
/**
* @brief unwind frame callback
*
* @param entry
* @param arg
* @return int
*/
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;
}
// printf("#~ sym1 0x%lx\n", sym.ip);
if (g_symbol_parser.get_symbol_info(entry->pid, sym, file)) {
// printf("#~ sym2 0x%lx\n", sym.ip);
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;
}
/**
* @brief extract buffer with func
*
* @param buf
* @param len
* @param func
* @param arg
*/
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);
}
}
/**
* @brief printf user stack
*
* @param pid
* @param ns_pid
* @param comm
* @param raw_stack
*/
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(" USER STACK: 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);
}
/**
* @brief printf task brief
*
* @param detail
*/
void printk_task_brief(task_detail *detail) {
printf(" TASK INFO: %s [%s / %s], PID: %d / %d\n",
sys_task_str(detail->sys_task), detail->cgroup_buf, detail->comm,
detail->tgid, detail->pid);
// printf(" TASK STATE: type: %s, state: %s, state %d\n",
// sys_task_str(detail->sys_task), state_str(detail->state).c_str(),
// detail->state);
}
/**
* @brief print kernel stack
*
* @param kern_stack
*/
void diag_printf_kern_stack(kern_stack_detail *kern_stack) {
int i;
symbol sym;
printf(" KERNEL STACK\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");
}
}
}
/**
* @brief print proc chains
*
* @param proc_chains
*/
void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
int detail = 1;
int i;
printf(" PROC CHAINS:\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]);
}
}
}