--- breakpoint.c.orig 2011-02-03 13:46:47.000000000 -0800 +++ breakpoint.c 2011-02-03 13:51:46.000000000 -0800 @@ -2217,6 +2217,46 @@ create_internal_breakpoint (struct gdbar return b; } +static const char *const longjmp_names[] = + { + "longjmp", "_longjmp", "siglongjmp", "_siglongjmp" + }; +#define NUM_LONGJMP_NAMES \ + (sizeof (longjmp_names) / sizeof (longjmp_names[0])) + +/* Per-objfile data private to breakpoint.c */ +struct breakpoint_objfile_data +{ + CORE_ADDR overlay_bp_addr; + CORE_ADDR longjmp_bp_addr[NUM_LONGJMP_NAMES]; + CORE_ADDR terminate_bp_addr; + CORE_ADDR exception_bp_addr; +}; + +static const struct objfile_data *breakpoint_objfile_key; + +/* Return per-objfile data needed by breakpoint.c. + Allocate the data if necessary. */ + +static struct breakpoint_objfile_data * +get_breakpoint_objfile_data (struct objfile *objfile) +{ + struct breakpoint_objfile_data *bp_objfile_data; + + bp_objfile_data = objfile_data (objfile, breakpoint_objfile_key); + if (bp_objfile_data == NULL) + { + bp_objfile_data = obstack_alloc (&objfile->objfile_obstack, + sizeof (*bp_objfile_data)); + + memset (bp_objfile_data, 0, sizeof (*bp_objfile_data)); + set_objfile_data (objfile, breakpoint_objfile_key, bp_objfile_data); + } + return bp_objfile_data; +} + +#define INVALID_CORE_ADDR ((CORE_ADDR)-1) + static void create_overlay_event_breakpoint (void) { @@ -2226,14 +2266,29 @@ create_overlay_event_breakpoint (void) ALL_OBJFILES (objfile) { struct breakpoint *b; - struct minimal_symbol *m; + struct breakpoint_objfile_data *bp_objfile_data; - m = lookup_minimal_symbol_text (func_name, objfile); - if (m == NULL) - continue; + bp_objfile_data = get_breakpoint_objfile_data (objfile); + + if (bp_objfile_data->overlay_bp_addr == INVALID_CORE_ADDR) + continue; + + if (bp_objfile_data->overlay_bp_addr == 0) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol_text (func_name, objfile); + if (m == NULL) + { + /* Avoid future lookups in this objfile. */ + bp_objfile_data->overlay_bp_addr = INVALID_CORE_ADDR; + continue; + } + bp_objfile_data->overlay_bp_addr = SYMBOL_VALUE_ADDRESS (m); + } b = create_internal_breakpoint (get_objfile_arch (objfile), - SYMBOL_VALUE_ADDRESS (m), + bp_objfile_data->overlay_bp_addr, bp_overlay_event); b->addr_string = xstrdup (func_name); @@ -2267,30 +2322,41 @@ create_longjmp_master_breakpoint (void) ALL_OBJFILES (objfile) { - const char *const longjmp_names[] - = { "longjmp", "_longjmp", "siglongjmp", "_siglongjmp" }; - const int num_longjmp_names - = sizeof (longjmp_names) / sizeof (longjmp_names[0]); int i; struct gdbarch *gdbarch; + struct breakpoint_objfile_data *bp_objfile_data; gdbarch = get_objfile_arch (objfile); if (!gdbarch_get_longjmp_target_p (gdbarch)) continue; - for (i = 0; i < num_longjmp_names; i++) + bp_objfile_data = get_breakpoint_objfile_data (objfile); + + for (i = 0; i < NUM_LONGJMP_NAMES; i++) { struct breakpoint *b; - struct minimal_symbol *m; const char *func_name; - func_name = longjmp_names[i]; - m = lookup_minimal_symbol_text (func_name, objfile); - if (m == NULL) + if (bp_objfile_data->longjmp_bp_addr[i] == INVALID_CORE_ADDR) continue; + func_name = longjmp_names[i]; + if (bp_objfile_data->longjmp_bp_addr[i] == 0) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol_text (func_name, objfile); + if (m == NULL) + { + /* Prevent future lookups in this objfile. */ + bp_objfile_data->longjmp_bp_addr[i] = INVALID_CORE_ADDR; + continue; + } + bp_objfile_data->longjmp_bp_addr[i] = SYMBOL_VALUE_ADDRESS (m); + } + b = create_internal_breakpoint (gdbarch, - SYMBOL_VALUE_ADDRESS (m), + bp_objfile_data->longjmp_bp_addr[i], bp_longjmp_master); b->addr_string = xstrdup (func_name); b->enable_state = bp_disabled; @@ -2307,31 +2373,50 @@ static void create_std_terminate_master_breakpoint (void) { struct program_space *pspace; - struct objfile *objfile; struct cleanup *old_chain; const char *const func_name = "std::terminate()"; old_chain = save_current_program_space (); ALL_PSPACES (pspace) + { + struct objfile *objfile; + + set_current_program_space (pspace); + ALL_OBJFILES (objfile) { struct breakpoint *b; - struct minimal_symbol *m; + struct breakpoint_objfile_data *bp_objfile_data; - set_current_program_space (pspace); + bp_objfile_data = get_breakpoint_objfile_data (objfile); - m = lookup_minimal_symbol (func_name, NULL, objfile); - if (m == NULL || (MSYMBOL_TYPE (m) != mst_text - && MSYMBOL_TYPE (m) != mst_file_text)) - continue; + if (bp_objfile_data->terminate_bp_addr == INVALID_CORE_ADDR) + continue; + + if (bp_objfile_data->terminate_bp_addr == 0) + { + struct minimal_symbol *m; + + m = lookup_minimal_symbol (func_name, NULL, objfile); + if (m == NULL || (MSYMBOL_TYPE (m) != mst_text + && MSYMBOL_TYPE (m) != mst_file_text)) + { + /* Prevent future lookups in this objfile. */ + bp_objfile_data->terminate_bp_addr = INVALID_CORE_ADDR; + continue; + } + bp_objfile_data->terminate_bp_addr = SYMBOL_VALUE_ADDRESS (m); + } b = create_internal_breakpoint (get_objfile_arch (objfile), - SYMBOL_VALUE_ADDRESS (m), + bp_objfile_data->terminate_bp_addr, bp_std_terminate_master); b->addr_string = xstrdup (func_name); b->enable_state = bp_disabled; } + } + update_global_location_list (1); do_cleanups (old_chain); @@ -2343,24 +2428,45 @@ void create_exception_master_breakpoint (void) { struct objfile *objfile; + const char *const func_name = "_Unwind_DebugHook"; ALL_OBJFILES (objfile) { - struct minimal_symbol *debug_hook; + struct breakpoint *b; + struct gdbarch *gdbarch; + struct breakpoint_objfile_data *bp_objfile_data; - debug_hook = lookup_minimal_symbol ("_Unwind_DebugHook", NULL, objfile); - if (debug_hook != NULL) + bp_objfile_data = get_breakpoint_objfile_data (objfile); + + if (bp_objfile_data->exception_bp_addr == INVALID_CORE_ADDR) + continue; + + gdbarch = get_objfile_arch (objfile); + + if (bp_objfile_data->exception_bp_addr == 0) { - struct breakpoint *b; - CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (debug_hook); - struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct minimal_symbol *debug_hook; + CORE_ADDR addr; - addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, - ¤t_target); - b = create_internal_breakpoint (gdbarch, addr, bp_exception_master); - b->addr_string = xstrdup ("_Unwind_DebugHook"); - b->enable_state = bp_disabled; + debug_hook = lookup_minimal_symbol (func_name, NULL, objfile); + if (debug_hook == NULL) + { + bp_objfile_data->exception_bp_addr = INVALID_CORE_ADDR; + continue; + } + + addr = SYMBOL_VALUE_ADDRESS (debug_hook); + + bp_objfile_data->exception_bp_addr + = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, + ¤t_target); } + + b = create_internal_breakpoint (gdbarch, + bp_objfile_data->exception_bp_addr, + bp_exception_master); + b->addr_string = xstrdup (func_name); + b->enable_state = bp_disabled; } update_global_location_list (1); @@ -12071,6 +12177,8 @@ _initialize_breakpoint (void) observer_attach_inferior_exit (clear_syscall_counts); observer_attach_memory_changed (invalidate_bp_value_on_memory_change); + breakpoint_objfile_key = register_objfile_data (); + breakpoint_chain = 0; /* Don't bother to call set_breakpoint_count. $bpnum isn't useful before a breakpoint is set. */