reformat code
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <gelf.h> // for GElf_Ehdr | Elf
|
||||
#include <gelf.h> // for GElf_Ehdr | Elf
|
||||
#include <libelf.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <elf.h>
|
||||
#include <libelf.h>
|
||||
|
||||
#include "unwind.h"
|
||||
|
||||
@@ -43,7 +43,8 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, GElf_Shdr *shp,
|
||||
|
||||
gelf_getshdr(sec, shp);
|
||||
str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
|
||||
if (!strcmp(name, str)) break;
|
||||
if (!strcmp(name, str))
|
||||
break;
|
||||
}
|
||||
|
||||
return sec;
|
||||
@@ -56,12 +57,15 @@ static u64 elf_section_offset(int fd, const char *name) {
|
||||
u64 offset = 0;
|
||||
|
||||
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
|
||||
if (elf == NULL) return 0;
|
||||
if (elf == NULL)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
if (gelf_getehdr(elf, &ehdr) == NULL) break;
|
||||
if (gelf_getehdr(elf, &ehdr) == NULL)
|
||||
break;
|
||||
|
||||
if (!elf_section_by_name(elf, &ehdr, &shdr, name)) break;
|
||||
if (!elf_section_by_name(elf, &ehdr, &shdr, name))
|
||||
break;
|
||||
|
||||
offset = shdr.sh_offset;
|
||||
} while (0);
|
||||
@@ -103,13 +107,16 @@ ssize_t dso_read(vma *dso, u64 offset, u8 *data, ssize_t size) {
|
||||
int fd;
|
||||
|
||||
fd = dso_data_fd(dso);
|
||||
if (fd < 0) return -1;
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
do {
|
||||
if (-1 == lseek(fd, offset, SEEK_SET)) break;
|
||||
if (-1 == lseek(fd, offset, SEEK_SET))
|
||||
break;
|
||||
|
||||
ret = read(fd, data, size);
|
||||
if (ret <= 0) break;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
} while (0);
|
||||
|
||||
close(fd);
|
||||
@@ -137,14 +144,15 @@ ssize_t dso__data_read_offset(vma *dso, u64 offset, u8 *data, ssize_t size) {
|
||||
return r;
|
||||
}
|
||||
|
||||
#define dw_read(ptr, type, end) \
|
||||
({ \
|
||||
type *__p = (type *)ptr; \
|
||||
type __v; \
|
||||
if ((__p + 1) > (type *)end) return -EINVAL; \
|
||||
__v = *__p++; \
|
||||
ptr = (typeof(ptr))__p; \
|
||||
__v; \
|
||||
#define dw_read(ptr, type, end) \
|
||||
({ \
|
||||
type *__p = (type *)ptr; \
|
||||
type __v; \
|
||||
if ((__p + 1) > (type *)end) \
|
||||
return -EINVAL; \
|
||||
__v = *__p++; \
|
||||
ptr = (typeof(ptr))__p; \
|
||||
__v; \
|
||||
})
|
||||
|
||||
static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, u8 encoding) {
|
||||
@@ -152,43 +160,44 @@ static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val, u8 encoding) {
|
||||
*val = 0;
|
||||
|
||||
switch (encoding) {
|
||||
case DW_EH_PE_omit:
|
||||
*val = 0;
|
||||
goto out;
|
||||
case DW_EH_PE_ptr:
|
||||
*val = dw_read(cur, unsigned long, end);
|
||||
goto out;
|
||||
default:
|
||||
break;
|
||||
case DW_EH_PE_omit:
|
||||
*val = 0;
|
||||
goto out;
|
||||
case DW_EH_PE_ptr:
|
||||
*val = dw_read(cur, unsigned long, end);
|
||||
goto out;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (encoding & DW_EH_PE_APPL_MASK) {
|
||||
case DW_EH_PE_absptr:
|
||||
break;
|
||||
case DW_EH_PE_pcrel:
|
||||
*val = (unsigned long)cur;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
case DW_EH_PE_absptr:
|
||||
break;
|
||||
case DW_EH_PE_pcrel:
|
||||
*val = (unsigned long)cur;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((encoding & 0x07) == 0x00) encoding |= DW_EH_PE_udata4;
|
||||
if ((encoding & 0x07) == 0x00)
|
||||
encoding |= DW_EH_PE_udata4;
|
||||
|
||||
switch (encoding & DW_EH_PE_FORMAT_MASK) {
|
||||
case DW_EH_PE_sdata4:
|
||||
*val += dw_read(cur, s32, end);
|
||||
break;
|
||||
case DW_EH_PE_udata4:
|
||||
*val += dw_read(cur, u32, end);
|
||||
break;
|
||||
case DW_EH_PE_sdata8:
|
||||
*val += dw_read(cur, s64, end);
|
||||
break;
|
||||
case DW_EH_PE_udata8:
|
||||
*val += dw_read(cur, u64, end);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
case DW_EH_PE_sdata4:
|
||||
*val += dw_read(cur, s32, end);
|
||||
break;
|
||||
case DW_EH_PE_udata4:
|
||||
*val += dw_read(cur, u32, end);
|
||||
break;
|
||||
case DW_EH_PE_sdata8:
|
||||
*val += dw_read(cur, s64, end);
|
||||
break;
|
||||
case DW_EH_PE_udata8:
|
||||
*val += dw_read(cur, u64, end);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -196,13 +205,13 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define dw_read_encoded_value(ptr, end, enc) \
|
||||
({ \
|
||||
u64 __v; \
|
||||
if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
__v; \
|
||||
#define dw_read_encoded_value(ptr, end, enc) \
|
||||
({ \
|
||||
u64 __v; \
|
||||
if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
__v; \
|
||||
})
|
||||
|
||||
static int unwind_spec_ehframe(vma *dso, u64 offset, u64 *table_data,
|
||||
@@ -233,7 +242,8 @@ static int read_unwind_spec(vma *dso, u64 *table_data, u64 *segbase,
|
||||
|
||||
if (dso->eh_frame_hdr_offset == 0 && dso->elf_read_error == 0) {
|
||||
fd = dso_data_fd(dso);
|
||||
if (fd < 0) return -EINVAL;
|
||||
if (fd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
dso->eh_frame_hdr_offset = elf_section_offset(fd, ".eh_frame_hdr");
|
||||
close(fd);
|
||||
@@ -300,7 +310,8 @@ static int get_dyn_info_list_addr(unw_addr_space_t as, unw_word_t *dil_addr,
|
||||
ssize_t dso__data_read_addr(vma *map, u64 addr, u8 *data, ssize_t size) {
|
||||
u64 offset;
|
||||
|
||||
if (map->name.size() > 0 && map->name[0] != '/') return 0;
|
||||
if (map->name.size() > 0 && map->name[0] != '/')
|
||||
return 0;
|
||||
|
||||
offset = addr - map->start + map->offset;
|
||||
return dso__data_read_offset(map, offset, data, size);
|
||||
@@ -336,7 +347,8 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
|
||||
*/
|
||||
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;
|
||||
if (id < 0 || id > 2)
|
||||
return -EINVAL;
|
||||
|
||||
*valp = regs->regs[id];
|
||||
return 0;
|
||||
@@ -411,17 +423,17 @@ int unwind__arch_reg_id(int regnum) {
|
||||
int id;
|
||||
|
||||
switch (regnum) {
|
||||
case UNW_X86_64_RBP:
|
||||
id = PERF_REG_BP;
|
||||
break;
|
||||
case UNW_X86_64_RSP:
|
||||
id = PERF_REG_SP;
|
||||
break;
|
||||
case UNW_X86_64_RIP:
|
||||
id = PERF_REG_IP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
case UNW_X86_64_RBP:
|
||||
id = PERF_REG_BP;
|
||||
break;
|
||||
case UNW_X86_64_RSP:
|
||||
id = PERF_REG_SP;
|
||||
break;
|
||||
case UNW_X86_64_RIP:
|
||||
id = PERF_REG_IP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return id;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "elf.h"
|
||||
|
||||
#include <elf.h>
|
||||
#include <fcntl.h> // for open
|
||||
#include <gelf.h> // for GElf_Ehdr
|
||||
#include <fcntl.h> // for open
|
||||
#include <gelf.h> // for GElf_Ehdr
|
||||
#include <libelf.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -88,7 +88,8 @@ static int get_symbols_in_section(sym_section_ctx *sym, Elf *elf, Elf_Scn *sec,
|
||||
return -1;
|
||||
}
|
||||
|
||||
sym->sym_count = shdr->sh_size / shdr->sh_entsize; // 获取section中的symbol数量
|
||||
sym->sym_count =
|
||||
shdr->sh_size / shdr->sh_entsize; // 获取section中的symbol数量
|
||||
sym->is_plt = 0;
|
||||
sym->is_reloc = is_reloc; // 是否是可重定位文件
|
||||
|
||||
@@ -120,7 +121,8 @@ static int get_plt_symbols_in_section(sym_section_ctx *sym, Elf *elf,
|
||||
sym->is_plt = 1;
|
||||
sym->plt_entsize = plt->plt.hdr->sh_type;
|
||||
sym->plt_offset = plt->plt.hdr->sh_offset;
|
||||
sym->sym_count = plt->plt_rel.hdr->sh_size / plt->plt_rel.hdr->sh_entsize; // 获取section中的symbol数量
|
||||
sym->sym_count = plt->plt_rel.hdr->sh_size /
|
||||
plt->plt_rel.hdr->sh_entsize; // 获取section中的symbol数量
|
||||
sym->plt_rel_type = plt->plt_rel.hdr->sh_type;
|
||||
|
||||
return 0;
|
||||
@@ -163,7 +165,8 @@ static void __get_symbol_without_plt(std::set<symbol> &ss, sym_section_ctx *tab,
|
||||
s.end = s.start + sym.st_size;
|
||||
s.ip = s.start;
|
||||
s.name = sym_name;
|
||||
// printf("name: %s, start: 0x%lx, end: 0x%lx\n", s.name.c_str(), s.start, s.end);
|
||||
// printf("name: %s, start: 0x%lx, end: 0x%lx\n", s.name.c_str(), s.start,
|
||||
// s.end);
|
||||
ss.insert(s);
|
||||
}
|
||||
}
|
||||
@@ -220,7 +223,8 @@ static void __get_plt_symbol(std::set<symbol> &ss, symbol_sections_ctx *si,
|
||||
s.end = s.start + si->dynsymtab.plt_entsize;
|
||||
s.ip = s.start;
|
||||
s.name = sym_name;
|
||||
// printf("plt name: %s, start: 0x%lx, end: 0x%lx\n", s.name.c_str(), s.start, s.end);
|
||||
// printf("plt name: %s, start: 0x%lx, end: 0x%lx\n", s.name.c_str(),
|
||||
// s.start, s.end);
|
||||
ss.insert(s);
|
||||
}
|
||||
}
|
||||
@@ -235,7 +239,8 @@ static void get_all_symbols(std::set<symbol> &ss, symbol_sections_ctx *si,
|
||||
// Dwarf_Off die_offset = 0, next_offset;
|
||||
// size_t header_size;
|
||||
// printf("1\n");
|
||||
// while (dwarf_nextcu(dw, die_offset, &next_offset, &header_size, NULL, NULL, NULL) == 0) {
|
||||
// while (dwarf_nextcu(dw, die_offset, &next_offset, &header_size, NULL, NULL,
|
||||
// NULL) == 0) {
|
||||
// printf("2\n");
|
||||
// Dwarf_Die cudie;
|
||||
// printf("3\n");
|
||||
@@ -280,11 +285,11 @@ static void get_all_symbols(std::set<symbol> &ss, symbol_sections_ctx *si,
|
||||
// }
|
||||
// }
|
||||
|
||||
bool is_stripped(const char* path) {
|
||||
bool is_stripped(const char *path) {
|
||||
char command[256];
|
||||
// snprintf(command, sizeof(command), "file %s", path);
|
||||
|
||||
FILE* fp = popen(command, "r");
|
||||
FILE *fp = popen(command, "r");
|
||||
if (fp == NULL) {
|
||||
// handle error
|
||||
return false;
|
||||
@@ -298,92 +303,87 @@ bool is_stripped(const char* path) {
|
||||
}
|
||||
|
||||
#define MAX_LINE_LENGTH 1024
|
||||
void get_symbol_from_elf_gdb(std::set<symbol> &ss, const char *path, size_t file_base_addr = 0)
|
||||
{
|
||||
FILE *fp;
|
||||
char cmd[MAX_LINE_LENGTH];
|
||||
char line[MAX_LINE_LENGTH];
|
||||
// 构建 GDB 命令
|
||||
snprintf(cmd, sizeof(cmd), "gdb -batch -ex \"file %s\" -ex \"info functions\"", path);
|
||||
void get_symbol_from_elf_gdb(std::set<symbol> &ss, const char *path,
|
||||
size_t file_base_addr = 0) {
|
||||
FILE *fp;
|
||||
char cmd[MAX_LINE_LENGTH];
|
||||
char line[MAX_LINE_LENGTH];
|
||||
// 构建 GDB 命令
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"gdb -batch -ex \"file %s\" -ex \"info functions\"", path);
|
||||
|
||||
// 执行 GDB 命令并获取输出
|
||||
fp = popen(cmd, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
perror("popen");
|
||||
return;
|
||||
// 执行 GDB 命令并获取输出
|
||||
fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen");
|
||||
return;
|
||||
}
|
||||
|
||||
bool non_debugging_symbols = false;
|
||||
std::map<unsigned long long, std::string> symbol_map;
|
||||
|
||||
// 读取并解析 GDB 的输出
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
unsigned long long address;
|
||||
char name[MAX_LINE_LENGTH];
|
||||
// printf("line: %s", line);
|
||||
if (!non_debugging_symbols) {
|
||||
if (strstr(line, "Non-debugging symbols:") != NULL) {
|
||||
non_debugging_symbols = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool non_debugging_symbols = false;
|
||||
std::map<unsigned long long, std::string> symbol_map;
|
||||
|
||||
// 读取并解析 GDB 的输出
|
||||
while (fgets(line, sizeof(line), fp) != NULL)
|
||||
{
|
||||
unsigned long long address;
|
||||
char name[MAX_LINE_LENGTH];
|
||||
// printf("line: %s", line);
|
||||
if (!non_debugging_symbols)
|
||||
{
|
||||
if (strstr(line, "Non-debugging symbols:") != NULL)
|
||||
{
|
||||
non_debugging_symbols = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
char *token = strtok(line, " ");
|
||||
if (token != NULL)
|
||||
{
|
||||
sscanf(token, "%llx", &address);
|
||||
token = strtok(NULL, "\n");
|
||||
if (token != NULL)
|
||||
{
|
||||
strcpy(name, token);
|
||||
}
|
||||
// if name == ":", 跳过
|
||||
if (name[0] == ':')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
symbol_map[address] = std::string(name);
|
||||
}
|
||||
// 解析函数名和地址
|
||||
// if (sscanf(line, "%llx %s", &address, name) == 2)
|
||||
// {
|
||||
// // if name == ":", 跳过
|
||||
// if (name[0] == ':')
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// // printf("Name %s, Address %llx\n", name, address);
|
||||
// // name -> std::string
|
||||
// symbol_map[address] = std::string(name);
|
||||
// }
|
||||
char *token = strtok(line, " ");
|
||||
if (token != NULL) {
|
||||
sscanf(token, "%llx", &address);
|
||||
token = strtok(NULL, "\n");
|
||||
if (token != NULL) {
|
||||
strcpy(name, token);
|
||||
}
|
||||
// if name == ":", 跳过
|
||||
if (name[0] == ':') {
|
||||
continue;
|
||||
}
|
||||
symbol_map[address] = std::string(name);
|
||||
}
|
||||
// 解析函数名和地址
|
||||
// if (sscanf(line, "%llx %s", &address, name) == 2)
|
||||
// {
|
||||
// // if name == ":", 跳过
|
||||
// if (name[0] == ':')
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// // printf("Name %s, Address %llx\n", name, address);
|
||||
// // name -> std::string
|
||||
// symbol_map[address] = std::string(name);
|
||||
// }
|
||||
}
|
||||
|
||||
symbol s;
|
||||
symbol s;
|
||||
|
||||
// 插入范围到新的map
|
||||
auto it = symbol_map.begin();
|
||||
auto next_it = it;
|
||||
++next_it;
|
||||
// 插入范围到新的map
|
||||
auto it = symbol_map.begin();
|
||||
auto next_it = it;
|
||||
++next_it;
|
||||
|
||||
for (; next_it != symbol_map.end(); ++it, ++next_it)
|
||||
{
|
||||
s.start = it->first - file_base_addr;
|
||||
s.end = next_it->first - file_base_addr;
|
||||
s.ip = s.start;
|
||||
s.name = it->second;
|
||||
// printf("gdb name: %s, start: 0x%lx, end: 0x%lx\n", s.name.c_str(), s.start, s.end);
|
||||
ss.insert(s);
|
||||
}
|
||||
// 关闭 GDB 进程
|
||||
pclose(fp);
|
||||
//
|
||||
for (; next_it != symbol_map.end(); ++it, ++next_it) {
|
||||
s.start = it->first - file_base_addr;
|
||||
s.end = next_it->first - file_base_addr;
|
||||
s.ip = s.start;
|
||||
s.name = it->second;
|
||||
// printf("gdb name: %s, start: 0x%lx, end: 0x%lx\n", s.name.c_str(),
|
||||
// s.start, s.end);
|
||||
ss.insert(s);
|
||||
}
|
||||
// 关闭 GDB 进程
|
||||
pclose(fp);
|
||||
//
|
||||
}
|
||||
|
||||
bool get_symbol_from_elf(std::set<symbol> &ss, const char *path, size_t file_base_addr) {
|
||||
bool get_symbol_from_elf(std::set<symbol> &ss, const char *path,
|
||||
size_t file_base_addr) {
|
||||
static int first_init = 0;
|
||||
|
||||
if (!first_init) {
|
||||
@@ -450,7 +450,7 @@ bool get_symbol_from_elf(std::set<symbol> &ss, const char *path, size_t file_bas
|
||||
|
||||
if (str && strcmp(".symtab", str) == 0) { // .symtab section
|
||||
symtab_sec = sec;
|
||||
memcpy(&symtab_shdr, &shdr, sizeof(dynsym_shdr));
|
||||
memcpy(&symtab_shdr, &shdr, sizeof(dynsym_shdr));
|
||||
}
|
||||
if (str && strcmp(".dynsym", str) == 0) { // .dynsym section
|
||||
dynsym_sec = sec;
|
||||
@@ -480,22 +480,13 @@ bool get_symbol_from_elf(std::set<symbol> &ss, const char *path, size_t file_bas
|
||||
symbol_sections_ctx si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
if (symtab_sec) {
|
||||
get_symbols_in_section(&si.symtab, elf, symtab_sec, &symtab_shdr, is_reloc);
|
||||
get_symbols_in_section(&si.symtab, elf, symtab_sec, &symtab_shdr, is_reloc);
|
||||
} else {
|
||||
if (hdr.e_type != ET_DYN) { // no shared object
|
||||
// is_reloc = 1;
|
||||
// printf("stripped, path: %s\n", path);
|
||||
get_symbol_from_elf_gdb(ss, path, file_base_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the file attribute contains "stripped"
|
||||
// if (is_stripped(path))
|
||||
// {
|
||||
// printf("stripped, path: %s\n", path);
|
||||
// get_symbol_from_elf_gdb(ss, path);
|
||||
// return true;
|
||||
// }
|
||||
if (hdr.e_type != ET_DYN) { // no shared object
|
||||
// printf("stripped, path: %s\n", path);
|
||||
get_symbol_from_elf_gdb(ss, path, file_base_addr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (dynsym_sec) {
|
||||
get_symbols_in_section(&si.symtab_in_dynsym, elf, dynsym_sec, &dynsym_shdr,
|
||||
@@ -508,13 +499,6 @@ bool get_symbol_from_elf(std::set<symbol> &ss, const char *path, size_t file_bas
|
||||
get_all_symbols(ss, &si, elf);
|
||||
elf_end(elf);
|
||||
|
||||
// After getting all symbols from .symtab and .dynsym
|
||||
// Dwarf *dw = dwarf_begin(fd, DWARF_C_READ);
|
||||
// if (dw) {
|
||||
// get_debug_symbols(ss, dw);
|
||||
// dwarf_end(dw);
|
||||
// }
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "symbol.h"
|
||||
|
||||
bool get_symbol_from_elf(std::set<symbol> &ss, const char *path, size_t file_base_addr);
|
||||
bool get_symbol_from_elf(std::set<symbol> &ss, const char *path,
|
||||
size_t file_base_addr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ bool symbol_parser::load_pid_maps(int pid) {
|
||||
|
||||
bool symbol_parser::find_symbol_in_cache(int tgid, unsigned long addr,
|
||||
std::string &symbol) {
|
||||
std::map<int, std::map<unsigned long, std::string> >::const_iterator it_pid =
|
||||
std::map<int, std::map<unsigned long, std::string>>::const_iterator it_pid =
|
||||
symbols_cache.find(tgid);
|
||||
|
||||
if (it_pid != symbols_cache.end()) {
|
||||
@@ -153,7 +153,7 @@ bool symbol_parser::get_symbol_info(int pid, symbol &sym, elf_file &file) {
|
||||
|
||||
bool symbol_parser::putin_symbol_cache(int tgid, unsigned long addr,
|
||||
std::string &symbol) {
|
||||
std::map<int, std::map<unsigned long, std::string> >::const_iterator it_pid =
|
||||
std::map<int, std::map<unsigned long, std::string>>::const_iterator it_pid =
|
||||
symbols_cache.find(tgid);
|
||||
|
||||
if (it_pid == symbols_cache.end()) {
|
||||
@@ -188,8 +188,9 @@ bool search_symbol(const std::set<symbol> &ss, symbol &sym) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool symbol_parser::load_elf(pid_t pid, const elf_file &file, size_t file_base_addr) {
|
||||
std::map<elf_file, std::set<symbol> >::iterator it;
|
||||
bool symbol_parser::load_elf(pid_t pid, const elf_file &file,
|
||||
size_t file_base_addr) {
|
||||
std::map<elf_file, std::set<symbol>>::iterator it;
|
||||
it = file_symbols.find(file);
|
||||
std::set<symbol> tmp;
|
||||
std::set<symbol> &syms = tmp;
|
||||
@@ -206,7 +207,7 @@ bool symbol_parser::load_elf(pid_t pid, const elf_file &file, size_t file_base_a
|
||||
|
||||
bool symbol_parser::find_elf_symbol(symbol &sym, const elf_file &file, int pid,
|
||||
int pid_ns) {
|
||||
std::map<elf_file, std::set<symbol> >::iterator it;
|
||||
std::map<elf_file, std::set<symbol>>::iterator it;
|
||||
it = file_symbols.find(file);
|
||||
std::set<symbol> ss;
|
||||
// printf("search symbol1 0x%lx, base 0x%lx\n", sym.ip, sym.base);
|
||||
|
||||
@@ -7,141 +7,140 @@
|
||||
|
||||
#define INVALID_ADDR ((size_t)(-1))
|
||||
enum {
|
||||
NATIVE_TYPE = 0,
|
||||
JIT_TYPE = 1,
|
||||
UNKNOWN = 2,
|
||||
NATIVE_TYPE = 0,
|
||||
JIT_TYPE = 1,
|
||||
UNKNOWN = 2,
|
||||
};
|
||||
|
||||
struct elf_file {
|
||||
unsigned char elf_read_error;
|
||||
size_t eh_frame_hdr_offset;
|
||||
size_t fde_count;
|
||||
size_t table_data;
|
||||
std::string filename;
|
||||
int type;
|
||||
unsigned char elf_read_error;
|
||||
size_t eh_frame_hdr_offset;
|
||||
size_t fde_count;
|
||||
size_t table_data;
|
||||
std::string filename;
|
||||
int type;
|
||||
|
||||
elf_file(const std::string &name) : filename(name), type(NATIVE_TYPE) {
|
||||
elf_read_error = 0;
|
||||
eh_frame_hdr_offset = 0;
|
||||
fde_count = 0;
|
||||
table_data = 0;
|
||||
}
|
||||
elf_file(const std::string &name) : filename(name), type(NATIVE_TYPE) {
|
||||
elf_read_error = 0;
|
||||
eh_frame_hdr_offset = 0;
|
||||
fde_count = 0;
|
||||
table_data = 0;
|
||||
}
|
||||
|
||||
elf_file() :type(NATIVE_TYPE) {}
|
||||
elf_file() : type(NATIVE_TYPE) {}
|
||||
|
||||
void reset(const std::string &name) {
|
||||
filename = name;
|
||||
elf_read_error = 0;
|
||||
eh_frame_hdr_offset = 0;
|
||||
fde_count = 0;
|
||||
table_data = 0;
|
||||
}
|
||||
void reset(const std::string &name) {
|
||||
filename = name;
|
||||
elf_read_error = 0;
|
||||
eh_frame_hdr_offset = 0;
|
||||
fde_count = 0;
|
||||
table_data = 0;
|
||||
}
|
||||
|
||||
bool operator< (const elf_file &rhs) const {
|
||||
return filename < rhs.filename;
|
||||
}
|
||||
bool operator<(const elf_file &rhs) const { return filename < rhs.filename; }
|
||||
};
|
||||
|
||||
struct vma {
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t offset;
|
||||
size_t pc;
|
||||
int type;
|
||||
std::string name;
|
||||
struct {
|
||||
unsigned char elf_read_error;
|
||||
size_t eh_frame_hdr_offset;
|
||||
size_t fde_count;
|
||||
size_t table_data;
|
||||
};
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t offset;
|
||||
size_t pc;
|
||||
int type;
|
||||
std::string name;
|
||||
struct {
|
||||
unsigned char elf_read_error;
|
||||
size_t eh_frame_hdr_offset;
|
||||
size_t fde_count;
|
||||
size_t table_data;
|
||||
};
|
||||
|
||||
size_t map(size_t pc) {
|
||||
// printf("pc: %lx, start: %lx, offset: %lx\n", pc, start, offset);
|
||||
return pc - start + offset;
|
||||
}
|
||||
|
||||
void set_type(int t) { type = t; }
|
||||
|
||||
vma(size_t s, size_t e, size_t o, const std::string &n)
|
||||
:start(s), end(e), offset(o), pc(0), type(NATIVE_TYPE), name(n) {}
|
||||
|
||||
vma() : start(0), end(0), offset(0), pc(0), type(NATIVE_TYPE) {}
|
||||
|
||||
vma(size_t addr) : start(0), end(0), offset(0), pc(addr), type(NATIVE_TYPE) {}
|
||||
|
||||
bool operator<(const vma &vm) {
|
||||
return vm.start < vm.pc;
|
||||
}
|
||||
|
||||
vma &operator=(const vma &vm) {
|
||||
if (this == &vm) {
|
||||
return *this;
|
||||
}
|
||||
start = vm.start;
|
||||
end = vm.end;
|
||||
offset = vm.offset;
|
||||
name = vm.name;
|
||||
return *this;
|
||||
size_t map(size_t pc) {
|
||||
// printf("pc: %lx, start: %lx, offset: %lx\n", pc, start, offset);
|
||||
return pc - start + offset;
|
||||
}
|
||||
|
||||
void set_type(int t) { type = t; }
|
||||
|
||||
vma(size_t s, size_t e, size_t o, const std::string &n)
|
||||
: start(s), end(e), offset(o), pc(0), type(NATIVE_TYPE), name(n) {}
|
||||
|
||||
vma() : start(0), end(0), offset(0), pc(0), type(NATIVE_TYPE) {}
|
||||
|
||||
vma(size_t addr) : start(0), end(0), offset(0), pc(addr), type(NATIVE_TYPE) {}
|
||||
|
||||
bool operator<(const vma &vm) { return vm.start < vm.pc; }
|
||||
|
||||
vma &operator=(const vma &vm) {
|
||||
if (this == &vm) {
|
||||
return *this;
|
||||
}
|
||||
start = vm.start;
|
||||
end = vm.end;
|
||||
offset = vm.offset;
|
||||
name = vm.name;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct symbol {
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t ip;
|
||||
size_t base;
|
||||
std::string name;
|
||||
size_t start;
|
||||
size_t end;
|
||||
size_t ip;
|
||||
size_t base;
|
||||
std::string name;
|
||||
|
||||
symbol() :start(0), end(0), ip(0) , base(0) {}
|
||||
symbol(size_t pc) :start(0), end(0), ip(pc) {}
|
||||
symbol() : start(0), end(0), ip(0), base(0) {}
|
||||
symbol(size_t pc) : start(0), end(0), ip(pc) {}
|
||||
|
||||
void reset(size_t va) { start = end = 0; ip = va; }
|
||||
bool operator< (const symbol &sym) const {
|
||||
return sym.ip < start;
|
||||
}
|
||||
void reset(size_t va) {
|
||||
start = end = 0;
|
||||
ip = va;
|
||||
}
|
||||
bool operator<(const symbol &sym) const { return sym.ip < start; }
|
||||
|
||||
bool operator> (const symbol &sym) const {
|
||||
return sym.ip > end;
|
||||
}
|
||||
bool operator>(const symbol &sym) const { return sym.ip > end; }
|
||||
};
|
||||
|
||||
class symbol_parser {
|
||||
private:
|
||||
typedef std::map<size_t, vma> proc_vma;
|
||||
typedef std::map<size_t, vma> proc_vma;
|
||||
|
||||
std::map<elf_file, std::set<symbol>> file_symbols;
|
||||
std::map<int, std::set<symbol>> java_symbols;
|
||||
std::set<symbol> kernel_symbols;
|
||||
std::map<int, proc_vma> machine_vma;
|
||||
std::set<int> java_procs;
|
||||
std::map<int, std::map<unsigned long, std::string>> symbols_cache;
|
||||
|
||||
std::map<elf_file, std::set<symbol> > file_symbols;
|
||||
std::map<int, std::set<symbol> > java_symbols;
|
||||
std::set<symbol> kernel_symbols;
|
||||
std::map<int, proc_vma> machine_vma;
|
||||
std::set<int> java_procs;
|
||||
std::map<int, std::map<unsigned long, std::string> > symbols_cache;
|
||||
public:
|
||||
bool load_kernel();
|
||||
std::set<int>& get_java_procs() { return java_procs; }
|
||||
bool load_kernel();
|
||||
std::set<int> &get_java_procs() { return java_procs; }
|
||||
|
||||
bool find_kernel_symbol(symbol &sym);
|
||||
bool find_elf_symbol(symbol &sym, const elf_file &file, int pid, int pid_ns);
|
||||
bool find_java_symbol(symbol &sym, int pid, int pid_ns);
|
||||
bool find_kernel_symbol(symbol &sym);
|
||||
bool find_elf_symbol(symbol &sym, const elf_file &file, int pid, int pid_ns);
|
||||
bool find_java_symbol(symbol &sym, int pid, int pid_ns);
|
||||
|
||||
bool get_symbol_info(int pid, symbol &sym, elf_file &file);
|
||||
bool get_symbol_info(int pid, symbol &sym, elf_file &file);
|
||||
|
||||
bool find_vma(pid_t pid, vma &vm);
|
||||
vma* find_vma(pid_t pid, size_t pc);
|
||||
void clear_symbol_info(int);
|
||||
bool add_pid_maps(int pid, size_t start, size_t end, size_t offset, const char *name);
|
||||
bool find_vma(pid_t pid, vma &vm);
|
||||
vma *find_vma(pid_t pid, size_t pc);
|
||||
void clear_symbol_info(int);
|
||||
bool add_pid_maps(int pid, size_t start, size_t end, size_t offset,
|
||||
const char *name);
|
||||
|
||||
bool find_symbol_in_cache(int tgid, unsigned long addr, std::string &symbol);
|
||||
bool putin_symbol_cache(int tgid, unsigned long addr, std::string &symbol);
|
||||
bool find_symbol_in_cache(int tgid, unsigned long addr, std::string &symbol);
|
||||
bool putin_symbol_cache(int tgid, unsigned long addr, std::string &symbol);
|
||||
|
||||
void dump(void);
|
||||
|
||||
void dump(void);
|
||||
private:
|
||||
bool load_pid_maps(int pid);
|
||||
bool load_elf(pid_t pid, const elf_file& file, size_t file_base_addr);
|
||||
bool load_perf_map(int pid, int pid_ns);
|
||||
bool load_pid_maps(int pid);
|
||||
bool load_elf(pid_t pid, const elf_file &file, size_t file_base_addr);
|
||||
bool load_perf_map(int pid, int pid_ns);
|
||||
|
||||
public:
|
||||
int java_only;
|
||||
int user_symbol;
|
||||
int java_only;
|
||||
int user_symbol;
|
||||
};
|
||||
|
||||
extern symbol_parser g_symbol_parser;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -15,21 +15,20 @@
|
||||
#include "ucli.h"
|
||||
#include "unwind.h"
|
||||
|
||||
|
||||
#define BUF_LEN 4096
|
||||
#define WHITESPACE " \t\n\r"
|
||||
#define WHITESPACE " \t\n\r"
|
||||
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
|
||||
#define streq(a,b) (strcmp((a),(b)) == 0)
|
||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||
|
||||
unsigned long run_in_host = 0;
|
||||
|
||||
using namespace std;
|
||||
|
||||
class pid_cmdline {
|
||||
private:
|
||||
private:
|
||||
std::map<int, std::string> cmdlines;
|
||||
|
||||
public:
|
||||
public:
|
||||
void clear(void);
|
||||
std::string &get_pid_cmdline(int pid);
|
||||
};
|
||||
@@ -71,14 +70,14 @@ long diag_call_ioctl(unsigned long request, unsigned long arg) {
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
@@ -94,7 +93,7 @@ err:
|
||||
|
||||
static int unwind_frame_callback(struct unwind_entry *entry, void *arg) {
|
||||
symbol sym;
|
||||
std::string symbol; // Use std::string instead of string
|
||||
std::string symbol; // Use std::string instead of string
|
||||
elf_file file;
|
||||
|
||||
sym.reset(entry->ip);
|
||||
@@ -135,9 +134,12 @@ void extract_variant_buffer(char *buf, unsigned int len,
|
||||
|
||||
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;
|
||||
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);
|
||||
@@ -171,29 +173,28 @@ void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
// 根据 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";
|
||||
case 0:
|
||||
return "USER_TASK";
|
||||
case 1:
|
||||
return "SYSTEM_TASK";
|
||||
case 2:
|
||||
return "IDLE_TASK";
|
||||
default:
|
||||
return "UNKNOWN_TASK";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *user_mode_str(int user_mode) {
|
||||
switch (user_mode) {
|
||||
case 1:
|
||||
return "USER MODE";
|
||||
case 0:
|
||||
return "SYSTEM MODE";
|
||||
default:
|
||||
return "UNKNOWN MODE";
|
||||
case 1:
|
||||
return "USER MODE";
|
||||
case 0:
|
||||
return "SYSTEM MODE";
|
||||
default:
|
||||
return "UNKNOWN MODE";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,9 +204,9 @@ static const char *user_mode_str(int user_mode) {
|
||||
// #define TASK_UNINTERRUPTIBLE 0x0002 // 等待事件阻塞 不可信号唤醒
|
||||
// #define __TASK_STOPPED 0x0004 // 暂停执行
|
||||
// #define __TASK_TRACED 0x0008 //调试状态
|
||||
// #define TASK_PARKED 0x0040 // parked 状态,暂停执行 保留在 cpu 但不被调度
|
||||
// #define TASK_DEAD 0x0080 // dead
|
||||
// #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
|
||||
// #define TASK_PARKED 0x0040 // parked 状态,暂停执行 保留在 cpu
|
||||
// 但不被调度 #define TASK_DEAD 0x0080 // dead #define
|
||||
// TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
|
||||
// #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
|
||||
// #define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
|
||||
// static const char *state_str(int __state){
|
||||
@@ -215,48 +216,61 @@ static const char *user_mode_str(int user_mode) {
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define TASK_RUNNING 0x0000
|
||||
#define TASK_INTERRUPTIBLE 0x0001
|
||||
#define TASK_UNINTERRUPTIBLE 0x0002
|
||||
#define __TASK_STOPPED 0x0004
|
||||
#define __TASK_TRACED 0x0008
|
||||
#define TASK_PARKED 0x0040
|
||||
#define TASK_DEAD 0x0080
|
||||
#define TASK_WAKEKILL 0x0100
|
||||
#define TASK_NOLOAD 0x0200
|
||||
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
|
||||
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
|
||||
#define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
|
||||
#define TASK_RUNNING 0x0000
|
||||
#define TASK_INTERRUPTIBLE 0x0001
|
||||
#define TASK_UNINTERRUPTIBLE 0x0002
|
||||
#define __TASK_STOPPED 0x0004
|
||||
#define __TASK_TRACED 0x0008
|
||||
#define TASK_PARKED 0x0040
|
||||
#define TASK_DEAD 0x0080
|
||||
#define TASK_WAKEKILL 0x0100
|
||||
#define TASK_NOLOAD 0x0200
|
||||
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
|
||||
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
|
||||
#define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
|
||||
|
||||
std::string state_str(int __state){
|
||||
std::vector<std::string> states;
|
||||
std::string state_str(int __state) {
|
||||
std::vector<std::string> states;
|
||||
|
||||
if (__state == TASK_RUNNING) states.push_back("TASK_RUNNING");
|
||||
// if (__state & TASK_RUNNING) states.push_back("TASK_RUNNING");
|
||||
if (__state & TASK_INTERRUPTIBLE) states.push_back("TASK_INTERRUPTIBLE");
|
||||
if (__state & TASK_UNINTERRUPTIBLE) states.push_back("TASK_UNINTERRUPTIBLE");
|
||||
if (__state & __TASK_STOPPED) states.push_back("__TASK_STOPPED");
|
||||
if (__state & __TASK_TRACED) states.push_back("__TASK_TRACED");
|
||||
if (__state & TASK_PARKED) states.push_back("TASK_PARKED");
|
||||
if (__state & TASK_DEAD) states.push_back("TASK_DEAD");
|
||||
if (__state == TASK_KILLABLE) states.push_back("TASK_KILLABLE");
|
||||
if (__state == TASK_STOPPED) states.push_back("TASK_STOPPED");
|
||||
if (__state == TASK_IDLE) states.push_back("TASK_IDLE");
|
||||
if (__state == TASK_RUNNING)
|
||||
states.push_back("TASK_RUNNING");
|
||||
// if (__state & TASK_RUNNING) states.push_back("TASK_RUNNING");
|
||||
if (__state & TASK_INTERRUPTIBLE)
|
||||
states.push_back("TASK_INTERRUPTIBLE");
|
||||
if (__state & TASK_UNINTERRUPTIBLE)
|
||||
states.push_back("TASK_UNINTERRUPTIBLE");
|
||||
if (__state & __TASK_STOPPED)
|
||||
states.push_back("__TASK_STOPPED");
|
||||
if (__state & __TASK_TRACED)
|
||||
states.push_back("__TASK_TRACED");
|
||||
if (__state & TASK_PARKED)
|
||||
states.push_back("TASK_PARKED");
|
||||
if (__state & TASK_DEAD)
|
||||
states.push_back("TASK_DEAD");
|
||||
if (__state == TASK_KILLABLE)
|
||||
states.push_back("TASK_KILLABLE");
|
||||
if (__state == TASK_STOPPED)
|
||||
states.push_back("TASK_STOPPED");
|
||||
if (__state == TASK_IDLE)
|
||||
states.push_back("TASK_IDLE");
|
||||
|
||||
std::string result;
|
||||
for (const auto& state : states) {
|
||||
if (!result.empty()) result += " | ";
|
||||
result += state;
|
||||
}
|
||||
std::string result;
|
||||
for (const auto &state : states) {
|
||||
if (!result.empty())
|
||||
result += " | ";
|
||||
result += state;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void diag_printf_kern_stack(kern_stack_detail *kern_stack) {
|
||||
@@ -284,7 +298,8 @@ void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
|
||||
|
||||
printf(" PROC CHAINS:\n");
|
||||
for (i = 0; i < PROCESS_CHAINS_COUNT; i++) {
|
||||
if (proc_chains->chains[i][0] == 0) break;
|
||||
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)
|
||||
@@ -300,155 +315,151 @@ void diag_printf_proc_chains(proc_chains_detail *proc_chains) {
|
||||
}
|
||||
|
||||
int is_pid_1_has_environ(const char *field) {
|
||||
bool done = false;
|
||||
FILE *f = NULL;
|
||||
int r = 0;
|
||||
size_t l;
|
||||
bool done = false;
|
||||
FILE *f = NULL;
|
||||
int r = 0;
|
||||
size_t l;
|
||||
|
||||
assert(field);
|
||||
assert(field);
|
||||
|
||||
f = fopen("/proc/1/environ", "re");
|
||||
if (!f)
|
||||
return 0;
|
||||
f = fopen("/proc/1/environ", "re");
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
(void)__fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
l = strlen(field);
|
||||
l = strlen(field);
|
||||
|
||||
do {
|
||||
char line[BUF_LEN];
|
||||
size_t i;
|
||||
do {
|
||||
char line[BUF_LEN];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(line)-1; i++) {
|
||||
int c;
|
||||
for (i = 0; i < sizeof(line) - 1; i++) {
|
||||
int c;
|
||||
|
||||
c = getc(f);
|
||||
if ((c == EOF)) {
|
||||
done = true;
|
||||
break;
|
||||
} else if (c == 0)
|
||||
break;
|
||||
c = getc(f);
|
||||
if ((c == EOF)) {
|
||||
done = true;
|
||||
break;
|
||||
} else if (c == 0)
|
||||
break;
|
||||
|
||||
line[i] = c;
|
||||
}
|
||||
line[i] = 0;
|
||||
line[i] = c;
|
||||
}
|
||||
line[i] = 0;
|
||||
|
||||
if (strneq(line, field, l) && line[l] == '=') {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
if (strneq(line, field, l) && line[l] == '=') {
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
} while (!done);
|
||||
} while (!done);
|
||||
|
||||
out:
|
||||
fclose(f);
|
||||
return r;
|
||||
fclose(f);
|
||||
return r;
|
||||
}
|
||||
|
||||
enum {
|
||||
RUN_IN_HOST = 0,
|
||||
RUN_IN_CONTAINER
|
||||
};
|
||||
enum { RUN_IN_HOST = 0, RUN_IN_CONTAINER };
|
||||
|
||||
int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) {
|
||||
char status[BUF_LEN] = {0};
|
||||
char *t, *f;
|
||||
size_t len;
|
||||
int r;
|
||||
int get_proc_field(const char *filename, const char *pattern,
|
||||
const char *terminator, char **field) {
|
||||
char status[BUF_LEN] = {0};
|
||||
char *t, *f;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
assert(terminator);
|
||||
assert(filename);
|
||||
assert(pattern);
|
||||
assert(field);
|
||||
assert(terminator);
|
||||
assert(filename);
|
||||
assert(pattern);
|
||||
assert(field);
|
||||
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = read(fd, &status, BUF_LEN - 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = read(fd, &status, BUF_LEN - 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
t = status;
|
||||
t = status;
|
||||
|
||||
do {
|
||||
bool pattern_ok;
|
||||
do {
|
||||
bool pattern_ok;
|
||||
|
||||
do {
|
||||
t = strstr(t, pattern);
|
||||
if (!t)
|
||||
return -ENOENT;
|
||||
do {
|
||||
t = strstr(t, pattern);
|
||||
if (!t)
|
||||
return -ENOENT;
|
||||
|
||||
/* Check that pattern occurs in beginning of line. */
|
||||
pattern_ok = (t == status || t[-1] == '\n');
|
||||
/* Check that pattern occurs in beginning of line. */
|
||||
pattern_ok = (t == status || t[-1] == '\n');
|
||||
|
||||
t += strlen(pattern);
|
||||
t += strlen(pattern);
|
||||
|
||||
} while (!pattern_ok);
|
||||
} while (!pattern_ok);
|
||||
|
||||
t += strspn(t, " \t");
|
||||
if (!*t)
|
||||
return -ENOENT;
|
||||
t += strspn(t, " \t");
|
||||
if (!*t)
|
||||
return -ENOENT;
|
||||
|
||||
} while (*t != ':');
|
||||
} while (*t != ':');
|
||||
|
||||
t++;
|
||||
t++;
|
||||
|
||||
if (*t) {
|
||||
t += strspn(t, " \t");
|
||||
|
||||
if (*t) {
|
||||
t += strspn(t, " \t");
|
||||
/* Also skip zeros, because when this is used for
|
||||
* capabilities, we don't want the zeros. This way the
|
||||
* same capability set always maps to the same string,
|
||||
* irrespective of the total capability set size. For
|
||||
* other numbers it shouldn't matter. */
|
||||
t += strspn(t, "0");
|
||||
/* Back off one char if there's nothing but whitespace
|
||||
and zeros */
|
||||
if (!*t || isspace(*t))
|
||||
t--;
|
||||
}
|
||||
|
||||
/* Also skip zeros, because when this is used for
|
||||
* capabilities, we don't want the zeros. This way the
|
||||
* same capability set always maps to the same string,
|
||||
* irrespective of the total capability set size. For
|
||||
* other numbers it shouldn't matter. */
|
||||
t += strspn(t, "0");
|
||||
/* Back off one char if there's nothing but whitespace
|
||||
and zeros */
|
||||
if (!*t || isspace(*t))
|
||||
t--;
|
||||
}
|
||||
len = strcspn(t, terminator);
|
||||
|
||||
len = strcspn(t, terminator);
|
||||
f = strndup(t, len);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
f = strndup(t, len);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
*field = f;
|
||||
return 0;
|
||||
*field = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int detect_container_by_pid_2(void) {
|
||||
char *s = NULL;
|
||||
int r;
|
||||
char *s = NULL;
|
||||
int r;
|
||||
|
||||
r = get_proc_field("/proc/2/status", "PPid", WHITESPACE, &s);
|
||||
if (r >= 0) {
|
||||
if (streq(s, "0"))
|
||||
r = RUN_IN_HOST;
|
||||
else
|
||||
r = RUN_IN_CONTAINER;
|
||||
} else if (r == -ENOENT)
|
||||
r = RUN_IN_CONTAINER;
|
||||
else {
|
||||
printf("Failed to read /proc/2/status: %d\n", r);
|
||||
r = RUN_IN_HOST;
|
||||
}
|
||||
r = get_proc_field("/proc/2/status", "PPid", WHITESPACE, &s);
|
||||
if (r >= 0) {
|
||||
if (streq(s, "0"))
|
||||
r = RUN_IN_HOST;
|
||||
else
|
||||
r = RUN_IN_CONTAINER;
|
||||
} else if (r == -ENOENT)
|
||||
r = RUN_IN_CONTAINER;
|
||||
else {
|
||||
printf("Failed to read /proc/2/status: %d\n", r);
|
||||
r = RUN_IN_HOST;
|
||||
}
|
||||
|
||||
free(s);
|
||||
return r;
|
||||
free(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
int check_in_host(void)
|
||||
{
|
||||
int r;
|
||||
int check_in_host(void) {
|
||||
int r;
|
||||
|
||||
if (is_pid_1_has_environ("container"))
|
||||
r = RUN_IN_CONTAINER;
|
||||
else
|
||||
r = detect_container_by_pid_2();
|
||||
if (is_pid_1_has_environ("container"))
|
||||
r = RUN_IN_CONTAINER;
|
||||
else
|
||||
r = detect_container_by_pid_2();
|
||||
|
||||
return r == RUN_IN_HOST;
|
||||
return r == RUN_IN_HOST;
|
||||
}
|
||||
|
||||
@@ -114,8 +114,7 @@ static int task_info_extract(void *buf, unsigned int len, void *) {
|
||||
.name, // Assuming name is a null-terminated string
|
||||
vm_record->threshold_record[i].ptr,
|
||||
vm_record->threshold_record[i].threshold,
|
||||
vm_record->threshold_record[i].true_value
|
||||
);
|
||||
vm_record->threshold_record[i].true_value);
|
||||
}
|
||||
break;
|
||||
case VARIABLE_MONITOR_TASK_TYPE:
|
||||
@@ -126,7 +125,7 @@ static int task_info_extract(void *buf, unsigned int len, void *) {
|
||||
|
||||
printf("##CGROUP:[%s] %d [%03d] [%s] state: %d\n",
|
||||
tsk_info->task.cgroup_buf, tsk_info->task.pid, seq,
|
||||
state_str(tsk_info->task.state).c_str(),tsk_info->task.state);
|
||||
state_str(tsk_info->task.state).c_str(), tsk_info->task.state);
|
||||
|
||||
printk_task_brief(&tsk_info->task);
|
||||
// diag_printf_raw_stack(tsk_info->task.tgid, tsk_info->task.container_tgid,
|
||||
@@ -141,12 +140,14 @@ static int task_info_extract(void *buf, unsigned int len, void *) {
|
||||
// diag_printf_kern_stack(&tsk_info->kern_stack);
|
||||
|
||||
// system task no need print raw_stack
|
||||
if (tsk_info->task.sys_task == 1){
|
||||
diag_printf_kern_stack(&tsk_info->kern_stack);
|
||||
}else{
|
||||
diag_printf_raw_stack(run_in_host ? tsk_info->task.tgid : tsk_info->task.container_tgid,
|
||||
tsk_info->task.container_tgid, tsk_info->task.comm, &tsk_info->raw_stack);
|
||||
diag_printf_kern_stack(&tsk_info->kern_stack);
|
||||
if (tsk_info->task.sys_task == 1) {
|
||||
diag_printf_kern_stack(&tsk_info->kern_stack);
|
||||
} else {
|
||||
diag_printf_raw_stack(run_in_host ? tsk_info->task.tgid
|
||||
: tsk_info->task.container_tgid,
|
||||
tsk_info->task.container_tgid, tsk_info->task.comm,
|
||||
&tsk_info->raw_stack);
|
||||
diag_printf_kern_stack(&tsk_info->kern_stack);
|
||||
}
|
||||
|
||||
printf("#* 0xffffffffffffff %s (UNKNOWN)\n", tsk_info->task.comm);
|
||||
@@ -161,17 +162,19 @@ static int task_info_extract(void *buf, unsigned int len, void *) {
|
||||
|
||||
printf("##CGROUP:[%s] %d [%03d] [%s] state: %d\n",
|
||||
tsk_info_system->task.cgroup_buf, tsk_info_system->task.pid, seq,
|
||||
state_str(tsk_info_system->task.state).c_str(),tsk_info_system->task.state);
|
||||
state_str(tsk_info_system->task.state).c_str(),
|
||||
tsk_info_system->task.state);
|
||||
|
||||
printk_task_brief(&tsk_info_system->task);
|
||||
// system task no need print raw_stack
|
||||
diag_printf_kern_stack(&tsk_info_system->kern_stack);
|
||||
printf("#* 0xffffffffffffff %s (UNKNOWN)\n", tsk_info_system->task.comm);
|
||||
printf("#* 0xffffffffffffff %s (UNKNOWN)\n",
|
||||
tsk_info_system->task.comm);
|
||||
// diag_printf_proc_chains(&tsk_info_system->proc_chains);
|
||||
printf("##\n");
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -248,7 +251,7 @@ int main(int argc, char *argv[]) {
|
||||
run_in_host = check_in_host();
|
||||
printf("run_in_host: %d\n", run_in_host);
|
||||
|
||||
for (int i = 0; i < argc; i++){
|
||||
for (int i = 0; i < argc; i++) {
|
||||
printf("argv[%d]: %s\n", i, argv[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef UAPI_H
|
||||
#define UAPI_H
|
||||
|
||||
#include <asm/ptrace.h> // struct pt_regs
|
||||
#include <asm/ptrace.h> // struct pt_regs
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <cstddef> // size_t
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
@@ -20,25 +20,25 @@
|
||||
#define DEVICE "/dev/variable_monitor"
|
||||
#define DEVICE_BAK "/host/dev/variable_monitor"
|
||||
|
||||
#define CGROUP_NAME_LEN 32 // max length of cgroup name
|
||||
#define TASK_COMM_LEN 16 // max length of task name
|
||||
#define CGROUP_NAME_LEN 32 // max length of cgroup name
|
||||
#define TASK_COMM_LEN 16 // max length of task name
|
||||
|
||||
#define BACKTRACE_DEPTH 30 // max depth of backtrace
|
||||
#define BACKTRACE_DEPTH 30 // max depth of backtrace
|
||||
|
||||
#define PROCESS_CHAINS_COUNT 10 // max count of process chains
|
||||
#define PROCESS_ARGV_LEN 128 // max length of process argv
|
||||
#define PROCESS_CHAINS_COUNT 10 // max count of process chains
|
||||
#define PROCESS_ARGV_LEN 128 // max length of process argv
|
||||
|
||||
#define MAX_NAME_LEN (127) // max name length
|
||||
#define TIMER_MAX_WATCH_NUM (32) // A timer max watch number at once time
|
||||
#define MAX_NAME_LEN (127) // max name length
|
||||
#define TIMER_MAX_WATCH_NUM (32) // A timer max watch number at once time
|
||||
|
||||
#define DIAG_USER_STACK_SIZE (16 * 1024)
|
||||
|
||||
typedef struct {
|
||||
pid_t task_id; // current process id
|
||||
char name[MAX_NAME_LEN + 1]; // name
|
||||
void *ptr; // virtual address
|
||||
long long threshold; // threshold value
|
||||
long long true_value; // target true value
|
||||
pid_t task_id; // current process id
|
||||
char name[MAX_NAME_LEN + 1]; // name
|
||||
void *ptr; // virtual address
|
||||
long long threshold; // threshold value
|
||||
long long true_value; // target true value
|
||||
} threshold;
|
||||
|
||||
typedef struct {
|
||||
@@ -92,9 +92,9 @@ typedef struct {
|
||||
} raw_stack_detail;
|
||||
|
||||
typedef struct {
|
||||
unsigned int full_argv[PROCESS_CHAINS_COUNT]; //
|
||||
char chains[PROCESS_CHAINS_COUNT][PROCESS_ARGV_LEN]; // process chains argv
|
||||
unsigned int tgid[PROCESS_CHAINS_COUNT]; // process chains tgid
|
||||
unsigned int full_argv[PROCESS_CHAINS_COUNT]; //
|
||||
char chains[PROCESS_CHAINS_COUNT][PROCESS_ARGV_LEN]; // process chains argv
|
||||
unsigned int tgid[PROCESS_CHAINS_COUNT]; // process chains tgid
|
||||
} proc_chains_detail;
|
||||
|
||||
// most important struct
|
||||
@@ -102,10 +102,10 @@ typedef struct {
|
||||
int et_type;
|
||||
unsigned long id;
|
||||
unsigned long long tv;
|
||||
task_detail task; // brief
|
||||
task_detail task; // brief
|
||||
// user_stack_detail user_stack; // user stack
|
||||
kern_stack_detail kern_stack; // kernel stack
|
||||
proc_chains_detail proc_chains; // process chains argv
|
||||
kern_stack_detail kern_stack; // kernel stack
|
||||
proc_chains_detail proc_chains; // process chains argv
|
||||
raw_stack_detail raw_stack;
|
||||
} variable_monitor_task;
|
||||
|
||||
@@ -113,8 +113,8 @@ typedef struct {
|
||||
int et_type;
|
||||
unsigned long id;
|
||||
unsigned long long tv;
|
||||
task_detail task; // brief
|
||||
kern_stack_detail kern_stack; // kernel stack
|
||||
task_detail task; // brief
|
||||
kern_stack_detail kern_stack; // kernel stack
|
||||
} variable_monitor_task_system;
|
||||
|
||||
#define DIAG_VARIANT_BUFFER_HEAD_MAGIC_SEALED 197612031122
|
||||
|
||||
@@ -20,16 +20,19 @@ static std::string unknow_symbol("UNKNOWN");
|
||||
// }
|
||||
|
||||
// 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)) {
|
||||
// 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);
|
||||
// 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);
|
||||
// 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;
|
||||
@@ -39,7 +42,8 @@ static std::string unknow_symbol("UNKNOWN");
|
||||
*/
|
||||
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;
|
||||
if (id < 0 || id > 2)
|
||||
return -EINVAL;
|
||||
|
||||
*valp = regs->regs[id];
|
||||
return 0;
|
||||
@@ -76,12 +80,13 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
|
||||
while (!ret && (unw_step(&c) > 0)) {
|
||||
unw_word_t ip;
|
||||
|
||||
unw_get_reg(&c, UNW_REG_IP, &ip); // get IP from current step;
|
||||
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;
|
||||
if (loops >= 50)
|
||||
break;
|
||||
}
|
||||
|
||||
unw_destroy_addr_space(addr_space);
|
||||
@@ -99,35 +104,16 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, symbol_parser *sp,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!data->user_regs.regs) return -EINVAL;
|
||||
if (!data->user_regs.regs)
|
||||
return -EINVAL;
|
||||
|
||||
ret = reg_value(&ip, &data->user_regs, PERF_REG_IP);
|
||||
if (ret) return ret;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = entry(ip, pid, pid_ns, cb, arg);
|
||||
if (ret) return -ENOMEM;
|
||||
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("##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);
|
||||
// }
|
||||
}
|
||||
@@ -103,7 +103,8 @@ struct unwind_info {
|
||||
};
|
||||
|
||||
// extern "C" void diag_printf_raw_stack(int pid, int ns_pid, const char *comm,
|
||||
// raw_stack_detail *raw_stack, int attach);
|
||||
// raw_stack_detail *raw_stack, int
|
||||
// attach);
|
||||
int unwind__get_entries(unwind_entry_cb_t cb, void *arg, symbol_parser *sp,
|
||||
int pid, int pid_ns, struct perf_sample *data);
|
||||
#endif /* __UNWIND_H */
|
||||
|
||||
Reference in New Issue
Block a user