map_s *elf_set_breakpoints(proc_s *proc) { elf_info_s *elf = elf_symbols(proc->fd); map_s *brkp = map_init(32, cmp_addr); for (size_t i = 0; i < elf->replt_count; ++i) { void *ret; GElf_Rel rel; GElf_Rela rela; const char *name; GElf_Sym sym; GElf_Addr addr; /* local relocation entries */ if (elf->replt->d_type == ELF_T_REL) { ret = gelf_getrel(elf->replt, i, &rel); rela.r_offset = rel.r_offset; rela.r_info = rel.r_info; rela.r_addend = 0; } /* external relocation entries */ else ret = gelf_getrela(elf->replt, i, &rela); gelf_getsym(elf->dynsym, ELF64_R_SYM(rela.r_info), &sym); name = elf->dynstr + sym.st_name; addr = elf->plt_addr + (i + 1) * 16; breakpoint_create(brkp, addr, name, proc->pid); } return brkp; }
void ddbg_add_breakpoint(bstring file, int index) { int32_t memory; if (!biseq(file, bfromcstr("memory"))) { memory = ddbg_file_to_address(file, index); } else { if (index < 0) { printd(LEVEL_DEFAULT, "Memory address must be greater than 0.\n"); memory = -1; } else { memory = index; } } // Did we get a valid result? if (memory == -1) { printd(LEVEL_DEFAULT, "Unable to resolve specified symbol.\n"); return; } list_append(&breakpoints, breakpoint_create(memory, false, false)); printd(LEVEL_DEFAULT, "Breakpoint added at 0x%04X.\n", memory); }
void start_debugger(pid_t target_pid) { int status; wait(&status); struct user_regs_struct initial_registers; trace_get_registers(target_pid, &initial_registers); // Peek at a specific address: unsigned bp_addr = 0x4000b0; breakpoint *bp = breakpoint_create(target_pid, (void *)bp_addr); trace_continue(target_pid); wait(&status); while (1) { if (WIFSTOPPED(status)) { struct user_regs_struct registers; trace_get_registers(target_pid, ®isters); printf("\nReached breakpoint at 0x%08llx\n", registers.rip); breakpoint_handle(target_pid, bp); int requesting_input = true; while (requesting_input) { input_option input = request_input(NULL); if (input == INPUT_CONTINUE) { trace_continue(target_pid); requesting_input = false; } else if (input == INPUT_SINGLE_STEP) { trace_single_step(target_pid); requesting_input = false; } } int resume_status; wait(&resume_status); if (WIFEXITED(resume_status)) { printf("Process %d exited\n", target_pid); return; } else if (WIFSTOPPED(resume_status)) { printf("Process %d stopped\n", target_pid); return; } } else if (WIFEXITED(status)) { printf("Process %d exited\n", target_pid); return; } else { puts("Returning"); return; } } }
void ddbg_add_breakpoint_identifier(bstring ident) { // TODO: In the future when C functions are supported // in the debugging symbol format, we should probably // allow setting breakpoints by C function name as well. int32_t memory = ddbg_label_to_address(ident); // Did we get a valid result? if (memory == -1) { printd(LEVEL_DEFAULT, "Unable to resolve specified symbol.\n"); return; } list_append(&breakpoints, breakpoint_create(memory, false, false)); printd(LEVEL_DEFAULT, "Breakpoint added at 0x%04X.\n", memory); }
void ddbg_step_over() { uint16_t inst, op_a, op_b, offset = 1, bp; inst = INSTRUCTION_GET_OP(vm->ram[vm->pc]); op_a = INSTRUCTION_GET_A(vm->ram[vm->pc]); op_b = INSTRUCTION_GET_B(vm->ram[vm->pc]); vm->sleep_cycles = 0; if (op_a == NXT) offset += 1; if (op_a == NXT_LIT) offset += 1; if (op_b == NXT) offset += 1; if (op_b == NXT_LIT) offset += 1; if (inst == NBOP_RESERVED) { if (op_b == NBOP_JSR) { bp = op_a; } } else { bp = vm->pc + offset; } list_append(&breakpoints, breakpoint_create(bp, true, true)); vm->halted = false; vm_execute(vm, NULL); // Handle custom Lua commands. dbg_lua_handle_hook(&lstate, NULL, bautofree(bfromcstr("next")), 0); }