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