2004-02-14 Elena Zannoni <ezannoni@redhat.com>
[platform/upstream/binutils.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)
130           || (chain != 0
131               && !deprecated_inside_entry_file (read_memory_integer
132                                                 (thisframe->frame + 4, 4))));
133 }
134
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.  */
139 static void
140 i386_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     {
152       frame->pc = DEPRECATED_SAVED_PC_AFTER_CALL (frame->next);
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?  */
165           ra = DEPRECATED_SAVED_PC_AFTER_CALL (frame);
166           if (ra >= null_start && ra < null_end)
167             deprecated_set_frame_type (frame, SIGTRAMP_FRAME);
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)
175             deprecated_set_frame_type (frame, SIGTRAMP_FRAME);
176         }
177       return;
178     }
179
180   if (!(get_frame_type (frame->next) == SIGTRAMP_FRAME))
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
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.  */
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
308 static CORE_ADDR
309 i386_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).  */
314   if ((get_frame_type (fi) == SIGTRAMP_FRAME))
315     return fi->next ? fi->next->pc : 0;
316   else
317     return read_memory_integer (fi->frame + 4, 4);
318 }
319
320 static void
321 i386_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
328   set_gdbarch_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
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);
333   set_gdbarch_deprecated_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
334   set_gdbarch_deprecated_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
335   set_gdbarch_deprecated_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
336   set_gdbarch_name_of_malloc (gdbarch, "_malloc");
337 }
338
339 static enum gdb_osabi
340 i386_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
350 void
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
356   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_INTERIX,
357                           i386_interix_init_abi);
358 }