gdbserver: Add GNU/Linux support for ARC
[deliverable/binutils-gdb.git] / gdb / arc-linux-tdep.c
CommitLineData
8d7f0635
AK
1/* Target dependent code for GNU/Linux ARC.
2
3 Copyright 2020 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20/* GDB header files. */
21#include "defs.h"
22#include "linux-tdep.h"
23#include "objfiles.h"
24#include "opcode/arc.h"
25#include "osabi.h"
26#include "solib-svr4.h"
27
28/* ARC header files. */
29#include "opcodes/arc-dis.h"
30#include "arc-tdep.h"
31
32/* Implement the "cannot_fetch_register" gdbarch method. */
33
34static int
35arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
36{
37 /* Assume that register is readable if it is unknown. */
38 switch (regnum)
39 {
40 case ARC_ILINK_REGNUM:
41 case ARC_RESERVED_REGNUM:
42 case ARC_LIMM_REGNUM:
43 return true;
44 case ARC_R30_REGNUM:
45 case ARC_R58_REGNUM:
46 case ARC_R59_REGNUM:
47 return !arc_mach_is_arcv2 (gdbarch);
48 }
49 return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
50}
51
52/* Implement the "cannot_store_register" gdbarch method. */
53
54static int
55arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
56{
57 /* Assume that register is writable if it is unknown. */
58 switch (regnum)
59 {
60 case ARC_ILINK_REGNUM:
61 case ARC_RESERVED_REGNUM:
62 case ARC_LIMM_REGNUM:
63 case ARC_PCL_REGNUM:
64 return true;
65 case ARC_R30_REGNUM:
66 case ARC_R58_REGNUM:
67 case ARC_R59_REGNUM:
68 return !arc_mach_is_arcv2 (gdbarch);
69 }
70 return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
71}
72
73/* For ARC Linux, breakpoints use the 16-bit TRAP_S 1 instruction, which
74 is 0x3e78 (little endian) or 0x783e (big endian). */
75
76static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
77static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
78static const int trap_size = 2; /* Number of bytes to insert "trap". */
79
80/* Implement the "breakpoint_kind_from_pc" gdbarch method. */
81
82static int
83arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
84{
85 return trap_size;
86}
87
88/* Implement the "sw_breakpoint_from_kind" gdbarch method. */
89
90static const gdb_byte *
91arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
92 int kind, int *size)
93{
94 *size = kind;
95 return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
96 ? arc_linux_trap_s_be
97 : arc_linux_trap_s_le);
98}
99
100/* Implement the "software_single_step" gdbarch method. */
101
102static std::vector<CORE_ADDR>
103arc_linux_software_single_step (struct regcache *regcache)
104{
105 struct gdbarch *gdbarch = regcache->arch ();
106 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
107 struct disassemble_info di = arc_disassemble_info (gdbarch);
108
109 /* Read current instruction. */
110 struct arc_instruction curr_insn;
111 arc_insn_decode (regcache_read_pc (regcache), &di, arc_delayed_print_insn,
112 &curr_insn);
113 CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
114
115 std::vector<CORE_ADDR> next_pcs;
116
117 /* For instructions with delay slots, the fall thru is not the
118 instruction immediately after the current instruction, but the one
119 after that. */
120 if (curr_insn.has_delay_slot)
121 {
122 struct arc_instruction next_insn;
123 arc_insn_decode (next_pc, &di, arc_delayed_print_insn, &next_insn);
124 next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
125 }
126 else
127 next_pcs.push_back (next_pc);
128
129 ULONGEST status32;
130 regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
131 &status32);
132
133 if (curr_insn.is_control_flow)
134 {
135 CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
136 if (branch_pc != next_pc)
137 next_pcs.push_back (branch_pc);
138 }
139 /* Is current instruction the last in a loop body? */
140 else if (tdep->has_hw_loops)
141 {
142 /* If STATUS32.L is 1, then ZD-loops are disabled. */
143 if ((status32 & ARC_STATUS32_L_MASK) == 0)
144 {
145 ULONGEST lp_end, lp_start, lp_count;
146 regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
147 &lp_start);
148 regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
149 regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
150 &lp_count);
151
152 if (arc_debug)
153 {
154 debug_printf ("arc-linux: lp_start = %s, lp_end = %s, "
155 "lp_count = %s, next_pc = %s\n",
156 paddress (gdbarch, lp_start),
157 paddress (gdbarch, lp_end),
158 pulongest (lp_count),
159 paddress (gdbarch, next_pc));
160 }
161
162 if (next_pc == lp_end && lp_count > 1)
163 {
164 /* The instruction is in effect a jump back to the start of
165 the loop. */
166 next_pcs.push_back (lp_start);
167 }
168 }
169 }
170
171 /* Is this a delay slot? Then next PC is in BTA register. */
172 if ((status32 & ARC_STATUS32_DE_MASK) != 0)
173 {
174 ULONGEST bta;
175 regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
176 next_pcs.push_back (bta);
177 }
178
179 return next_pcs;
180}
181
182/* Implement the "skip_solib_resolver" gdbarch method.
183
184 See glibc_skip_solib_resolver for details. */
185
186static CORE_ADDR
187arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
188{
189 /* For uClibc 0.9.26+.
190
191 An unresolved PLT entry points to "__dl_linux_resolve", which calls
192 "_dl_linux_resolver" to do the resolving and then eventually jumps to
193 the function.
194
195 So we look for the symbol `_dl_linux_resolver', and if we are there,
196 gdb sets a breakpoint at the return address, and continues. */
197 struct bound_minimal_symbol resolver
198 = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
199
200 if (arc_debug)
201 {
202 if (resolver.minsym != nullptr)
203 {
204 CORE_ADDR res_addr = BMSYMBOL_VALUE_ADDRESS (resolver);
205 debug_printf ("arc-linux: skip_solib_resolver (): "
206 "pc = %s, resolver at %s\n",
207 print_core_address (gdbarch, pc),
208 print_core_address (gdbarch, res_addr));
209 }
210 else
211 {
212 debug_printf ("arc-linux: skip_solib_resolver (): "
213 "pc = %s, no resolver found\n",
214 print_core_address (gdbarch, pc));
215 }
216 }
217
218 if (resolver.minsym != nullptr && BMSYMBOL_VALUE_ADDRESS (resolver) == pc)
219 {
220 /* Find the return address. */
221 return frame_unwind_caller_pc (get_current_frame ());
222 }
223 else
224 {
225 /* No breakpoint required. */
226 return 0;
227 }
228}
229
230/* Initialization specific to Linux environment. */
231
232static void
233arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
234{
235 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
236
237 if (arc_debug)
238 debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
239
240 /* If we are using Linux, we have in uClibc
241 (libc/sysdeps/linux/arc/bits/setjmp.h):
242
243 typedef int __jmp_buf[13+1+1+1]; //r13-r25, fp, sp, blink
244
245 Where "blink" is a stored PC of a caller function.
246 */
247 tdep->jb_pc = 15;
248
249 linux_init_abi (info, gdbarch);
250
251 /* Set up target dependent GDB architecture entries. */
252 set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
253 set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
254 set_gdbarch_breakpoint_kind_from_pc (gdbarch,
255 arc_linux_breakpoint_kind_from_pc);
256 set_gdbarch_sw_breakpoint_from_kind (gdbarch,
257 arc_linux_sw_breakpoint_from_kind);
258 set_gdbarch_fetch_tls_load_module_address (gdbarch,
259 svr4_fetch_objfile_link_map);
260 set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
261 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
262 set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
263
264 /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
265 and pointers (ILP32). */
266 set_solib_svr4_fetch_link_map_offsets (gdbarch,
267 svr4_ilp32_fetch_link_map_offsets);
268}
269
270/* Suppress warning from -Wmissing-prototypes. */
271extern initialize_file_ftype _initialize_arc_linux_tdep;
272
273void
274_initialize_arc_linux_tdep ()
275{
276 gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
277 arc_linux_init_osabi);
278}
This page took 0.041516 seconds and 4 git commands to generate.