2004-04-30 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / gdb / i386-interix-tdep.c
CommitLineData
7a7adcdf
JB
1/* Target-dependent code for Interix running on i386's, for GDB.
2 Copyright 2002 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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]) */
36static const int mcontext_EBP_greg_offset = 180;
37
38/* offsetof (mcontext_t, gregs.gregs[EIP]) */
39static const int mcontext_EIP_greg_offset = 184;
40
41/* offsetof (mcontext_t, gregs.gregs[UESP]) */
42static const int mcontext_UESP_greg_offset = 196;
43
44/* offsetof (mcontext_t, gregs.reserved[1]) */
45static const int mcontext_syscall_greg_offset = 4;
46
47/* offsetof (_JUMP_BUFFER, Eip) */
48static 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. */
53CORE_ADDR tramp_start;
54CORE_ADDR tramp_end;
55CORE_ADDR null_start;
56CORE_ADDR null_end;
57int winver; /* Windows NT version number */
58
59/* Forward declarations. */
60extern void _initialize_i386_interix_tdep (void);
61extern 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
70void
71pei_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
a39a16c4 93 for (i = 0; i < objfile->num_sections; i++)
7a7adcdf
JB
94 {
95 (objfile->section_offsets)->offsets[i] += symbols_offset;
96 }
97}
98
99static int
100i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
101{
102 /* This is sufficient, where used, but is NOT a complete test; There
e9582e71
AC
103 is more in DEPRECATED_INIT_EXTRA_FRAME_INFO
104 (a.k.a. interix_back_one_frame). */
7a7adcdf
JB
105 return ((pc >= tramp_start && pc < tramp_end)
106 || (pc >= null_start && pc < null_end));
107}
108
109static int
110i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
111{
112 return i386_pe_skip_trampoline_code (pc, name);
113}
114
115static CORE_ADDR
116i386_interix_skip_trampoline_code (CORE_ADDR pc)
117{
118 return i386_pe_skip_trampoline_code (pc, 0);
119}
120
7a7adcdf
JB
121static int
122i386_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. */
5a203e44 129 return ((get_frame_type (thisframe) == SIGTRAMP_FRAME)
7a7adcdf 130 || (chain != 0
627b3ba2
AC
131 && !deprecated_inside_entry_file (read_memory_integer
132 (thisframe->frame + 4, 4))));
7a7adcdf
JB
133}
134
5a203e44
AC
135/* We want to find the previous frame, which on Interix is tricky when
136 signals are involved; set frame->frame appropriately, and also get
137 the pc and tweak tye frame's type; this replaces a boatload of
138 nested macros, as well. */
7a7adcdf
JB
139static void
140i386_interix_back_one_frame (int fromleaf, struct frame_info *frame)
141{
142 CORE_ADDR ra;
143 CORE_ADDR fm;
144 CORE_ADDR context;
145 long t;
146
147 if (frame == NULL)
148 internal_error (__FILE__, __LINE__, "unexpected NULL frame");
149
150 if (fromleaf)
151 {
6913c89a 152 frame->pc = DEPRECATED_SAVED_PC_AFTER_CALL (frame->next);
7a7adcdf
JB
153 return;
154 }
155
156 if (!frame->next)
157 {
158 frame->pc = read_pc ();
159
160 /* Part of the signal stuff... See below. */
161 if (stopped_by_random_signal)
162 {
163 /* We know we're in a system call mini-frame; was it
164 NullApi or something else? */
6913c89a 165 ra = DEPRECATED_SAVED_PC_AFTER_CALL (frame);
7a7adcdf 166 if (ra >= null_start && ra < null_end)
5a203e44 167 deprecated_set_frame_type (frame, SIGTRAMP_FRAME);
7a7adcdf
JB
168 /* There might also be an indirect call to the mini-frame,
169 putting one more return address on the stack. (XP only,
170 I think?) This can't (reasonably) return the address of the
171 signal handler caller unless it's that situation, so this
172 is safe. */
173 ra = read_memory_unsigned_integer (read_register (SP_REGNUM) + 4, 4);
174 if (ra >= null_start && ra < null_end)
5a203e44 175 deprecated_set_frame_type (frame, SIGTRAMP_FRAME);
7a7adcdf
JB
176 }
177 return;
178 }
179
5a203e44 180 if (!(get_frame_type (frame->next) == SIGTRAMP_FRAME))
7a7adcdf
JB
181 {
182 frame->pc = read_memory_integer (frame->next->frame + 4, 4);
183 return;
184 }
185
186 /* This is messy (actually AWFUL)... The "trampoline" might be 2, 3
187 or all 5 entities on the frame.
188
189 Chunk 1 will be present when we're actually in a signal handler.
190 Chunk 2 will be present when an asynchronous signal (one that
191 didn't come in with a system call) is present.
192 We may not (yet) be in the handler, if we're just returning
193 from the call.
194 When we're actually in a handler taken from an asynchronous
195 signal, both will be present.
196
197 Chunk 1:
198 PdxSignalDeliverer's frame
199 + Context struct -- not accounted for in any frame
200
201 Chunk 2:
202 + PdxNullPosixApi's frame
203 + PdxNullApiCaller's frame
204 + Context struct = 0x230 not accounted for in any frame
205
206 The symbol names come from examining objdumps of psxdll.dll;
207 they don't appear in the runtime image.
208
209 For gdb's purposes, we can pile all this into one frame. */
210
211 ra = frame->next->pc;
212 /* Are we already pointing at PdxNullPosixApi? We are if
213 this is a signal frame, we're at next-to-top, and were stopped
214 by a random signal (if it wasn't the right address under
215 these circumstances, we wouldn't be here at all by tests above
216 on the prior frame). */
217 if (frame->next->next == NULL && stopped_by_random_signal)
218 {
219 /* We're pointing at the frame FOR PdxNullApi. */
220 fm = frame->frame;
221 }
222 else
223 {
224 /* No... We must be pointing at the frame that was called
225 by PdxSignalDeliverer; back up across the whole mess. */
226
618ce49f
AC
227 /* Extract the frame for PdxSignalDeliverer. Note:
228 DEPRECATED_FRAME_CHAIN used the "old" frame pointer because
229 we were a deliverer. Get the address of the context record
230 that's on here frameless. */
7a7adcdf
JB
231 context = read_memory_integer (frame->frame, 4); /* an Arg */
232
233 /* Now extract the frame pointer contained in the context. */
234 fm = read_memory_integer (context + mcontext_EBP_greg_offset, 4);
235
236 ra = read_memory_integer (context + mcontext_EIP_greg_offset, 4);
237
238 /* We need to know if we're in a system call because we'll be
239 in a syscall mini-frame, if so, and the rules are different. */
240 t = (long) read_memory_integer (context + mcontext_syscall_greg_offset,
241 4);
242 /* t contains 0 if running free, 1 if blocked on a system call,
243 and 2 if blocked on an exception message (e.g. a trap);
244 we don't expect to get here with a 2. */
245 if (t != 1)
246 {
247 /* Not at a system call, therefore it can't be NullApi. */
248 frame->pc = ra;
249 frame->frame = fm;
250 return;
251 }
252
253 /* It's a system call... Mini frame, then look for NullApi. */
254 /* Get the RA (on the stack) associated with this... It's
255 a system call mini-frame. */
256 ra = read_memory_integer (context + mcontext_UESP_greg_offset, 4);
257
258 if (winver >= 51)
259 {
260 /* Newer versions of Windows NT interpose another return
261 address (but no other "stack frame" stuff) that we need
262 to simply ignore here. */
263 ra += 4;
264 }
265
266 ra = read_memory_integer (ra, 4);
267
268 if (!(ra >= null_start && ra < null_end))
269 {
270 /* No Null API present; we're done. */
271 frame->pc = ra;
272 frame->frame = fm;
273 return;
274 }
275 }
276
277 /* At this point, we're looking at the frame for PdxNullPosixApi,
278 in either case.
279
280 PdxNullPosixApi is called by PdxNullApiCaller (which in turn
281 is called by _PdxNullApiCaller (note the _).)
282 PdxNullPosixApiCaller (no _) is a frameless function.
283
284 The saved frame pointer is as fm, but it's not of interest
285 to us because it skips us over the saved context, which is
286 the wrong thing to do, because it skips the interrrupted
287 routine! PdxNullApiCaller takes as its only argument the
288 address of the context of the interrupded function (which
289 is really in no frame, but jammed on the stack by the system)
290
291 So: fm+0: saved bp
292 fm+4: return address to _PdxNullApiCaller
293 fm+8: arg to PdxNullApiCaller pushed by _Pdx... */
294
295 fm = read_memory_integer (fm + 0x8, 4);
296
297 /* Extract the second context record. */
298
299 ra = read_memory_integer (fm + mcontext_EIP_greg_offset, 4);
300 fm = read_memory_integer (fm + mcontext_EBP_greg_offset, 4);
301
302 frame->frame = fm;
303 frame->pc = ra;
304
305 return;
306}
307
308static CORE_ADDR
309i386_interix_frame_saved_pc (struct frame_info *fi)
310{
311 /* Assume that we've already unwound enough to have the caller's address
312 if we're dealing with a signal handler caller (And if that fails,
313 return 0). */
5a203e44 314 if ((get_frame_type (fi) == SIGTRAMP_FRAME))
7a7adcdf
JB
315 return fi->next ? fi->next->pc : 0;
316 else
317 return read_memory_integer (fi->frame + 4, 4);
318}
319
320static void
321i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
322{
323 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
324
325 tdep->struct_return = reg_struct_return;
326 tdep->jb_pc_offset = jump_buffer_Eip_offset;
327
f561f026 328 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
7a7adcdf
JB
329 set_gdbarch_in_solib_call_trampoline (gdbarch,
330 i386_interix_in_solib_call_trampoline);
331 set_gdbarch_skip_trampoline_code (gdbarch,
332 i386_interix_skip_trampoline_code);
e9582e71 333 set_gdbarch_deprecated_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
618ce49f 334 set_gdbarch_deprecated_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
8bedc050 335 set_gdbarch_deprecated_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
7a7adcdf
JB
336 set_gdbarch_name_of_malloc (gdbarch, "_malloc");
337}
338
339static enum gdb_osabi
340i386_interix_osabi_sniffer (bfd * abfd)
341{
342 char *target_name = bfd_get_target (abfd);
343
344 if (strcmp (target_name, "pei-i386") == 0)
345 return GDB_OSABI_INTERIX;
346
347 return GDB_OSABI_UNKNOWN;
348}
349
350void
351_initialize_i386_interix_tdep (void)
352{
353 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
354 i386_interix_osabi_sniffer);
355
05816f70 356 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_INTERIX,
7a7adcdf
JB
357 i386_interix_init_abi);
358}
This page took 0.16073 seconds and 4 git commands to generate.