gdb/
[deliverable/binutils-gdb.git] / gdb / i386-cygwin-tdep.c
CommitLineData
1762d96d 1/* Target-dependent code for Cygwin running on i386's, for GDB.
acd5c798 2
4c38e0a4 3 Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
1762d96d 4
acd5c798 5 This file is part of GDB.
1762d96d 6
acd5c798
MK
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
acd5c798 10 (at your option) any later version.
1762d96d 11
acd5c798
MK
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
1762d96d 16
acd5c798 17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
1762d96d
CV
19
20#include "defs.h"
1762d96d 21#include "osabi.h"
acd5c798 22#include "gdb_string.h"
acd5c798 23#include "i386-tdep.h"
31b060a2 24#include "windows-tdep.h"
de584861
PA
25#include "regset.h"
26#include "gdb_obstack.h"
27#include "xml-support.h"
28#include "gdbcore.h"
8d465389
UW
29#include "solib.h"
30#include "solib-target.h"
de584861
PA
31
32/* Core file support. */
33
34/* This vector maps GDB's idea of a register's number into an address
dc05df57 35 in the windows exception context vector. */
de584861 36
dc05df57 37static int i386_windows_gregset_reg_offset[] =
de584861
PA
38{
39 176, /* eax */
40 172, /* ecx */
41 168, /* edx */
42 164, /* ebx */
43
44 196, /* esp */
45 180, /* ebp */
46 160, /* esi */
47 156, /* edi */
48
49 184, /* eip */
50 192, /* eflags */
51 188, /* cs */
52 200, /* ss */
53
54 152, /* ds */
55 148, /* es */
56 144, /* fs */
57 140, /* gs */
58
59 56, /* FloatSave.RegisterArea[0 * 10] */
60 66, /* FloatSave.RegisterArea[1 * 10] */
61 76, /* FloatSave.RegisterArea[2 * 10] */
62 86, /* FloatSave.RegisterArea[3 * 10] */
63 96, /* FloatSave.RegisterArea[4 * 10] */
64 106, /* FloatSave.RegisterArea[5 * 10] */
65 116, /* FloatSave.RegisterArea[6 * 10] */
66 126, /* FloatSave.RegisterArea[7 * 10] */
67
68 28, /* FloatSave.ControlWord */
69 32, /* FloatSave.StatusWord */
70 36, /* FloatSave.TagWord */
71 44, /* FloatSave.ErrorSelector */
72 40, /* FloatSave.ErrorOffset */
73 52, /* FloatSave.DataSelector */
74 48, /* FloatSave.DataOffset */
75 44, /* FloatSave.ErrorSelector */
76
77 /* XMM0-7 */
78 364, /* ExtendedRegisters[10*16] */
79 380, /* ExtendedRegisters[11*16] */
80 396, /* ExtendedRegisters[12*16] */
81 412, /* ExtendedRegisters[13*16] */
82 428, /* ExtendedRegisters[14*16] */
83 444, /* ExtendedRegisters[15*16] */
84 460, /* ExtendedRegisters[16*16] */
85 476, /* ExtendedRegisters[17*16] */
86
87 /* MXCSR */
88 228 /* ExtendedRegisters[24] */
89};
90
dc05df57 91#define I386_WINDOWS_SIZEOF_GREGSET 716
de584861
PA
92
93/* Return the appropriate register set for the core section identified
94 by SECT_NAME and SECT_SIZE. */
95
96static const struct regset *
dc05df57 97i386_windows_regset_from_core_section (struct gdbarch *gdbarch,
de584861
PA
98 const char *sect_name, size_t sect_size)
99{
100 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
101
102 if (strcmp (sect_name, ".reg") == 0
dc05df57 103 && sect_size == I386_WINDOWS_SIZEOF_GREGSET)
de584861
PA
104 {
105 if (tdep->gregset == NULL)
106 tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
107 i386_collect_gregset);
108 return tdep->gregset;
109 }
110
111 return NULL;
112}
113
de584861
PA
114struct cpms_data
115{
5af949e3 116 struct gdbarch *gdbarch;
de584861
PA
117 struct obstack *obstack;
118 int module_count;
119};
120
121static void
122core_process_module_section (bfd *abfd, asection *sect, void *obj)
123{
124 struct cpms_data *data = obj;
e17a4113 125 enum bfd_endian byte_order = gdbarch_byte_order (data->gdbarch);
de584861
PA
126
127 char *module_name;
128 size_t module_name_size;
129 CORE_ADDR base_addr;
130
131 char *buf = NULL;
132
133 if (strncmp (sect->name, ".module", 7) != 0)
134 return;
135
136 buf = xmalloc (bfd_get_section_size (sect) + 1);
137 if (!buf)
138 {
139 printf_unfiltered ("memory allocation failed for %s\n", sect->name);
140 goto out;
141 }
142 if (!bfd_get_section_contents (abfd, sect,
143 buf, 0, bfd_get_section_size (sect)))
144 goto out;
145
146
147
dc05df57 148 /* A DWORD (data_type) followed by struct windows_core_module_info. */
de584861
PA
149
150 base_addr =
e17a4113 151 extract_unsigned_integer (buf + 4, 4, byte_order);
de584861
PA
152
153 module_name_size =
e17a4113 154 extract_unsigned_integer (buf + 8, 4, byte_order);
de584861
PA
155
156 module_name = buf + 12;
157 if (module_name - buf + module_name_size > bfd_get_section_size (sect))
158 goto out;
159
160 /* The first module is the .exe itself. */
161 if (data->module_count != 0)
5af949e3
UW
162 windows_xfer_shared_library (module_name, base_addr,
163 data->gdbarch, data->obstack);
de584861
PA
164 data->module_count++;
165
166out:
167 if (buf)
168 xfree (buf);
169 return;
170}
171
172static LONGEST
dc05df57 173windows_core_xfer_shared_libraries (struct gdbarch *gdbarch,
de584861
PA
174 gdb_byte *readbuf,
175 ULONGEST offset, LONGEST len)
176{
177 struct obstack obstack;
178 const char *buf;
179 LONGEST len_avail;
5af949e3 180 struct cpms_data data = { gdbarch, &obstack, 0 };
de584861
PA
181
182 obstack_init (&obstack);
183 obstack_grow_str (&obstack, "<library-list>\n");
184 bfd_map_over_sections (core_bfd,
185 core_process_module_section,
186 &data);
187 obstack_grow_str0 (&obstack, "</library-list>\n");
188
189 buf = obstack_finish (&obstack);
190 len_avail = strlen (buf);
191 if (offset >= len_avail)
192 return 0;
193
194 if (len > len_avail - offset)
195 len = len_avail - offset;
196 memcpy (readbuf, buf + offset, len);
197
198 obstack_free (&obstack, NULL);
199 return len;
200}
1762d96d 201
f7948b5f 202static CORE_ADDR
52f729a7 203i386_cygwin_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
f7948b5f 204{
e17a4113 205 return i386_pe_skip_trampoline_code (frame, pc, NULL);
f7948b5f
JB
206}
207
f870a310
TT
208static const char *
209i386_cygwin_auto_wide_charset (void)
210{
211 return "UTF-16";
212}
213
1762d96d
CV
214static void
215i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
216{
217 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
218
f7948b5f
JB
219 set_gdbarch_skip_trampoline_code (gdbarch, i386_cygwin_skip_trampoline_code);
220
4309257c
PM
221 set_gdbarch_skip_main_prologue (gdbarch, i386_skip_main_prologue);
222
1762d96d 223 tdep->struct_return = reg_struct_return;
de584861 224
dc05df57
CF
225 tdep->gregset_reg_offset = i386_windows_gregset_reg_offset;
226 tdep->gregset_num_regs = ARRAY_SIZE (i386_windows_gregset_reg_offset);
227 tdep->sizeof_gregset = I386_WINDOWS_SIZEOF_GREGSET;
de584861 228
8d465389
UW
229 set_solib_ops (gdbarch, &solib_target_so_ops);
230
de584861
PA
231 /* Core file support. */
232 set_gdbarch_regset_from_core_section
dc05df57 233 (gdbarch, i386_windows_regset_from_core_section);
de584861 234 set_gdbarch_core_xfer_shared_libraries
dc05df57 235 (gdbarch, windows_core_xfer_shared_libraries);
f870a310
TT
236
237 set_gdbarch_auto_wide_charset (gdbarch, i386_cygwin_auto_wide_charset);
ab38a727
PA
238
239 /* Canonical paths on this target look like
240 `c:\Program Files\Foo App\mydll.dll', for example. */
241 set_gdbarch_has_dos_based_file_system (gdbarch, 1);
1762d96d
CV
242}
243
244static enum gdb_osabi
de584861
PA
245i386_cygwin_osabi_sniffer (bfd *abfd)
246{
1762d96d
CV
247 char *target_name = bfd_get_target (abfd);
248
de584861 249 /* Interix also uses pei-i386.
1762d96d
CV
250 We need a way to distinguish between the two. */
251 if (strcmp (target_name, "pei-i386") == 0)
252 return GDB_OSABI_CYGWIN;
253
c0993dbe
UW
254 /* Cygwin uses elf core dumps. Do not claim all ELF executables,
255 check whether there is a .reg section of proper size. */
de584861 256 if (strcmp (target_name, "elf32-i386") == 0)
c0993dbe
UW
257 {
258 asection *section = bfd_get_section_by_name (abfd, ".reg");
259 if (section
dc05df57 260 && bfd_section_size (abfd, section) == I386_WINDOWS_SIZEOF_GREGSET)
c0993dbe
UW
261 return GDB_OSABI_CYGWIN;
262 }
de584861 263
1762d96d
CV
264 return GDB_OSABI_UNKNOWN;
265}
266
acd5c798
MK
267/* Provide a prototype to silence -Wmissing-prototypes. */
268void _initialize_i386_cygwin_tdep (void);
269
1762d96d
CV
270void
271_initialize_i386_cygwin_tdep (void)
272{
273 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
274 i386_cygwin_osabi_sniffer);
275
de584861
PA
276 /* Cygwin uses elf core dumps. */
277 gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
278 i386_cygwin_osabi_sniffer);
279
1762d96d
CV
280 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
281 i386_cygwin_init_abi);
282}
This page took 0.517556 seconds and 4 git commands to generate.