* Unwind a single frame starting with *sp for the symbol at *pc. It * updates the *pc and *sp with the new values. */
| 379 | * updates the *pc and *sp with the new values. |
| 380 | */ |
| 381 | int unwind_frame(struct stackframe *frame, const struct unwind_idx **origin_idx, const struct unwind_idx exidx_start[], const struct unwind_idx exidx_end[]) |
| 382 | { |
| 383 | unsigned long low; |
| 384 | const struct unwind_idx *idx; |
| 385 | struct unwind_ctrl_block ctrl; |
| 386 | struct rt_thread *rt_c_thread; |
| 387 | |
| 388 | /* store the highest address on the stack to avoid crossing it*/ |
| 389 | low = frame->sp; |
| 390 | rt_c_thread = rt_thread_self(); |
| 391 | ctrl.sp_high = (unsigned long)((char*)rt_c_thread->stack_addr + rt_c_thread->stack_size); |
| 392 | |
| 393 | LOG_D("%s(pc = %08lx lr = %08lx sp = %08lx)", __func__, |
| 394 | frame->pc, frame->lr, frame->sp); |
| 395 | |
| 396 | idx = unwind_find_idx(frame->pc, origin_idx, exidx_start, exidx_end); |
| 397 | if (!idx) |
| 398 | { |
| 399 | LOG_W("unwind: Index not found %08lx", frame->pc); |
| 400 | return -URC_FAILURE; |
| 401 | } |
| 402 | |
| 403 | #ifdef RT_BACKTRACE_FUNCTION_NAME |
| 404 | { |
| 405 | char *fun_name; |
| 406 | fun_name = unwind_get_function_name((void *)prel31_to_addr(&idx->addr_offset)); |
| 407 | if (fun_name) |
| 408 | { |
| 409 | rt_kprintf("0x%08x @ %s\n", frame->pc, fun_name); |
| 410 | } |
| 411 | } |
| 412 | #endif |
| 413 | |
| 414 | ctrl.vrs[FP] = frame->fp; |
| 415 | ctrl.vrs[SP] = frame->sp; |
| 416 | ctrl.vrs[LR] = frame->lr; |
| 417 | ctrl.vrs[PC] = 0; |
| 418 | |
| 419 | if (idx->insn == 1) |
| 420 | /* can't unwind */ |
| 421 | return -URC_FAILURE; |
| 422 | else if ((idx->insn & 0x80000000) == 0) |
| 423 | /* prel31 to the unwind table */ |
| 424 | ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn); |
| 425 | else if ((idx->insn & 0xff000000) == 0x80000000) |
| 426 | /* only personality routine 0 supported in the index */ |
| 427 | ctrl.insn = &idx->insn; |
| 428 | else |
| 429 | { |
| 430 | LOG_W("unwind: Unsupported personality routine %08lx in the index at %x", |
| 431 | idx->insn, idx); |
| 432 | return -URC_FAILURE; |
| 433 | } |
| 434 | |
| 435 | /* check the personality routine */ |
| 436 | if ((*ctrl.insn & 0xff000000) == 0x80000000) |
| 437 | { |
| 438 | ctrl.byte = 2; |
no test coverage detected