Remove spurious gdb/ ...
[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
0fb0cc75 4 Copyright (C) 2007, 2008, 2009 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"
8d465389
UW
25#include "solib.h"
26#include "solib-target.h"
e17a4113 27#include "frame.h"
68070c10
PA
28
29#include "gdb_string.h"
30
31#include "arm-tdep.h"
32
33static const char arm_wince_le_breakpoint[] = { 0x10, 0x00, 0x00, 0xe6 };
190dce09 34static const char arm_wince_thumb_le_breakpoint[] = { 0xfe, 0xdf };
68070c10
PA
35
36/* Description of the longjmp buffer. */
37#define ARM_WINCE_JB_ELEMENT_SIZE INT_REGISTER_SIZE
8ad7c2b9 38#define ARM_WINCE_JB_PC 10
68070c10 39
6dc13412
PA
40static CORE_ADDR
41arm_pe_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
42{
e17a4113
UW
43 struct gdbarch *gdbarch = get_frame_arch (frame);
44 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
6dc13412
PA
45 ULONGEST indirect;
46 struct minimal_symbol *indsym;
47 char *symname;
48 CORE_ADDR next_pc;
49
50 /* The format of an ARM DLL trampoline is:
51 ldr ip, [pc]
52 ldr pc, [ip]
53 .dw __imp_<func> */
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);
65 if (indsym == NULL)
66 return 0;
67
68 symname = SYMBOL_LINKAGE_NAME (indsym);
69 if (symname == NULL || strncmp (symname, "__imp_", 6) != 0)
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
87CORE_ADDR
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;
103 struct minimal_symbol *s = lookup_minimal_symbol_by_pc (call_dest);
104
105 if (s != NULL
106 && SYMBOL_LINKAGE_NAME (s) != NULL
107 && strcmp (SYMBOL_LINKAGE_NAME (s), "__gccmain") == 0)
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{
117 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
118
119 tdep->arm_breakpoint = arm_wince_le_breakpoint;
120 tdep->arm_breakpoint_size = sizeof (arm_wince_le_breakpoint);
190dce09
UW
121 tdep->thumb_breakpoint = arm_wince_thumb_le_breakpoint;
122 tdep->thumb_breakpoint_size = sizeof (arm_wince_thumb_le_breakpoint);
68070c10
PA
123 tdep->struct_return = pcc_struct_return;
124
125 tdep->fp_model = ARM_FLOAT_SOFT_VFP;
126
127 tdep->jb_pc = ARM_WINCE_JB_PC;
128 tdep->jb_elt_size = ARM_WINCE_JB_ELEMENT_SIZE;
129
130 /* On ARM WinCE char defaults to signed. */
131 set_gdbarch_char_signed (gdbarch, 1);
132
68070c10 133 /* Shared library handling. */
8d465389 134 set_solib_ops (gdbarch, &solib_target_so_ops);
6dc13412 135 set_gdbarch_skip_trampoline_code (gdbarch, arm_pe_skip_trampoline_code);
190dce09
UW
136
137 /* Single stepping. */
138 set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
d7117c03
PA
139
140 /* Skip call to __gccmain that gcc places in main. */
141 set_gdbarch_skip_main_prologue (gdbarch, arm_wince_skip_main_prologue);
68070c10
PA
142}
143
144static enum gdb_osabi
145arm_wince_osabi_sniffer (bfd *abfd)
146{
147 const char *target_name = bfd_get_target (abfd);
148
149 if (strcmp (target_name, "pei-arm-wince-little") == 0)
150 return GDB_OSABI_WINCE;
151
152 return GDB_OSABI_UNKNOWN;
153}
154
155/* Provide a prototype to silence -Wmissing-prototypes. */
156void _initialize_arm_wince_tdep (void);
157
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.180098 seconds and 4 git commands to generate.