summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch')
-rw-r--r--meta/recipes-devtools/gdb/gdb/0012-arc-Add-support-for-signal-handlers.patch218
1 files changed, 218 insertions, 0 deletions
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 @@
+From bfee93403b46ae4f050282b7721ba39073905c69 Mon Sep 17 00:00:00 2001
+From: Anton Kolesov <Anton.Kolesov@synopsys.com>
+Date: Mon, 22 Aug 2016 19:39:46 +0300
+Subject: [PATCH 1/4] arc: Add support for signal handlers
+
+This patch adds the necessary infrastructure to handle signal frames for
+ARC architecture. It is fairly similar to what any other architecture
+would have. Linux specific parts will be in a separate patch.
+
+v2 [1]:
+- Make the logic of "arc_sigtramp_frame_sniffer ()" simpler.
+
+[1] Tom's remark for the first version
+https://sourceware.org/pipermail/gdb-patches/2020-November/173221.html
+
+gdb/ChangeLog:
+
+ * arc-tdep.c (arc_make_sigtramp_frame_cache): New function.
+ (arc_sigtramp_frame_this_id): Likewise.
+ (arc_sigtramp_frame_prev_register): Likewise.
+ (arc_sigtramp_frame_sniffer): Likewise.
+ (arc_siftramp_frame_unwind): New global variable.
+ (arc_gdbarch_init): Use sigtramp capabilities.
+ (arc_dump_tdep): Print sigtramp fields.
+ * arc-tdep.h (gdbarch_tdep): Add sigtramp fields.
+
+Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=b4e3cd0440109d0a5552d3313ccbd35c8103335b]
+
+Signed-off-by: Anton Kolesov <Anton.Kolesov@synopsys.com>
+Signed-off-by: Shahab Vahedi <shahab@synopsys.com>
+Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
+---
+ gdb/arc-tdep.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ gdb/arc-tdep.h | 13 ++++++
+ 2 files changed, 136 insertions(+)
+
+diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
+index 93e2fd88a9a..3356252525d 100644
+--- a/gdb/arc-tdep.c
++++ b/gdb/arc-tdep.c
+@@ -1843,6 +1843,104 @@ arc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ reg->how = DWARF2_FRAME_REG_CFA;
+ }
+
++/* Signal trampoline frame unwinder. Allows frame unwinding to happen
++ from within signal handlers. */
++
++static struct arc_frame_cache *
++arc_make_sigtramp_frame_cache (struct frame_info *this_frame)
++{
++ if (arc_debug)
++ debug_printf ("arc: sigtramp_frame_cache\n");
++
++ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
++
++ /* Allocate new frame cache instance and space for saved register info. */
++ struct arc_frame_cache *cache = FRAME_OBSTACK_ZALLOC (struct arc_frame_cache);
++ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
++
++ /* Get the stack pointer and use it as the frame base. */
++ cache->prev_sp = arc_frame_base_address (this_frame, NULL);
++
++ /* If the ARC-private target-dependent info doesn't have a table of
++ offsets of saved register contents within an OS signal context
++ structure, then there is nothing to analyze. */
++ if (tdep->sc_reg_offset == NULL)
++ return cache;
++
++ /* Find the address of the sigcontext structure. */
++ CORE_ADDR addr = tdep->sigcontext_addr (this_frame);
++
++ /* For each register, if its contents have been saved within the
++ sigcontext structure, determine the address of those contents. */
++ gdb_assert (tdep->sc_num_regs <= (ARC_LAST_REGNUM + 1));
++ for (int i = 0; i < tdep->sc_num_regs; i++)
++ {
++ if (tdep->sc_reg_offset[i] != ARC_OFFSET_NO_REGISTER)
++ cache->saved_regs[i].addr = addr + tdep->sc_reg_offset[i];
++ }
++
++ return cache;
++}
++
++/* Implement the "this_id" frame_unwind method for signal trampoline
++ frames. */
++
++static void
++arc_sigtramp_frame_this_id (struct frame_info *this_frame,
++ void **this_cache, struct frame_id *this_id)
++{
++ if (arc_debug)
++ debug_printf ("arc: sigtramp_frame_this_id\n");
++
++ if (*this_cache == NULL)
++ *this_cache = arc_make_sigtramp_frame_cache (this_frame);
++
++ struct gdbarch *gdbarch = get_frame_arch (this_frame);
++ struct arc_frame_cache *cache = (struct arc_frame_cache *) *this_cache;
++ CORE_ADDR stack_addr = cache->prev_sp;
++ CORE_ADDR code_addr
++ = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
++ *this_id = frame_id_build (stack_addr, code_addr);
++}
++
++/* Get a register from a signal handler frame. */
++
++static struct value *
++arc_sigtramp_frame_prev_register (struct frame_info *this_frame,
++ void **this_cache, int regnum)
++{
++ if (arc_debug)
++ debug_printf ("arc: sigtramp_frame_prev_register (regnum = %d)\n", regnum);
++
++ /* Make sure we've initialized the cache. */
++ if (*this_cache == NULL)
++ *this_cache = arc_make_sigtramp_frame_cache (this_frame);
++
++ struct arc_frame_cache *cache = (struct arc_frame_cache *) *this_cache;
++ return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
++}
++
++/* Frame sniffer for signal handler frame. Only recognize a frame if we
++ have a sigcontext_addr handler in the target dependency. */
++
++static int
++arc_sigtramp_frame_sniffer (const struct frame_unwind *self,
++ struct frame_info *this_frame,
++ void **this_cache)
++{
++ struct gdbarch_tdep *tdep;
++
++ if (arc_debug)
++ debug_printf ("arc: sigtramp_frame_sniffer\n");
++
++ tdep = gdbarch_tdep (get_frame_arch (this_frame));
++
++ /* If we have a sigcontext_addr handler, then just return 1 (same as the
++ "default_frame_sniffer ()"). */
++ return (tdep->sigcontext_addr != NULL && tdep->is_sigtramp != NULL
++ && tdep->is_sigtramp (this_frame));
++}
++
+ /* Structure defining the ARC ordinary frame unwind functions. Since we are
+ the fallback unwinder, we use the default frame sniffer, which always
+ accepts the frame. */
+@@ -1858,6 +1956,21 @@ static const struct frame_unwind arc_frame_unwind = {
+ NULL
+ };
+
++/* Structure defining the ARC signal frame unwind functions. Custom
++ sniffer is used, because this frame must be accepted only in the right
++ context. */
++
++static const struct frame_unwind arc_sigtramp_frame_unwind = {
++ SIGTRAMP_FRAME,
++ default_frame_unwind_stop_reason,
++ arc_sigtramp_frame_this_id,
++ arc_sigtramp_frame_prev_register,
++ NULL,
++ arc_sigtramp_frame_sniffer,
++ NULL,
++ NULL
++};
++
+
+ static const struct frame_base arc_normal_base = {
+ &arc_frame_unwind,
+@@ -2272,6 +2385,7 @@ arc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ /* Frame unwinders and sniffers. */
+ dwarf2_frame_set_init_reg (gdbarch, arc_dwarf2_frame_init_reg);
+ dwarf2_append_unwinders (gdbarch);
++ frame_unwind_append_unwinder (gdbarch, &arc_sigtramp_frame_unwind);
+ frame_unwind_append_unwinder (gdbarch, &arc_frame_unwind);
+ frame_base_set_default (gdbarch, &arc_normal_base);
+
+@@ -2350,6 +2464,15 @@ arc_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ fprintf_unfiltered (file, "arc_dump_tdep: jb_pc = %i\n", tdep->jb_pc);
++
++ fprintf_unfiltered (file, "arc_dump_tdep: is_sigtramp = <%s>\n",
++ host_address_to_string (tdep->is_sigtramp));
++ fprintf_unfiltered (file, "arc_dump_tdep: sigcontext_addr = <%s>\n",
++ host_address_to_string (tdep->sigcontext_addr));
++ fprintf_unfiltered (file, "arc_dump_tdep: sc_reg_offset = <%s>\n",
++ host_address_to_string (tdep->sc_reg_offset));
++ fprintf_unfiltered (file, "arc_dump_tdep: sc_num_regs = %d\n",
++ tdep->sc_num_regs);
+ }
+
+ /* This command accepts single argument - address of instruction to
+diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
+index 50b14905134..70fc3d95c48 100644
+--- a/gdb/arc-tdep.h
++++ b/gdb/arc-tdep.h
+@@ -124,6 +124,19 @@ struct gdbarch_tdep
+
+ /* Whether target has hardware (aka zero-delay) loops. */
+ bool has_hw_loops;
++
++ /* Detect sigtramp. */
++ bool (*is_sigtramp) (struct frame_info *);
++
++ /* Get address of sigcontext for sigtramp. */
++ CORE_ADDR (*sigcontext_addr) (struct frame_info *);
++
++ /* Offset of registers in `struct sigcontext'. */
++ const int *sc_reg_offset;
++
++ /* Number of registers in sc_reg_offsets. Most likely a ARC_LAST_REGNUM,
++ but in theory it could be less, so it is kept separate. */
++ int sc_num_regs;
+ };
+
+ /* Utility functions used by other ARC-specific modules. */
+--
+2.16.2
+