Rename 'descr' field in regset structure to 'regmap'.
[deliverable/binutils-gdb.git] / gdb / arm-wince-tdep.c
CommitLineData
68070c10
PA
1/* Target-dependent code for Windows CE running on ARM processors,
2 for GDB.
3
ecd75fc8 4 Copyright (C) 2007-2014 Free Software Foundation, Inc.
68070c10
PA
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
68070c10
PA
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
68070c10
PA
20
21#include "defs.h"
22#include "osabi.h"
6dc13412 23#include "gdbcore.h"
68070c10 24#include "target.h"
e17a4113 25#include "frame.h"
68070c10 26
68070c10 27#include "arm-tdep.h"
29f9ebfa 28#include "windows-tdep.h"
68070c10 29
948f8e3d
PA
30static const gdb_byte arm_wince_le_breakpoint[] = { 0x10, 0x00, 0x00, 0xe6 };
31static const gdb_byte arm_wince_thumb_le_breakpoint[] = { 0xfe, 0xdf };
68070c10
PA
32
33/* Description of the longjmp buffer. */
34#define ARM_WINCE_JB_ELEMENT_SIZE INT_REGISTER_SIZE
8ad7c2b9 35#define ARM_WINCE_JB_PC 10
68070c10 36
6dc13412
PA
37static CORE_ADDR
38arm_pe_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
39{
e17a4113
UW
40 struct gdbarch *gdbarch = get_frame_arch (frame);
41 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
6dc13412 42 ULONGEST indirect;
7cbd4a93 43 struct bound_minimal_symbol indsym;
0d5cff50 44 const char *symname;
6dc13412
PA
45 CORE_ADDR next_pc;
46
47 /* The format of an ARM DLL trampoline is:
48 ldr ip, [pc]
49 ldr pc, [ip]
50 .dw __imp_<func> */
51
52 if (pc == 0
e17a4113
UW
53 || read_memory_unsigned_integer (pc + 0, 4, byte_order) != 0xe59fc000
54 || read_memory_unsigned_integer (pc + 4, 4, byte_order) != 0xe59cf000)
6dc13412
PA
55 return 0;
56
e17a4113 57 indirect = read_memory_unsigned_integer (pc + 8, 4, byte_order);
6dc13412
PA
58 if (indirect == 0)
59 return 0;
60
61 indsym = lookup_minimal_symbol_by_pc (indirect);
7cbd4a93 62 if (indsym.minsym == NULL)
6dc13412
PA
63 return 0;
64
efd66ac6 65 symname = MSYMBOL_LINKAGE_NAME (indsym.minsym);
6dc13412
PA
66 if (symname == NULL || strncmp (symname, "__imp_", 6) != 0)
67 return 0;
68
e17a4113 69 next_pc = read_memory_unsigned_integer (indirect, 4, byte_order);
6dc13412
PA
70 if (next_pc != 0)
71 return next_pc;
72
73 /* Check with the default arm gdbarch_skip_trampoline. */
74 return arm_skip_stub (frame, pc);
75}
76
d7117c03
PA
77/* GCC emits a call to __gccmain in the prologue of main.
78
79 The function below examines the code pointed at by PC and checks to
80 see if it corresponds to a call to __gccmain. If so, it returns
81 the address of the instruction following that call. Otherwise, it
82 simply returns PC. */
83
693be288 84static CORE_ADDR
d7117c03
PA
85arm_wince_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
86{
87 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
88 ULONGEST this_instr;
89
90 this_instr = read_memory_unsigned_integer (pc, 4, byte_order);
91
92 /* bl offset <__gccmain> */
93 if ((this_instr & 0xfff00000) == 0xeb000000)
94 {
95#define sign_extend(V, N) \
96 (((long) (V) ^ (1L << ((N) - 1))) - (1L << ((N) - 1)))
97
98 long offset = sign_extend (this_instr & 0x000fffff, 23) << 2;
99 CORE_ADDR call_dest = (pc + 8 + offset) & 0xffffffffU;
7cbd4a93 100 struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
d7117c03 101
7cbd4a93 102 if (s.minsym != NULL
efd66ac6
TT
103 && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL
104 && strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__gccmain") == 0)
d7117c03
PA
105 pc += 4;
106 }
107
108 return pc;
109}
110
68070c10
PA
111static void
112arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
113{
114 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
115
29f9ebfa
YQ
116 windows_init_abi (info, gdbarch);
117
68070c10
PA
118 tdep->arm_breakpoint = arm_wince_le_breakpoint;
119 tdep->arm_breakpoint_size = sizeof (arm_wince_le_breakpoint);
190dce09
UW
120 tdep->thumb_breakpoint = arm_wince_thumb_le_breakpoint;
121 tdep->thumb_breakpoint_size = sizeof (arm_wince_thumb_le_breakpoint);
68070c10
PA
122 tdep->struct_return = pcc_struct_return;
123
124 tdep->fp_model = ARM_FLOAT_SOFT_VFP;
125
126 tdep->jb_pc = ARM_WINCE_JB_PC;
127 tdep->jb_elt_size = ARM_WINCE_JB_ELEMENT_SIZE;
128
129 /* On ARM WinCE char defaults to signed. */
130 set_gdbarch_char_signed (gdbarch, 1);
131
68070c10 132 /* Shared library handling. */
6dc13412 133 set_gdbarch_skip_trampoline_code (gdbarch, arm_pe_skip_trampoline_code);
190dce09
UW
134
135 /* Single stepping. */
136 set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
d7117c03
PA
137
138 /* Skip call to __gccmain that gcc places in main. */
139 set_gdbarch_skip_main_prologue (gdbarch, arm_wince_skip_main_prologue);
68070c10
PA
140}
141
142static enum gdb_osabi
143arm_wince_osabi_sniffer (bfd *abfd)
144{
145 const char *target_name = bfd_get_target (abfd);
146
147 if (strcmp (target_name, "pei-arm-wince-little") == 0)
148 return GDB_OSABI_WINCE;
149
150 return GDB_OSABI_UNKNOWN;
151}
152
153/* Provide a prototype to silence -Wmissing-prototypes. */
154void _initialize_arm_wince_tdep (void);
155
156void
157_initialize_arm_wince_tdep (void)
158{
159 gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_coff_flavour,
160 arm_wince_osabi_sniffer);
161
162 gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_WINCE,
163 arm_wince_init_abi);
164}
This page took 0.467329 seconds and 4 git commands to generate.