in Source/PLCrashFrameWalker.c [134:177]
plframe_error_t plframe_cursor_next_with_readers (plframe_cursor_t *cursor, plframe_cursor_frame_reader_t *readers[], size_t reader_count) {
/* The first frame is already available via existing thread state. */
if (cursor->depth == 0) {
cursor->depth++;
return PLFRAME_ESUCCESS;
}
/* A previous frame is only available if we're on the second frame */
plframe_stackframe_t *prev_frame = NULL;
if (cursor->depth >= 2)
prev_frame = &cursor->prev_frame;
/* Read in the next frame using the first successful frame reader. */
plframe_stackframe_t frame;
plframe_error_t ferr = PLFRAME_EINVAL; // default return value if reader_count is 0.
for (size_t i = 0; i < reader_count; i++) {
ferr = readers[i](cursor->task, cursor->image_list, &cursor->frame, prev_frame, &frame);
if (ferr == PLFRAME_ESUCCESS)
break;
}
if (ferr != PLFRAME_ESUCCESS) {
return ferr;
}
/* Check for completion */
if (!plcrash_async_thread_state_has_reg(&frame.thread_state, PLCRASH_REG_IP)) {
PLCF_DEBUG("Missing expected IP value in successfully read frame");
return PLFRAME_ENOFRAME;
}
/* A pc within the NULL page is a terminating frame */
plcrash_greg_t ip = plcrash_async_thread_state_get_reg(&frame.thread_state, PLCRASH_REG_IP);
if (ip <= PAGE_SIZE)
return PLFRAME_ENOFRAME;
/* Save the newly fetched frame */
cursor->prev_frame = cursor->frame;
cursor->frame = frame;
cursor->depth++;
return PLFRAME_ESUCCESS;
}