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

274 lines
6.8 KiB
C++
Raw Permalink Normal View History

2023-11-24 05:34:51 -05:00
#include <errno.h>
#include <fcntl.h>
2023-12-12 11:55:44 +08:00
#include <fstream>
2023-11-24 05:34:51 -05:00
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>
2023-11-26 22:09:56 -05:00
2023-12-04 23:03:19 -05:00
#include <assert.h>
#include <ctype.h>
2023-12-12 11:55:44 +08:00
#include <stdio_ext.h>
2023-12-04 23:03:19 -05:00
#include <stdlib.h>
#include <string.h>
2023-11-26 20:34:52 -05:00
#include "symbol.h"
2023-11-26 22:09:56 -05:00
#include "ucli.h"
#include "unwind.h"
2023-12-04 23:03:19 -05:00
#define BUF_LEN 4096
2023-12-12 11:55:44 +08:00
#define WHITESPACE " \t\n\r"
2023-12-04 23:03:19 -05:00
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
2023-12-12 11:55:44 +08:00
#define streq(a, b) (strcmp((a), (b)) == 0)
2023-12-04 23:03:19 -05:00
2023-11-26 22:09:56 -05:00
using namespace std;
class pid_cmdline {
2023-12-12 11:55:44 +08:00
private:
2023-11-26 22:09:56 -05:00
std::map<int, std::string> cmdlines;
2023-12-12 11:55:44 +08:00
public:
2023-11-26 22:09:56 -05:00
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];
}
2023-11-24 05:34:51 -05:00
2023-12-12 02:59:48 -05:00
// 根据 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";
}
}
2023-11-24 05:34:51 -05:00
/**
2023-12-12 02:59:48 -05:00
* @brief call ioctl
2023-11-24 05:34:51 -05:00
*/
long diag_call_ioctl(unsigned long request, unsigned long arg) {
long ret = 0;
int fd;
fd = open(DEVICE, O_RDWR, 0);
if (fd < 0) {
2023-12-12 11:55:44 +08:00
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);
}
2023-11-24 05:34:51 -05:00
}
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;
}
2023-12-12 02:59:48 -05:00
/**
* @brief unwind frame callback
*
* @param entry
* @param arg
* @return int
*/
2023-11-26 22:09:56 -05:00
static int unwind_frame_callback(struct unwind_entry *entry, void *arg) {
symbol sym;
2023-12-12 11:55:44 +08:00
std::string symbol; // Use std::string instead of string
2023-11-26 22:09:56 -05:00
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);
2023-11-26 22:09:56 -05:00
if (g_symbol_parser.get_symbol_info(entry->pid, sym, file)) {
// printf("#~ sym2 0x%lx\n", sym.ip);
2023-11-26 22:09:56 -05:00
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;
}
2023-12-12 02:59:48 -05:00
/**
* @brief extract buffer with func
*
* @param buf
* @param len
* @param func
* @param arg
*/
2023-11-26 20:34:52 -05:00
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);
2023-12-12 11:55:44 +08:00
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;
2023-11-26 20:34:52 -05:00
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);
}
}
2023-12-12 02:59:48 -05:00
/**
* @brief printf user stack
*
* @param pid
* @param ns_pid
* @param comm
* @param raw_stack
*/
2023-11-26 22:09:56 -05:00
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];
2023-12-05 22:29:41 -05:00
printf(" USER STACK: SP:%lx, BP:%lx, IP:%lx\n", raw_stack->sp,
2023-11-26 22:09:56 -05:00
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);
}
2023-12-12 02:59:48 -05:00
/**
* @brief printf task brief
*
* @param detail
*/
2023-11-26 22:09:56 -05:00
void printk_task_brief(task_detail *detail) {
2023-12-12 11:55:44 +08:00
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);
2023-11-26 20:34:52 -05:00
}
2023-12-12 02:59:48 -05:00
/**
* @brief print kernel stack
*
* @param kern_stack
*/
2023-11-26 22:09:56 -05:00
void diag_printf_kern_stack(kern_stack_detail *kern_stack) {
2023-11-26 20:34:52 -05:00
int i;
symbol sym;
2023-12-05 21:49:08 -05:00
printf(" KERNEL STACK\n");
2023-11-26 22:09:56 -05:00
for (i = 0; i < BACKTRACE_DEPTH; i++) {
if (kern_stack->stack[i] == (size_t)-1 || kern_stack->stack[i] == 0) {
break;
2023-11-26 20:34:52 -05:00
}
2023-11-26 22:09:56 -05:00
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");
2023-11-26 20:34:52 -05:00
}
}
}
2023-11-26 22:09:56 -05:00
2023-12-12 02:59:48 -05:00
/**
* @brief print proc chains
*
* @param proc_chains
*/
2023-11-26 22:09:56 -05:00
void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
int detail = 1;
int i;
2023-12-05 21:49:08 -05:00
printf(" PROC CHAINS:\n");
2023-11-26 22:09:56 -05:00
for (i = 0; i < PROCESS_CHAINS_COUNT; i++) {
2023-12-12 11:55:44 +08:00
if (proc_chains->chains[i][0] == 0)
break;
2023-11-26 22:09:56 -05:00
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]);
}
}
2023-12-12 02:59:48 -05:00
}