[patch/rfc] frame_unwind_register_unwinder -> frame_unwind_prepend_unwinder

Andrew Cagney
2004-04-03T19:33:33Z

[-- Attachment #1: Type: text/plain, Size: 903 bytes --]

Hello,

At present unwind sniffers are appeneded to the search list.
Consequently to ensure that the more specific OSABI unwinders override
the more generic architecture unwinders, the architecture code has to
append the sniffers in reverse order.

This is contrary to how the rest of the architecture vector is
constructed - for other architecture entries, the OSABI does its
initialization last, overriding earlier more generic architecture entries.

The attached replaces the recently added, and hardly called,
rame_unwind_register_unwinder (which does an append) with
frame_unwind_prepend_unwinder (which does a prepend).

By using this new method, OSABI code can ensure that their methods are
always at the front of the unwind sniffer search list, and hence ensure
that their methods always override the more generic architecture methods.

Comments? I'll leave this for a few days.
Andrew

[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 7804 bytes --]

2004-04-03 Andrew Cagney <cagney@redhat.com>

* frame-unwind.c (struct frame_unwind_table, frame_unwind_init)
(frame_unwind_prepend_unwinder, frame_unwind_append_sniffer)
(frame_unwind_find_by_frame): Re-implement the unwind sniffer so
that it can both prepend and append sniffers. Replace
frame_unwind_register_unwinder.
* tramp-frame.c (tramp_frame_append): Use
frame_unwind_prepend_unwinder.
* frame-unwind.h (frame_unwind_prepend_unwinder): Replace
frame_unwind_register_unwinder.
* tramp-frame.h (tramp_frame_prepend_unwinder): Rename
tramp_frame_append.
* tramp-frame.c (tramp_frame_prepend_unwinder): Update.
* mips-linux-tdep.c (mips_linux_init_abi, mips_linux_init_abi)
(mips_linux_init_abi): Update.

Index: frame-unwind.c
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.c,v
retrieving revision 1.11
diff -u -r1.11 frame-unwind.c
--- frame-unwind.c 21 Mar 2004 22:28:52 -0000 1.11
+++ frame-unwind.c 3 Apr 2004 19:23:38 -0000
@@ -37,8 +37,9 @@

struct frame_unwind_table
{
- struct frame_unwind_table_entry *head;
- struct frame_unwind_table_entry **tail;
+ struct frame_unwind_table_entry *list;
+ /* The head of the OSABI part of the search list. */
+ struct frame_unwind_table_entry **osabi_head;
};

static void *
@@ -46,9 +47,12 @@
{
struct frame_unwind_table *table
= OBSTACK_ZALLOC (obstack, struct frame_unwind_table);
- table->head = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
- table->head->sniffer = dummy_frame_sniffer;
- table->tail = &table->head->next;
+ /* Start the table out with a few default sniffers. OSABI code
+ can't override this. */
+ table->list = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry);
+ table->list->sniffer = dummy_frame_sniffer;
+ /* The insertion point for OSABI sniffers. */
+ table->osabi_head = &table->list->next;
return table;
}

@@ -57,20 +61,26 @@
frame_unwind_sniffer_ftype *sniffer)
{
struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
- (*table->tail) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
- (*table->tail)->sniffer = sniffer;
- table->tail = &((*table->tail)->next);
+ struct frame_unwind_table_entry **ip;
+
+ /* Find the end of the list and insert the new entry there. */
+ for (ip = table->osabi_head; (*ip) != NULL; ip = &(*ip)->next);
+ (*ip) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
+ (*ip)->sniffer = sniffer;
}

void
-frame_unwind_register_unwinder (struct gdbarch *gdbarch,
+frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
const struct frame_unwind *unwinder)
{
struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data);
- (*table->tail) = GDBARCH_OBSTACK_ZALLOC (gdbarch,
- struct frame_unwind_table_entry);
- (*table->tail)->unwinder = unwinder;
- table->tail = &((*table->tail)->next);
+ struct frame_unwind_table_entry *entry;
+
+ /* Insert the new entry at the start of the list. */
+ entry = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry);
+ entry->unwinder = unwinder;
+ entry->next = (*table->osabi_head);
+ (*table->osabi_head) = entry;
}

