From 30f2069f6eae88d7672db5d92a457dce007d578e Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sat, 18 Aug 2012 09:41:09 +0200 Subject: [PATCH] Rebase to FSF GDB 7.5. - Update dlopen to support two variants of glibc (Gary Benson, BZ 669432). --- .gitignore | 2 +- gdb-dlopen-stap-probe-1of7.patch | 795 ++++++++++++ gdb-dlopen-stap-probe-2of7.patch | 74 ++ gdb-dlopen-stap-probe-3of7.patch | 98 ++ gdb-dlopen-stap-probe-4of7.patch | 131 ++ gdb-dlopen-stap-probe-5of7.patch | 17 + gdb-dlopen-stap-probe-6of7.patch | 1989 +++++++++++++++++++++++++++++ gdb-dlopen-stap-probe-7of7.patch | 147 +++ gdb-dlopen-stap-probe-test.patch | 101 -- gdb-dlopen-stap-probe-test2.patch | 69 + gdb-dlopen-stap-probe.patch | 357 ------ gdb.spec | 36 +- sources | 2 +- 13 files changed, 3349 insertions(+), 469 deletions(-) create mode 100644 gdb-dlopen-stap-probe-1of7.patch create mode 100644 gdb-dlopen-stap-probe-2of7.patch create mode 100644 gdb-dlopen-stap-probe-3of7.patch create mode 100644 gdb-dlopen-stap-probe-4of7.patch create mode 100644 gdb-dlopen-stap-probe-5of7.patch create mode 100644 gdb-dlopen-stap-probe-6of7.patch create mode 100644 gdb-dlopen-stap-probe-7of7.patch create mode 100644 gdb-dlopen-stap-probe-test2.patch delete mode 100644 gdb-dlopen-stap-probe.patch diff --git a/.gitignore b/.gitignore index 5b72433..66e0ded 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ /gdb-libstdc++-v3-python-r155978.tar.bz2 -/gdb-7.4.91.20120801.tar.bz2 +/gdb-7.5.tar.bz2 diff --git a/gdb-dlopen-stap-probe-1of7.patch b/gdb-dlopen-stap-probe-1of7.patch new file mode 100644 index 0000000..1891fb3 --- /dev/null +++ b/gdb-dlopen-stap-probe-1of7.patch @@ -0,0 +1,795 @@ +http://sourceware.org/ml/gdb-cvs/2012-07/msg00123.html + +### src/gdb/ChangeLog 2012/07/18 04:36:15 1.14473 +### src/gdb/ChangeLog 2012/07/18 16:12:15 1.14474 +## -1,3 +1,37 @@ ++2012-07-18 Sergio Durigan Junior ++ ++ * elfread.c (elf_get_probe_argument_count): Remove `objfile' argument. ++ (elf_compile_to_ax): Likewise. ++ * infrun.c (insert_exception_resume_from_probe): Likewise. ++ (check_exception_resume): Remove `objfile' variable. ++ * probe.c (find_probe_by_pc): Remove `objfile' argument. ++ (struct probe_and_objfile, probe_and_objfile_s): Delete. ++ (collect_probes): Adjust return value to `VEC (probe_p) *'. ++ (compare_entries): Rename to... ++ (compare_probes): ...this. Adjust function to work with ++ `struct probe *'. Rename variables `ea' and `eb' to `pa' and `pb' ++ respectively. ++ (gen_ui_out_table_header_info): Adjust `probes' argument to be ++ `VEC (probe_p) *'. ++ (print_ui_out_info): Adjust argument to be `struct probe *'. ++ (info_probes_for_ops): Adjust internal computations to use ++ `VEC (probe_p) *'. ++ (probe_safe_evaluate_at_pc): Refactor to not pass `objfile' anymore. ++ * probe.h (struct probe_ops) : Remove `objfile' argument. ++ (struct probe) : New field. ++ (find_probe_by_pc): Remove `objfile' argument. ++ * stap-probe.c (stap_parse_probe_arguments): Likewise. ++ (stap_get_probe_argument_count): Likewise. ++ (stap_get_arg): Likewise. ++ (stap_evaluate_probe_argument): Likewise. ++ (stap_compile_to_ax): Likewise. ++ (compile_probe_arg): Refactor not to pass `objfile' anymore. ++ (handle_stap_probe): Fill `objfile' field from `struct probe'. ++ (stap_gen_info_probes_table_header): Remove `objfile' argument. ++ * symfile.h (struct sym_probe_fns) : Likewise. ++ + 2012-07-18 Terry Guo + + PR 14329 +--- src/gdb/elfread.c 2012/06/26 20:14:01 1.133 ++++ src/gdb/elfread.c 2012/07/18 16:12:15 1.134 +@@ -1635,33 +1635,29 @@ + symfile.h. */ + + static unsigned +-elf_get_probe_argument_count (struct objfile *objfile, +- struct probe *probe) ++elf_get_probe_argument_count (struct probe *probe) + { +- return probe->pops->get_probe_argument_count (probe, objfile); ++ return probe->pops->get_probe_argument_count (probe); + } + + /* Implementation of `sym_evaluate_probe_argument', as documented in + symfile.h. */ + + static struct value * +-elf_evaluate_probe_argument (struct objfile *objfile, +- struct probe *probe, +- unsigned n) ++elf_evaluate_probe_argument (struct probe *probe, unsigned n) + { +- return probe->pops->evaluate_probe_argument (probe, objfile, n); ++ return probe->pops->evaluate_probe_argument (probe, n); + } + + /* Implementation of `sym_compile_to_ax', as documented in symfile.h. */ + + static void +-elf_compile_to_ax (struct objfile *objfile, +- struct probe *probe, ++elf_compile_to_ax (struct probe *probe, + struct agent_expr *expr, + struct axs_value *value, + unsigned n) + { +- probe->pops->compile_to_ax (probe, objfile, expr, value, n); ++ probe->pops->compile_to_ax (probe, expr, value, n); + } + + /* Implementation of `sym_relocate_probe', as documented in symfile.h. */ +--- src/gdb/infrun.c 2012/07/01 10:37:04 1.549 ++++ src/gdb/infrun.c 2012/07/18 16:12:16 1.550 +@@ -5518,7 +5518,6 @@ + static void + insert_exception_resume_from_probe (struct thread_info *tp, + const struct probe *probe, +- struct objfile *objfile, + struct frame_info *frame) + { + struct value *arg_value; +@@ -5534,7 +5533,7 @@ + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: exception resume at %s\n", +- paddress (get_objfile_arch (objfile), ++ paddress (get_objfile_arch (probe->objfile), + handler)); + + bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame), +@@ -5552,7 +5551,6 @@ + struct frame_info *frame) + { + volatile struct gdb_exception e; +- struct objfile *objfile; + const struct probe *probe; + struct symbol *func; + +@@ -5560,11 +5558,10 @@ + SystemTap probe point. If so, the probe has two arguments: the + CFA and the HANDLER. We ignore the CFA, extract the handler, and + set a breakpoint there. */ +- probe = find_probe_by_pc (get_frame_pc (frame), &objfile); ++ probe = find_probe_by_pc (get_frame_pc (frame)); + if (probe) + { +- insert_exception_resume_from_probe (ecs->event_thread, probe, +- objfile, frame); ++ insert_exception_resume_from_probe (ecs->event_thread, probe, frame); + return; + } + +--- src/gdb/probe.c 2012/05/08 01:35:34 1.3 ++++ src/gdb/probe.c 2012/07/18 16:12:17 1.4 +@@ -204,7 +204,7 @@ + /* See definition in probe.h. */ + + struct probe * +-find_probe_by_pc (CORE_ADDR pc, struct objfile **objfile_out) ++find_probe_by_pc (CORE_ADDR pc) + { + struct objfile *objfile; + +@@ -221,10 +221,7 @@ + probes = objfile->sf->sym_probe_fns->sym_get_probes (objfile); + for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) + if (probe->address == pc) +- { +- *objfile_out = objfile; +- return probe; +- } ++ return probe; + } + + return NULL; +@@ -232,21 +229,6 @@ + + + +-/* A utility structure. A VEC of these is built when handling "info +- probes". */ +- +-struct probe_and_objfile +-{ +- /* The probe. */ +- struct probe *probe; +- +- /* The probe's objfile. */ +- struct objfile *objfile; +-}; +- +-typedef struct probe_and_objfile probe_and_objfile_s; +-DEF_VEC_O (probe_and_objfile_s); +- + /* A helper function for collect_probes that compiles a regexp and + throws an exception on error. This installs a cleanup to free the + resulting pattern on success. If RX is NULL, this does nothing. */ +@@ -275,16 +257,16 @@ + If POPS is not NULL, only probes of this certain probe_ops will match. + Each argument is a regexp, or NULL, which matches anything. */ + +-static VEC (probe_and_objfile_s) * ++static VEC (probe_p) * + collect_probes (char *objname, char *provider, char *probe_name, + const struct probe_ops *pops) + { + struct objfile *objfile; +- VEC (probe_and_objfile_s) *result = NULL; ++ VEC (probe_p) *result = NULL; + struct cleanup *cleanup, *cleanup_temps; + regex_t obj_pat, prov_pat, probe_pat; + +- cleanup = make_cleanup (VEC_cleanup (probe_and_objfile_s), &result); ++ cleanup = make_cleanup (VEC_cleanup (probe_p), &result); + + cleanup_temps = make_cleanup (null_cleanup, NULL); + compile_rx_or_error (&prov_pat, provider, _("Invalid provider regexp")); +@@ -310,8 +292,6 @@ + + for (ix = 0; VEC_iterate (probe_p, probes, ix, probe); ix++) + { +- probe_and_objfile_s entry; +- + if (pops != NULL && probe->pops != pops) + continue; + +@@ -323,9 +303,7 @@ + && regexec (&probe_pat, probe->name, 0, NULL, 0) != 0) + continue; + +- entry.probe = probe; +- entry.objfile = objfile; +- VEC_safe_push (probe_and_objfile_s, result, &entry); ++ VEC_safe_push (probe_p, result, probe); + } + } + +@@ -334,36 +312,36 @@ + return result; + } + +-/* A qsort comparison function for probe_and_objfile_s objects. */ ++/* A qsort comparison function for probe_p objects. */ + + static int +-compare_entries (const void *a, const void *b) ++compare_probes (const void *a, const void *b) + { +- const probe_and_objfile_s *ea = a; +- const probe_and_objfile_s *eb = b; ++ const struct probe *pa = *((const struct probe **) a); ++ const struct probe *pb = *((const struct probe **) b); + int v; + +- v = strcmp (ea->probe->provider, eb->probe->provider); ++ v = strcmp (pa->provider, pb->provider); + if (v) + return v; + +- v = strcmp (ea->probe->name, eb->probe->name); ++ v = strcmp (pa->name, pb->name); + if (v) + return v; + +- if (ea->probe->address < eb->probe->address) ++ if (pa->address < pb->address) + return -1; +- if (ea->probe->address > eb->probe->address) ++ if (pa->address > pb->address) + return 1; + +- return strcmp (ea->objfile->name, eb->objfile->name); ++ return strcmp (pa->objfile->name, pb->objfile->name); + } + + /* Helper function that generate entries in the ui_out table being + crafted by `info_probes_for_ops'. */ + + static void +-gen_ui_out_table_header_info (VEC (probe_and_objfile_s) *probes, ++gen_ui_out_table_header_info (VEC (probe_p) *probes, + const struct probe_ops *p) + { + /* `headings' refers to the names of the columns when printing `info +@@ -392,11 +370,11 @@ + VEC_iterate (info_probe_column_s, headings, ix, column); + ++ix) + { +- probe_and_objfile_s *entry; ++ struct probe *probe; + int jx; + size_t size_max = strlen (column->print_name); + +- for (jx = 0; VEC_iterate (probe_and_objfile_s, probes, jx, entry); ++jx) ++ for (jx = 0; VEC_iterate (probe_p, probes, jx, probe); ++jx) + { + /* `probe_fields' refers to the values of each new field that this + probe will display. */ +@@ -405,12 +383,11 @@ + const char *val; + int kx; + +- if (entry->probe->pops != p) ++ if (probe->pops != p) + continue; + + c2 = make_cleanup (VEC_cleanup (const_char_ptr), &probe_fields); +- p->gen_info_probes_table_values (entry->probe, entry->objfile, +- &probe_fields); ++ p->gen_info_probes_table_values (probe, &probe_fields); + + gdb_assert (VEC_length (const_char_ptr, probe_fields) + == headings_size); +@@ -437,10 +414,10 @@ + } + + /* Helper function to print extra information about a probe and an objfile +- represented by ENTRY. */ ++ represented by PROBE. */ + + static void +-print_ui_out_info (probe_and_objfile_s *entry) ++print_ui_out_info (struct probe *probe) + { + int ix; + int j = 0; +@@ -451,23 +428,21 @@ + info_probe_column_s *column; + struct cleanup *c; + +- gdb_assert (entry != NULL); +- gdb_assert (entry->probe != NULL); +- gdb_assert (entry->probe->pops != NULL); ++ gdb_assert (probe != NULL); ++ gdb_assert (probe->pops != NULL); + +- if (entry->probe->pops->gen_info_probes_table_header == NULL +- && entry->probe->pops->gen_info_probes_table_values == NULL) ++ if (probe->pops->gen_info_probes_table_header == NULL ++ && probe->pops->gen_info_probes_table_values == NULL) + return; + +- gdb_assert (entry->probe->pops->gen_info_probes_table_header != NULL +- && entry->probe->pops->gen_info_probes_table_values != NULL); ++ gdb_assert (probe->pops->gen_info_probes_table_header != NULL ++ && probe->pops->gen_info_probes_table_values != NULL); + + c = make_cleanup (VEC_cleanup (info_probe_column_s), &headings); + make_cleanup (VEC_cleanup (const_char_ptr), &values); + +- entry->probe->pops->gen_info_probes_table_header (&headings); +- entry->probe->pops->gen_info_probes_table_values (entry->probe, +- entry->objfile, &values); ++ probe->pops->gen_info_probes_table_header (&headings); ++ probe->pops->gen_info_probes_table_values (probe, &values); + + gdb_assert (VEC_length (info_probe_column_s, headings) + == VEC_length (const_char_ptr, values)); +@@ -515,16 +490,16 @@ + void + info_probes_for_ops (char *arg, int from_tty, const struct probe_ops *pops) + { +- char *provider, *probe = NULL, *objname = NULL; ++ char *provider, *probe_name = NULL, *objname = NULL; + struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); +- VEC (probe_and_objfile_s) *items; ++ VEC (probe_p) *probes; + int i, any_found; + int ui_out_extra_fields = 0; + size_t size_addr; + size_t size_name = strlen ("Name"); + size_t size_objname = strlen ("Object"); + size_t size_provider = strlen ("Provider"); +- probe_and_objfile_s *entry; ++ struct probe *probe; + struct gdbarch *gdbarch = get_current_arch (); + + /* Do we have a `provider:probe:objfile' style of linespec? */ +@@ -533,10 +508,10 @@ + { + make_cleanup (xfree, provider); + +- probe = extract_arg (&arg); +- if (probe) ++ probe_name = extract_arg (&arg); ++ if (probe_name) + { +- make_cleanup (xfree, probe); ++ make_cleanup (xfree, probe_name); + + objname = extract_arg (&arg); + if (objname) +@@ -564,28 +539,27 @@ + else + ui_out_extra_fields = get_number_extra_fields (pops); + +- items = collect_probes (objname, provider, probe, pops); +- make_cleanup (VEC_cleanup (probe_and_objfile_s), &items); ++ probes = collect_probes (objname, provider, probe_name, pops); ++ make_cleanup (VEC_cleanup (probe_p), &probes); + make_cleanup_ui_out_table_begin_end (current_uiout, + 4 + ui_out_extra_fields, +- VEC_length (probe_and_objfile_s, items), ++ VEC_length (probe_p, probes), + "StaticProbes"); + +- if (!VEC_empty (probe_and_objfile_s, items)) +- qsort (VEC_address (probe_and_objfile_s, items), +- VEC_length (probe_and_objfile_s, items), +- sizeof (probe_and_objfile_s), compare_entries); ++ if (!VEC_empty (probe_p, probes)) ++ qsort (VEC_address (probe_p, probes), VEC_length (probe_p, probes), ++ sizeof (probe_p), compare_probes); + + /* What's the size of an address in our architecture? */ + size_addr = gdbarch_addr_bit (gdbarch) == 64 ? 18 : 10; + + /* Determining the maximum size of each field (`provider', `name' and + `objname'). */ +- for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i) ++ for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i) + { +- size_name = max (strlen (entry->probe->name), size_name); +- size_provider = max (strlen (entry->probe->provider), size_provider); +- size_objname = max (strlen (entry->objfile->name), size_objname); ++ size_name = max (strlen (probe->name), size_name); ++ size_provider = max (strlen (probe->provider), size_provider); ++ size_objname = max (strlen (probe->objfile->name), size_objname); + } + + ui_out_table_header (current_uiout, size_provider, ui_left, "provider", +@@ -601,26 +575,26 @@ + /* We have to generate the table header for each new probe type that we + will print. */ + for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); ++ix) +- gen_ui_out_table_header_info (items, po); ++ gen_ui_out_table_header_info (probes, po); + } + else +- gen_ui_out_table_header_info (items, pops); ++ gen_ui_out_table_header_info (probes, pops); + + ui_out_table_header (current_uiout, size_objname, ui_left, "object", + _("Object")); + ui_out_table_body (current_uiout); + +- for (i = 0; VEC_iterate (probe_and_objfile_s, items, i, entry); ++i) ++ for (i = 0; VEC_iterate (probe_p, probes, i, probe); ++i) + { + struct cleanup *inner; + + inner = make_cleanup_ui_out_tuple_begin_end (current_uiout, "probe"); + +- ui_out_field_string (current_uiout, "provider", entry->probe->provider); +- ui_out_field_string (current_uiout, "name", entry->probe->name); ++ ui_out_field_string (current_uiout, "provider", probe->provider); ++ ui_out_field_string (current_uiout, "name", probe->name); + ui_out_field_core_addr (current_uiout, "addr", +- get_objfile_arch (entry->objfile), +- entry->probe->address); ++ get_objfile_arch (probe->objfile), ++ probe->address); + + if (pops == NULL) + { +@@ -629,19 +603,19 @@ + + for (ix = 0; VEC_iterate (probe_ops_cp, all_probe_ops, ix, po); + ++ix) +- if (entry->probe->pops == po) +- print_ui_out_info (entry); ++ if (probe->pops == po) ++ print_ui_out_info (probe); + } + else +- print_ui_out_info (entry); ++ print_ui_out_info (probe); + +- ui_out_field_string (current_uiout, "object", entry->objfile->name); ++ ui_out_field_string (current_uiout, "object", probe->objfile->name); + ui_out_text (current_uiout, "\n"); + + do_cleanups (inner); + } + +- any_found = !VEC_empty (probe_and_objfile_s, items); ++ any_found = !VEC_empty (probe_p, probes); + do_cleanups (cleanup); + + if (!any_found) +@@ -662,23 +636,24 @@ + probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) + { + struct probe *probe; +- struct objfile *objfile; ++ const struct sym_probe_fns *probe_fns; + unsigned n_probes; + +- probe = find_probe_by_pc (get_frame_pc (frame), &objfile); ++ probe = find_probe_by_pc (get_frame_pc (frame)); + if (!probe) + return NULL; +- gdb_assert (objfile->sf && objfile->sf->sym_probe_fns); + +- n_probes +- = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, +- probe); ++ gdb_assert (probe->objfile != NULL); ++ gdb_assert (probe->objfile->sf != NULL); ++ gdb_assert (probe->objfile->sf->sym_probe_fns != NULL); ++ ++ probe_fns = probe->objfile->sf->sym_probe_fns; ++ n_probes = probe_fns->sym_get_probe_argument_count (probe); ++ + if (n >= n_probes) + return NULL; + +- return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile, +- probe, +- n); ++ return probe_fns->sym_evaluate_probe_argument (probe, n); + } + + /* See comment in probe.h. */ +--- src/gdb/probe.h 2012/04/27 20:47:55 1.1 ++++ src/gdb/probe.h 2012/07/18 16:12:17 1.2 +@@ -66,21 +66,18 @@ + + /* Return the number of arguments of PROBE. */ + +- unsigned (*get_probe_argument_count) (struct probe *probe, +- struct objfile *objfile); ++ unsigned (*get_probe_argument_count) (struct probe *probe); + + /* Evaluate the Nth argument from the PROBE, returning a value + corresponding to it. The argument number is represented N. */ + + struct value *(*evaluate_probe_argument) (struct probe *probe, +- struct objfile *objfile, + unsigned n); + + /* Compile the Nth argument of the PROBE to an agent expression. + The argument number is represented by N. */ + +- void (*compile_to_ax) (struct probe *probe, struct objfile *objfile, +- struct agent_expr *aexpr, ++ void (*compile_to_ax) (struct probe *probe, struct agent_expr *aexpr, + struct axs_value *axs_value, unsigned n); + + /* Set the semaphore associated with the PROBE. This function only makes +@@ -108,8 +105,8 @@ + void (*gen_info_probes_table_header) (VEC (info_probe_column_s) **heads); + + /* Function that will fill VALUES with the values of the extra fields +- to be printed for PROBE and OBJFILE. If the backend implements +- the `gen_ui_out_table_header' method, then it should implement ++ to be printed for PROBE. If the backend implements the ++ `gen_ui_out_table_header' method, then it should implement + this method as well. The backend should also guarantee that the + order and the number of values in the vector is exactly the same + as the order of the extra fields provided in the method +@@ -118,7 +115,6 @@ + position in the vector. */ + + void (*gen_info_probes_table_values) (struct probe *probe, +- struct objfile *objfile, + VEC (const_char_ptr) **values); + }; + +@@ -157,6 +153,11 @@ + /* The operations associated with this probe. */ + const struct probe_ops *pops; + ++ /* The objfile which contains this probe. Even if the probe is also ++ present in a separate debug objfile, this variable always points to ++ the non-separate debug objfile. */ ++ struct objfile *objfile; ++ + /* The name of the probe. */ + const char *name; + +@@ -181,11 +182,9 @@ + extern void register_probe_ops (struct probe *probe); + + /* Given a PC, find an associated probe with type PTYPE. If a probe is +- found, set *OBJFILE_OUT to the probe's objfile, and return the +- probe. If no probe is found, return NULL. */ ++ found, return it. If no probe is found, return NULL. */ + +-extern struct probe *find_probe_by_pc (CORE_ADDR pc, +- struct objfile **objfile_out); ++extern struct probe *find_probe_by_pc (CORE_ADDR pc); + + /* Search OBJFILE for a probe with the given PROVIDER, NAME and PTYPE. + Return a VEC of all probes that were found. If no matching probe +--- src/gdb/stap-probe.c 2012/05/08 01:35:35 1.4 ++++ src/gdb/stap-probe.c 2012/07/18 16:12:17 1.5 +@@ -903,10 +903,10 @@ + this information. */ + + static void +-stap_parse_probe_arguments (struct stap_probe *probe, struct objfile *objfile) ++stap_parse_probe_arguments (struct stap_probe *probe) + { + const char *cur; +- struct gdbarch *gdbarch = get_objfile_arch (objfile); ++ struct gdbarch *gdbarch = get_objfile_arch (probe->p.objfile); + + gdb_assert (!probe->args_parsed); + cur = probe->args_u.text; +@@ -991,15 +991,14 @@ + argument string. */ + + static unsigned +-stap_get_probe_argument_count (struct probe *probe_generic, +- struct objfile *objfile) ++stap_get_probe_argument_count (struct probe *probe_generic) + { + struct stap_probe *probe = (struct stap_probe *) probe_generic; + + gdb_assert (probe_generic->pops == &stap_probe_ops); + + if (!probe->args_parsed) +- stap_parse_probe_arguments (probe, objfile); ++ stap_parse_probe_arguments (probe); + + gdb_assert (probe->args_parsed); + return VEC_length (stap_probe_arg_s, probe->args_u.vec); +@@ -1042,10 +1041,10 @@ + } + + static struct stap_probe_arg * +-stap_get_arg (struct stap_probe *probe, struct objfile *objfile, unsigned n) ++stap_get_arg (struct stap_probe *probe, unsigned n) + { + if (!probe->args_parsed) +- stap_parse_probe_arguments (probe, objfile); ++ stap_parse_probe_arguments (probe); + + return VEC_index (stap_probe_arg_s, probe->args_u.vec, n); + } +@@ -1054,8 +1053,7 @@ + corresponding to it. Assertion is thrown if N does not exist. */ + + static struct value * +-stap_evaluate_probe_argument (struct probe *probe_generic, +- struct objfile *objfile, unsigned n) ++stap_evaluate_probe_argument (struct probe *probe_generic, unsigned n) + { + struct stap_probe *stap_probe = (struct stap_probe *) probe_generic; + struct stap_probe_arg *arg; +@@ -1063,7 +1061,7 @@ + + gdb_assert (probe_generic->pops == &stap_probe_ops); + +- arg = stap_get_arg (stap_probe, objfile, n); ++ arg = stap_get_arg (stap_probe, n); + return evaluate_subexp_standard (arg->atype, arg->aexpr, &pos, EVAL_NORMAL); + } + +@@ -1071,9 +1069,8 @@ + Assertion is thrown if N does not exist. */ + + static void +-stap_compile_to_ax (struct probe *probe_generic, struct objfile *objfile, +- struct agent_expr *expr, struct axs_value *value, +- unsigned n) ++stap_compile_to_ax (struct probe *probe_generic, struct agent_expr *expr, ++ struct axs_value *value, unsigned n) + { + struct stap_probe *stap_probe = (struct stap_probe *) probe_generic; + struct stap_probe_arg *arg; +@@ -1081,7 +1078,7 @@ + + gdb_assert (probe_generic->pops == &stap_probe_ops); + +- arg = stap_get_arg (stap_probe, objfile, n); ++ arg = stap_get_arg (stap_probe, n); + + pc = arg->aexpr->elts; + gen_expr (arg->aexpr, &pc, expr, value); +@@ -1124,20 +1121,24 @@ + struct frame_info *frame = get_selected_frame (_("No frame selected")); + CORE_ADDR pc = get_frame_pc (frame); + int sel = (int) (uintptr_t) data; +- struct objfile *objfile; + struct probe *pc_probe; ++ const struct sym_probe_fns *pc_probe_fns; + unsigned n_args; + + /* SEL == -1 means "_probe_argc". */ + gdb_assert (sel >= -1); + +- pc_probe = find_probe_by_pc (pc, &objfile); ++ pc_probe = find_probe_by_pc (pc); + if (pc_probe == NULL) + error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc)); + +- n_args +- = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, +- pc_probe); ++ gdb_assert (pc_probe->objfile != NULL); ++ gdb_assert (pc_probe->objfile->sf != NULL); ++ gdb_assert (pc_probe->objfile->sf->sym_probe_fns != NULL); ++ ++ pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns; ++ ++ n_args = pc_probe_fns->sym_get_probe_argument_count (pc_probe); + if (sel == -1) + return value_from_longest (builtin_type (arch)->builtin_int, n_args); + +@@ -1145,9 +1146,7 @@ + error (_("Invalid probe argument %d -- probe has %u arguments available"), + sel, n_args); + +- return objfile->sf->sym_probe_fns->sym_evaluate_probe_argument (objfile, +- pc_probe, +- sel); ++ return pc_probe_fns->sym_evaluate_probe_argument (pc_probe, sel); + } + + /* This is called to compile one of the $_probe_arg* convenience +@@ -1159,20 +1158,25 @@ + { + CORE_ADDR pc = expr->scope; + int sel = (int) (uintptr_t) data; +- struct objfile *objfile; + struct probe *pc_probe; ++ const struct sym_probe_fns *pc_probe_fns; + int n_probes; + + /* SEL == -1 means "_probe_argc". */ + gdb_assert (sel >= -1); + +- pc_probe = find_probe_by_pc (pc, &objfile); ++ pc_probe = find_probe_by_pc (pc); + if (pc_probe == NULL) + error (_("No SystemTap probe at PC %s"), core_addr_to_string (pc)); + +- n_probes +- = objfile->sf->sym_probe_fns->sym_get_probe_argument_count (objfile, +- pc_probe); ++ gdb_assert (pc_probe->objfile != NULL); ++ gdb_assert (pc_probe->objfile->sf != NULL); ++ gdb_assert (pc_probe->objfile->sf->sym_probe_fns != NULL); ++ ++ pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns; ++ ++ n_probes = pc_probe_fns->sym_get_probe_argument_count (pc_probe); ++ + if (sel == -1) + { + value->kind = axs_rvalue; +@@ -1186,8 +1190,7 @@ + error (_("Invalid probe argument %d -- probe has %d arguments available"), + sel, n_probes); + +- objfile->sf->sym_probe_fns->sym_compile_to_ax (objfile, pc_probe, +- expr, value, sel); ++ pc_probe_fns->sym_compile_to_ax (pc_probe, expr, value, sel); + } + + +@@ -1297,6 +1300,7 @@ + + ret = obstack_alloc (&objfile->objfile_obstack, sizeof (*ret)); + ret->p.pops = &stap_probe_ops; ++ ret->p.objfile = objfile; + + /* Provider and the name of the probe. */ + ret->p.provider = &el->data[3 * size]; +@@ -1481,15 +1485,16 @@ + + static void + stap_gen_info_probes_table_values (struct probe *probe_generic, +- struct objfile *objfile, + VEC (const_char_ptr) **ret) + { + struct stap_probe *probe = (struct stap_probe *) probe_generic; +- struct gdbarch *gdbarch = get_objfile_arch (objfile); ++ struct gdbarch *gdbarch; + const char *val = NULL; + + gdb_assert (probe_generic->pops == &stap_probe_ops); + ++ gdbarch = get_objfile_arch (probe->p.objfile); ++ + if (probe->sem_addr) + val = print_core_address (gdbarch, probe->sem_addr); + +--- src/gdb/symfile.h 2012/05/24 22:14:35 1.109 ++++ src/gdb/symfile.h 2012/07/18 16:12:17 1.110 +@@ -320,8 +320,7 @@ + have come from a call to this objfile's sym_get_probes method. + If you provide an implementation of sym_get_probes, you must + implement this method as well. */ +- unsigned (*sym_get_probe_argument_count) (struct objfile *objfile, +- struct probe *probe); ++ unsigned (*sym_get_probe_argument_count) (struct probe *probe); + + /* Evaluate the Nth argument available to PROBE. PROBE will have + come from a call to this objfile's sym_get_probes method. N will +@@ -330,8 +329,7 @@ + PC will match the address of the probe. If you provide an + implementation of sym_get_probes, you must implement this method + as well. */ +- struct value *(*sym_evaluate_probe_argument) (struct objfile *objfile, +- struct probe *probe, ++ struct value *(*sym_evaluate_probe_argument) (struct probe *probe, + unsigned n); + + /* Compile the Nth probe argument to an agent expression. PROBE +@@ -339,8 +337,7 @@ + method. N will be between 0 and the number of arguments + available to this probe. EXPR and VALUE are the agent expression + that is being updated. */ +- void (*sym_compile_to_ax) (struct objfile *objfile, +- struct probe *probe, ++ void (*sym_compile_to_ax) (struct probe *probe, + struct agent_expr *expr, + struct axs_value *value, + unsigned n); diff --git a/gdb-dlopen-stap-probe-2of7.patch b/gdb-dlopen-stap-probe-2of7.patch new file mode 100644 index 0000000..81b35e9 --- /dev/null +++ b/gdb-dlopen-stap-probe-2of7.patch @@ -0,0 +1,74 @@ +http://sourceware.org/ml/gdb-cvs/2012-07/msg00124.html + +### src/gdb/ChangeLog 2012/07/18 16:12:15 1.14474 +### src/gdb/ChangeLog 2012/07/18 16:20:36 1.14475 +## -1,5 +1,10 @@ + 2012-07-18 Sergio Durigan Junior + ++ * probe.c (probe_safe_evaluate_at_pc): Rename variable `n_probes'. ++ * stap-probe.c (compile_probe_arg): Likewise. ++ ++2012-07-18 Sergio Durigan Junior ++ + * elfread.c (elf_get_probe_argument_count): Remove `objfile' argument. + (elf_compile_to_ax): Likewise. + * infrun.c (insert_exception_resume_from_probe): Likewise. +--- src/gdb/probe.c 2012/07/18 16:12:17 1.4 ++++ src/gdb/probe.c 2012/07/18 16:20:43 1.5 +@@ -637,7 +637,7 @@ + { + struct probe *probe; + const struct sym_probe_fns *probe_fns; +- unsigned n_probes; ++ unsigned n_args; + + probe = find_probe_by_pc (get_frame_pc (frame)); + if (!probe) +@@ -648,9 +648,9 @@ + gdb_assert (probe->objfile->sf->sym_probe_fns != NULL); + + probe_fns = probe->objfile->sf->sym_probe_fns; +- n_probes = probe_fns->sym_get_probe_argument_count (probe); ++ n_args = probe_fns->sym_get_probe_argument_count (probe); + +- if (n >= n_probes) ++ if (n >= n_args) + return NULL; + + return probe_fns->sym_evaluate_probe_argument (probe, n); +--- src/gdb/stap-probe.c 2012/07/18 16:12:17 1.5 ++++ src/gdb/stap-probe.c 2012/07/18 16:20:43 1.6 +@@ -1160,7 +1160,7 @@ + int sel = (int) (uintptr_t) data; + struct probe *pc_probe; + const struct sym_probe_fns *pc_probe_fns; +- int n_probes; ++ int n_args; + + /* SEL == -1 means "_probe_argc". */ + gdb_assert (sel >= -1); +@@ -1175,20 +1175,20 @@ + + pc_probe_fns = pc_probe->objfile->sf->sym_probe_fns; + +- n_probes = pc_probe_fns->sym_get_probe_argument_count (pc_probe); ++ n_args = pc_probe_fns->sym_get_probe_argument_count (pc_probe); + + if (sel == -1) + { + value->kind = axs_rvalue; + value->type = builtin_type (expr->gdbarch)->builtin_int; +- ax_const_l (expr, n_probes); ++ ax_const_l (expr, n_args); + return; + } + + gdb_assert (sel >= 0); +- if (sel >= n_probes) ++ if (sel >= n_args) + error (_("Invalid probe argument %d -- probe has %d arguments available"), +- sel, n_probes); ++ sel, n_args); + + pc_probe_fns->sym_compile_to_ax (pc_probe, expr, value, sel); + } diff --git a/gdb-dlopen-stap-probe-3of7.patch b/gdb-dlopen-stap-probe-3of7.patch new file mode 100644 index 0000000..2337ded --- /dev/null +++ b/gdb-dlopen-stap-probe-3of7.patch @@ -0,0 +1,98 @@ +2012-07-19 Gary Benson + + * probe.h (get_probe_argument_count): New declaration. + (evaluate_probe_argument): Likewise. + * probe.c (get_probe_argument_count): New function. + (evaluate_probe_argument): Likewise. + (probe_safe_evaluate_at_pc): Use the above new functions. + +diff --git a/gdb/probe.h b/gdb/probe.h +index 8d44ca2..1d29b87 100644 +--- a/gdb/probe.h ++++ b/gdb/probe.h +@@ -214,6 +214,16 @@ extern void info_probes_for_ops (char *arg, int from_tty, + + extern struct cmd_list_element **info_probes_cmdlist_get (void); + ++/* Return the argument count of the specified probe. */ ++ ++extern unsigned get_probe_argument_count (struct probe *probe); ++ ++/* Evaluate argument N of the specified probe. N must be between 0 ++ inclusive and get_probe_argument_count exclusive. */ ++ ++extern struct value *evaluate_probe_argument (struct probe *probe, ++ unsigned n); ++ + /* A convenience function that finds a probe at the PC in FRAME and + evaluates argument N, with 0 <= N < number_of_args. If there is no + probe at that location, or if the probe does not have enough arguments, +diff --git a/gdb/probe.c b/gdb/probe.c +index 77f3b13..a61f4ea 100644 +--- a/gdb/probe.c ++++ b/gdb/probe.c +@@ -632,28 +632,55 @@ info_probes_command (char *arg, int from_tty) + + /* See comments in probe.h. */ + ++unsigned ++get_probe_argument_count (struct probe *probe) ++{ ++ const struct sym_probe_fns *probe_fns; ++ ++ gdb_assert (probe->objfile != NULL); ++ gdb_assert (probe->objfile->sf != NULL); ++ ++ probe_fns = probe->objfile->sf->sym_probe_fns; ++ ++ gdb_assert (probe_fns != NULL); ++ ++ return probe_fns->sym_get_probe_argument_count (probe); ++} ++ ++/* See comments in probe.h. */ ++ ++struct value * ++evaluate_probe_argument (struct probe *probe, unsigned n) ++{ ++ const struct sym_probe_fns *probe_fns; ++ ++ gdb_assert (probe->objfile != NULL); ++ gdb_assert (probe->objfile->sf != NULL); ++ ++ probe_fns = probe->objfile->sf->sym_probe_fns; ++ ++ gdb_assert (probe_fns != NULL); ++ ++ return probe_fns->sym_evaluate_probe_argument (probe, n); ++} ++ ++/* See comments in probe.h. */ ++ + struct value * + probe_safe_evaluate_at_pc (struct frame_info *frame, unsigned n) + { + struct probe *probe; +- const struct sym_probe_fns *probe_fns; + unsigned n_args; + + probe = find_probe_by_pc (get_frame_pc (frame)); + if (!probe) + return NULL; + +- gdb_assert (probe->objfile != NULL); +- gdb_assert (probe->objfile->sf != NULL); +- gdb_assert (probe->objfile->sf->sym_probe_fns != NULL); +- +- probe_fns = probe->objfile->sf->sym_probe_fns; +- n_args = probe_fns->sym_get_probe_argument_count (probe); +- ++ n_args = get_probe_argument_count (probe); + if (n >= n_args) + return NULL; + +- return probe_fns->sym_evaluate_probe_argument (probe, n); ++ return evaluate_probe_argument (probe, n); + } + + /* See comment in probe.h. */ diff --git a/gdb-dlopen-stap-probe-4of7.patch b/gdb-dlopen-stap-probe-4of7.patch new file mode 100644 index 0000000..299931a --- /dev/null +++ b/gdb-dlopen-stap-probe-4of7.patch @@ -0,0 +1,131 @@ +2012-07-19 Gary Benson + + * solib-svr4.c (svr4_info): Move earlier. + (solib_svr4_pspace_data): Likewise. + (svr4_pspace_data_cleanup): Likewise. + (get_svr4_info): Likewise. + +diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c +index 307e483..c88b9cb 100644 +--- a/gdb/solib-svr4.c ++++ b/gdb/solib-svr4.c +@@ -106,6 +106,59 @@ static const char * const main_name_list[] = + NULL + }; + ++/* Per pspace SVR4 specific data. */ ++ ++struct svr4_info ++{ ++ CORE_ADDR debug_base; /* Base of dynamic linker structures. */ ++ ++ /* Validity flag for debug_loader_offset. */ ++ int debug_loader_offset_p; ++ ++ /* Load address for the dynamic linker, inferred. */ ++ CORE_ADDR debug_loader_offset; ++ ++ /* Name of the dynamic linker, valid if debug_loader_offset_p. */ ++ char *debug_loader_name; ++ ++ /* Load map address for the main executable. */ ++ CORE_ADDR main_lm_addr; ++ ++ CORE_ADDR interp_text_sect_low; ++ CORE_ADDR interp_text_sect_high; ++ CORE_ADDR interp_plt_sect_low; ++ CORE_ADDR interp_plt_sect_high; ++}; ++ ++/* Per-program-space data key. */ ++static const struct program_space_data *solib_svr4_pspace_data; ++ ++static void ++svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) ++{ ++ struct svr4_info *info; ++ ++ info = program_space_data (pspace, solib_svr4_pspace_data); ++ xfree (info); ++} ++ ++/* Get the current svr4 data. If none is found yet, add it now. This ++ function always returns a valid object. */ ++ ++static struct svr4_info * ++get_svr4_info (void) ++{ ++ struct svr4_info *info; ++ ++ info = program_space_data (current_program_space, solib_svr4_pspace_data); ++ if (info != NULL) ++ return info; ++ ++ info = XZALLOC (struct svr4_info); ++ set_program_space_data (current_program_space, solib_svr4_pspace_data, info); ++ return info; ++} ++ + /* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent + the same shared library. */ + +@@ -291,59 +344,6 @@ lm_addr_check (struct so_list *so, bfd *abfd) + return so->lm_info->l_addr; + } + +-/* Per pspace SVR4 specific data. */ +- +-struct svr4_info +-{ +- CORE_ADDR debug_base; /* Base of dynamic linker structures. */ +- +- /* Validity flag for debug_loader_offset. */ +- int debug_loader_offset_p; +- +- /* Load address for the dynamic linker, inferred. */ +- CORE_ADDR debug_loader_offset; +- +- /* Name of the dynamic linker, valid if debug_loader_offset_p. */ +- char *debug_loader_name; +- +- /* Load map address for the main executable. */ +- CORE_ADDR main_lm_addr; +- +- CORE_ADDR interp_text_sect_low; +- CORE_ADDR interp_text_sect_high; +- CORE_ADDR interp_plt_sect_low; +- CORE_ADDR interp_plt_sect_high; +-}; +- +-/* Per-program-space data key. */ +-static const struct program_space_data *solib_svr4_pspace_data; +- +-static void +-svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) +-{ +- struct svr4_info *info; +- +- info = program_space_data (pspace, solib_svr4_pspace_data); +- xfree (info); +-} +- +-/* Get the current svr4 data. If none is found yet, add it now. This +- function always returns a valid object. */ +- +-static struct svr4_info * +-get_svr4_info (void) +-{ +- struct svr4_info *info; +- +- info = program_space_data (current_program_space, solib_svr4_pspace_data); +- if (info != NULL) +- return info; +- +- info = XZALLOC (struct svr4_info); +- set_program_space_data (current_program_space, solib_svr4_pspace_data, info); +- return info; +-} +- + /* Local function prototypes */ + + static int match_main (const char *); diff --git a/gdb-dlopen-stap-probe-5of7.patch b/gdb-dlopen-stap-probe-5of7.patch new file mode 100644 index 0000000..cb18cd6 --- /dev/null +++ b/gdb-dlopen-stap-probe-5of7.patch @@ -0,0 +1,17 @@ +2012-07-19 Gary Benson + + * solib-svr4.c (svr4_info): Made debug_loader_offset_p a bitfield. + +diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c +index c88b9cb..8e41f19 100644 +--- a/gdb/solib-svr4.c ++++ b/gdb/solib-svr4.c +@@ -113,7 +113,7 @@ struct svr4_info + CORE_ADDR debug_base; /* Base of dynamic linker structures. */ + + /* Validity flag for debug_loader_offset. */ +- int debug_loader_offset_p; ++ unsigned int debug_loader_offset_p : 1; + + /* Load address for the dynamic linker, inferred. */ + CORE_ADDR debug_loader_offset; diff --git a/gdb-dlopen-stap-probe-6of7.patch b/gdb-dlopen-stap-probe-6of7.patch new file mode 100644 index 0000000..574150e --- /dev/null +++ b/gdb-dlopen-stap-probe-6of7.patch @@ -0,0 +1,1989 @@ +gdb/ +2012-07-30 Gary Benson + + * breakpoint.h (handle_solib_event): Moved function definition + to solib.h, and added a new parameter. + * breakpoint.c (handle_solib_event): Moved function to solib.c + and added a new parameter. + (bpstat_stop_status): Pass new argument to handle_solib_event. + * solib.h (breakpoint.h): New include. + (handle_solib_event): Moved function definition from breakpoint.h + and added a new parameter. + (update_solib_breakpoints): New function definition. + * solib.c (handle_solib_event): Moved function from breakpoint.c + and added a new parameter. + (update_solib_breakpoints): New function. + * solist.h (breakpoint.h): New include. + (target_so_ops): New fields "handle_solib_event" and + "update_breakpoints". + * infrun.c (set_stop_on_solib_events): New function. + (_initialize_infrun): Use the above for "set stop-on-solib-events". + (handle_inferior_event): Pass new argument to handle_solib_event. + * solib-svr4.c (probe.h): New include. + (namespace_table_flatten): New forward declaration. + (lm_info): New fields "lmid" and "in_initial_ns". + (probe_action): New enum. + (probe_info): New struct. + (probe_info): New static variable. + (NUM_PROBES): New definition. + (svr4_info): New fields "using_probes", "probes" and + "namespace_table". + (free_probes): New function. + (free_namespace_table): Likewise. + (svr4_pspace_data_cleanup): Free probes and namespace table. + (svr4_same): Also compare namespaces if using probes. + (lm_addr_check): Only print .dynamic section at wrong address + warning for initial namespace if using probes. + (r_map_from_debug_base): New function. + (solib_svr4_r_map): Call the above. + (svr4_read_so_list): New parameter "prev_lm". + Changed return type from void to int. + Return nonzero on success, zero on error. + (svr4_current_sos_from_debug_base): New function. + (svr4_current_sos): Create result from namespace table if available. + Use svr4_current_sos_from_debug_base to generate list otherwise. + (probe_and_info): New struct. + (solib_event_probe_at): New function. + (solib_event_probe_action): Likewise. + (namespace): New struct. + (hash_namespace): New function. + (equal_namespace): Likewise. + (free_namespace): Likewise. + (namespace_update_full): Likewise. + (namespace_update_incremental): Likewise. + (svr4_handle_solib_event): Likewise. + (namespace_table_flatten_helper): Likewise. + (namespace_table_flatten): Likewise. + (svr4_update_solib_event_breakpoint): Likewise. + (svr4_update_solib_event_breakpoints): Likewise. + (svr4_create_solib_event_breakpoints): Likewise. + (enable_break): Free probes before creating breakpoints. + Use svr4_create_solib_event_breakpoints to create breakpoints. + (svr4_solib_create_inferior_hook): Free the namespace table. + (_initialize_svr4_solib): Initialise svr4_so_ops.handle_solib_event + and svr4_so_ops.update_breakpoints. + +gdb/testsuite +2012-07-30 Gary Benson + + * gdb.base/break-interp.exp (solib_bp): New constant. + (reach_1): Use the above instead of "_dl_debug_state". + (test_attach): Likewise. + (test_ld): Likewise. + * gdb.base/break-probes.exp: New file. + * gdb.base/break-probes.c: Likewise. + * gdb.base/break-probes-solib.c: Likewise. + * gdb.base/info-shared.exp: New file. + * gdb.base/info-shared.c: Likewise. + * gdb.base/info-shared-solib1.c: Likewise. + * gdb.base/info-shared-solib2.c: Likewise. + * gdb.base/break-dlmopen.exp: Likewise. + * gdb.base/break-dlmopen.c: Likewise. + * gdb.base/break-dlmopen-solib.c: Likewise. + +Index: gdb-7.4.91.20120814/gdb/breakpoint.h +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/breakpoint.h 2012-08-14 17:31:37.050984427 +0200 ++++ gdb-7.4.91.20120814/gdb/breakpoint.h 2012-08-14 17:34:44.203746601 +0200 +@@ -1515,8 +1515,6 @@ extern int user_breakpoint_p (struct bre + /* Attempt to determine architecture of location identified by SAL. */ + extern struct gdbarch *get_sal_arch (struct symtab_and_line sal); + +-extern void handle_solib_event (void); +- + extern void breakpoints_relocate (struct objfile *objfile, + struct section_offsets *delta); + +Index: gdb-7.4.91.20120814/gdb/breakpoint.c +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/breakpoint.c 2012-08-14 17:31:37.128984404 +0200 ++++ gdb-7.4.91.20120814/gdb/breakpoint.c 2012-08-14 17:34:44.211746597 +0200 +@@ -5205,7 +5205,7 @@ bpstat_stop_status (struct address_space + { + if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event) + { +- handle_solib_event (); ++ handle_solib_event (bs); + break; + } + } +@@ -5301,25 +5301,6 @@ handle_jit_event (void) + target_terminal_inferior (); + } + +-/* Handle an solib event by calling solib_add. */ +- +-void +-handle_solib_event (void) +-{ +- clear_program_space_solib_cache (current_inferior ()->pspace); +- +- /* Check for any newly added shared libraries if we're supposed to +- be adding them automatically. Switch terminal for any messages +- produced by breakpoint_re_set. */ +- target_terminal_ours_for_output (); +-#ifdef SOLIB_ADD +- SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add); +-#else +- solib_add (NULL, 0, ¤t_target, auto_solib_add); +-#endif +- target_terminal_inferior (); +-} +- + /* Prepare WHAT final decision for infrun. */ + + /* Decide what infrun needs to do with this bpstat. */ +Index: gdb-7.4.91.20120814/gdb/solib.h +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/solib.h 2012-02-03 16:19:37.000000000 +0100 ++++ gdb-7.4.91.20120814/gdb/solib.h 2012-08-14 17:34:44.257746587 +0200 +@@ -21,6 +21,9 @@ + #ifndef SOLIB_H + #define SOLIB_H + ++/* For bpstat. */ ++#include "breakpoint.h" ++ + /* Forward decl's for prototypes */ + struct so_list; + struct target_ops; +@@ -91,4 +94,15 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f + void *), + void *data); + ++/* Handle an solib event by calling solib_add. Targets which handle ++ solib events using breakpoints must pass a valid bpstat. Targets ++ which handle solib events using some other mechanism should pass ++ NULL. */ ++ ++extern void handle_solib_event (bpstat bs); ++ ++/* Enable or disable optional solib event breakpoints as appropriate. */ ++ ++extern void update_solib_breakpoints (void); ++ + #endif /* SOLIB_H */ +Index: gdb-7.4.91.20120814/gdb/solib.c +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/solib.c 2012-08-14 17:31:36.832984492 +0200 ++++ gdb-7.4.91.20120814/gdb/solib.c 2012-08-14 17:34:44.272746583 +0200 +@@ -1226,6 +1226,42 @@ no_shared_libraries (char *ignored, int + objfile_purge_solibs (); + } + ++/* See solib.h. */ ++ ++void ++handle_solib_event (bpstat bs) ++{ ++ struct target_so_ops *ops = solib_ops (target_gdbarch); ++ ++ if (ops->handle_solib_event != NULL) ++ ops->handle_solib_event (bs); ++ ++ clear_program_space_solib_cache (current_inferior ()->pspace); ++ ++ /* Check for any newly added shared libraries if we're supposed to ++ be adding them automatically. Switch terminal for any messages ++ produced by breakpoint_re_set. */ ++ target_terminal_ours_for_output (); ++#ifdef SOLIB_ADD ++ SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add); ++#else ++ solib_add (NULL, 0, ¤t_target, auto_solib_add); ++#endif ++ target_terminal_inferior (); ++} ++ ++/* See solib.h. */ ++ ++void ++update_solib_breakpoints (void) ++{ ++ struct target_so_ops *ops = solib_ops (target_gdbarch); ++ ++ if (ops->update_breakpoints != NULL) ++ ops->update_breakpoints (); ++} ++ ++ + /* Reload shared libraries, but avoid reloading the same symbol file + we already have loaded. */ + +Index: gdb-7.4.91.20120814/gdb/solist.h +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/solist.h 2012-01-04 09:17:11.000000000 +0100 ++++ gdb-7.4.91.20120814/gdb/solist.h 2012-08-14 17:34:44.273746584 +0200 +@@ -23,6 +23,8 @@ + #define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */ + /* For domain_enum domain. */ + #include "symtab.h" ++/* For bpstat. */ ++#include "breakpoint.h" + + /* Forward declaration for target specific link map information. This + struct is opaque to all but the target specific file. */ +@@ -149,6 +151,20 @@ struct target_so_ops + core file (in particular, for readonly sections). */ + int (*keep_data_in_core) (CORE_ADDR vaddr, + unsigned long size); ++ ++ /* Target-specific handling of solib events. For targets which ++ handle solib events using breakpoints a valid bpstat must be ++ passed. Targets which handle solib events using some other ++ mechanism should pass NULL. This pointer can be NULL, in which ++ case no specific handling is necessary for this target. */ ++ void (*handle_solib_event) (bpstat bs); ++ ++ /* Enable or disable optional solib event breakpoints as ++ appropriate. This should be called whenever ++ stop_on_solib_events is changed. This pointer can be ++ NULL, in which case no enabling or disabling is necessary ++ for this target. */ ++ void (*update_breakpoints) (void); + }; + + /* Free the memory associated with a (so_list *). */ +Index: gdb-7.4.91.20120814/gdb/infrun.c +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/infrun.c 2012-08-14 17:33:16.249955007 +0200 ++++ gdb-7.4.91.20120814/gdb/infrun.c 2012-08-14 17:34:44.276746583 +0200 +@@ -361,6 +361,16 @@ static struct symbol *step_start_functio + /* Nonzero if we want to give control to the user when we're notified + of shared library events by the dynamic linker. */ + int stop_on_solib_events; ++ ++/* Enable or disable optional shared library event breakpoints ++ as appropriate when the above flag is changed. */ ++ ++static void ++set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c) ++{ ++ update_solib_breakpoints (); ++} ++ + static void + show_stop_on_solib_events (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +@@ -3321,7 +3331,7 @@ handle_inferior_event (struct execution_ + context_switch (ecs->ptid); + regcache = get_thread_regcache (ecs->ptid); + +- handle_solib_event (); ++ handle_solib_event (NULL); + + ecs->event_thread->control.stop_bpstat + = bpstat_stop_status (get_regcache_aspace (regcache), +@@ -7226,7 +7236,7 @@ Show stopping for shared library events. + If nonzero, gdb will give control to the user when the dynamic linker\n\ + notifies gdb of shared library events. The most common event of interest\n\ + to the user would be loading/unloading of a new library."), +- NULL, ++ set_stop_on_solib_events, + show_stop_on_solib_events, + &setlist, &showlist); + +Index: gdb-7.4.91.20120814/gdb/solib-svr4.c +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/solib-svr4.c 2012-08-14 17:34:39.346752840 +0200 ++++ gdb-7.4.91.20120814/gdb/solib-svr4.c 2012-08-14 17:35:42.635732596 +0200 +@@ -47,10 +47,12 @@ + #include "auxv.h" + #include "exceptions.h" + #include "gdb_bfd.h" ++#include "probe.h" + + static struct link_map_offsets *svr4_fetch_link_map_offsets (void); + static int svr4_have_link_map_offsets (void); + static void svr4_relocate_main_executable (void); ++static struct so_list *namespace_table_flatten (htab_t namespace_table); + + /* Link map info to include in an allocated so_list entry. */ + +@@ -71,6 +73,16 @@ struct lm_info + + /* Values read in from inferior's fields of the same name. */ + CORE_ADDR l_ld, l_next, l_prev, l_name; ++ ++ /* Numeric link-map ID of the namespace this object is loaded ++ into. This value is only valid when using the probes-based ++ interface. */ ++ LONGEST lmid; ++ ++ /* Nonzero if the namespace list this object is loaded into is the ++ application's initial namespace (LM_ID_BASE). This value is ++ only valid when using the probes-based interface. */ ++ unsigned int in_initial_ns : 1; + }; + + /* On SVR4 systems, a list of symbols in the dynamic linker where +@@ -107,6 +119,53 @@ static const char * const main_name_lis + NULL + }; + ++/* What to do with the namespace table when a probe stop occurs. */ ++ ++enum probe_action ++ { ++ /* Something went seriously wrong. Stop using probes and ++ revert to using the older interface. */ ++ NAMESPACE_TABLE_INVALIDATE, ++ ++ /* No action is required. This namespace is still valid. */ ++ NAMESPACE_NO_ACTION, ++ ++ /* This namespace should be reloaded entirely. */ ++ NAMESPACE_RELOAD, ++ ++ /* Attempt to incrementally update this namespace. If the ++ update fails or is not possible, fall back to reloading ++ the namespace in full. */ ++ NAMESPACE_UPDATE_OR_RELOAD, ++ }; ++ ++/* A probe's name and its associated action. */ ++ ++struct probe_info ++{ ++ /* The name of the probe. */ ++ const char *name; ++ ++ /* What to do with the namespace table when a probe stop occurs. */ ++ enum probe_action action; ++}; ++ ++/* A list of named probes and their associated actions. If all ++ probes are present in the dynamic linker then the probes-based ++ interface will be used. */ ++ ++static const struct probe_info probe_info[] = ++{ ++ { "init_start", NAMESPACE_NO_ACTION }, ++ { "init_complete", NAMESPACE_RELOAD }, ++ { "map_start", NAMESPACE_NO_ACTION }, ++ { "reloc_complete", NAMESPACE_UPDATE_OR_RELOAD }, ++ { "unmap_start", NAMESPACE_NO_ACTION }, ++ { "unmap_complete", NAMESPACE_RELOAD }, ++}; ++ ++#define NUM_PROBES ARRAY_SIZE (probe_info) ++ + /* Per pspace SVR4 specific data. */ + + struct svr4_info +@@ -129,17 +188,58 @@ struct svr4_info + CORE_ADDR interp_text_sect_high; + CORE_ADDR interp_plt_sect_low; + CORE_ADDR interp_plt_sect_high; ++ ++ /* Nonzero if we are using the probes-based interface. */ ++ unsigned int using_probes : 1; ++ ++ /* Named probes in the dynamic linker. */ ++ VEC (probe_p) *probes[NUM_PROBES]; ++ ++ /* Table of dynamic linker namespaces, used by the probes-based ++ interface. */ ++ htab_t namespace_table; + }; + + /* Per-program-space data key. */ + static const struct program_space_data *solib_svr4_pspace_data; + ++/* Free any allocated probe vectors. */ ++ ++static void ++free_probes (struct svr4_info *info) ++{ ++ int i; ++ ++ for (i = 0; i < NUM_PROBES; i++) ++ VEC_free (probe_p, info->probes[i]); ++ ++ memset (info->probes, 0, sizeof (info->probes)); ++} ++ ++/* Free the namespace table. */ ++ ++static void ++free_namespace_table (struct svr4_info *info) ++{ ++ if (info->namespace_table == NULL) ++ return; ++ ++ htab_delete (info->namespace_table); ++ info->namespace_table = NULL; ++} ++ + static void + svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) + { + struct svr4_info *info; + + info = program_space_data (pspace, solib_svr4_pspace_data); ++ if (info == NULL) ++ return; ++ ++ free_probes (info); ++ free_namespace_table (info); ++ + xfree (info); + } + +@@ -188,10 +288,21 @@ svr4_same_1 (const char *gdb_so_name, co + return 0; + } + ++/* Return non-zero if GDB and INFERIOR represent the same shared ++ library. */ ++ + static int + svr4_same (struct so_list *gdb, struct so_list *inferior) + { +- return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name)); ++ struct svr4_info *info = get_svr4_info (); ++ ++ if (info->using_probes) ++ { ++ if (gdb->lm_info->lmid != inferior->lm_info->lmid) ++ return 0; ++ } ++ ++ return svr4_same_1 (gdb->so_original_name, inferior->so_original_name); + } + + static struct lm_info * +@@ -322,18 +433,26 @@ lm_addr_check (struct so_list *so, bfd * + } + else + { +- /* There is no way to verify the library file matches. prelink +- can during prelinking of an unprelinked file (or unprelinking +- of a prelinked file) shift the DYNAMIC segment by arbitrary +- offset without any page size alignment. There is no way to +- find out the ELF header and/or Program Headers for a limited +- verification if it they match. One could do a verification +- of the DYNAMIC segment. Still the found address is the best +- one GDB could find. */ +- +- warning (_(".dynamic section for \"%s\" " +- "is not at the expected address " +- "(wrong library or version mismatch?)"), so->so_name); ++ struct svr4_info *info = get_svr4_info (); ++ ++ if (!info->using_probes || so->lm_info->in_initial_ns) ++ { ++ /* There is no way to verify the library file ++ matches. prelink can during prelinking of an ++ unprelinked file (or unprelinking of a prelinked ++ file) shift the DYNAMIC segment by arbitrary ++ offset without any page size alignment. There is ++ no way to find out the ELF header and/or Program ++ Headers for a limited verification if it they ++ match. One could do a verification of the ++ DYNAMIC segment. Still the found address is the ++ best one GDB could find. */ ++ ++ warning (_(".dynamic section for \"%s\" " ++ "is not at the expected address " ++ "(wrong library or version mismatch?)"), ++ so->so_name); ++ } + } + } + +@@ -775,16 +894,10 @@ locate_base (struct svr4_info *info) + return info->debug_base; + } + +-/* Find the first element in the inferior's dynamic link map, and +- return its address in the inferior. Return zero if the address +- could not be determined. +- +- FIXME: Perhaps we should validate the info somehow, perhaps by +- checking r_version for a known version number, or r_state for +- RT_CONSISTENT. */ ++/* Read the r_map field from the supplied r_debug structure. */ + + static CORE_ADDR +-solib_svr4_r_map (struct svr4_info *info) ++r_map_from_debug_base (CORE_ADDR debug_base) + { + struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; +@@ -793,13 +906,27 @@ solib_svr4_r_map (struct svr4_info *info + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { +- addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset, ++ addr = read_memory_typed_address (debug_base + lmo->r_map_offset, + ptr_type); + } + exception_print (gdb_stderr, ex); + return addr; + } + ++/* Find the first element in the inferior's dynamic link map, and ++ return its address in the inferior. Return zero if the address ++ could not be determined. ++ ++ FIXME: Perhaps we should validate the info somehow, perhaps by ++ checking r_version for a known version number, or r_state for ++ RT_CONSISTENT. */ ++ ++static CORE_ADDR ++solib_svr4_r_map (struct svr4_info *info) ++{ ++ return r_map_from_debug_base (info->debug_base); ++} ++ + /* Find r_brk from the inferior's debug base. */ + + static CORE_ADDR +@@ -1164,15 +1291,17 @@ svr4_default_sos (void) + return new; + } + +-/* Read the whole inferior libraries chain starting at address LM. Add the +- entries to the tail referenced by LINK_PTR_PTR. Ignore the first entry if +- IGNORE_FIRST and set global MAIN_LM_ADDR according to it. */ ++/* Read the whole inferior libraries chain starting at address LM. ++ Expect the first entry in the chain's previous entry to be PREV_LM. ++ Add the entries to the tail referenced by LINK_PTR_PTR. Ignore the ++ first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according ++ to it. Returns nonzero upon success. */ + +-static void +-svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, +- int ignore_first) ++static int ++svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm, ++ struct so_list ***link_ptr_ptr, int ignore_first) + { +- CORE_ADDR prev_lm = 0, next_lm; ++ CORE_ADDR next_lm; + + for (; lm != 0; prev_lm = lm, lm = next_lm) + { +@@ -1189,7 +1318,7 @@ svr4_read_so_list (CORE_ADDR lm, struct + if (new->lm_info == NULL) + { + do_cleanups (old_chain); +- break; ++ return 0; + } + + next_lm = new->lm_info->l_next; +@@ -1200,7 +1329,7 @@ svr4_read_so_list (CORE_ADDR lm, struct + paddress (target_gdbarch, prev_lm), + paddress (target_gdbarch, new->lm_info->l_prev)); + do_cleanups (old_chain); +- break; ++ return 0; + } + + /* For SVR4 versions, the first entry in the link map is for the +@@ -1295,20 +1424,61 @@ svr4_read_so_list (CORE_ADDR lm, struct + **link_ptr_ptr = new; + *link_ptr_ptr = &new->next; + } ++ ++ return 1; + } + +-/* Implement the "current_sos" target_so_ops method. */ ++/* Read the list of loaded libraries from the dynamic linker's base ++ structure. */ + + static struct so_list * +-svr4_current_sos (void) ++svr4_current_sos_from_debug_base (void) + { ++ struct svr4_info *info = get_svr4_info (); + CORE_ADDR lm; + struct so_list *head = NULL; + struct so_list **link_ptr = &head; +- struct svr4_info *info; + struct cleanup *back_to; + int ignore_first; ++ ++ gdb_assert (info->debug_base); ++ ++ /* Assume that everything is a library if the dynamic loader was loaded ++ late by a static executable. */ ++ if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) ++ ignore_first = 0; ++ else ++ ignore_first = 1; ++ ++ back_to = make_cleanup (svr4_free_library_list, &head); ++ ++ /* Walk the inferior's link map list, and build our list of ++ `struct so_list' nodes. */ ++ lm = solib_svr4_r_map (info); ++ if (lm) ++ svr4_read_so_list (lm, 0, &link_ptr, ignore_first); ++ ++ /* On Solaris, the dynamic linker is not in the normal list of ++ shared objects, so make sure we pick it up too. Having ++ symbol information for the dynamic linker is quite crucial ++ for skipping dynamic linker resolver code. */ ++ lm = solib_svr4_r_ldsomap (info); ++ if (lm) ++ svr4_read_so_list (lm, 0, &link_ptr, 0); ++ ++ discard_cleanups (back_to); ++ ++ return head; ++} ++ ++/* Implement the "current_sos" target_so_ops method. */ ++ ++static struct so_list * ++svr4_current_sos (void) ++{ ++ struct svr4_info *info; + struct svr4_library_list library_list; ++ struct so_list *result; + + /* Fall back to manual examination of the target if the packet is not + supported or gdbserver failed to find DT_DEBUG. gdb.server/solib-list.exp +@@ -1331,6 +1501,10 @@ svr4_current_sos (void) + + info = get_svr4_info (); + ++ /* If we have a namespace table then return a flattened copy. */ ++ if (info->namespace_table != NULL) ++ return namespace_table_flatten (info->namespace_table); ++ + /* Always locate the debug struct, in case it has moved. */ + info->debug_base = 0; + locate_base (info); +@@ -1340,35 +1514,12 @@ svr4_current_sos (void) + if (! info->debug_base) + return svr4_default_sos (); + +- /* Assume that everything is a library if the dynamic loader was loaded +- late by a static executable. */ +- if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) +- ignore_first = 0; +- else +- ignore_first = 1; +- +- back_to = make_cleanup (svr4_free_library_list, &head); +- +- /* Walk the inferior's link map list, and build our list of +- `struct so_list' nodes. */ +- lm = solib_svr4_r_map (info); +- if (lm) +- svr4_read_so_list (lm, &link_ptr, ignore_first); +- +- /* On Solaris, the dynamic linker is not in the normal list of +- shared objects, so make sure we pick it up too. Having +- symbol information for the dynamic linker is quite crucial +- for skipping dynamic linker resolver code. */ +- lm = solib_svr4_r_ldsomap (info); +- if (lm) +- svr4_read_so_list (lm, &link_ptr, 0); +- +- discard_cleanups (back_to); ++ result = svr4_current_sos_from_debug_base (); + +- if (head == NULL) ++ if (result == NULL) + return svr4_default_sos (); + +- return head; ++ return result; + } + + /* Get the address of the link_map for a given OBJFILE. */ +@@ -1450,6 +1601,498 @@ exec_entry_point (struct bfd *abfd, stru + targ); + } + ++/* A probe and its associated information structure. */ ++ ++struct probe_and_info ++{ ++ /* The probe. */ ++ struct probe *probe; ++ ++ /* The probe_info from which the probe was created. */ ++ const struct probe_info *info; ++}; ++ ++/* Get the solib event probe at the specified location, and the ++ probe_info the probe was created with. Fills in RESULT and ++ returns nonzero if a solib event probe was found at the ++ specified location. Returns zero if no solib event probe ++ was found. */ ++ ++static int ++solib_event_probe_at (struct svr4_info *info, struct bp_location *loc, ++ struct probe_and_info *result) ++{ ++ int i; ++ ++ for (i = 0; i < NUM_PROBES; i++) ++ { ++ struct probe *probe; ++ int ix; ++ ++ for (ix = 0; VEC_iterate (probe_p, info->probes[i], ix, probe); ++ix) ++ { ++ if (loc->pspace == current_program_space ++ && loc->address == probe->address) ++ { ++ result->info = &probe_info[i]; ++ result->probe = probe; ++ ++ return 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++/* Decide what action to take when the specified solib event probe is ++ hit. */ ++ ++static enum probe_action ++solib_event_probe_action (struct probe_and_info *pi) ++{ ++ enum probe_action action; ++ unsigned probe_argc; ++ ++ action = pi->info->action; ++ if (action == NAMESPACE_NO_ACTION || action == NAMESPACE_TABLE_INVALIDATE) ++ return action; ++ ++ gdb_assert (action == NAMESPACE_RELOAD ++ || action == NAMESPACE_UPDATE_OR_RELOAD); ++ ++ /* Check that an appropriate number of arguments has been supplied. ++ We expect: ++ arg0: Lmid_t lmid (mandatory) ++ arg1: struct r_debug *debug_base (mandatory) ++ arg2: struct link_map *new (optional, for incremental updates) */ ++ probe_argc = get_probe_argument_count (pi->probe); ++ if (probe_argc == 2) ++ action = NAMESPACE_RELOAD; ++ else if (probe_argc < 2) ++ action = NAMESPACE_TABLE_INVALIDATE; ++ ++ return action; ++} ++ ++/* A namespace in the dynamic linker. */ ++ ++struct namespace ++{ ++ /* Numeric link-map ID of the namespace. */ ++ LONGEST lmid; ++ ++ /* List of objects loaded into the namespace. */ ++ struct so_list *solist; ++}; ++ ++/* Returns a hash code for the namespace referenced by p. */ ++ ++static hashval_t ++hash_namespace (const void *p) ++{ ++ const struct namespace *ns = p; ++ ++ return (hashval_t) ns->lmid; ++} ++ ++/* Returns non-zero if the namespaces referenced by p1 and p2 ++ are equal. */ ++ ++static int ++equal_namespace (const void *p1, const void *p2) ++{ ++ const struct namespace *ns1 = p1; ++ const struct namespace *ns2 = p2; ++ ++ return ns1->lmid == ns2->lmid; ++} ++ ++/* Free a namespace. */ ++ ++static void ++free_namespace (void *p) ++{ ++ struct namespace *ns = p; ++ ++ svr4_free_library_list (ns->solist); ++ xfree (ns); ++} ++ ++/* Populate this namespace by reading the entire list of shared ++ objects from the inferior. Returns nonzero on success. */ ++ ++static int ++namespace_update_full (struct svr4_info *info, LONGEST lmid, ++ CORE_ADDR debug_base, int is_initial_ns) ++{ ++ struct so_list *result = NULL, *so; ++ struct namespace lookup, *ns; ++ void **slot; ++ ++ /* Read the list of shared objects from the inferior. The ++ initial namespace requires extra processing and is handled ++ separately. */ ++ if (is_initial_ns) ++ { ++ result = svr4_current_sos_from_debug_base (); ++ } ++ else ++ { ++ CORE_ADDR lm = r_map_from_debug_base (debug_base); ++ struct so_list **link_ptr = &result; ++ ++ if (!svr4_read_so_list (lm, 0, &link_ptr, 0)) ++ return 0; ++ } ++ ++ /* If the namespace is empty then delete it from the table. */ ++ if (result == NULL) ++ { ++ if (info->namespace_table != NULL) ++ { ++ lookup.lmid = lmid; ++ htab_remove_elt (info->namespace_table, &lookup); ++ } ++ ++ return 1; ++ } ++ ++ /* Fill in the link-map IDs and initial namespace flags. */ ++ for (so = result; so; so = so->next) ++ { ++ so->lm_info->lmid = lmid; ++ so->lm_info->in_initial_ns = is_initial_ns; ++ } ++ ++ /* Create the namespace table, if necessary. */ ++ if (info->namespace_table == NULL) ++ { ++ info->namespace_table = htab_create_alloc (1, hash_namespace, ++ equal_namespace, ++ free_namespace, ++ xcalloc, xfree); ++ } ++ ++ /* Update the namespace table with our new list. */ ++ lookup.lmid = lmid; ++ slot = htab_find_slot (info->namespace_table, &lookup, INSERT); ++ if (*slot == HTAB_EMPTY_ENTRY) ++ { ++ ns = XCNEW (struct namespace); ++ ns->lmid = lmid; ++ *slot = ns; ++ } ++ else ++ { ++ ns = *slot; ++ svr4_free_library_list (ns->solist); ++ } ++ ns->solist = result; ++ ++ return 1; ++} ++ ++/* Update this namespace starting from the link-map entry passed by ++ the linker in the probe's third argument. Returns nonzero if the ++ list was successfully updated, or zero to indicate failure. */ ++ ++static int ++namespace_update_incremental (struct svr4_info *info, LONGEST lmid, ++ CORE_ADDR lm, int is_initial_ns) ++{ ++ struct namespace lookup, *ns; ++ struct so_list *tail, **link, *so; ++ struct value *val; ++ ++ /* Find our namespace in the table. */ ++ if (info->namespace_table == NULL) ++ return 0; ++ ++ lookup.lmid = lmid; ++ ns = htab_find (info->namespace_table, &lookup); ++ if (ns == NULL) ++ return 0; ++ ++ /* Walk to the end of the list. */ ++ tail = ns->solist; ++ if (tail == NULL) ++ return 0; ++ ++ while (tail->next) ++ tail = tail->next; ++ link = &tail->next; ++ ++ /* Read the new objects. */ ++ if (!svr4_read_so_list (lm, tail->lm_info->lm_addr, &link, 0)) ++ return 0; ++ ++ /* Fill in the link-map IDs and initial namespace flags. */ ++ for (so = tail; so; so = so->next) ++ { ++ so->lm_info->lmid = lmid; ++ so->lm_info->in_initial_ns = is_initial_ns; ++ } ++ ++ return 1; ++} ++ ++/* Update the namespace table as appropriate when using the ++ probes-based linker interface. Do nothing if using the ++ standard interface. */ ++ ++static void ++svr4_handle_solib_event (bpstat bs) ++{ ++ struct svr4_info *info = get_svr4_info (); ++ struct probe_and_info buf, *pi = &buf; ++ enum probe_action action; ++ struct value *val; ++ LONGEST lmid; ++ CORE_ADDR debug_base, lm = 0; ++ int is_initial_ns; ++ ++ /* It is possible that this function will be called incorrectly ++ by the handle_solib_event in handle_inferior_event if GDB goes ++ fully multi-target. */ ++ gdb_assert (bs != NULL); ++ ++ if (!info->using_probes) ++ return; ++ ++ if (!solib_event_probe_at (info, bs->bp_location_at, pi)) ++ goto error; ++ ++ action = solib_event_probe_action (pi); ++ if (action == NAMESPACE_TABLE_INVALIDATE) ++ goto error; ++ ++ if (action == NAMESPACE_NO_ACTION) ++ return; ++ ++ val = evaluate_probe_argument (pi->probe, 0); ++ if (val == NULL) ++ goto error; ++ ++ lmid = value_as_long (val); ++ ++ val = evaluate_probe_argument (pi->probe, 1); ++ if (val == NULL) ++ goto error; ++ ++ debug_base = value_as_address (val); ++ if (debug_base == 0) ++ goto error; ++ ++ /* Always locate the debug struct, in case it moved. */ ++ info->debug_base = 0; ++ if (locate_base (info) == 0) ++ goto error; ++ ++ is_initial_ns = (debug_base == info->debug_base); ++ ++ if (action == NAMESPACE_UPDATE_OR_RELOAD) ++ { ++ val = evaluate_probe_argument (pi->probe, 2); ++ if (val != NULL) ++ lm = value_as_address (val); ++ ++ if (lm == 0) ++ action = NAMESPACE_RELOAD; ++ } ++ ++ if (action == NAMESPACE_UPDATE_OR_RELOAD) ++ { ++ if (namespace_update_incremental (info, lmid, lm, is_initial_ns)) ++ return; ++ ++ action = NAMESPACE_RELOAD; ++ } ++ ++ gdb_assert (action == NAMESPACE_RELOAD); ++ ++ if (namespace_update_full (info, lmid, debug_base, is_initial_ns)) ++ return; ++ ++ error: ++ ++ /* We should never reach here, but if we do we disable the ++ probes interface and revert to the original interface. ++ We don't reset the breakpoints as the ones we've set up ++ are adequate. */ ++ warning (_("Probes-based dynamic linker interface failed.\n" ++ "Reverting to original interface.\n")); ++ ++ free_namespace_table (info); ++ free_probes (info); ++ info->using_probes = 0; ++} ++ ++/* Helper function for namespace_table_flatten. */ ++ ++static int ++namespace_table_flatten_helper (void **slot, void *arg) ++{ ++ struct namespace *ns = (struct namespace *) *slot; ++ struct so_list *src = ns->solist; ++ struct so_list **link = (struct so_list **) arg; ++ ++ while (*link) ++ link = &(*link)->next; ++ ++ while (src != NULL) ++ { ++ struct so_list *dst; ++ ++ dst = xmalloc (sizeof (struct so_list)); ++ memcpy (dst, src, sizeof (struct so_list)); ++ ++ dst->lm_info = xmalloc (sizeof (struct lm_info)); ++ memcpy (dst->lm_info, src->lm_info, sizeof (struct lm_info)); ++ ++ *link = dst; ++ link = &dst->next; ++ ++ src = src->next; ++ } ++ ++ *link = NULL; ++ ++ return 1; /* Continue traversal. */ ++} ++ ++/* Flatten the namespace table into a single list. */ ++ ++static struct so_list * ++namespace_table_flatten (htab_t namespace_table) ++{ ++ struct so_list *dst = NULL; ++ ++ htab_traverse (namespace_table, namespace_table_flatten_helper, &dst); ++ ++ return dst; ++} ++ ++/* Helper function for svr4_update_solib_event_breakpoints. */ ++ ++static int ++svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg) ++{ ++ struct svr4_info *info = get_svr4_info (); ++ struct bp_location *loc; ++ ++ if (b->type != bp_shlib_event) ++ return 0; /* Continue iterating. */ ++ ++ for (loc = b->loc; loc; loc = loc->next) ++ { ++ struct probe_and_info buf, *pi = &buf; ++ ++ if (solib_event_probe_at (info, loc, pi)) ++ { ++ if (pi->info->action == NAMESPACE_NO_ACTION) ++ b->enable_state = (stop_on_solib_events ++ ? bp_enabled : bp_disabled); ++ ++ return 0; /* Continue iterating. */ ++ } ++ } ++ ++ return 0; /* Continue iterating. */ ++} ++ ++/* Enable or disable optional solib event breakpoints as appropriate. ++ Called whenever stop_on_solib_events is changed. */ ++ ++static void ++svr4_update_solib_event_breakpoints (void) ++{ ++ struct svr4_info *info = get_svr4_info (); ++ ++ if (info->using_probes) ++ iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL); ++} ++ ++/* Both the SunOS and the SVR4 dynamic linkers call a marker function ++ before and after mapping and unmapping shared libraries. The sole ++ purpose of this method is to allow debuggers to set a breakpoint so ++ they can track these changes. ++ ++ Some versions of the glibc dynamic linker contain named probes ++ to allow more fine grained stopping. Given the address of the ++ original marker function, this function attempts to find these ++ probes, and if found, sets breakpoints on those instead. If the ++ probes aren't found, a single breakpoint is set on the original ++ marker function. */ ++ ++static void ++svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch, ++ CORE_ADDR address) ++{ ++ struct svr4_info *info = get_svr4_info (); ++ struct obj_section *os; ++ ++ os = find_pc_section (address); ++ if (os != NULL) ++ { ++ int with_prefix; ++ ++ for (with_prefix = 0; with_prefix <= 1; with_prefix++) ++ { ++ int all_probes_found = 1; ++ int i; ++ ++ for (i = 0; i < NUM_PROBES; i++) ++ { ++ char name[32] = { '\0' }; ++ ++ /* Fedora 17, RHEL 6.2, and RHEL 6.3 shipped with an ++ early version of the probes code in which the probes' ++ names were prefixed with "rtld_". The locations and ++ arguments of the probes are otherwise the same, so we ++ check for the prefixed version if the unprefixed ++ probes are not found. */ ++ ++ if (with_prefix) ++ strncat (name, "rtld_", sizeof (name)); ++ ++ strncat (name, probe_info[i].name, sizeof (name) - sizeof ("rtld_")); ++ ++ info->probes[i] = find_probes_in_objfile (os->objfile, "rtld", ++ name); ++ ++ if (!VEC_length (probe_p, info->probes[i])) ++ { ++ free_probes (info); ++ all_probes_found = 0; ++ break; ++ } ++ } ++ ++ if (all_probes_found) ++ { ++ info->using_probes = 1; ++ ++ for (i = 0; i < NUM_PROBES; i++) ++ { ++ struct probe *probe; ++ int ix; ++ ++ for (ix = 0; ++ VEC_iterate (probe_p, info->probes[i], ix, probe); ++ ++ix) ++ create_solib_event_breakpoint (gdbarch, probe->address); ++ } ++ ++ svr4_update_solib_event_breakpoints (); ++ return; ++ } ++ } ++ } ++ ++ create_solib_event_breakpoint (gdbarch, address); ++} ++ + /* Helper function for gdb_bfd_lookup_symbol. */ + + static int +@@ -1502,6 +2145,9 @@ enable_break (struct svr4_info *info, in + info->interp_text_sect_low = info->interp_text_sect_high = 0; + info->interp_plt_sect_low = info->interp_plt_sect_high = 0; + ++ free_probes (info); ++ info->using_probes = 0; ++ + /* If we already have a shared library list in the target, and + r_debug contains r_brk, set the breakpoint there - this should + mean r_brk has already been relocated. Assume the dynamic linker +@@ -1533,7 +2179,7 @@ enable_break (struct svr4_info *info, in + That knowledge is encoded in the address, if it's Thumb the low bit + is 1. However, we've stripped that info above and it's not clear + what all the consequences are of passing a non-addr_bits_remove'd +- address to create_solib_event_breakpoint. The call to ++ address to svr4_create_solib_event_breakpoints. The call to + find_pc_section verifies we know about the address and have some + hope of computing the right kind of breakpoint to use (via + symbol info). It does mean that GDB needs to be pointed at a +@@ -1571,7 +2217,7 @@ enable_break (struct svr4_info *info, in + + bfd_section_size (tmp_bfd, interp_sect); + } + +- create_solib_event_breakpoint (target_gdbarch, sym_addr); ++ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); + return 1; + } + } +@@ -1729,7 +2375,8 @@ enable_break (struct svr4_info *info, in + + if (sym_addr != 0) + { +- create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr); ++ svr4_create_solib_event_breakpoints (target_gdbarch, ++ load_addr + sym_addr); + xfree (interp_name); + return 1; + } +@@ -1755,7 +2402,7 @@ enable_break (struct svr4_info *info, in + sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, + sym_addr, + ¤t_target); +- create_solib_event_breakpoint (target_gdbarch, sym_addr); ++ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); + return 1; + } + } +@@ -1771,7 +2418,7 @@ enable_break (struct svr4_info *info, in + sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, + sym_addr, + ¤t_target); +- create_solib_event_breakpoint (target_gdbarch, sym_addr); ++ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); + return 1; + } + } +@@ -2281,6 +2928,9 @@ svr4_solib_create_inferior_hook (int fro + + info = get_svr4_info (); + ++ /* Free the probes-based interface's namespace table. */ ++ free_namespace_table (info); ++ + /* Relocate the main executable if necessary. */ + svr4_relocate_main_executable (); + +@@ -2547,4 +3197,6 @@ _initialize_svr4_solib (void) + svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; + svr4_so_ops.same = svr4_same; + svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; ++ svr4_so_ops.handle_solib_event = svr4_handle_solib_event; ++ svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints; + } +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen-solib.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen-solib.c 2012-08-14 17:34:44.330746591 +0200 +@@ -0,0 +1,24 @@ ++/* Copyright 2012 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 . */ ++ ++#include ++ ++int ++foo (int n) ++{ ++ printf ("foo %d\n", n); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.c 2012-08-14 17:34:44.339746576 +0200 +@@ -0,0 +1,58 @@ ++/* Copyright 2012 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 . */ ++ ++#define _GNU_SOURCE ++#include ++ ++void ++stop () ++{ ++} ++ ++int ++main () ++{ ++ void *handle1, *handle2, *handle3; ++ void (*func)(int); ++ ++ handle1 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY); ++ stop (); ++ ++ func = (void (*)(int)) dlsym (handle1, "foo"); ++ func (1); ++ ++ handle2 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY); ++ stop (); ++ ++ func = (void (*)(int)) dlsym (handle2, "foo"); ++ func (2); ++ ++ handle3 = dlopen (SHLIB_NAME, RTLD_LAZY); ++ stop (); ++ ++ func = (void (*)(int)) dlsym (handle3, "foo"); ++ func (3); ++ ++ dlclose (handle1); ++ stop (); ++ ++ dlclose (handle2); ++ stop (); ++ ++ dlclose (handle3); ++ stop (); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.exp 2012-08-14 17:34:44.343746563 +0200 +@@ -0,0 +1,125 @@ ++# Copyright 2012 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 . ++ ++if { [skip_shlib_tests] || [is_remote target] } { ++ return 0 ++} ++ ++standard_testfile ++ ++set libname $testfile-solib ++set srcfile_lib $srcdir/$subdir/$libname.c ++set binfile_lib [standard_output_file $libname.so] ++ ++set normal_bp "_dl_debug_state" ++set probes_bp "dl_main" ++ ++if { [gdb_compile_shlib $srcfile_lib $binfile_lib \ ++ [list additional_flags=-fPIC]] != "" } { ++ untested "Could not compile $binfile_lib." ++ return -1 ++} ++ ++if { [prepare_for_testing $testfile.exp $testfile $srcfile \ ++ [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } { ++ return -1 ++} ++ ++# Run "info sharedlibrary" and check our library is shown the expected ++# number of times. ++proc check_info_shared { test expect } { ++ global libname ++ global gdb_prompt ++ ++ set actual 0 ++ ++ gdb_test_multiple "info sharedlibrary" $test { ++ -re $libname { ++ incr actual 1 ++ exp_continue ++ } ++ -re "\r\n$gdb_prompt $" { ++ if { $actual == $expect } { ++ pass $test ++ } else { ++ fail $test ++ } ++ } ++ } ++} ++ ++# Enable stop-on-solib-events ++gdb_test_no_output "set stop-on-solib-events 1" ++ ++# Run to the first stop ++gdb_test "run" ".*Stopped due to shared library event.*" ++ ++# XFAIL if we are not using probes ++set test "ensure using probes" ++set using_probes 0 ++gdb_test_multiple "bt" $test { ++ -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" { ++ xfail $test ++ } ++ -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" { ++ pass $test ++ set using_probes 1 ++ } ++} ++ ++if { $using_probes } { ++ # Set up breakpoints. ++ gdb_test_no_output "set stop-on-solib-events 0" ++ gdb_test "break stop" {Breakpoint [0-9]+ at .*} ++ gdb_test_no_output "set breakpoint pending on" ++ gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.} ++ ++ # Check our library isn't loaded. ++ check_info_shared "info sharedlibrary #1" 0 ++ ++ # Run to the first stop and check our library loaded. ++ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++ check_info_shared "info sharedlibrary #2" 1 ++ ++ # The next stop should be the function in the library. ++ gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} ++ ++ # Run to the next stop and check our library is now loaded twice. ++ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++ check_info_shared "info sharedlibrary #3" 2 ++ ++ # The next stop should be the function in the library. ++ gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} ++ ++ # Run to the next stop and check our library is now loaded three ++ # times. ++ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++ check_info_shared "info sharedlibrary #4" 3 ++ ++ # The next stop should be the function in the library. ++ gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} ++ ++ # Run to the next stop and check our library is now loaded twice. ++ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++ check_info_shared "info sharedlibrary #5" 2 ++ ++ # Run to the next stop and check our library is now loaded once. ++ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++ check_info_shared "info sharedlibrary #6" 1 ++ ++ # Run to the next stop and check our library is not loaded. ++ gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++ check_info_shared "info sharedlibrary #7" 0 ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-interp.exp +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/testsuite/gdb.base/break-interp.exp 2012-06-21 22:46:21.000000000 +0200 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-interp.exp 2012-08-14 17:34:44.344746565 +0200 +@@ -109,12 +109,19 @@ proc strip_debug {dest} { + } + } + ++# The marker function for the standard runtime linker interface is ++# _dl_debug_state. The probes-based interface has no specific marker ++# function; the probe we will stop on (init_start) is in dl_main so we ++# check for that. ++ ++set solib_bp {(_dl_debug_state|dl_main)} ++ + # Implementation of reach. + + proc reach_1 {func command displacement} { +- global gdb_prompt expect_out ++ global gdb_prompt expect_out solib_bp + +- if {$func == "_dl_debug_state"} { ++ if {$func == $solib_bp} { + # Breakpoint on _dl_debug_state can have problems due to its overlap + # with the existing internal breakpoint from GDB. + gdb_test_no_output "set stop-on-solib-events 1" +@@ -142,21 +149,21 @@ proc reach_1 {func command displacement} + exp_continue + } + -re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" { +- if {$func == "_dl_debug_state"} { ++ if {$func == $solib_bp} { + fail $test + } else { + pass $test + } + } + -re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" { +- if {$func == "_dl_debug_state"} { ++ if {$func == $solib_bp} { + fail $test + } else { + pass $test + } + } + -re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" { +- if {$func == "_dl_debug_state"} { ++ if {$func == $solib_bp} { + if {$debug_state_count == 0} { + # First stop does not yet relocate the _start function + # descriptor on ppc64. +@@ -175,7 +182,7 @@ proc reach_1 {func command displacement} + fail $test_displacement + } + +- if {$func == "_dl_debug_state"} { ++ if {$func == $solib_bp} { + gdb_test_no_output "set stop-on-solib-events 0" + } + } +@@ -357,7 +364,7 @@ proc test_attach {file displacement {rel + } + + proc test_ld {file ifmain trynosym displacement} { +- global srcdir subdir gdb_prompt expect_out inferior_exited_re ++ global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp + + # First test normal `file'-command loaded $FILE with symbols. + +@@ -385,9 +392,9 @@ proc test_ld {file ifmain trynosym displ + gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test" + } + +- reach "_dl_debug_state" "run" $displacement ++ reach $solib_bp "run" $displacement + +- gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt" ++ gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt" + + if $ifmain { + reach "main" continue "NONE" +@@ -399,7 +406,7 @@ proc test_ld {file ifmain trynosym displ + + # Try re-run if the new PIE displacement takes effect. + gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y" +- reach "_dl_debug_state" "run" $displacement ++ reach $solib_bp "run" $displacement + + if $ifmain { + test_core $file $displacement +@@ -431,7 +438,7 @@ proc test_ld {file ifmain trynosym displ + gdb_test "exec-file $file" "exec-file $escapedfile" "load" + + if $ifmain { +- reach "_dl_debug_state" run $displacement ++ reach $solib_bp run $displacement + + # Use two separate gdb_test_multiple statements to avoid timeouts due + # to slow processing of wildcard capturing long output +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes-solib.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes-solib.c 2012-08-14 17:34:44.355746561 +0200 +@@ -0,0 +1,24 @@ ++/* Copyright 2012 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 . */ ++ ++#include ++ ++int ++foo (int n) ++{ ++ printf ("foo %d\n", n); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.c 2012-08-14 17:34:44.362746561 +0200 +@@ -0,0 +1,26 @@ ++/* Copyright 2012 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 . */ ++ ++#include ++ ++int ++main () ++{ ++ void *handle = dlopen (SHLIB_NAME, RTLD_LAZY); ++ ++ dlclose (handle); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.exp 2012-08-14 17:34:44.363746561 +0200 +@@ -0,0 +1,76 @@ ++# Copyright 2012 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 . ++ ++if { [skip_shlib_tests] || [is_remote target] } { ++ return 0 ++} ++ ++standard_testfile ++ ++set libname $testfile-solib ++set srcfile_lib $srcdir/$subdir/$libname.c ++set binfile_lib [standard_output_file $libname.so] ++ ++set normal_bp "_dl_debug_state" ++set probes_bp "dl_main" ++ ++if { [gdb_compile_shlib $srcfile_lib $binfile_lib \ ++ [list additional_flags=-fPIC]] != "" } { ++ untested "Could not compile $binfile_lib." ++ return -1 ++} ++ ++if { [prepare_for_testing $testfile.exp $testfile $srcfile \ ++ [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } { ++ return -1 ++} ++ ++# Enable stop-on-solib-events ++gdb_test_no_output "set stop-on-solib-events 1" ++ ++# Run to the first stop ++gdb_test "run" ".*Stopped due to shared library event.*" ++ ++# XFAIL if we are not using probes ++set test "ensure using probes" ++set using_probes 0 ++gdb_test_multiple "bt" $test { ++ -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" { ++ xfail $test ++ } ++ -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" { ++ pass $test ++ set using_probes 1 ++ } ++} ++ ++if { $using_probes } { ++ # Run til it loads our library ++ set test "run til our library loads" ++ set loaded_library 0 ++ while { !$loaded_library } { ++ gdb_test_multiple "c" $test { ++ -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" { ++ pass $test ++ set loaded_library 1 ++ } ++ -re "Stopped due to shared library event\\M.*$gdb_prompt $" { ++ } ++ } ++ } ++ ++ # Call something to ensure that relocation occurred ++ gdb_test "call foo(23)" "foo 23.*\\\$.* = .*" ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib1.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib1.c 2012-08-14 17:34:44.365746561 +0200 +@@ -0,0 +1,24 @@ ++/* Copyright 2012 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 . */ ++ ++#include ++ ++int ++foo (int n) ++{ ++ printf ("foo %d\n", n); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib2.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib2.c 2012-08-14 17:34:44.365746561 +0200 +@@ -0,0 +1,24 @@ ++/* Copyright 2012 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 . */ ++ ++#include ++ ++int ++bar (int n) ++{ ++ printf ("bar %d\n", n); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.c 2012-08-14 17:34:44.366746561 +0200 +@@ -0,0 +1,48 @@ ++/* Copyright 2012 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 . */ ++ ++#include ++ ++void ++stop () ++{ ++} ++ ++int ++main () ++{ ++ void *handle1, *handle2; ++ void (*func)(int); ++ ++ handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY); ++ stop (); ++ ++ handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY); ++ stop (); ++ ++ func = (void (*)(int)) dlsym (handle1, "foo"); ++ func (1); ++ ++ func = (void (*)(int)) dlsym (handle2, "bar"); ++ func (2); ++ ++ dlclose (handle1); ++ stop (); ++ ++ dlclose (handle2); ++ stop (); ++ ++ return 0; ++} +Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.exp +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.exp 2012-08-14 17:34:44.367746561 +0200 +@@ -0,0 +1,139 @@ ++# Copyright 2012 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 . ++ ++if { [skip_shlib_tests] || [is_remote target] } { ++ return 0 ++} ++ ++standard_testfile ++ ++set lib1name $testfile-solib1 ++set srcfile_lib1 $srcdir/$subdir/$lib1name.c ++set binfile_lib1 [standard_output_file $lib1name.so] ++set define1 -DSHLIB1_NAME\=\"$binfile_lib1\" ++ ++set lib2name $testfile-solib2 ++set srcfile_lib2 $srcdir/$subdir/$lib2name.c ++set binfile_lib2 [standard_output_file $lib2name.so] ++set define2 -DSHLIB2_NAME\=\"$binfile_lib2\" ++ ++if { [gdb_compile_shlib $srcfile_lib1 $binfile_lib1 \ ++ [list additional_flags=-fPIC]] != "" } { ++ untested "Could not compile $binfile_lib1." ++ return -1 ++} ++ ++if { [gdb_compile_shlib $srcfile_lib2 $binfile_lib2 \ ++ [list additional_flags=-fPIC]] != "" } { ++ untested "Could not compile $binfile_lib2." ++ return -1 ++} ++ ++set cflags "$define1 $define2" ++if { [prepare_for_testing $testfile.exp $testfile $srcfile \ ++ [list additional_flags=$cflags libs=-ldl]] } { ++ return -1 ++} ++ ++# Run "info sharedlibrary" and check for the presence or absence of ++# our libraries. ++proc check_info_shared { test expect1 expect2 } { ++ global lib1name ++ global lib2name ++ global gdb_prompt ++ ++ set actual1 0 ++ set actual2 0 ++ ++ gdb_test_multiple "info sharedlibrary" $test { ++ -re $lib1name { ++ set actual1 1 ++ exp_continue ++ } ++ -re $lib2name { ++ set actual2 1 ++ exp_continue ++ } ++ -re "\r\n$gdb_prompt $" { ++ if { $actual1 == $expect1 && $actual2 == $expect2 } { ++ pass $test ++ } else { ++ fail $test ++ } ++ } ++ } ++} ++ ++# Set up breakpoints. ++gdb_test "break stop" {Breakpoint [0-9]+ at .*} ++gdb_test_no_output "set breakpoint pending on" ++gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.} ++gdb_test "break bar" {Breakpoint [0-9]+ \(bar\) pending\.} ++ ++# Check neither of the libraries are loaded at the start. ++gdb_test "start" {Temporary breakpoint [0-9]+, .* in main \(\)} ++check_info_shared "info sharedlibrary #1" 0 0 ++ ++# Run to the first stop and check that only the first library is loaded. ++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++check_info_shared "info sharedlibrary #2" 1 0 ++ ++# Run to the second stop and check that both libraries are loaded. ++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++check_info_shared "info sharedlibrary #3" 1 1 ++ ++# Check that the next stop is in foo. ++gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} ++ ++# Check that the next stop is in bar. ++gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*} ++ ++# Restart the inferior and make sure there are no breakpoint reset ++# errors. These can happen with the probes-based runtime linker ++# interface if the cache is not cleared correctly. ++set test "restart" ++gdb_test_multiple "run" $test { ++ -re {Start it from the beginning\? \(y or n\) } { ++ send_gdb "y\n" ++ exp_continue ++ } ++ -re {Error in re-setting breakpoint} { ++ fail $test ++ } ++ -re "\r\n$gdb_prompt $" { ++ pass $test ++ } ++} ++ ++# We're at the first stop. Check that only the first library is loaded. ++check_info_shared "info sharedlibrary #4" 1 0 ++ ++# Run to the second stop and check that both libraries are loaded. ++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++check_info_shared "info sharedlibrary #5" 1 1 ++ ++# Check that the next stop is in foo. ++gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} ++ ++# Check that the next stop is in bar. ++gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*} ++ ++# Run to the next stop and check that the first library has been unloaded. ++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++check_info_shared "info sharedlibrary #6" 0 1 ++ ++# Run to the last stop and check that both libraries are gone. ++gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} ++check_info_shared "info sharedlibrary #7" 0 0 diff --git a/gdb-dlopen-stap-probe-7of7.patch b/gdb-dlopen-stap-probe-7of7.patch new file mode 100644 index 0000000..074db24 --- /dev/null +++ b/gdb-dlopen-stap-probe-7of7.patch @@ -0,0 +1,147 @@ +2012-07-30 Gary Benson + + * objfiles.h (inhibit_section_map_updates): New function + declaration. + (resume_section_map_updates): Likewise. + (resume_section_map_updates_cleanup): Likewise. + * objfiles.c (objfile_pspace_info): New field "inhibit_updates". + (find_pc_section): Do not update the section map if + inhibit_updates is set. + (inhibit_section_map_updates): New function. + (resume_section_map_updates): Likewise. + (resume_section_map_updates_cleanup): Likewise. + * solib-svr4.c (svr4_handle_solib_event): Inhibit section map + updates for calls to evaluate_probe_argument. + +Index: gdb-7.4.91.20120814/gdb/objfiles.h +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/objfiles.h 2012-08-14 17:16:54.000000000 +0200 ++++ gdb-7.4.91.20120814/gdb/objfiles.h 2012-08-14 17:20:55.913174609 +0200 +@@ -526,6 +526,22 @@ extern void set_objfile_data (struct obj + extern void *objfile_data (struct objfile *objfile, + const struct objfile_data *data); + ++/* In normal use, the section map will be rebuilt by FIND_PC_SECTION ++ if objfiles have been added, removed or relocated since it was last ++ called. Calling INHIBIT_SECTION_MAP_UPDATES will inhibit this ++ behavior until RESUME_SECTION_MAP_UPDATES is called. If you call ++ INHIBIT_SECTION_MAP_UPDATES you must ensure that every call to ++ FIND_PC_SECTION in the inhibited region relates to a section that ++ is already in the section map and has not since been removed or ++ relocated. */ ++extern void inhibit_section_map_updates (void); ++ ++/* Resume automatically rebuilding the section map as required. */ ++extern void resume_section_map_updates (void); ++ ++/* Version of the above suitable for use as a cleanup. */ ++extern void resume_section_map_updates_cleanup (void *arg); ++ + extern void default_iterate_over_objfiles_in_search_order + (struct gdbarch *gdbarch, + iterate_over_objfiles_in_search_order_cb_ftype *cb, +Index: gdb-7.4.91.20120814/gdb/objfiles.c +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/objfiles.c 2012-08-14 17:16:55.000000000 +0200 ++++ gdb-7.4.91.20120814/gdb/objfiles.c 2012-08-14 17:20:55.915174609 +0200 +@@ -70,6 +70,9 @@ struct objfile_pspace_info + int objfiles_changed_p; + struct obj_section **sections; + int num_sections; ++ ++ /* Nonzero if section map updates should be inhibited. */ ++ int inhibit_updates; + }; + + /* Per-program-space data key. */ +@@ -1295,7 +1298,7 @@ find_pc_section (CORE_ADDR pc) + return s; + + pspace_info = get_objfile_pspace_data (current_program_space); +- if (pspace_info->objfiles_changed_p != 0) ++ if (pspace_info->objfiles_changed_p && !pspace_info->inhibit_updates) + { + update_section_map (current_program_space, + &pspace_info->sections, +@@ -1463,6 +1466,30 @@ objfiles_changed (void) + get_objfile_pspace_data (current_program_space)->objfiles_changed_p = 1; + } + ++/* See comments in objfiles.h. */ ++ ++void ++inhibit_section_map_updates (void) ++{ ++ get_objfile_pspace_data (current_program_space)->inhibit_updates = 1; ++} ++ ++/* See comments in objfiles.h. */ ++ ++void ++resume_section_map_updates (void) ++{ ++ get_objfile_pspace_data (current_program_space)->inhibit_updates = 0; ++} ++ ++/* See comments in objfiles.h. */ ++ ++void ++resume_section_map_updates_cleanup (void *arg) ++{ ++ resume_section_map_updates (); ++} ++ + /* The default implementation for the "iterate_over_objfiles_in_search_order" + gdbarch method. It is equivalent to use the ALL_OBJFILES macro, + searching the objfiles in the order they are stored internally, +Index: gdb-7.4.91.20120814/gdb/solib-svr4.c +=================================================================== +--- gdb-7.4.91.20120814.orig/gdb/solib-svr4.c 2012-08-14 17:20:42.000000000 +0200 ++++ gdb-7.4.91.20120814/gdb/solib-svr4.c 2012-08-14 17:21:14.090169216 +0200 +@@ -1847,6 +1847,7 @@ svr4_handle_solib_event (bpstat bs) + struct svr4_info *info = get_svr4_info (); + struct probe_and_info buf, *pi = &buf; + enum probe_action action; ++ struct cleanup *cleanups = NULL; + struct value *val; + LONGEST lmid; + CORE_ADDR debug_base, lm = 0; +@@ -1870,6 +1871,19 @@ svr4_handle_solib_event (bpstat bs) + if (action == NAMESPACE_NO_ACTION) + return; + ++ /* EVALUATE_PROBE_ARGUMENT looks up symbols in the dynamic linker ++ using FIND_PC_SECTION. FIND_PC_SECTION is accelerated by a cache ++ called the section map. The section map is invalidated every ++ time a shared library is loaded or unloaded, and if the inferior ++ is generating a lot of shared library events then the section map ++ will be updated every time SVR4_HANDLE_SOLIB_EVENT is called. ++ We called FIND_PC_SECTION in SVR4_CREATE_SOLIB_EVENT_BREAKPOINTS, ++ so we can guarantee that the dynamic linker's sections are in the ++ section map. We can therefore inhibit section map updates across ++ these calls to EVALUATE_PROBE_ARGUMENT and save a lot of time. */ ++ inhibit_section_map_updates (); ++ cleanups = make_cleanup (resume_section_map_updates_cleanup, NULL); ++ + val = evaluate_probe_argument (pi->probe, 0); + if (val == NULL) + goto error; +@@ -1901,6 +1915,9 @@ svr4_handle_solib_event (bpstat bs) + action = NAMESPACE_RELOAD; + } + ++ do_cleanups (cleanups); ++ cleanups = NULL; ++ + if (action == NAMESPACE_UPDATE_OR_RELOAD) + { + if (namespace_update_incremental (info, lmid, lm, is_initial_ns)) +@@ -1923,6 +1940,8 @@ svr4_handle_solib_event (bpstat bs) + warning (_("Probes-based dynamic linker interface failed.\n" + "Reverting to original interface.\n")); + ++ if (cleanups != NULL) ++ do_cleanups (cleanups); + free_namespace_table (info); + free_probes (info); + info->using_probes = 0; diff --git a/gdb-dlopen-stap-probe-test.patch b/gdb-dlopen-stap-probe-test.patch index efd3683..fb2ebd1 100644 --- a/gdb-dlopen-stap-probe-test.patch +++ b/gdb-dlopen-stap-probe-test.patch @@ -305,104 +305,3 @@ Index: gdb-7.4.50.20120714/gdb/testsuite/lib/prelink-support.exp return $prelink_args } -Index: gdb-7.4.50.20120714/gdb/testsuite/gdb.base/break-interp.exp -=================================================================== ---- gdb-7.4.50.20120714.orig/gdb/testsuite/gdb.base/break-interp.exp 2012-06-21 22:46:21.000000000 +0200 -+++ gdb-7.4.50.20120714/gdb/testsuite/gdb.base/break-interp.exp 2012-07-15 08:51:38.244701248 +0200 -@@ -109,14 +109,21 @@ proc strip_debug {dest} { - } - } - -+# Former symbol for solib changes notifications was _dl_debug_state, newer one -+# is dl_main (in fact _dl_debug_notify but it is inlined without any extra -+# debug info), the right one one traps by `set stop-on-solib-events 1'. -+ -+set solib_bp {(_dl_debug_state|dl_main)} -+ - # Implementation of reach. - - proc reach_1 {func command displacement} { -- global gdb_prompt expect_out -+ global gdb_prompt expect_out solib_bp - -- if {$func == "_dl_debug_state"} { -+ if {$func == $solib_bp} { - # Breakpoint on _dl_debug_state can have problems due to its overlap - # with the existing internal breakpoint from GDB. -+ # With also _dl_debug_notify we would need even two breakpoints. - gdb_test_no_output "set stop-on-solib-events 1" - } elseif {! [gdb_breakpoint $func allow-pending]} { - return -@@ -142,21 +149,21 @@ proc reach_1 {func command displacement} - exp_continue - } - -re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" { -- if {$func == "_dl_debug_state"} { -+ if {$func == $solib_bp} { - fail $test - } else { - pass $test - } - } - -re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" { -- if {$func == "_dl_debug_state"} { -+ if {$func == $solib_bp} { - fail $test - } else { - pass $test - } - } - -re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" { -- if {$func == "_dl_debug_state"} { -+ if {$func == $solib_bp} { - if {$debug_state_count == 0} { - # First stop does not yet relocate the _start function - # descriptor on ppc64. -@@ -175,7 +182,7 @@ proc reach_1 {func command displacement} - fail $test_displacement - } - -- if {$func == "_dl_debug_state"} { -+ if {$func == $solib_bp} { - gdb_test_no_output "set stop-on-solib-events 0" - } - } -@@ -357,7 +364,7 @@ proc test_attach {file displacement {rel - } - - proc test_ld {file ifmain trynosym displacement} { -- global srcdir subdir gdb_prompt expect_out inferior_exited_re -+ global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp - - # First test normal `file'-command loaded $FILE with symbols. - -@@ -385,9 +392,9 @@ proc test_ld {file ifmain trynosym displ - gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test" - } - -- reach "_dl_debug_state" "run" $displacement -+ reach $solib_bp "run" $displacement - -- gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt" -+ gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt" - - if $ifmain { - reach "main" continue "NONE" -@@ -399,7 +406,7 @@ proc test_ld {file ifmain trynosym displ - - # Try re-run if the new PIE displacement takes effect. - gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y" -- reach "_dl_debug_state" "run" $displacement -+ reach $solib_bp "run" $displacement - - if $ifmain { - test_core $file $displacement -@@ -431,7 +438,7 @@ proc test_ld {file ifmain trynosym displ - gdb_test "exec-file $file" "exec-file $escapedfile" "load" - - if $ifmain { -- reach "_dl_debug_state" run $displacement -+ reach $solib_bp run $displacement - - # Use two separate gdb_test_multiple statements to avoid timeouts due - # to slow processing of wildcard capturing long output diff --git a/gdb-dlopen-stap-probe-test2.patch b/gdb-dlopen-stap-probe-test2.patch new file mode 100644 index 0000000..9ca4f6b --- /dev/null +++ b/gdb-dlopen-stap-probe-test2.patch @@ -0,0 +1,69 @@ +http://sourceware.org/ml/gdb-patches/2012-08/msg00500.html +Subject: [patch] testsuite: Make solib-corrupted.exp untested for probes [Re: [RFA 0/4 take 2] Improved linker-debugger interface] + +On Fri, 17 Aug 2012 22:53:53 +0200, Jan Kratochvil wrote: +> It regresses with glibc-debuginfo installed: +> +> info sharedlibrary^M +> From To Syms Read Shared Object Library^M +> 0x00007ffff7ddcb20 0x00007ffff7df63d9 Yes /lib64/ld-linux-x86-64.so.2^M +> 0x00007ffff7ae05b0 0x00007ffff7b4ad78 Yes /lib64/libm.so.6^M +> 0x00007ffff77431a0 0x00007ffff7883cf0 Yes /lib64/libc.so.6^M +> (gdb) FAIL: gdb.base/solib-corrupted.exp: corrupted list +> +> But I guess there is no longer a way to test it with probes so it should just +> run some 'info probes' and make this test UNTESTED if rtld probes are +> available. + +I had to implement it for Fedora already anyway. + + +Regards, +Jan + + +gdb/testsuite/ +2012-08-18 Jan Kratochvil + + * gdb.base/solib-corrupted.exp: New variable probes. + (info probes): New test. + +diff --git a/gdb/testsuite/gdb.base/solib-corrupted.exp b/gdb/testsuite/gdb.base/solib-corrupted.exp +index 84b3b0c..c9f55d6 100644 +--- a/gdb/testsuite/gdb.base/solib-corrupted.exp ++++ b/gdb/testsuite/gdb.base/solib-corrupted.exp +@@ -36,6 +36,33 @@ if ![runto_main] { + return + } + ++# With probes interface GDB no longer scans the inferior library list so its ++# corruption cannot be tested. There is no way to disable the probes ++# interface. ++ ++set probes { init_start init_complete map_start reloc_complete unmap_start ++ unmap_complete } ++set test "info probes" ++gdb_test_multiple $test $test { ++ -re "^rtld\[ \t\]+(?:rtld_)?(\[a-z_\]+)\[ \t\]" { ++ set idx [lsearch -exact $probes $expect_out(1,string)] ++ if { $idx >= 0 } { ++ set probes [lreplace $probes $idx $idx] ++ } ++ exp_continue ++ } ++ -re "^\[^\r\n\]*\r\n" { ++ exp_continue ++ } ++ -re "^$gdb_prompt $" { ++ } ++} ++if { [llength $probes] == 0 } { ++ xfail $test ++ untested "GDB is using probes" ++ return ++} ++ + gdb_test "info sharedlibrary" "From * To .*" "normal list" + + # GDB checks there for matching L_PREV. + diff --git a/gdb-dlopen-stap-probe.patch b/gdb-dlopen-stap-probe.patch deleted file mode 100644 index ff19269..0000000 --- a/gdb-dlopen-stap-probe.patch +++ /dev/null @@ -1,357 +0,0 @@ -From: Gary Benson -To: Jan Kratochvil -Message-ID: <20110810133605.GB7294@redhat.com> - -Index: gdb-7.4.91.20120801/gdb/infrun.c -=================================================================== ---- gdb-7.4.91.20120801.orig/gdb/infrun.c 2012-08-01 18:38:24.000000000 +0200 -+++ gdb-7.4.91.20120801/gdb/infrun.c 2012-08-01 18:44:59.568518602 +0200 -@@ -361,6 +361,13 @@ static struct symbol *step_start_functio - /* Nonzero if we want to give control to the user when we're notified - of shared library events by the dynamic linker. */ - int stop_on_solib_events; -+ -+static void -+set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c) -+{ -+ update_solib_breakpoints (); -+} -+ - static void - show_stop_on_solib_events (struct ui_file *file, int from_tty, - struct cmd_list_element *c, const char *value) -@@ -7229,7 +7236,7 @@ Show stopping for shared library events. - If nonzero, gdb will give control to the user when the dynamic linker\n\ - notifies gdb of shared library events. The most common event of interest\n\ - to the user would be loading/unloading of a new library."), -- NULL, -+ set_stop_on_solib_events, - show_stop_on_solib_events, - &setlist, &showlist); - -Index: gdb-7.4.91.20120801/gdb/solib-svr4.c -=================================================================== ---- gdb-7.4.91.20120801.orig/gdb/solib-svr4.c 2012-08-01 18:38:24.000000000 +0200 -+++ gdb-7.4.91.20120801/gdb/solib-svr4.c 2012-08-01 18:45:13.449441787 +0200 -@@ -47,6 +47,7 @@ - #include "auxv.h" - #include "exceptions.h" - #include "gdb_bfd.h" -+#include "probe.h" - - static struct link_map_offsets *svr4_fetch_link_map_offsets (void); - static int svr4_have_link_map_offsets (void); -@@ -93,6 +94,32 @@ static const char * const solib_break_na - NULL - }; - -+/* A list of SystemTap probes which, if present in the dynamic linker, -+ allow more fine-grained breakpoints to be placed on shared library -+ events. */ -+ -+struct probe_info -+ { -+ /* The name of the probe. */ -+ const char *name; -+ -+ /* Nonzero if this probe must be stopped at even when -+ stop-on-solib-events is off. */ -+ int mandatory; -+ }; -+ -+static const struct probe_info probe_info[] = -+{ -+ {"rtld_init_start", 0}, -+ {"rtld_init_complete", 1}, -+ {"rtld_map_start", 0}, -+ {"rtld_reloc_complete", 1}, -+ {"rtld_unmap_start", 0}, -+ {"rtld_unmap_complete", 1}, -+}; -+ -+#define NUM_PROBES (sizeof(probe_info) / sizeof(probe_info[0])) -+ - static const char * const bkpt_names[] = - { - "_start", -@@ -314,6 +341,12 @@ struct svr4_info - CORE_ADDR interp_text_sect_high; - CORE_ADDR interp_plt_sect_low; - CORE_ADDR interp_plt_sect_high; -+ -+ /* SystemTap probes. */ -+ VEC (probe_p) *probes[NUM_PROBES]; -+ -+ /* Nonzero if we are using the SystemTap interface. */ -+ int using_probes; - }; - - /* Per-program-space data key. */ -@@ -323,8 +356,15 @@ static void - svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) - { - struct svr4_info *info; -+ int i; - - info = program_space_data (pspace, solib_svr4_pspace_data); -+ if (info == NULL) -+ return; -+ -+ for (i = 0; i < NUM_PROBES; i++) -+ VEC_free (probe_p, info->probes[i]); -+ - xfree (info); - } - -@@ -1450,6 +1490,126 @@ exec_entry_point (struct bfd *abfd, stru - targ); - } - -+/* Helper function for svr4_update_solib_event_breakpoints. */ -+ -+static int -+svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg) -+{ -+ struct svr4_info *info = get_svr4_info (); -+ struct bp_location *loc; -+ -+ if (b->type != bp_shlib_event) -+ return 0; -+ -+ for (loc = b->loc; loc; loc = loc->next) -+ { -+ int i; -+ -+ for (i = 0; i < NUM_PROBES; i++) -+ { -+ if (!probe_info[i].mandatory) -+ { -+ struct probe *probe; -+ int ix; -+ -+ for (ix = 0; -+ VEC_iterate (probe_p, info->probes[i], ix, probe); -+ ++ix) -+ { -+ if (loc->pspace == current_program_space -+ && loc->address == probe->address) -+ { -+ b->enable_state = -+ stop_on_solib_events ? bp_enabled : bp_disabled; -+ return 0; -+ } -+ } -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/* Enable or disable optional solib event breakpoints as appropriate. -+ Called whenever stop_on_solib_events is changed. */ -+ -+static void -+svr4_update_solib_event_breakpoints (void) -+{ -+ struct svr4_info *info = get_svr4_info (); -+ -+ if (info->using_probes) -+ iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL); -+} -+ -+/* Both the SunOS and the SVR4 dynamic linkers call a marker function -+ before and after mapping and unmapping shared libraries. The sole -+ purpose of this method is to allow debuggers to set a breakpoint so -+ they can track these changes. -+ -+ Some versions of the glibc dynamic linker contain SystemTap probes -+ to allow more fine grained stopping. Given the address of the -+ original marker function, this function attempts to find these -+ probes, and if found, sets breakpoints on those instead. If the -+ probes aren't found, a single breakpoint is set on the original -+ SVR4 marker function. */ -+ -+static void -+svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch, CORE_ADDR address) -+{ -+ struct svr4_info *info = get_svr4_info (); -+ struct obj_section *os; -+ -+ os = find_pc_section (address); -+ if (os != NULL) -+ { -+ int all_probes_found = 1; -+ int i; -+ -+ for (i = 0; i < NUM_PROBES; i++) -+ { -+ info->probes[i] = find_probes_in_objfile (os->objfile, "rtld", -+ probe_info[i].name); -+ -+ if (!VEC_length(probe_p, info->probes[i])) -+ { -+ int j; -+ -+ for (j = i - 1; j >= 0; j--) -+ { -+ VEC_free (probe_p, info->probes[j]); -+ info->probes[j] = NULL; -+ } -+ -+ all_probes_found = 0; -+ break; -+ } -+ } -+ -+ if (all_probes_found) -+ { -+ info->using_probes = 1; -+ -+ for (i = 0; i < NUM_PROBES; i++) -+ { -+ struct probe *probe; -+ int ix; -+ -+ for (ix = 0; -+ VEC_iterate (probe_p, info->probes[i], ix, probe); -+ ++ix) -+ create_solib_event_breakpoint (gdbarch, probe->address); -+ } -+ -+ svr4_update_solib_event_breakpoints (); -+ return; -+ } -+ } -+ -+ create_solib_event_breakpoint (gdbarch, address); -+} -+ - /* Helper function for gdb_bfd_lookup_symbol. */ - - static int -@@ -1498,10 +1658,18 @@ enable_break (struct svr4_info *info, in - asection *interp_sect; - gdb_byte *interp_name; - CORE_ADDR sym_addr; -+ int i; - - info->interp_text_sect_low = info->interp_text_sect_high = 0; - info->interp_plt_sect_low = info->interp_plt_sect_high = 0; - -+ for (i = 0; i < NUM_PROBES; i++) -+ { -+ VEC_free (probe_p, info->probes[i]); -+ info->probes[i] = NULL; -+ } -+ info->using_probes = 0; -+ - /* If we already have a shared library list in the target, and - r_debug contains r_brk, set the breakpoint there - this should - mean r_brk has already been relocated. Assume the dynamic linker -@@ -1533,7 +1701,7 @@ enable_break (struct svr4_info *info, in - That knowledge is encoded in the address, if it's Thumb the low bit - is 1. However, we've stripped that info above and it's not clear - what all the consequences are of passing a non-addr_bits_remove'd -- address to create_solib_event_breakpoint. The call to -+ address to svr4_create_solib_event_breakpoints. The call to - find_pc_section verifies we know about the address and have some - hope of computing the right kind of breakpoint to use (via - symbol info). It does mean that GDB needs to be pointed at a -@@ -1571,7 +1739,7 @@ enable_break (struct svr4_info *info, in - + bfd_section_size (tmp_bfd, interp_sect); - } - -- create_solib_event_breakpoint (target_gdbarch, sym_addr); -+ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); - return 1; - } - } -@@ -1729,7 +1897,8 @@ enable_break (struct svr4_info *info, in - - if (sym_addr != 0) - { -- create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr); -+ svr4_create_solib_event_breakpoints (target_gdbarch, -+ load_addr + sym_addr); - xfree (interp_name); - return 1; - } -@@ -1755,7 +1924,7 @@ enable_break (struct svr4_info *info, in - sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, - sym_addr, - ¤t_target); -- create_solib_event_breakpoint (target_gdbarch, sym_addr); -+ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); - return 1; - } - } -@@ -1771,7 +1940,7 @@ enable_break (struct svr4_info *info, in - sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, - sym_addr, - ¤t_target); -- create_solib_event_breakpoint (target_gdbarch, sym_addr); -+ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); - return 1; - } - } -@@ -2547,4 +2716,5 @@ _initialize_svr4_solib (void) - svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; - svr4_so_ops.same = svr4_same; - svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; -+ svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints; - } -Index: gdb-7.4.91.20120801/gdb/solib.c -=================================================================== ---- gdb-7.4.91.20120801.orig/gdb/solib.c 2012-08-01 18:38:24.000000000 +0200 -+++ gdb-7.4.91.20120801/gdb/solib.c 2012-08-01 18:44:59.573518572 +0200 -@@ -1226,6 +1226,18 @@ no_shared_libraries (char *ignored, int - objfile_purge_solibs (); - } - -+/* Enable or disable optional solib event breakpoints as appropriate. */ -+ -+void -+update_solib_breakpoints (void) -+{ -+ struct target_so_ops *ops = solib_ops (target_gdbarch); -+ -+ if (ops->update_breakpoints != NULL) -+ ops->update_breakpoints (); -+} -+ -+ - /* Reload shared libraries, but avoid reloading the same symbol file - we already have loaded. */ - -Index: gdb-7.4.91.20120801/gdb/solib.h -=================================================================== ---- gdb-7.4.91.20120801.orig/gdb/solib.h 2012-02-03 16:19:37.000000000 +0100 -+++ gdb-7.4.91.20120801/gdb/solib.h 2012-08-01 18:44:59.574518566 +0200 -@@ -91,4 +91,8 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f - void *), - void *data); - -+/* Enable or disable optional solib event breakpoints as appropriate. */ -+ -+extern void update_solib_breakpoints (void); -+ - #endif /* SOLIB_H */ -Index: gdb-7.4.91.20120801/gdb/solist.h -=================================================================== ---- gdb-7.4.91.20120801.orig/gdb/solist.h 2012-01-04 09:17:11.000000000 +0100 -+++ gdb-7.4.91.20120801/gdb/solist.h 2012-08-01 18:44:59.574518566 +0200 -@@ -149,6 +149,13 @@ struct target_so_ops - core file (in particular, for readonly sections). */ - int (*keep_data_in_core) (CORE_ADDR vaddr, - unsigned long size); -+ -+ /* Enable or disable optional solib event breakpoints as -+ appropriate. This should be called whenever -+ stop_on_solib_events is changed. This pointer can be -+ NULL, in which case no enabling or disabling is necessary -+ for this target. */ -+ void (*update_breakpoints) (void); - }; - - /* Free the memory associated with a (so_list *). */ diff --git a/gdb.spec b/gdb.spec index 73df70e..a915c38 100644 --- a/gdb.spec +++ b/gdb.spec @@ -27,20 +27,20 @@ Summary: A GNU source-level debugger for C, C++, Fortran, Go and other languages Name: %{?scl_prefix}gdb -%global snap 20120801 -# See tempstamp of source gnulib installed into gdb/gnulib/ . +%global snap 20120817 +# See timestamp of source gnulib installed into gdb/gnulib/ . %global snapgnulib 20120623 -Version: 7.4.91.%{snap} +Version: 7.5 # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 18%{?dist} +Release: 19%{?dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain Group: Development/Debuggers # Do not provide URL for snapshots as the file lasts there only for 2 days. # ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.bz2 -Source: gdb-%{version}.tar.bz2 +Source: ftp://sourceware.org/pub/gdb/releases/gdb-%{version}.tar.bz2 Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) URL: http://gnu.org/software/gdb/ @@ -512,8 +512,15 @@ Patch579: gdb-7.2.50-sparc-add-workaround-to-broken-debug-files.patch # Fix dlopen of libpthread.so, patched glibc required (Gary Benson, BZ 669432). #=push -Patch618: gdb-dlopen-stap-probe.patch +Patch618: gdb-dlopen-stap-probe-1of7.patch +Patch717: gdb-dlopen-stap-probe-2of7.patch +Patch718: gdb-dlopen-stap-probe-3of7.patch +Patch719: gdb-dlopen-stap-probe-4of7.patch +Patch720: gdb-dlopen-stap-probe-5of7.patch +Patch721: gdb-dlopen-stap-probe-6of7.patch +Patch722: gdb-dlopen-stap-probe-7of7.patch Patch619: gdb-dlopen-stap-probe-test.patch +Patch723: gdb-dlopen-stap-probe-test2.patch # Work around PR libc/13097 "linux-vdso.so.1" warning message. #=push @@ -848,6 +855,13 @@ rm -f gdb/jv-exp.c gdb/m2-exp.c gdb/objc-exp.c gdb/p-exp.c gdb/go-exp.c %patch548 -p1 %patch579 -p1 %patch618 -p1 +%patch717 -p1 +%patch718 -p1 +%patch719 -p1 +%patch720 -p1 +%patch721 -p1 +%patch722 -p1 +%patch723 -p1 %patch619 -p1 %patch627 -p1 %patch634 -p1 @@ -1355,7 +1369,11 @@ fi %endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch" %changelog -* Fri Aug 17 2012 Jan Kratochvil - 7.4.91.20120801-18 +* Sat Aug 18 2012 Jan Kratochvil - 7.5-19.fc18 +- Rebase to FSF GDB 7.5. +- Update dlopen to support two variants of glibc (Gary Benson, BZ 669432). + +* Fri Aug 17 2012 Jan Kratochvil - 7.4.91.20120801-18.fc18 - Drop Source URL for snapshots. - Separate %%{snapgnulib} from %%{snap}. - Fix %%{libstdcxxpython} to be %%{name}-prefixed. @@ -1363,11 +1381,11 @@ fi - Include RHEL-5 compatible %%{buildroot} cleanup. - Use %%__global_ldflags. -* Wed Aug 1 2012 Jan Kratochvil - 7.4.91.20120801-17 +* Wed Aug 1 2012 Jan Kratochvil - 7.4.91.20120801-17.fc18 - Rebase to FSF GDB 7.4.91.20120801. - [dwz] Rebase it from FSF GDB HEAD. -* Thu Jul 19 2012 Fedora Release Engineering - 7.4.50.20120714-16 +* Thu Jul 19 2012 Fedora Release Engineering - 7.4.50.20120714-16.fc18 - Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild * Mon Jul 16 2012 Jan Kratochvil - 7.4.50.20120714-15.fc18 diff --git a/sources b/sources index 1e944af..45b960d 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 4981307aa9619bbec5b73261e4e41c8d gdb-libstdc++-v3-python-r155978.tar.bz2 -ed42ee95b7a114551094c84ee4192643 gdb-7.4.91.20120801.tar.bz2 +24a6779a9fe0260667710de1b082ef61 gdb-7.5.tar.bz2