]> git.pld-linux.org Git - packages/gdb.git/blob - gdb-sigtramp.patch
- X doesn't seem to be used, disable it explicitly (and kill BR)
[packages/gdb.git] / gdb-sigtramp.patch
1 1999-07-29  Jim Blandy  <jimb@savonarola.red-bean.com>
2
3         Change from Ian Lance Taylor <ian@zembu.com>.  The
4         i386_linux_sigtramp* functions should be moved to
5         i386-linux-tdep.c, when that file is introduced.
6
7         * config/i386/tm-linux.h (LINUX_SIGCONTEXT_SIZE): Define.
8         (LINUX_SIGCONTEXT_PC_OFFSET): Define.
9         (LINUX_SIGCONTEXT_SP_OFFSET): Define.
10         (SIGCONTEXT_PC_OFFSET): Don't define.
11         (I386_LINUX_SIGTRAMP): Define.
12         (IN_SIGTRAMP): Define.
13         (i386_linux_sigtramp): Declare.
14         (sigtramp_saved_pc): Define.
15         (i386_linux_sigtramp_saved_pc): Declare.
16         (FRAMELESS_SIGNAL): Define.
17         (FRAME_CHAIN, FRAME_SAVED_PC): Define after #undef.
18         * i386-tdep.c (i386_linux_sigtramp_start): New static function if
19         I386_LINUX_SIGTRAMP.
20         (i386_linux_sigtramp): New function if I386_LINUX_SIGTRAMP.
21         (i386_linux_sigtramp_saved_pc): Likewise.
22         (i386_linux_sigtramp_saved_sp): Likewise.
23
24 ===================================================================
25 RCS file: /cvs/gdb/gdb/gdb/config/i386/tm-linux.h,v
26 retrieving revision 1.1.1.2
27 retrieving revision 1.1.1.3
28 diff -c -r1.1.1.2 -r1.1.1.3
29 *** gdb-4.18/gdb/config/i386/tm-linux.h 1999/07/07 20:13:20     1.1.1.2
30 --- gdb-4.18/gdb/config/i386/tm-linux.h 1999/08/02 23:46:27     1.1.1.3
31 ***************
32 *** 26,39 ****
33   
34   #include "i386/tm-i386.h"
35   
36 ! /* Offset to saved PC in sigcontext, from <linux/signal.h>.  */
37 ! #define SIGCONTEXT_PC_OFFSET 38
38   
39   /* We need this file for the SOLIB_TRAMPOLINE stuff. */
40   
41   #include "tm-sysv4.h"
42   
43   /* The following works around a problem with /usr/include/sys/procfs.h  */
44   #define sys_quotactl 1
45   
46   #endif /* #ifndef TM_LINUX_H */
47 --- 26,107 ----
48   
49   #include "i386/tm-i386.h"
50   
51 ! /* Size of sigcontext, from <asm/sigcontext.h>.  */
52 ! #define LINUX_SIGCONTEXT_SIZE (88)
53   
54 + /* Offset to saved PC in sigcontext, from <asm/sigcontext.h>.  */
55 + #define LINUX_SIGCONTEXT_PC_OFFSET (56)
56
57 + /* Offset to saved SP in sigcontext, from <asm/sigcontext.h>.  */
58 + #define LINUX_SIGCONTEXT_SP_OFFSET (28)
59
60   /* We need this file for the SOLIB_TRAMPOLINE stuff. */
61   
62   #include "tm-sysv4.h"
63   
64   /* The following works around a problem with /usr/include/sys/procfs.h  */
65   #define sys_quotactl 1
66
67 + /* When the i386 Linux kernel calls a signal handler, the return
68 +    address points to a bit of code on the stack.  These definitions
69 +    are used to identify this bit of code as a signal trampoline in
70 +    order to support backtracing through calls to signal handlers.  */
71
72 + #define I386_LINUX_SIGTRAMP
73 + #define IN_SIGTRAMP(pc, name) ((name) == NULL && i386_linux_sigtramp (pc))
74
75 + extern int i386_linux_sigtramp PARAMS ((CORE_ADDR));
76
77 + /* We need our own version of sigtramp_saved_pc to get the saved PC in
78 +    a sigtramp routine.  */
79
80 + #define sigtramp_saved_pc i386_linux_sigtramp_saved_pc
81 + extern CORE_ADDR i386_linux_sigtramp_saved_pc PARAMS ((struct frame_info *));
82
83 + /* Signal trampolines don't have a meaningful frame.  As in tm-i386.h,
84 +    the frame pointer value we use is actually the frame pointer of the
85 +    calling frame--that is, the frame which was in progress when the
86 +    signal trampoline was entered.  gdb mostly treats this frame
87 +    pointer value as a magic cookie.  We detect the case of a signal
88 +    trampoline by looking at the SIGNAL_HANDLER_CALLER field, which is
89 +    set based on IN_SIGTRAMP.
90
91 +    When a signal trampoline is invoked from a frameless function, we
92 +    essentially have two frameless functions in a row.  In this case,
93 +    we use the same magic cookie for three frames in a row.  We detect
94 +    this case by seeing whether the next frame has
95 +    SIGNAL_HANDLER_CALLER set, and, if it does, checking whether the
96 +    current frame is actually frameless.  In this case, we need to get
97 +    the PC by looking at the SP register value stored in the signal
98 +    context.
99
100 +    This should work in most cases except in horrible situations where
101 +    a signal occurs just as we enter a function but before the frame
102 +    has been set up.  */
103
104 + #define FRAMELESS_SIGNAL(FRAME)                                       \
105 +   ((FRAME)->next != NULL                                      \
106 +    && (FRAME)->next->signal_handler_caller                    \
107 +    && frameless_look_for_prologue (FRAME))
108
109 + #undef FRAME_CHAIN
110 + #define FRAME_CHAIN(FRAME)                                    \
111 +   ((FRAME)->signal_handler_caller                             \
112 +    ? (FRAME)->frame                                           \
113 +     : (FRAMELESS_SIGNAL (FRAME)                                       \
114 +        ? (FRAME)->frame                                               \
115 +        : (!inside_entry_file ((FRAME)->pc)                    \
116 +         ? read_memory_integer ((FRAME)->frame, 4)             \
117 +         : 0)))
118
119 + #undef FRAME_SAVED_PC
120 + #define FRAME_SAVED_PC(FRAME)                                 \
121 +   ((FRAME)->signal_handler_caller                             \
122 +    ? sigtramp_saved_pc (FRAME)                                        \
123 +    : (FRAMELESS_SIGNAL (FRAME)                                        \
124 +       ? read_memory_integer (i386_linux_sigtramp_saved_sp ((FRAME)->next), 4) \
125 +       : read_memory_integer ((FRAME)->frame + 4, 4)))
126
127 + extern CORE_ADDR i386_linux_sigtramp_saved_sp PARAMS ((struct frame_info *));
128   
129   #endif /* #ifndef TM_LINUX_H */
130 Index: i386-tdep.c
131 ===================================================================
132 RCS file: /cvs/gdb/gdb/gdb/i386-tdep.c,v
133 retrieving revision 1.1.1.4
134 retrieving revision 1.1.1.5
135 diff -c -r1.1.1.4 -r1.1.1.5
136 *** gdb-4.18/gdb/i386-tdep.c    1999/07/07 20:06:55     1.1.1.4
137 --- gdb-4.18/gdb/i386-tdep.c    1999/08/02 23:45:36     1.1.1.5
138 ***************
139 *** 722,727 ****
140 --- 722,861 ----
141   }
142   #endif /* I386V4_SIGTRAMP_SAVED_PC */
143   
144 + #ifdef I386_LINUX_SIGTRAMP
145
146 + /* When the i386 Linux kernel calls a signal handler, the return
147 +    address points to a bit of code on the stack.  This function
148 +    returns whether the PC appears to be within this bit of code.
149
150 +    The instruction sequence is
151 +        pop    %eax
152 +        mov    $0x77,%eax
153 +        int    $0x80
154 +    or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
155
156 +    Checking for the code sequence should be somewhat reliable, because
157 +    the effect is to call the system call sigreturn.  This is unlikely
158 +    to occur anywhere other than a signal trampoline.
159
160 +    It kind of sucks that we have to read memory from the process in
161 +    order to identify a signal trampoline, but there doesn't seem to be
162 +    any other way.  The IN_SIGTRAMP macro in tm-linux.h arranges to
163 +    only call us if no function name could be identified, which should
164 +    be the case since the code is on the stack.  */
165
166 + #define LINUX_SIGTRAMP_INSN0 (0x58)   /* pop %eax */
167 + #define LINUX_SIGTRAMP_OFFSET0 (0)
168 + #define LINUX_SIGTRAMP_INSN1 (0xb8)   /* mov $NNNN,%eax */
169 + #define LINUX_SIGTRAMP_OFFSET1 (1)
170 + #define LINUX_SIGTRAMP_INSN2 (0xcd)   /* int */
171 + #define LINUX_SIGTRAMP_OFFSET2 (6)
172
173 + static const unsigned char linux_sigtramp_code[] =
174 + {
175 +   LINUX_SIGTRAMP_INSN0,                                       /* pop %eax */
176 +   LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00,               /* mov $0x77,%eax */
177 +   LINUX_SIGTRAMP_INSN2, 0x80                          /* int $0x80 */
178 + };
179
180 + #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
181
182 + /* If PC is in a sigtramp routine, return the address of the start of
183 +    the routine.  Otherwise, return 0.  */
184
185 + static CORE_ADDR
186 + i386_linux_sigtramp_start (pc)
187 +      CORE_ADDR pc;
188 + {
189 +   unsigned char buf[LINUX_SIGTRAMP_LEN];
190
191 +   /* We only recognize a signal trampoline if PC is at the start of
192 +      one of the three instructions.  We optimize for finding the PC at
193 +      the start, as will be the case when the trampoline is not the
194 +      first frame on the stack.  We assume that in the case where the
195 +      PC is not at the start of the instruction sequence, there will be
196 +      a few trailing readable bytes on the stack.  */
197
198 +   if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
199 +     return 0;
200
201 +   if (buf[0] != LINUX_SIGTRAMP_INSN0)
202 +     {
203 +       int adjust;
204
205 +       switch (buf[0])
206 +       {
207 +       case LINUX_SIGTRAMP_INSN1:
208 +         adjust = LINUX_SIGTRAMP_OFFSET1;
209 +         break;
210 +       case LINUX_SIGTRAMP_INSN2:
211 +         adjust = LINUX_SIGTRAMP_OFFSET2;
212 +         break;
213 +       default:
214 +         return 0;
215 +       }
216
217 +       pc -= adjust;
218
219 +       if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
220 +       return 0;
221 +     }
222
223 +   if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
224 +     return 0;
225
226 +   return pc;
227 + }
228
229 + /* Return whether PC is in a Linux sigtramp routine.  */
230
231 + int
232 + i386_linux_sigtramp (pc)
233 +      CORE_ADDR pc;
234 + {
235 +   return i386_linux_sigtramp_start (pc) != 0;
236 + }
237
238 + /* Assuming FRAME is for a Linux sigtramp routine, return the saved
239 +    program counter.  The Linux kernel will set up a sigcontext
240 +    structure immediately before the sigtramp routine on the stack.  */
241
242 + CORE_ADDR
243 + i386_linux_sigtramp_saved_pc (frame)
244 +      struct frame_info *frame;
245 + {
246 +   CORE_ADDR pc;
247
248 +   pc = i386_linux_sigtramp_start (frame->pc);
249 +   if (pc == 0)
250 +     error ("i386_linux_sigtramp_saved_pc called when no sigtramp");
251 +   return read_memory_integer ((pc
252 +                              - LINUX_SIGCONTEXT_SIZE
253 +                              + LINUX_SIGCONTEXT_PC_OFFSET),
254 +                             4);
255 + }
256
257 + /* Assuming FRAME is for a Linux sigtramp routine, return the saved
258 +    stack pointer.  The Linux kernel will set up a sigcontext structure
259 +    immediately before the sigtramp routine on the stack.  */
260
261 + CORE_ADDR
262 + i386_linux_sigtramp_saved_sp (frame)
263 +      struct frame_info *frame;
264 + {
265 +   CORE_ADDR pc;
266
267 +   pc = i386_linux_sigtramp_start (frame->pc);
268 +   if (pc == 0)
269 +     error ("i386_linux_sigtramp_saved_sp called when no sigtramp");
270 +   return read_memory_integer ((pc
271 +                              - LINUX_SIGCONTEXT_SIZE
272 +                              + LINUX_SIGCONTEXT_SP_OFFSET),
273 +                             4);
274 + }
275
276 + #endif /* I386_LINUX_SIGTRAMP */
277
278   #ifdef STATIC_TRANSFORM_NAME
279   /* SunPRO encodes the static variables.  This is not related to C++ mangling,
280      it is done for C too.  */
This page took 0.0543979999999999 seconds and 3 git commands to generate.