* alpha-linux-tdep.c: New file. Move alpha_linux_sigtramp_offset
[external/binutils.git] / gdb / alpha-linux-tdep.c
1 /* Target-dependent code for GNU/Linux on Alpha.
2    Copyright 2002 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "defs.h"
22 #include "value.h"
23
24 #include "alpha-tdep.h"
25
26 /* Under GNU/Linux, signal handler invocations can be identified by the
27    designated code sequence that is used to return from a signal
28    handler.  In particular, the return address of a signal handler
29    points to the following sequence (the first instruction is quadword
30    aligned):
31   
32    bis $30,$30,$16
33    addq $31,0x67,$0
34    call_pal callsys 
35       
36    Each instruction has a unique encoding, so we simply attempt to
37    match the instruction the pc is pointing to with any of the above
38    instructions.  If there is a hit, we know the offset to the start
39    of the designated sequence and can then check whether we really are
40    executing in a designated sequence.  If not, -1 is returned,
41    otherwise the offset from the start of the desingated sequence is
42    returned.
43    
44    There is a slight chance of false hits: code could jump into the
45    middle of the designated sequence, in which case there is no
46    guarantee that we are in the middle of a sigreturn syscall.  Don't
47    think this will be a problem in praxis, though.  */
48 long
49 alpha_linux_sigtramp_offset (CORE_ADDR pc)
50 {
51   unsigned int i[3], w;
52   long off;
53
54   if (read_memory_nobpt (pc, (char *) &w, 4) != 0)
55     return -1;
56
57   off = -1;
58   switch (w)
59     {
60     case 0x47de0410:
61       off = 0;
62       break;                    /* bis $30,$30,$16 */
63     case 0x43ecf400:
64       off = 4;
65       break;                    /* addq $31,0x67,$0 */
66     case 0x00000083:
67       off = 8;
68       break;                    /* call_pal callsys */
69     default:
70       return -1;
71     }
72   pc -= off;
73   if (pc & 0x7)
74     {
75       /* designated sequence is not quadword aligned */
76       return -1;
77     }
78   if (read_memory_nobpt (pc, (char *) i, sizeof (i)) != 0)
79     return -1;
80
81   if (i[0] == 0x47de0410 && i[1] == 0x43ecf400 && i[2] == 0x00000083)
82     return off;
83
84   return -1;
85 }
86
87 static void
88 alpha_linux_init_abi (struct gdbarch_info info,
89                       struct gdbarch *gdbarch)
90 {
91   /* Place holder. */
92 }
93
94 void
95 _initialize_alpha_linux_tdep (void)
96 {
97   alpha_gdbarch_register_os_abi (ALPHA_ABI_LINUX, alpha_linux_init_abi);
98 }