blob: 6a98b65766f76aa4abd59c18aeb0b4a4afea3394 [file] [log] [blame]
Andrew Geissler09036742021-06-25 14:25:14 -05001From 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