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