summaryrefslogtreecommitdiffstats
path: root/backends
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2017-11-17 15:53:23 +0100
committerUlf Hermann <[email protected]>2017-11-24 12:24:16 +0000
commite61a262eed35c095ac451ee54fa7bf6527764747 (patch)
tree44feaf82c572e13acb7b13b35a514fa0d92a01d9 /backends
parentd86c13d143989a961eba149e3abfab9e3f471744 (diff)
Be stricter about frame pointer unwinding on ARM
There were too many false positives. We require reasonable values for SP and FP now, and we check that the new value for LR is not null before we set anything. Change-Id: I91ca205d0f0ad00e1934f2007d7aa998bb597b35 Reviewed-by: Christian Kandeler <[email protected]>
Diffstat (limited to 'backends')
-rw-r--r--backends/arm_unwind.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/backends/arm_unwind.c b/backends/arm_unwind.c
index 3d1e1f25..240eb56f 100644
--- a/backends/arm_unwind.c
+++ b/backends/arm_unwind.c
@@ -60,16 +60,20 @@ EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__
{
Dwarf_Word fp = 0, sp = 0; // have to be initialized because registers are 32bit only
- if (!getfunc(FP_REG, 1, &fp, arg))
- fp = 0;
+ if (!getfunc(FP_REG, 1, &fp, arg) || fp == 0)
+ return false;
- if (!getfunc(SP_REG, 1, &sp, arg))
- sp = 0;
+ if (!getfunc(SP_REG, 1, &sp, arg) || sp == 0)
+ return false;
+
+ // Stack frames of > 8M are rather unlikely in real programs.
+ if (fp <= sp || fp - sp >= 1 << 23)
+ return false;
Dwarf_Word newLr, newFp, newSp;
- if (!readfunc(fp + LR_OFFSET, &newLr, arg))
- newLr = 0;
+ if (!readfunc(fp + LR_OFFSET, &newLr, arg) || newLr == 0)
+ return false;
if (!readfunc(fp + FP_OFFSET, &newFp, arg))
newFp = 0;
@@ -87,7 +91,5 @@ EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__
setfunc(FP_REG, 1, &newFp, arg);
setfunc(SP_REG, 1, &newSp, arg);
- // If the fp is invalid, we might still have a valid lr.
- // But if the fp is valid, then the stack should be moving in the right direction.
- return newLr != 0 && (fp == 0 || newSp > sp);
+ return true;
}