1 1999-07-29 Jim Blandy <jimb@savonarola.red-bean.com>
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.
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
20 (i386_linux_sigtramp): New function if I386_LINUX_SIGTRAMP.
21 (i386_linux_sigtramp_saved_pc): Likewise.
22 (i386_linux_sigtramp_saved_sp): Likewise.
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
34 #include "i386/tm-i386.h"
36 ! /* Offset to saved PC in sigcontext, from <linux/signal.h>. */
37 ! #define SIGCONTEXT_PC_OFFSET 38
39 /* We need this file for the SOLIB_TRAMPOLINE stuff. */
43 /* The following works around a problem with /usr/include/sys/procfs.h */
44 #define sys_quotactl 1
46 #endif /* #ifndef TM_LINUX_H */
49 #include "i386/tm-i386.h"
51 ! /* Size of sigcontext, from <asm/sigcontext.h>. */
52 ! #define LINUX_SIGCONTEXT_SIZE (88)
54 + /* Offset to saved PC in sigcontext, from <asm/sigcontext.h>. */
55 + #define LINUX_SIGCONTEXT_PC_OFFSET (56)
57 + /* Offset to saved SP in sigcontext, from <asm/sigcontext.h>. */
58 + #define LINUX_SIGCONTEXT_SP_OFFSET (28)
60 /* We need this file for the SOLIB_TRAMPOLINE stuff. */
64 /* The following works around a problem with /usr/include/sys/procfs.h */
65 #define sys_quotactl 1
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. */
72 + #define I386_LINUX_SIGTRAMP
73 + #define IN_SIGTRAMP(pc, name) ((name) == NULL && i386_linux_sigtramp (pc))
75 + extern int i386_linux_sigtramp PARAMS ((CORE_ADDR));
77 + /* We need our own version of sigtramp_saved_pc to get the saved PC in
78 + a sigtramp routine. */
80 + #define sigtramp_saved_pc i386_linux_sigtramp_saved_pc
81 + extern CORE_ADDR i386_linux_sigtramp_saved_pc PARAMS ((struct frame_info *));
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.
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
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. */
104 + #define FRAMELESS_SIGNAL(FRAME) \
105 + ((FRAME)->next != NULL \
106 + && (FRAME)->next->signal_handler_caller \
107 + && frameless_look_for_prologue (FRAME))
110 + #define FRAME_CHAIN(FRAME) \
111 + ((FRAME)->signal_handler_caller \
113 + : (FRAMELESS_SIGNAL (FRAME) \
115 + : (!inside_entry_file ((FRAME)->pc) \
116 + ? read_memory_integer ((FRAME)->frame, 4) \
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)))
127 + extern CORE_ADDR i386_linux_sigtramp_saved_sp PARAMS ((struct frame_info *));
129 #endif /* #ifndef TM_LINUX_H */
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
142 #endif /* I386V4_SIGTRAMP_SAVED_PC */
144 + #ifdef I386_LINUX_SIGTRAMP
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.
150 + The instruction sequence is
154 + or 0x58 0xb8 0x77 0x00 0x00 0x00 0xcd 0x80.
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.
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. */
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)
173 + static const unsigned char linux_sigtramp_code[] =
175 + LINUX_SIGTRAMP_INSN0, /* pop %eax */
176 + LINUX_SIGTRAMP_INSN1, 0x77, 0x00, 0x00, 0x00, /* mov $0x77,%eax */
177 + LINUX_SIGTRAMP_INSN2, 0x80 /* int $0x80 */
180 + #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
182 + /* If PC is in a sigtramp routine, return the address of the start of
183 + the routine. Otherwise, return 0. */
186 + i386_linux_sigtramp_start (pc)
189 + unsigned char buf[LINUX_SIGTRAMP_LEN];
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. */
198 + if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
201 + if (buf[0] != LINUX_SIGTRAMP_INSN0)
207 + case LINUX_SIGTRAMP_INSN1:
208 + adjust = LINUX_SIGTRAMP_OFFSET1;
210 + case LINUX_SIGTRAMP_INSN2:
211 + adjust = LINUX_SIGTRAMP_OFFSET2;
219 + if (read_memory_nobpt (pc, (char *) buf, LINUX_SIGTRAMP_LEN) != 0)
223 + if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
229 + /* Return whether PC is in a Linux sigtramp routine. */
232 + i386_linux_sigtramp (pc)
235 + return i386_linux_sigtramp_start (pc) != 0;
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. */
243 + i386_linux_sigtramp_saved_pc (frame)
244 + struct frame_info *frame;
248 + pc = i386_linux_sigtramp_start (frame->pc);
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),
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. */
262 + i386_linux_sigtramp_saved_sp (frame)
263 + struct frame_info *frame;
267 + pc = i386_linux_sigtramp_start (frame->pc);
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),
276 + #endif /* I386_LINUX_SIGTRAMP */
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. */