From 35b5c2255719adc77d7dade3da0ad41e55f7d295 Mon Sep 17 00:00:00 2001 From: Igor Nabirushkin Date: Tue, 2 Dec 2014 15:48:47 +0400 Subject: misc: tegra-profiler: fix vsp increment Decode the unwinding instructions (AArch32): fix incorrect increment of virtual stack pointer (vsp). Bug 1584541 Bug 1598009 Change-Id: I4ec64eb21a758b9283df9e6bd6b87a0555180eab Signed-off-by: Igor Nabirushkin Reviewed-on: http://git-master/r/658441 (cherry picked from commit c963ce2532586098ddae159d19a2e241fc25cd1a) Reviewed-on: http://git-master/r/672040 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty --- drivers/misc/tegra-profiler/eh_unwind.c | 50 +++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'drivers/misc/tegra-profiler/eh_unwind.c') diff --git a/drivers/misc/tegra-profiler/eh_unwind.c b/drivers/misc/tegra-profiler/eh_unwind.c index 728ca6394f99..a097fd8d1067 100644 --- a/drivers/misc/tegra-profiler/eh_unwind.c +++ b/drivers/misc/tegra-profiler/eh_unwind.c @@ -667,6 +667,39 @@ unwind_get_byte(struct quadd_mmap_area *mmap, return ret; } +static long +read_uleb128(struct quadd_mmap_area *mmap, + struct unwind_ctrl_block *ctrl, + unsigned long *ret) +{ + long err = 0; + unsigned long result; + unsigned char byte; + int shift, count; + + result = 0; + shift = 0; + count = 0; + + while (1) { + byte = unwind_get_byte(mmap, ctrl, &err); + if (err < 0) + return err; + + count++; + + result |= (byte & 0x7f) << shift; + shift += 7; + + if (!(byte & 0x80)) + break; + } + + *ret = result; + + return count; +} + /* * Execute the current unwind instruction. */ @@ -790,14 +823,21 @@ unwind_exec_insn(struct quadd_mmap_area *mmap, ctrl->vrs[SP] = (u32)(unsigned long)vsp; pr_debug("new vsp: %#x\n", ctrl->vrs[SP]); } else if (insn == 0xb2) { - unsigned long uleb128 = unwind_get_byte(mmap, ctrl, &err); - if (err < 0) - return err; + long count; + unsigned long uleb128 = 0; + + count = read_uleb128(mmap, ctrl, &uleb128); + if (count < 0) + return count; + + if (count == 0) + return -QUADD_URC_TBL_IS_CORRUPT; ctrl->vrs[SP] += 0x204 + (uleb128 << 2); - pr_debug("CMD_DATA_POP: vsp = vsp + %lu, new vsp: %#x\n", - 0x204 + (uleb128 << 2), ctrl->vrs[SP]); + pr_debug("CMD_DATA_POP: vsp = vsp + %lu (%#lx), new vsp: %#x\n", + 0x204 + (uleb128 << 2), 0x204 + (uleb128 << 2), + ctrl->vrs[SP]); } else if (insn == 0xb3 || insn == 0xc8 || insn == 0xc9) { unsigned long data, reg_from, reg_to; u32 *vsp = (u32 *)(unsigned long)ctrl->vrs[SP]; -- cgit v1.2.3