Browse Source

backtrace ("bt") command works (only if frame pointer is not ommited!)

master
A.Olokhtonov 3 years ago
parent
commit
0b0fd8d1ea
  1. 21
      command.c
  2. 39
      common.h
  3. 65
      dwarf.c
  4. 2
      main.c
  5. 39
      res/004-scoped-variables.c
  6. 46
      util.c

21
command.c

@ -127,3 +127,24 @@ command_kill(struct mi_process proc) @@ -127,3 +127,24 @@ command_kill(struct mi_process proc)
{
kill(proc.pid, SIGKILL);
}
static void
command_backtrace(struct mi_process proc)
{
struct mi_registers regs = get_process_registers(proc);
struct mi_function *func = get_function_around_pc(proc, regs.rip - proc.base_address);
u64 fb = regs.rbp;
u64 return_address = ptrace(PTRACE_PEEKDATA, proc.pid, fb + 8, NULL);
printf("%s: %#lx\n", func->name, regs.rip);
for (int i = 0; i < 3; ++i) {
func = get_function_around_pc(proc, return_address - proc.base_address);
if (func) {
printf("%s: %#lx\n", func->name, regs.rip);
}
fb = ptrace(PTRACE_PEEKDATA, proc.pid, fb, NULL);
return_address = ptrace(PTRACE_PEEKDATA, proc.pid, fb + 8, NULL);
}
}

39
common.h

