Update years in copyright notice for the GDB files.
[platform/upstream/binutils.git] / gdb / amd64-windows-tdep.c
1 /* Copyright (C) 2009-2013 Free Software Foundation, Inc.
2
3    This file is part of GDB.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include "defs.h"
19 #include "osabi.h"
20 #include "amd64-tdep.h"
21 #include "solib.h"
22 #include "solib-target.h"
23 #include "gdbtypes.h"
24 #include "gdbcore.h"
25 #include "regcache.h"
26 #include "windows-tdep.h"
27 #include "frame.h"
28
29 /* The registers used to pass integer arguments during a function call.  */
30 static int amd64_windows_dummy_call_integer_regs[] =
31 {
32   AMD64_RCX_REGNUM,          /* %rcx */
33   AMD64_RDX_REGNUM,          /* %rdx */
34   8,                         /* %r8 */
35   9                          /* %r9 */
36 };
37
38 /* Implement the "classify" method in the gdbarch_tdep structure
39    for amd64-windows.  */
40
41 static void
42 amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
43 {
44   switch (TYPE_CODE (type))
45     {
46       case TYPE_CODE_ARRAY:
47         /* Arrays are always passed by memory.  */
48         class[0] = class[1] = AMD64_MEMORY;
49         break;
50
51       case TYPE_CODE_STRUCT:
52       case TYPE_CODE_UNION:
53         /* Struct/Union types whose size is 1, 2, 4, or 8 bytes
54            are passed as if they were integers of the same size.
55            Types of different sizes are passed by memory.  */
56         if (TYPE_LENGTH (type) == 1
57             || TYPE_LENGTH (type) == 2
58             || TYPE_LENGTH (type) == 4
59             || TYPE_LENGTH (type) == 8)
60           {
61             class[0] = AMD64_INTEGER;
62             class[1] = AMD64_NO_CLASS;
63           }
64         else
65           class[0] = class[1] = AMD64_MEMORY;
66         break;
67
68       default:
69         /* For all the other types, the conventions are the same as
70            with the System V ABI.  */
71         amd64_classify (type, class);
72     }
73 }
74
75 /* Implement the "return_value" gdbarch method for amd64-windows.  */
76
77 static enum return_value_convention
78 amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
79                             struct type *type, struct regcache *regcache,
80                             gdb_byte *readbuf, const gdb_byte *writebuf)
81 {
82   int len = TYPE_LENGTH (type);
83   int regnum = -1;
84
85   /* See if our value is returned through a register.  If it is, then
86      store the associated register number in REGNUM.  */
87   switch (TYPE_CODE (type))
88     {
89       case TYPE_CODE_FLT:
90       case TYPE_CODE_DECFLOAT:
91         /* __m128, __m128i, __m128d, floats, and doubles are returned
92            via XMM0.  */
93         if (len == 4 || len == 8 || len == 16)
94           regnum = AMD64_XMM0_REGNUM;
95         break;
96       default:
97         /* All other values that are 1, 2, 4 or 8 bytes long are returned
98            via RAX.  */
99         if (len == 1 || len == 2 || len == 4 || len == 8)
100           regnum = AMD64_RAX_REGNUM;
101         break;
102     }
103
104   if (regnum < 0)
105     {
106       /* RAX contains the address where the return value has been stored.  */
107       if (readbuf)
108         {
109           ULONGEST addr;
110
111           regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
112           read_memory (addr, readbuf, TYPE_LENGTH (type));
113         }
114       return RETURN_VALUE_ABI_RETURNS_ADDRESS;
115     }
116   else
117     {
118       /* Extract the return value from the register where it was stored.  */
119       if (readbuf)
120         regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
121       if (writebuf)
122         regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
123       return RETURN_VALUE_REGISTER_CONVENTION;
124     }
125 }
126
127 /* Check that the code pointed to by PC corresponds to a call to
128    __main, skip it if so.  Return PC otherwise.  */
129
130 static CORE_ADDR
131 amd64_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
132 {
133   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
134   gdb_byte op;
135
136   target_read_memory (pc, &op, 1);
137   if (op == 0xe8)
138     {
139       gdb_byte buf[4];
140
141       if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
142         {
143           struct minimal_symbol *s;
144           CORE_ADDR call_dest;
145
146           call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
147           s = lookup_minimal_symbol_by_pc (call_dest);
148           if (s != NULL
149               && SYMBOL_LINKAGE_NAME (s) != NULL
150               && strcmp (SYMBOL_LINKAGE_NAME (s), "__main") == 0)
151             pc += 5;
152         }
153     }
154
155   return pc;
156 }
157
158 /* Check Win64 DLL jmp trampolines and find jump destination.  */
159
160 static CORE_ADDR
161 amd64_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
162 {
163   CORE_ADDR destination = 0;
164   struct gdbarch *gdbarch = get_frame_arch (frame);
165   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
166
167   /* Check for jmp *<offset>(%rip) (jump near, absolute indirect (/4)).  */
168   if (pc && read_memory_unsigned_integer (pc, 2, byte_order) == 0x25ff)
169     {
170       /* Get opcode offset and see if we can find a reference in our data.  */
171       ULONGEST offset
172         = read_memory_unsigned_integer (pc + 2, 4, byte_order);
173
174       /* Get address of function pointer at end of pc.  */
175       CORE_ADDR indirect_addr = pc + offset + 6;
176
177       struct minimal_symbol *indsym
178         = indirect_addr ? lookup_minimal_symbol_by_pc (indirect_addr) : NULL;
179       const char *symname = indsym ? SYMBOL_LINKAGE_NAME (indsym) : NULL;
180
181       if (symname)
182         {
183           if (strncmp (symname, "__imp_", 6) == 0
184               || strncmp (symname, "_imp_", 5) == 0)
185             destination
186               = read_memory_unsigned_integer (indirect_addr, 8, byte_order);
187         }
188     }
189
190   return destination;
191 }
192
193 /* Implement the "auto_wide_charset" gdbarch method.  */
194
195 static const char *
196 amd64_windows_auto_wide_charset (void)
197 {
198   return "UTF-16";
199 }
200
201 static void
202 amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
203 {
204   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
205
206   amd64_init_abi (info, gdbarch);
207
208   /* On Windows, "long"s are only 32bit.  */
209   set_gdbarch_long_bit (gdbarch, 32);
210
211   /* Function calls.  */
212   tdep->call_dummy_num_integer_regs =
213     ARRAY_SIZE (amd64_windows_dummy_call_integer_regs);
214   tdep->call_dummy_integer_regs = amd64_windows_dummy_call_integer_regs;
215   tdep->classify = amd64_windows_classify;
216   tdep->memory_args_by_pointer = 1;
217   tdep->integer_param_regs_saved_in_caller_frame = 1;
218   set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
219   set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
220   set_gdbarch_skip_trampoline_code (gdbarch,
221                                     amd64_windows_skip_trampoline_code);
222
223   set_gdbarch_iterate_over_objfiles_in_search_order
224     (gdbarch, windows_iterate_over_objfiles_in_search_order);
225
226   set_gdbarch_auto_wide_charset (gdbarch, amd64_windows_auto_wide_charset);
227
228   set_solib_ops (gdbarch, &solib_target_so_ops);
229 }
230
231 /* -Wmissing-prototypes */
232 extern initialize_file_ftype _initialize_amd64_windows_tdep;
233
234 void
235 _initialize_amd64_windows_tdep (void)
236 {
237   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
238                           amd64_windows_init_abi);
239 }
240