diff --git a/arch/arm/src/common/arm_backtrace_unwind.c b/arch/arm/src/common/arm_backtrace_unwind.c index 0a96b59a55..599df384db 100644 --- a/arch/arm/src/common/arm_backtrace_unwind.c +++ b/arch/arm/src/common/arm_backtrace_unwind.c @@ -338,6 +338,31 @@ static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_s *ctrl, return 0; } +static unsigned long unwind_decode_uleb128(struct unwind_ctrl_s *ctrl) +{ + unsigned long bytes = 0; + unsigned long insn; + unsigned long result = 0; + + /* unwind_get_byte() will advance `ctrl` one instruction at a time, so + * loop until we get an instruction byte where bit 7 is not set. + * + * Note: This decodes a maximum of 4 bytes to output 28 bits data where + * max is 0xfffffff: that will cover a vsp increment of 1073742336, hence + * it is sufficient for unwinding the stack. + */ + + do + { + insn = unwind_get_byte(ctrl); + result |= (insn & 0x7f) << (bytes * 7); + bytes++; + } + while (!!(insn & 0x80) && (bytes != sizeof(result))); + + return result; +} + /**************************************************************************** * Name: unwind_pop_register * @@ -403,7 +428,7 @@ static int unwind_exec_content(struct unwind_ctrl_s *ctrl) } else if (content == 0xb2) { - unsigned long uleb128 = unwind_get_byte(ctrl); + unsigned long uleb128 = unwind_decode_uleb128(ctrl); ctrl->vrs[SP] += 0x204 + (uleb128 << 2); }