Sort includes for files gdb/[a-f]*.[chyl].
[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
42a4f53d 4 Copyright (C) 2007-2019 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"
68070c10 22
d55e5aa6 23/* Local non-gdb includes. */
cba7e83f 24#include "arch/arm.h"
68070c10 25#include "arm-tdep.h"
d55e5aa6
TT
26#include "frame.h"
27#include "gdbcore.h"
28#include "osabi.h"
29#include "target.h"
29f9ebfa 30#include "windows-tdep.h"
68070c10 31
948f8e3d
PA
32static const gdb_byte arm_wince_le_breakpoint[] = { 0x10, 0x00, 0x00, 0xe6 };
33static const gdb_byte arm_wince_thumb_le_breakpoint[] = { 0xfe, 0xdf };
68070c10
PA
34
35/* Description of the longjmp buffer. */
36#define ARM_WINCE_JB_ELEMENT_SIZE INT_REGISTER_SIZE
8ad7c2b9 37#define ARM_WINCE_JB_PC 10
68070c10 38
6dc13412
PA
39static CORE_ADDR
40arm_pe_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
41{
e17a4113
UW
42 struct gdbarch *gdbarch = get_frame_arch (frame);
43 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
6dc13412 44 ULONGEST indirect;
7cbd4a93 45 struct bound_minimal_symbol indsym;
0d5cff50 46 const char *symname;
6dc13412
PA
47 CORE_ADDR next_pc;
48
49 /* The format of an ARM DLL trampoline is:
5f52445b 50
6dc13412
PA
51 ldr ip, [pc]
52 ldr pc, [ip]
5f52445b
YQ
53 .dw __imp_<func>
54
55 */
6dc13412
PA
56
57 if (pc == 0
e17a4113
UW
58 || read_memory_unsigned_integer (pc + 0, 4, byte_order) != 0xe59fc000
59 || read_memory_unsigned_integer (pc + 4, 4, byte_order) != 0xe59cf000)
6dc13412
PA
60 return 0;
61
e17a4113 62 indirect = read_memory_unsigned_integer (pc + 8, 4, byte_order);
6dc13412
PA
63 if (indirect == 0)
64 return 0;
65
66 indsym = lookup_minimal_symbol_by_pc (indirect);
7cbd4a93 67 if (indsym.minsym == NULL)
6dc13412
PA
68 return 0;
69
efd66ac6 70 symname = MSYMBOL_LINKAGE_NAME (indsym.minsym);
61012eef 71 if (symname == NULL || !startswith (symname, "__imp_"))
6dc13412
PA
72 return 0;
73
e17a4113 74 next_pc = read_memory_unsigned_integer (indirect, 4, byte_order);
6dc13412
PA
75 if (next_pc != 0)
76 return next_pc;
77
78 /* Check with the default arm gdbarch_skip_trampoline. */
79 return arm_skip_stub (frame, pc);
80}
81
d7117c03
PA
82/* GCC emits a call to __gccmain in the prologue of main.
83
84 The function below examines the code pointed at by PC and checks to
85 see if it corresponds to a call to __gccmain. If so, it returns
86 the address of the instruction following that call. Otherwise, it
87 simply returns PC. */
88
693be288 89static CORE_ADDR
d7117c03
PA
90arm_wince_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
91{
92 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
93 ULONGEST this_instr;
94
95 this_instr = read_memory_unsigned_integer (pc, 4, byte_order);
96
97 /* bl offset <__gccmain> */
98 if ((this_instr & 0xfff00000) == 0xeb000000)
99 {
100#define sign_extend(V, N) \
101 (((long) (V) ^ (1L << ((N) - 1))) - (1L << ((N) - 1)))
102
103 long offset = sign_extend (this_instr & 0x000fffff, 23) << 2;
104 CORE_ADDR call_dest = (pc + 8 + offset) & 0xffffffffU;
7cbd4a93 105 struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
d7117c03 106
7cbd4a93 107 if (s.minsym != NULL
efd66ac6
TT
108 && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL
109 && strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__gccmain") == 0)
d7117c03
PA
110 pc += 4;
111 }
112
113 return pc;
114}
115
68070c10
PA
116static void
117arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
118{
119 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
120
29f9ebfa
YQ
121 windows_init_abi (info, gdbarch);
122
68070c10
PA
123 tdep->arm_breakpoint = arm_wince_le_breakpoint;
124 tdep->arm_breakpoint_size = sizeof (arm_wince_le_breakpoint);
190dce09
UW
125 tdep->thumb_breakpoint = arm_wince_thumb_le_breakpoint;
126 tdep->thumb_breakpoint_size = sizeof (arm_wince_thumb_le_breakpoint);
68070c10
PA
127 tdep->struct_return = pcc_struct_return;
128
129 tdep->fp_model = ARM_FLOAT_SOFT_VFP;
130
131 tdep->jb_pc = ARM_WINCE_JB_PC;
132 tdep->jb_elt_size = ARM_WINCE_JB_ELEMENT_SIZE;
133
134 /* On ARM WinCE char defaults to signed. */
135 set_gdbarch_char_signed (gdbarch, 1);
136
68070c10 137 /* Shared library handling. */
6dc13412 138 set_gdbarch_skip_trampoline_code (gdbarch, arm_pe_skip_trampoline_code);
190dce09
UW
139
140 /* Single stepping. */
141 set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
d7117c03
PA
142
143 /* Skip call to __gccmain that gcc places in main. */
144 set_gdbarch_skip_main_prologue (gdbarch, arm_wince_skip_main_prologue);
68070c10
PA
145}
146
147static enum gdb_osabi
148arm_wince_osabi_sniffer (bfd *abfd)
149{
150 const char *target_name = bfd_get_target (abfd);
151
152 if (strcmp (target_name, "pei-arm-wince-little") == 0)
153 return GDB_OSABI_WINCE;
154
155 return GDB_OSABI_UNKNOWN;
156}
157
68070c10
PA
158void
159_initialize_arm_wince_tdep (void)
160{
161 gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_coff_flavour,
162 arm_wince_osabi_sniffer);
163
164 gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_WINCE,
165 arm_wince_init_abi);
166}
This page took 0.941234 seconds and 4 git commands to generate.