From fddda83a880748d62dce1cfb1a3e13e09f0e0ba7 Mon Sep 17 00:00:00 2001 From: John Doe Date: Mon, 11 Dec 2023 10:47:15 +0000 Subject: [PATCH] when .symtab is null, use gdb info function --- source/ucli/elf.cc | 125 ++++++++++++++++++++++++++++++---------- source/ucli/elf.h | 2 +- source/ucli/symbol.cc | 12 +++- source/ucli/symbol.h | 6 +- source/ucli/ucli-lib.cc | 3 +- 5 files changed, 110 insertions(+), 38 deletions(-) diff --git a/source/ucli/elf.cc b/source/ucli/elf.cc index af4f801..3f64a99 100644 --- a/source/ucli/elf.cc +++ b/source/ucli/elf.cc @@ -163,7 +163,7 @@ static void __get_symbol_without_plt(std::set &ss, sym_section_ctx *tab, s.end = s.start + sym.st_size; s.ip = s.start; s.name = sym_name; - printf("name: %s, start: %lx, end: %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 +220,7 @@ static void __get_plt_symbol(std::set &ss, symbol_sections_ctx *si, s.end = s.start + si->dynsymtab.plt_entsize; s.ip = s.start; s.name = sym_name; - printf("name: %s, start: %lx, end: %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); } } @@ -282,7 +282,7 @@ static void get_all_symbols(std::set &ss, symbol_sections_ctx *si, bool is_stripped(const char* path) { char command[256]; - snprintf(command, sizeof(command), "file %s", path); + // snprintf(command, sizeof(command), "file %s", path); FILE* fp = popen(command, "r"); if (fp == NULL) { @@ -298,38 +298,92 @@ bool is_stripped(const char* path) { } #define MAX_LINE_LENGTH 1024 -void get_symbol_from_elf_gdb(std::set &ss, const char *path) { +void get_symbol_from_elf_gdb(std::set &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); + 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 的输出 - while (fgets(line, sizeof(line), fp) != NULL) { - unsigned long address; - char name[MAX_LINE_LENGTH]; - - // 解析函数名和地址 - if (sscanf(line, "%lx %s", &address, name) == 2) { - printf("Name: %s, Address: %lx\n", name, address); + if (fp == NULL) + { + perror("popen"); + return; } - } - // 关闭 GDB 进程 - pclose(fp); - // + bool non_debugging_symbols = false; + std::map 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); + // } + } + + symbol s; + + // 插入范围到新的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); + // } -bool get_symbol_from_elf(std::set &ss, const char *path) { +bool get_symbol_from_elf(std::set &ss, const char *path, size_t file_base_addr) { static int first_init = 0; if (!first_init) { @@ -340,12 +394,6 @@ bool get_symbol_from_elf(std::set &ss, const char *path) { int is_reloc = 0; elf_version(EV_CURRENT); - // Check if the file attribute contains "stripped" - if (is_stripped(path)){ - get_symbol_from_elf_gdb(ss, path); - return true; - } - int fd = open(path, O_RDONLY); Elf *elf = elf_begin(fd, ELF_C_READ, NULL); // 指向elf文件的指针 @@ -432,7 +480,22 @@ bool get_symbol_from_elf(std::set &ss, const char *path) { 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 (dynsym_sec) { get_symbols_in_section(&si.symtab_in_dynsym, elf, dynsym_sec, &dynsym_shdr, diff --git a/source/ucli/elf.h b/source/ucli/elf.h index 7b4c5e9..df33f91 100644 --- a/source/ucli/elf.h +++ b/source/ucli/elf.h @@ -6,6 +6,6 @@ #include "symbol.h" -bool get_symbol_from_elf(std::set &ss, const char *path); +bool get_symbol_from_elf(std::set &ss, const char *path, size_t file_base_addr); #endif diff --git a/source/ucli/symbol.cc b/source/ucli/symbol.cc index c07cfe2..0db5426 100644 --- a/source/ucli/symbol.cc +++ b/source/ucli/symbol.cc @@ -145,6 +145,7 @@ bool symbol_parser::get_symbol_info(int pid, symbol &sym, elf_file &file) { file.reset(area.name); if (file.type != JIT_TYPE) { sym.reset(area.map(sym.ip)); + sym.base = area.start; // add base address } return true; @@ -173,6 +174,7 @@ bool symbol_parser::putin_symbol_cache(int tgid, unsigned long addr, } bool search_symbol(const std::set &ss, symbol &sym) { + // printf("search symbol2 0x%lx\n", sym.ip); std::set::const_iterator it = ss.find(sym); if (it != ss.end()) { @@ -186,7 +188,7 @@ bool search_symbol(const std::set &ss, symbol &sym) { return false; } -bool symbol_parser::load_elf(pid_t pid, const elf_file &file) { +bool symbol_parser::load_elf(pid_t pid, const elf_file &file, size_t file_base_addr) { std::map >::iterator it; it = file_symbols.find(file); std::set tmp; @@ -194,7 +196,8 @@ bool symbol_parser::load_elf(pid_t pid, const elf_file &file) { if (it != file_symbols.end()) { return true; } - if (get_symbol_from_elf(syms, file.filename.c_str())) { + if (get_symbol_from_elf(syms, file.filename.c_str(), file_base_addr)) { + // printf("load elf %s\n", file.filename.c_str()); file_symbols.insert(make_pair(file, std::move(syms))); return true; } @@ -206,10 +209,13 @@ bool symbol_parser::find_elf_symbol(symbol &sym, const elf_file &file, int pid, std::map >::iterator it; it = file_symbols.find(file); std::set ss; + // printf("search symbol1 0x%lx, base 0x%lx\n", sym.ip, sym.base); if (it == file_symbols.end()) { - if (!load_elf(pid, file)) { + if (!load_elf(pid, file, sym.base)) { + // printf("load elf %s failed\n", file.filename.c_str()); return false; } + // printf("load elf %s success\n", file.filename.c_str()); it = file_symbols.find(file); return search_symbol(it->second, sym); } else { diff --git a/source/ucli/symbol.h b/source/ucli/symbol.h index 7831845..4f074fa 100644 --- a/source/ucli/symbol.h +++ b/source/ucli/symbol.h @@ -57,6 +57,7 @@ struct vma { }; size_t map(size_t pc) { + // printf("pc: %lx, start: %lx, offset: %lx\n", pc, start, offset); return pc - start + offset; } @@ -89,9 +90,10 @@ struct symbol { size_t start; size_t end; size_t ip; + size_t base; std::string name; - symbol() :start(0), end(0), ip(0) {} + 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; } @@ -135,7 +137,7 @@ public: void dump(void); private: bool load_pid_maps(int pid); - bool load_elf(pid_t pid, const elf_file& file); + 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; diff --git a/source/ucli/ucli-lib.cc b/source/ucli/ucli-lib.cc index 31d438a..e710d86 100644 --- a/source/ucli/ucli-lib.cc +++ b/source/ucli/ucli-lib.cc @@ -103,8 +103,9 @@ static int unwind_frame_callback(struct unwind_entry *entry, void *arg) { 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);