From 27c2469e2f0236a696b5e3161a2668ae21f86666 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sat, 3 Nov 2007 19:10:29 +0000 Subject: [PATCH] - Backport `Breakpoints at multiple locations' patch primarily for C++. --- gdb-6.3-bz193763-object-name-completion.patch | 21 - gdb-6.3-constructor-20041216.patch | 44 - gdb-6.3-ctorline-20050120.patch | 681 --- gdb-6.3-dtorfix-20050121.patch | 52 - gdb-6.3-linespec-20041213.patch | 651 --- gdb-6.3-pie-20050110.patch | 211 +- gdb-6.3-test-dtorfix-20050121.patch | 276 - gdb-6.3-test-pie-20050107.patch | 8 +- gdb-6.3-threaded-watchpoints-20041213.patch | 116 +- gdb-6.3-xfree-20050922.patch | 21 - gdb-6.5-bz200048-find_line_pc-segv.patch | 30 - gdb-6.7.1-upstream.patch | 5084 +++++++++++++++++ gdb.spec | 37 +- 13 files changed, 5254 insertions(+), 1978 deletions(-) delete mode 100644 gdb-6.3-bz193763-object-name-completion.patch delete mode 100644 gdb-6.3-constructor-20041216.patch delete mode 100644 gdb-6.3-ctorline-20050120.patch delete mode 100644 gdb-6.3-dtorfix-20050121.patch delete mode 100644 gdb-6.3-linespec-20041213.patch delete mode 100644 gdb-6.3-test-dtorfix-20050121.patch delete mode 100644 gdb-6.3-xfree-20050922.patch delete mode 100644 gdb-6.5-bz200048-find_line_pc-segv.patch diff --git a/gdb-6.3-bz193763-object-name-completion.patch b/gdb-6.3-bz193763-object-name-completion.patch deleted file mode 100644 index 84f7809..0000000 --- a/gdb-6.3-bz193763-object-name-completion.patch +++ /dev/null @@ -1,21 +0,0 @@ -https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=193763 - -[base] - -2007-09-21 Jan Kratochvil - - Updated for the longer `$allocate' marker. - -Index: gdb-6.5/gdb/linespec.c -=================================================================== ---- gdb-6.5.orig/gdb/linespec.c 2006-08-24 02:57:04.000000000 -0300 -+++ gdb-6.5/gdb/linespec.c 2006-08-24 02:57:07.000000000 -0300 -@@ -295,7 +295,7 @@ add_minsym_members (const char *class_na - This will give us a list of all the member names including - the function signature. */ - completion_name = xmalloc (strlen (class_name) + -- strlen (member_name) + 9); -+ strlen (member_name) + strlen("'::$allocate(") + 1); - completion_name[0] = '\''; - strcpy (completion_name+1, class_name); - /* FIXME: make this the language class separator. */ diff --git a/gdb-6.3-constructor-20041216.patch b/gdb-6.3-constructor-20041216.patch deleted file mode 100644 index f89f08a..0000000 --- a/gdb-6.3-constructor-20041216.patch +++ /dev/null @@ -1,44 +0,0 @@ -2004-12-16 Jeff Johnston - - * cp-demangle.c (d_print_comp): Add support for exposing - not-in-charge constructors/destructors in the demangled - names. - ---- gdb-6.3/libiberty/cp-demangle.c.fix Thu Dec 16 16:39:09 2004 -+++ gdb-6.3/libiberty/cp-demangle.c Thu Dec 16 16:39:37 2004 -@@ -2978,11 +2978,35 @@ d_print_comp (dpi, dc) - - case DEMANGLE_COMPONENT_CTOR: - d_print_comp (dpi, dc->u.s_ctor.name); -+ switch (dc->u.s_ctor.kind) -+ { -+ case gnu_v3_complete_object_ctor: -+ /* no decoration */ -+ break; -+ case gnu_v3_base_object_ctor: -+ d_append_string (dpi, "$base"); -+ break; -+ case gnu_v3_complete_object_allocating_ctor: -+ d_append_string (dpi, "$allocate"); -+ break; -+ } - return; - - case DEMANGLE_COMPONENT_DTOR: - d_append_char (dpi, '~'); - d_print_comp (dpi, dc->u.s_dtor.name); -+ switch (dc->u.s_dtor.kind) -+ { -+ case gnu_v3_deleting_dtor: -+ d_append_string (dpi, "$delete"); -+ break; -+ case gnu_v3_complete_object_dtor: -+ /* no decoration */ -+ break; -+ case gnu_v3_base_object_dtor: -+ d_append_string (dpi, "$base"); -+ break; -+ } - return; - - case DEMANGLE_COMPONENT_VTABLE: diff --git a/gdb-6.3-ctorline-20050120.patch b/gdb-6.3-ctorline-20050120.patch deleted file mode 100644 index 6171131..0000000 --- a/gdb-6.3-ctorline-20050120.patch +++ /dev/null @@ -1,681 +0,0 @@ -2005-01-20 Jeff Johnston - - * symtab.h (find_line_pc): Change prototype to new api - which returns a list of pc values and the number of list elements. - * symtab.c (find_line_pc): Change function to new api which - returns a list of pc values. Support recognizing a base ctor - or dtor and finding an additional pc value for the in-charge - ctor or dtor accordingly. - (find_line_common): Change api to accept a start_index argument - which determines where to start searching from in the line table. - (find_line_by_pc): New function. - * breakpoint.c (resolve_sal_pc_list): New function. - (breakpoint_sals_to_pc): Support multiple pc values for a - line in a ctor/dtor. - (gdb_breakpoint): Change call to find_line_pc to use new api. - (break_command_1): Move resolve_sals_to_pc earlier due to the - fact it now can extend the sal list. - * mi/mi-cmd-disas.c (mi_cmd_disassemble): Change call to - find_line_pc to new api. - * tui/tui-layout.c (extract_display_start_addr): Ditto. - * tui/tui-win.c (make_visible_with_new_height): Ditto. - * tui/tui-winsource.c (tui_update_source_windows_with_addr): Ditto. - -2007-09-22 Jan Kratochvil - - * symtab.c (find_line_pc): Support also the `$allocate' and `$delete' - variants. Support searching for the `$base' name even if the bare name - was found first. - * breakpoint.c (breakpoint_sals_to_pc): Support more than two returned - PC values. - -2007-09-25 Jan Kratochvil - - * breakpoint.c (breakpoint_sals_to_pc): New parameter ADDR_STRING_P. - Expand also *ADDR_STRING_P if multiple PCs were found. - (break_command_1, do_captured_breakpoint): Pass also the ADDR_STRING - variable to be updated. - -2007-10-05 Jan Kratochvil - - * breakpoint.c (breakpoint_sals_to_pc): Provide "%42" suffix to the - multiple-PC breakpoints' ADDR_STRINGs. - (breakpoint_re_set_one): New variables ID_S, ID, PC_LIST, NUM_PC_VALUES. - Parse the "%42" suffix of the multiple-PC breakpoints's ADDR_STRINGs. - -2007-10-14 Jan Kratochvil - - Port to GDB-6.7. - -Index: gdb-6.7/gdb/mi/mi-cmd-disas.c -=================================================================== ---- gdb-6.7.orig/gdb/mi/mi-cmd-disas.c 2007-08-23 20:08:48.000000000 +0200 -+++ gdb-6.7/gdb/mi/mi-cmd-disas.c 2007-10-14 23:26:23.000000000 +0200 -@@ -143,11 +143,18 @@ mi_cmd_disassemble (char *command, char - - if (line_seen && file_seen) - { -+ CORE_ADDR *pc_list; -+ int num_pc_values; -+ - s = lookup_symtab (file_string); - if (s == NULL) - error (_("mi_cmd_disassemble: Invalid filename.")); -- if (!find_line_pc (s, line_num, &start)) -+ if (!find_line_pc (s, line_num, &pc_list, &num_pc_values)) - error (_("mi_cmd_disassemble: Invalid line number")); -+ /* FIXME: What do we do with multiple pc values for ctors/dtors -+ under mi? */ -+ start = pc_list[0]; -+ xfree (pc_list); - if (find_pc_partial_function (start, NULL, &low, &high) == 0) - error (_("mi_cmd_disassemble: No function contains specified address")); - } -Index: gdb-6.7/gdb/tui/tui-layout.c -=================================================================== ---- gdb-6.7.orig/gdb/tui/tui-layout.c 2007-08-23 20:08:50.000000000 +0200 -+++ gdb-6.7/gdb/tui/tui-layout.c 2007-10-14 23:26:23.000000000 +0200 -@@ -516,7 +516,8 @@ extract_display_start_addr (void) - { - enum tui_layout_type cur_layout = tui_current_layout (); - CORE_ADDR addr; -- CORE_ADDR pc; -+ CORE_ADDR *pc_list; -+ int num_pc_values; - struct symtab_and_line cursal = get_current_source_symtab_and_line (); - - switch (cur_layout) -@@ -525,8 +526,11 @@ extract_display_start_addr (void) - case SRC_DATA_COMMAND: - find_line_pc (cursal.symtab, - TUI_SRC_WIN->detail.source_info.start_line_or_addr.u.line_no, -- &pc); -- addr = pc; -+ &pc_list, &num_pc_values); -+ /* FIXME: What do we do with multiple pc values for ctors/dtors or -+ inlined functions? */ -+ addr = pc_list[0]; -+ xfree (pc_list); - break; - case DISASSEM_COMMAND: - case SRC_DISASSEM_COMMAND: -Index: gdb-6.7/gdb/tui/tui-win.c -=================================================================== ---- gdb-6.7.orig/gdb/tui/tui-win.c 2007-08-23 20:08:50.000000000 +0200 -+++ gdb-6.7/gdb/tui/tui-win.c 2007-10-14 23:26:23.000000000 +0200 -@@ -1359,8 +1359,16 @@ make_visible_with_new_height (struct tui - } - else - { -+ CORE_ADDR *pc_list; -+ int num_pc_values; - line.loa = LOA_ADDRESS; -- find_line_pc (s, cursal.line, &line.u.addr); -+ if (find_line_pc (s, cursal.line, &pc_list, &num_pc_values)) -+ { -+ /* FIXME: What do we do with multiple pc values for -+ ctors/dtors and inlined functions? */ -+ line.u.addr = pc_list[0]; -+ xfree (pc_list); -+ } - } - tui_update_source_window (win_info, s, line, TRUE); - } -Index: gdb-6.7/gdb/tui/tui-winsource.c -=================================================================== ---- gdb-6.7.orig/gdb/tui/tui-winsource.c 2007-08-23 20:08:50.000000000 +0200 -+++ gdb-6.7/gdb/tui/tui-winsource.c 2007-10-14 23:26:23.000000000 +0200 -@@ -173,14 +173,21 @@ tui_update_source_windows_with_addr (COR - void - tui_update_source_windows_with_line (struct symtab *s, int line) - { -- CORE_ADDR pc; -+ CORE_ADDR pc = 0; -+ CORE_ADDR *pc_list; -+ int num_pc_values; - struct tui_line_or_address l; - - switch (tui_current_layout ()) - { - case DISASSEM_COMMAND: - case DISASSEM_DATA_COMMAND: -- find_line_pc (s, line, &pc); -+ /* FIXME: What do we do with multiple pc values for ctors/dtors? */ -+ if (find_line_pc (s, line, &pc_list, &num_pc_values)) -+ { -+ pc = pc_list[0]; -+ xfree (pc_list); -+ } - tui_update_source_windows_with_addr (pc); - break; - default: -@@ -189,7 +196,12 @@ tui_update_source_windows_with_line (str - tui_show_symtab_source (s, l, FALSE); - if (tui_current_layout () == SRC_DISASSEM_COMMAND) - { -- find_line_pc (s, line, &pc); -+ /* FIXME: What do we do with multiple pc values for ctors/dtors? */ -+ if (find_line_pc (s, line, &pc_list, &num_pc_values)) -+ { -+ pc = pc_list[0]; -+ xfree (pc_list); -+ } - tui_show_disassem (pc); - } - break; -Index: gdb-6.7/gdb/symtab.c -=================================================================== ---- gdb-6.7.orig/gdb/symtab.c 2007-10-12 22:35:58.000000000 +0200 -+++ gdb-6.7/gdb/symtab.c 2007-10-14 23:26:23.000000000 +0200 -@@ -73,7 +73,9 @@ static void sources_info (char *, int); - - static void output_source_filename (const char *, int *); - --static int find_line_common (struct linetable *, int, int *); -+static int find_line_common (struct linetable *, int, int, int *); -+ -+static int find_line_by_pc (struct linetable *, CORE_ADDR, int *); - - /* This one is used by linespec.c */ - -@@ -2252,6 +2254,9 @@ find_pc_line (CORE_ADDR pc, int notcurre - /* Find line number LINE in any symtab whose name is the same as - SYMTAB. - -+ If INDEX is non-NULL, use the value as the starting index in the -+ linetable to start at. -+ - If found, return the symtab that contains the linetable in which it was - found, set *INDEX to the index in the linetable of the best entry - found, and set *EXACT_MATCH nonzero if the value returned is an -@@ -2268,13 +2273,19 @@ find_line_symtab (struct symtab *symtab, - so far seen. */ - - int best_index; -+ int start_index; - struct linetable *best_linetable; - struct symtab *best_symtab; - -+ if (index) -+ start_index = *index; -+ else -+ start_index = 0; -+ - /* First try looking it up in the given symtab. */ - best_linetable = LINETABLE (symtab); - best_symtab = symtab; -- best_index = find_line_common (best_linetable, line, &exact); -+ best_index = find_line_common (best_linetable, line, start_index, &exact); - if (best_index < 0 || !exact) - { - /* Didn't find an exact match. So we better keep looking for -@@ -2305,7 +2316,7 @@ find_line_symtab (struct symtab *symtab, - if (strcmp (symtab->filename, s->filename) != 0) - continue; - l = LINETABLE (s); -- ind = find_line_common (l, line, &exact); -+ ind = find_line_common (l, line, start_index, &exact); - if (ind >= 0) - { - if (exact) -@@ -2341,13 +2352,23 @@ done: - Returns zero for invalid line number (and sets the PC to 0). - The source file is specified with a struct symtab. */ - -+static CORE_ADDR empty_pc_list = (CORE_ADDR)0; -+ - int --find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc) -+find_line_pc (struct symtab *symtab, int line, CORE_ADDR **pc_array, -+ int *num_elements) - { - struct linetable *l; -- int ind; -+ int ind = 0; -+ char *name; -+ CORE_ADDR main_pc; -+ struct minimal_symbol *minsym; -+ struct minimal_symbol *minsym2; -+ -+ -+ *pc_array = &empty_pc_list; -+ *num_elements = 0; - -- *pc = 0; - if (symtab == 0) - return 0; - -@@ -2355,7 +2376,73 @@ find_line_pc (struct symtab *symtab, int - if (symtab != NULL) - { - l = LINETABLE (symtab); -- *pc = l->item[ind].pc; -+ main_pc = l->item[ind].pc; -+ *pc_array = xmalloc (sizeof (CORE_ADDR) * 3); -+ *num_elements = 0; -+ (*pc_array)[(*num_elements)++] = main_pc; -+ minsym = lookup_minimal_symbol_by_pc (main_pc); -+ if (minsym != NULL && minsym->ginfo.language == language_cplus) -+ { -+ char *src = minsym->ginfo.language_specific.cplus_specific.demangled_name; -+ char *src_point = strchr (src, '('); -+ char *s, *point; -+ /* Keep "" last as the trimming part always matches it. */ -+ const char *variants[] = {"$base","$allocate","$delete",""}; -+ int i; -+ -+ if (src_point != NULL) -+ { -+ char *dst = xmalloc (strlen (src) + strlen ("$allocate") + 1); -+ char *dst_point = dst + (src_point - src); -+ -+ memcpy (dst, src, src_point - src); -+ -+ /* Trim out any variant markers there first. */ -+ for (i = 0; i < ARRAY_SIZE (variants); i++) -+ { -+ size_t len = strlen (variants[i]); -+ -+ if (dst_point - dst >= len -+ && memcmp (dst_point - len, variants[i], len) == 0) -+ { -+ dst_point -= len; -+ /* In fact it should not be needed here. */ -+ break; -+ } -+ } -+ -+ /* And now try to append all of them. */ -+ for (i = 0; i < ARRAY_SIZE (variants); i++) -+ { -+ size_t len = strlen (variants[i]); -+ struct minimal_symbol *minsym2; -+ -+ memcpy (dst_point, variants[i], len); -+ strcpy (dst_point + len, src_point); -+ -+ minsym2 = lookup_minimal_symbol (dst, NULL, NULL); -+ if (minsym2 != NULL) -+ { -+ /* We have recognized we have a ctor or dtor and have -+ located our line in the not-in-charge version. We -+ also have located the in-charge version's minsym. -+ From this, we can find the index for the first line -+ line in the in-charge ctor/dtor and then search forward -+ for the specified line, thereby finding the 2nd match. */ -+ int exact; -+ int ind = find_line_by_pc (l, minsym2->ginfo.value.address, -+ &exact); -+ if (ind >= 0) -+ { -+ ind = find_line_common (l, line, ind, &exact); -+ if (ind >= 0 && l->item[ind].pc != main_pc) -+ (*pc_array)[(*num_elements)++] = l->item[ind].pc; -+ } -+ } -+ } -+ xfree (dst); -+ } -+ } - return 1; - } - else -@@ -2373,12 +2460,22 @@ find_line_pc_range (struct symtab_and_li - CORE_ADDR *endptr) - { - CORE_ADDR startaddr; -+ CORE_ADDR *pc_list; -+ int num_pc_values; - struct symtab_and_line found_sal; - - startaddr = sal.pc; -- if (startaddr == 0 && !find_line_pc (sal.symtab, sal.line, &startaddr)) -+ if (startaddr == 0 -+ && !find_line_pc (sal.symtab, sal.line, &pc_list, &num_pc_values)) - return 0; - -+ /* FIXME: have to handle ctors/dtors where line equates to multiple -+ pc ranges. */ -+ if (startaddr == 0) -+ startaddr = pc_list[0]; -+ -+ xfree (pc_list); -+ - /* This whole function is based on address. For example, if line 10 has - two parts, one from 0x100 to 0x200 and one from 0x300 to 0x400, then - "info line *0x123" should say the line goes from 0x100 to 0x200 -@@ -2408,7 +2505,7 @@ find_line_pc_range (struct symtab_and_li - Set *EXACT_MATCH nonzero if the value returned is an exact match. */ - - static int --find_line_common (struct linetable *l, int lineno, -+find_line_common (struct linetable *l, int lineno, int start_index, - int *exact_match) - { - int i; -@@ -2427,7 +2524,7 @@ find_line_common (struct linetable *l, i - return -1; - - len = l->nitems; -- for (i = 0; i < len; i++) -+ for (i = start_index; i < len; i++) - { - struct linetable_entry *item = &(l->item[i]); - -@@ -2451,6 +2548,52 @@ find_line_common (struct linetable *l, i - return best_index; - } - -+/* Given a line table and a pc value, return the index into the line -+ table for the line with pc >= specified pc value. -+ Return -1 if none is found. The value is >= 0 if it is an index. -+ -+ Set *EXACT_MATCH nonzero if the value returned is an exact match. */ -+ -+static int -+find_line_by_pc (struct linetable *l, CORE_ADDR pc, -+ int *exact_match) -+{ -+ int i; -+ int len; -+ -+ /* BEST is the smallest linenumber > LINENO so far seen, -+ or 0 if none has been seen so far. -+ BEST_INDEX identifies the item for it. */ -+ -+ if (l == 0) -+ return -1; -+ -+ len = l->nitems; -+ for (i = 0; i < len; i++) -+ { -+ struct linetable_entry *item = &(l->item[i]); -+ -+ /* Return the first (lowest address) entry which matches or -+ exceeds the given pc value. */ -+ if (item->pc == pc) -+ { -+ *exact_match = 1; -+ return i; -+ } -+ -+ if (item->pc > pc) -+ { -+ *exact_match = 0; -+ return i; -+ } -+ } -+ -+ /* If we got here, we didn't get a match. */ -+ -+ *exact_match = 0; -+ return -1; -+} -+ - int - find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr) - { -Index: gdb-6.7/gdb/symtab.h -=================================================================== ---- gdb-6.7.orig/gdb/symtab.h 2007-08-23 20:08:45.000000000 +0200 -+++ gdb-6.7/gdb/symtab.h 2007-10-14 23:26:23.000000000 +0200 -@@ -1271,13 +1271,16 @@ extern struct symtab_and_line find_pc_se - - /* Given a symtab and line number, return the pc there. */ - --extern int find_line_pc (struct symtab *, int, CORE_ADDR *); -+extern int find_line_pc (struct symtab *, int, CORE_ADDR **, int *); - - extern int find_line_pc_range (struct symtab_and_line, CORE_ADDR *, - CORE_ADDR *); - - extern void resolve_sal_pc (struct symtab_and_line *); - -+extern void resolve_sal_pc_list (struct symtab_and_line *, CORE_ADDR **, -+ int *); -+ - /* Given a string, return the line specified by it. For commands like "list" - and "breakpoint". */ - -Index: gdb-6.7/gdb/breakpoint.c -=================================================================== ---- gdb-6.7.orig/gdb/breakpoint.c 2007-10-13 05:29:58.000000000 +0200 -+++ gdb-6.7/gdb/breakpoint.c 2007-10-14 23:26:23.000000000 +0200 -@@ -5325,12 +5325,70 @@ parse_breakpoint_sals (char **address, - - static void - breakpoint_sals_to_pc (struct symtabs_and_lines *sals, -- char *address) -+ char *address, char ***addr_string_p) - { -- int i; -- for (i = 0; i < sals->nelts; i++) -- { -- resolve_sal_pc (&sals->sals[i]); -+ int i, j, incr; -+ int num_pc_values = 1; -+ -+ /* If a line has multiple pc values, we want to create an sal for -+ each pc value so we will end up creating n breakpoints. */ -+ for (i = 0; i < sals->nelts; i+=incr) -+ { -+ CORE_ADDR *pc_list; -+ incr = 1; -+ -+ resolve_sal_pc_list (&sals->sals[i], &pc_list, &num_pc_values); -+ if (num_pc_values != 0) -+ sals->sals[i].pc = pc_list[0]; -+ if (num_pc_values > 1) -+ { -+ struct symtab_and_line *new_sals = -+ xmalloc ((sals->nelts + num_pc_values - 1) -+ * sizeof (struct symtab_and_line)); -+ char **new_addr_string; -+ char *addr_string_base; -+ -+ /* Expand the SALS array. */ -+ memcpy (new_sals, sals->sals, (i + 1) -+ * sizeof (struct symtab_and_line)); -+ /* The one returned SALS entry is copied for all the PCs. */ -+ for (j = 1; j < num_pc_values; ++j) -+ { -+ memcpy (&(new_sals[i + j]), &sals->sals[i], -+ sizeof (struct symtab_and_line)); -+ } -+ xfree (sals->sals); -+ sals->sals = new_sals; -+ sals->nelts += num_pc_values - 1; -+ for (j = 1; j < num_pc_values; ++j) -+ { -+ sals->sals[i + j].pc = pc_list[j]; -+ } -+ -+ /* Expand the *ADDR_STRING_P array. */ -+ new_addr_string = xmalloc ((sals->nelts + num_pc_values - 1) -+ * sizeof *new_addr_string); -+ memcpy (new_addr_string, *addr_string_p, -+ (i + 1) * sizeof *new_addr_string); -+ /* The existing *ADDR_STRING_P entry must be copied for all the -+ multiple PCs. BREAKPOINT_RE_SET will follow the new trailing "%id" -+ syntax so it will get resolved right even later. Do not use the -+ unambiguous NULL values (resolved to "0x%x" by CREATE_BREAKPOINTS) -+ as the address may change for the shared libraries. */ -+ addr_string_base = (*addr_string_p)[i]; -+ for (j = 0; j < num_pc_values; ++j) -+ new_addr_string[i + j] = xstrprintf ("%s%%%d", addr_string_base, j); -+ xfree (addr_string_base); -+ memcpy (&new_addr_string[i + num_pc_values], &(*addr_string_p)[i + 1], -+ (sals->nelts - (i + num_pc_values)) * sizeof *new_addr_string); -+ xfree (*addr_string_p); -+ *addr_string_p = new_addr_string; -+ -+ incr = num_pc_values; -+ } -+ -+ if (num_pc_values != 0) -+ xfree (pc_list); - - /* It's possible for the PC to be nonzero, but still an illegal - value on some targets. -@@ -5465,6 +5523,10 @@ break_command_1 (char *arg, int flag, in - - if (!pending) - { -+ /* Resolve all line numbers to PC's and verify that the addresses -+ are ok for the target. */ -+ breakpoint_sals_to_pc (&sals, addr_start, &addr_string); -+ - /* Make sure that all storage allocated to SALS gets freed. */ - make_cleanup (xfree, sals.sals); - -@@ -5495,11 +5557,6 @@ break_command_1 (char *arg, int flag, in - make_cleanup (xfree, addr_string[i]); - } - -- /* Resolve all line numbers to PC's and verify that the addresses -- are ok for the target. */ -- if (!pending) -- breakpoint_sals_to_pc (&sals, addr_start); -- - /* Verify that condition can be parsed, before setting any - breakpoints. Allocate a separate condition expression for each - breakpoint. */ -@@ -5675,7 +5732,7 @@ do_captured_breakpoint (struct ui_out *u - error (_("Garbage %s following breakpoint address"), address_end); - - /* Resolve all line numbers to PC's. */ -- breakpoint_sals_to_pc (&sals, args->address); -+ breakpoint_sals_to_pc (&sals, args->address, &addr_string); - - /* Verify that conditions can be parsed, before setting any - breakpoints. */ -@@ -5732,14 +5789,16 @@ gdb_breakpoint (char *address, char *con - void - resolve_sal_pc (struct symtab_and_line *sal) - { -- CORE_ADDR pc; -+ CORE_ADDR *pc_list; -+ int num_pc_values; - - if (sal->pc == 0 && sal->symtab != NULL) - { -- if (!find_line_pc (sal->symtab, sal->line, &pc)) -+ if (!find_line_pc (sal->symtab, sal->line, &pc_list, &num_pc_values)) - error (_("No line %d in file \"%s\"."), - sal->line, sal->symtab->filename); -- sal->pc = pc; -+ sal->pc = pc_list[0]; -+ xfree (pc_list); - } - - if (sal->section == 0 && sal->symtab != NULL) -@@ -5776,6 +5835,54 @@ resolve_sal_pc (struct symtab_and_line * - } - } - -+/* Helper function for break_command_1 and disassemble_command. */ -+ -+void -+resolve_sal_pc_list (struct symtab_and_line *sal, CORE_ADDR **pc_list, -+ int *num_pc_values) -+{ -+ *num_pc_values = 0; -+ if (sal->pc == 0 && sal->symtab != NULL) -+ { -+ if (!find_line_pc (sal->symtab, sal->line, pc_list, num_pc_values)) -+ error ("No line %d in file \"%s\".", -+ sal->line, sal->symtab->filename); -+ sal->pc = (*pc_list)[0]; -+ } -+ -+ if (sal->section == 0 && sal->symtab != NULL) -+ { -+ struct blockvector *bv; -+ struct block *b; -+ struct symbol *sym; -+ int index; -+ -+ bv = blockvector_for_pc_sect (sal->pc, 0, &index, sal->symtab); -+ if (bv != NULL) -+ { -+ b = BLOCKVECTOR_BLOCK (bv, index); -+ sym = block_function (b); -+ if (sym != NULL) -+ { -+ fixup_symbol_section (sym, sal->symtab->objfile); -+ sal->section = SYMBOL_BFD_SECTION (sym); -+ } -+ else -+ { -+ /* It really is worthwhile to have the section, so we'll just -+ have to look harder. This case can be executed if we have -+ line numbers but no functions (as can happen in assembly -+ source). */ -+ -+ struct minimal_symbol *msym; -+ -+ msym = lookup_minimal_symbol_by_pc (sal->pc); -+ if (msym) -+ sal->section = SYMBOL_BFD_SECTION (msym); -+ } -+ } -+ } -+} - void - break_command (char *arg, int from_tty) - { -@@ -7320,6 +7427,8 @@ breakpoint_re_set_one (void *bint) - int *not_found_ptr = NULL; - struct symtabs_and_lines sals; - char *s; -+ char *id_s; -+ int id = -1; - enum enable_state save_enable; - - switch (b->type) -@@ -7380,11 +7489,44 @@ breakpoint_re_set_one (void *bint) - set_language (b->language); - input_radix = b->input_radix; - s = b->addr_string; -+ for (id_s = s + strlen (s) - 1; id_s >= s; id_s--) -+ { -+ if (isdigit (*id_s)) -+ continue; -+ if (*id_s == '%') -+ break; -+ id_s = NULL; -+ break; -+ } -+ if (id_s >= s) -+ { -+ s = alloca (id_s - b->addr_string + 1); -+ memcpy (s, b->addr_string, id_s - b->addr_string); -+ s[id_s - b->addr_string] = 0; -+ id = atoi (id_s + 1); -+ } - sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, - not_found_ptr); - for (i = 0; i < sals.nelts; i++) - { -- resolve_sal_pc (&sals.sals[i]); -+ CORE_ADDR *pc_list; -+ int num_pc_values; -+ -+ resolve_sal_pc_list (&sals.sals[i], &pc_list, &num_pc_values); -+ if (num_pc_values > 0) -+ { -+ if (id != -1) -+ { -+ /* The number of PC values should not usually change. */ -+ if (id >= num_pc_values) -+ { -+ delete_breakpoint (b); -+ return 0; -+ } -+ sals.sals[i].pc = pc_list[id]; -+ } -+ xfree (pc_list); -+ } - - /* Reparse conditions, they might contain references to the - old symtab. */ diff --git a/gdb-6.3-dtorfix-20050121.patch b/gdb-6.3-dtorfix-20050121.patch deleted file mode 100644 index 55cd23e..0000000 --- a/gdb-6.3-dtorfix-20050121.patch +++ /dev/null @@ -1,52 +0,0 @@ -2005-01-21 Jeff Johnston - - * linespec.c (collect_methods): Don't do special processing for - destructors as this will be handled in find_methods. - (find_methods): Fix ctor check to also check for dtor. - -2007-10-14 Jan Kratochvil - - Port to GDB-6.7. - -Index: gdb-6.7/gdb/linespec.c -=================================================================== ---- gdb-6.7.orig/gdb/linespec.c 2007-10-13 05:26:33.000000000 +0200 -+++ gdb-6.7/gdb/linespec.c 2007-10-14 23:31:03.000000000 +0200 -@@ -398,12 +398,14 @@ add_matching_methods (int method_counter - - /* Check for special case of looking for member that - doesn't have a mangled name provided. This will happen -- when we have in-charge and not-in-charge constructors. -+ when we have in-charge and not-in-charge ctors/dtors. - Since we don't have a mangled name to work with, if we -- look for the symbol, we can only find the class itself. -+ look for the symbol, we can at best find the class itself. - We can find the information we need in the minimal symbol - table which has the full member name information we need. */ -- if (strlen (phys_name) <= strlen (class_name)) -+ if (strlen (phys_name) <= strlen (class_name) -+ || (strlen (phys_name) == strlen (class_name) + 1 -+ && phys_name[0] == '~')) - return add_minsym_members (class_name, phys_name, msym_arr); - - /* Destructor is handled by caller, don't add it to -@@ -1731,6 +1733,11 @@ collect_methods (char *copy, struct type - { - int i1 = 0; /* Counter for the symbol array. */ - -+#if 0 -+ /* Ignore this special method for getting destructors because -+ find_methods is more robust and can handle multiple -+ destructors which is the case when gcc generates a not-in-charge -+ vs an in-charge destructor. */ - if (destructor_name_p (copy, t)) - { - /* Destructors are a special case. */ -@@ -1749,6 +1756,7 @@ collect_methods (char *copy, struct type - } - } - else -+#endif - i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr, msym_arr); - - return i1; diff --git a/gdb-6.3-linespec-20041213.patch b/gdb-6.3-linespec-20041213.patch deleted file mode 100644 index 08beccf..0000000 --- a/gdb-6.3-linespec-20041213.patch +++ /dev/null @@ -1,651 +0,0 @@ -[base] - -2007-09-21 Jan Kratochvil - - * linespec.c (add_minsym_members): Support also the `$allocate' and - `$delete' variants. - -2007-10-05 Jan Kratochvil - - * linespec.c (add_minsym_members): Support also the `$allocate' and - `$delete' variants. - (decode_variable): Renamed to ... - (decode_variable_1) ... here, its parameter NOT_FOUND_PTR and its - exception throwing was moved to ... - (decode_variable_not_found): ... a new function here. - (decode_variable): New function. - -2007-10-31 Jan Kratochvil - - Port to GDB-6.7. - -Index: gdb-6.7/gdb/linespec.c -=================================================================== ---- gdb-6.7.orig/gdb/linespec.c 2007-08-23 20:08:35.000000000 +0200 -+++ gdb-6.7/gdb/linespec.c 2007-10-13 05:26:33.000000000 +0200 -@@ -36,6 +36,7 @@ - #include "linespec.h" - #include "exceptions.h" - #include "language.h" -+#include "gdb_assert.h" - - /* We share this one with symtab.c, but it is not exported widely. */ - -@@ -75,7 +76,8 @@ static struct symtabs_and_lines find_met - - static int collect_methods (char *copy, struct type *t, - struct symbol *sym_class, -- struct symbol **sym_arr); -+ struct symbol **sym_arr, -+ struct minimal_symbol **msym_arr); - - static NORETURN void cplusplus_error (const char *name, - const char *fmt, ...) -@@ -84,11 +86,13 @@ static NORETURN void cplusplus_error (co - static int total_number_of_methods (struct type *type); - - static int find_methods (struct type *, char *, -- enum language, struct symbol **); -+ enum language, struct symbol **, -+ struct minimal_symbol **); - - static int add_matching_methods (int method_counter, struct type *t, - enum language language, -- struct symbol **sym_arr); -+ struct symbol **sym_arr, -+ struct minimal_symbol **msym_arr); - - static int add_constructors (int method_counter, struct type *t, - enum language language, -@@ -104,6 +108,9 @@ static int is_objc_method_format (const - static struct symtabs_and_lines decode_line_2 (struct symbol *[], - int, int, char ***); - -+static struct symtabs_and_lines decode_line_3 (struct minimal_symbol *[], -+ int, int, char ***); -+ - static struct symtab *symtab_from_filename (char **argptr, - char *p, int is_quote_enclosed, - int *not_found_ptr); -@@ -194,13 +201,18 @@ total_number_of_methods (struct type *ty - /* Recursive helper function for decode_line_1. - Look for methods named NAME in type T. - Return number of matches. -- Put matches in SYM_ARR, which should have been allocated with -+ Put symbol matches in SYM_ARR, which should have been allocated with - a size of total_number_of_methods (T) * sizeof (struct symbol *). -+ In a special case where we are looking for constructors, we may -+ have to return minimal symbols in the array: MSYM_ARR. This occurs -+ when the compiler does not generate mangled names for the constructor's -+ debug info because there are multiple versions of the constructor -+ (in-charge vs not-in-charge). - Note that this function is g++ specific. */ - - static int - find_methods (struct type *t, char *name, enum language language, -- struct symbol **sym_arr) -+ struct symbol **sym_arr, struct minimal_symbol **msym_arr) - { - int i1 = 0; - int ibase; -@@ -243,7 +255,7 @@ find_methods (struct type *t, char *name - if (strcmp_iw (name, method_name) == 0) - /* Find all the overloaded methods with that name. */ - i1 += add_matching_methods (method_counter, t, language, -- sym_arr + i1); -+ sym_arr + i1, msym_arr); - else if (strncmp (class_name, name, name_len) == 0 - && (class_name[name_len] == '\0' - || class_name[name_len] == '<')) -@@ -266,21 +278,100 @@ find_methods (struct type *t, char *name - if (i1 == 0) - for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++) - i1 += find_methods (TYPE_BASECLASS (t, ibase), name, -- language, sym_arr + i1); -+ language, sym_arr + i1, msym_arr); - - return i1; - } - -+static int -+add_minsym_members (const char *class_name, -+ const char *member_name, -+ struct minimal_symbol **msym_arr) -+{ -+ char *completion_name; -+ char **list; -+ int i; -+ int comp_len; -+ int counter = 0; -+ -+ /* To find the member, we first cheat and use symbol completion. -+ This will give us a list of all the member names including -+ the function signature. */ -+ completion_name = xmalloc (strlen (class_name) + -+ strlen (member_name) + 9); -+ completion_name[0] = '\''; -+ strcpy (completion_name+1, class_name); -+ /* FIXME: make this the language class separator. */ -+ strcat (completion_name, "::"); -+ strcat (completion_name, member_name); -+ strcat (completion_name, "("); -+ list = make_symbol_completion_list (completion_name, -+ completion_name+1); -+ -+ /* Now that we have the list, we generate an array of their -+ corresponding minimal symbols. */ -+ counter = 0; -+ while (list && list[counter] != NULL) -+ { -+ msym_arr[counter] = lookup_minimal_symbol (list[counter], NULL, NULL); -+ ++counter; -+ } -+ -+ xfree (list); -+ -+ /* In the case of constructors, there may be in-charge vs not-in-charge -+ constructors. Check for names with $base which indicates not-in-charge -+ constructors. */ -+ comp_len = strlen (completion_name); -+ strcpy (completion_name + comp_len - 1, "$base("); -+ list = make_symbol_completion_list (completion_name, -+ completion_name+1); -+ -+ /* Again we have a list. Add their minimal symbols to the array. */ -+ i = 0; -+ while (list && list[i] != NULL) -+ { -+ msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL); -+ ++counter; -+ } -+ xfree (list); -+ -+ /* Target also the allocating/deleting variants. */ -+ if (member_name[0] == '~') -+ strcpy (completion_name + comp_len - 1, "$delete("); -+ else -+ strcpy (completion_name + comp_len - 1, "$allocate("); -+ list = make_symbol_completion_list (completion_name, -+ completion_name+1); -+ -+ /* Again we have a list. Add their minimal symbols to the array. */ -+ i = 0; -+ while (list && list[i] != NULL) -+ { -+ msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL); -+ ++counter; -+ } -+ xfree (list); -+ -+ xfree (completion_name); -+ -+ return counter; -+} -+ - /* Add the symbols associated to methods of the class whose type is T - and whose name matches the method indexed by METHOD_COUNTER in the - array SYM_ARR. Return the number of methods added. */ - - static int - add_matching_methods (int method_counter, struct type *t, -- enum language language, struct symbol **sym_arr) -+ enum language language, struct symbol **sym_arr, -+ struct minimal_symbol **msym_arr) - { - int field_counter; - int i1 = 0; -+ int cons_index = 0; -+ char *class_name = type_name_no_tag (t); -+ char **list = NULL; - - for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1; - field_counter >= 0; -@@ -305,6 +396,16 @@ add_matching_methods (int method_counter - else - phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter); - -+ /* Check for special case of looking for member that -+ doesn't have a mangled name provided. This will happen -+ when we have in-charge and not-in-charge constructors. -+ Since we don't have a mangled name to work with, if we -+ look for the symbol, we can only find the class itself. -+ We can find the information we need in the minimal symbol -+ table which has the full member name information we need. */ -+ if (strlen (phys_name) <= strlen (class_name)) -+ return add_minsym_members (class_name, phys_name, msym_arr); -+ - /* Destructor is handled by caller, don't add it to - the list. */ - if (is_destructor_name (phys_name) != 0) -@@ -330,6 +431,9 @@ add_matching_methods (int method_counter - } - } - -+ if (list) -+ xfree (list); -+ - return i1; - } - -@@ -610,6 +714,146 @@ decode_line_2 (struct symbol *sym_arr[], - discard_cleanups (old_chain); - return return_values; - } -+ -+/* Given a list of NELTS minimal symbols in MSYM_ARR, return a list of lines to -+ operate on (ask user if necessary). -+ If CANONICAL is non-NULL return a corresponding array of mangled names -+ as canonical line specs there. */ -+ -+static struct symtabs_and_lines -+decode_line_3 (struct minimal_symbol *msym_arr[], -+ int nelts, int funfirstline, -+ char ***canonical) -+{ -+ struct symtabs_and_lines values, return_values; -+ char *args, *arg1; -+ int i; -+ char *prompt; -+ char *symname; -+ struct cleanup *old_chain; -+ char **canonical_arr = (char **) NULL; -+ -+ values.sals = (struct symtab_and_line *) -+ alloca (nelts * sizeof (struct symtab_and_line)); -+ return_values.sals = (struct symtab_and_line *) -+ xmalloc (nelts * sizeof (struct symtab_and_line)); -+ old_chain = make_cleanup (xfree, return_values.sals); -+ -+ if (canonical) -+ { -+ canonical_arr = (char **) xmalloc (nelts * sizeof (char *)); -+ make_cleanup (xfree, canonical_arr); -+ memset (canonical_arr, 0, nelts * sizeof (char *)); -+ *canonical = canonical_arr; -+ } -+ -+ i = 0; -+ printf_unfiltered ("[0] cancel\n[1] all\n"); -+ while (i < nelts) -+ { -+ init_sal (&return_values.sals[i]); /* Initialize to zeroes. */ -+ init_sal (&values.sals[i]); -+ if (msym_arr[i]) -+ { -+ struct symtabs_and_lines msal = minsym_found (funfirstline, -+ msym_arr[i]); -+ memcpy (&values.sals[i], &msal.sals[0], -+ sizeof (struct symtab_and_line)); -+ if (values.sals[i].symtab) -+ printf_unfiltered ("[%d] %s at %s:%d\n", -+ (i + 2), -+ SYMBOL_PRINT_NAME (msym_arr[i]), -+ values.sals[i].symtab->filename, -+ values.sals[i].line); -+ else -+ printf_unfiltered ("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n", -+ (i + 2), -+ SYMBOL_PRINT_NAME (msym_arr[i]), -+ values.sals[i].line); -+ -+ } -+ else -+ printf_unfiltered ("?HERE\n"); -+ i++; -+ } -+ -+ prompt = getenv ("PS2"); -+ if (prompt == NULL) -+ { -+ prompt = "> "; -+ } -+ args = command_line_input (prompt, 0, "overload-choice"); -+ -+ if (args == 0 || *args == 0) -+ error_no_arg ("one or more choice numbers"); -+ -+ i = 0; -+ while (*args) -+ { -+ int num; -+ -+ arg1 = args; -+ while (*arg1 >= '0' && *arg1 <= '9') -+ arg1++; -+ if (*arg1 && *arg1 != ' ' && *arg1 != '\t') -+ error ("Arguments must be choice numbers."); -+ -+ num = atoi (args); -+ -+ if (num == 0) -+ error ("canceled"); -+ else if (num == 1) -+ { -+ if (canonical_arr) -+ { -+ for (i = 0; i < nelts; i++) -+ { -+ if (canonical_arr[i] == NULL) -+ { -+ symname = DEPRECATED_SYMBOL_NAME (msym_arr[i]); -+ canonical_arr[i] = savestring (symname, strlen (symname)); -+ } -+ } -+ } -+ memcpy (return_values.sals, values.sals, -+ (nelts * sizeof (struct symtab_and_line))); -+ return_values.nelts = nelts; -+ discard_cleanups (old_chain); -+ return return_values; -+ } -+ -+ if (num >= nelts + 2) -+ { -+ printf_unfiltered ("No choice number %d.\n", num); -+ } -+ else -+ { -+ num -= 2; -+ if (values.sals[num].pc) -+ { -+ if (canonical_arr) -+ { -+ symname = DEPRECATED_SYMBOL_NAME (msym_arr[num]); -+ make_cleanup (xfree, symname); -+ canonical_arr[i] = savestring (symname, strlen (symname)); -+ } -+ return_values.sals[i++] = values.sals[num]; -+ values.sals[num].pc = 0; -+ } -+ else -+ { -+ printf_unfiltered ("duplicate request for %d ignored.\n", num); -+ } -+ } -+ -+ args = arg1; -+ while (*args == ' ' || *args == '\t') -+ args++; -+ } -+ return_values.nelts = i; -+ discard_cleanups (old_chain); -+ return return_values; -+} - - /* The parser of linespec itself. */ - -@@ -1414,35 +1658,46 @@ find_method (int funfirstline, char ***c - struct symbol **sym_arr = alloca (total_number_of_methods (t) - * sizeof (struct symbol *)); - -+ struct minimal_symbol **msym_arr = alloca (total_number_of_methods (t) -+ * sizeof (struct minimal_symbol *)); -+ -+ msym_arr[0] = NULL; -+ - /* Find all methods with a matching name, and put them in - sym_arr. */ - -- i1 = collect_methods (copy, t, sym_class, sym_arr); -+ i1 = collect_methods (copy, t, sym_class, sym_arr, msym_arr); - - if (i1 == 1) - { - /* There is exactly one field with that name. */ -- sym = sym_arr[0]; -- -- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) -- { -- values.sals = (struct symtab_and_line *) -- xmalloc (sizeof (struct symtab_and_line)); -- values.nelts = 1; -- values.sals[0] = find_function_start_sal (sym, -- funfirstline); -- } -+ if (msym_arr[0] != NULL) -+ return minsym_found (funfirstline, msym_arr[0]); - else - { -- values.sals = NULL; -- values.nelts = 0; -+ sym = sym_arr[0]; -+ -+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK) -+ { -+ values.sals = (struct symtab_and_line *) -+ xmalloc (sizeof (struct symtab_and_line)); -+ values.nelts = 1; -+ values.sals[0] = find_function_start_sal (sym, -+ funfirstline); -+ } -+ else -+ { -+ values.nelts = 0; -+ } -+ return values; - } -- return values; - } - if (i1 > 0) - { - /* There is more than one field with that name - (overloaded). Ask the user which one to use. */ -+ if (msym_arr[0] != NULL) -+ return decode_line_3 (msym_arr, i1, funfirstline, canonical); - return decode_line_2 (sym_arr, i1, funfirstline, canonical); - } - else -@@ -1469,11 +1722,12 @@ find_method (int funfirstline, char ***c - } - - /* Find all methods named COPY in the class whose type is T, and put -- them in SYM_ARR. Return the number of methods found. */ -+ them in SYM_ARR or MSYM_ARR. Return the number of methods found. */ - - static int - collect_methods (char *copy, struct type *t, -- struct symbol *sym_class, struct symbol **sym_arr) -+ struct symbol *sym_class, struct symbol **sym_arr, -+ struct minimal_symbol **msym_arr) - { - int i1 = 0; /* Counter for the symbol array. */ - -@@ -1495,7 +1749,7 @@ collect_methods (char *copy, struct type - } - } - else -- i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr); -+ i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr, msym_arr); - - return i1; - } -@@ -1717,12 +1971,13 @@ decode_dollar (char *copy, int funfirstl - and do not issue an error message. */ - - static struct symtabs_and_lines --decode_variable (char *copy, int funfirstline, char ***canonical, -- struct symtab *file_symtab, int *not_found_ptr) -+decode_variable_1 (char *copy, int funfirstline, char ***canonical, -+ struct symtab *file_symtab) - { - struct symbol *sym; - /* The symtab that SYM was found in. */ - struct symtab *sym_symtab; -+ struct symtabs_and_lines retval; - - struct minimal_symbol *msymbol; - -@@ -1740,8 +1995,25 @@ decode_variable (char *copy, int funfirs - msymbol = lookup_minimal_symbol (copy, NULL, NULL); - - if (msymbol != NULL) -- return minsym_found (funfirstline, msymbol); -+ { -+ retval = minsym_found (funfirstline, msymbol); -+ -+ /* Create a `filename:linkage_symbol_name' reference. */ -+ if (file_symtab == 0) -+ build_canonical_line_spec (retval.sals, SYMBOL_LINKAGE_NAME (msymbol), -+ canonical); - -+ return retval; -+ } -+ -+ retval.nelts = 0; -+ retval.sals = NULL; -+ return retval; -+} -+ -+static void -+decode_variable_not_found (char *copy, int *not_found_ptr) -+{ - if (!have_full_symbols () && - !have_partial_symbols () && !have_minimal_symbols ()) - error (_("No symbol table is loaded. Use the \"file\" command.")); -@@ -1751,6 +2023,132 @@ decode_variable (char *copy, int funfirs - throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy); - } - -+/* Wrapper of DECODE_VARIABLE_1 collecting the results for all the found -+ VARIANTS of the symbol COPY. */ -+ -+static struct symtabs_and_lines -+decode_variable (char *copy, int funfirstline, char ***canonical, -+ struct symtab *file_symtab, int *not_found_ptr) -+{ -+ char *src; -+ char *src_point; -+ char *s, *point; -+ /* Keep "" last as the trimming part always matches it. */ -+ const char *variants[] = {"$base","$allocate","$delete",""}; -+ int i; -+ char *dst, *dst_point; -+ struct -+ { -+ struct symtabs_and_lines sals; -+ char **canonical; -+ } found[ARRAY_SIZE (variants)]; -+ struct symtabs_and_lines retval_sals; -+ char **retval_canonical = NULL; /* Shut up GCC. */ -+ int filled; -+ int canonicals = 0; /* Shut up GCC. */ -+ -+ src = copy; -+ src_point = strchr (src, '('); -+ if (src_point == NULL) -+ { -+ struct symtabs_and_lines sals; -+ -+ sals = decode_variable_1 (src, funfirstline, canonical, file_symtab); -+ if (sals.nelts > 0) -+ return sals; -+ decode_variable_not_found (copy, not_found_ptr); -+ /* NOTREACHED */ -+ } -+ -+ dst = xmalloc (strlen (src) + strlen ("$allocate") + 1); -+ dst_point = dst + (src_point - src); -+ -+ memcpy (dst, src, src_point - src); -+ -+ /* Trim out any variant markers there first. */ -+ for (i = 0; i < ARRAY_SIZE (variants); i++) -+ { -+ size_t len = strlen (variants[i]); -+ -+ if (dst_point - dst >= len -+ && memcmp (dst_point - len, variants[i], len) == 0) -+ { -+ dst_point -= len; -+ /* In fact it should not be needed here. */ -+ break; -+ } -+ } -+ -+ filled = 0; -+ /* And now try to append all of them. */ -+ for (i = 0; i < ARRAY_SIZE (variants); i++) -+ { -+ size_t len = strlen (variants[i]); -+ struct minimal_symbol *minsym2; -+ -+ memcpy (dst_point, variants[i], len); -+ strcpy (dst_point + len, src_point); -+ -+ found[i].canonical = NULL; -+ found[i].sals = decode_variable_1 (dst, funfirstline, -+ (canonical == NULL ? NULL -+ : &found[i].canonical), -+ file_symtab); -+ filled += found[i].sals.nelts; -+ } -+ xfree (dst); -+ if (filled == 0) -+ { -+ decode_variable_not_found (copy, not_found_ptr); -+ /* NOTREACHED */ -+ } -+ -+ retval_sals.nelts = filled; -+ retval_sals.sals = xmalloc (filled * sizeof *retval_sals.sals); -+ if (canonical != NULL) -+ { -+ retval_canonical = xmalloc (filled * sizeof *retval_canonical); -+ canonicals = 0; -+ } -+ filled = 0; -+ for (i = 0; i < ARRAY_SIZE (variants); i++) -+ { -+ memcpy (&retval_sals.sals[filled], found[i].sals.sals, -+ found[i].sals.nelts * sizeof *retval_sals.sals); -+ xfree (found[i].sals.sals); -+ if (canonical != NULL) -+ { -+ if (found[i].canonical == NULL) -+ memset (&retval_canonical[filled], 0, -+ found[i].sals.nelts * sizeof *retval_canonical); -+ else -+ { -+ int j; -+ -+ memcpy (&retval_canonical[filled], found[i].canonical, -+ found[i].sals.nelts * sizeof *retval_canonical); -+ for (j = 0; j < found[i].sals.nelts; j++) -+ if (found[i].canonical[j] != NULL) -+ canonicals++; -+ xfree (found[i].canonical); -+ } -+ } -+ filled += found[i].sals.nelts; -+ } -+ gdb_assert (filled == retval_sals.nelts); -+ -+ if (canonical != NULL) -+ { -+ if (canonicals != 0) -+ *canonical = retval_canonical; -+ else -+ { -+ *canonical = NULL; -+ xfree (retval_canonical); -+ } -+ } -+ return retval_sals; -+} - - - -Index: gdb-6.7/gdb/Makefile.in -=================================================================== ---- gdb-6.7.orig/gdb/Makefile.in 2007-10-13 05:09:50.000000000 +0200 -+++ gdb-6.7/gdb/Makefile.in 2007-10-13 05:15:13.000000000 +0200 -@@ -2233,7 +2233,8 @@ libunwind-frame.o: libunwind-frame.c $(d - linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \ - $(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \ - $(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \ -- $(objc_lang_h) $(linespec_h) $(exceptions_h) $(language_h) -+ $(objc_lang_h) $(linespec_h) $(exceptions_h) $(language_h) \ -+ $(gdb_assert_h) - linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \ - $(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \ - $(linux_nat_h) diff --git a/gdb-6.3-pie-20050110.patch b/gdb-6.3-pie-20050110.patch index e00a671..3bb085f 100644 --- a/gdb-6.3-pie-20050110.patch +++ b/gdb-6.3-pie-20050110.patch @@ -1,7 +1,15 @@ -Index: gdb-6.7/gdb/dwarf2read.c +2007-11-02 Jan Kratochvil + + Port to GDB-6.7.1. + +2007-11-02 Jan Kratochvil + + Port to post-GDB-6.7.1 multi-PC breakpoints. + +Index: gdb-6.7.1/gdb/dwarf2read.c =================================================================== ---- gdb-6.7.orig/gdb/dwarf2read.c 2007-10-13 05:27:15.000000000 +0200 -+++ gdb-6.7/gdb/dwarf2read.c 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/dwarf2read.c 2007-11-02 15:24:10.000000000 +0100 ++++ gdb-6.7.1/gdb/dwarf2read.c 2007-11-02 15:24:19.000000000 +0100 @@ -1226,7 +1226,7 @@ dwarf2_build_psymtabs (struct objfile *o else dwarf2_per_objfile->loc_buffer = NULL; @@ -11,10 +19,10 @@ Index: gdb-6.7/gdb/dwarf2read.c || (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)) { -Index: gdb-6.7/gdb/auxv.c +Index: gdb-6.7.1/gdb/auxv.c =================================================================== ---- gdb-6.7.orig/gdb/auxv.c 2007-08-23 20:08:26.000000000 +0200 -+++ gdb-6.7/gdb/auxv.c 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/auxv.c 2007-08-23 20:08:26.000000000 +0200 ++++ gdb-6.7.1/gdb/auxv.c 2007-11-02 15:24:19.000000000 +0100 @@ -80,7 +80,7 @@ procfs_xfer_auxv (struct target_ops *ops Return 1 if an entry was read into *TYPEP and *VALP. */ int @@ -86,10 +94,10 @@ Index: gdb-6.7/gdb/auxv.c switch (flavor) { case dec: -Index: gdb-6.7/gdb/auxv.h +Index: gdb-6.7.1/gdb/auxv.h =================================================================== ---- gdb-6.7.orig/gdb/auxv.h 2007-08-23 20:08:26.000000000 +0200 -+++ gdb-6.7/gdb/auxv.h 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/auxv.h 2007-08-23 20:08:26.000000000 +0200 ++++ gdb-6.7.1/gdb/auxv.h 2007-11-02 15:24:19.000000000 +0100 @@ -35,14 +35,14 @@ struct target_ops; /* Forward declarati Return 1 if an entry was read into *TYPEP and *VALP. */ extern int target_auxv_parse (struct target_ops *ops, @@ -107,11 +115,11 @@ Index: gdb-6.7/gdb/auxv.h /* Print the contents of the target's AUXV on the specified file. */ extern int fprint_target_auxv (struct ui_file *file, struct target_ops *ops); -Index: gdb-6.7/gdb/breakpoint.h +Index: gdb-6.7.1/gdb/breakpoint.h =================================================================== ---- gdb-6.7.orig/gdb/breakpoint.h 2007-10-13 05:09:50.000000000 +0200 -+++ gdb-6.7/gdb/breakpoint.h 2007-10-13 05:29:58.000000000 +0200 -@@ -153,6 +153,7 @@ enum enable_state +--- gdb-6.7.1.orig/gdb/breakpoint.h 2007-11-02 15:22:24.000000000 +0100 ++++ gdb-6.7.1/gdb/breakpoint.h 2007-11-02 15:24:59.000000000 +0100 +@@ -150,6 +150,7 @@ enum enable_state automatically enabled and reset when the call "lands" (either completes, or stops at another eventpoint). */ @@ -119,23 +127,21 @@ Index: gdb-6.7/gdb/breakpoint.h bp_permanent /* There is a breakpoint instruction hard-wired into the target's code. Don't try to write another breakpoint instruction on top of it, or restore -@@ -807,8 +808,12 @@ extern void remove_thread_event_breakpoi +@@ -826,6 +827,10 @@ extern void remove_thread_event_breakpoi extern void disable_breakpoints_in_shlibs (void); +extern void disable_breakpoints_at_startup (int silent); + - extern void re_enable_breakpoints_in_shlibs (void); - -+void re_enable_breakpoints_at_startup (void); ++extern void re_enable_breakpoints_at_startup (void); + extern void create_solib_load_event_breakpoint (char *, int, char *, char *); extern void create_solib_unload_event_breakpoint (char *, int, -Index: gdb-6.7/gdb/symfile-mem.c +Index: gdb-6.7.1/gdb/symfile-mem.c =================================================================== ---- gdb-6.7.orig/gdb/symfile-mem.c 2007-08-23 20:08:39.000000000 +0200 -+++ gdb-6.7/gdb/symfile-mem.c 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/symfile-mem.c 2007-08-23 20:08:39.000000000 +0200 ++++ gdb-6.7.1/gdb/symfile-mem.c 2007-11-02 15:24:19.000000000 +0100 @@ -108,7 +108,7 @@ symbol_file_add_from_memory (struct bfd } @@ -145,13 +151,13 @@ Index: gdb-6.7/gdb/symfile-mem.c /* This might change our ideas about frames already looked at. */ reinit_frame_cache (); -Index: gdb-6.7/gdb/infrun.c +Index: gdb-6.7.1/gdb/infrun.c =================================================================== ---- gdb-6.7.orig/gdb/infrun.c 2007-10-13 05:09:50.000000000 +0200 -+++ gdb-6.7/gdb/infrun.c 2007-10-13 05:29:58.000000000 +0200 -@@ -2305,6 +2305,11 @@ process_event_stop_test: - code segments in shared libraries might be mapped in now. */ - re_enable_breakpoints_in_shlibs (); +--- gdb-6.7.1.orig/gdb/infrun.c 2007-11-02 15:21:57.000000000 +0100 ++++ gdb-6.7.1/gdb/infrun.c 2007-11-02 15:24:19.000000000 +0100 +@@ -2298,6 +2298,11 @@ process_event_stop_test: + #endif + target_terminal_inferior (); + /* For PIE executables, we dont really know where the + breakpoints are going to be until we start up the @@ -161,10 +167,10 @@ Index: gdb-6.7/gdb/infrun.c /* If requested, stop when the dynamic linker notifies gdb of events. This allows the user to get control and place breakpoints in initializer routines for -Index: gdb-6.7/gdb/objfiles.c +Index: gdb-6.7.1/gdb/objfiles.c =================================================================== ---- gdb-6.7.orig/gdb/objfiles.c 2007-08-23 20:08:36.000000000 +0200 -+++ gdb-6.7/gdb/objfiles.c 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/objfiles.c 2007-08-23 20:08:36.000000000 +0200 ++++ gdb-6.7.1/gdb/objfiles.c 2007-11-02 15:24:19.000000000 +0100 @@ -48,6 +48,9 @@ #include "dictionary.h" #include "source.h" @@ -196,10 +202,10 @@ Index: gdb-6.7/gdb/objfiles.c } /* Create the terminating entry of OBJFILE's minimal symbol table. -Index: gdb-6.7/gdb/solib-svr4.c +Index: gdb-6.7.1/gdb/solib-svr4.c =================================================================== ---- gdb-6.7.orig/gdb/solib-svr4.c 2007-10-12 22:34:03.000000000 +0200 -+++ gdb-6.7/gdb/solib-svr4.c 2007-10-14 23:04:45.000000000 +0200 +--- gdb-6.7.1.orig/gdb/solib-svr4.c 2007-11-02 15:21:46.000000000 +0100 ++++ gdb-6.7.1/gdb/solib-svr4.c 2007-11-02 15:24:19.000000000 +0100 @@ -31,6 +31,8 @@ #include "gdbcore.h" #include "target.h" @@ -355,7 +361,7 @@ Index: gdb-6.7/gdb/solib-svr4.c *ptr = dyn_ptr; } return 1; -@@ -547,6 +638,10 @@ solib_svr4_r_map (void) +@@ -547,6 +642,10 @@ solib_svr4_r_map (void) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); @@ -366,7 +372,7 @@ Index: gdb-6.7/gdb/solib-svr4.c return read_memory_typed_address (debug_base + lmo->r_map_offset, builtin_type_void_data_ptr); } -@@ -704,6 +799,11 @@ svr4_current_sos (void) +@@ -704,6 +803,11 @@ svr4_current_sos (void) struct so_list **link_ptr = &head; CORE_ADDR ldsomap = 0; @@ -378,7 +384,7 @@ Index: gdb-6.7/gdb/solib-svr4.c /* Make sure we've looked up the inferior's dynamic linker's base structure. */ if (! debug_base) -@@ -713,11 +813,21 @@ svr4_current_sos (void) +@@ -713,11 +817,21 @@ svr4_current_sos (void) /* If we can't find the dynamic linker's base structure, this must not be a dynamically linked executable. Hmm. */ if (! debug_base) @@ -401,7 +407,7 @@ Index: gdb-6.7/gdb/solib-svr4.c lm = solib_svr4_r_map (); while (lm) -@@ -733,23 +843,103 @@ svr4_current_sos (void) +@@ -733,23 +847,103 @@ svr4_current_sos (void) new->lm_info->lm = xzalloc (lmo->link_map_size); make_cleanup (xfree, new->lm_info->lm); @@ -506,7 +512,7 @@ Index: gdb-6.7/gdb/solib-svr4.c target_read_string (LM_NAME (new), &buffer, SO_NAME_MAX_PATH_SIZE - 1, &errcode); if (errcode != 0) -@@ -757,23 +947,35 @@ svr4_current_sos (void) +@@ -757,23 +951,35 @@ svr4_current_sos (void) safe_strerror (errcode)); else { @@ -558,7 +564,7 @@ Index: gdb-6.7/gdb/solib-svr4.c } /* On Solaris, the dynamic linker is not in the normal list of -@@ -789,6 +991,11 @@ svr4_current_sos (void) +@@ -789,6 +995,11 @@ svr4_current_sos (void) if (head == NULL) return svr4_default_sos (); @@ -570,7 +576,7 @@ Index: gdb-6.7/gdb/solib-svr4.c return head; } -@@ -868,7 +1075,7 @@ svr4_fetch_objfile_link_map (struct objf +@@ -868,7 +1079,7 @@ svr4_fetch_objfile_link_map (struct objf /* On some systems, the only way to recognize the link map entry for the main executable file is by looking at its name. Return non-zero iff SONAME matches one of the known main executable names. */ @@ -579,7 +585,7 @@ Index: gdb-6.7/gdb/solib-svr4.c static int match_main (char *soname) { -@@ -882,6 +1089,7 @@ match_main (char *soname) +@@ -882,6 +1093,7 @@ match_main (char *soname) return (0); } @@ -587,7 +593,7 @@ Index: gdb-6.7/gdb/solib-svr4.c /* Return 1 if PC lies in the dynamic symbol resolution code of the SVR4 run time loader. */ -@@ -979,6 +1187,11 @@ enable_break (void) +@@ -979,6 +1191,11 @@ enable_break (void) /* Find the .interp section; if not found, warn the user and drop into the old breakpoint at symbol code. */ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); @@ -599,7 +605,7 @@ Index: gdb-6.7/gdb/solib-svr4.c if (interp_sect) { unsigned int interp_sect_size; -@@ -1018,6 +1231,9 @@ enable_break (void) +@@ -1018,6 +1235,9 @@ enable_break (void) if (tmp_fd >= 0) tmp_bfd = bfd_fopen (tmp_pathname, gnutarget, FOPEN_RB, tmp_fd); @@ -609,7 +615,7 @@ Index: gdb-6.7/gdb/solib-svr4.c if (tmp_bfd == NULL) goto bkpt_at_symbol; -@@ -1115,6 +1331,9 @@ enable_break (void) +@@ -1115,6 +1335,9 @@ enable_break (void) if (sym_addr != 0) { create_solib_event_breakpoint (load_addr + sym_addr); @@ -619,7 +625,7 @@ Index: gdb-6.7/gdb/solib-svr4.c return 1; } -@@ -1375,6 +1594,8 @@ svr4_solib_create_inferior_hook (void) +@@ -1375,6 +1598,8 @@ svr4_solib_create_inferior_hook (void) while (stop_signal != TARGET_SIGNAL_TRAP); stop_soon = NO_STOP_QUIETLY; #endif /* defined(_SCO_DS) */ @@ -628,7 +634,7 @@ Index: gdb-6.7/gdb/solib-svr4.c } static void -@@ -1551,6 +1772,75 @@ svr4_lp64_fetch_link_map_offsets (void) +@@ -1551,6 +1776,75 @@ svr4_lp64_fetch_link_map_offsets (void) return lmp; } @@ -704,7 +710,7 @@ Index: gdb-6.7/gdb/solib-svr4.c struct target_so_ops svr4_so_ops; -@@ -1592,4 +1882,8 @@ _initialize_svr4_solib (void) +@@ -1592,4 +1886,8 @@ _initialize_svr4_solib (void) /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ current_target_so_ops = &svr4_so_ops; @@ -713,10 +719,10 @@ Index: gdb-6.7/gdb/solib-svr4.c + "Display the inferior's linkmap."); + } -Index: gdb-6.7/gdb/varobj.c +Index: gdb-6.7.1/gdb/varobj.c =================================================================== ---- gdb-6.7.orig/gdb/varobj.c 2007-08-31 21:01:17.000000000 +0200 -+++ gdb-6.7/gdb/varobj.c 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/varobj.c 2007-08-31 21:01:17.000000000 +0200 ++++ gdb-6.7.1/gdb/varobj.c 2007-11-02 15:24:19.000000000 +0100 @@ -1116,6 +1116,62 @@ install_new_value (struct varobj *var, s return changed; } @@ -780,10 +786,10 @@ Index: gdb-6.7/gdb/varobj.c /* Update the values for a variable and its children. This is a two-pronged attack. First, re-parse the value for the root's expression to see if it's changed. Then go all the way -Index: gdb-6.7/gdb/solist.h +Index: gdb-6.7.1/gdb/solist.h =================================================================== ---- gdb-6.7.orig/gdb/solist.h 2007-08-23 20:08:38.000000000 +0200 -+++ gdb-6.7/gdb/solist.h 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/solist.h 2007-08-23 20:08:38.000000000 +0200 ++++ gdb-6.7.1/gdb/solist.h 2007-11-02 15:24:19.000000000 +0100 @@ -61,6 +61,8 @@ struct so_list bfd *abfd; char symbols_loaded; /* flag: symbols read in yet? */ @@ -816,10 +822,10 @@ Index: gdb-6.7/gdb/solist.h +/* Controls the printing of debugging output. */ +extern int debug_solib; #endif -Index: gdb-6.7/gdb/varobj.h +Index: gdb-6.7.1/gdb/varobj.h =================================================================== ---- gdb-6.7.orig/gdb/varobj.h 2007-08-31 20:52:05.000000000 +0200 -+++ gdb-6.7/gdb/varobj.h 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/varobj.h 2007-08-31 20:52:05.000000000 +0200 ++++ gdb-6.7.1/gdb/varobj.h 2007-11-02 15:24:19.000000000 +0100 @@ -114,4 +114,6 @@ extern int varobj_update (struct varobj extern void varobj_invalidate (void); @@ -827,10 +833,10 @@ Index: gdb-6.7/gdb/varobj.h +extern void varobj_refresh(void); + #endif /* VAROBJ_H */ -Index: gdb-6.7/gdb/symfile.c +Index: gdb-6.7.1/gdb/symfile.c =================================================================== ---- gdb-6.7.orig/gdb/symfile.c 2007-09-24 23:48:05.000000000 +0200 -+++ gdb-6.7/gdb/symfile.c 2007-10-13 05:32:14.000000000 +0200 +--- gdb-6.7.1.orig/gdb/symfile.c 2007-09-24 23:48:05.000000000 +0200 ++++ gdb-6.7.1/gdb/symfile.c 2007-11-02 15:24:19.000000000 +0100 @@ -47,6 +47,7 @@ #include "readline/readline.h" #include "gdb_assert.h" @@ -918,11 +924,11 @@ Index: gdb-6.7/gdb/symfile.c observer_notify_new_objfile (NULL); /* Clear globals which might have pointed into a removed objfile. -Index: gdb-6.7/gdb/breakpoint.c +Index: gdb-6.7.1/gdb/breakpoint.c =================================================================== ---- gdb-6.7.orig/gdb/breakpoint.c 2007-10-13 05:27:15.000000000 +0200 -+++ gdb-6.7/gdb/breakpoint.c 2007-10-13 05:29:58.000000000 +0200 -@@ -840,15 +840,15 @@ insert_watchpoints_for_new_thread (ptid_ +--- gdb-6.7.1.orig/gdb/breakpoint.c 2007-11-02 15:24:10.000000000 +0100 ++++ gdb-6.7.1/gdb/breakpoint.c 2007-11-02 15:26:50.000000000 +0100 +@@ -847,15 +847,15 @@ insert_watchpoints_for_new_thread (ptid_ struct value *v = b->owner->val_chain; /* Look at each value on the value chain. */ @@ -941,7 +947,7 @@ Index: gdb-6.7/gdb/breakpoint.c /* We only watch structs and arrays if user asked for it explicitly, never if they just happen to -@@ -860,8 +860,8 @@ insert_watchpoints_for_new_thread (ptid_ +@@ -867,8 +867,8 @@ insert_watchpoints_for_new_thread (ptid_ CORE_ADDR addr; int len, type; @@ -952,7 +958,7 @@ Index: gdb-6.7/gdb/breakpoint.c type = hw_write; if (b->owner->type == bp_read_watchpoint) type = hw_read; -@@ -2749,12 +2749,12 @@ mark_triggered_watchpoints (CORE_ADDR st +@@ -2767,12 +2767,12 @@ mark_triggered_watchpoints (CORE_ADDR st || b->type == bp_read_watchpoint || b->type == bp_access_watchpoint) { @@ -968,7 +974,7 @@ Index: gdb-6.7/gdb/breakpoint.c if (v == b->val_chain || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT -@@ -2762,11 +2762,11 @@ mark_triggered_watchpoints (CORE_ADDR st +@@ -2780,11 +2780,11 @@ mark_triggered_watchpoints (CORE_ADDR st { CORE_ADDR vaddr; @@ -982,7 +988,7 @@ Index: gdb-6.7/gdb/breakpoint.c b->watchpoint_triggered = 1; } } -@@ -2936,12 +2936,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p +@@ -2957,12 +2957,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p bs->stop = 0; continue; } @@ -998,7 +1004,7 @@ Index: gdb-6.7/gdb/breakpoint.c if (v == b->val_chain || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT -@@ -2949,11 +2949,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p +@@ -2970,11 +2970,11 @@ bpstat_stop_status (CORE_ADDR bp_addr, p { CORE_ADDR vaddr; @@ -1012,15 +1018,17 @@ Index: gdb-6.7/gdb/breakpoint.c must_check_value = 1; } } -@@ -3996,6 +3996,7 @@ describe_other_breakpoints (CORE_ADDR pc - printf_filtered ("%s%s ", - ((b->enable_state == bp_disabled || - b->enable_state == bp_shlib_disabled || -+ b->enable_state == bp_startup_disabled || - b->enable_state == bp_call_disabled) - ? " (disabled)" - : b->enable_state == bp_permanent -@@ -4669,6 +4670,62 @@ re_enable_breakpoints_in_shlibs (void) +@@ -4118,7 +4118,8 @@ describe_other_breakpoints (CORE_ADDR pc + printf_filtered (" (thread %d)", b->thread); + printf_filtered ("%s%s ", + ((b->enable_state == bp_disabled || +- b->enable_state == bp_call_disabled) ++ b->enable_state == bp_call_disabled || ++ b->enable_state == bp_startup_disabled) + ? " (disabled)" + : b->enable_state == bp_permanent + ? " (permanent)" +@@ -4773,6 +4774,62 @@ disable_breakpoints_in_unloaded_shlib (s } } @@ -1083,28 +1091,10 @@ Index: gdb-6.7/gdb/breakpoint.c static void solib_load_unload_1 (char *hookname, int tempflag, char *dll_pathname, char *cond_string, enum bptype bp_kind) -@@ -7084,6 +7141,7 @@ delete_breakpoint (struct breakpoint *bp - && !b->loc->duplicate - && b->enable_state != bp_disabled - && b->enable_state != bp_shlib_disabled -+ && b->enable_state != bp_startup_disabled - && !b->pending - && b->enable_state != bp_call_disabled) - { -@@ -7308,7 +7366,8 @@ breakpoint_re_set_one (void *bint) - break; - - save_enable = b->enable_state; -- if (b->enable_state != bp_shlib_disabled) -+ if (b->enable_state != bp_shlib_disabled -+ || b->enable_state != bp_shlib_disabled) - b->enable_state = bp_disabled; - else - /* If resetting a shlib-disabled breakpoint, we don't want to -Index: gdb-6.7/gdb/solib.c +Index: gdb-6.7.1/gdb/solib.c =================================================================== ---- gdb-6.7.orig/gdb/solib.c 2007-08-23 20:08:38.000000000 +0200 -+++ gdb-6.7/gdb/solib.c 2007-10-13 05:32:46.000000000 +0200 +--- gdb-6.7.1.orig/gdb/solib.c 2007-08-23 20:08:38.000000000 +0200 ++++ gdb-6.7.1/gdb/solib.c 2007-11-02 15:24:19.000000000 +0100 @@ -78,6 +78,8 @@ set_solib_ops (struct gdbarch *gdbarch, /* external data declarations */ @@ -1279,10 +1269,10 @@ Index: gdb-6.7/gdb/solib.c + NULL, NULL, + &setdebuglist, &showdebuglist); } -Index: gdb-6.7/gdb/elfread.c +Index: gdb-6.7.1/gdb/elfread.c =================================================================== ---- gdb-6.7.orig/gdb/elfread.c 2007-08-23 20:08:28.000000000 +0200 -+++ gdb-6.7/gdb/elfread.c 2007-10-13 05:29:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/elfread.c 2007-08-23 20:08:28.000000000 +0200 ++++ gdb-6.7.1/gdb/elfread.c 2007-11-02 15:24:19.000000000 +0100 @@ -611,7 +611,7 @@ elf_symfile_read (struct objfile *objfil /* If we are reinitializing, or if we have never loaded syms yet, set table to empty. MAINLINE is cleared so that *_read_psymtab @@ -1292,15 +1282,11 @@ Index: gdb-6.7/gdb/elfread.c { init_psymbol_list (objfile, 0); mainline = 0; - -2007-10-31 Jan Kratochvil - - Port to GDB-6.7 - workaround too early breakpoint address analysis. - -diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7-orig/gdb/Makefile.in gdb-6.7-patched/gdb/Makefile.in ---- gdb-6.7-orig/gdb/Makefile.in 2007-10-31 12:50:10.000000000 +0100 -+++ gdb-6.7-patched/gdb/Makefile.in 2007-10-31 00:38:11.000000000 +0100 -@@ -1824,7 +1824,7 @@ amd64-tdep.o: amd64-tdep.c $(defs_h) $(a +Index: gdb-6.7.1/gdb/Makefile.in +=================================================================== +--- gdb-6.7.1.orig/gdb/Makefile.in 2007-11-02 15:24:10.000000000 +0100 ++++ gdb-6.7.1/gdb/Makefile.in 2007-11-02 15:24:19.000000000 +0100 +@@ -1819,7 +1819,7 @@ amd64-tdep.o: amd64-tdep.c $(defs_h) $(a $(dummy_frame_h) $(frame_h) $(frame_base_h) $(frame_unwind_h) \ $(inferior_h) $(gdbcmd_h) $(gdbcore_h) $(objfiles_h) $(regcache_h) \ $(regset_h) $(symfile_h) $(gdb_assert_h) $(amd64_tdep_h) \ @@ -1309,9 +1295,10 @@ diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7-orig/gdb/Makefile.in gdb-6.7- annotate.o: annotate.c $(defs_h) $(annotate_h) $(value_h) $(target_h) \ $(gdbtypes_h) $(breakpoint_h) arch-utils.o: arch-utils.c $(defs_h) $(arch_utils_h) $(buildsym_h) \ -diff -u -X /home/jkratoch/.diffi.list -rup gdb-6.7-orig/gdb/amd64-tdep.c gdb-6.7-patched/gdb/amd64-tdep.c ---- gdb-6.7-orig/gdb/amd64-tdep.c 2007-10-31 12:50:09.000000000 +0100 -+++ gdb-6.7-patched/gdb/amd64-tdep.c 2007-10-31 00:46:13.000000000 +0100 +Index: gdb-6.7.1/gdb/amd64-tdep.c +=================================================================== +--- gdb-6.7.1.orig/gdb/amd64-tdep.c 2007-11-02 15:21:46.000000000 +0100 ++++ gdb-6.7.1/gdb/amd64-tdep.c 2007-11-02 15:24:19.000000000 +0100 @@ -36,6 +36,7 @@ #include "symfile.h" #include "dwarf2-frame.h" diff --git a/gdb-6.3-test-dtorfix-20050121.patch b/gdb-6.3-test-dtorfix-20050121.patch deleted file mode 100644 index 65de72a..0000000 --- a/gdb-6.3-test-dtorfix-20050121.patch +++ /dev/null @@ -1,276 +0,0 @@ -[base] - -2007-10-14 Jan Kratochvil - - Port to GDB-6.7. - -Index: gdb-6.7/gdb/testsuite/gdb.cp/constructortest.cc -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.7/gdb/testsuite/gdb.cp/constructortest.cc 2007-10-14 23:29:48.000000000 +0200 -@@ -0,0 +1,99 @@ -+/* This testcase is part of GDB, the GNU debugger. -+ -+ Copyright 2005 Free Software Foundation, Inc. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 59 Temple Place - Suite 330, -+ Boston, MA 02111-1307, USA. */ -+ -+class A -+{ -+ public: -+ A(); -+ ~A(); -+ int k; -+ private: -+ int x; -+}; -+ -+class B: public A -+{ -+ public: -+ B(); -+ private: -+ int y; -+}; -+ -+/* C and D are for the $delete destructor. */ -+ -+class C -+{ -+ public: -+ C(); -+ virtual ~C(); -+ private: -+ int x; -+}; -+ -+class D: public C -+{ -+ public: -+ D(); -+ private: -+ int y; -+}; -+ -+int main(int argc, char *argv[]) -+{ -+ A* a = new A; -+ B* b = new B; -+ D* d = new D; -+ delete a; -+ delete b; -+ delete d; -+ return 0; -+} -+ -+A::A() /* Constructor A */ -+{ -+ x = 1; /* First line A */ -+ k = 4; /* Second line A */ -+} -+ -+A::~A() /* Destructor A */ -+{ -+ x = 3; /* First line ~A */ -+ k = 6; /* Second line ~A */ -+} -+ -+B::B() -+{ -+ y = 2; /* First line B */ -+ k = 5; -+} -+ -+C::C() /* Constructor C */ -+{ -+ x = 1; /* First line C */ -+} -+ -+C::~C() /* Destructor C */ -+{ -+ x = 3; /* First line ~C */ -+} -+ -+D::D() -+{ -+ y = 2; /* First line D */ -+} -Index: gdb-6.7/gdb/testsuite/gdb.cp/constructortest.exp -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ gdb-6.7/gdb/testsuite/gdb.cp/constructortest.exp 2007-10-14 23:29:48.000000000 +0200 -@@ -0,0 +1,148 @@ -+# This testcase is part of GDB, the GNU debugger. -+ -+# Copyright 2005, 2007 Free Software Foundation, Inc. -+ -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ -+# Check that GDB can break at multiple forms of constructors. -+ -+if $tracelevel { -+ strace $tracelevel -+} -+ -+set prms_id 0 -+set bug_id 0 -+ -+set testfile "constructortest" -+set srcfile ${testfile}.cc -+set binfile ${objdir}/${subdir}/${testfile} -+# PIE is required for testing proper BREAKPOINT_RE_SET of the multiple-PC -+# breakpoints. -+if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++ "additional_flags=-fpie -pie"}] != "" } { -+ return -1 -+} -+ -+gdb_exit -+gdb_start -+gdb_reinitialize_dir $srcdir/$subdir -+gdb_load ${binfile} -+ -+# -+# Run to `main' where we begin our tests. -+# -+ -+if ![runto_main] then { -+ gdb_suppress_tests -+} -+ -+# Break on the various forms of the A::A constructor -+gdb_test_multiple "break A\:\:A" "breaking on A::A" { -+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. A::A\\(\\) at .*\[\r\n\]*.3. A::A\\\$base\\(\\) at .*\[\r\n\]*> $" { -+ gdb_test "1" \ -+ ".*Multiple breakpoints were set.*" \ -+ "break on multiple constructors" -+ } -+} -+ -+# Verify that we break for the A constructor two times -+# Once for new A and once for new B -+gdb_continue_to_breakpoint "First line A" -+gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in in-charge A::A" -+gdb_continue_to_breakpoint "First line A" -+gdb_test "bt" "#0.*A.*#1.*B.*#2.*main.*" "Verify in not-in-charge A::A" -+ -+# Now do the same for destructors -+gdb_test "break 'A::~A()'" "" -+gdb_test "break 'A::~A\$base()'" "" -+ -+# Verify that we break for the A destructor two times -+# Once for delete a and once for delete b -+gdb_continue_to_breakpoint "First line ~A" -+gdb_test "bt" "#0.*~A.*#1.*main.*" "Verify in in-charge A::~A" -+gdb_continue_to_breakpoint "First line ~A" -+gdb_test "bt" "#0.*~A.*#1.*~B.*#2.*main.*" "Verify in not-in-charge A::~A" -+ -+ -+# Verify that we can break by line number in a constructor and find -+# both occurrences -+runto_main -+gdb_test "break 'A::A()'" "" "break in constructor A 2" -+gdb_continue_to_breakpoint "First line A" -+set second_line [gdb_get_line_number "Second line A"] -+gdb_test "break $second_line" ".*$second_line.*$second_line.*Multiple breakpoints were set.*" "break by line in constructor" -+gdb_continue_to_breakpoint "Second line A" -+gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in in-charge A::A second line" -+gdb_continue_to_breakpoint "Second line A" -+gdb_test "bt" "#0.*A.*#1.*B.*#2.*main.*" "Verify in not-in-charge A::A second line" -+ -+# Verify that we can break by line number in a destructor and find -+# both occurrences -+gdb_test "break 'A::~A()'" "" "break in constructor ~A 2" -+gdb_continue_to_breakpoint "First line ~A" -+set second_line_dtor [gdb_get_line_number "Second line ~A"] -+gdb_test "break $second_line_dtor" ".*$second_line_dtor.*$second_line_dtor.*Multiple breakpoints were set.*" "break by line in destructor" -+gdb_continue_to_breakpoint "Second line ~A" -+gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in in-charge A::~A second line" -+# FIXME: Analyse this case better. -+gdb_continue_to_breakpoint "Second line ~A" -+gdb_test "bt" "#0.*A.*#1.*main.*" "Verify in A::~A second line #2" -+gdb_continue_to_breakpoint "Second line ~A" -+gdb_test "bt" "#0.*A.*#1.*B.*#2.*main.*" "Verify in not-in-charge A::~A second line" -+ -+ -+# Test now the $delete destructors. -+ -+gdb_load ${binfile} -+runto_main -+ -+# Break on the various forms of the C::~C destructor -+set test "breaking on C::~C" -+gdb_test_multiple "break C\:\:~C" $test { -+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. C::~C\\(\\) at .*\[\r\n\]*.3. C::~C\\\$base\\(\\) at .*\[\r\n\]*4. C::~C\\\$delete\\(\\) at .*\[\r\n\]*> $" { -+ gdb_test "1" \ -+ ".*Multiple breakpoints were set.*" \ -+ "break on multiple constructors" -+ } -+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*> $" { -+ fail $test -+ } -+} -+gdb_continue_to_breakpoint "First line ~C" -+ -+# Verify that we can break by line number in a destructor and find -+# the $delete occurence -+ -+gdb_load ${binfile} -+delete_breakpoints -+ -+set first_line_dtor [gdb_get_line_number "First line ~C"] -+gdb_test "break $first_line_dtor" ".*$first_line_dtor.*$first_line_dtor.*Multiple breakpoints were set.*" "break by line in destructor" -+ -+# Run to `main' where we begin our tests. -+# Set the breakpoints first to test PIE multiple-PC BREAKPOINT_RE_SET. -+# RUNTO_MAIN or RUNTO MAIN are not usable here as it runs DELETE_BREAKPOINTS. -+ -+if ![gdb_breakpoint main] { -+ gdb_suppress_tests -+} -+gdb_run_cmd -+set test "running to main" -+gdb_test_multiple "" $test { -+ -re "Breakpoint \[0-9\]*, main .*$gdb_prompt $" { -+ pass $test -+ } -+} -+ -+gdb_continue_to_breakpoint "First line ~C" -Index: gdb-6.7/gdb/testsuite/gdb.cp/templates.exp -=================================================================== ---- gdb-6.7.orig/gdb/testsuite/gdb.cp/templates.exp 2007-08-23 20:14:17.000000000 +0200 -+++ gdb-6.7/gdb/testsuite/gdb.cp/templates.exp 2007-10-14 23:29:48.000000000 +0200 -@@ -142,7 +142,7 @@ proc test_template_breakpoints {} { - # See CLLbs14792 - if {$hp_aCC_compiler} {setup_xfail hppa*-*-* CLLbs14792} - -- gdb_test_multiple "break T5::~T5" "destructor_breakpoint" { -+ gdb_test_multiple "break 'T5::~T5()'" "destructor_breakpoint" { - -re "Breakpoint.*at.* file .*${testfile}.cc, line.*$gdb_prompt $" - { - pass "destructor breakpoint" diff --git a/gdb-6.3-test-pie-20050107.patch b/gdb-6.3-test-pie-20050107.patch index be1c9e9..1a0643d 100644 --- a/gdb-6.3-test-pie-20050107.patch +++ b/gdb-6.3-test-pie-20050107.patch @@ -2,6 +2,10 @@ Port to GDB-6.7. +2007-11-02 Jan Kratochvil + + Port to post-GDB-6.7.1 multi-PC breakpoints. + Index: gdb-6.7/gdb/testsuite/configure.ac =================================================================== --- gdb-6.7.orig/gdb/testsuite/configure.ac 2007-08-23 19:58:44.000000000 +0200 @@ -1059,7 +1063,7 @@ Index: gdb-6.7/gdb/testsuite/gdb.pie/break.exp +set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1] + +gdb_test "info break" \ -+ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++ "Num\[\t \]+Type\[\t \]+Disp\[\t \]+Enb\[\t \]+Address\[ \]+What.* +\[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.* +\[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile1:($bp_location8|$bp_location9).* +\[0-9\]+\[\t \]+breakpoint keep y.* in factorial$proto at .*$srcfile:$bp_location7.* @@ -1189,7 +1193,7 @@ Index: gdb-6.7/gdb/testsuite/gdb.pie/break.exp +# +# check to see what breakpoints are set (temporary this time) +# -+gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\] ++gdb_test "info break" "Num\[\t \]+Type.*Disp\[\t \]+Enb\[\t \]+Address.*What.*\[\r\n\] +\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\] +\[0-9\]+\[\t \]+breakpoint del.*y.*in factorial$proto at .*$srcfile:$bp_location7.*\[\r\n\] +\[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\] diff --git a/gdb-6.3-threaded-watchpoints-20041213.patch b/gdb-6.3-threaded-watchpoints-20041213.patch index 0e9f97d..26780cc 100644 --- a/gdb-6.3-threaded-watchpoints-20041213.patch +++ b/gdb-6.3-threaded-watchpoints-20041213.patch @@ -32,10 +32,14 @@ Port to GDB-6.7. -Index: gdb-6.7/gdb/doc/observer.texi +2007-11-02 Jan Kratochvil + + Port to post-GDB-6.7.1 multi-PC breakpoints. + +Index: gdb-6.7.1/gdb/doc/observer.texi =================================================================== ---- gdb-6.7.orig/gdb/doc/observer.texi 2007-05-11 21:55:20.000000000 +0200 -+++ gdb-6.7/gdb/doc/observer.texi 2007-10-13 04:51:21.000000000 +0200 +--- gdb-6.7.1.orig/gdb/doc/observer.texi 2007-05-11 21:55:20.000000000 +0200 ++++ gdb-6.7.1/gdb/doc/observer.texi 2007-11-02 15:21:57.000000000 +0100 @@ -129,3 +129,12 @@ Called with @var{objfile} equal to @code previously loaded symbol table data has now been invalidated. @end deftypefun @@ -49,11 +53,11 @@ Index: gdb-6.7/gdb/doc/observer.texi +A low-level SIGTRAP has been discovered. This notification can be used to save +additional state necessary if the trap is deferred for later handling. +@end deftypefun -Index: gdb-6.7/gdb/infrun.c +Index: gdb-6.7.1/gdb/infrun.c =================================================================== ---- gdb-6.7.orig/gdb/infrun.c 2007-10-12 22:35:58.000000000 +0200 -+++ gdb-6.7/gdb/infrun.c 2007-10-13 04:50:11.000000000 +0200 -@@ -1784,9 +1784,19 @@ handle_inferior_event (struct execution_ +--- gdb-6.7.1.orig/gdb/infrun.c 2007-11-02 15:21:46.000000000 +0100 ++++ gdb-6.7.1/gdb/infrun.c 2007-11-02 15:21:57.000000000 +0100 +@@ -1781,9 +1781,19 @@ handle_inferior_event (struct execution_ single step over a watchpoint without disabling the watchpoint. */ if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws)) { @@ -74,7 +78,7 @@ Index: gdb-6.7/gdb/infrun.c prepare_to_wait (ecs); return; } -@@ -1797,6 +1807,8 @@ handle_inferior_event (struct execution_ +@@ -1794,6 +1804,8 @@ handle_inferior_event (struct execution_ if (gdbarch_have_nonsteppable_watchpoint (current_gdbarch) && STOPPED_BY_WATCHPOINT (ecs->ws)) { @@ -83,7 +87,7 @@ Index: gdb-6.7/gdb/infrun.c /* At this point, we are stopped at an instruction which has attempted to write to a piece of memory under control of a watchpoint. The instruction hasn't actually executed -@@ -1804,15 +1816,12 @@ handle_inferior_event (struct execution_ +@@ -1801,15 +1813,12 @@ handle_inferior_event (struct execution_ now, we would get the old value, and therefore no change would seem to have occurred. @@ -105,7 +109,7 @@ Index: gdb-6.7/gdb/infrun.c if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n"); -@@ -1883,6 +1892,41 @@ handle_inferior_event (struct execution_ +@@ -1880,6 +1889,41 @@ handle_inferior_event (struct execution_ } } @@ -147,7 +151,7 @@ Index: gdb-6.7/gdb/infrun.c /* Look at the cause of the stop, and decide what to do. The alternatives are: 1) break; to really stop and return to the debugger, -@@ -1935,6 +1979,8 @@ handle_inferior_event (struct execution_ +@@ -1932,6 +1976,8 @@ handle_inferior_event (struct execution_ See more comments in inferior.h. */ if (stop_soon == STOP_QUIETLY_NO_SIGSTOP) { @@ -156,11 +160,11 @@ Index: gdb-6.7/gdb/infrun.c stop_stepping (ecs); if (stop_signal == TARGET_SIGNAL_STOP) stop_signal = TARGET_SIGNAL_0; -Index: gdb-6.7/gdb/breakpoint.c +Index: gdb-6.7.1/gdb/breakpoint.c =================================================================== ---- gdb-6.7.orig/gdb/breakpoint.c 2007-08-30 00:07:47.000000000 +0200 -+++ gdb-6.7/gdb/breakpoint.c 2007-10-13 04:50:11.000000000 +0200 -@@ -806,6 +806,90 @@ insert_catchpoint (struct ui_out *uo, vo +--- gdb-6.7.1.orig/gdb/breakpoint.c 2007-11-02 15:21:45.000000000 +0100 ++++ gdb-6.7.1/gdb/breakpoint.c 2007-11-02 15:23:04.000000000 +0100 +@@ -813,6 +813,90 @@ insert_catchpoint (struct ui_out *uo, vo } } @@ -251,7 +255,7 @@ Index: gdb-6.7/gdb/breakpoint.c /* Helper routine: free the value chain for a breakpoint (watchpoint). */ static void -@@ -1294,6 +1378,7 @@ remove_breakpoints (void) +@@ -1301,6 +1385,7 @@ remove_breakpoints (void) { struct bp_location *b; int val; @@ -259,7 +263,7 @@ Index: gdb-6.7/gdb/breakpoint.c ALL_BP_LOCATIONS (b) { -@@ -1301,10 +1386,10 @@ remove_breakpoints (void) +@@ -1308,10 +1393,10 @@ remove_breakpoints (void) { val = remove_breakpoint (b, mark_uninserted); if (val != 0) @@ -272,7 +276,7 @@ Index: gdb-6.7/gdb/breakpoint.c } int -@@ -2187,8 +2272,13 @@ print_it_typical (bpstat bs) +@@ -2200,8 +2285,13 @@ print_it_typical (bpstat bs) break; case bp_thread_event: @@ -288,7 +292,7 @@ Index: gdb-6.7/gdb/breakpoint.c printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n")); return PRINT_NOTHING; break; -@@ -2636,6 +2726,54 @@ which its expression is valid.\n"); +@@ -2654,6 +2744,54 @@ which its expression is valid.\n"); } } @@ -343,7 +347,7 @@ Index: gdb-6.7/gdb/breakpoint.c /* Get a bpstat associated with having just stopped at address BP_ADDR in thread PTID. STOPPED_BY_WATCHPOINT is 1 if the target thinks we stopped due to a hardware watchpoint, 0 if we -@@ -2766,82 +2904,61 @@ bpstat_stop_status (CORE_ADDR bp_addr, p +@@ -2787,82 +2925,61 @@ bpstat_stop_status (CORE_ADDR bp_addr, p bs->stop = 1; bs->print = 1; @@ -471,7 +475,7 @@ Index: gdb-6.7/gdb/breakpoint.c { char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", b->number); -@@ -2870,6 +2987,15 @@ bpstat_stop_status (CORE_ADDR bp_addr, p +@@ -2891,6 +3008,15 @@ bpstat_stop_status (CORE_ADDR bp_addr, p break; case WP_VALUE_NOT_CHANGED: /* Stop. */ @@ -487,7 +491,7 @@ Index: gdb-6.7/gdb/breakpoint.c ++(b->hit_count); break; default: -@@ -2885,7 +3011,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p +@@ -2906,7 +3032,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, p break; } } @@ -496,22 +500,22 @@ Index: gdb-6.7/gdb/breakpoint.c { /* This is a case where some watchpoint(s) triggered, but not at the address of this watchpoint (FOUND -@@ -4186,6 +4312,7 @@ set_raw_breakpoint (struct symtab_and_li +@@ -4292,6 +4418,7 @@ set_raw_breakpoint_without_location (enu b->exec_pathname = NULL; b->ops = NULL; - b->pending = 0; + b->condition_not_parsed = 0; + b->watchpoint_triggered = 0; /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order -Index: gdb-6.7/gdb/breakpoint.h +Index: gdb-6.7.1/gdb/breakpoint.h =================================================================== ---- gdb-6.7.orig/gdb/breakpoint.h 2007-08-23 20:08:26.000000000 +0200 -+++ gdb-6.7/gdb/breakpoint.h 2007-10-13 04:50:11.000000000 +0200 -@@ -420,6 +420,11 @@ struct breakpoint - - /* Is breakpoint pending on shlib loads? */ - int pending; +--- gdb-6.7.1.orig/gdb/breakpoint.h 2007-11-02 15:21:45.000000000 +0100 ++++ gdb-6.7.1/gdb/breakpoint.h 2007-11-02 15:22:24.000000000 +0100 +@@ -439,6 +439,11 @@ struct breakpoint + no location initially so had no context to parse + the condition in. */ + int condition_not_parsed; + + /* Has a watchpoint been triggered? This is only used for + non-continuable watchpoints which trigger prior to the data @@ -520,7 +524,7 @@ Index: gdb-6.7/gdb/breakpoint.h }; /* The following stuff is an abstract data type "bpstat" ("breakpoint -@@ -688,6 +693,14 @@ extern void tbreak_command (char *, int) +@@ -707,6 +712,14 @@ extern void tbreak_command (char *, int) extern int insert_breakpoints (void); @@ -535,10 +539,10 @@ Index: gdb-6.7/gdb/breakpoint.h extern int remove_breakpoints (void); /* This function can be used to physically insert eventpoints from the -Index: gdb-6.7/gdb/linux-nat.c +Index: gdb-6.7.1/gdb/linux-nat.c =================================================================== ---- gdb-6.7.orig/gdb/linux-nat.c 2007-10-12 22:35:58.000000000 +0200 -+++ gdb-6.7/gdb/linux-nat.c 2007-10-13 04:50:11.000000000 +0200 +--- gdb-6.7.1.orig/gdb/linux-nat.c 2007-11-02 15:21:46.000000000 +0100 ++++ gdb-6.7.1/gdb/linux-nat.c 2007-11-02 15:21:57.000000000 +0100 @@ -34,6 +34,7 @@ #include "gdbthread.h" #include "gdbcmd.h" @@ -586,10 +590,10 @@ Index: gdb-6.7/gdb/linux-nat.c /* Handle GNU/Linux's extended waitstatus for trace events. */ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0) { -Index: gdb-6.7/gdb/linux-nat.h +Index: gdb-6.7.1/gdb/linux-nat.h =================================================================== ---- gdb-6.7.orig/gdb/linux-nat.h 2007-10-12 22:35:58.000000000 +0200 -+++ gdb-6.7/gdb/linux-nat.h 2007-10-13 04:50:11.000000000 +0200 +--- gdb-6.7.1.orig/gdb/linux-nat.h 2007-11-02 15:21:46.000000000 +0100 ++++ gdb-6.7.1/gdb/linux-nat.h 2007-11-02 15:21:57.000000000 +0100 @@ -61,6 +61,18 @@ struct lwp_info /* Next LWP in list. */ @@ -609,10 +613,10 @@ Index: gdb-6.7/gdb/linux-nat.h }; /* Attempt to initialize libthread_db. */ -Index: gdb-6.7/gdb/Makefile.in +Index: gdb-6.7.1/gdb/Makefile.in =================================================================== ---- gdb-6.7.orig/gdb/Makefile.in 2007-09-05 02:14:02.000000000 +0200 -+++ gdb-6.7/gdb/Makefile.in 2007-10-13 04:50:53.000000000 +0200 +--- gdb-6.7.1.orig/gdb/Makefile.in 2007-09-05 02:14:02.000000000 +0200 ++++ gdb-6.7.1/gdb/Makefile.in 2007-11-02 15:21:57.000000000 +0100 @@ -2160,7 +2160,7 @@ i387-tdep.o: i387-tdep.c $(defs_h) $(dou $(gdb_assert_h) $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h) ia64-linux-nat.o: ia64-linux-nat.c $(defs_h) $(gdb_string_h) $(inferior_h) \ @@ -631,10 +635,10 @@ Index: gdb-6.7/gdb/Makefile.in s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \ $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) \ $(floatformat_h) $(regcache_h) $(trad_frame_h) $(frame_base_h) \ -Index: gdb-6.7/gdb/linux-thread-db.c +Index: gdb-6.7.1/gdb/linux-thread-db.c =================================================================== ---- gdb-6.7.orig/gdb/linux-thread-db.c 2007-08-23 20:08:35.000000000 +0200 -+++ gdb-6.7/gdb/linux-thread-db.c 2007-10-13 04:53:59.000000000 +0200 +--- gdb-6.7.1.orig/gdb/linux-thread-db.c 2007-08-23 20:08:35.000000000 +0200 ++++ gdb-6.7.1/gdb/linux-thread-db.c 2007-11-02 15:21:57.000000000 +0100 @@ -34,6 +34,7 @@ #include "target.h" #include "regcache.h" @@ -685,10 +689,10 @@ Index: gdb-6.7/gdb/linux-thread-db.c /* Check for a thread event. */ check_event (ptid); -Index: gdb-6.7/gdb/i386-linux-nat.c +Index: gdb-6.7.1/gdb/i386-linux-nat.c =================================================================== ---- gdb-6.7.orig/gdb/i386-linux-nat.c 2007-08-23 20:08:34.000000000 +0200 -+++ gdb-6.7/gdb/i386-linux-nat.c 2007-10-13 04:50:11.000000000 +0200 +--- gdb-6.7.1.orig/gdb/i386-linux-nat.c 2007-08-23 20:08:34.000000000 +0200 ++++ gdb-6.7.1/gdb/i386-linux-nat.c 2007-11-02 15:21:57.000000000 +0100 @@ -585,10 +585,9 @@ i386_linux_dr_get (int regnum) int tid; unsigned long value; @@ -717,10 +721,10 @@ Index: gdb-6.7/gdb/i386-linux-nat.c errno = 0; ptrace (PTRACE_POKEUSER, tid, -Index: gdb-6.7/gdb/ia64-linux-nat.c +Index: gdb-6.7.1/gdb/ia64-linux-nat.c =================================================================== ---- gdb-6.7.orig/gdb/ia64-linux-nat.c 2007-08-23 20:08:35.000000000 +0200 -+++ gdb-6.7/gdb/ia64-linux-nat.c 2007-10-13 05:07:58.000000000 +0200 +--- gdb-6.7.1.orig/gdb/ia64-linux-nat.c 2007-08-23 20:08:35.000000000 +0200 ++++ gdb-6.7.1/gdb/ia64-linux-nat.c 2007-11-02 15:21:57.000000000 +0100 @@ -27,6 +27,7 @@ #include "regcache.h" #include "ia64-tdep.h" @@ -912,10 +916,10 @@ Index: gdb-6.7/gdb/ia64-linux-nat.c + observer_attach_linux_new_thread (ia64_linux_new_thread); + observer_attach_sigtrap (ia64_linux_save_sigtrap_info); } -Index: gdb-6.7/gdb/amd64-linux-nat.c +Index: gdb-6.7.1/gdb/amd64-linux-nat.c =================================================================== ---- gdb-6.7.orig/gdb/amd64-linux-nat.c 2007-08-23 20:08:26.000000000 +0200 -+++ gdb-6.7/gdb/amd64-linux-nat.c 2007-10-13 04:50:11.000000000 +0200 +--- gdb-6.7.1.orig/gdb/amd64-linux-nat.c 2007-08-23 20:08:26.000000000 +0200 ++++ gdb-6.7.1/gdb/amd64-linux-nat.c 2007-11-02 15:21:57.000000000 +0100 @@ -240,10 +240,9 @@ amd64_linux_dr_get (int regnum) int tid; unsigned long value; @@ -944,10 +948,10 @@ Index: gdb-6.7/gdb/amd64-linux-nat.c errno = 0; ptrace (PT_WRITE_U, tid, offsetof (struct user, u_debugreg[regnum]), value); -Index: gdb-6.7/gdb/s390-nat.c +Index: gdb-6.7.1/gdb/s390-nat.c =================================================================== ---- gdb-6.7.orig/gdb/s390-nat.c 2007-08-23 20:08:37.000000000 +0200 -+++ gdb-6.7/gdb/s390-nat.c 2007-10-13 04:50:11.000000000 +0200 +--- gdb-6.7.1.orig/gdb/s390-nat.c 2007-08-23 20:08:37.000000000 +0200 ++++ gdb-6.7.1/gdb/s390-nat.c 2007-11-02 15:21:57.000000000 +0100 @@ -27,6 +27,7 @@ #include "linux-nat.h" diff --git a/gdb-6.3-xfree-20050922.patch b/gdb-6.3-xfree-20050922.patch deleted file mode 100644 index a5e59ee..0000000 --- a/gdb-6.3-xfree-20050922.patch +++ /dev/null @@ -1,21 +0,0 @@ -2005-09-22 Bastien Nocera - - * symtab.c (find_line_pc_range): Don't free up pc_list - unconditionally as it may not be allocated. - ---- gdb-6.3/gdb/symtab.c.fix 2005-09-22 16:24:06.000000000 -0400 -+++ gdb-6.3/gdb/symtab.c 2005-09-22 16:26:17.000000000 -0400 -@@ -2427,9 +2427,10 @@ find_line_pc_range (struct symtab_and_li - /* FIXME: have to handle ctors/dtors where line equates to multiple - pc ranges. */ - if (startaddr == 0) -- startaddr = pc_list[0]; -- -- xfree (pc_list); -+ { -+ startaddr = pc_list[0]; -+ xfree (pc_list); -+ } - - /* This whole function is based on address. For example, if line 10 has - two parts, one from 0x100 to 0x200 and one from 0x300 to 0x400, then diff --git a/gdb-6.5-bz200048-find_line_pc-segv.patch b/gdb-6.5-bz200048-find_line_pc-segv.patch deleted file mode 100644 index 26cc5ba..0000000 --- a/gdb-6.5-bz200048-find_line_pc-segv.patch +++ /dev/null @@ -1,30 +0,0 @@ -https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=200048 - - -diff -ru gdb-6.5-orig/gdb/tui/tui-layout.c gdb-6.5-pr200048/gdb/tui/tui-layout.c ---- gdb-6.5-orig/gdb/tui/tui-layout.c 2006-08-07 21:33:42.000000000 +0200 -+++ gdb-6.5-pr200048/gdb/tui/tui-layout.c 2006-08-13 02:26:39.000000000 +0200 -@@ -519,13 +519,17 @@ - { - case SRC_COMMAND: - case SRC_DATA_COMMAND: -- find_line_pc (cursal.symtab, -+ if (find_line_pc (cursal.symtab, - TUI_SRC_WIN->detail.source_info.start_line_or_addr.u.line_no, -- &pc_list, &num_pc_values); -- /* FIXME: What do we do with multiple pc values for ctors/dtors or -- inlined functions? */ -- addr = pc_list[0]; -- xfree (pc_list); -+ &pc_list, &num_pc_values)) -+ { -+ /* FIXME: What do we do with multiple pc values for ctors/dtors or -+ inlined functions? */ -+ addr = pc_list[0]; -+ xfree (pc_list); -+ } -+ else -+ addr = 0; - break; - case DISASSEM_COMMAND: - case SRC_DISASSEM_COMMAND: diff --git a/gdb-6.7.1-upstream.patch b/gdb-6.7.1-upstream.patch index 7587463..dabb0e0 100644 --- a/gdb-6.7.1-upstream.patch +++ b/gdb-6.7.1-upstream.patch @@ -66,3 +66,5087 @@ Fix: { "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, { "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } }, + + + +2007-09-22 Vladimir Prus + + Associate bp_stat with bp_location, not breakpoint. + * breakpoint.h (breakpoint_at): Change type + to bp_location*. + * breakpoint.c (bpstat_alloc): Take bp_location, + not breakpoint. + (bpstat_find_breakpoint): Look at bpstat's location's + owner, not at bpstat->breakpoint_at. + (bpstat_find_step_resume_breakpoint): Likewise. + (bpstat_num): Likewise. + (print_it_typical): Likewise. + (print_bp_stop_message): Likewise. + (watchpoint_check): Likewise. + (bpstat_what): Likewise. + (bpstat_get_triggered_catchpoints): Likewise. + (breakpoint_auto_delete): Likewise. + (delete_breakpoint): Likewise. + (bpstat_stop_status): Pass location, not breakpoint, + to bpstat_alloc. Look at bpstat's location's + owner, not at bpstat->breakpoint_at. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.263 +retrieving revision 1.264 +diff -u -r1.263 -r1.264 +--- src/gdb/breakpoint.c 2007/08/29 22:07:47 1.263 ++++ src/gdb/breakpoint.c 2007/09/22 17:49:40 1.264 +@@ -109,7 +109,7 @@ + + static void breakpoint_1 (int, int); + +-static bpstat bpstat_alloc (struct breakpoint *, bpstat); ++static bpstat bpstat_alloc (struct bp_location *, bpstat); + + static int breakpoint_cond_eval (void *); + +@@ -1968,7 +1968,7 @@ + + for (; bsp != NULL; bsp = bsp->next) + { +- if (bsp->breakpoint_at == breakpoint) ++ if (bsp->breakpoint_at && bsp->breakpoint_at->owner == breakpoint) + return bsp; + } + return NULL; +@@ -1994,10 +1994,10 @@ + for (; bsp != NULL; bsp = bsp->next) + { + if ((bsp->breakpoint_at != NULL) && +- (bsp->breakpoint_at->type == bp_step_resume) && +- (bsp->breakpoint_at->thread == current_thread || +- bsp->breakpoint_at->thread == -1)) +- return bsp->breakpoint_at; ++ (bsp->breakpoint_at->owner->type == bp_step_resume) && ++ (bsp->breakpoint_at->owner->thread == current_thread || ++ bsp->breakpoint_at->owner->thread == -1)) ++ return bsp->breakpoint_at->owner; + } + + internal_error (__FILE__, __LINE__, _("No step_resume breakpoint found.")); +@@ -2021,7 +2021,11 @@ + if ((*bsp) == NULL) + return 0; /* No more breakpoint values */ + +- b = (*bsp)->breakpoint_at; ++ /* We assume we'll never have several bpstats that ++ correspond to a single breakpoint -- otherwise, ++ this function might return the same number more ++ than once and this will look ugly. */ ++ b = (*bsp)->breakpoint_at ? (*bsp)->breakpoint_at->owner : NULL; + *bsp = (*bsp)->next; + if (b == NULL) + return -1; /* breakpoint that's been deleted since */ +@@ -2152,6 +2156,7 @@ + print_it_typical (bpstat bs) + { + struct cleanup *old_chain, *ui_out_chain; ++ struct breakpoint *b; + struct ui_stream *stb; + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); +@@ -2159,21 +2164,22 @@ + which has since been deleted. */ + if (bs->breakpoint_at == NULL) + return PRINT_UNKNOWN; ++ b = bs->breakpoint_at->owner; + +- switch (bs->breakpoint_at->type) ++ switch (b->type) + { + case bp_breakpoint: + case bp_hardware_breakpoint: +- if (bs->breakpoint_at->loc->address != bs->breakpoint_at->loc->requested_address) +- breakpoint_adjustment_warning (bs->breakpoint_at->loc->requested_address, +- bs->breakpoint_at->loc->address, +- bs->breakpoint_at->number, 1); +- annotate_breakpoint (bs->breakpoint_at->number); ++ if (b->loc->address != b->loc->requested_address) ++ breakpoint_adjustment_warning (b->loc->requested_address, ++ b->loc->address, ++ b->number, 1); ++ annotate_breakpoint (b->number); + ui_out_text (uiout, "\nBreakpoint "); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); +- ui_out_field_int (uiout, "bkptno", bs->breakpoint_at->number); ++ ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ", "); + return PRINT_SRC_AND_LOC; + break; +@@ -2200,42 +2206,42 @@ + break; + + case bp_catch_load: +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (loaded %s), "), +- bs->breakpoint_at->number, +- bs->breakpoint_at->triggered_dll_pathname); ++ b->number, ++ b->triggered_dll_pathname); + return PRINT_SRC_AND_LOC; + break; + + case bp_catch_unload: +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (unloaded %s), "), +- bs->breakpoint_at->number, +- bs->breakpoint_at->triggered_dll_pathname); ++ b->number, ++ b->triggered_dll_pathname); + return PRINT_SRC_AND_LOC; + break; + + case bp_catch_fork: +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (forked process %d), "), +- bs->breakpoint_at->number, +- bs->breakpoint_at->forked_inferior_pid); ++ b->number, ++ b->forked_inferior_pid); + return PRINT_SRC_AND_LOC; + break; + + case bp_catch_vfork: +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (vforked process %d), "), +- bs->breakpoint_at->number, +- bs->breakpoint_at->forked_inferior_pid); ++ b->number, ++ b->forked_inferior_pid); + return PRINT_SRC_AND_LOC; + break; + + case bp_catch_exec: +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (exec'd %s), "), +- bs->breakpoint_at->number, +- bs->breakpoint_at->exec_pathname); ++ b->number, ++ b->exec_pathname); + return PRINT_SRC_AND_LOC; + break; + +@@ -2243,9 +2249,9 @@ + if (current_exception_event && + (CURRENT_EXCEPTION_KIND == EX_EVENT_CATCH)) + { +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (exception caught), "), +- bs->breakpoint_at->number); ++ b->number); + if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE) + printf_filtered (_("throw location %s:%d, "), + CURRENT_EXCEPTION_THROW_FILE, +@@ -2274,9 +2280,9 @@ + if (current_exception_event && + (CURRENT_EXCEPTION_KIND == EX_EVENT_THROW)) + { +- annotate_catchpoint (bs->breakpoint_at->number); ++ annotate_catchpoint (b->number); + printf_filtered (_("\nCatchpoint %d (exception thrown), "), +- bs->breakpoint_at->number); ++ b->number); + if (CURRENT_EXCEPTION_THROW_PC && CURRENT_EXCEPTION_THROW_LINE) + printf_filtered (_("throw location %s:%d, "), + CURRENT_EXCEPTION_THROW_FILE, +@@ -2305,18 +2311,18 @@ + case bp_hardware_watchpoint: + if (bs->old_val != NULL) + { +- annotate_watchpoint (bs->breakpoint_at->number); ++ annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER)); +- mention (bs->breakpoint_at); ++ mention (b); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nOld value = "); + value_print (bs->old_val, stb->stream, 0, Val_pretty_default); + ui_out_field_stream (uiout, "old", stb); + ui_out_text (uiout, "\nNew value = "); +- value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default); ++ value_print (b->val, stb->stream, 0, Val_pretty_default); + ui_out_field_stream (uiout, "new", stb); + do_cleanups (ui_out_chain); + ui_out_text (uiout, "\n"); +@@ -2332,10 +2338,10 @@ + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER)); +- mention (bs->breakpoint_at); ++ mention (b); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nValue = "); +- value_print (bs->breakpoint_at->val, stb->stream, 0, Val_pretty_default); ++ value_print (b->val, stb->stream, 0, Val_pretty_default); + ui_out_field_stream (uiout, "value", stb); + do_cleanups (ui_out_chain); + ui_out_text (uiout, "\n"); +@@ -2345,12 +2351,12 @@ + case bp_access_watchpoint: + if (bs->old_val != NULL) + { +- annotate_watchpoint (bs->breakpoint_at->number); ++ annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); +- mention (bs->breakpoint_at); ++ mention (b); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nOld value = "); + value_print (bs->old_val, stb->stream, 0, Val_pretty_default); +@@ -2361,7 +2367,7 @@ + } + else + { +- mention (bs->breakpoint_at); ++ mention (b); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", +@@ -2369,7 +2375,7 @@ + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nValue = "); + } +- value_print (bs->breakpoint_at->val, stb->stream, 0,Val_pretty_default); ++ value_print (b->val, stb->stream, 0,Val_pretty_default); + ui_out_field_stream (uiout, "new", stb); + do_cleanups (ui_out_chain); + ui_out_text (uiout, "\n"); +@@ -2429,14 +2435,19 @@ + break; + + case print_it_normal: +- /* Normal case. Call the breakpoint's print_it method, or +- print_it_typical. */ +- if (bs->breakpoint_at != NULL && bs->breakpoint_at->ops != NULL +- && bs->breakpoint_at->ops->print_it != NULL) +- return bs->breakpoint_at->ops->print_it (bs->breakpoint_at); +- else +- return print_it_typical (bs); +- break; ++ { ++ struct bp_location *bl = bs->breakpoint_at; ++ struct breakpoint *b = bl ? bl->owner : NULL; ++ ++ /* Normal case. Call the breakpoint's print_it method, or ++ print_it_typical. */ ++ /* FIXME: how breakpoint can ever be NULL here? */ ++ if (b != NULL && b->ops != NULL && b->ops->print_it != NULL) ++ return b->ops->print_it (b); ++ else ++ return print_it_typical (bs); ++ } ++ break; + + default: + internal_error (__FILE__, __LINE__, +@@ -2505,13 +2516,13 @@ + /* Allocate a new bpstat and chain it to the current one. */ + + static bpstat +-bpstat_alloc (struct breakpoint *b, bpstat cbs /* Current "bs" value */ ) ++bpstat_alloc (struct bp_location *bl, bpstat cbs /* Current "bs" value */ ) + { + bpstat bs; + + bs = (bpstat) xmalloc (sizeof (*bs)); + cbs->next = bs; +- bs->breakpoint_at = b; ++ bs->breakpoint_at = bl; + /* If the condition is false, etc., don't do the commands. */ + bs->commands = NULL; + bs->old_val = NULL; +@@ -2541,7 +2552,7 @@ + struct frame_info *fr; + int within_current_scope; + +- b = bs->breakpoint_at; ++ b = bs->breakpoint_at->owner; + + if (b->exp_valid_block == NULL) + within_current_scope = 1; +@@ -2588,7 +2599,7 @@ + we might be in the middle of evaluating a function call. */ + + struct value *mark = value_mark (); +- struct value *new_val = evaluate_expression (bs->breakpoint_at->exp); ++ struct value *new_val = evaluate_expression (b->exp); + if (!value_equal (b->val, new_val)) + { + release_value (new_val); +@@ -2624,7 +2635,7 @@ + ui_out_field_string + (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE)); + ui_out_text (uiout, "\nWatchpoint "); +- ui_out_field_int (uiout, "wpnum", bs->breakpoint_at->number); ++ ui_out_field_int (uiout, "wpnum", b->number); + ui_out_text (uiout, " deleted because the program has left the block in\n\ + which its expression is valid.\n"); + +@@ -2760,7 +2771,7 @@ + + /* Come here if it's a watchpoint, or if the break address matches */ + +- bs = bpstat_alloc (b, bs); /* Alloc a bpstat to explain stop */ ++ bs = bpstat_alloc (b->loc, bs); /* Alloc a bpstat to explain stop */ + + /* Watchpoints may change this, if not found to have triggered. */ + bs->stop = 1; +@@ -2971,9 +2982,9 @@ + /* The value of a hardware watchpoint hasn't changed, but the + intermediate memory locations we are watching may have. */ + if (bs && !bs->stop && +- (bs->breakpoint_at->type == bp_hardware_watchpoint || +- bs->breakpoint_at->type == bp_read_watchpoint || +- bs->breakpoint_at->type == bp_access_watchpoint)) ++ (bs->breakpoint_at->owner->type == bp_hardware_watchpoint || ++ bs->breakpoint_at->owner->type == bp_read_watchpoint || ++ bs->breakpoint_at->owner->type == bp_access_watchpoint)) + { + remove_breakpoints (); + insert_breakpoints (); +@@ -3134,7 +3145,7 @@ + /* I suspect this can happen if it was a momentary breakpoint + which has since been deleted. */ + continue; +- switch (bs->breakpoint_at->type) ++ switch (bs->breakpoint_at->owner->type) + { + case bp_none: + continue; +@@ -3289,7 +3300,7 @@ + for (; ep_list != NULL; ep_list = ep_list->next) + { + /* Is this eventpoint a catchpoint? If not, ignore it. */ +- ep = ep_list->breakpoint_at; ++ ep = ep_list->breakpoint_at->owner; + if (ep == NULL) + break; + if ((ep->type != bp_catch_load) && +@@ -3300,7 +3311,7 @@ + continue; + + /* Yes; add it to the list. */ +- bs = bpstat_alloc (ep, bs); ++ bs = bpstat_alloc (ep_list->breakpoint_at, bs); + *bs = *ep_list; + bs->next = NULL; + bs = root_bs->next; +@@ -6849,9 +6860,9 @@ + struct breakpoint *b, *temp; + + for (; bs; bs = bs->next) +- if (bs->breakpoint_at && bs->breakpoint_at->disposition == disp_del ++ if (bs->breakpoint_at && bs->breakpoint_at->owner->disposition == disp_del + && bs->stop) +- delete_breakpoint (bs->breakpoint_at); ++ delete_breakpoint (bs->breakpoint_at->owner); + + ALL_BREAKPOINTS_SAFE (b, temp) + { +@@ -7041,7 +7052,7 @@ + in event-top.c won't do anything, and temporary breakpoints + with commands won't work. */ + for (bs = stop_bpstat; bs; bs = bs->next) +- if (bs->breakpoint_at == bpt) ++ if (bs->breakpoint_at && bs->breakpoint_at->owner == bpt) + { + bs->breakpoint_at = NULL; + bs->old_val = NULL; +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.h,v +retrieving revision 1.47 +retrieving revision 1.48 +diff -u -r1.47 -r1.48 +--- src/gdb/breakpoint.h 2007/08/23 18:08:26 1.47 ++++ src/gdb/breakpoint.h 2007/09/22 17:49:41 1.48 +@@ -603,7 +603,7 @@ + place, and a bpstat reflects the fact that both have been hit. */ + bpstat next; + /* Breakpoint that we are at. */ +- struct breakpoint *breakpoint_at; ++ struct bp_location *breakpoint_at; + /* Commands left to be done. */ + struct command_line *commands; + /* Old value associated with a watchpoint. */ + +2007-09-22 Vladimir Prus + + * breakpoint.h (struct breakpoint): Move the cond + field to... + (struct bp_location): Here. + * breakpoint.c (condition_command, bpstat_stop_status) + (print_one_breakpoint, allocate_bp_location) + (solib_load_unload_1, create_fork_vfork_event_catchpoint) + (create_exec_event_catchpoint, create_breakpoints) + (break_command_1, watch_command_1, handle_gnu_v3_exceptions) + (create_ada_exception_breakpoint, set_breakpoint_sal) + (delete_breakpoint, breakpoint_re_set_one): Adjust. + * tui/tui-winsource.c (tui_update_breakpoint_info): Adjust. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.264 +retrieving revision 1.265 +diff -u -r1.264 -r1.265 +--- src/gdb/breakpoint.c 2007/09/22 17:49:40 1.264 ++++ src/gdb/breakpoint.c 2007/09/22 19:06:59 1.265 +@@ -569,17 +569,17 @@ + ALL_BREAKPOINTS (b) + if (b->number == bnum) + { +- if (b->cond) ++ struct bp_location *loc = b->loc; ++ if (loc->cond) + { +- xfree (b->cond); +- b->cond = 0; ++ xfree (loc->cond); ++ loc->cond = 0; + } + if (b->cond_string != NULL) + xfree (b->cond_string); + + if (*p == 0) + { +- b->cond = 0; + b->cond_string = NULL; + if (from_tty) + printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum); +@@ -592,7 +592,8 @@ + b->cond_string = savestring (arg, strlen (arg)); + if (!b->pending) + { +- b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); ++ b->loc->cond = parse_exp_1 (&arg, ++ block_for_pc (b->loc->address), 0); + if (*arg) + error (_("Junk at end of expression")); + } +@@ -2923,19 +2924,19 @@ + { + int value_is_zero = 0; + +- if (b->cond) ++ if (b->loc->cond) + { + /* Need to select the frame, with all that implies + so that the conditions will have the right context. */ + select_frame (get_current_frame ()); + value_is_zero +- = catch_errors (breakpoint_cond_eval, (b->cond), ++ = catch_errors (breakpoint_cond_eval, (b->loc->cond), + "Error in testing breakpoint condition:\n", + RETURN_MASK_ALL); + /* FIXME-someday, should give breakpoint # */ + free_all_values (); + } +- if (b->cond && value_is_zero) ++ if (b->loc->cond && value_is_zero) + { + bs->stop = 0; + /* Don't consider this a hit. */ +@@ -3606,14 +3607,14 @@ + ui_out_text (uiout, "\n"); + } + +- if (b->cond && !ada_exception_catchpoint_p (b)) ++ if (b->loc->cond && !ada_exception_catchpoint_p (b)) + { + /* We do not print the condition for Ada exception catchpoints + because the condition is an internal implementation detail + that we do not want to expose to the user. */ + annotate_field (7); + ui_out_text (uiout, "\tstop only if "); +- print_expression (b->cond, stb->stream); ++ print_expression (b->loc->cond, stb->stream); + ui_out_field_stream (uiout, "cond", stb); + ui_out_text (uiout, "\n"); + } +@@ -4085,6 +4086,7 @@ + memset (loc, 0, sizeof (*loc)); + + loc->owner = bpt; ++ loc->cond = NULL; + + switch (bp_type) + { +@@ -4604,7 +4606,6 @@ + b = set_raw_breakpoint (sals.sals[0], bp_kind); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = NULL; + b->cond_string = (cond_string == NULL) ? + NULL : savestring (cond_string, strlen (cond_string)); + b->thread = thread; +@@ -4661,7 +4662,6 @@ + b = set_raw_breakpoint (sal, bp_kind); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = NULL; + b->cond_string = (cond_string == NULL) ? + NULL : savestring (cond_string, strlen (cond_string)); + b->thread = thread; +@@ -4700,7 +4700,6 @@ + b = set_raw_breakpoint (sal, bp_catch_exec); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = NULL; + b->cond_string = (cond_string == NULL) ? + NULL : savestring (cond_string, strlen (cond_string)); + b->thread = thread; +@@ -5033,7 +5032,7 @@ + b = set_raw_breakpoint (sal, type); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = cond[i]; ++ b->loc->cond = cond[i]; + b->thread = thread; + if (addr_string[i]) + b->addr_string = addr_string[i]; +@@ -5056,7 +5055,7 @@ + { + arg = pending_bp->cond_string; + b->cond_string = savestring (arg, strlen (arg)); +- b->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); ++ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); + if (*arg) + error (_("Junk at end of pending breakpoint condition expression")); + } +@@ -5399,7 +5398,7 @@ + : bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = *cond; ++ b->loc->cond = *cond; + b->thread = thread; + b->addr_string = *addr_string; + b->cond_string = *cond_string; +@@ -5792,7 +5791,7 @@ + b->exp_valid_block = exp_valid_block; + b->exp_string = savestring (exp_start, exp_end - exp_start); + b->val = val; +- b->cond = cond; ++ b->loc->cond = cond; + if (cond_start) + b->cond_string = savestring (cond_start, cond_end - cond_start); + else +@@ -6352,7 +6351,6 @@ + b = set_raw_breakpoint (*sal, bptype); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = NULL; + b->cond_string = (cond_string == NULL) ? + NULL : savestring (cond_string, strlen (cond_string)); + b->thread = thread; +@@ -6432,7 +6430,6 @@ + b = set_raw_breakpoint (sals.sals[0], bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = NULL; + b->cond_string = (cond_string == NULL) ? + NULL : savestring (cond_string, strlen (cond_string)); + b->thread = -1; +@@ -6519,7 +6516,7 @@ + b->disposition = tempflag ? disp_del : disp_donttouch; + b->number = breakpoint_count; + b->ignore_count = 0; +- b->cond = cond; ++ b->loc->cond = cond; + b->addr_string = addr_string; + b->language = language_ada; + b->cond_string = cond_string; +@@ -6701,7 +6698,6 @@ + b = set_raw_breakpoint (sal, bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->cond = 0; + b->thread = -1; + return b; + } +@@ -7021,8 +7017,6 @@ + } + + free_command_lines (&bpt->commands); +- if (bpt->cond) +- xfree (bpt->cond); + if (bpt->cond_string != NULL) + xfree (bpt->cond_string); + if (bpt->addr_string != NULL) +@@ -7062,6 +7056,8 @@ + bp, we mark it as deleted before freeing its storage. */ + bpt->type = bp_none; + ++ if (bpt->loc->cond) ++ xfree (bpt->loc->cond); + xfree (bpt->loc); + xfree (bpt); + } +@@ -7215,14 +7211,14 @@ + if (b->cond_string != NULL) + { + s = b->cond_string; +- if (b->cond) ++ if (b->loc->cond) + { +- xfree (b->cond); ++ xfree (b->loc->cond); + /* Avoid re-freeing b->exp if an error during the call + to parse_exp_1. */ +- b->cond = NULL; ++ b->loc->cond = NULL; + } +- b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0); ++ b->loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0); + } + + /* We need to re-set the breakpoint if the address changes... */ +@@ -7314,14 +7310,14 @@ + if (b->cond_string != NULL) + { + s = b->cond_string; +- if (b->cond) ++ if (b->loc->cond) + { +- xfree (b->cond); ++ xfree (b->loc->cond); + /* Avoid re-freeing b->exp if an error during the call + to parse_exp_1. */ +- b->cond = NULL; ++ b->loc->cond = NULL; + } +- b->cond = parse_exp_1 (&s, (struct block *) 0, 0); ++ b->loc->cond = parse_exp_1 (&s, (struct block *) 0, 0); + } + if (breakpoint_enabled (b)) + mention (b); +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.h,v +retrieving revision 1.48 +retrieving revision 1.49 +diff -u -r1.48 -r1.49 +--- src/gdb/breakpoint.h 2007/09/22 17:49:41 1.48 ++++ src/gdb/breakpoint.h 2007/09/22 19:06:59 1.49 +@@ -243,6 +243,13 @@ + than reference counting. */ + struct breakpoint *owner; + ++ /* Conditional. Break only if this expression's value is nonzero. ++ Unlike string form of condition, which is associated with breakpoint, ++ this is associated with location, since if breakpoint has several ++ locations, the evaluation of expression can be different for ++ different locations. */ ++ struct expression *cond; ++ + /* Nonzero if this breakpoint is now inserted. */ + char inserted; + +@@ -341,8 +348,6 @@ + /* Stack depth (address of frame). If nonzero, break only if fp + equals this. */ + struct frame_id frame_id; +- /* Conditional. Break only if this expression's value is nonzero. */ +- struct expression *cond; + + /* String we used to set the breakpoint (malloc'd). */ + char *addr_string; +=================================================================== +RCS file: /cvs/src/src/gdb/tui/tui-winsource.c,v +retrieving revision 1.28 +retrieving revision 1.29 +diff -u -r1.28 -r1.29 +--- src/gdb/tui/tui-winsource.c 2007/08/23 18:08:50 1.28 ++++ src/gdb/tui/tui-winsource.c 2007/09/22 19:06:59 1.29 +@@ -449,7 +449,7 @@ + mode |= TUI_BP_ENABLED; + if (bp->hit_count) + mode |= TUI_BP_HIT; +- if (bp->cond) ++ if (bp->loc->cond) + mode |= TUI_BP_CONDITIONAL; + if (bp->type == bp_hardware_breakpoint) + mode |= TUI_BP_HARDWARE; + +2007-09-22 Vladimir Prus + + * breakpoint.c (create_breakpoint): Split from + create_breakpoints, implementing most of its logic. + Take just a single sal, single address string and + single condition. Do not take parsed condition at + all. + (create_breakpoints): Just call create_breakpoint + for each sal. + (find_condition_and_thread): New. + (break_command_1): Use find_condition_and_thread. + Do not keep parsed conditions. + (do_captured_breakpoint): Don't convert + condition string to struct expression. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.265 +retrieving revision 1.266 +diff -u -r1.265 -r1.266 +--- src/gdb/breakpoint.c 2007/09/22 19:06:59 1.265 ++++ src/gdb/breakpoint.c 2007/09/22 19:10:05 1.266 +@@ -4984,93 +4984,125 @@ + } + + +-/* Add SALS.nelts breakpoints to the breakpoint table. For each +- SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i], +- COND[i] and COND_STRING[i] values. + ++/* Create a breakpoint with SAL as location. Use ADDR_STRING ++ as textual description of the location, and COND_STRING ++ as condition expression. ++ ++ The paramter PENDING_BP is same as for the ++ create_breakpoints function. */ ++ ++static void ++create_breakpoint (struct symtab_and_line sal, char *addr_string, ++ char *cond_string, ++ enum bptype type, enum bpdisp disposition, ++ int thread, int ignore_count, int from_tty, ++ struct breakpoint *pending_bp) ++{ ++ struct breakpoint *b; ++ ++ if (type == bp_hardware_breakpoint) ++ { ++ int i = hw_breakpoint_used_count (); ++ int target_resources_ok = ++ TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, ++ i + 1, 0); ++ if (target_resources_ok == 0) ++ error (_("No hardware breakpoint support in the target.")); ++ else if (target_resources_ok < 0) ++ error (_("Hardware breakpoints used exceeds limit.")); ++ } ++ ++ if (from_tty) ++ describe_other_breakpoints (sal.pc, sal.section, thread); ++ ++ b = set_raw_breakpoint (sal, type); ++ set_breakpoint_count (breakpoint_count + 1); ++ b->number = breakpoint_count; ++ b->thread = thread; ++ ++ b->cond_string = cond_string; ++ b->ignore_count = ignore_count; ++ b->enable_state = bp_enabled; ++ b->disposition = disposition; ++ /* If resolving a pending breakpoint, a check must be made to see if ++ the user has specified a new condition or commands for the ++ breakpoint. A new condition will override any condition that was ++ initially specified with the initial breakpoint command. */ ++ if (pending_bp) ++ { ++ if (pending_bp->cond_string) ++ b->cond_string = savestring (pending_bp->cond_string, ++ strlen (pending_bp->cond_string)); ++ ++ /* If there are commands associated with the breakpoint, they should ++ be copied too. */ ++ if (pending_bp->commands) ++ b->commands = copy_command_lines (pending_bp->commands); ++ ++ /* We have to copy over the ignore_count and thread as well. */ ++ b->ignore_count = pending_bp->ignore_count; ++ b->thread = pending_bp->thread; ++ } ++ ++ if (b->cond_string) ++ { ++ char *arg = b->cond_string; ++ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); ++ if (*arg) ++ { ++ if (pending_bp) ++ error (_("Junk at end of pending breakpoint condition expression")); ++ else ++ error (_("Garbage %s follows condition"), arg); ++ } ++ } ++ ++ if (addr_string) ++ b->addr_string = addr_string; ++ else ++ /* addr_string has to be used or breakpoint_re_set will delete ++ me. */ ++ b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address)); ++ ++ mention (b); ++} ++ ++/* Add SALS.nelts breakpoints to the breakpoint table. For each ++ SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i] ++ value. COND_STRING, if not NULL, specified the condition to be ++ used for all breakpoints. Essentially the only case where ++ SALS.nelts is not 1 is when we set a breakpoint on an overloaded ++ function. In that case, it's still not possible to specify ++ separate conditions for different overloaded functions, so ++ we take just a single condition string. ++ + The parameter PENDING_BP points to a pending breakpoint that is + the basis of the breakpoints currently being created. The pending + breakpoint may contain a separate condition string or commands + that were added after the initial pending breakpoint was created. + + NOTE: If the function succeeds, the caller is expected to cleanup +- the arrays ADDR_STRING, COND_STRING, COND and SALS (but not the ++ the arrays ADDR_STRING, COND_STRING, and SALS (but not the + array contents). If the function fails (error() is called), the + caller is expected to cleanups both the ADDR_STRING, COND_STRING, + COND and SALS arrays and each of those arrays contents. */ + + static void + create_breakpoints (struct symtabs_and_lines sals, char **addr_string, +- struct expression **cond, char **cond_string, ++ char *cond_string, + enum bptype type, enum bpdisp disposition, + int thread, int ignore_count, int from_tty, + struct breakpoint *pending_bp) + { +- if (type == bp_hardware_breakpoint) ++ int i; ++ for (i = 0; i < sals.nelts; ++i) + { +- int i = hw_breakpoint_used_count (); +- int target_resources_ok = +- TARGET_CAN_USE_HARDWARE_WATCHPOINT (bp_hardware_breakpoint, +- i + sals.nelts, 0); +- if (target_resources_ok == 0) +- error (_("No hardware breakpoint support in the target.")); +- else if (target_resources_ok < 0) +- error (_("Hardware breakpoints used exceeds limit.")); ++ create_breakpoint (sals.sals[i], addr_string[i], ++ cond_string, type, disposition, ++ thread, ignore_count, from_tty, ++ pending_bp); + } +- +- /* Now set all the breakpoints. */ +- { +- int i; +- for (i = 0; i < sals.nelts; i++) +- { +- struct breakpoint *b; +- struct symtab_and_line sal = sals.sals[i]; +- +- if (from_tty) +- describe_other_breakpoints (sal.pc, sal.section, thread); +- +- b = set_raw_breakpoint (sal, type); +- set_breakpoint_count (breakpoint_count + 1); +- b->number = breakpoint_count; +- b->loc->cond = cond[i]; +- b->thread = thread; +- if (addr_string[i]) +- b->addr_string = addr_string[i]; +- else +- /* addr_string has to be used or breakpoint_re_set will delete +- me. */ +- b->addr_string = xstrprintf ("*0x%s", paddr (b->loc->address)); +- b->cond_string = cond_string[i]; +- b->ignore_count = ignore_count; +- b->enable_state = bp_enabled; +- b->disposition = disposition; +- /* If resolving a pending breakpoint, a check must be made to see if +- the user has specified a new condition or commands for the +- breakpoint. A new condition will override any condition that was +- initially specified with the initial breakpoint command. */ +- if (pending_bp) +- { +- char *arg; +- if (pending_bp->cond_string) +- { +- arg = pending_bp->cond_string; +- b->cond_string = savestring (arg, strlen (arg)); +- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); +- if (*arg) +- error (_("Junk at end of pending breakpoint condition expression")); +- } +- /* If there are commands associated with the breakpoint, they should +- be copied too. */ +- if (pending_bp->commands) +- b->commands = copy_command_lines (pending_bp->commands); +- +- /* We have to copy over the ignore_count and thread as well. */ +- b->ignore_count = pending_bp->ignore_count; +- b->thread = pending_bp->thread; +- } +- mention (b); +- } +- } + } + + /* Parse ARG which is assumed to be a SAL specification possibly +@@ -5192,6 +5224,59 @@ + args->not_found_ptr); + } + ++/* Given TOK, a string specification of condition and thread, as ++ accepted by the 'break' command, extract the condition ++ string and thread number and set *COND_STRING and *THREAD. ++ PC identifies the context at which the condition should be parsed. ++ If no condition is found, *COND_STRING is set to NULL. ++ If no thread is found, *THREAD is set to -1. */ ++static void ++find_condition_and_thread (char *tok, CORE_ADDR pc, ++ char **cond_string, int *thread) ++{ ++ *cond_string = NULL; ++ *thread = -1; ++ while (tok && *tok) ++ { ++ char *end_tok; ++ int toklen; ++ char *cond_start = NULL; ++ char *cond_end = NULL; ++ while (*tok == ' ' || *tok == '\t') ++ tok++; ++ ++ end_tok = tok; ++ ++ while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') ++ end_tok++; ++ ++ toklen = end_tok - tok; ++ ++ if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) ++ { ++ tok = cond_start = end_tok + 1; ++ parse_exp_1 (&tok, block_for_pc (pc), 0); ++ cond_end = tok; ++ *cond_string = savestring (cond_start, ++ cond_end - cond_start); ++ } ++ else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) ++ { ++ char *tmptok; ++ ++ tok = end_tok + 1; ++ tmptok = tok; ++ *thread = strtol (tok, &tok, 0); ++ if (tok == tmptok) ++ error (_("Junk after thread keyword.")); ++ if (!valid_thread_id (*thread)) ++ error (_("Unknown thread %d."), *thread); ++ } ++ else ++ error (_("Junk at end of arguments.")); ++ } ++} ++ + /* Set a breakpoint according to ARG (function, linenum or *address) + flag: first bit : 0 non-temporary, 1 temporary. + second bit : 0 normal breakpoint, 1 hardware breakpoint. +@@ -5205,9 +5290,8 @@ + struct gdb_exception e; + int tempflag, hardwareflag; + struct symtabs_and_lines sals; +- struct expression **cond = 0; + struct symtab_and_line pending_sal; +- char **cond_string = (char **) NULL; ++ char *cond_string = NULL; + char *copy_arg; + char *err_msg; + char *addr_start = arg; +@@ -5297,14 +5381,6 @@ + make_cleanup (xfree, addr_string); + } + +- /* Allocate space for all the cond expressions. */ +- cond = xcalloc (sals.nelts, sizeof (struct expression *)); +- make_cleanup (xfree, cond); +- +- /* Allocate space for all the cond strings. */ +- cond_string = xcalloc (sals.nelts, sizeof (char **)); +- make_cleanup (xfree, cond_string); +- + /* ----------------------------- SNIP ----------------------------- + Anything added to the cleanup chain beyond this point is assumed + to be part of a breakpoint. If the breakpoint create succeeds +@@ -5328,56 +5404,16 @@ + /* Verify that condition can be parsed, before setting any + breakpoints. Allocate a separate condition expression for each + breakpoint. */ +- thread = -1; /* No specific thread yet */ + if (!pending) + { +- for (i = 0; i < sals.nelts; i++) +- { +- char *tok = arg; +- while (tok && *tok) +- { +- char *end_tok; +- int toklen; +- char *cond_start = NULL; +- char *cond_end = NULL; +- while (*tok == ' ' || *tok == '\t') +- tok++; +- +- end_tok = tok; +- +- while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000') +- end_tok++; +- +- toklen = end_tok - tok; +- +- if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) +- { +- tok = cond_start = end_tok + 1; +- cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), +- 0); +- make_cleanup (xfree, cond[i]); +- cond_end = tok; +- cond_string[i] = savestring (cond_start, +- cond_end - cond_start); +- make_cleanup (xfree, cond_string[i]); +- } +- else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) +- { +- char *tmptok; +- +- tok = end_tok + 1; +- tmptok = tok; +- thread = strtol (tok, &tok, 0); +- if (tok == tmptok) +- error (_("Junk after thread keyword.")); +- if (!valid_thread_id (thread)) +- error (_("Unknown thread %d."), thread); +- } +- else +- error (_("Junk at end of arguments.")); +- } +- } +- create_breakpoints (sals, addr_string, cond, cond_string, ++ /* Here we only parse 'arg' to separate condition ++ from thread number, so parsing in context of first ++ sal is OK. When setting the breakpoint we'll ++ re-parse it in context of each sal. */ ++ find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, &thread); ++ if (cond_string) ++ make_cleanup (xfree, cond_string); ++ create_breakpoints (sals, addr_string, cond_string, + hardwareflag ? bp_hardware_breakpoint + : bp_breakpoint, + tempflag ? disp_del : disp_donttouch, +@@ -5398,10 +5434,10 @@ + : bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->loc->cond = *cond; ++ b->loc->cond = NULL; + b->thread = thread; +- b->addr_string = *addr_string; +- b->cond_string = *cond_string; ++ b->addr_string = addr_string[0]; ++ b->cond_string = cond_string; + b->ignore_count = ignore_count; + b->pending = 1; + b->disposition = tempflag ? disp_del : disp_donttouch; +@@ -5445,7 +5481,7 @@ + struct cleanup *breakpoint_chain = NULL; + int i; + char **addr_string; +- char **cond_string; ++ char *cond_string; + + char *address_end; + +@@ -5502,22 +5538,13 @@ + /* Resolve all line numbers to PC's. */ + breakpoint_sals_to_pc (&sals, args->address); + +- /* Verify that conditions can be parsed, before setting any +- breakpoints. */ +- for (i = 0; i < sals.nelts; i++) ++ if (args->condition != NULL) + { +- if (args->condition != NULL) +- { +- char *tok = args->condition; +- cond[i] = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0); +- if (*tok != '\0') +- error (_("Garbage %s follows condition"), tok); +- make_cleanup (xfree, cond[i]); +- cond_string[i] = xstrdup (args->condition); +- } ++ cond_string = xstrdup (args->condition); ++ make_cleanup (xfree, cond_string); + } + +- create_breakpoints (sals, addr_string, cond, cond_string, ++ create_breakpoints (sals, addr_string, args->condition, + args->hardwareflag ? bp_hardware_breakpoint : bp_breakpoint, + args->tempflag ? disp_del : disp_donttouch, + args->thread, args->ignore_count, 0/*from-tty*/, + +2007-09-22 Vladimir Prus + + * breakpoint.c (do_restore_lang_radix_cleanup): Remove. + (resolve_pending_breakpoint): Remove. + (re_enable_breakpoints_in_shlibs): Remove. + (unlink_locations_from_global_list): New. + (update_breakpoint_locations): New. + (breakpoint_re_set_one): Don't bail out on pending breakpoints. + Use parse_condition and update_breakpoint_location to + reset breakpoint. Ignore 'symbol not found' error from + decode_line_1. + (breakpoint_re_set): Don't emit newline before the + reason why breakpoint is not reset. + (do_enable_breakpoint): Don't specially process pending + breakpoints. + (free_bp_location): New. + (break_command_1): For pending breakpoints, initialize + all fields of a sal with zeroes. + * breakpoint.h (re_enable_breakpoints_in_shlibs): Remove. + * infcmd.c (post_create_inferior): Don't call + re_enable_breakpoints_in_shlibs. + * infrun.c (handle_inferior_event): Likewise. + * solib-irix.c (irix_solib_create_inferior_hook): Likewise. + * solib-osf.c (osf_solib_create_inferior_hook): Likewise. + * win32-nat.c (get_win32_debug_event): Likewise. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.266 +retrieving revision 1.267 +diff -u -r1.266 -r1.267 +--- src/gdb/breakpoint.c 2007/09/22 19:10:05 1.266 ++++ src/gdb/breakpoint.c 2007/09/22 19:33:31 1.267 +@@ -203,6 +203,8 @@ + + static int single_step_breakpoint_inserted_here_p (CORE_ADDR pc); + ++static void free_bp_location (struct bp_location *loc); ++ + /* Prototypes for exported functions. */ + + /* If FALSE, gdb will not use hardware support for watchpoints, even +@@ -4140,6 +4142,13 @@ + return loc; + } + ++static void free_bp_location (struct bp_location *loc) ++{ ++ if (loc->cond) ++ xfree (loc->cond); ++ xfree (loc); ++} ++ + /* set_raw_breakpoint() is a low level routine for allocating and + partially initializing a breakpoint of type BPTYPE. The newly + created breakpoint's address, section, source file name, and line +@@ -4396,51 +4405,6 @@ + int radix; + }; + +-/* Cleanup helper routine to restore the current language and +- input radix. */ +-static void +-do_restore_lang_radix_cleanup (void *old) +-{ +- struct lang_and_radix *p = old; +- set_language (p->lang); +- input_radix = p->radix; +-} +- +-/* Try and resolve a pending breakpoint. */ +-static int +-resolve_pending_breakpoint (struct breakpoint *b) +-{ +- /* Try and reparse the breakpoint in case the shared library +- is now loaded. */ +- struct symtabs_and_lines sals; +- struct symtab_and_line pending_sal; +- char **cond_string = (char **) NULL; +- char *copy_arg = b->addr_string; +- char **addr_string; +- char *errmsg; +- int rc; +- int not_found = 0; +- struct ui_file *old_gdb_stderr; +- struct lang_and_radix old_lr; +- struct cleanup *old_chain; +- +- /* Set language, input-radix, then reissue breakpoint command. +- Ensure the language and input-radix are restored afterwards. */ +- old_lr.lang = current_language->la_language; +- old_lr.radix = input_radix; +- old_chain = make_cleanup (do_restore_lang_radix_cleanup, &old_lr); +- +- set_language (b->language); +- input_radix = b->input_radix; +- rc = break_command_1 (b->addr_string, b->flag, b->from_tty, b); +- +- if (rc == GDB_RC_OK) +- /* Pending breakpoint has been resolved. */ +- printf_filtered (_("Pending breakpoint \"%s\" resolved\n"), b->addr_string); +- +- do_cleanups (old_chain); +- return rc; +-} + + void + remove_solib_event_breakpoints (void) +@@ -4523,37 +4487,6 @@ + } + } + +-/* Try to reenable any breakpoints in shared libraries. */ +-void +-re_enable_breakpoints_in_shlibs (void) +-{ +- struct breakpoint *b, *tmp; +- +- ALL_BREAKPOINTS_SAFE (b, tmp) +- { +- if (b->enable_state == bp_shlib_disabled) +- { +- gdb_byte buf[1]; +- char *lib; +- +- /* Do not reenable the breakpoint if the shared library is +- still not mapped in. */ +-#ifdef PC_SOLIB +- lib = PC_SOLIB (b->loc->address); +-#else +- lib = solib_address (b->loc->address); +-#endif +- if (lib != NULL && target_read_memory (b->loc->address, buf, 1) == 0) +- b->enable_state = bp_enabled; +- } +- else if (b->pending && (b->enable_state == bp_enabled)) +- { +- if (resolve_pending_breakpoint (b) == GDB_RC_OK) +- delete_breakpoint (b); +- } +- } +-} +- + static void + solib_load_unload_1 (char *hookname, int tempflag, char *dll_pathname, + char *cond_string, enum bptype bp_kind) +@@ -5422,12 +5355,9 @@ + } + else + { +- struct symtab_and_line sal; ++ struct symtab_and_line sal = {0}; + struct breakpoint *b; + +- sal.symtab = NULL; +- sal.pc = 0; +- + make_cleanup (xfree, copy_arg); + + b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint +@@ -7153,6 +7083,97 @@ + map_breakpoint_numbers (arg, delete_breakpoint); + } + ++static void ++unlink_locations_from_global_list (struct breakpoint *bpt) ++ /* Remove locations of this breakpoint from the list of ++ all breakpoint locations. */ ++{ ++ struct bp_location **tmp = &bp_location_chain; ++ struct bp_location *here = bpt->loc; ++ ++ if (here == NULL) ++ return; ++ ++ for (; *tmp && *tmp != here; tmp = &((*tmp)->next)); ++ gdb_assert (*tmp); ++ ++ *tmp = here->next; ++} ++ ++ ++static void ++update_breakpoint_location (struct breakpoint *b, ++ struct symtabs_and_lines sals) ++{ ++ int i; ++ char *s; ++ /* FIXME: memleak. */ ++ struct bp_location *existing = b->loc; ++ struct bp_location *loc; ++ struct symtab_and_line sal; ++ ++ if (b->enable_state == bp_shlib_disabled && sals.nelts == 0) ++ return; ++ ++ unlink_locations_from_global_list (b); ++ b->loc = NULL; ++ ++ gdb_assert (sals.nelts == 0 || sals.nelts == 1); ++ if (sals.nelts == 0) ++ return; ++ sal = sals.sals[0]; ++ ++ loc = allocate_bp_location (b, b->type); ++ loc->requested_address = sal.pc; ++ loc->address = adjust_breakpoint_address (loc->requested_address, ++ b->type); ++ loc->section = sal.section; ++ b->loc = loc; ++ ++ /* Reparse conditions, they might contain references to the ++ old symtab. */ ++ if (b->cond_string != NULL) ++ { ++ struct gdb_exception e; ++ ++ s = b->cond_string; ++ TRY_CATCH (e, RETURN_MASK_ERROR) ++ { ++ loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc), ++ 0); ++ } ++ if (e.reason < 0) ++ { ++ warning (_("failed to reevaluate condition for breakpoint %d: %s"), ++ b->number, e.message); ++ b->enable_state = bp_disabled; ++ } ++ } ++ ++ if (b->source_file != NULL) ++ xfree (b->source_file); ++ if (sal.symtab == NULL) ++ b->source_file = NULL; ++ else ++ b->source_file = ++ savestring (sal.symtab->filename, ++ strlen (sal.symtab->filename)); ++ ++ if (b->line_number == 0) ++ b->line_number = sal.line; ++ ++ if (b->enable_state == bp_shlib_disabled) ++ b->enable_state = bp_enabled; ++ ++ b->pending = 0; ++ ++ check_duplicates (b); ++ ++ if (existing) ++ free_bp_location (existing); ++} ++ ++ + /* Reset a breakpoint given it's struct breakpoint * BINT. + The value we return ends up being the return value from catch_errors. + Unused in this case. */ +@@ -7164,11 +7185,13 @@ + struct breakpoint *b = (struct breakpoint *) bint; + struct value *mark; + int i; +- int not_found; +- int *not_found_ptr = NULL; +- struct symtabs_and_lines sals; ++ int not_found = 0; ++ int *not_found_ptr = ¬_found; ++ struct symtabs_and_lines sals = {}; + char *s; + enum enable_state save_enable; ++ struct gdb_exception e; ++ + + switch (b->type) + { +@@ -7186,115 +7209,59 @@ + delete_breakpoint (b); + return 0; + } +- /* HACK: cagney/2001-11-11: kettenis/2001-11-11: MarkK wrote: +- +- ``And a hack it is, although Apple's Darwin version of GDB +- contains an almost identical hack to implement a "future +- break" command. It seems to work in many real world cases, +- but it is easy to come up with a test case where the patch +- doesn't help at all.'' +- +- ``It seems that the way GDB implements breakpoints - in - +- shared - libraries was designed for a.out shared library +- systems (SunOS 4) where shared libraries were loaded at a +- fixed address in memory. Since ELF shared libraries can (and +- will) be loaded at any address in memory, things break. +- Fixing this is not trivial. Therefore, I'm not sure whether +- we should add this hack to the branch only. I cannot +- guarantee that things will be fixed on the trunk in the near +- future.'' +- +- In case we have a problem, disable this breakpoint. We'll +- restore its status if we succeed. Don't disable a +- shlib_disabled breakpoint though. There's a fair chance we +- can't re-set it if the shared library it's in hasn't been +- loaded yet. */ +- +- if (b->pending) +- break; +- +- save_enable = b->enable_state; +- if (b->enable_state != bp_shlib_disabled) +- b->enable_state = bp_disabled; +- else +- /* If resetting a shlib-disabled breakpoint, we don't want to +- see an error message if it is not found since we will expect +- this to occur until the shared library is finally reloaded. +- We accomplish this by giving decode_line_1 a pointer to use +- for silent notification that the symbol is not found. */ +- not_found_ptr = ¬_found; + + set_language (b->language); + input_radix = b->input_radix; + s = b->addr_string; +- sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, +- not_found_ptr); +- for (i = 0; i < sals.nelts; i++) +- { +- resolve_sal_pc (&sals.sals[i]); +- +- /* Reparse conditions, they might contain references to the +- old symtab. */ +- if (b->cond_string != NULL) +- { +- s = b->cond_string; +- if (b->loc->cond) +- { +- xfree (b->loc->cond); +- /* Avoid re-freeing b->exp if an error during the call +- to parse_exp_1. */ +- b->loc->cond = NULL; +- } +- b->loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0); +- } ++ TRY_CATCH (e, RETURN_MASK_ERROR) ++ { ++ sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, ++ not_found_ptr); ++ } ++ if (e.reason < 0) ++ { ++ int not_found_and_ok = 0; ++ /* For pending breakpoints, it's expected that parsing ++ will fail until the right shared library is loaded. ++ User has already told to create pending breakpoints and ++ don't need extra messages. If breakpoint is in bp_shlib_disabled ++ state, then user already saw the message about that breakpoint ++ being disabled, and don't want to see more errors. */ ++ if (not_found && (b->pending || b->enable_state == bp_shlib_disabled ++ || b->enable_state == bp_disabled)) ++ not_found_and_ok = 1; + +- /* We need to re-set the breakpoint if the address changes... */ +- if (b->loc->address != sals.sals[i].pc +- /* ...or new and old breakpoints both have source files, and +- the source file name or the line number changes... */ +- || (b->source_file != NULL +- && sals.sals[i].symtab != NULL +- && (strcmp (b->source_file, sals.sals[i].symtab->filename) != 0 +- || b->line_number != sals.sals[i].line) +- ) +- /* ...or we switch between having a source file and not having +- one. */ +- || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL)) +- ) ++ if (!not_found_and_ok) + { +- if (b->source_file != NULL) +- xfree (b->source_file); +- if (sals.sals[i].symtab == NULL) +- b->source_file = NULL; +- else +- b->source_file = +- savestring (sals.sals[i].symtab->filename, +- strlen (sals.sals[i].symtab->filename)); +- b->line_number = sals.sals[i].line; +- b->loc->requested_address = sals.sals[i].pc; +- b->loc->address +- = adjust_breakpoint_address (b->loc->requested_address, +- b->type); +- +- /* Used to check for duplicates here, but that can +- cause trouble, as it doesn't check for disabled +- breakpoints. */ +- +- mention (b); +- +- /* Might be better to do this just once per breakpoint_re_set, +- rather than once for every breakpoint. */ +- breakpoints_changed (); ++ /* We surely don't want to warn about the same breakpoint ++ 10 times. One solution, implemented here, is disable ++ the breakpoint on error. Another solution would be to ++ have separate 'warning emitted' flag. Since this ++ happens only when a binary has changed, I don't know ++ which approach is better. */ ++ b->enable_state = bp_disabled; ++ throw_exception (e); + } +- b->loc->section = sals.sals[i].section; +- b->enable_state = save_enable; /* Restore it, this worked. */ ++ } + ++ if (not_found) ++ break; ++ ++ gdb_assert (sals.nelts == 1); ++ resolve_sal_pc (&sals.sals[0]); ++ if (b->pending && s && s[0]) ++ { ++ char *cond_string = 0; ++ int thread = -1; ++ find_condition_and_thread (s, sals.sals[0].pc, ++ &cond_string, &thread); ++ if (cond_string) ++ b->cond_string = cond_string; ++ b->thread = thread; ++ } + +- /* Now that this is re-enabled, check_duplicates +- can be used. */ +- check_duplicates (b); ++ update_breakpoint_location (b, sals); + +- } + xfree (sals.sals); + break; + +@@ -7408,7 +7375,7 @@ + ALL_BREAKPOINTS_SAFE (b, temp) + { + /* Format possible error msg */ +- char *message = xstrprintf ("Error in re-setting breakpoint %d:\n", ++ char *message = xstrprintf ("Error in re-setting breakpoint %d: ", + b->number); + struct cleanup *cleanups = make_cleanup (xfree, message); + catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL); +@@ -7635,88 +7602,68 @@ + error (_("Hardware breakpoints used exceeds limit.")); + } + +- if (bpt->pending) ++ if (bpt->enable_state != bp_permanent) ++ bpt->enable_state = bp_enabled; ++ bpt->disposition = disposition; ++ check_duplicates (bpt); ++ breakpoints_changed (); ++ ++ if (bpt->type == bp_watchpoint || ++ bpt->type == bp_hardware_watchpoint || ++ bpt->type == bp_read_watchpoint || ++ bpt->type == bp_access_watchpoint) + { +- if (bpt->enable_state != bp_enabled) ++ struct frame_id saved_frame_id; ++ ++ saved_frame_id = get_frame_id (get_selected_frame (NULL)); ++ if (bpt->exp_valid_block != NULL) + { +- /* When enabling a pending breakpoint, we need to check if the breakpoint +- is resolvable since shared libraries could have been loaded +- after the breakpoint was disabled. */ +- breakpoints_changed (); +- if (resolve_pending_breakpoint (bpt) == GDB_RC_OK) ++ struct frame_info *fr = ++ fr = frame_find_by_id (bpt->watchpoint_frame); ++ if (fr == NULL) + { +- delete_breakpoint (bpt); ++ printf_filtered (_("\ ++Cannot enable watchpoint %d because the block in which its expression\n\ ++is valid is not currently in scope.\n"), bpt->number); ++ bpt->enable_state = bp_disabled; + return; + } +- bpt->enable_state = bp_enabled; +- bpt->disposition = disposition; ++ select_frame (fr); + } +- } +- else /* Not a pending breakpoint. */ +- { +- if (bpt->enable_state != bp_permanent) +- bpt->enable_state = bp_enabled; +- bpt->disposition = disposition; +- check_duplicates (bpt); +- breakpoints_changed (); + +- if (bpt->type == bp_watchpoint || +- bpt->type == bp_hardware_watchpoint || +- bpt->type == bp_read_watchpoint || ++ value_free (bpt->val); ++ mark = value_mark (); ++ bpt->val = evaluate_expression (bpt->exp); ++ release_value (bpt->val); ++ if (value_lazy (bpt->val)) ++ value_fetch_lazy (bpt->val); ++ ++ if (bpt->type == bp_hardware_watchpoint || ++ bpt->type == bp_read_watchpoint || + bpt->type == bp_access_watchpoint) + { +- struct frame_id saved_frame_id; +- +- saved_frame_id = get_frame_id (get_selected_frame (NULL)); +- if (bpt->exp_valid_block != NULL) +- { +- struct frame_info *fr = +- fr = frame_find_by_id (bpt->watchpoint_frame); +- if (fr == NULL) +- { +- printf_filtered (_("\ +-Cannot enable watchpoint %d because the block in which its expression\n\ +-is valid is not currently in scope.\n"), bpt->number); +- bpt->enable_state = bp_disabled; +- return; +- } +- select_frame (fr); +- } +- +- value_free (bpt->val); +- mark = value_mark (); +- bpt->val = evaluate_expression (bpt->exp); +- release_value (bpt->val); +- if (value_lazy (bpt->val)) +- value_fetch_lazy (bpt->val); ++ int i = hw_watchpoint_used_count (bpt->type, &other_type_used); ++ int mem_cnt = can_use_hardware_watchpoint (bpt->val); + +- if (bpt->type == bp_hardware_watchpoint || +- bpt->type == bp_read_watchpoint || +- bpt->type == bp_access_watchpoint) ++ /* Hack around 'unused var' error for some targets here */ ++ (void) mem_cnt, (void) i; ++ target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT ( ++ bpt->type, i + mem_cnt, other_type_used); ++ /* we can consider of type is bp_hardware_watchpoint, convert to ++ bp_watchpoint in the following condition */ ++ if (target_resources_ok < 0) + { +- int i = hw_watchpoint_used_count (bpt->type, &other_type_used); +- int mem_cnt = can_use_hardware_watchpoint (bpt->val); +- +- /* Hack around 'unused var' error for some targets here */ +- (void) mem_cnt, (void) i; +- target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT ( +- bpt->type, i + mem_cnt, other_type_used); +- /* we can consider of type is bp_hardware_watchpoint, convert to +- bp_watchpoint in the following condition */ +- if (target_resources_ok < 0) +- { +- printf_filtered (_("\ ++ printf_filtered (_("\ + Cannot enable watchpoint %d because target watch resources\n\ + have been allocated for other watchpoints.\n"), bpt->number); +- bpt->enable_state = bp_disabled; +- value_free_to_mark (mark); +- return; +- } ++ bpt->enable_state = bp_disabled; ++ value_free_to_mark (mark); ++ return; + } +- +- select_frame (frame_find_by_id (saved_frame_id)); +- value_free_to_mark (mark); + } ++ ++ select_frame (frame_find_by_id (saved_frame_id)); ++ value_free_to_mark (mark); + } + + if (deprecated_modify_breakpoint_hook) +@@ -7724,6 +7671,7 @@ + breakpoint_modify_event (bpt->number); + } + ++ + void + enable_breakpoint (struct breakpoint *bpt) + { +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.h,v +retrieving revision 1.49 +retrieving revision 1.50 +diff -u -r1.49 -r1.50 +--- src/gdb/breakpoint.h 2007/09/22 19:06:59 1.49 ++++ src/gdb/breakpoint.h 2007/09/22 19:33:31 1.50 +@@ -799,8 +799,6 @@ + + extern void disable_breakpoints_in_shlibs (void); + +-extern void re_enable_breakpoints_in_shlibs (void); +- + extern void create_solib_load_event_breakpoint (char *, int, char *, char *); + + extern void create_solib_unload_event_breakpoint (char *, int, +=================================================================== +RCS file: /cvs/src/src/gdb/infcmd.c,v +retrieving revision 1.158 +retrieving revision 1.159 +diff -u -r1.158 -r1.159 +--- src/gdb/infcmd.c 2007/09/04 01:38:07 1.158 ++++ src/gdb/infcmd.c 2007/09/22 19:33:31 1.159 +@@ -433,10 +433,6 @@ + #else + solib_create_inferior_hook (); + #endif +- +- /* Enable any breakpoints which were disabled when the +- underlying shared library was deleted. */ +- re_enable_breakpoints_in_shlibs (); + } + + observer_notify_inferior_created (target, from_tty); +=================================================================== +RCS file: /cvs/src/src/gdb/infrun.c,v +retrieving revision 1.247 +retrieving revision 1.248 +diff -u -r1.247 -r1.248 +--- src/gdb/infrun.c 2007/09/17 19:44:20 1.247 ++++ src/gdb/infrun.c 2007/09/22 19:33:31 1.248 +@@ -1337,10 +1337,6 @@ + #endif + target_terminal_inferior (); + +- /* Try to reenable shared library breakpoints, additional +- code segments in shared libraries might be mapped in now. */ +- re_enable_breakpoints_in_shlibs (); +- + /* If requested, stop when the dynamic linker notifies + gdb of events. This allows the user to get control + and place breakpoints in initializer routines for +@@ -2276,10 +2272,6 @@ + #endif + target_terminal_inferior (); + +- /* Try to reenable shared library breakpoints, additional +- code segments in shared libraries might be mapped in now. */ +- re_enable_breakpoints_in_shlibs (); +- + /* If requested, stop when the dynamic linker notifies + gdb of events. This allows the user to get control + and place breakpoints in initializer routines for +=================================================================== +RCS file: /cvs/src/src/gdb/solib-irix.c,v +retrieving revision 1.14 +retrieving revision 1.15 +diff -u -r1.14 -r1.15 +--- src/gdb/solib-irix.c 2007/08/23 18:08:38 1.14 ++++ src/gdb/solib-irix.c 2007/09/22 19:33:31 1.15 +@@ -457,7 +457,6 @@ + suppresses the warning. */ + solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add); + stop_soon = NO_STOP_QUIETLY; +- re_enable_breakpoints_in_shlibs (); + } + + /* LOCAL FUNCTION +=================================================================== +RCS file: /cvs/src/src/gdb/solib-osf.c,v +retrieving revision 1.11 +retrieving revision 1.12 +diff -u -r1.11 -r1.12 +--- src/gdb/solib-osf.c 2007/08/23 18:08:38 1.11 ++++ src/gdb/solib-osf.c 2007/09/22 19:33:31 1.12 +@@ -336,9 +336,6 @@ + suppresses the warning. */ + solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add); + stop_soon = NO_STOP_QUIETLY; +- +- /* Enable breakpoints disabled (unnecessarily) by clear_solib(). */ +- re_enable_breakpoints_in_shlibs (); + } + + /* target_so_ops callback. Do additional symbol handling, lookup, etc. after + +2007-09-22 Vladimir Prus + + * gdb.base/pending.exp: No longer expect "Pending breakpoint resolved" + messages. + * gdb.base/chng-syms.exp: Likewise. + * gdb.base/unload.exp: Likewise. + +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/chng-syms.exp,v +retrieving revision 1.8 +retrieving revision 1.9 +diff -u -r1.8 -r1.9 +--- src/gdb/testsuite/gdb.base/chng-syms.exp 2007/08/23 18:14:16 1.8 ++++ src/gdb/testsuite/gdb.base/chng-syms.exp 2007/09/22 19:33:32 1.9 +@@ -105,10 +105,10 @@ + + gdb_run_cmd + gdb_expect { +- -re "Error in re-setting .*No symbol .var1..*Program exited normally.*$gdb_prompt $" { ++ -re ".*No symbol .var1..*Program exited normally.*$gdb_prompt $" { + pass "running with invalidated bpt condition after executable changes" + } +- -re "Error in re-setting .*No symbol .var1..*Breakpoint .*,( 0x.* in)? (\[^ \]*)exit .*$gdb_prompt $" { ++ -re "No symbol .var1..*Breakpoint .*,( 0x.* in)? (\[^ \]*)exit .*$gdb_prompt $" { + pass "running with invalidated bpt condition after executable changes" + } + -re "$gdb_prompt $" { +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/pending.exp,v +retrieving revision 1.10 +retrieving revision 1.11 +diff -u -r1.10 -r1.11 +--- src/gdb/testsuite/gdb.base/pending.exp 2007/08/23 18:14:17 1.10 ++++ src/gdb/testsuite/gdb.base/pending.exp 2007/09/22 19:33:32 1.11 +@@ -194,9 +194,7 @@ + + gdb_run_cmd + gdb_test "" \ +-"Breakpoint.*at.* +-Pending breakpoint \"pendshr.c:$bp2_loc if x > 3\" resolved.* +-Breakpoint.*, main.*$mainline.*" \ ++".*Breakpoint.*, main.*$mainline.*" \ + "running to main" + + # +@@ -204,8 +202,7 @@ + # + + gdb_test "enable 1" \ +-"Breakpoint.*at.* +-Pending breakpoint \"pendfunc1.* resolved.*" \ ++"" \ + "re-enabling pending breakpoint that can resolve instantly" + + # +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/unload.exp,v +retrieving revision 1.11 +retrieving revision 1.12 +diff -u -r1.11 -r1.12 +--- src/gdb/testsuite/gdb.base/unload.exp 2007/08/23 18:14:17 1.11 ++++ src/gdb/testsuite/gdb.base/unload.exp 2007/09/22 19:33:32 1.12 +@@ -89,9 +89,7 @@ + + gdb_run_cmd + gdb_test "" \ +-"Breakpoint.*at.* +-Pending breakpoint \"shrfunc1\" resolved.* +-Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \ ++".*Breakpoint.*, shrfunc1 \\\(x=3\\\).*unloadshr.c:$unloadshr_line.*" \ + "running program" + + gdb_test "continue" \ + +2007-09-23 Vladimir Prus + + Allow a code breakpoint to have several locations + associated with it. + * breakpoint.h (enum enable_state): Remove the + bp_shlib_disabled enumerator. + (struct bp_location): New members shlib_disabled, + global_next, enabled and function_name. + Rename pending to condition_not_parsed. + + * breakpoint.c (ALL_BP_LOCATIONS): Iterate over global_next. + (ALL_BP_LOCATIONS_SAFE): Likewise. + (breakpoint_enabled): Don't check for pending. + (condition_command): Free and update all locations of + a breakpoint. + (insert_bp_location): Adjust. + (software_breakpoint_inserted_here_p): Don't care + if breakpoint is enabled, as soon as it's inserted. + (print_it_typical): Print bpstat's location, not + bpstat's breakpoint's location. + (bpstat_stop_status): Iterate over all locations, not + all breakpoints. + (print_breakpoint_location): New. + (print_one_breakpoint): Renamed to + (print_one_breakpoint_location): ...this. Take + parameters to describe which location is being + printed. Modify code to properly print header + for several locations and individual locations. + (print_one_breakpoint): Print all locations. + (breakpoint_has_pc): New. + (describe_other_breakpoints): Use the above. + (check_duplicates): Renamed to... + (check_duplicates_for): .. this. + (check_duplicates): Use check_duplicates_for. + (allocate_bp_location): Adjust. + (set_raw_breakpoint_without_location): New, + extracted from set_raw_breakpoint. + (set_breakpoint_location_function): New. + (set_raw_breakpoint): Use + set_raw_breakpoint_without_location. + (make_breakpoint_permanent): Mark all locations + as inserted. + (disable_breakpoints_in_shlibs): Iterate over + locations. + (disable_breakpoints_in_unloaded_shlib): Likewise. + (re_enable_breakpoints_in_shlibs): Likewise. + (mention): Say "pending" when breakpoint has + zero locations. If breakpoint has more than one + location, say so. + (add_location_to_breakpoint): New. + (create_breakpoint): Accept symtabs_and_lines, not + symtab_and_line. Pass extra sals to + add_location_to_breakpoint. + (create_breakpoints): Pass symtabs_and_lines to + create_breakpoints. + (break_command_1): Make pending breakpoints + have zero locations. + (do_captured_breakpoint): Remove wrong allocation. + (clear_command): Iterate over all locations. + (unlink_locations_from_global_list): Renamed + from unlink_location_from_global_list. Remove + all locations. + (delete_breakpoint): Remove all locations. + Iterate over all locations when deciding which + other location to re-enable. + (all_locations_are_pending): New. + (update_breakpoint_locations): Renamed from + update_breakpoint_location. Try to match old + and new locations using names of containing + functions. + (breakpoint_re_set_one): Adjust. + (find_location_by_number): New. + (disable_command): Allow disabling individual location. + (enable_command): Allow enabling individual location. + * breakpoint.c: Adjust all uses of breakpoint's + enable state to for bp_shlib_disabled change. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.267 +retrieving revision 1.268 +diff -u -r1.267 -r1.268 +--- src/gdb/breakpoint.c 2007/09/22 19:33:31 1.267 ++++ src/gdb/breakpoint.c 2007/09/23 07:56:22 1.268 +@@ -275,11 +275,11 @@ + + /* Similar iterators for the low-level breakpoints. */ + +-#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->next) ++#define ALL_BP_LOCATIONS(B) for (B = bp_location_chain; B; B = B->global_next) + + #define ALL_BP_LOCATIONS_SAFE(B,TMP) \ + for (B = bp_location_chain; \ +- B ? (TMP=B->next, 1): 0; \ ++ B ? (TMP=B->global_next, 1): 0; \ + B = TMP) + + /* True if breakpoint hit counts should be displayed in breakpoint info. */ +@@ -356,7 +356,7 @@ + static int + breakpoint_enabled (struct breakpoint *b) + { +- return (b->enable_state == bp_enabled && !b->pending); ++ return (b->enable_state == bp_enabled); + } + + /* Set breakpoint count to NUM. */ +@@ -572,10 +572,13 @@ + if (b->number == bnum) + { + struct bp_location *loc = b->loc; +- if (loc->cond) ++ for (; loc; loc = loc->next) + { +- xfree (loc->cond); +- loc->cond = 0; ++ if (loc->cond) ++ { ++ xfree (loc->cond); ++ loc->cond = 0; ++ } + } + if (b->cond_string != NULL) + xfree (b->cond_string); +@@ -592,10 +595,11 @@ + /* I don't know if it matters whether this is the string the user + typed in or the decompiled expression. */ + b->cond_string = savestring (arg, strlen (arg)); +- if (!b->pending) ++ b->condition_not_parsed = 0; ++ for (loc = b->loc; loc; loc = loc->next) + { +- b->loc->cond = parse_exp_1 (&arg, +- block_for_pc (b->loc->address), 0); ++ arg = p; ++ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0); + if (*arg) + error (_("Junk at end of expression")); + } +@@ -846,7 +850,7 @@ + if (!breakpoint_enabled (bpt->owner)) + return 0; + +- if (bpt->inserted || bpt->duplicate) ++ if (!bpt->enabled || bpt->shlib_disabled || bpt->inserted || bpt->duplicate) + return 0; + + /* Initialize the target-specific information. */ +@@ -969,7 +973,7 @@ + { + /* See also: disable_breakpoints_in_shlibs. */ + val = 0; +- bpt->owner->enable_state = bp_shlib_disabled; ++ bpt->shlib_disabled = 1; + if (!*disabled_breaks) + { + fprintf_unfiltered (tmp_error_stream, +@@ -1808,9 +1812,7 @@ + if (bpt->loc_type != bp_loc_software_breakpoint) + continue; + +- if ((breakpoint_enabled (bpt->owner) +- || bpt->owner->enable_state == bp_permanent) +- && bpt->inserted ++ if (bpt->inserted + && bpt->address == pc) /* bp is enabled and matches pc */ + { + if (overlay_debugging +@@ -2160,6 +2162,7 @@ + { + struct cleanup *old_chain, *ui_out_chain; + struct breakpoint *b; ++ struct bp_location *bl; + struct ui_stream *stb; + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); +@@ -2167,15 +2170,16 @@ + which has since been deleted. */ + if (bs->breakpoint_at == NULL) + return PRINT_UNKNOWN; +- b = bs->breakpoint_at->owner; ++ bl = bs->breakpoint_at; ++ b = bl->owner; + + switch (b->type) + { + case bp_breakpoint: + case bp_hardware_breakpoint: +- if (b->loc->address != b->loc->requested_address) +- breakpoint_adjustment_warning (b->loc->requested_address, +- b->loc->address, ++ if (bl->address != bl->requested_address) ++ breakpoint_adjustment_warning (bl->requested_address, ++ bl->address, + b->number, 1); + annotate_breakpoint (b->number); + ui_out_text (uiout, "\nBreakpoint "); +@@ -2672,7 +2676,8 @@ + bpstat + bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid, int stopped_by_watchpoint) + { +- struct breakpoint *b, *temp; ++ struct breakpoint *b = NULL; ++ struct bp_location *bl; + /* True if we've hit a breakpoint (as opposed to a watchpoint). */ + int real_breakpoint = 0; + /* Root of the chain of bpstat's */ +@@ -2681,8 +2686,10 @@ + bpstat bs = root_bs; + int thread_id = pid_to_thread_id (ptid); + +- ALL_BREAKPOINTS_SAFE (b, temp) ++ ALL_BP_LOCATIONS (bl) + { ++ b = bl->owner; ++ gdb_assert (b); + if (!breakpoint_enabled (b) && b->enable_state != bp_permanent) + continue; + +@@ -2697,11 +2704,11 @@ + && b->type != bp_catch_catch + && b->type != bp_catch_throw) /* a non-watchpoint bp */ + { +- if (b->loc->address != bp_addr) /* address doesn't match */ ++ if (bl->address != bp_addr) /* address doesn't match */ + continue; + if (overlay_debugging /* unmapped overlay section */ +- && section_is_overlay (b->loc->section) +- && !section_is_mapped (b->loc->section)) ++ && section_is_overlay (bl->section) ++ && !section_is_mapped (bl->section)) + continue; + } + +@@ -2719,11 +2726,11 @@ + + if (b->type == bp_hardware_breakpoint) + { +- if (b->loc->address != bp_addr) ++ if (bl->address != bp_addr) + continue; + if (overlay_debugging /* unmapped overlay section */ +- && section_is_overlay (b->loc->section) +- && !section_is_mapped (b->loc->section)) ++ && section_is_overlay (bl->section) ++ && !section_is_mapped (bl->section)) + continue; + } + +@@ -2774,7 +2781,7 @@ + + /* Come here if it's a watchpoint, or if the break address matches */ + +- bs = bpstat_alloc (b->loc, bs); /* Alloc a bpstat to explain stop */ ++ bs = bpstat_alloc (bl, bs); /* Alloc a bpstat to explain stop */ + + /* Watchpoints may change this, if not found to have triggered. */ + bs->stop = 1; +@@ -2926,19 +2933,19 @@ + { + int value_is_zero = 0; + +- if (b->loc->cond) ++ if (bl->cond) + { + /* Need to select the frame, with all that implies + so that the conditions will have the right context. */ + select_frame (get_current_frame ()); + value_is_zero +- = catch_errors (breakpoint_cond_eval, (b->loc->cond), ++ = catch_errors (breakpoint_cond_eval, (bl->cond), + "Error in testing breakpoint condition:\n", + RETURN_MASK_ALL); + /* FIXME-someday, should give breakpoint # */ + free_all_values (); + } +- if (b->loc->cond && value_is_zero) ++ if (bl->cond && value_is_zero) + { + bs->stop = 0; + /* Don't consider this a hit. */ +@@ -2985,9 +2992,9 @@ + /* The value of a hardware watchpoint hasn't changed, but the + intermediate memory locations we are watching may have. */ + if (bs && !bs->stop && +- (bs->breakpoint_at->owner->type == bp_hardware_watchpoint || +- bs->breakpoint_at->owner->type == bp_read_watchpoint || +- bs->breakpoint_at->owner->type == bp_access_watchpoint)) ++ (b->type == bp_hardware_watchpoint || ++ b->type == bp_read_watchpoint || ++ b->type == bp_access_watchpoint)) + { + remove_breakpoints (); + insert_breakpoints (); +@@ -3349,10 +3356,54 @@ + *cp_list = bs; + } + ++static void print_breakpoint_location (struct breakpoint *b, ++ struct bp_location *loc, ++ char *wrap_indent, ++ struct ui_stream *stb) ++{ ++ if (b->source_file) ++ { ++ struct symbol *sym ++ = find_pc_sect_function (loc->address, loc->section); ++ if (sym) ++ { ++ ui_out_text (uiout, "in "); ++ ui_out_field_string (uiout, "func", ++ SYMBOL_PRINT_NAME (sym)); ++ ui_out_wrap_hint (uiout, wrap_indent); ++ ui_out_text (uiout, " at "); ++ } ++ ui_out_field_string (uiout, "file", b->source_file); ++ ui_out_text (uiout, ":"); ++ ++ if (ui_out_is_mi_like_p (uiout)) ++ { ++ struct symtab_and_line sal = find_pc_line (loc->address, 0); ++ char *fullname = symtab_to_fullname (sal.symtab); ++ ++ if (fullname) ++ ui_out_field_string (uiout, "fullname", fullname); ++ } ++ ++ ui_out_field_int (uiout, "line", b->line_number); ++ } ++ else if (!b->loc) ++ { ++ ui_out_field_string (uiout, "pending", b->addr_string); ++ } ++ else ++ { ++ print_address_symbolic (loc->address, stb->stream, demangle, ""); ++ ui_out_field_stream (uiout, "at", stb); ++ } ++} ++ + /* Print B to gdb_stdout. */ + static void +-print_one_breakpoint (struct breakpoint *b, +- CORE_ADDR *last_addr) ++print_one_breakpoint_location (struct breakpoint *b, ++ struct bp_location *loc, ++ int loc_number, ++ CORE_ADDR *last_addr) + { + struct command_line *l; + struct symbol *sym; +@@ -3397,30 +3448,80 @@ + struct cleanup *old_chain = make_cleanup_ui_out_stream_delete (stb); + struct cleanup *bkpt_chain; + ++ int header_of_multiple = 0; ++ int part_of_multiple = (loc != NULL); ++ ++ gdb_assert (!loc || loc_number != 0); ++ /* See comment in print_one_breakpoint concerning ++ treatment of breakpoints with single disabled ++ location. */ ++ if (loc == NULL ++ && (b->loc != NULL ++ && (b->loc->next != NULL || !b->loc->enabled))) ++ header_of_multiple = 1; ++ if (loc == NULL) ++ loc = b->loc; ++ + annotate_record (); + bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt"); + + /* 1 */ + annotate_field (0); +- ui_out_field_int (uiout, "number", b->number); ++ if (part_of_multiple) ++ { ++ char *formatted; ++ asprintf (&formatted, "%d.%d", b->number, loc_number); ++ ui_out_field_string (uiout, "number", formatted); ++ xfree (formatted); ++ } ++ else ++ { ++ ui_out_field_int (uiout, "number", b->number); ++ } + + /* 2 */ + annotate_field (1); +- if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0]))) +- || ((int) b->type != bptypes[(int) b->type].type)) +- internal_error (__FILE__, __LINE__, +- _("bptypes table does not describe type #%d."), +- (int) b->type); +- ui_out_field_string (uiout, "type", bptypes[(int) b->type].description); ++ if (part_of_multiple) ++ ui_out_field_skip (uiout, "type"); ++ else ++ { ++ if (((int) b->type >= (sizeof (bptypes) / sizeof (bptypes[0]))) ++ || ((int) b->type != bptypes[(int) b->type].type)) ++ internal_error (__FILE__, __LINE__, ++ _("bptypes table does not describe type #%d."), ++ (int) b->type); ++ ui_out_field_string (uiout, "type", bptypes[(int) b->type].description); ++ } + + /* 3 */ + annotate_field (2); +- ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]); ++ if (part_of_multiple) ++ ui_out_field_skip (uiout, "disp"); ++ else ++ ui_out_field_string (uiout, "disp", bpdisps[(int) b->disposition]); ++ + + /* 4 */ + annotate_field (3); +- ui_out_field_fmt (uiout, "enabled", "%c", bpenables[(int) b->enable_state]); +- ui_out_spaces (uiout, 2); ++ if (part_of_multiple) ++ ui_out_field_string (uiout, "enabled", ++ loc->shlib_disabled ++ ? (loc->enabled ? "y(p)" : "n(p)") ++ : (loc->enabled ? "y" : "n")); ++ else ++ { ++ int pending = (b->loc == NULL || b->loc->shlib_disabled); ++ /* For header of multiple, there's no point showing pending ++ state -- it will be apparent from the locations. */ ++ if (header_of_multiple) ++ pending = 0; ++ ui_out_field_fmt (uiout, "enabled", "%c%s", ++ bpenables[(int) b->enable_state], ++ pending ? "(p)" : ""); ++ if (!pending) ++ ui_out_spaces (uiout, 3); ++ } ++ + + /* 5 and 6 */ + strcpy (wrap_indent, " "); +@@ -3433,7 +3534,14 @@ + } + + if (b->ops != NULL && b->ops->print_one != NULL) +- b->ops->print_one (b, last_addr); ++ { ++ /* Although the print_one can possibly print ++ all locations, calling it here is not likely ++ to get any nice result. So, make sure there's ++ just one location. */ ++ gdb_assert (b->loc == NULL || b->loc->next == NULL); ++ b->ops->print_one (b, last_addr); ++ } + else + switch (b->type) + { +@@ -3545,51 +3653,22 @@ + if (addressprint) + { + annotate_field (4); +- if (b->pending) ++ if (b->loc == NULL) + ui_out_field_string (uiout, "addr", ""); ++ else if (header_of_multiple) ++ ui_out_field_string (uiout, "addr", ""); + else +- ui_out_field_core_addr (uiout, "addr", b->loc->address); ++ ui_out_field_core_addr (uiout, "addr", loc->address); + } + annotate_field (5); +- *last_addr = b->loc->address; +- if (b->source_file) +- { +- sym = find_pc_sect_function (b->loc->address, b->loc->section); +- if (sym) +- { +- ui_out_text (uiout, "in "); +- ui_out_field_string (uiout, "func", +- SYMBOL_PRINT_NAME (sym)); +- ui_out_wrap_hint (uiout, wrap_indent); +- ui_out_text (uiout, " at "); +- } +- ui_out_field_string (uiout, "file", b->source_file); +- ui_out_text (uiout, ":"); +- +- if (ui_out_is_mi_like_p (uiout)) +- { +- struct symtab_and_line sal = find_pc_line (b->loc->address, 0); +- char *fullname = symtab_to_fullname (sal.symtab); +- +- if (fullname) +- ui_out_field_string (uiout, "fullname", fullname); +- } +- +- ui_out_field_int (uiout, "line", b->line_number); +- } +- else if (b->pending) +- { +- ui_out_field_string (uiout, "pending", b->addr_string); +- } +- else +- { +- print_address_symbolic (b->loc->address, stb->stream, demangle, ""); +- ui_out_field_stream (uiout, "at", stb); +- } ++ if (!header_of_multiple) ++ print_breakpoint_location (b, loc, wrap_indent, stb); ++ if (b->loc) ++ *last_addr = b->loc->address; + break; + } + +- if (b->thread != -1) ++ if (!part_of_multiple && b->thread != -1) + { + /* FIXME: This seems to be redundant and lost here; see the + "stop only in" line a little further down. */ +@@ -3599,7 +3678,7 @@ + + ui_out_text (uiout, "\n"); + +- if (frame_id_p (b->frame_id)) ++ if (part_of_multiple && frame_id_p (b->frame_id)) + { + annotate_field (6); + ui_out_text (uiout, "\tstop only in stack frame at "); +@@ -3609,27 +3688,18 @@ + ui_out_text (uiout, "\n"); + } + +- if (b->loc->cond && !ada_exception_catchpoint_p (b)) ++ if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b)) + { + /* We do not print the condition for Ada exception catchpoints + because the condition is an internal implementation detail + that we do not want to expose to the user. */ + annotate_field (7); + ui_out_text (uiout, "\tstop only if "); +- print_expression (b->loc->cond, stb->stream); +- ui_out_field_stream (uiout, "cond", stb); +- ui_out_text (uiout, "\n"); +- } +- +- if (b->pending && b->cond_string) +- { +- annotate_field (7); +- ui_out_text (uiout, "\tstop only if "); + ui_out_field_string (uiout, "cond", b->cond_string); + ui_out_text (uiout, "\n"); + } + +- if (b->thread != -1) ++ if (!part_of_multiple && b->thread != -1) + { + /* FIXME should make an annotation for this */ + ui_out_text (uiout, "\tstop only in thread "); +@@ -3637,7 +3707,7 @@ + ui_out_text (uiout, "\n"); + } + +- if (show_breakpoint_hit_counts && b->hit_count) ++ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count) + { + /* FIXME should make an annotation for this */ + if (ep_is_catchpoint (b)) +@@ -3655,10 +3725,10 @@ + /* Output the count also if it is zero, but only if this is + mi. FIXME: Should have a better test for this. */ + if (ui_out_is_mi_like_p (uiout)) +- if (show_breakpoint_hit_counts && b->hit_count == 0) ++ if (!part_of_multiple && show_breakpoint_hit_counts && b->hit_count == 0) + ui_out_field_int (uiout, "times", b->hit_count); + +- if (b->ignore_count) ++ if (!part_of_multiple && b->ignore_count) + { + annotate_field (8); + ui_out_text (uiout, "\tignore next "); +@@ -3666,7 +3736,7 @@ + ui_out_text (uiout, " hits\n"); + } + +- if ((l = b->commands)) ++ if (!part_of_multiple && (l = b->commands)) + { + struct cleanup *script_chain; + +@@ -3679,6 +3749,35 @@ + do_cleanups (old_chain); + } + ++static void ++print_one_breakpoint (struct breakpoint *b, ++ CORE_ADDR *last_addr) ++{ ++ print_one_breakpoint_location (b, NULL, 0, last_addr); ++ ++ /* If this breakpoint has custom print function, ++ it's already printed. Otherwise, print individual ++ locations, if any. */ ++ if (b->ops == NULL || b->ops->print_one == NULL) ++ { ++ /* If breakpoint has a single location that is ++ disabled, we print it as if it had ++ several locations, since otherwise it's hard to ++ represent "breakpoint enabled, location disabled" ++ situation. */ ++ if (b->loc ++ && (b->loc->next || !b->loc->enabled) ++ && !ui_out_is_mi_like_p (uiout)) ++ { ++ struct bp_location *loc; ++ int n = 1; ++ for (loc = b->loc; loc; loc = loc->next, ++n) ++ print_one_breakpoint_location (b, loc, n, last_addr); ++ } ++ } ++} ++ ++ + struct captured_breakpoint_query_args + { + int bnum; +@@ -3771,7 +3870,7 @@ + annotate_breakpoints_headers (); + if (nr_printable_breakpoints > 0) + annotate_field (0); +- ui_out_table_header (uiout, 3, ui_left, "number", "Num"); /* 1 */ ++ ui_out_table_header (uiout, 7, ui_left, "number", "Num"); /* 1 */ + if (nr_printable_breakpoints > 0) + annotate_field (1); + ui_out_table_header (uiout, 14, ui_left, "type", "Type"); /* 2 */ +@@ -3780,7 +3879,7 @@ + ui_out_table_header (uiout, 4, ui_left, "disp", "Disp"); /* 3 */ + if (nr_printable_breakpoints > 0) + annotate_field (3); +- ui_out_table_header (uiout, 3, ui_left, "enabled", "Enb"); /* 4 */ ++ ui_out_table_header (uiout, 4, ui_left, "enabled", "Enb"); /* 4 */ + if (addressprint) + { + if (nr_printable_breakpoints > 0) +@@ -3852,6 +3951,19 @@ + breakpoint_1 (bnum, 1); + } + ++static int ++breakpoint_has_pc (struct breakpoint *b, CORE_ADDR pc, asection *section) ++{ ++ struct bp_location *bl = b->loc; ++ for (; bl; bl = bl->next) ++ { ++ if (bl->address == pc ++ && (!overlay_debugging || bl->section == section)) ++ return 1; ++ } ++ return 0; ++} ++ + /* Print a message describing any breakpoints set at PC. */ + + static void +@@ -3861,9 +3973,7 @@ + struct breakpoint *b; + + ALL_BREAKPOINTS (b) +- if (b->loc->address == pc) /* address match / overlay match */ +- if (!b->pending && (!overlay_debugging || b->loc->section == section)) +- others++; ++ others += breakpoint_has_pc (b, pc, section); + if (others > 0) + { + if (others == 1) +@@ -3871,26 +3981,24 @@ + else /* if (others == ???) */ + printf_filtered (_("Note: breakpoints ")); + ALL_BREAKPOINTS (b) +- if (b->loc->address == pc) /* address match / overlay match */ +- if (!b->pending && (!overlay_debugging || b->loc->section == section)) +- { +- others--; +- printf_filtered ("%d", b->number); +- if (b->thread == -1 && thread != -1) +- printf_filtered (" (all threads)"); +- else if (b->thread != -1) +- printf_filtered (" (thread %d)", b->thread); +- printf_filtered ("%s%s ", +- ((b->enable_state == bp_disabled || +- b->enable_state == bp_shlib_disabled || +- b->enable_state == bp_call_disabled) +- ? " (disabled)" +- : b->enable_state == bp_permanent +- ? " (permanent)" +- : ""), +- (others > 1) ? "," +- : ((others == 1) ? " and" : "")); +- } ++ if (breakpoint_has_pc (b, pc, section)) ++ { ++ others--; ++ printf_filtered ("%d", b->number); ++ if (b->thread == -1 && thread != -1) ++ printf_filtered (" (all threads)"); ++ else if (b->thread != -1) ++ printf_filtered (" (thread %d)", b->thread); ++ printf_filtered ("%s%s ", ++ ((b->enable_state == bp_disabled || ++ b->enable_state == bp_call_disabled) ++ ? " (disabled)" ++ : b->enable_state == bp_permanent ++ ? " (permanent)" ++ : ""), ++ (others > 1) ? "," ++ : ((others == 1) ? " and" : "")); ++ } + printf_filtered (_("also set at pc ")); + deprecated_print_address_numeric (pc, 1, gdb_stdout); + printf_filtered (".\n"); +@@ -3951,22 +4059,17 @@ + that one the official one, and the rest as duplicates. */ + + static void +-check_duplicates (struct breakpoint *bpt) ++check_duplicates_for (CORE_ADDR address, asection *section) + { + struct bp_location *b; + int count = 0; + struct bp_location *perm_bp = 0; +- CORE_ADDR address = bpt->loc->address; +- asection *section = bpt->loc->section; +- +- if (! breakpoint_address_is_meaningful (bpt)) +- return; + + ALL_BP_LOCATIONS (b) + if (b->owner->enable_state != bp_disabled +- && b->owner->enable_state != bp_shlib_disabled +- && !b->owner->pending + && b->owner->enable_state != bp_call_disabled ++ && b->enabled ++ && !b->shlib_disabled + && b->address == address /* address / overlay match */ + && (!overlay_debugging || b->section == section) + && breakpoint_address_is_meaningful (b->owner)) +@@ -3999,9 +4102,8 @@ + if (b != perm_bp) + { + if (b->owner->enable_state != bp_disabled +- && b->owner->enable_state != bp_shlib_disabled +- && !b->owner->pending + && b->owner->enable_state != bp_call_disabled ++ && b->enabled && !b->shlib_disabled + && b->address == address /* address / overlay match */ + && (!overlay_debugging || b->section == section) + && breakpoint_address_is_meaningful (b->owner)) +@@ -4018,6 +4120,18 @@ + } + + static void ++check_duplicates (struct breakpoint *bpt) ++{ ++ struct bp_location *bl = bpt->loc; ++ ++ if (! breakpoint_address_is_meaningful (bpt)) ++ return; ++ ++ for (; bl; bl = bl->next) ++ check_duplicates_for (bl->address, bl->section); ++} ++ ++static void + breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr, + int bnum, int have_bnum) + { +@@ -4089,6 +4203,8 @@ + + loc->owner = bpt; + loc->cond = NULL; ++ loc->shlib_disabled = 0; ++ loc->enabled = 1; + + switch (bp_type) + { +@@ -4134,9 +4250,9 @@ + bp_location_chain = loc; + else + { +- while (loc_p->next) +- loc_p = loc_p->next; +- loc_p->next = loc; ++ while (loc_p->global_next) ++ loc_p = loc_p->global_next; ++ loc_p->global_next = loc; + } + + return loc; +@@ -4149,53 +4265,21 @@ + xfree (loc); + } + +-/* set_raw_breakpoint() is a low level routine for allocating and +- partially initializing a breakpoint of type BPTYPE. The newly +- created breakpoint's address, section, source file name, and line +- number are provided by SAL. The newly created and partially +- initialized breakpoint is added to the breakpoint chain and +- is also returned as the value of this function. +- +- It is expected that the caller will complete the initialization of +- the newly created breakpoint struct as well as output any status +- information regarding the creation of a new breakpoint. In +- particular, set_raw_breakpoint() does NOT set the breakpoint +- number! Care should be taken to not allow an error() to occur +- prior to completing the initialization of the breakpoint. If this +- should happen, a bogus breakpoint will be left on the chain. */ ++/* Helper to set_raw_breakpoint below. Creates a breakpoint ++ that has type BPTYPE and has no locations as yet. */ + + struct breakpoint * +-set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype) ++set_raw_breakpoint_without_location (enum bptype bptype) + { + struct breakpoint *b, *b1; +- CORE_ADDR adjusted_address; + + b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint)); + memset (b, 0, sizeof (*b)); + +- /* Adjust the breakpoint's address prior to allocating a location. +- Once we call allocate_bp_location(), that mostly uninitialized +- location will be placed on the location chain. Adjustment of the +- breakpoint may cause read_memory_nobpt() to be called and we do +- not want its scan of the location chain to find a breakpoint and +- location that's only been partially initialized. */ +- adjusted_address = adjust_breakpoint_address (sal.pc, bptype); +- +- b->loc = allocate_bp_location (b, bptype); +- b->loc->requested_address = sal.pc; +- b->loc->address = adjusted_address; +- +- if (sal.symtab == NULL) +- b->source_file = NULL; +- else +- b->source_file = savestring (sal.symtab->filename, +- strlen (sal.symtab->filename)); +- b->loc->section = sal.section; + b->type = bptype; + b->language = current_language->la_language; + b->input_radix = input_radix; + b->thread = -1; +- b->line_number = sal.line; + b->enable_state = bp_enabled; + b->next = 0; + b->silent = 0; +@@ -4207,7 +4291,7 @@ + b->forked_inferior_pid = 0; + b->exec_pathname = NULL; + b->ops = NULL; +- b->pending = 0; ++ b->condition_not_parsed = 0; + + /* Add this breakpoint to the end of the chain + so that a list of breakpoints will come out in order +@@ -4222,6 +4306,65 @@ + b1 = b1->next; + b1->next = b; + } ++ return b; ++} ++ ++/* Initialize loc->function_name. */ ++static void ++set_breakpoint_location_function (struct bp_location *loc) ++{ ++ if (loc->owner->type == bp_breakpoint ++ || loc->owner->type == bp_hardware_breakpoint) ++ { ++ find_pc_partial_function (loc->address, &(loc->function_name), ++ NULL, NULL); ++ if (loc->function_name) ++ loc->function_name = xstrdup (loc->function_name); ++ } ++} ++ ++/* set_raw_breakpoint is a low level routine for allocating and ++ partially initializing a breakpoint of type BPTYPE. The newly ++ created breakpoint's address, section, source file name, and line ++ number are provided by SAL. The newly created and partially ++ initialized breakpoint is added to the breakpoint chain and ++ is also returned as the value of this function. ++ ++ It is expected that the caller will complete the initialization of ++ the newly created breakpoint struct as well as output any status ++ information regarding the creation of a new breakpoint. In ++ particular, set_raw_breakpoint does NOT set the breakpoint ++ number! Care should be taken to not allow an error to occur ++ prior to completing the initialization of the breakpoint. If this ++ should happen, a bogus breakpoint will be left on the chain. */ ++ ++struct breakpoint * ++set_raw_breakpoint (struct symtab_and_line sal, enum bptype bptype) ++{ ++ struct breakpoint *b = set_raw_breakpoint_without_location (bptype); ++ CORE_ADDR adjusted_address; ++ ++ /* Adjust the breakpoint's address prior to allocating a location. ++ Once we call allocate_bp_location(), that mostly uninitialized ++ location will be placed on the location chain. Adjustment of the ++ breakpoint may cause read_memory_nobpt() to be called and we do ++ not want its scan of the location chain to find a breakpoint and ++ location that's only been partially initialized. */ ++ adjusted_address = adjust_breakpoint_address (sal.pc, bptype); ++ ++ b->loc = allocate_bp_location (b, bptype); ++ b->loc->requested_address = sal.pc; ++ b->loc->address = adjusted_address; ++ ++ if (sal.symtab == NULL) ++ b->source_file = NULL; ++ else ++ b->source_file = savestring (sal.symtab->filename, ++ strlen (sal.symtab->filename)); ++ b->loc->section = sal.section; ++ b->line_number = sal.line; ++ ++ set_breakpoint_location_function (b->loc); + + check_duplicates (b); + breakpoints_changed (); +@@ -4235,10 +4378,16 @@ + void + make_breakpoint_permanent (struct breakpoint *b) + { ++ struct bp_location *bl; + b->enable_state = bp_permanent; + +- /* By definition, permanent breakpoints are already present in the code. */ +- b->loc->inserted = 1; ++ /* By definition, permanent breakpoints are already present in the code. ++ Mark all locations as inserted. For now, make_breakpoint_permanent ++ is called in just one place, so it's hard to say if it's reasonable ++ to have permanent breakpoint with multiple locations or not, ++ but it's easy to implmement. */ ++ for (bl = b->loc; bl; bl = bl->next) ++ bl->inserted = 1; + } + + static struct breakpoint * +@@ -4431,20 +4580,28 @@ + void + disable_breakpoints_in_shlibs (void) + { +- struct breakpoint *b; ++ struct bp_location *loc; + int disabled_shlib_breaks = 0; + +- ALL_BREAKPOINTS (b) ++ ALL_BP_LOCATIONS (loc) + { ++ struct breakpoint *b = loc->owner; ++ /* We apply the check to all breakpoints, including disabled ++ for those with loc->duplicate set. This is so that when breakpoint ++ becomes enabled, or the duplicate is removed, gdb will try to insert ++ all breakpoints. If we don't set shlib_disabled here, we'll try ++ to insert those breakpoints and fail. */ + if (((b->type == bp_breakpoint) || (b->type == bp_hardware_breakpoint)) +- && breakpoint_enabled (b) && !b->loc->duplicate ++ && !loc->shlib_disabled + #ifdef PC_SOLIB +- && PC_SOLIB (b->loc->address) ++ && PC_SOLIB (loc->address) + #else +- && solib_address (b->loc->address) ++ && solib_address (loc->address) + #endif + ) +- b->enable_state = bp_shlib_disabled; ++ { ++ loc->shlib_disabled = 1; ++ } + } + } + +@@ -4454,27 +4611,28 @@ + void + disable_breakpoints_in_unloaded_shlib (struct so_list *solib) + { +- struct breakpoint *b; ++ struct bp_location *loc; + int disabled_shlib_breaks = 0; + +- ALL_BREAKPOINTS (b) ++ ALL_BP_LOCATIONS (loc) + { +- if ((b->loc->loc_type == bp_loc_hardware_breakpoint +- || b->loc->loc_type == bp_loc_software_breakpoint) +- && breakpoint_enabled (b) && !b->loc->duplicate) ++ struct breakpoint *b = loc->owner; ++ if ((loc->loc_type == bp_loc_hardware_breakpoint ++ || loc->loc_type == bp_loc_software_breakpoint) ++ && !loc->shlib_disabled) + { + #ifdef PC_SOLIB +- char *so_name = PC_SOLIB (b->loc->address); ++ char *so_name = PC_SOLIB (loc->address); + #else +- char *so_name = solib_address (b->loc->address); ++ char *so_name = solib_address (loc->address); + #endif + if (so_name && !strcmp (so_name, solib->so_name)) + { +- b->enable_state = bp_shlib_disabled; ++ loc->shlib_disabled = 1; + /* At this point, we cannot rely on remove_breakpoint + succeeding so we must mark the breakpoint as not inserted + to prevent future errors occurring in remove_breakpoints. */ +- b->loc->inserted = 0; ++ loc->inserted = 0; + if (!disabled_shlib_breaks) + { + target_terminal_ours_for_output (); +@@ -4894,7 +5052,7 @@ + { + /* i18n: cagney/2005-02-11: Below needs to be merged into a + single string. */ +- if (b->pending) ++ if (b->loc == NULL) + { + printf_filtered (_(" (%s) pending."), b->addr_string); + } +@@ -4908,6 +5066,16 @@ + if (b->source_file) + printf_filtered (": file %s, line %d.", + b->source_file, b->line_number); ++ ++ if (b->loc->next) ++ { ++ struct bp_location *loc = b->loc; ++ int n = 0; ++ for (; loc; loc = loc->next) ++ ++n; ++ printf_filtered (" (%d locations)", n); ++ } ++ + } + } + do_cleanups (old_chain); +@@ -4917,6 +5085,24 @@ + } + + ++static struct bp_location * ++add_location_to_breakpoint (struct breakpoint *b, enum bptype bptype, ++ const struct symtab_and_line *sal) ++{ ++ struct bp_location *loc, **tmp; ++ ++ loc = allocate_bp_location (b, bptype); ++ for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next)) ++ ; ++ *tmp = loc; ++ loc->requested_address = sal->pc; ++ loc->address = adjust_breakpoint_address (loc->requested_address, ++ bptype); ++ loc->section = sal->section; ++ ++ set_breakpoint_location_function (loc); ++ return loc; ++} + + /* Create a breakpoint with SAL as location. Use ADDR_STRING + as textual description of the location, and COND_STRING +@@ -4926,13 +5112,14 @@ + create_breakpoints function. */ + + static void +-create_breakpoint (struct symtab_and_line sal, char *addr_string, ++create_breakpoint (struct symtabs_and_lines sals, char *addr_string, + char *cond_string, + enum bptype type, enum bpdisp disposition, + int thread, int ignore_count, int from_tty, + struct breakpoint *pending_bp) + { +- struct breakpoint *b; ++ struct breakpoint *b = NULL; ++ int i; + + if (type == bp_hardware_breakpoint) + { +@@ -4946,50 +5133,46 @@ + error (_("Hardware breakpoints used exceeds limit.")); + } + +- if (from_tty) +- describe_other_breakpoints (sal.pc, sal.section, thread); +- +- b = set_raw_breakpoint (sal, type); +- set_breakpoint_count (breakpoint_count + 1); +- b->number = breakpoint_count; +- b->thread = thread; ++ for (i = 0; i < sals.nelts; ++i) ++ { ++ struct symtab_and_line sal = sals.sals[i]; ++ struct bp_location *loc; ++ ++ if (from_tty) ++ describe_other_breakpoints (sal.pc, sal.section, thread); ++ ++ if (i == 0) ++ { ++ b = set_raw_breakpoint (sal, type); ++ set_breakpoint_count (breakpoint_count + 1); ++ b->number = breakpoint_count; ++ b->thread = thread; + +- b->cond_string = cond_string; +- b->ignore_count = ignore_count; +- b->enable_state = bp_enabled; +- b->disposition = disposition; +- /* If resolving a pending breakpoint, a check must be made to see if +- the user has specified a new condition or commands for the +- breakpoint. A new condition will override any condition that was +- initially specified with the initial breakpoint command. */ +- if (pending_bp) +- { +- if (pending_bp->cond_string) +- b->cond_string = savestring (pending_bp->cond_string, +- strlen (pending_bp->cond_string)); +- +- /* If there are commands associated with the breakpoint, they should +- be copied too. */ +- if (pending_bp->commands) +- b->commands = copy_command_lines (pending_bp->commands); +- +- /* We have to copy over the ignore_count and thread as well. */ +- b->ignore_count = pending_bp->ignore_count; +- b->thread = pending_bp->thread; +- } ++ b->cond_string = cond_string; ++ b->ignore_count = ignore_count; ++ b->enable_state = bp_enabled; ++ b->disposition = disposition; + +- if (b->cond_string) +- { +- char *arg = b->cond_string; +- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); +- if (*arg) ++ loc = b->loc; ++ } ++ else + { +- if (pending_bp) +- error (_("Junk at end of pending breakpoint condition expression")); +- else +- error (_("Garbage %s follows condition"), arg); ++ loc = add_location_to_breakpoint (b, type, &sal); + } +- } ++ ++ if (b->cond_string) ++ { ++ char *arg = b->cond_string; ++ b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); ++ if (*arg) ++ { ++ if (pending_bp) ++ error (_("Junk at end of pending breakpoint condition expression")); ++ else ++ error (_("Garbage %s follows condition"), arg); ++ } ++ } ++ } + + if (addr_string) + b->addr_string = addr_string; +@@ -5031,7 +5214,11 @@ + int i; + for (i = 0; i < sals.nelts; ++i) + { +- create_breakpoint (sals.sals[i], addr_string[i], ++ struct symtabs_and_lines sals2; ++ sals2.sals = sals.sals + i; ++ sals2.nelts = 1; ++ ++ create_breakpoint (sals2, addr_string[i], + cond_string, type, disposition, + thread, ignore_count, from_tty, + pending_bp); +@@ -5360,19 +5547,19 @@ + + make_cleanup (xfree, copy_arg); + +- b = set_raw_breakpoint (sal, hardwareflag ? bp_hardware_breakpoint +- : bp_breakpoint); ++ b = set_raw_breakpoint_without_location (hardwareflag ++ ? bp_hardware_breakpoint ++ : bp_breakpoint); + set_breakpoint_count (breakpoint_count + 1); + b->number = breakpoint_count; +- b->loc->cond = NULL; + b->thread = thread; + b->addr_string = addr_string[0]; + b->cond_string = cond_string; + b->ignore_count = ignore_count; +- b->pending = 1; + b->disposition = tempflag ? disp_del : disp_donttouch; + b->from_tty = from_tty; + b->flag = flag; ++ b->condition_not_parsed = 1; + mention (b); + } + +@@ -5411,7 +5598,7 @@ + struct cleanup *breakpoint_chain = NULL; + int i; + char **addr_string; +- char *cond_string; ++ char *cond_string = 0; + + char *address_end; + +@@ -5440,10 +5627,6 @@ + cond = xcalloc (sals.nelts, sizeof (struct expression *)); + make_cleanup (xfree, cond); + +- /* Allocate space for all the cond strings. */ +- cond_string = xcalloc (sals.nelts, sizeof (char **)); +- make_cleanup (xfree, cond_string); +- + /* ----------------------------- SNIP ----------------------------- + Anything added to the cleanup chain beyond this point is assumed + to be part of a breakpoint. If the breakpoint create goes +@@ -6733,23 +6916,35 @@ + breakpoint chain, and add them to the 'found' chain. */ + ALL_BREAKPOINTS_SAFE (b, tmp) + { ++ int match = 0; + /* Are we going to delete b? */ + if (b->type != bp_none + && b->type != bp_watchpoint + && b->type != bp_hardware_watchpoint + && b->type != bp_read_watchpoint +- && b->type != bp_access_watchpoint +- /* Not if b is a watchpoint of any sort... */ +- && (((sal.pc && (b->loc->address == sal.pc)) +- && (!section_is_overlay (b->loc->section) +- || b->loc->section == sal.section)) +- /* Yes, if sal.pc matches b (modulo overlays). */ +- || ((default_match || (0 == sal.pc)) +- && b->source_file != NULL +- && sal.symtab != NULL +- && strcmp (b->source_file, sal.symtab->filename) == 0 +- && b->line_number == sal.line))) +- /* Yes, if sal source file and line matches b. */ ++ && b->type != bp_access_watchpoint) ++ { ++ struct bp_location *loc = b->loc; ++ for (; loc; loc = loc->next) ++ { ++ int pc_match = sal.pc ++ && (loc->address == sal.pc) ++ && (!section_is_overlay (loc->section) ++ || loc->section == sal.section); ++ int line_match = ((default_match || (0 == sal.pc)) ++ && b->source_file != NULL ++ && sal.symtab != NULL ++ && strcmp (b->source_file, sal.symtab->filename) == 0 ++ && b->line_number == sal.line); ++ if (pc_match || line_match) ++ { ++ match = 1; ++ break; ++ } ++ } ++ } ++ ++ if (match) + { + /* Remove it from breakpoint_chain... */ + if (b == breakpoint_chain) +@@ -6824,6 +7019,35 @@ + } + } + ++/* Remove locations of breakpoint BPT from ++ the global list of breakpoint locations. */ ++ ++static void ++unlink_locations_from_global_list (struct breakpoint *bpt) ++{ ++ /* This code assumes that the locations ++ of a breakpoint are found in the global list ++ in the same order, but not necessary adjacent. */ ++ struct bp_location **tmp = &bp_location_chain; ++ struct bp_location *here = bpt->loc; ++ ++ if (here == NULL) ++ return; ++ ++ for (; *tmp && here;) ++ { ++ if (*tmp == here) ++ { ++ *tmp = here->global_next; ++ here = here->next; ++ } ++ else ++ { ++ tmp = &((*tmp)->global_next); ++ } ++ } ++} ++ + /* Delete a breakpoint and clean up all traces of it in the data + structures. */ + +@@ -6856,17 +7080,23 @@ + deprecated_delete_breakpoint_hook (bpt); + breakpoint_delete_event (bpt->number); + +- if (bpt->loc->inserted) +- remove_breakpoint (bpt->loc, mark_inserted); ++ for (loc = bpt->loc; loc; loc = loc->next) ++ { ++ if (loc->inserted) ++ remove_breakpoint (loc, mark_inserted); ++ ++ free_valchain (loc); + +- free_valchain (bpt->loc); ++ if (loc->cond) ++ xfree (loc->cond); ++ ++ if (loc->function_name) ++ xfree (loc->function_name); ++ } + + if (breakpoint_chain == bpt) + breakpoint_chain = bpt->next; + +- if (bp_location_chain == bpt->loc) +- bp_location_chain = bpt->loc->next; +- + /* If we have callback-style exception catchpoints, don't go through + the adjustments to the C++ runtime library etc. if the inferior + isn't actually running. target_enable_exception_callback for a +@@ -6896,82 +7126,83 @@ + break; + } + +- ALL_BP_LOCATIONS (loc) +- if (loc->next == bpt->loc) +- { +- loc->next = bpt->loc->next; +- break; +- } ++ unlink_locations_from_global_list (bpt); + + check_duplicates (bpt); +- /* If this breakpoint was inserted, and there is another breakpoint +- at the same address, we need to insert the other breakpoint. */ +- if (bpt->loc->inserted +- && bpt->type != bp_hardware_watchpoint ++ ++ if (bpt->type != bp_hardware_watchpoint + && bpt->type != bp_read_watchpoint + && bpt->type != bp_access_watchpoint + && bpt->type != bp_catch_fork + && bpt->type != bp_catch_vfork + && bpt->type != bp_catch_exec) +- { +- ALL_BREAKPOINTS (b) +- if (b->loc->address == bpt->loc->address +- && b->loc->section == bpt->loc->section +- && !b->loc->duplicate +- && b->enable_state != bp_disabled +- && b->enable_state != bp_shlib_disabled +- && !b->pending +- && b->enable_state != bp_call_disabled) +- { +- int val; +- +- /* We should never reach this point if there is a permanent +- breakpoint at the same address as the one being deleted. +- If there is a permanent breakpoint somewhere, it should +- always be the only one inserted. */ +- if (b->enable_state == bp_permanent) +- internal_error (__FILE__, __LINE__, +- _("another breakpoint was inserted on top of " +- "a permanent breakpoint")); +- +- memset (&b->loc->target_info, 0, sizeof (b->loc->target_info)); +- b->loc->target_info.placed_address = b->loc->address; +- if (b->type == bp_hardware_breakpoint) +- val = target_insert_hw_breakpoint (&b->loc->target_info); +- else +- val = target_insert_breakpoint (&b->loc->target_info); ++ for (loc = bpt->loc; loc; loc = loc->next) ++ { ++ /* If this breakpoint location was inserted, and there is ++ another breakpoint at the same address, we need to ++ insert the other breakpoint. */ ++ if (loc->inserted) ++ { ++ struct bp_location *loc2; ++ ALL_BP_LOCATIONS (loc2) ++ if (loc2->address == loc->address ++ && loc2->section == loc->section ++ && !loc->duplicate ++ && loc2->owner->enable_state != bp_disabled ++ && loc2->enabled ++ && !loc2->shlib_disabled ++ && loc2->owner->enable_state != bp_call_disabled) ++ { ++ int val; + +- /* If there was an error in the insert, print a message, then stop execution. */ +- if (val != 0) +- { +- struct ui_file *tmp_error_stream = mem_fileopen (); +- make_cleanup_ui_file_delete (tmp_error_stream); +- ++ /* We should never reach this point if there is a permanent ++ breakpoint at the same address as the one being deleted. ++ If there is a permanent breakpoint somewhere, it should ++ always be the only one inserted. */ ++ if (loc2->owner->enable_state == bp_permanent) ++ internal_error (__FILE__, __LINE__, ++ _("another breakpoint was inserted on top of " ++ "a permanent breakpoint")); ++ ++ memset (&loc2->target_info, 0, sizeof (loc2->target_info)); ++ loc2->target_info.placed_address = loc2->address; ++ if (b->type == bp_hardware_breakpoint) ++ val = target_insert_hw_breakpoint (&loc2->target_info); ++ else ++ val = target_insert_breakpoint (&loc2->target_info); + +- if (b->type == bp_hardware_breakpoint) +- { +- fprintf_unfiltered (tmp_error_stream, +- "Cannot insert hardware breakpoint %d.\n" +- "You may have requested too many hardware breakpoints.\n", +- b->number); +- } +- else +- { +- fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number); +- fprintf_filtered (tmp_error_stream, "Error accessing memory address "); +- deprecated_print_address_numeric (b->loc->address, 1, tmp_error_stream); +- fprintf_filtered (tmp_error_stream, ": %s.\n", +- safe_strerror (val)); +- } +- +- fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process."); +- target_terminal_ours_for_output (); +- error_stream(tmp_error_stream); +- } +- else +- b->loc->inserted = 1; +- } +- } ++ /* If there was an error in the insert, print a message, then stop execution. */ ++ if (val != 0) ++ { ++ struct ui_file *tmp_error_stream = mem_fileopen (); ++ make_cleanup_ui_file_delete (tmp_error_stream); ++ ++ ++ if (b->type == bp_hardware_breakpoint) ++ { ++ fprintf_unfiltered (tmp_error_stream, ++ "Cannot insert hardware breakpoint %d.\n" ++ "You may have requested too many hardware breakpoints.\n", ++ b->number); ++ } ++ else ++ { ++ fprintf_unfiltered (tmp_error_stream, "Cannot insert breakpoint %d.\n", b->number); ++ fprintf_filtered (tmp_error_stream, "Error accessing memory address "); ++ deprecated_print_address_numeric (loc2->address, 1, tmp_error_stream); ++ fprintf_filtered (tmp_error_stream, ": %s.\n", ++ safe_strerror (val)); ++ } ++ ++ fprintf_unfiltered (tmp_error_stream,"The same program may be running in another process."); ++ target_terminal_ours_for_output (); ++ error_stream(tmp_error_stream); ++ } ++ else ++ loc2->inserted = 1; ++ } ++ } ++ } + + free_command_lines (&bpt->commands); + if (bpt->cond_string != NULL) +@@ -7013,9 +7244,12 @@ + bp, we mark it as deleted before freeing its storage. */ + bpt->type = bp_none; + +- if (bpt->loc->cond) +- xfree (bpt->loc->cond); +- xfree (bpt->loc); ++ for (loc = bpt->loc; loc;) ++ { ++ struct bp_location *loc_next = loc->next; ++ xfree (loc); ++ loc = loc_next; ++ } + xfree (bpt); + } + +@@ -7083,94 +7317,95 @@ + map_breakpoint_numbers (arg, delete_breakpoint); + } + +-static void +-unlink_locations_from_global_list (struct breakpoint *bpt) +- /* Remove locations of this breakpoint from the list of +- all breakpoint locations. */ ++static int ++all_locations_are_pending (struct bp_location *loc) + { +- struct bp_location **tmp = &bp_location_chain; +- struct bp_location *here = bpt->loc; +- +- if (here == NULL) +- return; +- +- for (; *tmp && *tmp != here; tmp = &((*tmp)->next)); +- gdb_assert (*tmp); +- +- *tmp = here->next; ++ for (; loc; loc = loc->next) ++ if (!loc->shlib_disabled) ++ return 0; ++ return 1; + } + +- + static void +-update_breakpoint_location (struct breakpoint *b, +- struct symtabs_and_lines sals) ++update_breakpoint_locations (struct breakpoint *b, ++ struct symtabs_and_lines sals) + { + int i; + char *s; +- /* FIXME: memleak. */ +- struct bp_location *existing = b->loc; +- struct bp_location *loc; +- struct symtab_and_line sal; +- +- if (b->enable_state == bp_shlib_disabled && sals.nelts == 0) ++ struct bp_location *existing_locations = b->loc; ++ ++ /* If there's no new locations, and all existing locations ++ are pending, don't do anything. This optimizes ++ the common case where all locations are in the same ++ shared library, that was unloaded. We'd like to ++ retain the location, so that when the library ++ is loaded again, we don't loose the enabled/disabled ++ status of the individual locations. */ ++ if (all_locations_are_pending (existing_locations) && sals.nelts == 0) + return; + + unlink_locations_from_global_list (b); + b->loc = NULL; + +- gdb_assert (sals.nelts == 0 || sals.nelts == 1); +- if (sals.nelts == 0) +- return; +- sal = sals.sals[0]; +- +- loc = allocate_bp_location (b, b->type); +- loc->requested_address = sal.pc; +- loc->address = adjust_breakpoint_address (loc->requested_address, +- b->type); +- loc->section = sal.section; +- b->loc = loc; +- +- /* Reparse conditions, they might contain references to the +- old symtab. */ +- if (b->cond_string != NULL) ++ for (i = 0; i < sals.nelts; ++i) + { +- struct gdb_exception e; +- +- s = b->cond_string; +- TRY_CATCH (e, RETURN_MASK_ERROR) +- { +- loc->cond = parse_exp_1 (&s, block_for_pc (sal.pc), +- 0); +- } +- if (e.reason < 0) +- { +- warning (_("failed to reevaluate condition for breakpoint %d: %s"), +- b->number, e.message); +- b->enable_state = bp_disabled; +- } +- } ++ struct bp_location *new_loc = ++ add_location_to_breakpoint (b, b->type, &(sals.sals[i])); + +- if (b->source_file != NULL) +- xfree (b->source_file); +- if (sal.symtab == NULL) +- b->source_file = NULL; +- else +- b->source_file = +- savestring (sal.symtab->filename, +- strlen (sal.symtab->filename)); ++ /* Reparse conditions, they might contain references to the ++ old symtab. */ ++ if (b->cond_string != NULL) ++ { ++ struct gdb_exception e; + +- if (b->line_number == 0) +- b->line_number = sal.line; ++ s = b->cond_string; ++ TRY_CATCH (e, RETURN_MASK_ERROR) ++ { ++ new_loc->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), ++ 0); ++ } ++ if (e.reason < 0) ++ { ++ warning (_("failed to reevaluate condition for breakpoint %d: %s"), ++ b->number, e.message); ++ new_loc->enabled = 0; ++ } ++ } + +- if (b->enable_state == bp_shlib_disabled) +- b->enable_state = bp_enabled; ++ if (b->source_file != NULL) ++ xfree (b->source_file); ++ if (sals.sals[i].symtab == NULL) ++ b->source_file = NULL; ++ else ++ b->source_file = ++ savestring (sals.sals[i].symtab->filename, ++ strlen (sals.sals[i].symtab->filename)); + +- b->pending = 0; ++ if (b->line_number == 0) ++ b->line_number = sals.sals[i].line; ++ } + +- check_duplicates (b); ++ /* If possible, carry over 'disable' status from existing breakpoints. */ ++ { ++ struct bp_location *e = existing_locations; ++ for (; e; e = e->next) ++ { ++ if (!e->enabled && e->function_name) ++ { ++ struct bp_location *l = b->loc; ++ for (; l; l = l->next) ++ if (l->function_name ++ && strcmp (e->function_name, l->function_name) == 0) ++ { ++ l->enabled = 0; ++ break; ++ } ++ } ++ } ++ } + +- if (existing) +- free_bp_location (existing); ++ if (existing_locations) ++ free_bp_location (existing_locations); + } + + +@@ -7227,8 +7462,10 @@ + don't need extra messages. If breakpoint is in bp_shlib_disabled + state, then user already saw the message about that breakpoint + being disabled, and don't want to see more errors. */ +- if (not_found && (b->pending || b->enable_state == bp_shlib_disabled +- || b->enable_state == bp_disabled)) ++ if (not_found ++ && (b->condition_not_parsed ++ || (b->loc && b->loc->shlib_disabled) ++ || b->enable_state == bp_disabled)) + not_found_and_ok = 1; + + if (!not_found_and_ok) +@@ -7249,7 +7486,7 @@ + + gdb_assert (sals.nelts == 1); + resolve_sal_pc (&sals.sals[0]); +- if (b->pending && s && s[0]) ++ if (b->condition_not_parsed && s && s[0]) + { + char *cond_string = 0; + int thread = -1; +@@ -7258,9 +7495,14 @@ + if (cond_string) + b->cond_string = cond_string; + b->thread = thread; ++ b->condition_not_parsed = 0; + } + +- update_breakpoint_location (b, sals); ++ update_breakpoint_locations (b, sals); ++ ++ /* Now that this is re-enabled, check_duplicates ++ can be used. */ ++ check_duplicates (b); + + xfree (sals.sals); + break; +@@ -7524,6 +7766,48 @@ + } + } + ++static struct bp_location * ++find_location_by_number (char *number) ++{ ++ char *dot = strchr (number, '.'); ++ char *p1; ++ int bp_num; ++ int loc_num; ++ struct breakpoint *b; ++ struct bp_location *loc; ++ ++ *dot = '\0'; ++ ++ p1 = number; ++ bp_num = get_number_or_range (&p1); ++ if (bp_num == 0) ++ error (_("Bad breakpoint number '%s'"), number); ++ ++ ALL_BREAKPOINTS (b) ++ if (b->number == bp_num) ++ { ++ break; ++ } ++ ++ if (!b || b->number != bp_num) ++ error (_("Bad breakpoint number '%s'"), number); ++ ++ p1 = dot+1; ++ loc_num = get_number_or_range (&p1); ++ if (loc_num == 0) ++ error (_("Bad breakpoint location number '%s'"), number); ++ ++ --loc_num; ++ loc = b->loc; ++ for (;loc_num && loc; --loc_num, loc = loc->next) ++ ; ++ if (!loc) ++ error (_("Bad breakpoint location number '%s'"), dot+1); ++ ++ return loc; ++} ++ ++ + /* Set ignore-count of breakpoint number BPTNUM to COUNT. + If from_tty is nonzero, it prints a message to that effect, + which ends with a period (no newline). */ +@@ -7579,6 +7863,13 @@ + default: + continue; + } ++ else if (strchr (args, '.')) ++ { ++ struct bp_location *loc = find_location_by_number (args); ++ if (loc) ++ loc->enabled = 0; ++ check_duplicates (loc->owner); ++ } + else + map_breakpoint_numbers (args, disable_breakpoint); + } +@@ -7711,6 +8002,13 @@ + default: + continue; + } ++ else if (strchr (args, '.')) ++ { ++ struct bp_location *loc = find_location_by_number (args); ++ if (loc) ++ loc->enabled = 1; ++ check_duplicates (loc->owner); ++ } + else + map_breakpoint_numbers (args, enable_breakpoint); + } +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.h,v +retrieving revision 1.50 +retrieving revision 1.51 +diff -u -r1.50 -r1.51 +--- src/gdb/breakpoint.h 2007/09/22 19:33:31 1.50 ++++ src/gdb/breakpoint.h 2007/09/23 07:56:22 1.51 +@@ -143,9 +143,6 @@ + { + bp_disabled, /* The eventpoint is inactive, and cannot trigger. */ + bp_enabled, /* The eventpoint is active, and can trigger. */ +- bp_shlib_disabled, /* The eventpoint's address is in an unloaded solib. +- The eventpoint will be automatically enabled +- and reset when that solib is loaded. */ + bp_call_disabled, /* The eventpoint has been disabled while a call + into the inferior is "in flight", because some + eventpoints interfere with the implementation of +@@ -232,9 +229,14 @@ + + struct bp_location + { +- /* Chain pointer to the next breakpoint location. */ ++ /* Chain pointer to the next breakpoint location for ++ the same parent breakpoint. */ + struct bp_location *next; + ++ /* Pointer to the next breakpoint location, in a global ++ list of all breakpoint locations. */ ++ struct bp_location *global_next; ++ + /* Type of this breakpoint location. */ + enum bp_loc_type loc_type; + +@@ -249,6 +251,14 @@ + locations, the evaluation of expression can be different for + different locations. */ + struct expression *cond; ++ ++ /* This location's address is in an unloaded solib, and so this ++ location should not be inserted. It will be automatically ++ enabled when that solib is loaded. */ ++ char shlib_disabled; ++ ++ /* Is this particular location enabled. */ ++ char enabled; + + /* Nonzero if this breakpoint is now inserted. */ + char inserted; +@@ -281,6 +291,8 @@ + processor's architectual constraints. */ + CORE_ADDR requested_address; + ++ char *function_name; ++ + /* Details of the placed breakpoint, when inserted. */ + struct bp_target_info target_info; + +@@ -423,8 +435,10 @@ + second bit : 0 normal breakpoint, 1 hardware breakpoint. */ + int flag; + +- /* Is breakpoint pending on shlib loads? */ +- int pending; ++ /* Is breakpoint's condition not yet parsed because we found ++ no location initially so had no context to parse ++ the condition in. */ ++ int condition_not_parsed; + }; + + /* The following stuff is an abstract data type "bpstat" ("breakpoint + +2007-09-23 Vladimir Prus + + * gdb.base/annota1.exp: Adjust for 'info break' + format changes. + * gdb.base/annota3.exp: Likewise. + * gdb.base/break.exp: Likewise. + * gdb.base/condbreak.exp: Likewise. + * gdb.base/pending.exp: Likewise. + * gdb.base/sepdebug.exp: Likewise. + * gdb.base/unload.exp: Likewise. + * gdb.base/ovldbreak.exp: Likewise. + +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/annota1.exp,v +retrieving revision 1.24 +retrieving revision 1.25 +diff -u -r1.24 -r1.25 +--- src/gdb/testsuite/gdb.base/annota1.exp 2007/08/23 18:14:16 1.24 ++++ src/gdb/testsuite/gdb.base/annota1.exp 2007/09/23 07:56:22 1.25 +@@ -117,9 +117,9 @@ + # + send_gdb "info break\n" + gdb_expect { +- -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \ ++ -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at ${escapedsrcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \ + {pass "breakpoint info"} +- -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \ ++ -re "\r\n\032\032post-prompt\r\n\r\n\032\032breakpoints-headers\r\n\r\n\032\032field 0\r\nNum \r\n\032\032field 1\r\nType \r\n\032\032field 2\r\nDisp \r\n\032\032field 3\r\nEnb \r\n\032\032field 4\r\nAddress +\r\n\032\032field 5\r\nWhat\r\n\r\n\032\032breakpoints-table\r\n\r\n\032\032record\r\n\r\n\032\032field 0\r\n1 \r\n\032\032field 1\r\nbreakpoint \r\n\032\032field 2\r\nkeep \r\n\032\032field 3\r\ny \r\n\032\032field 4\r\n$hex +\r\n\032\032field 5\r\nin main at .*${srcfile}:$main_line\r\n\r\n\032\032breakpoints-table-end\r\n$gdb_prompt$" \ + { setup_xfail "*-*-*" 1270 + fail "breakpoint info"} + -re ".*$gdb_prompt$" { fail "breakpoint info" } +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/annota3.exp,v +retrieving revision 1.14 +retrieving revision 1.15 +diff -u -r1.14 -r1.15 +--- src/gdb/testsuite/gdb.base/annota3.exp 2007/08/23 18:14:16 1.14 ++++ src/gdb/testsuite/gdb.base/annota3.exp 2007/09/23 07:56:22 1.15 +@@ -127,8 +127,8 @@ + send_gdb "info break\n" + gdb_expect_list "breakpoint info" "$gdb_prompt$" { + "\r\n\032\032post-prompt\r\n" +- "Num Type Disp Enb Address +What\r\n" +- "1 breakpoint keep y 0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n" ++ "Num Type Disp Enb Address +What\r\n" ++ "1 breakpoint keep y 0x\[0-9a-zA-Z\]+ +in main at .*annota3.c:32\r\n" + } + + +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/break.exp,v +retrieving revision 1.29 +retrieving revision 1.30 +diff -u -r1.29 -r1.30 +--- src/gdb/testsuite/gdb.base/break.exp 2007/08/23 18:14:16 1.29 ++++ src/gdb/testsuite/gdb.base/break.exp 2007/09/23 07:56:22 1.30 +@@ -179,7 +179,7 @@ + set bp_location9 [gdb_get_line_number "set breakpoint 9 here" $srcfile1] + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.* + \[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile1:($bp_location8|$bp_location9).* + \[0-9\]+\[\t \]+breakpoint keep y.* in factorial$proto at .*$srcfile:$bp_location7.* +@@ -309,7 +309,7 @@ + # + # check to see what breakpoints are set (temporary this time) + # +-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\] ++gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\] + \[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\] + \[0-9\]+\[\t \]+breakpoint del.*y.*in factorial$proto at .*$srcfile:$bp_location7.*\[\r\n\] + \[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\] +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/condbreak.exp,v +retrieving revision 1.8 +retrieving revision 1.9 +diff -u -r1.8 -r1.9 +--- src/gdb/testsuite/gdb.base/condbreak.exp 2007/08/23 18:14:16 1.8 ++++ src/gdb/testsuite/gdb.base/condbreak.exp 2007/09/23 07:56:22 1.9 +@@ -125,14 +125,14 @@ + } + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location6.* + \[0-9\]+\[\t \]+breakpoint keep y.* in marker1$marker1_proto at .*$srcfile1:($bp_location15|$bp_location16).* +-\[\t \]+stop only if 1 == 1.* ++\[\t \]+stop only if \\(1==1\\).* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$bp_location1.* +-\[\t \]+stop only if 1 == 1.* ++\[\t \]+stop only if \\(1==1\\).* + \[0-9\]+\[\t \]+breakpoint keep y.* in marker2$marker2_proto at .*$srcfile1:($bp_location8|$bp_location9).* +-\[\t \]+stop only if a == 43.*" \ ++\[\t \]+stop only if \\(a==43\\).*" \ + "breakpoint info" + + +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/pending.exp,v +retrieving revision 1.11 +retrieving revision 1.12 +diff -u -r1.11 -r1.12 +--- src/gdb/testsuite/gdb.base/pending.exp 2007/09/22 19:33:32 1.11 ++++ src/gdb/testsuite/gdb.base/pending.exp 2007/09/23 07:56:22 1.12 +@@ -71,8 +71,8 @@ + } + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.*" \ ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.*" \ + "single pending breakpoint info" + + # +@@ -86,8 +86,8 @@ + "breakpoint function" + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \ + "pending plus real breakpoint info" + +@@ -108,8 +108,8 @@ + gdb_test "condition 1 k == 1" "" + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendfunc1.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendfunc1.* + \[\t \]+stop only if k == 1.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \ + "pending plus condition" +@@ -121,8 +121,8 @@ + gdb_test "disable 1" "" + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.* + \[\t \]+stop only if k == 1.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \ + "pending disabled" +@@ -134,8 +134,8 @@ + "Set commands for pending breakpoint" + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.* + \[\t \]+stop only if k == 1.* + \[\t \]+print k.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline" \ +@@ -154,12 +154,12 @@ + } + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.* + \[\t \]+stop only if k == 1.* + \[\t \]+print k.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \ ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.*" \ + "multiple pending breakpoints" + + +@@ -179,13 +179,13 @@ + "set ignore count on pending breakpoint 3" + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep n.*PENDING.*pendfunc1.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep n\\(p\\).*PENDING.*pendfunc1.* + \[\t \]+stop only if k == 1.* + \[\t \]+print k.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp2_loc if x > 3.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \ ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp2_loc if x > 3.* ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*pendshr.c:$bp3_loc.*ignore next 2 hits.*" \ + "multiple pending breakpoints 2" + + # +@@ -253,7 +253,7 @@ + rerun_to_main + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$mainline.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*imaginary.*" \ ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*imaginary.*" \ + "verify pending breakpoint after restart" +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/sepdebug.exp,v +retrieving revision 1.10 +retrieving revision 1.11 +diff -u -r1.10 -r1.11 +--- src/gdb/testsuite/gdb.base/sepdebug.exp 2007/09/21 22:42:52 1.10 ++++ src/gdb/testsuite/gdb.base/sepdebug.exp 2007/09/23 07:56:22 1.11 +@@ -179,7 +179,7 @@ + set bp_location9 [gdb_get_line_number "set breakpoint 9 here"] + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y.* in main at .*$srcfile:$main_line.* + \[0-9\]+\[\t \]+breakpoint keep y.* in marker2 at .*$srcfile:($bp_location8|$bp_location9).* + \[0-9\]+\[\t \]+breakpoint keep y.* in factorial at .*$srcfile:$bp_location7.* +@@ -298,7 +298,7 @@ + # + # check to see what breakpoints are set (temporary this time) + # +-gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\] ++gdb_test "info break" "Num Type.*Disp Enb Address.*What.*\[\r\n\] + \[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$main_line.*\[\r\n\] + \[0-9\]+\[\t \]+breakpoint del.*y.*in factorial at .*$srcfile:$bp_location7.*\[\r\n\] + \[0-9\]+\[\t \]+breakpoint del.*y.*in main at .*$srcfile:$bp_location1.*\[\r\n\] +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.base/unload.exp,v +retrieving revision 1.12 +retrieving revision 1.13 +diff -u -r1.12 -r1.13 +--- src/gdb/testsuite/gdb.base/unload.exp 2007/09/22 19:33:32 1.12 ++++ src/gdb/testsuite/gdb.base/unload.exp 2007/09/23 07:56:22 1.13 +@@ -81,8 +81,8 @@ + } + + gdb_test "info break" \ +- "Num Type\[ \]+Disp Enb Address\[ \]+What.* +-\[0-9\]+\[\t \]+breakpoint keep y.*PENDING.*shrfunc1.*" \ ++ "Num Type\[ \]+Disp Enb Address\[ \]+What.* ++\[0-9\]+\[\t \]+breakpoint keep y\\(p\\).*PENDING.*shrfunc1.*" \ + "single pending breakpoint info" + + set unloadshr_line [gdb_get_line_number "unloadshr break" ${libsrcfile}] +=================================================================== +RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/ovldbreak.exp,v +retrieving revision 1.6 +retrieving revision 1.7 +diff -u -r1.6 -r1.7 +--- src/gdb/testsuite/gdb.cp/ovldbreak.exp 2007/08/23 18:14:17 1.6 ++++ src/gdb/testsuite/gdb.cp/ovldbreak.exp 2007/09/23 07:56:22 1.7 +@@ -153,7 +153,7 @@ + # Verify the breakpoints. + + gdb_test "info break" \ +- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* ++ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r + \[\t \]+breakpoint already hit 1 time\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r +@@ -211,7 +211,7 @@ + } + + gdb_test "info break" \ +- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* ++ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r + \[\t \]+breakpoint already hit 1 time\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r +@@ -290,7 +290,7 @@ + } + + gdb_test "info break" \ +- "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* ++ "Num Type\[\t \]+Disp Enb Address\[\t \]+What.* + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r + \[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r + +2007-09-24 Vladimir Prus + + * breakpoint.c (remove_sal): New. + (expand_line_sal_maybe): New. + (create_breakpoints): Call expand_line_sal_maybe. + (clear_command): Add comment. + (breakpoint_re_set_one): Call expand_line_sal_maybe. + * linespec.c (decode_indirect): Set explicit_pc to 1. + (decode_all_digits): Set explicit_line to 1. + (append_expanded_sal): New. + (expand_line_sal): New. + * linespec.h (expand_line_sal): Declare. + * symtab.c (init_sal): Initialize explicit_pc + and explicit_line. + * symtab.h (struct symtab_and_line): New fields + explicit_pc and explicit_line. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.268 +retrieving revision 1.269 +diff -u -r1.268 -r1.269 +--- src/gdb/breakpoint.c 2007/09/23 07:56:22 1.268 ++++ src/gdb/breakpoint.c 2007/09/24 07:40:32 1.269 +@@ -5184,6 +5184,128 @@ + mention (b); + } + ++/* Remove element at INDEX_TO_REMOVE from SAL, shifting other ++ elements to fill the void space. */ ++static void remove_sal (struct symtabs_and_lines *sal, int index_to_remove) ++{ ++ int i = index_to_remove+1; ++ int last_index = sal->nelts-1; ++ ++ for (;i <= last_index; ++i) ++ sal->sals[i-1] = sal->sals[i]; ++ ++ --(sal->nelts); ++} ++ ++/* If appropriate, obtains all sals that correspond ++ to the same file and line as SAL. This is done ++ only if SAL does not have explicit PC and has ++ line and file information. If we got just a single ++ expanded sal, return the original. ++ ++ Otherwise, if SAL.explicit_line is not set, filter out ++ all sals for which the name of enclosing function ++ is different from SAL. This makes sure that if we have ++ breakpoint originally set in template instantiation, say ++ foo(), we won't expand SAL to locations at the same ++ line in all existing instantiations of 'foo'. ++ ++*/ ++struct symtabs_and_lines ++expand_line_sal_maybe (struct symtab_and_line sal) ++{ ++ struct symtabs_and_lines expanded; ++ CORE_ADDR original_pc = sal.pc; ++ char *original_function = NULL; ++ int found; ++ int i; ++ ++ /* If we have explicit pc, don't expand. ++ If we have no line number, we can't expand. */ ++ if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL) ++ { ++ expanded.nelts = 1; ++ expanded.sals = xmalloc (sizeof (struct symtab_and_line)); ++ expanded.sals[0] = sal; ++ return expanded; ++ } ++ ++ sal.pc = 0; ++ find_pc_partial_function (original_pc, &original_function, NULL, NULL); ++ ++ expanded = expand_line_sal (sal); ++ if (expanded.nelts == 1) ++ { ++ /* We had one sal, we got one sal. Without futher ++ processing, just return the original sal. */ ++ xfree (expanded.sals); ++ expanded.nelts = 1; ++ expanded.sals = xmalloc (sizeof (struct symtab_and_line)); ++ sal.pc = original_pc; ++ expanded.sals[0] = sal; ++ return expanded; ++ } ++ ++ if (!sal.explicit_line) ++ { ++ CORE_ADDR func_addr, func_end; ++ for (i = 0; i < expanded.nelts; ++i) ++ { ++ CORE_ADDR pc = expanded.sals[i].pc; ++ char *this_function; ++ if (find_pc_partial_function (pc, &this_function, ++ &func_addr, &func_end)) ++ { ++ if (this_function && ++ strcmp (this_function, original_function) != 0) ++ { ++ remove_sal (&expanded, i); ++ --i; ++ } ++ else if (func_addr == pc) ++ { ++ /* We're at beginning of a function, and should ++ skip prologue. */ ++ struct symbol *sym = find_pc_function (pc); ++ if (sym) ++ expanded.sals[i] = find_function_start_sal (sym, 1); ++ else ++ expanded.sals[i].pc ++ = gdbarch_skip_prologue (current_gdbarch, pc); ++ } ++ } ++ } ++ } ++ ++ ++ if (expanded.nelts <= 1) ++ { ++ /* This is un ugly workaround. If we get zero ++ expanded sals then something is really wrong. ++ Fix that by returnign the original sal. */ ++ xfree (expanded.sals); ++ expanded.nelts = 1; ++ expanded.sals = xmalloc (sizeof (struct symtab_and_line)); ++ sal.pc = original_pc; ++ expanded.sals[0] = sal; ++ return expanded; ++ } ++ ++ if (original_pc) ++ { ++ found = 0; ++ for (i = 0; i < expanded.nelts; ++i) ++ if (expanded.sals[i].pc == original_pc) ++ { ++ found = 1; ++ break; ++ } ++ gdb_assert (found); ++ } ++ ++ return expanded; ++} ++ + /* Add SALS.nelts breakpoints to the breakpoint table. For each + SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i] + value. COND_STRING, if not NULL, specified the condition to be +@@ -5214,11 +5336,10 @@ + int i; + for (i = 0; i < sals.nelts; ++i) + { +- struct symtabs_and_lines sals2; +- sals2.sals = sals.sals + i; +- sals2.nelts = 1; ++ struct symtabs_and_lines expanded = ++ expand_line_sal_maybe (sals.sals[i]); + +- create_breakpoint (sals2, addr_string[i], ++ create_breakpoint (expanded, addr_string[i], + cond_string, type, disposition, + thread, ignore_count, from_tty, + pending_bp); +@@ -6889,6 +7010,23 @@ + default_match = 1; + } + ++ /* We don't call resolve_sal_pc here. That's not ++ as bad as it seems, because all existing breakpoints ++ typically have both file/line and pc set. So, if ++ clear is given file/line, we can match this to existing ++ breakpoint without obtaining pc at all. ++ ++ We only support clearing given the address explicitly ++ present in breakpoint table. Say, we've set breakpoint ++ at file:line. There were several PC values for that file:line, ++ due to optimization, all in one block. ++ We've picked one PC value. If "clear" is issued with another ++ PC corresponding to the same file:line, the breakpoint won't ++ be cleared. We probably can still clear the breakpoint, but ++ since the other PC value is never presented to user, user ++ can only find it by guessing, and it does not seem important ++ to support that. */ ++ + /* For each line spec given, delete bps which correspond + to it. Do it in two passes, solely to preserve the current + behavior that from_tty is forced true if we delete more than +@@ -7404,8 +7542,12 @@ + } + } + +- if (existing_locations) +- free_bp_location (existing_locations); ++ while (existing_locations) ++ { ++ struct bp_location *next = existing_locations->next; ++ free_bp_location (existing_locations); ++ existing_locations = next; ++ } + } + + +@@ -7423,6 +7565,7 @@ + int not_found = 0; + int *not_found_ptr = ¬_found; + struct symtabs_and_lines sals = {}; ++ struct symtabs_and_lines expanded; + char *s; + enum enable_state save_enable; + struct gdb_exception e; +@@ -7497,8 +7640,8 @@ + b->thread = thread; + b->condition_not_parsed = 0; + } +- +- update_breakpoint_locations (b, sals); ++ expanded = expand_line_sal_maybe (sals.sals[0]); ++ update_breakpoint_locations (b, expanded); + + /* Now that this is re-enabled, check_duplicates + can be used. */ +=================================================================== +RCS file: /cvs/src/src/gdb/linespec.c,v +retrieving revision 1.72 +retrieving revision 1.73 +diff -u -r1.72 -r1.73 +--- src/gdb/linespec.c 2007/08/23 18:08:35 1.72 ++++ src/gdb/linespec.c 2007/09/24 07:40:32 1.73 +@@ -963,6 +963,7 @@ + values.sals[0] = find_pc_line (pc, 0); + values.sals[0].pc = pc; + values.sals[0].section = find_pc_overlay (pc); ++ values.sals[0].explicit_pc = 1; + + return values; + } +@@ -1633,6 +1634,7 @@ + values.nelts = 1; + if (need_canonical) + build_canonical_line_spec (values.sals, NULL, canonical); ++ values.sals[0].explicit_line = 1; + return values; + } + +=================================================================== +RCS file: /cvs/src/src/gdb/symtab.c,v +retrieving revision 1.164 +retrieving revision 1.165 +diff -u -r1.164 -r1.165 +--- src/gdb/symtab.c 2007/08/29 18:34:46 1.164 ++++ src/gdb/symtab.c 2007/09/24 07:40:32 1.165 +@@ -691,6 +691,8 @@ + sal->line = 0; + sal->pc = 0; + sal->end = 0; ++ sal->explicit_pc = 0; ++ sal->explicit_line = 0; + } + + +@@ -4172,6 +4174,166 @@ + set_main_name (NULL); + } + ++/* Helper to expand_line_sal below. Appends new sal to SAL, ++ initializing it from SYMTAB, LINENO and PC. */ ++static void ++append_expanded_sal (struct symtabs_and_lines *sal, ++ struct symtab *symtab, ++ int lineno, CORE_ADDR pc) ++{ ++ CORE_ADDR func_addr, func_end; ++ ++ sal->sals = xrealloc (sal->sals, ++ sizeof (sal->sals[0]) ++ * (sal->nelts + 1)); ++ init_sal (sal->sals + sal->nelts); ++ sal->sals[sal->nelts].symtab = symtab; ++ sal->sals[sal->nelts].section = NULL; ++ sal->sals[sal->nelts].end = 0; ++ sal->sals[sal->nelts].line = lineno; ++ sal->sals[sal->nelts].pc = pc; ++ ++sal->nelts; ++} ++ ++/* Compute a set of all sals in ++ the entire program that correspond to same file ++ and line as SAL and return those. If there ++ are several sals that belong to the same block, ++ only one sal for the block is included in results. */ ++ ++struct symtabs_and_lines ++expand_line_sal (struct symtab_and_line sal) ++{ ++ struct symtabs_and_lines ret, this_line; ++ int i, j; ++ struct objfile *objfile; ++ struct partial_symtab *psymtab; ++ struct symtab *symtab; ++ int lineno; ++ int deleted = 0; ++ struct block **blocks = NULL; ++ int *filter; ++ ++ ret.nelts = 0; ++ ret.sals = NULL; ++ ++ if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0) ++ { ++ ret.sals = xmalloc (sizeof (struct symtab_and_line)); ++ ret.sals[0] = sal; ++ ret.nelts = 1; ++ return ret; ++ } ++ else ++ { ++ struct linetable_entry *best_item = 0; ++ struct symtab *best_symtab = 0; ++ int exact = 0; ++ ++ lineno = sal.line; ++ ++ /* We meed to find all symtabs for a file which name ++ is described by sal. We cannot just directly ++ iterate over symtabs, since a symtab might not be ++ yet created. We also cannot iterate over psymtabs, ++ calling PSYMTAB_TO_SYMTAB and working on that symtab, ++ since PSYMTAB_TO_SYMTAB will return NULL for psymtab ++ corresponding to an included file. Therefore, we do ++ first pass over psymtabs, reading in those with ++ the right name. Then, we iterate over symtabs, knowing ++ that all symtabs we're interested in are loaded. */ ++ ++ ALL_PSYMTABS (objfile, psymtab) ++ { ++ if (strcmp (sal.symtab->filename, ++ psymtab->filename) == 0) ++ PSYMTAB_TO_SYMTAB (psymtab); ++ } ++ ++ ++ /* For each symtab, we add all pcs to ret.sals. I'm actually ++ not sure what to do if we have exact match in one symtab, ++ and non-exact match on another symtab. ++ */ ++ ALL_SYMTABS (objfile, symtab) ++ { ++ if (strcmp (sal.symtab->filename, ++ symtab->filename) == 0) ++ { ++ struct linetable *l; ++ int len; ++ l = LINETABLE (symtab); ++ if (!l) ++ continue; ++ len = l->nitems; ++ ++ for (j = 0; j < len; j++) ++ { ++ struct linetable_entry *item = &(l->item[j]); ++ ++ if (item->line == lineno) ++ { ++ exact = 1; ++ append_expanded_sal (&ret, symtab, lineno, item->pc); ++ } ++ else if (!exact && item->line > lineno ++ && (best_item == NULL || item->line < best_item->line)) ++ ++ { ++ best_item = item; ++ best_symtab = symtab; ++ } ++ } ++ } ++ } ++ if (!exact && best_item) ++ append_expanded_sal (&ret, best_symtab, lineno, best_item->pc); ++ } ++ ++ /* For optimized code, compiler can scatter one source line accross ++ disjoint ranges of PC values, even when no duplicate functions ++ or inline functions are involved. For example, 'for (;;)' inside ++ non-template non-inline non-ctor-or-dtor function can result ++ in two PC ranges. In this case, we don't want to set breakpoint ++ on first PC of each range. To filter such cases, we use containing ++ blocks -- for each PC found above we see if there are other PCs ++ that are in the same block. If yes, the other PCs are filtered out. */ ++ ++ filter = xmalloc (ret.nelts * sizeof (int)); ++ blocks = xmalloc (ret.nelts * sizeof (struct block *)); ++ for (i = 0; i < ret.nelts; ++i) ++ { ++ filter[i] = 1; ++ blocks[i] = block_for_pc (ret.sals[i].pc); ++ } ++ ++ for (i = 0; i < ret.nelts; ++i) ++ if (blocks[i] != NULL) ++ for (j = i+1; j < ret.nelts; ++j) ++ if (blocks[j] == blocks[i]) ++ { ++ filter[j] = 0; ++ ++deleted; ++ break; ++ } ++ ++ { ++ struct symtab_and_line *final = ++ xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted)); ++ ++ for (i = 0, j = 0; i < ret.nelts; ++i) ++ if (filter[i]) ++ final[j++] = ret.sals[i]; ++ ++ ret.nelts -= deleted; ++ xfree (ret.sals); ++ ret.sals = final; ++ } ++ ++ return ret; ++} ++ ++ + void + _initialize_symtab (void) + { +=================================================================== +RCS file: /cvs/src/src/gdb/symtab.h,v +retrieving revision 1.106 +retrieving revision 1.107 +diff -u -r1.106 -r1.107 +--- src/gdb/symtab.h 2007/08/23 18:08:45 1.106 ++++ src/gdb/symtab.h 2007/09/24 07:40:32 1.107 +@@ -1213,6 +1213,8 @@ + + CORE_ADDR pc; + CORE_ADDR end; ++ int explicit_pc; ++ int explicit_line; + }; + + extern void init_sal (struct symtab_and_line *sal); +@@ -1404,5 +1406,7 @@ + const domain_enum domain, + struct symtab **symtab); + ++extern struct symtabs_and_lines ++expand_line_sal (struct symtab_and_line sal); + + #endif /* !defined(SYMTAB_H) */ + +2007-09-24 Vladimir Prus + + * gdb.cp/mb-ctor.cc: New. + * gdb.cp/mb-ctor.exp: New. + * gdb.cp/mb-templates.cc: New. + * gdb.cp/mb-templates.exp: New. + +/cvs/src/src/gdb/testsuite/gdb.cp/mb-ctor.cc,v --> standard output +revision 1.1 +--- src/gdb/testsuite/gdb.cp/mb-ctor.cc ++++ - 2007-11-01 22:04:53.928594000 +0000 +@@ -0,0 +1,58 @@ ++ ++#include ++ ++class Base ++{ ++public: ++ Base(int k); ++ ~Base(); ++ virtual void foo() {} ++private: ++ int k; ++}; ++ ++Base::Base(int k) ++{ ++ this->k = k; ++} ++ ++Base::~Base() ++{ ++ printf("~Base\n"); ++} ++ ++class Derived : public virtual Base ++{ ++public: ++ Derived(int i); ++ ~Derived(); ++private: ++ int i; ++}; ++ ++Derived::Derived(int i) : Base(i) ++{ ++ this->i = i; ++} ++ ++Derived::~Derived() ++{ ++ printf("~Derived\n"); ++} ++ ++class DeeplyDerived : public Derived ++{ ++public: ++ DeeplyDerived(int i) : Base(i), Derived(i) {} ++}; ++ ++int main() ++{ ++ /* Invokes the Derived ctor that constructs both ++ Derived and Base. */ ++ Derived d(7); ++ /* Invokes the Derived ctor that constructs only ++ Derived. Base is constructed separately by ++ DeeplyDerived's ctor. */ ++ DeeplyDerived dd(15); ++} +/cvs/src/src/gdb/testsuite/gdb.cp/mb-ctor.exp,v --> standard output +revision 1.1 +--- src/gdb/testsuite/gdb.cp/mb-ctor.exp ++++ - 2007-11-01 22:04:54.490054000 +0000 +@@ -0,0 +1,86 @@ ++# Copyright 2007 ++# Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# Test that breakpoints on C++ constructors work, despite the ++# fact that gcc generates several versions of constructor function. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile "mb-ctor" ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if [get_compiler_info ${binfile} "c++"] { ++ return -1 ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { ++ untested mb-ctor.exp ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# Set a breakpoint with multiple locations ++# and a condition. ++ ++gdb_test "break 'Derived::Derived(int)'" \ ++ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \ ++ "set-breakpoint at ctor" ++ ++gdb_test "break 'Derived::~Derived()'" \ ++ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \ ++ "set-breakpoint at ctor" ++ ++gdb_run_cmd ++gdb_expect { ++ -re "Breakpoint \[0-9\]+,.*Derived.*i=7.*$gdb_prompt $" { ++ pass "run to breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "run to breakpoint" ++ } ++ timeout { ++ fail "run to breakpoint (timeout)" ++ } ++} ++ ++gdb_test "continue" \ ++ ".*Breakpoint.*Derived.*i=15.*" \ ++ "run to breakpoint 2" ++ ++gdb_test "continue" \ ++ ".*Breakpoint.*~Derived.*" \ ++ "run to breakpoint 3" ++ ++gdb_test "continue" \ ++ ".*Breakpoint.*~Derived.*" \ ++ "run to breakpoint 4" ++ ++gdb_test "continue" \ ++ ".*exited normally.*" \ ++ "run to exit" ++ ++ ++ +/cvs/src/src/gdb/testsuite/gdb.cp/mb-templates.cc,v --> standard output +revision 1.1 +--- src/gdb/testsuite/gdb.cp/mb-templates.cc ++++ - 2007-11-01 22:04:55.064722000 +0000 +@@ -0,0 +1,19 @@ ++ ++#include ++using namespace std; ++ ++template ++void foo(T i) ++{ ++ std::cout << "hi\n"; // set breakpoint here ++} ++ ++int main() ++{ ++ foo(0); ++ foo(0); ++ foo(1); ++ foo(1); ++ foo(2); ++ foo(2); ++} +/cvs/src/src/gdb/testsuite/gdb.cp/mb-templates.exp,v --> standard output +revision 1.1 +--- src/gdb/testsuite/gdb.cp/mb-templates.exp ++++ - 2007-11-01 22:04:55.647560000 +0000 +@@ -0,0 +1,161 @@ ++# Copyright 2007 ++# Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# This test verifies that setting breakpoint on line in template ++# function will fire in all instantiations of that template. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set prms_id 0 ++set bug_id 0 ++ ++set testfile "mb-templates" ++set srcfile ${testfile}.cc ++set binfile ${objdir}/${subdir}/${testfile} ++ ++if [get_compiler_info ${binfile} "c++"] { ++ return -1 ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { ++ untested mb-templates.exp ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++set bp_location [gdb_get_line_number "set breakpoint here"] ++ ++# Set a breakpoint with multiple locations ++# and a condition. ++ ++gdb_test "break $srcfile:$bp_location if i==1" \ ++ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \ ++ "initial condition: set breakpoint" ++ ++gdb_run_cmd ++gdb_expect { ++ -re "Breakpoint \[0-9\]+,.*foo \\(i=1\\).*$gdb_prompt $" { ++ pass "initial condition: run to breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "initial condition: run to breakpoint" ++ } ++ timeout { ++ fail "initial condition: run to breakpoint (timeout)" ++ } ++} ++ ++gdb_test "continue" \ ++ ".*Breakpoint.*foo \\(i=1\\).*" \ ++ "initial condition: run to breakpoint 2" ++ ++# Set breakpoint with multiple locations. ++# Separately set the condition. ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++gdb_test "break $srcfile:$bp_location" \ ++ "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \ ++ "separate condition: set breakpoint" ++ ++gdb_test "condition 1 i==1" "" \ ++ "separate condition: set condition" ++ ++gdb_run_cmd ++gdb_expect { ++ -re "Breakpoint \[0-9\]+,.*foo \\(i=1\\).*$gdb_prompt $" { ++ pass "separate condition: run to breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "separate condition: run to breakpoint" ++ } ++ timeout { ++ fail "separate condition: run to breakpoint (timeout)" ++ } ++} ++ ++gdb_test "continue" \ ++ ".*Breakpoint.*foo \\(i=1\\).*" \ ++ "separate condition: run to breakpoint 2" ++ ++# Try disabling a single location. We also test ++# that at least in simple cases, the enable/disable ++# state of locations surive "run". ++gdb_test "disable 1.1" "" "disabling location: disable" ++ ++gdb_run_cmd ++gdb_expect { ++ -re "Breakpoint \[0-9\]+,.*foo \\(i=1\\).*$gdb_prompt $" { ++ pass "disabling location: run to breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "disabling location: run to breakpoint" ++ } ++ timeout { ++ fail "disabling location: run to breakpoint (timeout)" ++ } ++} ++ ++# Try disabling entire breakpoint ++gdb_test "enable 1.1" "" "disabling location: enable" ++ ++ ++gdb_test "disable 1" "" "disable breakpoint: disable" ++ ++gdb_run_cmd ++gdb_expect { ++ -re "Program exited normally.*$gdb_prompt $" { ++ pass "disable breakpoint: run to breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "disable breakpoint: run to breakpoint" ++ } ++ timeout { ++ fail "disable breakpoint: run to breakpoint (timeout)" ++ } ++} ++ ++# Make sure breakpoint can be set on a specific instantion. ++delete_breakpoints ++gdb_test "break 'void foo(int)'" ".*" \ ++ "instantiation: set breakpoint" ++ ++ ++gdb_run_cmd ++gdb_expect { ++ -re ".*Breakpoint \[0-9\]+,.*foo \\(i=0\\).*$gdb_prompt $" { ++ pass "instantiation: run to breakpoint" ++ } ++ -re "$gdb_prompt $" { ++ fail "instantiation: run to breakpoint" ++ } ++ timeout { ++ fail "instantiation: run to breakpoint (timeout)" ++ } ++} ++ ++gdb_test "continue" \ ++ ".*Breakpoint.*foo \\(i=1\\).*" \ ++ "instantiation: run to breakpoint 2" ++ + +2007-09-26 Vladimir Prus + + * breakpoint.c (create_breakpoint): Set + condition on each location, not on the first + location of breakpoint. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.269 +retrieving revision 1.270 +diff -u -r1.269 -r1.270 +--- src/gdb/breakpoint.c 2007/09/24 07:40:32 1.269 ++++ src/gdb/breakpoint.c 2007/09/26 18:44:55 1.270 +@@ -5163,7 +5163,7 @@ + if (b->cond_string) + { + char *arg = b->cond_string; +- b->loc->cond = parse_exp_1 (&arg, block_for_pc (b->loc->address), 0); ++ loc->cond = parse_exp_1 (&arg, block_for_pc (loc->address), 0); + if (*arg) + { + if (pending_bp) + +2007-09-28 Vladimir Prus + + * NEW: Mention pending breakpoint changes and + support for breakpoints at multiple locations. + +=================================================================== +RCS file: /cvs/src/src/gdb/NEWS,v +retrieving revision 1.239 +retrieving revision 1.240 +diff -u -r1.239 -r1.240 +--- src/gdb/NEWS 2007/09/17 19:30:05 1.239 ++++ src/gdb/NEWS 2007/09/28 06:24:20 1.240 +@@ -3,6 +3,13 @@ + + *** Changes since GDB 6.7 + ++* Pending breakpoints no longer change their number when their address ++ is resolved. ++ ++* GDB now supports breakpoints with multiple locations, ++ including breakpoints on C++ constructors, inside C++ templates, ++ and in inlined functions. ++ + *** Changes in GDB 6.6 + + * Resolved 101 resource leaks, null pointer dereferences, etc. in gdb, + +2007-09-28 Vladimir Prus + + * gdb.texinfo (Setting Breakpoints): Revise + documentation for pending breakpoints. Document + breakpoints with multiple locations. + +=================================================================== +RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v +retrieving revision 1.432 +retrieving revision 1.433 +diff -u -r1.432 -r1.433 +--- src/gdb/doc/gdb.texinfo 2007/09/16 14:59:30 1.432 ++++ src/gdb/doc/gdb.texinfo 2007/09/28 06:24:20 1.433 +@@ -2991,11 +2991,17 @@ + Whether the breakpoint is marked to be disabled or deleted when hit. + @item Enabled or Disabled + Enabled breakpoints are marked with @samp{y}. @samp{n} marks breakpoints +-that are not enabled. ++that are not enabled. An optional @samp{(p)} suffix marks pending ++breakpoints --- breakpoints for which address is either not yet ++resolved, pending load of a shared library, or for which address was ++in a shared library that was since unloaded. Such breakpoint won't ++fire until a shared library that has the symbol or line referred by ++breakpoint is loaded. See below for details. + @item Address +-Where the breakpoint is in your program, as a memory address. If the +-breakpoint is pending (see below for details) on a future load of a shared library, the address +-will be listed as @samp{}. ++Where the breakpoint is in your program, as a memory address. For a ++pending breakpoint whose address is not yet known, this field will ++contain @samp{}. A breakpoint with several locations will ++have @samp{} in this field --- see below for details. + @item What + Where the breakpoint is in the source for your program, as a file and + line number. For a pending breakpoint, the original string passed to +@@ -3032,23 +3038,83 @@ + the breakpoints are conditional, this is even useful + (@pxref{Conditions, ,Break Conditions}). + +-@cindex pending breakpoints +-If a specified breakpoint location cannot be found, it may be due to the fact +-that the location is in a shared library that is yet to be loaded. In such +-a case, you may want @value{GDBN} to create a special breakpoint (known as +-a @dfn{pending breakpoint}) that +-attempts to resolve itself in the future when an appropriate shared library +-gets loaded. +- +-Pending breakpoints are useful to set at the start of your +-@value{GDBN} session for locations that you know will be dynamically loaded +-later by the program being debugged. When shared libraries are loaded, +-a check is made to see if the load resolves any pending breakpoint locations. +-If a pending breakpoint location gets resolved, +-a regular breakpoint is created and the original pending breakpoint is removed. ++It is possible that a breakpoint correspond to several locations ++in your program. Examples of this situation are: ++ ++@itemize @bullet ++ ++@item ++For a C@t{++} constructor, the @value{NGCC} compiler generates several ++instances of the function body, used in different cases. + +-@value{GDBN} provides some additional commands for controlling pending +-breakpoint support: ++@item ++For a C@t{++} template function, a given line in the function can ++correspond to any number of instantiations. ++ ++@item ++For an inlined function, a given source line can correspond to ++several places where that function is inlined. ++ ++@end itemize ++ ++In all those cases, @value{GDBN} will insert a breakpoint at all ++the relevant locations. ++ ++A breakpoint with multiple locations is displayed in the ++breakpoint table using several rows --- one header row, followed ++by one row for each breakpoint location. The header row ++has @samp{} in the address column. The rows for ++individual locations contain the actual addresses for locations, ++and say what functions those locations are in. The number ++column for a location has number in the format ++@var{breakpoint-number}.@var{location-number}. ++ ++For example: ++@smallexample ++Num Type Disp Enb Address What ++1 breakpoint keep y ++ stop only if i==1 ++ breakpoint already hit 1 time ++1.1 y 0x080486a2 in void foo() at t.cc:8 ++1.2 y 0x080486ca in void foo() at t.cc:8 ++@end smallexample ++ ++Each location can be individually enabled or disabled by passing ++@var{breakpoint-number}.@var{location-number} as argument to the ++@code{enable} and @code{disable} commands. ++ ++@cindex pending breakpoints ++It's quite common to have a breakpoint inside a shared library. ++The shared library may be loaded and unloaded explicitly, ++and possibly repeatedly, as the program is executed. To support ++this use case, @value{GDBN} updates breakpoint locations whenever ++any shared library is loaded or unloaded. Typically, you would ++set a breakpoint in a shared library at the beginning of your ++debugging session, when the library is not loaded, and when the ++symbols from the library are not available. When you try to set ++breakpoint, @value{GDBN} will ask you if you want to set ++a so called @dfn{pending breakpoint} --- breakpoint whose address ++is not yet resolved. ++ ++After the program is run, whenever a new shared library is loaded, ++@value{GDBN} reevaluates all the breakpoints. When a newly loaded ++shared library contains the symbol or line referred to by some ++pending breakpoint, that breakpoint is resolved and becomes an ++ordinary breakpoint. When a library is unloaded, all breakpoints ++that refer to its symbols or source lines become pending again. ++ ++This logic works for breakpoints with multiple locations, too. For ++example, if you have a breakpoint in a C@t{++} template function, and ++a newly loaded shared library has an instantiation of that template, ++a new location is added to the list of locations for the breakpoint. ++ ++Except for having unresolved address, pending breakpoints do not ++differ from regular breakpoints. You can set conditions or commands, ++enable and disable them and perform other breakpoint operations. ++ ++@value{GDBN} provides some additional commands for controlling what ++happens when the @samp{break} command cannot resolve breakpoint ++address specification to an address: + + @kindex set breakpoint pending + @kindex show breakpoint pending +@@ -3070,19 +3136,9 @@ + Show the current behavior setting for creating pending breakpoints. + @end table + +-@cindex operations allowed on pending breakpoints +-Normal breakpoint operations apply to pending breakpoints as well. You may +-specify a condition for a pending breakpoint and/or commands to run when the +-breakpoint is reached. You can also enable or disable +-the pending breakpoint. When you specify a condition for a pending breakpoint, +-the parsing of the condition will be deferred until the point where the +-pending breakpoint location is resolved. Disabling a pending breakpoint +-tells @value{GDBN} to not attempt to resolve the breakpoint on any subsequent +-shared library load. When a pending breakpoint is re-enabled, +-@value{GDBN} checks to see if the location is already resolved. +-This is done because any number of shared library loads could have +-occurred since the time the breakpoint was disabled and one or more +-of these loads could resolve the location. ++The settings above only affect the @code{break} command and its ++variants. Once breakpoint is set, it will be automatically updated ++as shared libraries are loaded and unloaded. + + @cindex automatic hardware breakpoints + For some targets, @value{GDBN} can automatically decide if hardware or + +2007-10-08 Pierre Muller + + * breakpoint.c (print_one_breakpoint_location): ARI fix: + Replace asprintf by xstrprintf. + +=================================================================== +RCS file: /cvs/src/src/gdb/breakpoint.c,v +retrieving revision 1.271 +retrieving revision 1.272 +diff -u -r1.271 -r1.272 +--- src/gdb/breakpoint.c 2007/10/01 00:17:57 1.271 ++++ src/gdb/breakpoint.c 2007/10/08 15:23:42 1.272 +@@ -3526,7 +3526,7 @@ + if (part_of_multiple) + { + char *formatted; +- asprintf (&formatted, "%d.%d", b->number, loc_number); ++ formatted = xstrprintf ("%d.%d", b->number, loc_number); + ui_out_field_string (uiout, "number", formatted); + xfree (formatted); + } diff --git a/gdb.spec b/gdb.spec index a8c3281..f9423fe 100644 --- a/gdb.spec +++ b/gdb.spec @@ -11,7 +11,7 @@ Name: gdb Version: 6.7.1 # The release always contains a leading reserved number, start it at 1. -Release: 1%{?dist} +Release: 2%{?dist} License: GPL Group: Development/Debuggers @@ -85,12 +85,6 @@ Patch260: gdb-6.6-scheduler_locking-step-is-default.patch # Threaded watchpoint support Patch113: gdb-6.3-threaded-watchpoints-20041213.patch -# Fix to expose multiple constructors to end-user -Patch115: gdb-6.3-constructor-20041216.patch - -# Fix to display base constructors from list and breakpoint commands -Patch116: gdb-6.3-linespec-20041213.patch - # Continue removing breakpoints even when failure occurs. Patch117: gdb-6.3-removebp-20041130.patch @@ -114,13 +108,6 @@ Patch125: gdb-6.3-test-self-20050110.patch # Fix for non-threaded watchpoints. Patch128: gdb-6.3-nonthreaded-wp-20050117.patch -# Add PPC .symbols to min-symtable. -Patch130: gdb-6.3-ctorline-20050120.patch - -# Fix to support multiple destructors just like multiple constructors -Patch133: gdb-6.3-test-dtorfix-20050121.patch -Patch134: gdb-6.3-dtorfix-20050121.patch - # Fix to support executable moving Patch136: gdb-6.3-test-movedir-20050125.patch @@ -180,9 +167,6 @@ Patch163: gdb-6.3-inheritancetest-20050726.patch # Add readnever option Patch164: gdb-6.3-readnever-20050907.patch -# Remove extraneous xfree -Patch165: gdb-6.3-xfree-20050922.patch - # Fix frame pointer for ia64 sigtramp frame Patch166: gdb-6.3-ia64-sigtramp-fp-20050926.patch @@ -206,12 +190,6 @@ Patch178: gdb-6.3-catch-debug-registers-error-20060527.patch # ia32el. Patch179: gdb-6.3-ia32el-fix-waitpid-20060615.patch -# Bugfix segv on the source display by ^X 1 (fixes Patch130, BZ 200048). -Patch181: gdb-6.5-bz200048-find_line_pc-segv.patch - -# Bugfix object names completion (fixes Patch116, BZ 193763). -Patch185: gdb-6.3-bz193763-object-name-completion.patch - # Testcase for corrupted or missing location list information (BZ 196439). Patch187: gdb-6.5-bz196439-valgrind-memcheck-compat-test.patch @@ -385,6 +363,7 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c # Apply patches defined above. +%patch232 -p1 %patch0 -p1 %patch1 -p1 %patch2 -p1 @@ -399,8 +378,6 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch111 -p1 %patch112 -p1 %patch113 -p1 -%patch115 -p1 -%patch116 -p1 %patch117 -p1 %patch118 -p1 %patch119 -p1 @@ -409,9 +386,6 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch124 -p1 %patch125 -p1 %patch128 -p1 -%patch130 -p1 -%patch133 -p1 -%patch134 -p1 %patch136 -p1 %patch139 -p1 %patch140 -p1 @@ -432,7 +406,6 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch162 -p1 %patch163 -p1 %patch164 -p1 -%patch165 -p1 %patch166 -p1 %patch169 -p1 %patch170 -p1 @@ -440,8 +413,6 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch177 -p1 %patch178 -p1 %patch179 -p1 -%patch181 -p1 -%patch185 -p1 %patch187 -p1 %patch188 -p1 %patch190 -p1 @@ -462,7 +433,6 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c %patch225 -p1 %patch229 -p1 %patch231 -p1 -%patch232 -p1 %patch234 -p1 %patch235 -p1 %patch236 -p1 @@ -642,6 +612,9 @@ fi # don't include the files in include, they are part of binutils %changelog +* Sat Nov 3 2007 Jan Kratochvil - 6.7.1-2 +- Backport `Breakpoints at multiple locations' patch primarily for C++. + * Thu Nov 1 2007 Jan Kratochvil - 6.7.1-1 - Upgrade to GDB 6.7.1. Drop redundant patches, forward-port remaining ones.