1 /* Target-dependent code for Interix running on i386's, for GDB.
2 Copyright 2002 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
21 #include "arch-utils.h"
24 #include "gdb_string.h"
25 #include "gdb-stabs.h"
28 #include "i386-tdep.h"
35 /* offsetof (mcontext_t, gregs.gregs[EBP]) */
36 static const int mcontext_EBP_greg_offset
= 180;
38 /* offsetof (mcontext_t, gregs.gregs[EIP]) */
39 static const int mcontext_EIP_greg_offset
= 184;
41 /* offsetof (mcontext_t, gregs.gregs[UESP]) */
42 static const int mcontext_UESP_greg_offset
= 196;
44 /* offsetof (mcontext_t, gregs.reserved[1]) */
45 static const int mcontext_syscall_greg_offset
= 4;
47 /* offsetof (_JUMP_BUFFER, Eip) */
48 static const int jump_buffer_Eip_offset
= 20;
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
53 CORE_ADDR tramp_start
;
57 int winver
; /* Windows NT version number */
59 /* Forward declarations. */
60 extern void _initialize_i386_interix_tdep (void);
61 extern initialize_file_ftype _initialize_i386_interix_tdep
;
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
67 If main programs ever start showing up at other than the default Image
68 Base, this is where that would likely be applied. */
71 pei_adjust_objfile_offsets (struct objfile
*objfile
,
72 enum objfile_adjusts type
)
75 CORE_ADDR symbols_offset
;
79 case adjust_for_symtab
:
80 symbols_offset
= NONZERO_LINK_BASE (objfile
->obfd
);
82 case adjust_for_symtab_restore
:
83 symbols_offset
= -NONZERO_LINK_BASE (objfile
->obfd
);
85 case adjust_for_stabs
:
86 case adjust_for_stabs_restore
:
87 case adjust_for_dwarf
:
88 case adjust_for_dwarf_restore
:
93 for (i
= 0; i
< SECT_OFF_MAX
; i
++)
95 (objfile
->section_offsets
)->offsets
[i
] += symbols_offset
;
100 i386_interix_pc_in_sigtramp (CORE_ADDR pc
, char *name
)
102 /* This is sufficient, where used, but is NOT a complete test; There
103 is more in INIT_EXTRA_FRAME_INFO (a.k.a. interix_back_one_frame). */
104 return ((pc
>= tramp_start
&& pc
< tramp_end
)
105 || (pc
>= null_start
&& pc
< null_end
));
109 i386_interix_in_solib_call_trampoline (CORE_ADDR pc
, char *name
)
111 return i386_pe_skip_trampoline_code (pc
, name
);
115 i386_interix_skip_trampoline_code (CORE_ADDR pc
)
117 return i386_pe_skip_trampoline_code (pc
, 0);
121 i386_interix_init_frame_pc (int fromleaf
, struct frame_info
*prev
)
123 /* Nothing to do on Interix. */
127 i386_interix_frame_chain_valid (CORE_ADDR chain
, struct frame_info
*thisframe
)
129 /* In the context where this is used, we get the saved PC before we've
130 successfully unwound far enough to be sure what we've got (it may
131 be a signal handler caller). If we're dealing with a signal
132 handler caller, this will return valid, which is fine. If not,
133 it'll make the correct test. */
134 return (thisframe
->signal_handler_caller
136 && !inside_entry_file (read_memory_integer
137 (thisframe
->frame
+ 4, 4))));
140 /* We want to find the previous frame, which on Interix is tricky when signals
141 are involved; set frame->frame appropriately, and also get the pc
142 and tweak signal_handler_caller; this replaces a boatload of nested
145 i386_interix_back_one_frame (int fromleaf
, struct frame_info
*frame
)
153 internal_error (__FILE__
, __LINE__
, "unexpected NULL frame");
157 frame
->pc
= SAVED_PC_AFTER_CALL (frame
->next
);
163 frame
->pc
= read_pc ();
165 /* Part of the signal stuff... See below. */
166 if (stopped_by_random_signal
)
168 /* We know we're in a system call mini-frame; was it
169 NullApi or something else? */
170 ra
= SAVED_PC_AFTER_CALL (frame
);
171 if (ra
>= null_start
&& ra
< null_end
)
172 frame
->signal_handler_caller
= 1;
173 /* There might also be an indirect call to the mini-frame,
174 putting one more return address on the stack. (XP only,
175 I think?) This can't (reasonably) return the address of the
176 signal handler caller unless it's that situation, so this
178 ra
= read_memory_unsigned_integer (read_register (SP_REGNUM
) + 4, 4);
179 if (ra
>= null_start
&& ra
< null_end
)
180 frame
->signal_handler_caller
= 1;
185 if (!frame
->next
->signal_handler_caller
)
187 frame
->pc
= read_memory_integer (frame
->next
->frame
+ 4, 4);
191 /* This is messy (actually AWFUL)... The "trampoline" might be 2, 3
192 or all 5 entities on the frame.
194 Chunk 1 will be present when we're actually in a signal handler.
195 Chunk 2 will be present when an asynchronous signal (one that
196 didn't come in with a system call) is present.
197 We may not (yet) be in the handler, if we're just returning
199 When we're actually in a handler taken from an asynchronous
200 signal, both will be present.
203 PdxSignalDeliverer's frame
204 + Context struct -- not accounted for in any frame
207 + PdxNullPosixApi's frame
208 + PdxNullApiCaller's frame
209 + Context struct = 0x230 not accounted for in any frame
211 The symbol names come from examining objdumps of psxdll.dll;
212 they don't appear in the runtime image.
214 For gdb's purposes, we can pile all this into one frame. */
216 ra
= frame
->next
->pc
;
217 /* Are we already pointing at PdxNullPosixApi? We are if
218 this is a signal frame, we're at next-to-top, and were stopped
219 by a random signal (if it wasn't the right address under
220 these circumstances, we wouldn't be here at all by tests above
221 on the prior frame). */
222 if (frame
->next
->next
== NULL
&& stopped_by_random_signal
)
224 /* We're pointing at the frame FOR PdxNullApi. */
229 /* No... We must be pointing at the frame that was called
230 by PdxSignalDeliverer; back up across the whole mess. */
232 /* Extract the frame for PdxSignalDeliverer.
233 Note: FRAME_CHAIN used the "old" frame pointer because we were
234 a deliverer. Get the address of the context record that's on
236 context
= read_memory_integer (frame
->frame
, 4); /* an Arg */
238 /* Now extract the frame pointer contained in the context. */
239 fm
= read_memory_integer (context
+ mcontext_EBP_greg_offset
, 4);
241 ra
= read_memory_integer (context
+ mcontext_EIP_greg_offset
, 4);
243 /* We need to know if we're in a system call because we'll be
244 in a syscall mini-frame, if so, and the rules are different. */
245 t
= (long) read_memory_integer (context
+ mcontext_syscall_greg_offset
,
247 /* t contains 0 if running free, 1 if blocked on a system call,
248 and 2 if blocked on an exception message (e.g. a trap);
249 we don't expect to get here with a 2. */
252 /* Not at a system call, therefore it can't be NullApi. */
258 /* It's a system call... Mini frame, then look for NullApi. */
259 /* Get the RA (on the stack) associated with this... It's
260 a system call mini-frame. */
261 ra
= read_memory_integer (context
+ mcontext_UESP_greg_offset
, 4);
265 /* Newer versions of Windows NT interpose another return
266 address (but no other "stack frame" stuff) that we need
267 to simply ignore here. */
271 ra
= read_memory_integer (ra
, 4);
273 if (!(ra
>= null_start
&& ra
< null_end
))
275 /* No Null API present; we're done. */
282 /* At this point, we're looking at the frame for PdxNullPosixApi,
285 PdxNullPosixApi is called by PdxNullApiCaller (which in turn
286 is called by _PdxNullApiCaller (note the _).)
287 PdxNullPosixApiCaller (no _) is a frameless function.
289 The saved frame pointer is as fm, but it's not of interest
290 to us because it skips us over the saved context, which is
291 the wrong thing to do, because it skips the interrrupted
292 routine! PdxNullApiCaller takes as its only argument the
293 address of the context of the interrupded function (which
294 is really in no frame, but jammed on the stack by the system)
297 fm+4: return address to _PdxNullApiCaller
298 fm+8: arg to PdxNullApiCaller pushed by _Pdx... */
300 fm
= read_memory_integer (fm
+ 0x8, 4);
302 /* Extract the second context record. */
304 ra
= read_memory_integer (fm
+ mcontext_EIP_greg_offset
, 4);
305 fm
= read_memory_integer (fm
+ mcontext_EBP_greg_offset
, 4);
314 i386_interix_frame_saved_pc (struct frame_info
*fi
)
316 /* Assume that we've already unwound enough to have the caller's address
317 if we're dealing with a signal handler caller (And if that fails,
319 if (fi
->signal_handler_caller
)
320 return fi
->next
? fi
->next
->pc
: 0;
322 return read_memory_integer (fi
->frame
+ 4, 4);
326 i386_interix_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
328 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
330 tdep
->struct_return
= reg_struct_return
;
331 tdep
->jb_pc_offset
= jump_buffer_Eip_offset
;
333 set_gdbarch_decr_pc_after_break (gdbarch
, 0);
334 set_gdbarch_pc_in_sigtramp (gdbarch
, i386_interix_pc_in_sigtramp
);
335 set_gdbarch_in_solib_call_trampoline (gdbarch
,
336 i386_interix_in_solib_call_trampoline
);
337 set_gdbarch_skip_trampoline_code (gdbarch
,
338 i386_interix_skip_trampoline_code
);
339 set_gdbarch_init_extra_frame_info (gdbarch
, i386_interix_back_one_frame
);
340 set_gdbarch_init_frame_pc (gdbarch
, i386_interix_init_frame_pc
);
341 set_gdbarch_frame_chain_valid (gdbarch
, i386_interix_frame_chain_valid
);
342 set_gdbarch_frame_saved_pc (gdbarch
, i386_interix_frame_saved_pc
);
343 set_gdbarch_name_of_malloc (gdbarch
, "_malloc");
346 static enum gdb_osabi
347 i386_interix_osabi_sniffer (bfd
* abfd
)
349 char *target_name
= bfd_get_target (abfd
);
351 if (strcmp (target_name
, "pei-i386") == 0)
352 return GDB_OSABI_INTERIX
;
354 return GDB_OSABI_UNKNOWN
;
358 _initialize_i386_interix_tdep (void)
360 gdbarch_register_osabi_sniffer (bfd_arch_i386
, bfd_target_coff_flavour
,
361 i386_interix_osabi_sniffer
);
363 gdbarch_register_osabi (bfd_arch_i386
, GDB_OSABI_INTERIX
,
364 i386_interix_init_abi
);