2005-08-14 06:31:30 +08:00
|
|
|
/* Signal trampoline unwinder.
|
2004-03-23 22:12:30 +08:00
|
|
|
|
2017-01-01 14:50:51 +08:00
|
|
|
Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
2004-03-23 22:12:30 +08:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2007-08-24 02:08:50 +08:00
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
2004-03-23 22:12:30 +08:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2007-08-24 02:08:50 +08:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2004-03-23 22:12:30 +08:00
|
|
|
|
|
|
|
#ifndef TRAMP_FRAME_H
|
|
|
|
#define TRAMP_FRAME_H
|
|
|
|
|
2004-07-20 23:11:37 +08:00
|
|
|
#include "frame.h" /* For "enum frame_type". */
|
|
|
|
|
2004-03-23 22:12:30 +08:00
|
|
|
struct trad_frame;
|
|
|
|
struct frame_info;
|
|
|
|
struct trad_frame_cache;
|
|
|
|
|
|
|
|
/* A trampoline consists of a small sequence of instructions placed at
|
|
|
|
an unspecified location in the inferior's address space. The only
|
|
|
|
identifying attribute of the trampoline's address is that it does
|
|
|
|
not fall inside an object file's section.
|
|
|
|
|
|
|
|
The only way to identify a trampoline is to perform a brute force
|
|
|
|
examination of the instructions at and around the PC.
|
|
|
|
|
2008-05-04 07:24:17 +08:00
|
|
|
This module provides a convenient interface for performing that
|
2004-03-23 22:12:30 +08:00
|
|
|
operation. */
|
|
|
|
|
|
|
|
/* A trampoline descriptor. */
|
|
|
|
|
2004-03-25 07:14:39 +08:00
|
|
|
/* Magic instruction that to mark the end of the signal trampoline
|
|
|
|
instruction sequence. */
|
|
|
|
#define TRAMP_SENTINEL_INSN ((LONGEST) -1)
|
|
|
|
|
2004-03-23 22:12:30 +08:00
|
|
|
struct tramp_frame
|
|
|
|
{
|
2004-07-20 23:11:37 +08:00
|
|
|
/* The trampoline's type, some a signal trampolines, some are normal
|
|
|
|
call-frame trampolines (aka thunks). */
|
|
|
|
enum frame_type frame_type;
|
|
|
|
/* The trampoline's entire instruction sequence. It consists of a
|
|
|
|
bytes/mask pair. Search for this in the inferior at or around
|
|
|
|
the frame's PC. It is assumed that the PC is INSN_SIZE aligned,
|
|
|
|
and that each element of TRAMP contains one INSN_SIZE
|
|
|
|
instruction. It is also assumed that INSN[0] contains the first
|
|
|
|
instruction of the trampoline and hence the address of the
|
|
|
|
instruction matching INSN[0] is the trampoline's "func" address.
|
|
|
|
The instruction sequence is terminated by
|
2004-03-25 07:14:39 +08:00
|
|
|
TRAMP_SENTINEL_INSN. */
|
2004-03-23 22:12:30 +08:00
|
|
|
int insn_size;
|
2004-07-20 23:11:37 +08:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
ULONGEST bytes;
|
|
|
|
ULONGEST mask;
|
2007-12-30 01:01:41 +08:00
|
|
|
} insn[48];
|
2004-03-23 22:12:30 +08:00
|
|
|
/* Initialize a trad-frame cache corresponding to the tramp-frame.
|
|
|
|
FUNC is the address of the instruction TRAMP[0] in memory. */
|
|
|
|
void (*init) (const struct tramp_frame *self,
|
2008-05-01 05:19:10 +08:00
|
|
|
struct frame_info *this_frame,
|
2004-03-23 22:12:30 +08:00
|
|
|
struct trad_frame_cache *this_cache,
|
|
|
|
CORE_ADDR func);
|
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.
2014-12-04 03:19:41 +08:00
|
|
|
/* Return non-zero if the tramp-frame is valid for the PC requested.
|
|
|
|
Adjust the PC to point to the address to check the instruction
|
|
|
|
sequence against if required. If this is NULL, then the tramp-frame
|
|
|
|
is valid for any PC. */
|
|
|
|
int (*validate) (const struct tramp_frame *self,
|
|
|
|
struct frame_info *this_frame,
|
|
|
|
CORE_ADDR *pc);
|
2004-03-23 22:12:30 +08:00
|
|
|
};
|
|
|
|
|
2004-04-09 04:03:52 +08:00
|
|
|
void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
|
|
|
|
const struct tramp_frame *tramp);
|
2004-03-23 22:12:30 +08:00
|
|
|
|
|
|
|
#endif
|