xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/arc-linux-tdep.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Target dependent code for GNU/Linux ARC.
27d62b00eSchristos 
3*6881a400Schristos    Copyright 2020-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos /* GDB header files.  */
217d62b00eSchristos #include "defs.h"
227d62b00eSchristos #include "linux-tdep.h"
237d62b00eSchristos #include "objfiles.h"
247d62b00eSchristos #include "opcode/arc.h"
257d62b00eSchristos #include "osabi.h"
267d62b00eSchristos #include "solib-svr4.h"
27*6881a400Schristos #include "disasm.h"
287d62b00eSchristos 
297d62b00eSchristos /* ARC header files.  */
307d62b00eSchristos #include "opcodes/arc-dis.h"
31*6881a400Schristos #include "arc-linux-tdep.h"
327d62b00eSchristos #include "arc-tdep.h"
33*6881a400Schristos #include "arch/arc.h"
34*6881a400Schristos 
35*6881a400Schristos /* Print an "arc-linux" debug statement.  */
36*6881a400Schristos 
37*6881a400Schristos #define arc_linux_debug_printf(fmt, ...) \
38*6881a400Schristos   debug_prefixed_printf_cond (arc_debug, "arc-linux", fmt, ##__VA_ARGS__)
39*6881a400Schristos 
40*6881a400Schristos #define REGOFF(offset) (offset * ARC_REGISTER_SIZE)
41*6881a400Schristos 
42*6881a400Schristos /* arc_linux_sc_reg_offsets[i] is the offset of register i in the `struct
43*6881a400Schristos    sigcontext'.  Array index is an internal GDB register number, as defined in
44*6881a400Schristos    arc-tdep.h:arc_regnum.
45*6881a400Schristos 
46*6881a400Schristos    From <include/uapi/asm/sigcontext.h> and <include/uapi/asm/ptrace.h>.
47*6881a400Schristos 
48*6881a400Schristos    The layout of this struct is tightly bound to "arc_regnum" enum
49*6881a400Schristos    in arc-tdep.h.  Any change of order in there, must be reflected
50*6881a400Schristos    here as well.  */
51*6881a400Schristos static const int arc_linux_sc_reg_offsets[] = {
52*6881a400Schristos   /* R0 - R12.  */
53*6881a400Schristos   REGOFF (22), REGOFF (21), REGOFF (20), REGOFF (19),
54*6881a400Schristos   REGOFF (18), REGOFF (17), REGOFF (16), REGOFF (15),
55*6881a400Schristos   REGOFF (14), REGOFF (13), REGOFF (12), REGOFF (11),
56*6881a400Schristos   REGOFF (10),
57*6881a400Schristos 
58*6881a400Schristos   /* R13 - R25.  */
59*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
60*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
61*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
62*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
63*6881a400Schristos   ARC_OFFSET_NO_REGISTER,
64*6881a400Schristos 
65*6881a400Schristos   REGOFF (9),			/* R26 (GP) */
66*6881a400Schristos   REGOFF (8),			/* FP */
67*6881a400Schristos   REGOFF (23),			/* SP */
68*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* ILINK */
69*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* R30 */
70*6881a400Schristos   REGOFF (7),			/* BLINK */
71*6881a400Schristos 
72*6881a400Schristos   /* R32 - R59.  */
73*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
74*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
75*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
76*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
77*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
78*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
79*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
80*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
81*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
82*6881a400Schristos   ARC_OFFSET_NO_REGISTER,
83*6881a400Schristos 
84*6881a400Schristos   REGOFF (4),			/* LP_COUNT */
85*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* RESERVED */
86*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* LIMM */
87*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* PCL */
88*6881a400Schristos 
89*6881a400Schristos   REGOFF (6),			/* PC  */
90*6881a400Schristos   REGOFF (5),			/* STATUS32 */
91*6881a400Schristos   REGOFF (2),			/* LP_START */
92*6881a400Schristos   REGOFF (3),			/* LP_END */
93*6881a400Schristos   REGOFF (1),			/* BTA */
94*6881a400Schristos };
95*6881a400Schristos 
96*6881a400Schristos /* arc_linux_core_reg_offsets[i] is the offset in the .reg section of GDB
97*6881a400Schristos    regnum i.  Array index is an internal GDB register number, as defined in
98*6881a400Schristos    arc-tdep.h:arc_regnum.
99*6881a400Schristos 
100*6881a400Schristos    From include/uapi/asm/ptrace.h in the ARC Linux sources.  */
101*6881a400Schristos 
102*6881a400Schristos /* The layout of this struct is tightly bound to "arc_regnum" enum
103*6881a400Schristos    in arc-tdep.h.  Any change of order in there, must be reflected
104*6881a400Schristos    here as well.  */
105*6881a400Schristos static const int arc_linux_core_reg_offsets[] = {
106*6881a400Schristos   /* R0 - R12.  */
107*6881a400Schristos   REGOFF (22), REGOFF (21), REGOFF (20), REGOFF (19),
108*6881a400Schristos   REGOFF (18), REGOFF (17), REGOFF (16), REGOFF (15),
109*6881a400Schristos   REGOFF (14), REGOFF (13), REGOFF (12), REGOFF (11),
110*6881a400Schristos   REGOFF (10),
111*6881a400Schristos 
112*6881a400Schristos   /* R13 - R25.  */
113*6881a400Schristos   REGOFF (37), REGOFF (36), REGOFF (35), REGOFF (34),
114*6881a400Schristos   REGOFF (33), REGOFF (32), REGOFF (31), REGOFF (30),
115*6881a400Schristos   REGOFF (29), REGOFF (28), REGOFF (27), REGOFF (26),
116*6881a400Schristos   REGOFF (25),
117*6881a400Schristos 
118*6881a400Schristos   REGOFF (9),			/* R26 (GP) */
119*6881a400Schristos   REGOFF (8),			/* FP */
120*6881a400Schristos   REGOFF (23),			/* SP */
121*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* ILINK */
122*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* R30 */
123*6881a400Schristos   REGOFF (7),			/* BLINK */
124*6881a400Schristos 
125*6881a400Schristos   /* R32 - R59.  */
126*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
127*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
128*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
129*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
130*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
131*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
132*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
133*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
134*6881a400Schristos   ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
135*6881a400Schristos   ARC_OFFSET_NO_REGISTER,
136*6881a400Schristos 
137*6881a400Schristos   REGOFF (4),			/* LP_COUNT */
138*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* RESERVED */
139*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* LIMM */
140*6881a400Schristos   ARC_OFFSET_NO_REGISTER,	/* PCL */
141*6881a400Schristos 
142*6881a400Schristos   REGOFF (39),			/* PC  */
143*6881a400Schristos   REGOFF (5),			/* STATUS32 */
144*6881a400Schristos   REGOFF (2),			/* LP_START */
145*6881a400Schristos   REGOFF (3),			/* LP_END */
146*6881a400Schristos   REGOFF (1),			/* BTA */
147*6881a400Schristos   REGOFF (6)			/* ERET */
148*6881a400Schristos };
149*6881a400Schristos 
150*6881a400Schristos /* Is THIS_FRAME a sigtramp function - the function that returns from
151*6881a400Schristos    signal handler into normal execution flow? This is the case if the PC is
152*6881a400Schristos    either at the start of, or in the middle of the two instructions:
153*6881a400Schristos 
154*6881a400Schristos      mov r8, __NR_rt_sigreturn ; __NR_rt_sigreturn == 139
155*6881a400Schristos      trap_s 0 ; `swi' for ARC700
156*6881a400Schristos 
157*6881a400Schristos    On ARC uClibc Linux this function is called __default_rt_sa_restorer.
158*6881a400Schristos 
159*6881a400Schristos    Returns TRUE if this is a sigtramp frame.  */
160*6881a400Schristos 
161*6881a400Schristos static bool
162*6881a400Schristos arc_linux_is_sigtramp (frame_info_ptr this_frame)
163*6881a400Schristos {
164*6881a400Schristos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
165*6881a400Schristos   CORE_ADDR pc = get_frame_pc (this_frame);
166*6881a400Schristos 
167*6881a400Schristos   arc_linux_debug_printf ("pc=%s", paddress(gdbarch, pc));
168*6881a400Schristos 
169*6881a400Schristos   static const gdb_byte insns_be_hs[] = {
170*6881a400Schristos     0x20, 0x8a, 0x12, 0xc2,	/* mov  r8,nr_rt_sigreturn */
171*6881a400Schristos     0x78, 0x1e			/* trap_s 0 */
172*6881a400Schristos   };
173*6881a400Schristos   static const gdb_byte insns_be_700[] = {
174*6881a400Schristos     0x20, 0x8a, 0x12, 0xc2,	/* mov  r8,nr_rt_sigreturn */
175*6881a400Schristos     0x22, 0x6f, 0x00, 0x3f	/* swi */
176*6881a400Schristos   };
177*6881a400Schristos 
178*6881a400Schristos   gdb_byte arc_sigtramp_insns[sizeof (insns_be_700)];
179*6881a400Schristos   size_t insns_sz;
180*6881a400Schristos   if (arc_mach_is_arcv2 (gdbarch))
181*6881a400Schristos     {
182*6881a400Schristos       insns_sz = sizeof (insns_be_hs);
183*6881a400Schristos       memcpy (arc_sigtramp_insns, insns_be_hs, insns_sz);
184*6881a400Schristos     }
185*6881a400Schristos   else
186*6881a400Schristos     {
187*6881a400Schristos       insns_sz = sizeof (insns_be_700);
188*6881a400Schristos       memcpy (arc_sigtramp_insns, insns_be_700, insns_sz);
189*6881a400Schristos     }
190*6881a400Schristos   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
191*6881a400Schristos     {
192*6881a400Schristos       /* On little endian targets, ARC code section is in what is called
193*6881a400Schristos 	 "middle endian", where half-words are in the big-endian order,
194*6881a400Schristos 	 only bytes inside the halfwords are in the little endian order.
195*6881a400Schristos 	 As a result it is very easy to convert big endian instruction to
196*6881a400Schristos 	 little endian, since it is needed to swap bytes in the halfwords,
197*6881a400Schristos 	 so there is no need to have information on whether that is a
198*6881a400Schristos 	 4-byte instruction or 2-byte.  */
199*6881a400Schristos       gdb_assert ((insns_sz % 2) == 0);
200*6881a400Schristos       for (int i = 0; i < insns_sz; i += 2)
201*6881a400Schristos 	std::swap (arc_sigtramp_insns[i], arc_sigtramp_insns[i+1]);
202*6881a400Schristos     }
203*6881a400Schristos 
204*6881a400Schristos   gdb_byte buf[insns_sz];
205*6881a400Schristos 
206*6881a400Schristos   /* Read the memory at the PC.  Since we are stopped, any breakpoint must
207*6881a400Schristos      have been removed.  */
208*6881a400Schristos   if (!safe_frame_unwind_memory (this_frame, pc, {buf, insns_sz}))
209*6881a400Schristos     {
210*6881a400Schristos       /* Failed to unwind frame.  */
211*6881a400Schristos       return FALSE;
212*6881a400Schristos     }
213*6881a400Schristos 
214*6881a400Schristos   /* Is that code the sigtramp instruction sequence?  */
215*6881a400Schristos   if (memcmp (buf, arc_sigtramp_insns, insns_sz) == 0)
216*6881a400Schristos     return TRUE;
217*6881a400Schristos 
218*6881a400Schristos   /* No - look one instruction earlier in the code...  */
219*6881a400Schristos   if (!safe_frame_unwind_memory (this_frame, pc - 4, {buf, insns_sz}))
220*6881a400Schristos     {
221*6881a400Schristos       /* Failed to unwind frame.  */
222*6881a400Schristos       return FALSE;
223*6881a400Schristos     }
224*6881a400Schristos 
225*6881a400Schristos   return (memcmp (buf, arc_sigtramp_insns, insns_sz) == 0);
226*6881a400Schristos }
227*6881a400Schristos 
228*6881a400Schristos /* Get sigcontext structure of sigtramp frame - it contains saved
229*6881a400Schristos    registers of interrupted frame.
230*6881a400Schristos 
231*6881a400Schristos    Stack pointer points to the rt_sigframe structure, and sigcontext can
232*6881a400Schristos    be found as in:
233*6881a400Schristos 
234*6881a400Schristos    struct rt_sigframe {
235*6881a400Schristos      struct siginfo info;
236*6881a400Schristos      struct ucontext uc;
237*6881a400Schristos      ...
238*6881a400Schristos    };
239*6881a400Schristos 
240*6881a400Schristos    struct ucontext {
241*6881a400Schristos      unsigned long uc_flags;
242*6881a400Schristos      struct ucontext *uc_link;
243*6881a400Schristos      stack_t uc_stack;
244*6881a400Schristos      struct sigcontext uc_mcontext;
245*6881a400Schristos      sigset_t uc_sigmask;
246*6881a400Schristos    };
247*6881a400Schristos 
248*6881a400Schristos    sizeof (struct siginfo) == 0x80
249*6881a400Schristos    offsetof (struct ucontext, uc_mcontext) == 0x14
250*6881a400Schristos 
251*6881a400Schristos    GDB cannot include linux headers and use offsetof () because those are
252*6881a400Schristos    target headers and GDB might be built for a different run host.  There
253*6881a400Schristos    doesn't seem to be an established mechanism to figure out those offsets
254*6881a400Schristos    via gdbserver, so the only way is to hardcode values in the GDB,
255*6881a400Schristos    meaning that GDB will be broken if values will change.  That seems to
256*6881a400Schristos    be a very unlikely scenario and other arches (aarch64, alpha, amd64,
257*6881a400Schristos    etc) in GDB hardcode values.  */
258*6881a400Schristos 
259*6881a400Schristos static CORE_ADDR
260*6881a400Schristos arc_linux_sigcontext_addr (frame_info_ptr this_frame)
261*6881a400Schristos {
262*6881a400Schristos   const int ucontext_offset = 0x80;
263*6881a400Schristos   const int sigcontext_offset = 0x14;
264*6881a400Schristos   return get_frame_sp (this_frame) + ucontext_offset + sigcontext_offset;
265*6881a400Schristos }
2667d62b00eSchristos 
2677d62b00eSchristos /* Implement the "cannot_fetch_register" gdbarch method.  */
2687d62b00eSchristos 
2697d62b00eSchristos static int
2707d62b00eSchristos arc_linux_cannot_fetch_register (struct gdbarch *gdbarch, int regnum)
2717d62b00eSchristos {
2727d62b00eSchristos   /* Assume that register is readable if it is unknown.  */
2737d62b00eSchristos   switch (regnum)
2747d62b00eSchristos     {
2757d62b00eSchristos     case ARC_ILINK_REGNUM:
2767d62b00eSchristos     case ARC_RESERVED_REGNUM:
2777d62b00eSchristos     case ARC_LIMM_REGNUM:
2787d62b00eSchristos       return true;
2797d62b00eSchristos     case ARC_R30_REGNUM:
2807d62b00eSchristos     case ARC_R58_REGNUM:
2817d62b00eSchristos     case ARC_R59_REGNUM:
2827d62b00eSchristos       return !arc_mach_is_arcv2 (gdbarch);
2837d62b00eSchristos     }
2847d62b00eSchristos   return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
2857d62b00eSchristos }
2867d62b00eSchristos 
2877d62b00eSchristos /* Implement the "cannot_store_register" gdbarch method.  */
2887d62b00eSchristos 
2897d62b00eSchristos static int
2907d62b00eSchristos arc_linux_cannot_store_register (struct gdbarch *gdbarch, int regnum)
2917d62b00eSchristos {
2927d62b00eSchristos   /* Assume that register is writable if it is unknown.  */
2937d62b00eSchristos   switch (regnum)
2947d62b00eSchristos     {
2957d62b00eSchristos     case ARC_ILINK_REGNUM:
2967d62b00eSchristos     case ARC_RESERVED_REGNUM:
2977d62b00eSchristos     case ARC_LIMM_REGNUM:
2987d62b00eSchristos     case ARC_PCL_REGNUM:
2997d62b00eSchristos       return true;
3007d62b00eSchristos     case ARC_R30_REGNUM:
3017d62b00eSchristos     case ARC_R58_REGNUM:
3027d62b00eSchristos     case ARC_R59_REGNUM:
3037d62b00eSchristos       return !arc_mach_is_arcv2 (gdbarch);
3047d62b00eSchristos     }
3057d62b00eSchristos   return (regnum > ARC_BLINK_REGNUM) && (regnum < ARC_LP_COUNT_REGNUM);
3067d62b00eSchristos }
3077d62b00eSchristos 
3087d62b00eSchristos /* For ARC Linux, breakpoints use the 16-bit TRAP_S 1 instruction, which
3097d62b00eSchristos    is 0x3e78 (little endian) or 0x783e (big endian).  */
3107d62b00eSchristos 
3117d62b00eSchristos static const gdb_byte arc_linux_trap_s_be[] = { 0x78, 0x3e };
3127d62b00eSchristos static const gdb_byte arc_linux_trap_s_le[] = { 0x3e, 0x78 };
3137d62b00eSchristos static const int trap_size = 2;   /* Number of bytes to insert "trap".  */
3147d62b00eSchristos 
3157d62b00eSchristos /* Implement the "breakpoint_kind_from_pc" gdbarch method.  */
3167d62b00eSchristos 
3177d62b00eSchristos static int
3187d62b00eSchristos arc_linux_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
3197d62b00eSchristos {
3207d62b00eSchristos   return trap_size;
3217d62b00eSchristos }
3227d62b00eSchristos 
3237d62b00eSchristos /* Implement the "sw_breakpoint_from_kind" gdbarch method.  */
3247d62b00eSchristos 
3257d62b00eSchristos static const gdb_byte *
3267d62b00eSchristos arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch,
3277d62b00eSchristos 				   int kind, int *size)
3287d62b00eSchristos {
329*6881a400Schristos   gdb_assert (kind == trap_size);
3307d62b00eSchristos   *size = kind;
3317d62b00eSchristos   return ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
3327d62b00eSchristos 	  ? arc_linux_trap_s_be
3337d62b00eSchristos 	  : arc_linux_trap_s_le);
3347d62b00eSchristos }
3357d62b00eSchristos 
336*6881a400Schristos /* Check for an atomic sequence of instructions beginning with an
337*6881a400Schristos    LLOCK instruction and ending with a SCOND instruction.
338*6881a400Schristos 
339*6881a400Schristos    These patterns are hand coded in libc's (glibc and uclibc). Take
340*6881a400Schristos    a look at [1] for instance:
341*6881a400Schristos 
342*6881a400Schristos    main+14: llock   r2,[r0]
343*6881a400Schristos    main+18: brne.nt r2,0,main+30
344*6881a400Schristos    main+22: scond   r3,[r0]
345*6881a400Schristos    main+26: bne     main+14
346*6881a400Schristos    main+30: mov_s   r0,0
347*6881a400Schristos 
348*6881a400Schristos    If such a sequence is found, attempt to step over it.
349*6881a400Schristos    A breakpoint is placed at the end of the sequence.
350*6881a400Schristos 
351*6881a400Schristos    This function expects the INSN to be a "llock(d)" instruction.
352*6881a400Schristos 
353*6881a400Schristos    [1]
354*6881a400Schristos    https://cgit.uclibc-ng.org/cgi/cgit/uclibc-ng.git/tree/libc/ \
355*6881a400Schristos      sysdeps/linux/arc/bits/atomic.h#n46
356*6881a400Schristos    */
357*6881a400Schristos 
358*6881a400Schristos static std::vector<CORE_ADDR>
359*6881a400Schristos handle_atomic_sequence (arc_instruction insn, disassemble_info *di)
360*6881a400Schristos {
361*6881a400Schristos   const int atomic_seq_len = 24;    /* Instruction sequence length.  */
362*6881a400Schristos   std::vector<CORE_ADDR> next_pcs;
363*6881a400Schristos 
364*6881a400Schristos   /* Sanity check.  */
365*6881a400Schristos   gdb_assert (insn.insn_class == LLOCK);
366*6881a400Schristos 
367*6881a400Schristos   /* Data size we are dealing with: LLOCK vs. LLOCKD  */
368*6881a400Schristos   arc_ldst_data_size llock_data_size_mode = insn.data_size_mode;
369*6881a400Schristos   /* Indicator if any conditional branch is found in the sequence.  */
370*6881a400Schristos   bool found_bc = false;
371*6881a400Schristos   /* Becomes true if "LLOCK(D) .. SCOND(D)" sequence is found.  */
372*6881a400Schristos   bool is_pattern_valid = false;
373*6881a400Schristos 
374*6881a400Schristos   for (int insn_count = 0; insn_count < atomic_seq_len; ++insn_count)
375*6881a400Schristos     {
376*6881a400Schristos       arc_insn_decode (arc_insn_get_linear_next_pc (insn),
377*6881a400Schristos 		       di, arc_delayed_print_insn, &insn);
378*6881a400Schristos 
379*6881a400Schristos       if (insn.insn_class == BRCC)
380*6881a400Schristos         {
381*6881a400Schristos           /* If more than one conditional branch is found, this is not
382*6881a400Schristos              the pattern we are interested in.  */
383*6881a400Schristos           if (found_bc)
384*6881a400Schristos 	    break;
385*6881a400Schristos 	  found_bc = true;
386*6881a400Schristos 	  continue;
387*6881a400Schristos         }
388*6881a400Schristos 
389*6881a400Schristos       /* This is almost a happy ending.  */
390*6881a400Schristos       if (insn.insn_class == SCOND)
391*6881a400Schristos         {
392*6881a400Schristos 	  /* SCOND should match the LLOCK's data size.  */
393*6881a400Schristos 	  if (insn.data_size_mode == llock_data_size_mode)
394*6881a400Schristos 	    is_pattern_valid = true;
395*6881a400Schristos 	  break;
396*6881a400Schristos         }
397*6881a400Schristos     }
398*6881a400Schristos 
399*6881a400Schristos   if (is_pattern_valid)
400*6881a400Schristos     {
401*6881a400Schristos       /* Get next instruction after scond(d).  There is no limm.  */
402*6881a400Schristos       next_pcs.push_back (insn.address + insn.length);
403*6881a400Schristos     }
404*6881a400Schristos 
405*6881a400Schristos   return next_pcs;
406*6881a400Schristos }
407*6881a400Schristos 
4087d62b00eSchristos /* Implement the "software_single_step" gdbarch method.  */
4097d62b00eSchristos 
4107d62b00eSchristos static std::vector<CORE_ADDR>
4117d62b00eSchristos arc_linux_software_single_step (struct regcache *regcache)
4127d62b00eSchristos {
4137d62b00eSchristos   struct gdbarch *gdbarch = regcache->arch ();
414*6881a400Schristos   arc_gdbarch_tdep *tdep = gdbarch_tdep<arc_gdbarch_tdep> (gdbarch);
415*6881a400Schristos   struct gdb_non_printing_memory_disassembler dis (gdbarch);
4167d62b00eSchristos 
4177d62b00eSchristos   /* Read current instruction.  */
4187d62b00eSchristos   struct arc_instruction curr_insn;
419*6881a400Schristos   arc_insn_decode (regcache_read_pc (regcache), dis.disasm_info (),
420*6881a400Schristos 		   arc_delayed_print_insn, &curr_insn);
4217d62b00eSchristos 
422*6881a400Schristos   if (curr_insn.insn_class == LLOCK)
423*6881a400Schristos     return handle_atomic_sequence (curr_insn, dis.disasm_info ());
424*6881a400Schristos 
425*6881a400Schristos   CORE_ADDR next_pc = arc_insn_get_linear_next_pc (curr_insn);
4267d62b00eSchristos   std::vector<CORE_ADDR> next_pcs;
4277d62b00eSchristos 
4287d62b00eSchristos   /* For instructions with delay slots, the fall thru is not the
4297d62b00eSchristos      instruction immediately after the current instruction, but the one
4307d62b00eSchristos      after that.  */
4317d62b00eSchristos   if (curr_insn.has_delay_slot)
4327d62b00eSchristos     {
4337d62b00eSchristos       struct arc_instruction next_insn;
434*6881a400Schristos       arc_insn_decode (next_pc, dis.disasm_info (), arc_delayed_print_insn,
435*6881a400Schristos 		       &next_insn);
4367d62b00eSchristos       next_pcs.push_back (arc_insn_get_linear_next_pc (next_insn));
4377d62b00eSchristos     }
4387d62b00eSchristos   else
4397d62b00eSchristos     next_pcs.push_back (next_pc);
4407d62b00eSchristos 
4417d62b00eSchristos   ULONGEST status32;
4427d62b00eSchristos   regcache_cooked_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch),
4437d62b00eSchristos 				 &status32);
4447d62b00eSchristos 
4457d62b00eSchristos   if (curr_insn.is_control_flow)
4467d62b00eSchristos     {
4477d62b00eSchristos       CORE_ADDR branch_pc = arc_insn_get_branch_target (curr_insn);
4487d62b00eSchristos       if (branch_pc != next_pc)
4497d62b00eSchristos 	next_pcs.push_back (branch_pc);
4507d62b00eSchristos     }
4517d62b00eSchristos   /* Is current instruction the last in a loop body?  */
4527d62b00eSchristos   else if (tdep->has_hw_loops)
4537d62b00eSchristos     {
4547d62b00eSchristos       /* If STATUS32.L is 1, then ZD-loops are disabled.  */
4557d62b00eSchristos       if ((status32 & ARC_STATUS32_L_MASK) == 0)
4567d62b00eSchristos 	{
4577d62b00eSchristos 	  ULONGEST lp_end, lp_start, lp_count;
4587d62b00eSchristos 	  regcache_cooked_read_unsigned (regcache, ARC_LP_START_REGNUM,
4597d62b00eSchristos 					 &lp_start);
4607d62b00eSchristos 	  regcache_cooked_read_unsigned (regcache, ARC_LP_END_REGNUM, &lp_end);
4617d62b00eSchristos 	  regcache_cooked_read_unsigned (regcache, ARC_LP_COUNT_REGNUM,
4627d62b00eSchristos 					 &lp_count);
4637d62b00eSchristos 
464*6881a400Schristos 	  arc_linux_debug_printf ("lp_start = %s, lp_end = %s, "
465*6881a400Schristos 				  "lp_count = %s, next_pc = %s",
4667d62b00eSchristos 				  paddress (gdbarch, lp_start),
4677d62b00eSchristos 				  paddress (gdbarch, lp_end),
4687d62b00eSchristos 				  pulongest (lp_count),
4697d62b00eSchristos 				  paddress (gdbarch, next_pc));
4707d62b00eSchristos 
4717d62b00eSchristos 	  if (next_pc == lp_end && lp_count > 1)
4727d62b00eSchristos 	    {
4737d62b00eSchristos 	      /* The instruction is in effect a jump back to the start of
4747d62b00eSchristos 		 the loop.  */
4757d62b00eSchristos 	      next_pcs.push_back (lp_start);
4767d62b00eSchristos 	    }
4777d62b00eSchristos 	}
4787d62b00eSchristos     }
4797d62b00eSchristos 
4807d62b00eSchristos   /* Is this a delay slot?  Then next PC is in BTA register.  */
4817d62b00eSchristos   if ((status32 & ARC_STATUS32_DE_MASK) != 0)
4827d62b00eSchristos     {
4837d62b00eSchristos       ULONGEST bta;
4847d62b00eSchristos       regcache_cooked_read_unsigned (regcache, ARC_BTA_REGNUM, &bta);
4857d62b00eSchristos       next_pcs.push_back (bta);
4867d62b00eSchristos     }
4877d62b00eSchristos 
4887d62b00eSchristos   return next_pcs;
4897d62b00eSchristos }
4907d62b00eSchristos 
4917d62b00eSchristos /* Implement the "skip_solib_resolver" gdbarch method.
4927d62b00eSchristos 
4937d62b00eSchristos    See glibc_skip_solib_resolver for details.  */
4947d62b00eSchristos 
4957d62b00eSchristos static CORE_ADDR
4967d62b00eSchristos arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
4977d62b00eSchristos {
4987d62b00eSchristos   /* For uClibc 0.9.26+.
4997d62b00eSchristos 
5007d62b00eSchristos      An unresolved PLT entry points to "__dl_linux_resolve", which calls
5017d62b00eSchristos      "_dl_linux_resolver" to do the resolving and then eventually jumps to
5027d62b00eSchristos      the function.
5037d62b00eSchristos 
5047d62b00eSchristos      So we look for the symbol `_dl_linux_resolver', and if we are there,
5057d62b00eSchristos      gdb sets a breakpoint at the return address, and continues.  */
5067d62b00eSchristos   struct bound_minimal_symbol resolver
5077d62b00eSchristos     = lookup_minimal_symbol ("_dl_linux_resolver", NULL, NULL);
5087d62b00eSchristos 
5097d62b00eSchristos   if (arc_debug)
5107d62b00eSchristos     {
5117d62b00eSchristos       if (resolver.minsym != nullptr)
5127d62b00eSchristos 	{
513*6881a400Schristos 	  CORE_ADDR res_addr = resolver.value_address ();
514*6881a400Schristos 	  arc_linux_debug_printf ("pc = %s, resolver at %s",
5157d62b00eSchristos 				  print_core_address (gdbarch, pc),
5167d62b00eSchristos 				  print_core_address (gdbarch, res_addr));
5177d62b00eSchristos 	}
5187d62b00eSchristos       else
519*6881a400Schristos 	arc_linux_debug_printf ("pc = %s, no resolver found",
5207d62b00eSchristos 				print_core_address (gdbarch, pc));
5217d62b00eSchristos     }
5227d62b00eSchristos 
523*6881a400Schristos   if (resolver.minsym != nullptr && resolver.value_address () == pc)
5247d62b00eSchristos     {
5257d62b00eSchristos       /* Find the return address.  */
5267d62b00eSchristos       return frame_unwind_caller_pc (get_current_frame ());
5277d62b00eSchristos     }
5287d62b00eSchristos   else
5297d62b00eSchristos     {
5307d62b00eSchristos       /* No breakpoint required.  */
5317d62b00eSchristos       return 0;
5327d62b00eSchristos     }
5337d62b00eSchristos }
5347d62b00eSchristos 
535*6881a400Schristos /* Populate REGCACHE with register REGNUM from BUF.  */
536*6881a400Schristos 
537*6881a400Schristos static void
538*6881a400Schristos supply_register (struct regcache *regcache, int regnum, const gdb_byte *buf)
539*6881a400Schristos {
540*6881a400Schristos   /* Skip non-existing registers.  */
541*6881a400Schristos   if ((arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER))
542*6881a400Schristos     return;
543*6881a400Schristos 
544*6881a400Schristos   regcache->raw_supply (regnum, buf + arc_linux_core_reg_offsets[regnum]);
545*6881a400Schristos }
546*6881a400Schristos 
547*6881a400Schristos void
548*6881a400Schristos arc_linux_supply_gregset (const struct regset *regset,
549*6881a400Schristos 			  struct regcache *regcache,
550*6881a400Schristos 			  int regnum, const void *gregs, size_t size)
551*6881a400Schristos {
552*6881a400Schristos   gdb_static_assert (ARC_LAST_REGNUM
553*6881a400Schristos 		     < ARRAY_SIZE (arc_linux_core_reg_offsets));
554*6881a400Schristos 
555*6881a400Schristos   const bfd_byte *buf = (const bfd_byte *) gregs;
556*6881a400Schristos 
557*6881a400Schristos   /* REGNUM == -1 means writing all the registers.  */
558*6881a400Schristos   if (regnum == -1)
559*6881a400Schristos     for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
560*6881a400Schristos       supply_register (regcache, reg, buf);
561*6881a400Schristos   else if (regnum <= ARC_LAST_REGNUM)
562*6881a400Schristos     supply_register (regcache, regnum, buf);
563*6881a400Schristos   else
564*6881a400Schristos     gdb_assert_not_reached ("Invalid regnum in arc_linux_supply_gregset.");
565*6881a400Schristos }
566*6881a400Schristos 
567*6881a400Schristos void
568*6881a400Schristos arc_linux_supply_v2_regset (const struct regset *regset,
569*6881a400Schristos 			    struct regcache *regcache, int regnum,
570*6881a400Schristos 			    const void *v2_regs, size_t size)
571*6881a400Schristos {
572*6881a400Schristos   const bfd_byte *buf = (const bfd_byte *) v2_regs;
573*6881a400Schristos 
574*6881a400Schristos   /* user_regs_arcv2 is defined in linux arch/arc/include/uapi/asm/ptrace.h.  */
575*6881a400Schristos   if (regnum == -1 || regnum == ARC_R30_REGNUM)
576*6881a400Schristos     regcache->raw_supply (ARC_R30_REGNUM, buf);
577*6881a400Schristos   if (regnum == -1 || regnum == ARC_R58_REGNUM)
578*6881a400Schristos     regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
579*6881a400Schristos   if (regnum == -1 || regnum == ARC_R59_REGNUM)
580*6881a400Schristos     regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
581*6881a400Schristos }
582*6881a400Schristos 
583*6881a400Schristos /* Populate BUF with register REGNUM from the REGCACHE.  */
584*6881a400Schristos 
585*6881a400Schristos static void
586*6881a400Schristos collect_register (const struct regcache *regcache, struct gdbarch *gdbarch,
587*6881a400Schristos 		  int regnum, gdb_byte *buf)
588*6881a400Schristos {
589*6881a400Schristos   int offset;
590*6881a400Schristos 
591*6881a400Schristos   /* Skip non-existing registers.  */
592*6881a400Schristos   if (arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER)
593*6881a400Schristos     return;
594*6881a400Schristos 
595*6881a400Schristos   /* The address where the execution has stopped is in pseudo-register
596*6881a400Schristos      STOP_PC.  However, when kernel code is returning from the exception,
597*6881a400Schristos      it uses the value from ERET register.  Since, TRAP_S (the breakpoint
598*6881a400Schristos      instruction) commits, the ERET points to the next instruction.  In
599*6881a400Schristos      other words: ERET != STOP_PC.  To jump back from the kernel code to
600*6881a400Schristos      the correct address, ERET must be overwritten by GDB's STOP_PC.  Else,
601*6881a400Schristos      the program will continue at the address after the current instruction.
602*6881a400Schristos      */
603*6881a400Schristos   if (regnum == gdbarch_pc_regnum (gdbarch))
604*6881a400Schristos     offset = arc_linux_core_reg_offsets[ARC_ERET_REGNUM];
605*6881a400Schristos   else
606*6881a400Schristos     offset = arc_linux_core_reg_offsets[regnum];
607*6881a400Schristos   regcache->raw_collect (regnum, buf + offset);
608*6881a400Schristos }
609*6881a400Schristos 
610*6881a400Schristos void
611*6881a400Schristos arc_linux_collect_gregset (const struct regset *regset,
612*6881a400Schristos 			   const struct regcache *regcache,
613*6881a400Schristos 			   int regnum, void *gregs, size_t size)
614*6881a400Schristos {
615*6881a400Schristos   gdb_static_assert (ARC_LAST_REGNUM
616*6881a400Schristos 		     < ARRAY_SIZE (arc_linux_core_reg_offsets));
617*6881a400Schristos 
618*6881a400Schristos   gdb_byte *buf = (gdb_byte *) gregs;
619*6881a400Schristos   struct gdbarch *gdbarch = regcache->arch ();
620*6881a400Schristos 
621*6881a400Schristos   /* REGNUM == -1 means writing all the registers.  */
622*6881a400Schristos   if (regnum == -1)
623*6881a400Schristos     for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
624*6881a400Schristos       collect_register (regcache, gdbarch, reg, buf);
625*6881a400Schristos   else if (regnum <= ARC_LAST_REGNUM)
626*6881a400Schristos     collect_register (regcache, gdbarch, regnum, buf);
627*6881a400Schristos   else
628*6881a400Schristos     gdb_assert_not_reached ("Invalid regnum in arc_linux_collect_gregset.");
629*6881a400Schristos }
630*6881a400Schristos 
631*6881a400Schristos void
632*6881a400Schristos arc_linux_collect_v2_regset (const struct regset *regset,
633*6881a400Schristos 			     const struct regcache *regcache, int regnum,
634*6881a400Schristos 			     void *v2_regs, size_t size)
635*6881a400Schristos {
636*6881a400Schristos   bfd_byte *buf = (bfd_byte *) v2_regs;
637*6881a400Schristos 
638*6881a400Schristos   if (regnum == -1 || regnum == ARC_R30_REGNUM)
639*6881a400Schristos     regcache->raw_collect (ARC_R30_REGNUM, buf);
640*6881a400Schristos   if (regnum == -1 || regnum == ARC_R58_REGNUM)
641*6881a400Schristos     regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
642*6881a400Schristos   if (regnum == -1 || regnum == ARC_R59_REGNUM)
643*6881a400Schristos     regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
644*6881a400Schristos }
645*6881a400Schristos 
646*6881a400Schristos /* Linux regset definitions.  */
647*6881a400Schristos 
648*6881a400Schristos static const struct regset arc_linux_gregset = {
649*6881a400Schristos   arc_linux_core_reg_offsets,
650*6881a400Schristos   arc_linux_supply_gregset,
651*6881a400Schristos   arc_linux_collect_gregset,
652*6881a400Schristos };
653*6881a400Schristos 
654*6881a400Schristos static const struct regset arc_linux_v2_regset = {
655*6881a400Schristos   NULL,
656*6881a400Schristos   arc_linux_supply_v2_regset,
657*6881a400Schristos   arc_linux_collect_v2_regset,
658*6881a400Schristos };
659*6881a400Schristos 
660*6881a400Schristos /* Implement the `iterate_over_regset_sections` gdbarch method.  */
661*6881a400Schristos 
662*6881a400Schristos static void
663*6881a400Schristos arc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
664*6881a400Schristos 					iterate_over_regset_sections_cb *cb,
665*6881a400Schristos 					void *cb_data,
666*6881a400Schristos 					const struct regcache *regcache)
667*6881a400Schristos {
668*6881a400Schristos   /* There are 40 registers in Linux user_regs_struct, although some of
669*6881a400Schristos      them are now just a mere paddings, kept to maintain binary
670*6881a400Schristos      compatibility with older tools.  */
671*6881a400Schristos   const int sizeof_gregset = 40 * ARC_REGISTER_SIZE;
672*6881a400Schristos 
673*6881a400Schristos   cb (".reg", sizeof_gregset, sizeof_gregset, &arc_linux_gregset, NULL,
674*6881a400Schristos       cb_data);
675*6881a400Schristos   cb (".reg-arc-v2", ARC_LINUX_SIZEOF_V2_REGSET, ARC_LINUX_SIZEOF_V2_REGSET,
676*6881a400Schristos       &arc_linux_v2_regset, NULL, cb_data);
677*6881a400Schristos }
678*6881a400Schristos 
679*6881a400Schristos /* Implement the `core_read_description` gdbarch method.  */
680*6881a400Schristos 
681*6881a400Schristos static const struct target_desc *
682*6881a400Schristos arc_linux_core_read_description (struct gdbarch *gdbarch,
683*6881a400Schristos 				 struct target_ops *target,
684*6881a400Schristos 				 bfd *abfd)
685*6881a400Schristos {
686*6881a400Schristos   arc_arch_features features
687*6881a400Schristos     = arc_arch_features_create (abfd,
688*6881a400Schristos 				gdbarch_bfd_arch_info (gdbarch)->mach);
689*6881a400Schristos   return arc_lookup_target_description (features);
690*6881a400Schristos }
691*6881a400Schristos 
6927d62b00eSchristos /* Initialization specific to Linux environment.  */
6937d62b00eSchristos 
6947d62b00eSchristos static void
6957d62b00eSchristos arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
6967d62b00eSchristos {
697*6881a400Schristos   arc_gdbarch_tdep *tdep = gdbarch_tdep<arc_gdbarch_tdep> (gdbarch);
6987d62b00eSchristos 
699*6881a400Schristos   arc_linux_debug_printf ("GNU/Linux OS/ABI initialization.");
700*6881a400Schristos 
701*6881a400Schristos   /* Fill in target-dependent info in ARC-private structure.  */
702*6881a400Schristos   tdep->is_sigtramp = arc_linux_is_sigtramp;
703*6881a400Schristos   tdep->sigcontext_addr = arc_linux_sigcontext_addr;
704*6881a400Schristos   tdep->sc_reg_offset = arc_linux_sc_reg_offsets;
705*6881a400Schristos   tdep->sc_num_regs = ARRAY_SIZE (arc_linux_sc_reg_offsets);
7067d62b00eSchristos 
7077d62b00eSchristos   /* If we are using Linux, we have in uClibc
7087d62b00eSchristos      (libc/sysdeps/linux/arc/bits/setjmp.h):
7097d62b00eSchristos 
7107d62b00eSchristos      typedef int __jmp_buf[13+1+1+1];    //r13-r25, fp, sp, blink
7117d62b00eSchristos 
7127d62b00eSchristos      Where "blink" is a stored PC of a caller function.
7137d62b00eSchristos    */
7147d62b00eSchristos   tdep->jb_pc = 15;
7157d62b00eSchristos 
716*6881a400Schristos   linux_init_abi (info, gdbarch, 0);
7177d62b00eSchristos 
7187d62b00eSchristos   /* Set up target dependent GDB architecture entries.  */
7197d62b00eSchristos   set_gdbarch_cannot_fetch_register (gdbarch, arc_linux_cannot_fetch_register);
7207d62b00eSchristos   set_gdbarch_cannot_store_register (gdbarch, arc_linux_cannot_store_register);
7217d62b00eSchristos   set_gdbarch_breakpoint_kind_from_pc (gdbarch,
7227d62b00eSchristos 				       arc_linux_breakpoint_kind_from_pc);
7237d62b00eSchristos   set_gdbarch_sw_breakpoint_from_kind (gdbarch,
7247d62b00eSchristos 				       arc_linux_sw_breakpoint_from_kind);
7257d62b00eSchristos   set_gdbarch_fetch_tls_load_module_address (gdbarch,
7267d62b00eSchristos 					     svr4_fetch_objfile_link_map);
7277d62b00eSchristos   set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
7287d62b00eSchristos   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
7297d62b00eSchristos   set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
730*6881a400Schristos   set_gdbarch_iterate_over_regset_sections
731*6881a400Schristos     (gdbarch, arc_linux_iterate_over_regset_sections);
732*6881a400Schristos   set_gdbarch_core_read_description (gdbarch, arc_linux_core_read_description);
7337d62b00eSchristos 
7347d62b00eSchristos   /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
7357d62b00eSchristos      and pointers (ILP32).  */
7367d62b00eSchristos   set_solib_svr4_fetch_link_map_offsets (gdbarch,
737*6881a400Schristos 					 linux_ilp32_fetch_link_map_offsets);
7387d62b00eSchristos }
7397d62b00eSchristos 
7407d62b00eSchristos /* Suppress warning from -Wmissing-prototypes.  */
7417d62b00eSchristos extern initialize_file_ftype _initialize_arc_linux_tdep;
7427d62b00eSchristos 
7437d62b00eSchristos void
7447d62b00eSchristos _initialize_arc_linux_tdep ()
7457d62b00eSchristos {
7467d62b00eSchristos   gdbarch_register_osabi (bfd_arch_arc, 0, GDB_OSABI_LINUX,
7477d62b00eSchristos 			  arc_linux_init_osabi);
7487d62b00eSchristos }
749