2004-04-30 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / i386-interix-tdep.c
1 /* Target-dependent code for Interix running on i386's, for GDB.
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, Boston, MA 02111-1307, USA. */
19
20 #include "defs.h"
21 #include "arch-utils.h"
22
23 #include "frame.h"
24 #include "gdb_string.h"
25 #include "gdb-stabs.h"
26 #include "gdbcore.h"
27 #include "gdbtypes.h"
28 #include "i386-tdep.h"
29 #include "inferior.h"
30 #include "libbfd.h"
31 #include "objfiles.h"
32 #include "osabi.h"
33 #include "regcache.h"
34
35 /* offsetof (mcontext_t, gregs.gregs[EBP]) */
36 static const int mcontext_EBP_greg_offset = 180;
37
38 /* offsetof (mcontext_t, gregs.gregs[EIP]) */
39 static const int mcontext_EIP_greg_offset = 184;
40
41 /* offsetof (mcontext_t, gregs.gregs[UESP]) */
42 static const int mcontext_UESP_greg_offset = 196;
43
44 /* offsetof (mcontext_t, gregs.reserved[1]) */
45 static const int mcontext_syscall_greg_offset = 4;
46
47 /* offsetof (_JUMP_BUFFER, Eip) */
48 static const int jump_buffer_Eip_offset = 20;
49
50 /* See procfs.c and *interix*.h in config/[alpha,i386]. */
51 /* ??? These should be static, but this needs a bit of work before this
52 can be done. */
53 CORE_ADDR tramp_start;
54 CORE_ADDR tramp_end;
55 CORE_ADDR null_start;
56 CORE_ADDR null_end;
57 int winver; /* Windows NT version number */
58
59 /* Forward declarations. */
60 extern void _initialize_i386_interix_tdep (void);
61 extern initialize_file_ftype _initialize_i386_interix_tdep;
62
63 /* Adjust the section offsets in an objfile structure so that it's correct
64 for the type of symbols being read (or undo it with the _restore
65 arguments).
66
67 If main programs ever start showing up at other than the default Image
68 Base, this is where that would likely be applied. */
69
70 void
71 pei_adjust_objfile_offsets (struct objfile *objfile,
72 enum objfile_adjusts type)
73 {
74 int i;
75 CORE_ADDR symbols_offset;
76
77 switch (type)
78 {
79 case adjust_for_symtab:
80 symbols_offset = NONZERO_LINK_BASE (objfile->obfd);
81 break;
82 case adjust_for_symtab_restore:
83 symbols_offset = -NONZERO_LINK_BASE (objfile->obfd);
84 break;
85 case adjust_for_stabs:
86 case adjust_for_stabs_restore:
87 case adjust_for_dwarf:
88 case adjust_for_dwarf_restore:
89 default:
90 return;
91 }
92
93 for (i = 0; i < objfile->num_sections; i++)
94 {
95 (objfile->section_offsets)->offsets[i] += symbols_offset;
96 }
97 }
98
99 static int
100 i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
101 {
102 /* This is sufficient, where used, but is NOT a complete test; There
103 is more in DEPRECATED_INIT_EXTRA_FRAME_INFO
104 (a.k.a. interix_back_one_frame). */
105 return ((pc >= tramp_start && pc < tramp_end)
106 || (pc >= null_start && pc < null_end));
107 }
108
109 static int
110 i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
111 {
112 return i386_pe_skip_trampoline_code (pc, name);
113 }
114
115 static CORE_ADDR
116 i386_interix_skip_trampoline_code (CORE_ADDR pc)
117 {
118 return i386_pe_skip_trampoline_code (pc, 0);
119 }
120
121 static int
122 i386_interix_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
123 {
124 /* In the context where this is used, we get the saved PC before we've
125 successfully unwound far enough to be sure what we've got (it may
126 be a signal handler caller). If we're dealing with a signal
127 handler caller, this will return valid, which is fine. If not,
128 it'll make the correct test. */
129 return ((get_frame_type (thisframe) == SIGTRAMP_FRAME) || chain != 0);
130 }
131
132 /* We want to find the previous frame, which on Interix is tricky when
133 signals are involved; set frame->frame appropriately, and also get
134 the pc and tweak tye frame's type; this replaces a boatload of
135 nested macros, as well. */
136 static void
137 i386_interix_back_one_frame (int fromleaf, struct frame_info *frame)
138 {
139 CORE_ADDR ra;
140 CORE_ADDR fm;
141 CORE_ADDR context;
142 long t;
143
144 if (frame == NULL)
145 internal_error (__FILE__, __LINE__, "unexpected NULL frame");
146
147 if (fromleaf)
148 {
149 frame->pc = DEPRECATED_SAVED_PC_AFTER_CALL (frame->next);
150 return;
151 }
152
153 if (!frame->next)
154 {
155 frame->pc = read_pc ();
156
157 /* Part of the signal stuff... See below. */
158 if (stopped_by_random_signal)
159 {
160 /* We know we're in a system call mini-frame; was it
161 NullApi or something else? */
162 ra = DEPRECATED_SAVED_PC_AFTER_CALL (frame);
163 if (ra >= null_start && ra < null_end)
164 deprecated_set_frame_type (frame, SIGTRAMP_FRAME);
165 /* There might also be an indirect call to the mini-frame,
166 putting one more return address on the stack. (XP only,
167 I think?) This can't (reasonably) return the address of the
168 signal handler caller unless it's that situation, so this
169 is safe. */
170 ra = read_memory_unsigned_integer (read_register (SP_REGNUM) + 4, 4);
171 if (ra >= null_start && ra < null_end)
172 deprecated_set_frame_type (frame, SIGTRAMP_FRAME);
173 }
174 return;
175 }
176
177 if (!(get_frame_type (frame->next) == SIGTRAMP_FRAME))
178 {
179 frame->pc = read_memory_integer (frame->next->frame + 4, 4);
180 return;
181 }
182
183 /* This is messy (actually AWFUL)... The "trampoline" might be 2, 3
184 or all 5 entities on the frame.
185
186 Chunk 1 will be present when we're actually in a signal handler.
187 Chunk 2 will be present when an asynchronous signal (one that
188 didn't come in with a system call) is present.
189 We may not (yet) be in the handler, if we're just returning
190 from the call.
191 When we're actually in a handler taken from an asynchronous
192 signal, both will be present.
193
194 Chunk 1:
195 PdxSignalDeliverer's frame
196 + Context struct -- not accounted for in any frame
197
198 Chunk 2:
199 + PdxNullPosixApi's frame
200 + PdxNullApiCaller's frame
201 + Context struct = 0x230 not accounted for in any frame
202
203 The symbol names come from examining objdumps of psxdll.dll;
204 they don't appear in the runtime image.
205
206 For gdb's purposes, we can pile all this into one frame. */
207
208 ra = frame->next->pc;
209 /* Are we already pointing at PdxNullPosixApi? We are if
210 this is a signal frame, we're at next-to-top, and were stopped
211 by a random signal (if it wasn't the right address under
212 these circumstances, we wouldn't be here at all by tests above
213 on the prior frame). */
214 if (frame->next->next == NULL && stopped_by_random_signal)
215 {
216 /* We're pointing at the frame FOR PdxNullApi. */
217 fm = frame->frame;
218 }
219 else
220 {
221 /* No... We must be pointing at the frame that was called
222 by PdxSignalDeliverer; back up across the whole mess. */
223
224 /* Extract the frame for PdxSignalDeliverer. Note:
225 DEPRECATED_FRAME_CHAIN used the "old" frame pointer because
226 we were a deliverer. Get the address of the context record
227 that's on here frameless. */
228 context = read_memory_integer (frame->frame, 4); /* an Arg */
229
230 /* Now extract the frame pointer contained in the context. */
231 fm = read_memory_integer (context + mcontext_EBP_greg_offset, 4);
232
233 ra = read_memory_integer (context + mcontext_EIP_greg_offset, 4);
234
235 /* We need to know if we're in a system call because we'll be
236 in a syscall mini-frame, if so, and the rules are different. */
237 t = (long) read_memory_integer (context + mcontext_syscall_greg_offset,
238 4);
239 /* t contains 0 if running free, 1 if blocked on a system call,
240 and 2 if blocked on an exception message (e.g. a trap);
241 we don't expect to get here with a 2. */
242 if (t != 1)
243 {
244 /* Not at a system call, therefore it can't be NullApi. */
245 frame->pc = ra;
246 frame->frame = fm;
247 return;
248 }
249
250 /* It's a system call... Mini frame, then look for NullApi. */
251 /* Get the RA (on the stack) associated with this... It's
252 a system call mini-frame. */
253 ra = read_memory_integer (context + mcontext_UESP_greg_offset, 4);
254
255 if (winver >= 51)
256 {
257 /* Newer versions of Windows NT interpose another return
258 address (but no other "stack frame" stuff) that we need
259 to simply ignore here. */
260 ra += 4;
261 }
262
263 ra = read_memory_integer (ra, 4);
264
265 if (!(ra >= null_start && ra < null_end))
266 {
267 /* No Null API present; we're done. */
268 frame->pc = ra;
269 frame->frame = fm;
270 return;
271 }
272 }
273
274 /* At this point, we're looking at the frame for PdxNullPosixApi,
275 in either case.
276
277 PdxNullPosixApi is called by PdxNullApiCaller (which in turn
278 is called by _PdxNullApiCaller (note the _).)
279 PdxNullPosixApiCaller (no _) is a frameless function.
280
281 The saved frame pointer is as fm, but it's not of interest
282 to us because it skips us over the saved context, which is
283 the wrong thing to do, because it skips the interrrupted
284 routine! PdxNullApiCaller takes as its only argument the
285 address of the context of the interrupded function (which
286 is really in no frame, but jammed on the stack by the system)
287
288 So: fm+0: saved bp
289 fm+4: return address to _PdxNullApiCaller
290 fm+8: arg to PdxNullApiCaller pushed by _Pdx... */
291
292 fm = read_memory_integer (fm + 0x8, 4);
293
294 /* Extract the second context record. */
295
296 ra = read_memory_integer (fm + mcontext_EIP_greg_offset, 4);
297 fm = read_memory_integer (fm + mcontext_EBP_greg_offset, 4);
298
299 frame->frame = fm;
300 frame->pc = ra;
301
302 return;
303 }
304
305 static CORE_ADDR
306 i386_interix_frame_saved_pc (struct frame_info *fi)
307 {
308 /* Assume that we've already unwound enough to have the caller's address
309 if we're dealing with a signal handler caller (And if that fails,
310 return 0). */
311 if ((get_frame_type (fi) == SIGTRAMP_FRAME))
312 return fi->next ? fi->next->pc : 0;
313 else
314 return read_memory_integer (fi->frame + 4, 4);
315 }
316
317 static void
318 i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
319 {
320 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
321
322 tdep->struct_return = reg_struct_return;
323 tdep->jb_pc_offset = jump_buffer_Eip_offset;
324
325 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
326 set_gdbarch_in_solib_call_trampoline (gdbarch,
327 i386_interix_in_solib_call_trampoline);
328 set_gdbarch_skip_trampoline_code (gdbarch,
329 i386_interix_skip_trampoline_code);
330 set_gdbarch_deprecated_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
331 set_gdbarch_deprecated_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
332 set_gdbarch_deprecated_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
333 set_gdbarch_name_of_malloc (gdbarch, "_malloc");
334 }
335
336 static enum gdb_osabi
337 i386_interix_osabi_sniffer (bfd * abfd)
338 {
339 char *target_name = bfd_get_target (abfd);
340
341 if (strcmp (target_name, "pei-i386") == 0)
342 return GDB_OSABI_INTERIX;
343
344 return GDB_OSABI_UNKNOWN;
345 }
346
347 void
348 _initialize_i386_interix_tdep (void)
349 {
350 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
351 i386_interix_osabi_sniffer);
352
353 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_INTERIX,
354 i386_interix_init_abi);
355 }
This page took 0.036769 seconds and 4 git commands to generate.