1/* Definitions for frame unwinder, for GDB, the GNU debugger. 2 3 Copyright 2003, 2004 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22#include "defs.h" 23#include "frame.h" 24#include "frame-unwind.h" 25#include "gdb_assert.h" 26#include "dummy-frame.h" 27#include "gdb_obstack.h" 28 29static struct gdbarch_data *frame_unwind_data; 30 31struct frame_unwind_table_entry 32{ 33 frame_unwind_sniffer_ftype *sniffer; 34 const struct frame_unwind *unwinder; 35 struct frame_unwind_table_entry *next; 36}; 37 38struct frame_unwind_table 39{ 40 struct frame_unwind_table_entry *list; 41 /* The head of the OSABI part of the search list. */ 42 struct frame_unwind_table_entry **osabi_head; 43}; 44 45static void * 46frame_unwind_init (struct obstack *obstack) 47{ 48 struct frame_unwind_table *table 49 = OBSTACK_ZALLOC (obstack, struct frame_unwind_table); 50 /* Start the table out with a few default sniffers. OSABI code 51 can't override this. */ 52 table->list = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry); 53 table->list->unwinder = dummy_frame_unwind; 54 /* The insertion point for OSABI sniffers. */ 55 table->osabi_head = &table->list->next; 56 return table; 57} 58 59void 60frame_unwind_append_sniffer (struct gdbarch *gdbarch, 61 frame_unwind_sniffer_ftype *sniffer) 62{ 63 struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); 64 struct frame_unwind_table_entry **ip; 65 66 /* Find the end of the list and insert the new entry there. */ 67 for (ip = table->osabi_head; (*ip) != NULL; ip = &(*ip)->next); 68 (*ip) = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry); 69 (*ip)->sniffer = sniffer; 70} 71 72void 73frame_unwind_prepend_unwinder (struct gdbarch *gdbarch, 74 const struct frame_unwind *unwinder) 75{ 76 struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); 77 struct frame_unwind_table_entry *entry; 78 79 /* Insert the new entry at the start of the list. */ 80 entry = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind_table_entry); 81 entry->unwinder = unwinder; 82 entry->next = (*table->osabi_head); 83 (*table->osabi_head) = entry; 84} 85 86const struct frame_unwind * 87frame_unwind_find_by_frame (struct frame_info *next_frame, void **this_cache) 88{ 89 int i; 90 struct gdbarch *gdbarch = get_frame_arch (next_frame); 91 struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); 92 struct frame_unwind_table_entry *entry; 93 for (entry = table->list; entry != NULL; entry = entry->next) 94 { 95 if (entry->sniffer != NULL) 96 { 97 const struct frame_unwind *desc = NULL; 98 desc = entry->sniffer (next_frame); 99 if (desc != NULL) 100 return desc; 101 } 102 if (entry->unwinder != NULL) 103 { 104 if (entry->unwinder->sniffer (entry->unwinder, next_frame, 105 this_cache)) 106 return entry->unwinder; 107 } 108 } 109 internal_error (__FILE__, __LINE__, "frame_unwind_find_by_frame failed"); 110} 111 112extern initialize_file_ftype _initialize_frame_unwind; /* -Wmissing-prototypes */ 113 114void 115_initialize_frame_unwind (void) 116{ 117 frame_unwind_data = gdbarch_data_register_pre_init (frame_unwind_init); 118} 119