summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-devtools/gdb/gdb-10.2.inc4
-rw-r--r--meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch218
-rw-r--r--meta/recipes-devtools/gdb/gdb/0013-arc-Add-support-for-signal-frames-for-Linux-targets.patch232
-rw-r--r--meta/recipes-devtools/gdb/gdb/0014-arc-Take-into-account-the-REGNUM-in-supply-collect-g.patch104
-rw-r--r--meta/recipes-devtools/gdb/gdb/0015-gdb-Add-native-support-for-ARC-in-GNU-Linux.patch414
5 files changed, 972 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gdb/gdb-10.2.inc b/meta/recipes-devtools/gdb/gdb-10.2.inc
index 0a7df54e9f..0d275075e6 100644
--- a/meta/recipes-devtools/gdb/gdb-10.2.inc
+++ b/meta/recipes-devtools/gdb/gdb-10.2.inc
@@ -15,5 +15,9 @@ SRC_URI = "${GNU_MIRROR}/gdb/gdb-${PV}.tar.xz \
15 file://0009-resolve-restrict-keyword-conflict.patch \ 15 file://0009-resolve-restrict-keyword-conflict.patch \
16 file://0010-Fix-invalid-sigprocmask-call.patch \ 16 file://0010-Fix-invalid-sigprocmask-call.patch \
17 file://0011-gdbserver-ctrl-c-handling.patch \ 17 file://0011-gdbserver-ctrl-c-handling.patch \
18 file://0012-arc-Add-support-for-signal-handlers.patch \
19 file://0013-arc-Add-support-for-signal-frames-for-Linux-targets.patch \
20 file://0014-arc-Take-into-account-the-REGNUM-in-supply-collect-g.patch \
21 file://0015-gdb-Add-native-support-for-ARC-in-GNU-Linux.patch \
18 " 22 "
19SRC_URI[sha256sum] = "aaa1223d534c9b700a8bec952d9748ee1977513f178727e1bee520ee000b4f29" 23SRC_URI[sha256sum] = "aaa1223d534c9b700a8bec952d9748ee1977513f178727e1bee520ee000b4f29"
diff --git a/meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch b/meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch
new file mode 100644
index 0000000000..6a98b65766
--- /dev/null
+++ b/meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch
@@ -0,0 +1,218 @@
1From bfee93403b46ae4f050282b7721ba39073905c69 Mon Sep 17 00:00:00 2001
2From: Anton Kolesov <Anton.Kolesov@synopsys.com>
3Date: Mon, 22 Aug 2016 19:39:46 +0300
4Subject: [PATCH 1/4] arc: Add support for signal handlers
5
6This patch adds the necessary infrastructure to handle signal frames for
7ARC architecture. It is fairly similar to what any other architecture
8would have. Linux specific parts will be in a separate patch.
9
10v2 [1]:
11- Make the logic of "arc_sigtramp_frame_sniffer ()" simpler.
12
13[1] Tom's remark for the first version
14https://sourceware.org/pipermail/gdb-patches/2020-November/173221.html
15
16gdb/ChangeLog:
17
18 * arc-tdep.c (arc_make_sigtramp_frame_cache): New function.
19 (arc_sigtramp_frame_this_id): Likewise.
20 (arc_sigtramp_frame_prev_register): Likewise.
21 (arc_sigtramp_frame_sniffer): Likewise.
22 (arc_siftramp_frame_unwind): New global variable.
23 (arc_gdbarch_init): Use sigtramp capabilities.
24 (arc_dump_tdep): Print sigtramp fields.
25 * arc-tdep.h (gdbarch_tdep): Add sigtramp fields.
26
27Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=b4e3cd0440109d0a5552d3313ccbd35c8103335b]
28
29Signed-off-by: Anton Kolesov <Anton.Kolesov@synopsys.com>
30Signed-off-by: Shahab Vahedi <shahab@synopsys.com>
31Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
32---
33 gdb/arc-tdep.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
34 gdb/arc-tdep.h | 13 ++++++
35 2 files changed, 136 insertions(+)
36
37diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
38index 93e2fd88a9a..3356252525d 100644
39--- a/gdb/arc-tdep.c
40+++ b/gdb/arc-tdep.c
41@@ -1843,6 +1843,104 @@ arc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
42 reg->how = DWARF2_FRAME_REG_CFA;
43 }
44
45+/* Signal trampoline frame unwinder. Allows frame unwinding to happen
46+ from within signal handlers. */
47+
48+static struct arc_frame_cache *
49+arc_make_sigtramp_frame_cache (struct frame_info *this_frame)
50+{
51+ if (arc_debug)
52+ debug_printf ("arc: sigtramp_frame_cache\n");
53+
54+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
55+
56+ /* Allocate new frame cache instance and space for saved register info. */
57+ struct arc_frame_cache *cache = FRAME_OBSTACK_ZALLOC (struct arc_frame_cache);
58+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
59+
60+ /* Get the stack pointer and use it as the frame base. */
61+ cache->prev_sp = arc_frame_base_address (this_frame, NULL);
62+
63+ /* If the ARC-private target-dependent info doesn't have a table of
64+ offsets of saved register contents within an OS signal context
65+ structure, then there is nothing to analyze. */
66+ if (tdep->sc_reg_offset == NULL)
67+ return cache;
68+
69+ /* Find the address of the sigcontext structure. */
70+ CORE_ADDR addr = tdep->sigcontext_addr (this_frame);
71+
72+ /* For each register, if its contents have been saved within the
73+ sigcontext structure, determine the address of those contents. */
74+ gdb_assert (tdep->sc_num_regs <= (ARC_LAST_REGNUM + 1));
75+ for (int i = 0; i < tdep->sc_num_regs; i++)
76+ {
77+ if (tdep->sc_reg_offset[i] != ARC_OFFSET_NO_REGISTER)
78+ cache->saved_regs[i].addr = addr + tdep->sc_reg_offset[i];
79+ }
80+
81+ return cache;
82+}
83+
84+/* Implement the "this_id" frame_unwind method for signal trampoline
85+ frames. */
86+
87+static void
88+arc_sigtramp_frame_this_id (struct frame_info *this_frame,
89+ void **this_cache, struct frame_id *this_id)
90+{
91+ if (arc_debug)
92+ debug_printf ("arc: sigtramp_frame_this_id\n");
93+
94+ if (*this_cache == NULL)
95+ *this_cache = arc_make_sigtramp_frame_cache (this_frame);
96+
97+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
98+ struct arc_frame_cache *cache = (struct arc_frame_cache *) *this_cache;
99+ CORE_ADDR stack_addr = cache->prev_sp;
100+ CORE_ADDR code_addr
101+ = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
102+ *this_id = frame_id_build (stack_addr, code_addr);
103+}
104+
105+/* Get a register from a signal handler frame. */
106+
107+static struct value *
108+arc_sigtramp_frame_prev_register (struct frame_info *this_frame,
109+ void **this_cache, int regnum)
110+{
111+ if (arc_debug)
112+ debug_printf ("arc: sigtramp_frame_prev_register (regnum = %d)\n", regnum);
113+
114+ /* Make sure we've initialized the cache. */
115+ if (*this_cache == NULL)
116+ *this_cache = arc_make_sigtramp_frame_cache (this_frame);
117+
118+ struct arc_frame_cache *cache = (struct arc_frame_cache *) *this_cache;
119+ return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
120+}
121+
122+/* Frame sniffer for signal handler frame. Only recognize a frame if we
123+ have a sigcontext_addr handler in the target dependency. */
124+
125+static int
126+arc_sigtramp_frame_sniffer (const struct frame_unwind *self,
127+ struct frame_info *this_frame,
128+ void **this_cache)
129+{
130+ struct gdbarch_tdep *tdep;
131+
132+ if (arc_debug)
133+ debug_printf ("arc: sigtramp_frame_sniffer\n");
134+
135+ tdep = gdbarch_tdep (get_frame_arch (this_frame));
136+
137+ /* If we have a sigcontext_addr handler, then just return 1 (same as the
138+ "default_frame_sniffer ()"). */
139+ return (tdep->sigcontext_addr != NULL && tdep->is_sigtramp != NULL
140+ && tdep->is_sigtramp (this_frame));
141+}
142+
143 /* Structure defining the ARC ordinary frame unwind functions. Since we are
144 the fallback unwinder, we use the default frame sniffer, which always
145 accepts the frame. */
146@@ -1858,6 +1956,21 @@ static const struct frame_unwind arc_frame_unwind = {
147 NULL
148 };
149
150+/* Structure defining the ARC signal frame unwind functions. Custom
151+ sniffer is used, because this frame must be accepted only in the right
152+ context. */
153+
154+static const struct frame_unwind arc_sigtramp_frame_unwind = {
155+ SIGTRAMP_FRAME,
156+ default_frame_unwind_stop_reason,
157+ arc_sigtramp_frame_this_id,
158+ arc_sigtramp_frame_prev_register,
159+ NULL,
160+ arc_sigtramp_frame_sniffer,
161+ NULL,
162+ NULL
163+};
164+
165
166 static const struct frame_base arc_normal_base = {
167 &arc_frame_unwind,
168@@ -2272,6 +2385,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
169 /* Frame unwinders and sniffers. */
170 dwarf2_frame_set_init_reg (gdbarch, arc_dwarf2_frame_init_reg);
171 dwarf2_append_unwinders (gdbarch);
172+ frame_unwind_append_unwinder (gdbarch, &arc_sigtramp_frame_unwind);
173 frame_unwind_append_unwinder (gdbarch, &arc_frame_unwind);
174 frame_base_set_default (gdbarch, &arc_normal_base);
175
176@@ -2350,6 +2464,15 @@ arc_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
177 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
178
179 fprintf_unfiltered (file, "arc_dump_tdep: jb_pc = %i\n", tdep->jb_pc);
180+
181+ fprintf_unfiltered (file, "arc_dump_tdep: is_sigtramp = <%s>\n",
182+ host_address_to_string (tdep->is_sigtramp));
183+ fprintf_unfiltered (file, "arc_dump_tdep: sigcontext_addr = <%s>\n",
184+ host_address_to_string (tdep->sigcontext_addr));
185+ fprintf_unfiltered (file, "arc_dump_tdep: sc_reg_offset = <%s>\n",
186+ host_address_to_string (tdep->sc_reg_offset));
187+ fprintf_unfiltered (file, "arc_dump_tdep: sc_num_regs = %d\n",
188+ tdep->sc_num_regs);
189 }
190
191 /* This command accepts single argument - address of instruction to
192diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
193index 50b14905134..70fc3d95c48 100644
194--- a/gdb/arc-tdep.h
195+++ b/gdb/arc-tdep.h
196@@ -124,6 +124,19 @@ struct gdbarch_tdep
197
198 /* Whether target has hardware (aka zero-delay) loops. */
199 bool has_hw_loops;
200+
201+ /* Detect sigtramp. */
202+ bool (*is_sigtramp) (struct frame_info *);
203+
204+ /* Get address of sigcontext for sigtramp. */
205+ CORE_ADDR (*sigcontext_addr) (struct frame_info *);
206+
207+ /* Offset of registers in `struct sigcontext'. */
208+ const int *sc_reg_offset;
209+
210+ /* Number of registers in sc_reg_offsets. Most likely a ARC_LAST_REGNUM,
211+ but in theory it could be less, so it is kept separate. */
212+ int sc_num_regs;
213 };
214
215 /* Utility functions used by other ARC-specific modules. */
216--
2172.16.2
218
diff --git a/meta/recipes-devtools/gdb/gdb/0013-arc-Add-support-for-signal-frames-for-Linux-targets.patch b/meta/recipes-devtools/gdb/gdb/0013-arc-Add-support-for-signal-frames-for-Linux-targets.patch
new file mode 100644
index 0000000000..f699a5888d
--- /dev/null
+++ b/meta/recipes-devtools/gdb/gdb/0013-arc-Add-support-for-signal-frames-for-Linux-targets.patch
@@ -0,0 +1,232 @@
1From 16ddc17b4f403a38701e0108b02aff967900cc66 Mon Sep 17 00:00:00 2001
2From: Anton Kolesov <Anton.Kolesov@synopsys.com>
3Date: Thu, 22 Dec 2016 21:52:16 +0300
4Subject: [PATCH 2/4] arc: Add support for signal frames for Linux targets
5
6Implement functions needed to unwind signal frames on ARC Linux targets.
7
8gdb/ChangeLog
9
10 * arc-linux-tdep.c (arc_linux_sc_reg_offsets): New static variable.
11 (arc_linux_is_sigtramp): New function.
12 (arc_linux_sigcontext_addr): Likewise.
13 (arc_linux_init_osabi): Use them.
14
15Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=d4af727286e3a9f177ba11677fbd3a012d36558a]
16
17Signed-off-by: Anton Kolesov <Anton.Kolesov@synopsys.com>
18Signed-off-by: Shahab Vahedi <shahab@synopsys.com>
19Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
20---
21 gdb/arc-linux-tdep.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++
22 1 file changed, 181 insertions(+)
23
24diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
25index a7bace12623..17bb3e7b276 100644
26--- a/gdb/arc-linux-tdep.c
27+++ b/gdb/arc-linux-tdep.c
28@@ -33,6 +33,60 @@
29
30 #define REGOFF(offset) (offset * ARC_REGISTER_SIZE)
31
32+/* arc_linux_sc_reg_offsets[i] is the offset of register i in the `struct
33+ sigcontext'. Array index is an internal GDB register number, as defined in
34+ arc-tdep.h:arc_regnum.
35+
36+ From <include/uapi/asm/sigcontext.h> and <include/uapi/asm/ptrace.h>.
37+
38+ The layout of this struct is tightly bound to "arc_regnum" enum
39+ in arc-tdep.h. Any change of order in there, must be reflected
40+ here as well. */
41+static const int arc_linux_sc_reg_offsets[] = {
42+ /* R0 - R12. */
43+ REGOFF (22), REGOFF (21), REGOFF (20), REGOFF (19),
44+ REGOFF (18), REGOFF (17), REGOFF (16), REGOFF (15),
45+ REGOFF (14), REGOFF (13), REGOFF (12), REGOFF (11),
46+ REGOFF (10),
47+
48+ /* R13 - R25. */
49+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
50+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
51+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
52+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
53+ ARC_OFFSET_NO_REGISTER,
54+
55+ REGOFF (9), /* R26 (GP) */
56+ REGOFF (8), /* FP */
57+ REGOFF (23), /* SP */
58+ ARC_OFFSET_NO_REGISTER, /* ILINK */
59+ ARC_OFFSET_NO_REGISTER, /* R30 */
60+ REGOFF (7), /* BLINK */
61+
62+ /* R32 - R59. */
63+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
64+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
65+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
66+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
67+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
68+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
69+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
70+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
71+ ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
72+ ARC_OFFSET_NO_REGISTER,
73+
74+ REGOFF (4), /* LP_COUNT */
75+ ARC_OFFSET_NO_REGISTER, /* RESERVED */
76+ ARC_OFFSET_NO_REGISTER, /* LIMM */
77+ ARC_OFFSET_NO_REGISTER, /* PCL */
78+
79+ REGOFF (6), /* PC */
80+ REGOFF (5), /* STATUS32 */
81+ REGOFF (2), /* LP_START */
82+ REGOFF (3), /* LP_END */
83+ REGOFF (1), /* BTA */
84+};
85+
86 /* arc_linux_core_reg_offsets[i] is the offset in the .reg section of GDB
87 regnum i. Array index is an internal GDB register number, as defined in
88 arc-tdep.h:arc_regnum.
89@@ -87,6 +141,127 @@ static const int arc_linux_core_reg_offsets[] = {
90 REGOFF (6) /* ERET */
91 };
92
93+/* Is THIS_FRAME a sigtramp function - the function that returns from
94+ signal handler into normal execution flow? This is the case if the PC is
95+ either at the start of, or in the middle of the two instructions:
96+
97+ mov r8, __NR_rt_sigreturn ; __NR_rt_sigreturn == 139
98+ trap_s 0 ; `swi' for ARC700
99+
100+ On ARC uClibc Linux this function is called __default_rt_sa_restorer.
101+
102+ Returns TRUE if this is a sigtramp frame. */
103+
104+static bool
105+arc_linux_is_sigtramp (struct frame_info *this_frame)
106+{
107+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
108+ CORE_ADDR pc = get_frame_pc (this_frame);
109+
110+ if (arc_debug)
111+ {
112+ debug_printf ("arc-linux: arc_linux_is_sigtramp, pc=%s\n",
113+ paddress(gdbarch, pc));
114+ }
115+
116+ static const gdb_byte insns_be_hs[] = {
117+ 0x20, 0x8a, 0x12, 0xc2, /* mov r8,nr_rt_sigreturn */
118+ 0x78, 0x1e /* trap_s 0 */
119+ };
120+ static const gdb_byte insns_be_700[] = {
121+ 0x20, 0x8a, 0x12, 0xc2, /* mov r8,nr_rt_sigreturn */
122+ 0x22, 0x6f, 0x00, 0x3f /* swi */
123+ };
124+
125+ gdb_byte arc_sigtramp_insns[sizeof (insns_be_700)];
126+ size_t insns_sz;
127+ if (arc_mach_is_arcv2 (gdbarch))
128+ {
129+ insns_sz = sizeof (insns_be_hs);
130+ memcpy (arc_sigtramp_insns, insns_be_hs, insns_sz);
131+ }
132+ else
133+ {
134+ insns_sz = sizeof (insns_be_700);
135+ memcpy (arc_sigtramp_insns, insns_be_700, insns_sz);
136+ }
137+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
138+ {
139+ /* On little endian targets, ARC code section is in what is called
140+ "middle endian", where half-words are in the big-endian order,
141+ only bytes inside the halfwords are in the little endian order.
142+ As a result it is very easy to convert big endian instruction to
143+ little endian, since it is needed to swap bytes in the halfwords,
144+ so there is no need to have information on whether that is a
145+ 4-byte instruction or 2-byte. */
146+ gdb_assert ((insns_sz % 2) == 0);
147+ for (int i = 0; i < insns_sz; i += 2)
148+ std::swap (arc_sigtramp_insns[i], arc_sigtramp_insns[i+1]);
149+ }
150+
151+ gdb_byte buf[insns_sz];
152+
153+ /* Read the memory at the PC. Since we are stopped, any breakpoint must
154+ have been removed. */
155+ if (!safe_frame_unwind_memory (this_frame, pc, buf, insns_sz))
156+ {
157+ /* Failed to unwind frame. */
158+ return FALSE;
159+ }
160+
161+ /* Is that code the sigtramp instruction sequence? */
162+ if (memcmp (buf, arc_sigtramp_insns, insns_sz) == 0)
163+ return TRUE;
164+
165+ /* No - look one instruction earlier in the code... */
166+ if (!safe_frame_unwind_memory (this_frame, pc - 4, buf, insns_sz))
167+ {
168+ /* Failed to unwind frame. */
169+ return FALSE;
170+ }
171+
172+ return (memcmp (buf, arc_sigtramp_insns, insns_sz) == 0);
173+}
174+
175+/* Get sigcontext structure of sigtramp frame - it contains saved
176+ registers of interrupted frame.
177+
178+ Stack pointer points to the rt_sigframe structure, and sigcontext can
179+ be found as in:
180+
181+ struct rt_sigframe {
182+ struct siginfo info;
183+ struct ucontext uc;
184+ ...
185+ };
186+
187+ struct ucontext {
188+ unsigned long uc_flags;
189+ struct ucontext *uc_link;
190+ stack_t uc_stack;
191+ struct sigcontext uc_mcontext;
192+ sigset_t uc_sigmask;
193+ };
194+
195+ sizeof (struct siginfo) == 0x80
196+ offsetof (struct ucontext, uc_mcontext) == 0x14
197+
198+ GDB cannot include linux headers and use offsetof () because those are
199+ target headers and GDB might be built for a different run host. There
200+ doesn't seem to be an established mechanism to figure out those offsets
201+ via gdbserver, so the only way is to hardcode values in the GDB,
202+ meaning that GDB will be broken if values will change. That seems to
203+ be a very unlikely scenario and other arches (aarch64, alpha, amd64,
204+ etc) in GDB hardcode values. */
205+
206+static CORE_ADDR
207+arc_linux_sigcontext_addr (struct frame_info *this_frame)
208+{
209+ const int ucontext_offset = 0x80;
210+ const int sigcontext_offset = 0x14;
211+ return get_frame_sp (this_frame) + ucontext_offset + sigcontext_offset;
212+}
213+
214 /* Implement the "cannot_fetch_register" gdbarch method. */
215
216 static int
217@@ -504,6 +679,12 @@ arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
218 if (arc_debug)
219 debug_printf ("arc-linux: GNU/Linux OS/ABI initialization.\n");
220
221+ /* Fill in target-dependent info in ARC-private structure. */
222+ tdep->is_sigtramp = arc_linux_is_sigtramp;
223+ tdep->sigcontext_addr = arc_linux_sigcontext_addr;
224+ tdep->sc_reg_offset = arc_linux_sc_reg_offsets;
225+ tdep->sc_num_regs = ARRAY_SIZE (arc_linux_sc_reg_offsets);
226+
227 /* If we are using Linux, we have in uClibc
228 (libc/sysdeps/linux/arc/bits/setjmp.h):
229
230--
2312.16.2
232
diff --git a/meta/recipes-devtools/gdb/gdb/0014-arc-Take-into-account-the-REGNUM-in-supply-collect-g.patch b/meta/recipes-devtools/gdb/gdb/0014-arc-Take-into-account-the-REGNUM-in-supply-collect-g.patch
new file mode 100644
index 0000000000..a7256065cc
--- /dev/null
+++ b/meta/recipes-devtools/gdb/gdb/0014-arc-Take-into-account-the-REGNUM-in-supply-collect-g.patch
@@ -0,0 +1,104 @@
1From 5eb97d5e92ad23ee81cebc1ebd5eafe0aa55fc17 Mon Sep 17 00:00:00 2001
2From: Shahab Vahedi <shahab@synopsys.com>
3Date: Tue, 10 Nov 2020 19:34:57 +0100
4Subject: [PATCH 3/4] arc: Take into account the REGNUM in supply/collect gdb
5 hooks
6
7All the arc_linux_supply_*() target operations and the
8arc_linux_collect_v2_regset() in arc-linux-tdep.c were
9supplying/collecting all the registers in regcache as if the
10REGNUM was set to -1.
11
12The more efficient behavior is to examine the REGNUM and act
13accordingly. That is what this patch does.
14
15gdb/ChangeLog:
16
17 * arc-linux-tdep.c (supply_register): New.
18 (arc_linux_supply_gregset, arc_linux_supply_v2_regset,
19 arc_linux_collect_v2_regset): Consider REGNUM.
20
21Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=46023bbe81355230b4e7b76d3084337823d02362]
22
23Signed-off-by: Shahab Vahedi <shahab@synopsys.com>
24Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
25---
26 gdb/arc-linux-tdep.c | 41 ++++++++++++++++++++++++++++++++---------
27 1 file changed, 32 insertions(+), 9 deletions(-)
28
29diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
30index 17bb3e7b276..e83d82b6f5c 100644
31--- a/gdb/arc-linux-tdep.c
32+++ b/gdb/arc-linux-tdep.c
33@@ -535,6 +535,18 @@ arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
34 }
35 }
36
37+/* Populate REGCACHE with register REGNUM from BUF. */
38+
39+static void
40+supply_register (struct regcache *regcache, int regnum, const gdb_byte *buf)
41+{
42+ /* Skip non-existing registers. */
43+ if ((arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER))
44+ return;
45+
46+ regcache->raw_supply (regnum, buf + arc_linux_core_reg_offsets[regnum]);
47+}
48+
49 void
50 arc_linux_supply_gregset (const struct regset *regset,
51 struct regcache *regcache,
52@@ -545,9 +557,14 @@ arc_linux_supply_gregset (const struct regset *regset,
53
54 const bfd_byte *buf = (const bfd_byte *) gregs;
55
56- for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
57- if (arc_linux_core_reg_offsets[reg] != ARC_OFFSET_NO_REGISTER)
58- regcache->raw_supply (reg, buf + arc_linux_core_reg_offsets[reg]);
59+ /* regnum == -1 means writing all the registers. */
60+ if (regnum == -1)
61+ for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
62+ supply_register (regcache, reg, buf);
63+ else if (regnum <= ARC_LAST_REGNUM)
64+ supply_register (regcache, regnum, buf);
65+ else
66+ gdb_assert_not_reached ("Invalid regnum in arc_linux_supply_gregset.");
67 }
68
69 void
70@@ -558,9 +575,12 @@ arc_linux_supply_v2_regset (const struct regset *regset,
71 const bfd_byte *buf = (const bfd_byte *) v2_regs;
72
73 /* user_regs_arcv2 is defined in linux arch/arc/include/uapi/asm/ptrace.h. */
74- regcache->raw_supply (ARC_R30_REGNUM, buf);
75- regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
76- regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
77+ if (regnum == -1 || regnum == ARC_R30_REGNUM)
78+ regcache->raw_supply (ARC_R30_REGNUM, buf);
79+ if (regnum == -1 || regnum == ARC_R58_REGNUM)
80+ regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
81+ if (regnum == -1 || regnum == ARC_R59_REGNUM)
82+ regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
83 }
84
85 /* Populate BUF with register REGNUM from the REGCACHE. */
86@@ -618,9 +638,12 @@ arc_linux_collect_v2_regset (const struct regset *regset,
87 {
88 bfd_byte *buf = (bfd_byte *) v2_regs;
89
90- regcache->raw_collect (ARC_R30_REGNUM, buf);
91- regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
92- regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
93+ if (regnum == -1 || regnum == ARC_R30_REGNUM)
94+ regcache->raw_collect (ARC_R30_REGNUM, buf);
95+ if (regnum == -1 || regnum == ARC_R58_REGNUM)
96+ regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
97+ if (regnum == -1 || regnum == ARC_R59_REGNUM)
98+ regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
99 }
100
101 /* Linux regset definitions. */
102--
1032.16.2
104
diff --git a/meta/recipes-devtools/gdb/gdb/0015-gdb-Add-native-support-for-ARC-in-GNU-Linux.patch b/meta/recipes-devtools/gdb/gdb/0015-gdb-Add-native-support-for-ARC-in-GNU-Linux.patch
new file mode 100644
index 0000000000..31cf0b0be2
--- /dev/null
+++ b/meta/recipes-devtools/gdb/gdb/0015-gdb-Add-native-support-for-ARC-in-GNU-Linux.patch
@@ -0,0 +1,414 @@
1From 32b366249fd42d74cbc4a91039431554ebadcfd0 Mon Sep 17 00:00:00 2001
2From: Anton Kolesov <anton.kolesov@synopsys.com>
3Date: Fri, 14 Feb 2014 11:56:23 +0400
4Subject: [PATCH 4/4] gdb: Add native support for ARC in GNU/Linux
5
6With this patch in place it is possible to build a GDB that
7can run on ARC (GNU/Linux) hosts for debugging ARC targets.
8
9The "arc-linux-nat.c" is a rather small one that mostly deals
10with registers and a few thread related hooks.
11
12v2 [1]:
13- Remove "void" from the input of "_initialize_arc_linux_nat ()"
14
15[1] Tom's remark after the first patch
16https://sourceware.org/pipermail/gdb-patches/2020-November/173223.html
17
18gdb/ChangeLog:
19
20 * Makefile.in (ALLDEPFILES): Add arc-linux-nat.c.
21 * configure.host (host to gdb names): Add arc*-*-linux*.
22 * configure.nat (gdb_host_cpu): Add arc.
23 * arc-linux-nat.c: New.
24
25Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=04c9f85efcd8df5fc482ce97c0104cc7dd5d19e6]
26
27Signed-off-by: Anton Kolesov <Anton.Kolesov@synopsys.com>
28Signed-off-by: Shahab Vahedi <shahab@synopsys.com>
29Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
30---
31 gdb/Makefile.in | 1 +
32 gdb/arc-linux-nat.c | 320 ++++++++++++++++++++++++++++++++++++++++++++++++++++
33 gdb/configure.host | 3 +
34 gdb/configure.nat | 4 +
35 4 files changed, 328 insertions(+)
36 create mode 100644 gdb/arc-linux-nat.c
37
38diff --git a/gdb/Makefile.in b/gdb/Makefile.in
39index ec371fc7e52..c76136907ae 100644
40--- a/gdb/Makefile.in
41+++ b/gdb/Makefile.in
42@@ -2136,6 +2136,7 @@ ALLDEPFILES = \
43 amd64-obsd-tdep.c \
44 amd64-sol2-tdep.c \
45 amd64-tdep.c \
46+ arc-linux-nat.c \
47 arc-tdep.c \
48 arm.c \
49 arm-bsd-tdep.c \
50diff --git a/gdb/arc-linux-nat.c b/gdb/arc-linux-nat.c
51new file mode 100644
52index 00000000000..41301fd4fed
53--- /dev/null
54+++ b/gdb/arc-linux-nat.c
55@@ -0,0 +1,320 @@
56+/* Native-dependent code for GNU/Linux ARC.
57+
58+ Copyright 2020 Free Software Foundation, Inc.
59+
60+ This file is part of GDB.
61+
62+ This program is free software; you can redistribute it and/or modify
63+ it under the terms of the GNU General Public License as published by
64+ the Free Software Foundation; either version 3 of the License, or
65+ (at your option) any later version.
66+
67+ This program is distributed in the hope that it will be useful,
68+ but WITHOUT ANY WARRANTY; without even the implied warranty of
69+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70+ GNU General Public License for more details.
71+
72+ You should have received a copy of the GNU General Public License
73+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
74+
75+#include "defs.h"
76+#include "frame.h"
77+#include "inferior.h"
78+#include "gdbcore.h"
79+#include "regcache.h"
80+#include "gdbsupport/gdb_assert.h"
81+#include "target.h"
82+#include "linux-nat.h"
83+#include "nat/gdb_ptrace.h"
84+
85+#include <stdint.h>
86+#include <sys/types.h>
87+#include <sys/param.h>
88+#include <signal.h>
89+#include <sys/user.h>
90+#include <sys/ioctl.h>
91+#include "gdbsupport/gdb_wait.h"
92+#include <fcntl.h>
93+#include <sys/procfs.h>
94+#include <linux/elf.h>
95+
96+#include "gregset.h"
97+#include "arc-tdep.h"
98+#include "arc-linux-tdep.h"
99+#include "arch/arc.h"
100+
101+/* Defines ps_err_e, struct ps_prochandle. */
102+#include "gdb_proc_service.h"
103+
104+/* Linux starting with 4.12 supports NT_ARC_V2 note type, which adds R30,
105+ R58 and R59 registers, which are specific to ARC HS and aren't
106+ available in ARC 700. */
107+#if defined (NT_ARC_V2) && defined (__ARCHS__)
108+#define ARC_HAS_V2_REGSET
109+#endif
110+
111+class arc_linux_nat_target final : public linux_nat_target
112+{
113+public:
114+ /* Add ARC register access methods. */
115+ void fetch_registers (struct regcache *, int) override;
116+ void store_registers (struct regcache *, int) override;
117+
118+ const struct target_desc *read_description () override;
119+
120+ /* Handle threads */
121+ void low_prepare_to_resume (struct lwp_info *lp) override;
122+};
123+
124+static arc_linux_nat_target the_arc_linux_nat_target;
125+
126+/* Read general registers from target process/thread (via ptrace)
127+ into REGCACHE. */
128+
129+static void
130+fetch_gregs (struct regcache *regcache, int regnum)
131+{
132+ const int tid = get_ptrace_pid (regcache->ptid ());
133+ struct iovec iov;
134+ gdb_gregset_t regs;
135+
136+ iov.iov_base = &regs;
137+ iov.iov_len = sizeof (gdb_gregset_t);
138+
139+ if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
140+ perror_with_name (_("Couldn't get general registers"));
141+ else
142+ arc_linux_supply_gregset (NULL, regcache, regnum, &regs, 0);
143+}
144+
145+#ifdef ARC_HAS_V2_REGSET
146+/* Read ARC v2 registers from target process/thread (via ptrace)
147+ into REGCACHE. */
148+
149+static void
150+fetch_v2_regs (struct regcache *regcache, int regnum)
151+{
152+ const int tid = get_ptrace_pid (regcache->ptid ());
153+ struct iovec iov;
154+ bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
155+
156+ iov.iov_base = &v2_buffer;
157+ iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
158+
159+ if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
160+ perror_with_name (_("Couldn't get ARC HS registers"));
161+ else
162+ arc_linux_supply_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
163+}
164+#endif
165+
166+/* Store general registers from REGCACHE into the target process/thread. */
167+
168+static void
169+store_gregs (const struct regcache *regcache, int regnum)
170+{
171+ const int tid = get_ptrace_pid (regcache->ptid ());
172+ struct iovec iov;
173+ gdb_gregset_t regs;
174+
175+ iov.iov_base = &regs;
176+ iov.iov_len = sizeof (gdb_gregset_t);
177+
178+ if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
179+ perror_with_name (_("Couldn't get general registers"));
180+ else
181+ {
182+ arc_linux_collect_gregset (NULL, regcache, regnum, regs, 0);
183+
184+ if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
185+ perror_with_name (_("Couldn't write general registers"));
186+ }
187+}
188+
189+#ifdef ARC_HAS_V2_REGSET
190+/* Store ARC v2 registers from REGCACHE into the target process/thread. */
191+
192+static void
193+store_v2_regs (const struct regcache *regcache, int regnum)
194+{
195+ const int tid = get_ptrace_pid (regcache->ptid ());
196+ struct iovec iov;
197+ bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
198+
199+ iov.iov_base = &v2_buffer;
200+ iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
201+
202+ if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
203+ perror_with_name (_("Couldn't get ARC HS registers"));
204+ else
205+ {
206+ arc_linux_collect_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
207+
208+ if (ptrace (PTRACE_SETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
209+ perror_with_name (_("Couldn't write ARC HS registers"));
210+ }
211+}
212+#endif
213+
214+/* Target operation: Read REGNUM register (all registers if REGNUM == -1)
215+ from target process into REGCACHE. */
216+
217+void
218+arc_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
219+{
220+
221+ if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
222+ fetch_gregs (regcache, regnum);
223+
224+#ifdef ARC_HAS_V2_REGSET
225+ if (regnum == -1
226+ || regnum == ARC_R30_REGNUM
227+ || regnum == ARC_R58_REGNUM
228+ || regnum == ARC_R59_REGNUM)
229+ fetch_v2_regs (regcache, regnum);
230+#endif
231+}
232+
233+/* Target operation: Store REGNUM register (all registers if REGNUM == -1)
234+ to the target process from REGCACHE. */
235+
236+void
237+arc_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
238+{
239+ if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
240+ store_gregs (regcache, regnum);
241+
242+#ifdef ARC_HAS_V2_REGSET
243+ if (regnum == -1
244+ || regnum == ARC_R30_REGNUM
245+ || regnum == ARC_R58_REGNUM
246+ || regnum == ARC_R59_REGNUM)
247+ store_v2_regs (regcache, regnum);
248+#endif
249+}
250+
251+/* Copy general purpose register(s) from REGCACHE into regset GREGS.
252+ This function is exported to proc-service.c */
253+
254+void
255+fill_gregset (const struct regcache *regcache,
256+ gdb_gregset_t *gregs, int regnum)
257+{
258+ arc_linux_collect_gregset (NULL, regcache, regnum, gregs, 0);
259+}
260+
261+/* Copy all the general purpose registers from regset GREGS into REGCACHE.
262+ This function is exported to proc-service.c. */
263+
264+void
265+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
266+{
267+ arc_linux_supply_gregset (NULL, regcache, -1, gregs, 0);
268+}
269+
270+/* ARC doesn't have separate FP registers. This function is exported
271+ to proc-service.c. */
272+
273+void
274+fill_fpregset (const struct regcache *regcache,
275+ gdb_fpregset_t *fpregsetp, int regnum)
276+{
277+ if (arc_debug)
278+ debug_printf ("arc-linux-nat: fill_fpregset called.");
279+ return;
280+}
281+
282+/* ARC doesn't have separate FP registers. This function is exported
283+ to proc-service.c. */
284+
285+void
286+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
287+{
288+ if (arc_debug)
289+ debug_printf ("arc-linux-nat: supply_fpregset called.");
290+ return;
291+}
292+
293+/* Implement the "read_description" method of linux_nat_target. */
294+
295+const struct target_desc *
296+arc_linux_nat_target::read_description ()
297+{
298+ /* This is a native target, hence description is hardcoded. */
299+#ifdef __ARCHS__
300+ arc_arch_features features (4, ARC_ISA_ARCV2);
301+#else
302+ arc_arch_features features (4, ARC_ISA_ARCV1);
303+#endif
304+ return arc_lookup_target_description (features);
305+}
306+
307+/* As described in arc_linux_collect_gregset(), we need to write resume-PC
308+ to ERET. However by default GDB for native targets doesn't write
309+ registers if they haven't been changed. This is a callback called by
310+ generic GDB, and in this callback we have to rewrite PC value so it
311+ would force rewrite of register on target. It seems that the only
312+ other arch that utilizes this hook is x86/x86-64 for HW breakpoint
313+ support. But then, AFAIK no other arch has this stop_pc/eret
314+ complexity.
315+
316+ No better way was found, other than this fake write of register value,
317+ to force GDB into writing register to target. Is there any? */
318+
319+void
320+arc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
321+{
322+ /* When new processes and threads are created we do not have the address
323+ space for them and calling get_thread_regcache will cause an internal
324+ error in GDB. It looks like that checking for last_resume_kind is the
325+ sensible way to determine processes for which we cannot get regcache.
326+ Ultimately, a better way would be removing the need for
327+ low_prepare_to_resume in the first place. */
328+ if (lwp->last_resume_kind == resume_stop)
329+ return;
330+
331+ struct regcache *regcache = get_thread_regcache (this, lwp->ptid);
332+ struct gdbarch *gdbarch = regcache->arch ();
333+
334+ /* Read current PC value, then write it back. It is required to call
335+ invalidate(), otherwise GDB will note that new value is equal to old
336+ value and will skip write. */
337+ ULONGEST new_pc;
338+ regcache_cooked_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
339+ &new_pc);
340+ regcache->invalidate (gdbarch_pc_regnum (gdbarch));
341+ regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
342+ new_pc);
343+}
344+
345+/* Fetch the thread-local storage pointer for libthread_db. Note that
346+ this function is not called from GDB, but is called from libthread_db.
347+ This is required to debug multithreaded applications with NPTL. */
348+
349+ps_err_e
350+ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx,
351+ void **base)
352+{
353+ if (arc_debug >= 2)
354+ debug_printf ("arc-linux-nat: ps_get_thread_area called");
355+
356+ if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
357+ return PS_ERR;
358+
359+ /* IDX is the bias from the thread pointer to the beginning of the
360+ thread descriptor. It has to be subtracted due to implementation
361+ quirks in libthread_db. */
362+ *base = (void *) ((char *) *base - idx);
363+
364+ return PS_OK;
365+}
366+
367+/* Suppress warning from -Wmissing-prototypes. */
368+void _initialize_arc_linux_nat ();
369+void
370+_initialize_arc_linux_nat ()
371+{
372+ /* Register the target. */
373+ linux_target = &the_arc_linux_nat_target;
374+ add_inf_child_target (&the_arc_linux_nat_target);
375+}
376diff --git a/gdb/configure.host b/gdb/configure.host
377index ce528237291..e94a19b0332 100644
378--- a/gdb/configure.host
379+++ b/gdb/configure.host
380@@ -60,6 +60,7 @@ case "${host_cpu}" in
381
382 aarch64*) gdb_host_cpu=aarch64 ;;
383 alpha*) gdb_host_cpu=alpha ;;
384+arc*) gdb_host_cpu=arc ;;
385 arm*) gdb_host_cpu=arm ;;
386 hppa*) gdb_host_cpu=pa ;;
387 i[34567]86*) gdb_host_cpu=i386 ;;
388@@ -91,6 +92,8 @@ alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu)
389 gdb_host=nbsd ;;
390 alpha*-*-openbsd*) gdb_host=nbsd ;;
391
392+arc*-*-linux*) gdb_host=linux ;;
393+
394 arm*-*-freebsd*) gdb_host=fbsd ;;
395 arm*-*-linux*) gdb_host=linux ;;
396 arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu)
397diff --git a/gdb/configure.nat b/gdb/configure.nat
398index bb70e303384..cd11bc86dca 100644
399--- a/gdb/configure.nat
400+++ b/gdb/configure.nat
401@@ -238,6 +238,10 @@ case ${gdb_host} in
402 nat/aarch64-linux.o \
403 nat/aarch64-sve-linux-ptrace.o"
404 ;;
405+ arc)
406+ # Host: ARC based machine running GNU/Linux
407+ NATDEPFILES="${NATDEPFILES} arc-linux-nat.o"
408+ ;;
409 arm)
410 # Host: ARM based machine running GNU/Linux
411 NATDEPFILES="${NATDEPFILES} arm-linux-nat.o \
412--
4132.16.2
414