diff --git a/src/debug_symbol.c b/src/debug_symbol.c index 3cb05d5..486fa78 100644 --- a/src/debug_symbol.c +++ b/src/debug_symbol.c @@ -41,12 +41,21 @@ typedef struct { Mapping *mappings; } SrcInfo; +typedef struct { + char *name; + int page; + int addr; + boolean is_local; +} FuncInfo; + struct debug_symbols { int version; int nr_srcs; SrcInfo *srcs; int nr_vars; char **variables; + int nr_funcs; + FuncInfo *functions; }; const char *fget4cc(FILE *fp) { @@ -161,6 +170,21 @@ static boolean load_vari(struct debug_symbols *dsym, char *buf) { return true; } +static boolean load_func(struct debug_symbols *dsym, char *buf) { + dsym->nr_funcs = LittleEndian_getDW(buf, 0); + dsym->functions = calloc(dsym->nr_funcs, sizeof(FuncInfo)); + char *p = buf + 4; + for (int i = 0; i < dsym->nr_funcs; i++) { + dsym->functions[i].name = p; + p += strlen(p) + 1; + dsym->functions[i].page = LittleEndian_getW(p, 0); + dsym->functions[i].addr = LittleEndian_getDW(p, 2); + dsym->functions[i].is_local = p[6]; + p += 7; + } + return true; +} + struct debug_symbols *dsym_load(const char *path) { FILE *fp = fopen(path, "rb"); if (!fp) { @@ -206,6 +230,8 @@ struct debug_symbols *dsym_load(const char *path) { ok = load_line(dsym, section_content); } else if (!strcmp(tag, "VARI")) { ok = load_vari(dsym, section_content); + } else if (!strcmp(tag, "FUNC")) { + ok = load_func(dsym, section_content); } else { WARNING("%s: unrecognized section %s\n", path, tag); } @@ -304,3 +330,26 @@ int dsym_lookup_variable(struct debug_symbols *dsym, const char *name) { } return -1; } + +const char *dsym_addr2func(struct debug_symbols *dsym, int page, int addr) { + if (!dsym) + return NULL; + + // Binary search. + int left = 0, right = dsym->nr_funcs; + while (left < right) { + int mid = (left + right) / 2; + FuncInfo *f = &dsym->functions[mid]; + if (f->page < page || (f->page == page && f->addr <= addr)) + left = mid + 1; + else + right = mid; + } + if (left == 0) + return NULL; + FuncInfo *f = &dsym->functions[left - 1]; + if (f->page != page) + return NULL; + assert(f->addr <= addr); + return f->name; +} diff --git a/src/debug_symbol.h b/src/debug_symbol.h index 7f61d35..1960981 100644 --- a/src/debug_symbol.h +++ b/src/debug_symbol.h @@ -31,5 +31,6 @@ int dsym_line2addr(struct debug_symbols *dsym, int page, int line); int dsym_addr2line(struct debug_symbols *dsym, int page, int addr); const char *dsym_source_line(struct debug_symbols *dsym, int page, int line); int dsym_lookup_variable(struct debug_symbols *dsym, const char *name); +const char *dsym_addr2func(struct debug_symbols *dsym, int page, int addr); #endif // __DEBUG_SYMBOL_H__ diff --git a/src/debugger.c b/src/debugger.c index 3d51b1f..f6a4ac0 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -53,17 +53,22 @@ static Breakpoint *internal_breakpoint; static const char whitespaces[] = " \t\r\n"; static const char *format_address(int page, int addr, boolean is_return_addr) { - static char buf[120]; + static char buf[100]; const char *src = dsym_page2src(symbols, page); // For return addresses, search with (addr - 1) so that the function call's // line number will be printed. int line = dsym_addr2line(symbols, page, is_return_addr ? addr - 1 : addr); + const char *func = dsym_addr2func(symbols, page, is_return_addr ? addr - 1 : addr); - if (src && line > 0) - sprintf(buf, "%.100s:%d", src, line); // TODO: print function name - else - sprintf(buf, "%d:0x%x", page, addr); + if (src && line > 0) { + if (func) + snprintf(buf, sizeof(buf), "%s:%d in %s", src, line, func); + else + snprintf(buf, sizeof(buf), "%s:%d", src, line); + } else { + snprintf(buf, sizeof(buf), "%d:0x%x", page, addr); + } return buf; } @@ -364,7 +369,7 @@ void dbg_repl(void) { } char buf[256]; - while (printf("dbg> "), fgets(buf, sizeof(buf), stdin)) { + while (printf("dbg> "), fflush(stdout), fgets(buf, sizeof(buf), stdin)) { char *cmd = strtok(buf, whitespaces); if (!cmd) { // TODO: repeat last command