]> git.pld-linux.org Git - packages/gdb.git/blame - gdb-sigtramp.patch
- merge translations from Conectiva.
[packages/gdb.git] / gdb-sigtramp.patch
CommitLineData
0f840cc8 11999-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===================================================================
25RCS file: /cvs/gdb/gdb/gdb/config/i386/tm-linux.h,v
26retrieving revision 1.1.1.2
27retrieving revision 1.1.1.3
28diff -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 */
130Index: i386-tdep.c
131===================================================================
132RCS file: /cvs/gdb/gdb/gdb/i386-tdep.c,v
133retrieving revision 1.1.1.4
134retrieving revision 1.1.1.5
135diff -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.113541 seconds and 4 git commands to generate.