const struct frame_unwind *
@@ -86,7 +96,7 @@
the dummy frame mechanism. All architectures should be using
generic dummy frames). */
return legacy_saved_regs_unwind;
- for (entry = table->head; entry != NULL; entry = entry->next)
+ for (entry = table->list; entry != NULL; entry = entry->next)
{
if (entry->sniffer != NULL)
{
Index: frame-unwind.h
===================================================================
RCS file: /cvs/src/src/gdb/frame-unwind.h,v
retrieving revision 1.10
diff -u -r1.10 frame-unwind.h
--- frame-unwind.h 21 Mar 2004 22:28:52 -0000 1.10
+++ frame-unwind.h 3 Apr 2004 19:23:38 -0000
@@ -131,11 +131,14 @@
frame_sniffer_ftype *sniffer;
};

-/* Register a frame unwinder, _appending_ it to the end of the search
- list. */
-extern void frame_unwind_register_unwinder (struct gdbarch *gdbarch,
- const struct frame_unwind *unwinder);
-
+/* Register a frame unwinder, _prepending_ it to the front of the
+ search list (so it is sniffed before previously registered
+ unwinders). By using a prepend, later calls can install unwinders
+ that override earlier calls. This allows, for instance, an OSABI
+ to install a a more specific sigtramp unwinder that overrides the
+ traditional brute-force unwinder. */
+extern void frame_unwind_prepend_unwinder (struct gdbarch *gdbarch,
+ const struct frame_unwind *unwinder);

/* Given the NEXT frame, take a wiff of THIS frame's registers (namely
the PC and attributes) and if it is the applicable unwinder return
Index: mips-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.21
diff -u -r1.21 mips-linux-tdep.c
--- mips-linux-tdep.c 25 Mar 2004 01:27:26 -0000 1.21
+++ mips-linux-tdep.c 3 Apr 2004 19:23:40 -0000
@@ -1119,8 +1119,8 @@
set_solib_svr4_fetch_link_map_offsets
(gdbarch, mips_linux_svr4_fetch_link_map_offsets);
set_mips_linux_register_addr (gdbarch, mips_linux_register_addr);
- tramp_frame_append (gdbarch, &mips_linux_o32_sigframe);
- tramp_frame_append (gdbarch, &mips_linux_o32_rt_sigframe);
+ tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe);
+ tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe);
break;
case MIPS_ABI_N32:
set_gdbarch_get_longjmp_target (gdbarch,
@@ -1128,7 +1128,7 @@
set_solib_svr4_fetch_link_map_offsets
(gdbarch, mips_linux_svr4_fetch_link_map_offsets);
set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
- tramp_frame_append (gdbarch, &mips_linux_n32_rt_sigframe);
+ tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
break;
case MIPS_ABI_N64:
set_gdbarch_get_longjmp_target (gdbarch,
@@ -1136,7 +1136,7 @@
set_solib_svr4_fetch_link_map_offsets
(gdbarch, mips64_linux_svr4_fetch_link_map_offsets);
set_mips_linux_register_addr (gdbarch, mips64_linux_register_addr);
- tramp_frame_append (gdbarch, &mips_linux_n64_rt_sigframe);
+ tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
break;
default:
internal_error (__FILE__, __LINE__, "can't handle ABI");
Index: tramp-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/tramp-frame.c,v
retrieving revision 1.4
diff -u -r1.4 tramp-frame.c
--- tramp-frame.c 2 Apr 2004 19:44:25 -0000 1.4
+++ tramp-frame.c 3 Apr 2004 19:23:40 -0000
@@ -146,8 +146,8 @@
}

void
-tramp_frame_append (struct gdbarch *gdbarch,
- const struct tramp_frame *tramp_frame)
+tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
+ const struct tramp_frame *tramp_frame)
{
struct frame_data *data;
struct frame_unwind *unwinder;
@@ -171,5 +171,5 @@
unwinder->sniffer = tramp_frame_sniffer;
unwinder->this_id = tramp_frame_this_id;
unwinder->prev_register = tramp_frame_prev_register;
- frame_unwind_register_unwinder (gdbarch, unwinder);
+ frame_unwind_prepend_unwinder (gdbarch, unwinder);
}
Index: tramp-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/tramp-frame.h,v
retrieving revision 1.3
diff -u -r1.3 tramp-frame.h
--- tramp-frame.h 24 Mar 2004 23:14:39 -0000 1.3
+++ tramp-frame.h 3 Apr 2004 19:23:40 -0000
@@ -63,7 +63,7 @@
CORE_ADDR func);
};

-void tramp_frame_append (struct gdbarch *gdbarch,
- const struct tramp_frame *tramp);
+void tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
+ const struct tramp_frame *tramp);

#endif