mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-21 23:27:39 +01:00
ARM: fix non-signal-frame local unw_resume() due to compiler optimization cleverness
When cross-compiling libunwind with optimizations (-O1 or higher), gcc-4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) optimizes away the memory writes prior to the inline asm() statement in arm_local_resume() in the non-signal-frame path, causing the `regs' array to be only allocated on the stack, but not populated. This means that we are restoring garbage to the registers. As suggested in the GCC docs, add a fixed size input memory constraint for the array content. This is enough to get the desired code to be generated. Adding __builtin_unreachable() to the point that we should never reach was also in itself enough to inhibit the optimization. It also reduces the function size by a few instructions.
This commit is contained in:
parent
5fef17c05d
commit
14fc15928b
1 changed files with 8 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
||||||
/* libunwind - a platform-independent unwind library
|
/* libunwind - a platform-independent unwind library
|
||||||
Copyright (C) 2008 CodeSourcery
|
Copyright (C) 2008 CodeSourcery
|
||||||
Copyright 2011 Linaro Limited
|
Copyright 2011 Linaro Limited
|
||||||
|
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
|
||||||
|
|
||||||
This file is part of libunwind.
|
This file is part of libunwind.
|
||||||
|
|
||||||
|
@ -51,11 +52,16 @@ arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||||
regs[8] = uc->regs[13]; /* SP */
|
regs[8] = uc->regs[13]; /* SP */
|
||||||
regs[9] = uc->regs[14]; /* LR */
|
regs[9] = uc->regs[14]; /* LR */
|
||||||
|
|
||||||
|
struct regs_overlay {
|
||||||
|
char x[sizeof(regs)];
|
||||||
|
};
|
||||||
|
|
||||||
asm __volatile__ (
|
asm __volatile__ (
|
||||||
"ldmia %0, {r4-r12, lr}\n"
|
"ldmia %0, {r4-r12, lr}\n"
|
||||||
"mov sp, r12\n"
|
"mov sp, r12\n"
|
||||||
"bx lr\n"
|
"bx lr\n"
|
||||||
: : "r" (regs)
|
: : "r" (regs),
|
||||||
|
"m" (*(struct regs_overlay *)regs)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -90,6 +96,7 @@ arm_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
|
||||||
: : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
|
: : "r" (c->sigcontext_sp), "r" (c->sigcontext_pc)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
#else
|
#else
|
||||||
printf ("%s: implement me\n", __FUNCTION__);
|
printf ("%s: implement me\n", __FUNCTION__);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue