]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blame - gdb/patches/gdb-dlopen-stap-probe.patch
Merge remote-tracking branch 'stevee/audit'
[people/ms/ipfire-3.x.git] / gdb / patches / gdb-dlopen-stap-probe.patch
CommitLineData
5a03b7c3
MT
1From: Gary Benson <gbenson@redhat.com>
2To: Jan Kratochvil <jan.kratochvil@redhat.com>
3Message-ID: <20110810133605.GB7294@redhat.com>
4
5diff --git a/gdb/infrun.c b/gdb/infrun.c
6index 4296d3a..fd5e9c3 100644
7--- a/gdb/infrun.c
8+++ b/gdb/infrun.c
9@@ -321,6 +323,13 @@ static struct symbol *step_start_function;
10 /* Nonzero if we want to give control to the user when we're notified
11 of shared library events by the dynamic linker. */
12 int stop_on_solib_events;
13+
14+static void
15+set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c)
16+{
17+ update_solib_breakpoints ();
18+}
19+
20 static void
21 show_stop_on_solib_events (struct ui_file *file, int from_tty,
22 struct cmd_list_element *c, const char *value)
23@@ -7153,7 +7162,7 @@ Show stopping for shared library events."), _("\
24 If nonzero, gdb will give control to the user when the dynamic linker\n\
25 notifies gdb of shared library events. The most common event of interest\n\
26 to the user would be loading/unloading of a new library."),
27- NULL,
28+ set_stop_on_solib_events,
29 show_stop_on_solib_events,
30 &setlist, &showlist);
31
32diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
33index dffc621..73cbe1c 100644
34--- a/gdb/solib-svr4.c
35+++ b/gdb/solib-svr4.c
36@@ -48,6 +48,8 @@
37 #include "auxv.h"
38 #include "exceptions.h"
39
40+#include "stap-probe.h"
41+
42 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
43 static int svr4_have_link_map_offsets (void);
44 static void svr4_relocate_main_executable (void);
45@@ -92,6 +94,32 @@ static const char * const solib_break_names[] =
46 NULL
47 };
48
49+/* A list of SystemTap probes which, if present in the dynamic linker,
50+ allow more fine-grained breakpoints to be placed on shared library
51+ events. */
52+
53+struct probe_info
54+ {
55+ /* The name of the probe. */
56+ const char *name;
57+
58+ /* Nonzero if this probe must be stopped at even when
59+ stop-on-solib-events is off. */
60+ int mandatory;
61+ };
62+
63+static const struct probe_info probe_info[] =
64+{
65+ {"rtld_init_start", 0},
66+ {"rtld_init_complete", 1},
67+ {"rtld_map_start", 0},
68+ {"rtld_reloc_complete", 1},
69+ {"rtld_unmap_start", 0},
70+ {"rtld_unmap_complete", 1},
71+};
72+
73+#define NUM_PROBES (sizeof(probe_info) / sizeof(probe_info[0]))
74+
75 static const char * const bkpt_names[] =
76 {
77 "_start",
78@@ -335,6 +363,12 @@ struct svr4_info
79 CORE_ADDR interp_text_sect_high;
80 CORE_ADDR interp_plt_sect_low;
81 CORE_ADDR interp_plt_sect_high;
82+
83+ /* SystemTap probes. */
84+ VEC (stap_probe_p) *probes[NUM_PROBES];
85+
86+ /* Nonzero if we are using the SystemTap interface. */
87+ int using_probes;
88 };
89
90 /* Per-program-space data key. */
91@@ -344,8 +378,15 @@ static void
92 svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
93 {
94 struct svr4_info *info;
95+ int i;
96
97 info = program_space_data (pspace, solib_svr4_pspace_data);
98+ if (info == NULL)
99+ return;
100+
101+ for (i = 0; i < NUM_PROBES; i++)
102+ VEC_free (stap_probe_p, info->probes[i]);
103+
104 xfree (info);
105 }
106
107@@ -1321,6 +1362,126 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ)
108 targ);
109 }
110
111+/* Helper function for svr4_update_solib_event_breakpoints. */
112+
113+static int
114+svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg)
115+{
116+ struct svr4_info *info = get_svr4_info ();
117+ struct bp_location *loc;
118+
119+ if (b->type != bp_shlib_event)
120+ return 0;
121+
122+ for (loc = b->loc; loc; loc = loc->next)
123+ {
124+ int i;
125+
126+ for (i = 0; i < NUM_PROBES; i++)
127+ {
128+ if (!probe_info[i].mandatory)
129+ {
130+ const struct stap_probe *probe;
131+ int ix;
132+
133+ for (ix = 0;
134+ VEC_iterate (stap_probe_p, info->probes[i], ix, probe);
135+ ++ix)
136+ {
137+ if (loc->pspace == current_program_space
138+ && loc->address == probe->address)
139+ {
140+ b->enable_state =
141+ stop_on_solib_events ? bp_enabled : bp_disabled;
142+ return 0;
143+ }
144+ }
145+ }
146+ }
147+ }
148+
149+ return 0;
150+}
151+
152+/* Enable or disable optional solib event breakpoints as appropriate.
153+ Called whenever stop_on_solib_events is changed. */
154+
155+static void
156+svr4_update_solib_event_breakpoints (void)
157+{
158+ struct svr4_info *info = get_svr4_info ();
159+
160+ if (info->using_probes)
161+ iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL);
162+}
163+
164+/* Both the SunOS and the SVR4 dynamic linkers call a marker function
165+ before and after mapping and unmapping shared libraries. The sole
166+ purpose of this method is to allow debuggers to set a breakpoint so
167+ they can track these changes.
168+
169+ Some versions of the glibc dynamic linker contain SystemTap probes
170+ to allow more fine grained stopping. Given the address of the
171+ original marker function, this function attempts to find these
172+ probes, and if found, sets breakpoints on those instead. If the
173+ probes aren't found, a single breakpoint is set on the original
174+ SVR4 marker function. */
175+
176+static void
177+svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch, CORE_ADDR address)
178+{
179+ struct svr4_info *info = get_svr4_info ();
180+ struct obj_section *os;
181+
182+ os = find_pc_section (address);
183+ if (os != NULL)
184+ {
185+ int all_probes_found = 1;
186+ int i;
187+
188+ for (i = 0; i < NUM_PROBES; i++)
189+ {
190+ info->probes[i] = find_probes_in_objfile (os->objfile, "rtld",
191+ probe_info[i].name);
192+
193+ if (!VEC_length(stap_probe_p, info->probes[i]))
194+ {
195+ int j;
196+
197+ for (j = i - 1; j >= 0; j--)
198+ {
199+ VEC_free (stap_probe_p, info->probes[j]);
200+ info->probes[j] = NULL;
201+ }
202+
203+ all_probes_found = 0;
204+ break;
205+ }
206+ }
207+
208+ if (all_probes_found)
209+ {
210+ info->using_probes = 1;
211+
212+ for (i = 0; i < NUM_PROBES; i++)
213+ {
214+ const struct stap_probe *probe;
215+ int ix;
216+
217+ for (ix = 0;
218+ VEC_iterate (stap_probe_p, info->probes[i], ix, probe);
219+ ++ix)
220+ create_solib_event_breakpoint (gdbarch, probe->address);
221+ }
222+
223+ svr4_update_solib_event_breakpoints ();
224+ return;
225+ }
226+ }
227+
228+ create_solib_event_breakpoint (gdbarch, address);
229+}
230+
231 /*
232
233 LOCAL FUNCTION
234@@ -1372,10 +1533,18 @@ enable_break (struct svr4_info *info, int from_tty)
235 asection *interp_sect;
236 gdb_byte *interp_name;
237 CORE_ADDR sym_addr;
238+ int i;
239
240 info->interp_text_sect_low = info->interp_text_sect_high = 0;
241 info->interp_plt_sect_low = info->interp_plt_sect_high = 0;
242
243+ for (i = 0; i < NUM_PROBES; i++)
244+ {
245+ VEC_free (stap_probe_p, info->probes[i]);
246+ info->probes[i] = NULL;
247+ }
248+ info->using_probes = 0;
249+
250 /* If we already have a shared library list in the target, and
251 r_debug contains r_brk, set the breakpoint there - this should
252 mean r_brk has already been relocated. Assume the dynamic linker
253@@ -1407,7 +1576,7 @@ enable_break (struct svr4_info *info, int from_tty)
254 That knowledge is encoded in the address, if it's Thumb the low bit
255 is 1. However, we've stripped that info above and it's not clear
256 what all the consequences are of passing a non-addr_bits_remove'd
257- address to create_solib_event_breakpoint. The call to
258+ address to svr4_create_solib_event_breakpoints. The call to
259 find_pc_section verifies we know about the address and have some
260 hope of computing the right kind of breakpoint to use (via
261 symbol info). It does mean that GDB needs to be pointed at a
262@@ -1445,7 +1614,7 @@ enable_break (struct svr4_info *info, int from_tty)
263 + bfd_section_size (tmp_bfd, interp_sect);
264 }
265
266- create_solib_event_breakpoint (target_gdbarch, sym_addr);
267+ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
268 return 1;
269 }
270 }
271@@ -1599,7 +1768,8 @@ enable_break (struct svr4_info *info, int from_tty)
272
273 if (sym_addr != 0)
274 {
275- create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr);
276+ svr4_create_solib_event_breakpoints (target_gdbarch,
277+ load_addr + sym_addr);
278 xfree (interp_name);
279 return 1;
280 }
281@@ -1625,7 +1795,7 @@ enable_break (struct svr4_info *info, int from_tty)
282 sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
283 sym_addr,
284 &current_target);
285- create_solib_event_breakpoint (target_gdbarch, sym_addr);
286+ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
287 return 1;
288 }
289 }
290@@ -1641,7 +1811,7 @@ enable_break (struct svr4_info *info, int from_tty)
291 sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
292 sym_addr,
293 &current_target);
294- create_solib_event_breakpoint (target_gdbarch, sym_addr);
295+ svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr);
296 return 1;
297 }
298 }
299@@ -2470,4 +2640,5 @@ _initialize_svr4_solib (void)
300 svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
301 svr4_so_ops.same = svr4_same;
302 svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
303+ svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
304 }
305diff --git a/gdb/solib.c b/gdb/solib.c
306index 3296ed4..7ba70ce 100644
307--- a/gdb/solib.c
308+++ b/gdb/solib.c
309@@ -1313,6 +1313,18 @@ no_shared_libraries (char *ignored, int from_tty)
310 objfile_purge_solibs ();
311 }
312
313+/* Enable or disable optional solib event breakpoints as appropriate. */
314+
315+void
316+update_solib_breakpoints (void)
317+{
318+ struct target_so_ops *ops = solib_ops (target_gdbarch);
319+
320+ if (ops->update_breakpoints != NULL)
321+ ops->update_breakpoints ();
322+}
323+
324+
325 /* Reload shared libraries, but avoid reloading the same symbol file
326 we already have loaded. */
327
328diff --git a/gdb/solib.h b/gdb/solib.h
329index c473d85..7b3881c 100644
330--- a/gdb/solib.h
331+++ b/gdb/solib.h
332@@ -78,4 +78,8 @@ extern void set_solib_ops (struct gdbarch *gdbarch,
333
334 extern int libpthread_name_p (const char *name);
335
336+/* Enable or disable optional solib event breakpoints as appropriate. */
337+
338+extern void update_solib_breakpoints (void);
339+
340 #endif /* SOLIB_H */
341diff --git a/gdb/solist.h b/gdb/solist.h
342index dad11be..14ede10 100644
343--- a/gdb/solist.h
344+++ b/gdb/solist.h
345@@ -137,6 +137,13 @@ struct target_so_ops
346 core file (in particular, for readonly sections). */
347 int (*keep_data_in_core) (CORE_ADDR vaddr,
348 unsigned long size);
349+
350+ /* Enable or disable optional solib event breakpoints as
351+ appropriate. This should be called whenever
352+ stop_on_solib_events is changed. This pointer can be
353+ NULL, in which case no enabling or disabling is necessary
354+ for this target. */
355+ void (*update_breakpoints) (void);
356 };
357
358 /* Free the memory associated with a (so_list *). */