void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) { if (pc != NULL) pc = pc - 1; if (exn != caml_read_root(Caml_state->backtrace_last_exn) || !reraise) { Caml_state->backtrace_pos = 0; caml_modify_root(Caml_state->backtrace_last_exn, exn); } if (Caml_state->backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1) return; if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; /* testing the code region is needed: PR#1554 */ if (find_debug_info(pc) != NULL) Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = pc; /* Traverse the stack and put all values pointing into bytecode into the backtrace buffer. */ value *trap_sp = Stack_high(Caml_state->current_stack) + Caml_state->trap_sp_off; for (/*nothing*/; sp < trap_sp; sp++) { if (Is_long(*sp)) { code_t p = Pc_val(*sp); if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; if (find_debug_info(p) != NULL) Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = p; } } }
void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) { code_t end_code = (code_t) ((char *) caml_start_code + caml_code_size); if (pc != NULL) pc = pc - 1; if (exn != caml_backtrace_last_exn || !reraise) { caml_backtrace_pos = 0; caml_backtrace_last_exn = exn; } if (caml_backtrace_buffer == NULL) { Assert(caml_backtrace_pos == 0); caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t)); if (caml_backtrace_buffer == NULL) return; } if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; /* testing the code region is needed: PR#1554 */ if (find_debug_info(pc) != NULL) caml_backtrace_buffer[caml_backtrace_pos++] = pc; /* Traverse the stack and put all values pointing into bytecode into the backtrace buffer. */ for (/*nothing*/; sp < caml_stack_high + caml_trap_sp_off; sp++) { code_t p = Pc_val(*sp); if (Is_long(*sp) && Pc_val(*sp) >= caml_start_code && Pc_val(*sp) < end_code) { if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; if (find_debug_info(p) != NULL) caml_backtrace_buffer[caml_backtrace_pos++] = p; } } }
static struct ev_info *event_for_location(code_t pc) { uintnat low, high; struct debug_info *di = find_debug_info(pc); if (di == NULL) return NULL; if (!di->already_read) read_main_debug_info(di); if (di->num_events == 0) return NULL; low = 0; high = di->num_events; while (low+1 < high) { uintnat m = (low+high)/2; if(pc < di->events[m].ev_pc) high = m; else low = m; } if (di->events[low].ev_pc == pc) return &di->events[low]; /* ocamlc sometimes moves an event past a following PUSH instruction; allow mismatch by 1 instruction. */ if (di->events[low].ev_pc == pc + 1) return &di->events[low]; if (low+1 < di->num_events && di->events[low+1].ev_pc == pc + 1) return &di->events[low+1]; return NULL; }
code_t caml_next_frame_pointer(value* stack_high, value ** sp, intnat * trap_spoff) { while (*sp < stack_high) { value* p = (*sp)++; if(&Trap_pc(stack_high + *trap_spoff) == p) { *trap_spoff = Trap_link(stack_high + *trap_spoff); continue; } if (Is_long(*p) && find_debug_info(Pc_val(*p)) != NULL) return Pc_val(*p); } return NULL; }
code_t caml_next_frame_pointer(value ** sp, intnat * trap_spoff) { code_t end_code = (code_t) ((char *) caml_start_code + caml_code_size); while (*sp < caml_stack_high) { value *p = (*sp)++; if(&Trap_pc(caml_stack_high + *trap_spoff) == p) { *trap_spoff = Trap_link(caml_stack_high + *trap_spoff); continue; } if (Is_long(*p) && Pc_val(*p) >= caml_start_code && Pc_val(*p) < end_code && find_debug_info((code_t)*p)) { return Pc_val(*p); } } return NULL; }