OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [i386-linux-tdep.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/* Target-dependent code for Linux running on i386's, for GDB.
2
   Copyright (C) 2000 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 "gdbcore.h"
23
#include "frame.h"
24
#include "value.h"
25
 
26
 
27
/* Recognizing signal handler frames.  */
28
 
29
/* Linux has two flavors of signals.  Normal signal handlers, and
30
   "realtime" (RT) signals.  The RT signals can provide additional
31
   information to the signal handler if the SA_SIGINFO flag is set
32
   when establishing a signal handler using `sigaction'.  It is not
33
   unlikely that future versions of Linux will support SA_SIGINFO for
34
   normal signals too.  */
35
 
36
/* When the i386 Linux kernel calls a signal handler and the
37
   SA_RESTORER flag isn't set, the return address points to a bit of
38
   code on the stack.  This function returns whether the PC appears to
39
   be within this bit of code.
40
 
41
   The instruction sequence for normal signals is
42
       pop    %eax
43
       mov    $0x77,%eax
44
       int    $0x80
45
   or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
46
 
47
   Checking for the code sequence should be somewhat reliable, because
48
   the effect is to call the system call sigreturn.  This is unlikely
49
   to occur anywhere other than a signal trampoline.
50
 
51
   It kind of sucks that we have to read memory from the process in
52
   order to identify a signal trampoline, but there doesn't seem to be
53
   any other way.  The IN_SIGTRAMP macro in tm-linux.h arranges to
54
   only call us if no function name could be identified, which should
55
   be the case since the code is on the stack.
56
 
57
   Detection of signal trampolines for handlers that set the
58
   SA_RESTORER flag is in general not possible.  Unfortunately this is
59
   what the GNU C Library has been doing for quite some time now.
60
   However, as of version 2.1.2, the GNU C Library uses signal
61
   trampolines (named __restore and __restore_rt) that are identical
62
   to the ones used by the kernel.  Therefore, these trampolines are
63
   supported too.  */
64
 
65
#define LINUX_SIGTRAMP_INSN0 (0x58)     /* pop %eax */
66
#define LINUX_SIGTRAMP_OFFSET0 (0)
67
#define LINUX_SIGTRAMP_INSN1 (0xb8)     /* mov $NNNN,%eax */
68
#define LINUX_SIGTRAMP_OFFSET1 (1)
69
#define LINUX_SIGTRAMP_INSN2 (0xcd)     /* int */
70
#define LINUX_SIGTRAMP_OFFSET2 (6)
71
 
72
static const unsigned char linux_sigtramp_code[] =
73
{
74
  LINUX_SIGTRAMP_INSN0,                                 /* pop %eax */
75
  LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,         /* mov $0x77,%eax */
76
  LINUX_SIGTRAMP_INSN2, 0x80                            /* int $0x80 */
77
};
78
 
79
#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
80
 
81
/* If PC is in a sigtramp routine, return the address of the start of
82
   the routine.  Otherwise, return 0.  */
83
 
84
static CORE_ADDR
85
i386_linux_sigtramp_start (CORE_ADDR pc)
86
{
87
  unsigned char buf[LINUX_SIGTRAMP_LEN];
88
 
89
  /* We only recognize a signal trampoline if PC is at the start of
90
     one of the three instructions.  We optimize for finding the PC at
91
     the start, as will be the case when the trampoline is not the
92
     first frame on the stack.  We assume that in the case where the
93
     PC is not at the start of the instruction sequence, there will be
94
     a few trailing readable bytes on the stack.  */
95
 
96
  if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
97
    return 0;
98
 
99
  if (buf[0] != LINUX_SIGTRAMP_INSN0)
100
    {
101
      int adjust;
102
 
103
      switch (buf[0])
104
        {
105
        case LINUX_SIGTRAMP_INSN1:
106
          adjust = LINUX_SIGTRAMP_OFFSET1;
107
          break;
108
        case LINUX_SIGTRAMP_INSN2:
109
          adjust = LINUX_SIGTRAMP_OFFSET2;
110
          break;
111
        default:
112
          return 0;
113
        }
114
 
115
      pc -= adjust;
116
 
117
      if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
118
        return 0;
119
    }
120
 
121
  if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
122
    return 0;
123
 
124
  return pc;
125
}
126
 
127
/* This function does the same for RT signals.  Here the instruction
128
   sequence is
129
       mov    $0xad,%eax
130
       int    $0x80
131
   or 0xb8 0xad 0x00 0x00 0x00 0xcd 0x80.
132
 
133
   The effect is to call the system call rt_sigreturn.  */
134
 
135
#define LINUX_RT_SIGTRAMP_INSN0 (0xb8)  /* mov $NNNN,%eax */
136
#define LINUX_RT_SIGTRAMP_OFFSET0 (0)
137
#define LINUX_RT_SIGTRAMP_INSN1 (0xcd)  /* int */
138
#define LINUX_RT_SIGTRAMP_OFFSET1 (5)
139
 
140
static const unsigned char linux_rt_sigtramp_code[] =
141
{
142
  LINUX_RT_SIGTRAMP_INSN0, 0xad, 0x00, 0x00, 0x00,      /* mov $0xad,%eax */
143
  LINUX_RT_SIGTRAMP_INSN1, 0x80                         /* int $0x80 */
144
};
145
 
146
#define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
147
 
148
/* If PC is in a RT sigtramp routine, return the address of the start
149
   of the routine.  Otherwise, return 0.  */
150
 
151
static CORE_ADDR
152
i386_linux_rt_sigtramp_start (CORE_ADDR pc)
153
{
154
  unsigned char buf[LINUX_RT_SIGTRAMP_LEN];
155
 
156
  /* We only recognize a signal trampoline if PC is at the start of
157
     one of the two instructions.  We optimize for finding the PC at
158
     the start, as will be the case when the trampoline is not the
159
     first frame on the stack.  We assume that in the case where the
160
     PC is not at the start of the instruction sequence, there will be
161
     a few trailing readable bytes on the stack.  */
162
 
163
  if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
164
    return 0;
165
 
166
  if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
167
    {
168
      if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
169
        return 0;
170
 
171
      pc -= LINUX_RT_SIGTRAMP_OFFSET1;
172
 
173
      if (read_memory_nobpt (pc, (char *) buf, LINUX_RT_SIGTRAMP_LEN) != 0)
174
        return 0;
175
    }
176
 
177
  if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
178
    return 0;
179
 
180
  return pc;
181
}
182
 
183
/* Return whether PC is in a Linux sigtramp routine.  */
184
 
185
int
186
i386_linux_in_sigtramp (CORE_ADDR pc, char *name)
187
{
188
  if (name)
189
    return STREQ ("__restore", name) || STREQ ("__restore_rt", name);
190
 
191
  return (i386_linux_sigtramp_start (pc) != 0
192
          || i386_linux_rt_sigtramp_start (pc) != 0);
193
}
194
 
195
/* Assuming FRAME is for a Linux sigtramp routine, return the address
196
   of the associated sigcontext structure.  */
197
 
198
CORE_ADDR
199
i386_linux_sigcontext_addr (struct frame_info *frame)
200
{
201
  CORE_ADDR pc;
202
 
203
  pc = i386_linux_sigtramp_start (frame->pc);
204
  if (pc)
205
    {
206
      CORE_ADDR sp;
207
 
208
      if (frame->next)
209
        /* If this isn't the top frame, the next frame must be for the
210
           signal handler itself.  The sigcontext structure lives on
211
           the stack, right after the signum argument.  */
212
        return frame->next->frame + 12;
213
 
214
      /* This is the top frame.  We'll have to find the address of the
215
         sigcontext structure by looking at the stack pointer.  Keep
216
         in mind that the first instruction of the sigtramp code is
217
         "pop %eax".  If the PC is at this instruction, adjust the
218
         returned value accordingly.  */
219
      sp = read_register (SP_REGNUM);
220
      if (pc == frame->pc)
221
        return sp + 4;
222
      return sp;
223
    }
224
 
225
  pc = i386_linux_rt_sigtramp_start (frame->pc);
226
  if (pc)
227
    {
228
      if (frame->next)
229
        /* If this isn't the top frame, the next frame must be for the
230
           signal handler itself.  The sigcontext structure is part of
231
           the user context.  A pointer to the user context is passed
232
           as the third argument to the signal handler.  */
233
        return read_memory_integer (frame->next->frame + 16, 4) + 20;
234
 
235
      /* This is the top frame.  Again, use the stack pointer to find
236
         the address of the sigcontext structure.  */
237
      return read_memory_integer (read_register (SP_REGNUM) + 8, 4) + 20;
238
    }
239
 
240
  error ("Couldn't recognize signal trampoline.");
241
  return 0;
242
}
243
 
244
/* Offset to saved PC in sigcontext, from <asm/sigcontext.h>.  */
245
#define LINUX_SIGCONTEXT_PC_OFFSET (56)
246
 
247
/* Assuming FRAME is for a Linux sigtramp routine, return the saved
248
   program counter.  */
249
 
250
CORE_ADDR
251
i386_linux_sigtramp_saved_pc (struct frame_info *frame)
252
{
253
  CORE_ADDR addr;
254
  addr = i386_linux_sigcontext_addr (frame);
255
  return read_memory_integer (addr + LINUX_SIGCONTEXT_PC_OFFSET, 4);
256
}
257
 
258
/* Offset to saved SP in sigcontext, from <asm/sigcontext.h>.  */
259
#define LINUX_SIGCONTEXT_SP_OFFSET (28)
260
 
261
/* Assuming FRAME is for a Linux sigtramp routine, return the saved
262
   stack pointer.  */
263
 
264
CORE_ADDR
265
i386_linux_sigtramp_saved_sp (struct frame_info *frame)
266
{
267
  CORE_ADDR addr;
268
  addr = i386_linux_sigcontext_addr (frame);
269
  return read_memory_integer (addr + LINUX_SIGCONTEXT_SP_OFFSET, 4);
270
}
271
 
272
/* Immediately after a function call, return the saved pc.  */
273
 
274
CORE_ADDR
275
i386_linux_saved_pc_after_call (struct frame_info *frame)
276
{
277
  if (frame->signal_handler_caller)
278
    return i386_linux_sigtramp_saved_pc (frame);
279
 
280
  return read_memory_integer (read_register (SP_REGNUM), 4);
281
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.