@ -43,13 +43,6 @@ struct mi_sourcepoint { @@ -43,13 +43,6 @@ struct mi_sourcepoint {
int file;
};
struct mi_function {
char *name;
int comp_unit;
u64 low_pc;
u64 high_pc;
};
struct mi_sourcefile {
char *filename;
char *dir;
@ -61,18 +54,15 @@ struct mi_variable { @@ -61,18 +54,15 @@ struct mi_variable {
s64 location;
};
struct mi_block {
struct mi_function {
u64 low_pc;
u64 high_pc;
struct mi_variable variables[4]; // TODO
int var_count;
char *name;
int variables_from;
int variables_count;
};
struct mi_compunit {
u64 low_pc;
u64 high_pc;
struct mi_sourceinfo {
struct mi_sourcepoint *sp_table;
int sp_count;
@ -83,17 +73,26 @@ struct mi_compunit { @@ -83,17 +73,26 @@ struct mi_compunit {
int source_dirs_count;
char *comp_dir;
};
struct mi_block blocks[4]; // TODO
int block_count;
struct mi_compunit {
u64 low_pc;
u64 high_pc;
struct mi_sourceinfo source;
int functions_from;
int functions_count;
};
struct mi_debuginfo {
struct mi_compunit compilation_units[16]; // TODO
int cu_count;
struct mi_compunit compilation_units[16];
struct mi_function functions[64];
struct mi_variable variables[64];
struct mi_function functions[64]; // TODO
int cu_count;
int func_count;
int var_count;
};
struct mi_process {

65
dwarf.c

@ -768,30 +768,16 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -768,30 +768,16 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
u32 depth = 0;
u64 base_data_offset = data_offset - header_size;
int found_sr = 0;
struct mi_function *func = dest->functions + dest->func_count;
struct mi_compunit *comp_unit = dest->compilation_units + dest->cu_count;
struct mi_block *block = comp_unit->blocks;
struct mi_variable *variable = block->variables;
enum dwarf_die_tag parent = 0;
struct mi_function *func = dest->functions + dest->func_count;
struct mi_variable *variable = dest->variables + dest->var_count;
// TODO: make this not bad
comp_unit->functions_from = dest->func_count;
for (;;) {
data_offset += decode_leb128(file + data_offset, &code);
if (code == 0) {
// NOTE: finalize parent
if (parent == DW_TAG_lexical_block) {
block->high_pc = block->low_pc + block->high_pc;
++block;
++comp_unit->block_count;
variable = block->variables;
__builtin_trap();
}
if (depth > 1) {
--depth;
continue;
@ -808,7 +794,6 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -808,7 +794,6 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
u32 has_children = file[schema_offset++];
if (has_children) {
parent = tag;
++depth;
}
@ -828,7 +813,7 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -828,7 +813,7 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
} else if (attribute == DW_AT_high_pc) {
comp_unit->high_pc = value;
} else if (attribute == DW_AT_comp_dir) {
comp_unit->comp_dir = (char *) value;
comp_unit->source.comp_dir = (char *) value;
}
} else if (tag == DW_TAG_subprogram) {
if (attribute == DW_AT_name) {
@ -838,12 +823,6 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -838,12 +823,6 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
} else if (attribute == DW_AT_high_pc) {
func->high_pc = value;
}
} else if (tag == DW_TAG_lexical_block) {
if (attribute == DW_AT_low_pc) {
block->low_pc = value;
} else if (attribute == DW_AT_high_pc) {
block->high_pc = value;
}
} else if (tag == DW_TAG_variable) {
if (attribute == DW_AT_name) {
variable->name = (char *) value;
@ -853,16 +832,18 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest, @@ -853,16 +832,18 @@ read_debug_info_for_compilation_unit(u8 *file, struct mi_debuginfo *dest,
}
} while (attribute != 0 || form != 0);
if (parent == DW_TAG_variable) {
++variable;
++block->var_count;
}
if (parent == DW_TAG_subprogram) {
// NOTE(aolo2): DIE completely processed, finish it up
if (tag == DW_TAG_subprogram) {
func->high_pc = func->low_pc + func->high_pc;
func->comp_unit = dest->cu_count;
++func;
func->variables_from = dest->var_count;
++comp_unit->functions_count;
++dest->func_count;
++func;
} else if (tag == DW_TAG_variable) {
struct mi_function *parent = func - 1;
++parent->variables_count;
++dest->var_count;
++variable;
}
}
@ -900,14 +881,14 @@ parse_debug_info(u8 *file, struct mi_debuginfo *dest) @@ -900,14 +881,14 @@ parse_debug_info(u8 *file, struct mi_debuginfo *dest)
static u64
read_debug_line_for_compilation_unit(u8 *file, u64 dl_offset, struct mi_compunit *unit)
{
struct mi_sourcepoint *dest = unit->sp_table;
int *dest_size = &unit->sp_count;
struct mi_sourcepoint *dest = unit->source.sp_table;
int *dest_size = &unit->source.sp_count;
struct mi_sourcefile *dest_files = unit->source_files;
int *dest_files_size = &unit->source_file_count;
struct mi_sourcefile *dest_files = unit->source.source_files;
int *dest_files_size = &unit->source.source_file_count;
char **dest_directories = unit->source_directories;
int *dest_directories_size = &unit->source_dirs_count;
char **dest_directories = unit->source.source_directories;
int *dest_directories_size = &unit->source.source_dirs_count;
struct dwarf_debug_line_header_v3_x32 header = { 0 };
memcpy(&header, file + dl_offset, 15); /* all fixed-size info */
@ -1246,9 +1227,9 @@ parse_debug_line(u8 *file, struct mi_debuginfo *debug) @@ -1246,9 +1227,9 @@ parse_debug_line(u8 *file, struct mi_debuginfo *debug)
// count
for (;;) {
u64 size = read_debug_line_for_compilation_unit(file, at, unit);
unit->sp_table = calloc(1, unit->sp_count * sizeof(struct mi_sourcepoint));
unit->source_directories = calloc(1, unit->source_dirs_count * sizeof(char *));
unit->source_files = calloc(1, unit->source_file_count * sizeof(struct mi_sourcefile));
unit->source.sp_table = calloc(1, unit->source.sp_count * sizeof(struct mi_sourcepoint));
unit->source.source_directories = calloc(1, unit->source.source_dirs_count * sizeof(char *));
unit->source.source_files = calloc(1, unit->source.source_file_count * sizeof(struct mi_sourcefile));
read += size;
at += size;
++unit;

2
main.c

@ -55,6 +55,8 @@ main(int argc, char *argv[]) @@ -55,6 +55,8 @@ main(int argc, char *argv[])
command_next(process);
} else if (0 == strncmp(command, "line\n", command_length)) {
command_list(process);
} else if (0 == strncmp(command, "bt\n", command_length)) {
command_backtrace(process);
} else if (0 == strncmp(command, "cont\n", command_length)) {
command_cont(process);
wait = 1;

39
res/004-scoped-variables.c

@ -1,11 +1,38 @@ @@ -1,11 +1,38 @@
void f1();
void f2();
void f3();
void
f3()
{
int a_f3 = 3;
f2();
}
void
f2()
{
int a_f2 = 2;
{
int b_f2 = 22;
{
int c_f2 = 33;
}
}
}
void
f1()
{
int a_f1 = 1;
f2();
}
int
main(int argc, char **argv)
{
int outer = 1;
if (outer > 0) {
char *inner = "INNER";
int outer = -1;
outer += 10;
}
int a_main = 0;
f1();
f3();
return(0);
}

46
util.c

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
static struct mi_registers
get_process_registers(struct mi_process proc)
{
@ -114,11 +113,11 @@ pc_to_sourcepoint(struct mi_process proc, u64 pc, int *comp_unit) @@ -114,11 +113,11 @@ pc_to_sourcepoint(struct mi_process proc, u64 pc, int *comp_unit)
for (int c = 0; c < proc.debug.cu_count; ++c) {
struct mi_compunit unit = proc.debug.compilation_units[c];
if (unit.low_pc <= pc && pc < unit.high_pc) {
for (int i = 0; i < unit.sp_count; ++i) {
struct mi_sourcepoint *point = unit.sp_table + i;
for (int i = 0; i < unit.source.sp_count; ++i) {
struct mi_sourcepoint *point = unit.source.sp_table + i;
if (point->pc > pc) {
*comp_unit = c;
return(unit.sp_table + i - 1);
return(unit.source.sp_table + i - 1);
}
}
break;
@ -173,19 +172,19 @@ print_sourcepoint(struct mi_process proc, int comp_unit, struct mi_sourcepoint * @@ -173,19 +172,19 @@ print_sourcepoint(struct mi_process proc, int comp_unit, struct mi_sourcepoint *
struct mi_compunit unit = proc.debug.compilation_units[comp_unit];
// NOTE: sourcepoint file indices are 1-based
if (unit.source_files[sp->file - 1].file.data == 0) {
char *file_filename = unit.source_files[sp->file - 1].filename;
char *file_dirname = unit.source_files[sp->file - 1].dir;
char *comp_dir = unit.comp_dir;
if (unit.source.source_files[sp->file - 1].file.data == 0) {
char *file_filename = unit.source.source_files[sp->file - 1].filename;
char *file_dirname = unit.source.source_files[sp->file - 1].dir;
char *comp_dir = unit.source.comp_dir;
char full_path[512] = { 0 };
snprintf(full_path, 511, "%s/%s/%s", comp_dir, file_dirname, file_filename);
struct mi_buffer file = read_file_mmap(full_path);
unit.source_files[sp->file - 1].file = file;
unit.source.source_files[sp->file - 1].file = file;
}
struct mi_buffer file = unit.source_files[sp->file - 1].file;
struct mi_buffer file = unit.source.source_files[sp->file - 1].file;
char *source = (char *) file.data;
u64 size = file.size;
@ -280,6 +279,7 @@ lookup_identifier_address(struct mi_process proc, char *ident, int len) @@ -280,6 +279,7 @@ lookup_identifier_address(struct mi_process proc, char *ident, int len)
struct mi_registers regs = get_process_registers(proc);
u64 pc_local = regs.rip - proc.base_address;
#if 0
for (int c = 0; c < proc.debug.cu_count; ++c) {
struct mi_compunit unit = proc.debug.compilation_units[c];
@ -303,6 +303,32 @@ lookup_identifier_address(struct mi_process proc, char *ident, int len) @@ -303,6 +303,32 @@ lookup_identifier_address(struct mi_process proc, char *ident, int len)
}
}
#endif
return(0);
}
static struct mi_function *
get_function_around_pc(struct mi_process proc, u64 pc)
{
struct mi_debuginfo debug = proc.debug;
for (int c = 0; c < debug.cu_count; ++c) {
struct mi_compunit *unit = debug.compilation_units + c;
if (unit->low_pc <= pc && pc < unit->high_pc) {
for (int f = 0; f < unit->functions_count; ++f) {
struct mi_function *func = debug.functions + unit->functions_from + f;
if (func->low_pc <= pc && pc < func->high_pc) {
return(func);
}
}
break;
}
}
return(0);
}
Loading…
Cancel
Save