aboutsummaryrefslogtreecommitdiff
path: root/gdb/tramp-frame.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@codesourcery.com>2014-12-03 19:19:41 +0000
committerMaciej W. Rozycki <macro@codesourcery.com>2014-12-03 20:57:06 +0000
commit858339f2b7aafe199c1cd07fc8d4a7c8130aa285 (patch)
tree106917d932b59e6210394d1c5cab5b5753e34ddb /gdb/tramp-frame.c
parentdb6b071a97893d5c7bf34e7fb171a0b710ea736d (diff)
downloadgdb-858339f2b7aafe199c1cd07fc8d4a7c8130aa285.zip
gdb-858339f2b7aafe199c1cd07fc8d4a7c8130aa285.tar.gz
gdb-858339f2b7aafe199c1cd07fc8d4a7c8130aa285.tar.bz2
MIPS: Add support for microMIPS Linux signal trampolines
The necessity for this change has been revealed in the course of investigation related to proposed changes in the treatment of the ISA bit encoded in function symbols on the MIPS target. This change adds support for Linux signal trampolines encoded with the microMIPS instruction set. Such trampolines are used by the Linux kernel if compiled as a microMIPS binary (even if the binary run/debugged itself contains no microMIPS code at all). To see if we need to check whether the execution mode selected matches the given trampoline I have checked what the bit patterns of all the trampoline sequences decode to in the opposite instruction set. This produced useless or at least unusual code in most cases, for example: microMIPS/EB, o32 sigreturn, decoded as MIPS code: 30401017 andi zero,v0,0x1017 00008b7c dsll32 s1,zero,0xd MIPS/EL, o32 sigreturn, decoded as microMIPS code: 1017 2402 addi zero,s7,9218 000c 0000 sll zero,t0,0x0 However in some corner cases reasonable code can mimic a trampoline, for example: MIPS/EB, n32 rt_sigreturn, decoded as microMIPS code: 2402 sll s0,s0,1 1843 0000 sb v0,0(v1) 000c 0f3c jr t0 -- here the first instruction is a 16-bit one, making things nastier even as there are some other microMIPS instructions whose first 16-bit halfword is 0x000c and therefore matches this whole trampoline pattern. To overcome this problem I have decided the signal trampoline unwinder has to ask the platform backend whether it can apply a given trampoline pattern to the code location being concerned or not. Anticipating the acceptance of the ISA bit proposal I decided the handler not to merely be a predicate, but also to be able to provide an adjusted PC if required. I decided that returning zero will mean that the trampoline pattern is not applicable and any other value is the adjusted PC to use; a handler may return the value requested if the trampoline pattern and the PC requested as-is are both accepted. This changes the semantics of the trampoline unwinder a bit in that the zero PC now has a special value. I think this should be safe as a NULL pointer is generally supposed to be invalid. * tramp-frame.h (tramp_frame): Add `validate' member. * tramp-frame.c (tramp_frame_start): Validate trampoline before scanning. * mips-linux-tdep.c (MICROMIPS_INST_LI_V0): New macro. (MICROMIPS_INST_POOL32A, MICROMIPS_INST_SYSCALL): Likewise. (mips_linux_o32_sigframe): Initialize `validate' member. (mips_linux_o32_rt_sigframe): Likewise. (mips_linux_n32_rt_sigframe): Likewise. (mips_linux_n64_rt_sigframe): Likewise. (micromips_linux_o32_sigframe): New variable. (micromips_linux_o32_rt_sigframe): Likewise. (micromips_linux_n32_rt_sigframe): Likewise. (micromips_linux_n64_rt_sigframe): Likewise. (mips_linux_o32_sigframe_init): Handle microMIPS trampolines. (mips_linux_n32n64_sigframe_init): Likewise. (mips_linux_sigframe_validate): New function. (micromips_linux_sigframe_validate): Likewise. (mips_linux_init_abi): Install microMIPS trampoline unwinders.
Diffstat (limited to 'gdb/tramp-frame.c')
-rw-r--r--gdb/tramp-frame.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c
index 0fd6ddc..a0e3eb5 100644
--- a/gdb/tramp-frame.c
+++ b/gdb/tramp-frame.c
@@ -86,6 +86,10 @@ tramp_frame_start (const struct tramp_frame *tramp,
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int ti;
+ /* Check if we can use this trampoline. */
+ if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
+ return 0;
+
/* Search through the trampoline for one that matches the
instruction sequence around PC. */
for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)