]>
Commit | Line | Data |
---|---|---|
a7de96f0 PS |
1 | gdb/ |
2 | 2012-07-30 Gary Benson <gbenson@redhat.com> | |
3 | ||
4 | * breakpoint.h (handle_solib_event): Moved function definition | |
5 | to solib.h, and added a new parameter. | |
6 | * breakpoint.c (handle_solib_event): Moved function to solib.c | |
7 | and added a new parameter. | |
8 | (bpstat_stop_status): Pass new argument to handle_solib_event. | |
9 | * solib.h (breakpoint.h): New include. | |
10 | (handle_solib_event): Moved function definition from breakpoint.h | |
11 | and added a new parameter. | |
12 | (update_solib_breakpoints): New function definition. | |
13 | * solib.c (handle_solib_event): Moved function from breakpoint.c | |
14 | and added a new parameter. | |
15 | (update_solib_breakpoints): New function. | |
16 | * solist.h (breakpoint.h): New include. | |
17 | (target_so_ops): New fields "handle_solib_event" and | |
18 | "update_breakpoints". | |
19 | * infrun.c (set_stop_on_solib_events): New function. | |
20 | (_initialize_infrun): Use the above for "set stop-on-solib-events". | |
21 | (handle_inferior_event): Pass new argument to handle_solib_event. | |
22 | * solib-svr4.c (probe.h): New include. | |
23 | (namespace_table_flatten): New forward declaration. | |
24 | (lm_info): New fields "lmid" and "in_initial_ns". | |
25 | (probe_action): New enum. | |
26 | (probe_info): New struct. | |
27 | (probe_info): New static variable. | |
28 | (NUM_PROBES): New definition. | |
29 | (svr4_info): New fields "using_probes", "probes" and | |
30 | "namespace_table". | |
31 | (free_probes): New function. | |
32 | (free_namespace_table): Likewise. | |
33 | (svr4_pspace_data_cleanup): Free probes and namespace table. | |
34 | (svr4_same): Also compare namespaces if using probes. | |
35 | (lm_addr_check): Only print .dynamic section at wrong address | |
36 | warning for initial namespace if using probes. | |
37 | (r_map_from_debug_base): New function. | |
38 | (solib_svr4_r_map): Call the above. | |
39 | (svr4_read_so_list): New parameter "prev_lm". | |
40 | Changed return type from void to int. | |
41 | Return nonzero on success, zero on error. | |
42 | (svr4_current_sos_from_debug_base): New function. | |
43 | (svr4_current_sos): Create result from namespace table if available. | |
44 | Use svr4_current_sos_from_debug_base to generate list otherwise. | |
45 | (probe_and_info): New struct. | |
46 | (solib_event_probe_at): New function. | |
47 | (solib_event_probe_action): Likewise. | |
48 | (namespace): New struct. | |
49 | (hash_namespace): New function. | |
50 | (equal_namespace): Likewise. | |
51 | (free_namespace): Likewise. | |
52 | (namespace_update_full): Likewise. | |
53 | (namespace_update_incremental): Likewise. | |
54 | (svr4_handle_solib_event): Likewise. | |
55 | (namespace_table_flatten_helper): Likewise. | |
56 | (namespace_table_flatten): Likewise. | |
57 | (svr4_update_solib_event_breakpoint): Likewise. | |
58 | (svr4_update_solib_event_breakpoints): Likewise. | |
59 | (svr4_create_solib_event_breakpoints): Likewise. | |
60 | (enable_break): Free probes before creating breakpoints. | |
61 | Use svr4_create_solib_event_breakpoints to create breakpoints. | |
62 | (svr4_solib_create_inferior_hook): Free the namespace table. | |
63 | (_initialize_svr4_solib): Initialise svr4_so_ops.handle_solib_event | |
64 | and svr4_so_ops.update_breakpoints. | |
65 | ||
66 | gdb/testsuite | |
67 | 2012-07-30 Gary Benson <gbenson@redhat.com> | |
68 | ||
69 | * gdb.base/break-interp.exp (solib_bp): New constant. | |
70 | (reach_1): Use the above instead of "_dl_debug_state". | |
71 | (test_attach): Likewise. | |
72 | (test_ld): Likewise. | |
73 | * gdb.base/break-probes.exp: New file. | |
74 | * gdb.base/break-probes.c: Likewise. | |
75 | * gdb.base/break-probes-solib.c: Likewise. | |
76 | * gdb.base/info-shared.exp: New file. | |
77 | * gdb.base/info-shared.c: Likewise. | |
78 | * gdb.base/info-shared-solib1.c: Likewise. | |
79 | * gdb.base/info-shared-solib2.c: Likewise. | |
80 | * gdb.base/break-dlmopen.exp: Likewise. | |
81 | * gdb.base/break-dlmopen.c: Likewise. | |
82 | * gdb.base/break-dlmopen-solib.c: Likewise. | |
83 | ||
84 | Index: gdb-7.4.91.20120814/gdb/breakpoint.h | |
85 | =================================================================== | |
86 | --- gdb-7.4.91.20120814.orig/gdb/breakpoint.h 2012-08-14 17:31:37.050984427 +0200 | |
87 | +++ gdb-7.4.91.20120814/gdb/breakpoint.h 2012-08-14 17:34:44.203746601 +0200 | |
88 | @@ -1515,8 +1515,6 @@ extern int user_breakpoint_p (struct bre | |
89 | /* Attempt to determine architecture of location identified by SAL. */ | |
90 | extern struct gdbarch *get_sal_arch (struct symtab_and_line sal); | |
91 | ||
92 | -extern void handle_solib_event (void); | |
93 | - | |
94 | extern void breakpoints_relocate (struct objfile *objfile, | |
95 | struct section_offsets *delta); | |
96 | ||
97 | Index: gdb-7.4.91.20120814/gdb/breakpoint.c | |
98 | =================================================================== | |
99 | --- gdb-7.4.91.20120814.orig/gdb/breakpoint.c 2012-08-14 17:31:37.128984404 +0200 | |
100 | +++ gdb-7.4.91.20120814/gdb/breakpoint.c 2012-08-14 17:34:44.211746597 +0200 | |
101 | @@ -5205,7 +5205,7 @@ bpstat_stop_status (struct address_space | |
102 | { | |
103 | if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event) | |
104 | { | |
105 | - handle_solib_event (); | |
106 | + handle_solib_event (bs); | |
107 | break; | |
108 | } | |
109 | } | |
110 | @@ -5301,25 +5301,6 @@ handle_jit_event (void) | |
111 | target_terminal_inferior (); | |
112 | } | |
113 | ||
114 | -/* Handle an solib event by calling solib_add. */ | |
115 | - | |
116 | -void | |
117 | -handle_solib_event (void) | |
118 | -{ | |
119 | - clear_program_space_solib_cache (current_inferior ()->pspace); | |
120 | - | |
121 | - /* Check for any newly added shared libraries if we're supposed to | |
122 | - be adding them automatically. Switch terminal for any messages | |
123 | - produced by breakpoint_re_set. */ | |
124 | - target_terminal_ours_for_output (); | |
125 | -#ifdef SOLIB_ADD | |
126 | - SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add); | |
127 | -#else | |
128 | - solib_add (NULL, 0, ¤t_target, auto_solib_add); | |
129 | -#endif | |
130 | - target_terminal_inferior (); | |
131 | -} | |
132 | - | |
133 | /* Prepare WHAT final decision for infrun. */ | |
134 | ||
135 | /* Decide what infrun needs to do with this bpstat. */ | |
136 | Index: gdb-7.4.91.20120814/gdb/solib.h | |
137 | =================================================================== | |
138 | --- gdb-7.4.91.20120814.orig/gdb/solib.h 2012-02-03 16:19:37.000000000 +0100 | |
139 | +++ gdb-7.4.91.20120814/gdb/solib.h 2012-08-14 17:34:44.257746587 +0200 | |
140 | @@ -21,6 +21,9 @@ | |
141 | #ifndef SOLIB_H | |
142 | #define SOLIB_H | |
143 | ||
144 | +/* For bpstat. */ | |
145 | +#include "breakpoint.h" | |
146 | + | |
147 | /* Forward decl's for prototypes */ | |
148 | struct so_list; | |
149 | struct target_ops; | |
150 | @@ -91,4 +94,15 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f | |
151 | void *), | |
152 | void *data); | |
153 | ||
154 | +/* Handle an solib event by calling solib_add. Targets which handle | |
155 | + solib events using breakpoints must pass a valid bpstat. Targets | |
156 | + which handle solib events using some other mechanism should pass | |
157 | + NULL. */ | |
158 | + | |
159 | +extern void handle_solib_event (bpstat bs); | |
160 | + | |
161 | +/* Enable or disable optional solib event breakpoints as appropriate. */ | |
162 | + | |
163 | +extern void update_solib_breakpoints (void); | |
164 | + | |
165 | #endif /* SOLIB_H */ | |
166 | Index: gdb-7.4.91.20120814/gdb/solib.c | |
167 | =================================================================== | |
168 | --- gdb-7.4.91.20120814.orig/gdb/solib.c 2012-08-14 17:31:36.832984492 +0200 | |
169 | +++ gdb-7.4.91.20120814/gdb/solib.c 2012-08-14 17:34:44.272746583 +0200 | |
170 | @@ -1226,6 +1226,42 @@ no_shared_libraries (char *ignored, int | |
171 | objfile_purge_solibs (); | |
172 | } | |
173 | ||
174 | +/* See solib.h. */ | |
175 | + | |
176 | +void | |
177 | +handle_solib_event (bpstat bs) | |
178 | +{ | |
179 | + struct target_so_ops *ops = solib_ops (target_gdbarch); | |
180 | + | |
181 | + if (ops->handle_solib_event != NULL) | |
182 | + ops->handle_solib_event (bs); | |
183 | + | |
184 | + clear_program_space_solib_cache (current_inferior ()->pspace); | |
185 | + | |
186 | + /* Check for any newly added shared libraries if we're supposed to | |
187 | + be adding them automatically. Switch terminal for any messages | |
188 | + produced by breakpoint_re_set. */ | |
189 | + target_terminal_ours_for_output (); | |
190 | +#ifdef SOLIB_ADD | |
191 | + SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add); | |
192 | +#else | |
193 | + solib_add (NULL, 0, ¤t_target, auto_solib_add); | |
194 | +#endif | |
195 | + target_terminal_inferior (); | |
196 | +} | |
197 | + | |
198 | +/* See solib.h. */ | |
199 | + | |
200 | +void | |
201 | +update_solib_breakpoints (void) | |
202 | +{ | |
203 | + struct target_so_ops *ops = solib_ops (target_gdbarch); | |
204 | + | |
205 | + if (ops->update_breakpoints != NULL) | |
206 | + ops->update_breakpoints (); | |
207 | +} | |
208 | + | |
209 | + | |
210 | /* Reload shared libraries, but avoid reloading the same symbol file | |
211 | we already have loaded. */ | |
212 | ||
213 | Index: gdb-7.4.91.20120814/gdb/solist.h | |
214 | =================================================================== | |
215 | --- gdb-7.4.91.20120814.orig/gdb/solist.h 2012-01-04 09:17:11.000000000 +0100 | |
216 | +++ gdb-7.4.91.20120814/gdb/solist.h 2012-08-14 17:34:44.273746584 +0200 | |
217 | @@ -23,6 +23,8 @@ | |
218 | #define SO_NAME_MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */ | |
219 | /* For domain_enum domain. */ | |
220 | #include "symtab.h" | |
221 | +/* For bpstat. */ | |
222 | +#include "breakpoint.h" | |
223 | ||
224 | /* Forward declaration for target specific link map information. This | |
225 | struct is opaque to all but the target specific file. */ | |
226 | @@ -149,6 +151,20 @@ struct target_so_ops | |
227 | core file (in particular, for readonly sections). */ | |
228 | int (*keep_data_in_core) (CORE_ADDR vaddr, | |
229 | unsigned long size); | |
230 | + | |
231 | + /* Target-specific handling of solib events. For targets which | |
232 | + handle solib events using breakpoints a valid bpstat must be | |
233 | + passed. Targets which handle solib events using some other | |
234 | + mechanism should pass NULL. This pointer can be NULL, in which | |
235 | + case no specific handling is necessary for this target. */ | |
236 | + void (*handle_solib_event) (bpstat bs); | |
237 | + | |
238 | + /* Enable or disable optional solib event breakpoints as | |
239 | + appropriate. This should be called whenever | |
240 | + stop_on_solib_events is changed. This pointer can be | |
241 | + NULL, in which case no enabling or disabling is necessary | |
242 | + for this target. */ | |
243 | + void (*update_breakpoints) (void); | |
244 | }; | |
245 | ||
246 | /* Free the memory associated with a (so_list *). */ | |
247 | Index: gdb-7.4.91.20120814/gdb/infrun.c | |
248 | =================================================================== | |
249 | --- gdb-7.4.91.20120814.orig/gdb/infrun.c 2012-08-14 17:33:16.249955007 +0200 | |
250 | +++ gdb-7.4.91.20120814/gdb/infrun.c 2012-08-14 17:34:44.276746583 +0200 | |
251 | @@ -361,6 +361,16 @@ static struct symbol *step_start_functio | |
252 | /* Nonzero if we want to give control to the user when we're notified | |
253 | of shared library events by the dynamic linker. */ | |
254 | int stop_on_solib_events; | |
255 | + | |
256 | +/* Enable or disable optional shared library event breakpoints | |
257 | + as appropriate when the above flag is changed. */ | |
258 | + | |
259 | +static void | |
260 | +set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c) | |
261 | +{ | |
262 | + update_solib_breakpoints (); | |
263 | +} | |
264 | + | |
265 | static void | |
266 | show_stop_on_solib_events (struct ui_file *file, int from_tty, | |
267 | struct cmd_list_element *c, const char *value) | |
268 | @@ -3321,7 +3331,7 @@ handle_inferior_event (struct execution_ | |
269 | context_switch (ecs->ptid); | |
270 | regcache = get_thread_regcache (ecs->ptid); | |
271 | ||
272 | - handle_solib_event (); | |
273 | + handle_solib_event (NULL); | |
274 | ||
275 | ecs->event_thread->control.stop_bpstat | |
276 | = bpstat_stop_status (get_regcache_aspace (regcache), | |
277 | @@ -7226,7 +7236,7 @@ Show stopping for shared library events. | |
278 | If nonzero, gdb will give control to the user when the dynamic linker\n\ | |
279 | notifies gdb of shared library events. The most common event of interest\n\ | |
280 | to the user would be loading/unloading of a new library."), | |
281 | - NULL, | |
282 | + set_stop_on_solib_events, | |
283 | show_stop_on_solib_events, | |
284 | &setlist, &showlist); | |
285 | ||
286 | Index: gdb-7.4.91.20120814/gdb/solib-svr4.c | |
287 | =================================================================== | |
288 | --- gdb-7.4.91.20120814.orig/gdb/solib-svr4.c 2012-08-14 17:34:39.346752840 +0200 | |
289 | +++ gdb-7.4.91.20120814/gdb/solib-svr4.c 2012-08-14 17:35:42.635732596 +0200 | |
290 | @@ -47,10 +47,12 @@ | |
291 | #include "auxv.h" | |
292 | #include "exceptions.h" | |
293 | #include "gdb_bfd.h" | |
294 | +#include "probe.h" | |
295 | ||
296 | static struct link_map_offsets *svr4_fetch_link_map_offsets (void); | |
297 | static int svr4_have_link_map_offsets (void); | |
298 | static void svr4_relocate_main_executable (void); | |
299 | +static struct so_list *namespace_table_flatten (htab_t namespace_table); | |
300 | ||
301 | /* Link map info to include in an allocated so_list entry. */ | |
302 | ||
303 | @@ -71,6 +73,16 @@ struct lm_info | |
304 | ||
305 | /* Values read in from inferior's fields of the same name. */ | |
306 | CORE_ADDR l_ld, l_next, l_prev, l_name; | |
307 | + | |
308 | + /* Numeric link-map ID of the namespace this object is loaded | |
309 | + into. This value is only valid when using the probes-based | |
310 | + interface. */ | |
311 | + LONGEST lmid; | |
312 | + | |
313 | + /* Nonzero if the namespace list this object is loaded into is the | |
314 | + application's initial namespace (LM_ID_BASE). This value is | |
315 | + only valid when using the probes-based interface. */ | |
316 | + unsigned int in_initial_ns : 1; | |
317 | }; | |
318 | ||
319 | /* On SVR4 systems, a list of symbols in the dynamic linker where | |
320 | @@ -107,6 +119,53 @@ static const char * const main_name_lis | |
321 | NULL | |
322 | }; | |
323 | ||
324 | +/* What to do with the namespace table when a probe stop occurs. */ | |
325 | + | |
326 | +enum probe_action | |
327 | + { | |
328 | + /* Something went seriously wrong. Stop using probes and | |
329 | + revert to using the older interface. */ | |
330 | + NAMESPACE_TABLE_INVALIDATE, | |
331 | + | |
332 | + /* No action is required. This namespace is still valid. */ | |
333 | + NAMESPACE_NO_ACTION, | |
334 | + | |
335 | + /* This namespace should be reloaded entirely. */ | |
336 | + NAMESPACE_RELOAD, | |
337 | + | |
338 | + /* Attempt to incrementally update this namespace. If the | |
339 | + update fails or is not possible, fall back to reloading | |
340 | + the namespace in full. */ | |
341 | + NAMESPACE_UPDATE_OR_RELOAD, | |
342 | + }; | |
343 | + | |
344 | +/* A probe's name and its associated action. */ | |
345 | + | |
346 | +struct probe_info | |
347 | +{ | |
348 | + /* The name of the probe. */ | |
349 | + const char *name; | |
350 | + | |
351 | + /* What to do with the namespace table when a probe stop occurs. */ | |
352 | + enum probe_action action; | |
353 | +}; | |
354 | + | |
355 | +/* A list of named probes and their associated actions. If all | |
356 | + probes are present in the dynamic linker then the probes-based | |
357 | + interface will be used. */ | |
358 | + | |
359 | +static const struct probe_info probe_info[] = | |
360 | +{ | |
361 | + { "init_start", NAMESPACE_NO_ACTION }, | |
362 | + { "init_complete", NAMESPACE_RELOAD }, | |
363 | + { "map_start", NAMESPACE_NO_ACTION }, | |
364 | + { "reloc_complete", NAMESPACE_UPDATE_OR_RELOAD }, | |
365 | + { "unmap_start", NAMESPACE_NO_ACTION }, | |
366 | + { "unmap_complete", NAMESPACE_RELOAD }, | |
367 | +}; | |
368 | + | |
369 | +#define NUM_PROBES ARRAY_SIZE (probe_info) | |
370 | + | |
371 | /* Per pspace SVR4 specific data. */ | |
372 | ||
373 | struct svr4_info | |
374 | @@ -129,17 +188,58 @@ struct svr4_info | |
375 | CORE_ADDR interp_text_sect_high; | |
376 | CORE_ADDR interp_plt_sect_low; | |
377 | CORE_ADDR interp_plt_sect_high; | |
378 | + | |
379 | + /* Nonzero if we are using the probes-based interface. */ | |
380 | + unsigned int using_probes : 1; | |
381 | + | |
382 | + /* Named probes in the dynamic linker. */ | |
383 | + VEC (probe_p) *probes[NUM_PROBES]; | |
384 | + | |
385 | + /* Table of dynamic linker namespaces, used by the probes-based | |
386 | + interface. */ | |
387 | + htab_t namespace_table; | |
388 | }; | |
389 | ||
390 | /* Per-program-space data key. */ | |
391 | static const struct program_space_data *solib_svr4_pspace_data; | |
392 | ||
393 | +/* Free any allocated probe vectors. */ | |
394 | + | |
395 | +static void | |
396 | +free_probes (struct svr4_info *info) | |
397 | +{ | |
398 | + int i; | |
399 | + | |
400 | + for (i = 0; i < NUM_PROBES; i++) | |
401 | + VEC_free (probe_p, info->probes[i]); | |
402 | + | |
403 | + memset (info->probes, 0, sizeof (info->probes)); | |
404 | +} | |
405 | + | |
406 | +/* Free the namespace table. */ | |
407 | + | |
408 | +static void | |
409 | +free_namespace_table (struct svr4_info *info) | |
410 | +{ | |
411 | + if (info->namespace_table == NULL) | |
412 | + return; | |
413 | + | |
414 | + htab_delete (info->namespace_table); | |
415 | + info->namespace_table = NULL; | |
416 | +} | |
417 | + | |
418 | static void | |
419 | svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) | |
420 | { | |
421 | struct svr4_info *info; | |
422 | ||
423 | info = program_space_data (pspace, solib_svr4_pspace_data); | |
424 | + if (info == NULL) | |
425 | + return; | |
426 | + | |
427 | + free_probes (info); | |
428 | + free_namespace_table (info); | |
429 | + | |
430 | xfree (info); | |
431 | } | |
432 | ||
433 | @@ -188,10 +288,21 @@ svr4_same_1 (const char *gdb_so_name, co | |
434 | return 0; | |
435 | } | |
436 | ||
437 | +/* Return non-zero if GDB and INFERIOR represent the same shared | |
438 | + library. */ | |
439 | + | |
440 | static int | |
441 | svr4_same (struct so_list *gdb, struct so_list *inferior) | |
442 | { | |
443 | - return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name)); | |
444 | + struct svr4_info *info = get_svr4_info (); | |
445 | + | |
446 | + if (info->using_probes) | |
447 | + { | |
448 | + if (gdb->lm_info->lmid != inferior->lm_info->lmid) | |
449 | + return 0; | |
450 | + } | |
451 | + | |
452 | + return svr4_same_1 (gdb->so_original_name, inferior->so_original_name); | |
453 | } | |
454 | ||
455 | static struct lm_info * | |
456 | @@ -322,18 +433,26 @@ lm_addr_check (struct so_list *so, bfd * | |
457 | } | |
458 | else | |
459 | { | |
460 | - /* There is no way to verify the library file matches. prelink | |
461 | - can during prelinking of an unprelinked file (or unprelinking | |
462 | - of a prelinked file) shift the DYNAMIC segment by arbitrary | |
463 | - offset without any page size alignment. There is no way to | |
464 | - find out the ELF header and/or Program Headers for a limited | |
465 | - verification if it they match. One could do a verification | |
466 | - of the DYNAMIC segment. Still the found address is the best | |
467 | - one GDB could find. */ | |
468 | - | |
469 | - warning (_(".dynamic section for \"%s\" " | |
470 | - "is not at the expected address " | |
471 | - "(wrong library or version mismatch?)"), so->so_name); | |
472 | + struct svr4_info *info = get_svr4_info (); | |
473 | + | |
474 | + if (!info->using_probes || so->lm_info->in_initial_ns) | |
475 | + { | |
476 | + /* There is no way to verify the library file | |
477 | + matches. prelink can during prelinking of an | |
478 | + unprelinked file (or unprelinking of a prelinked | |
479 | + file) shift the DYNAMIC segment by arbitrary | |
480 | + offset without any page size alignment. There is | |
481 | + no way to find out the ELF header and/or Program | |
482 | + Headers for a limited verification if it they | |
483 | + match. One could do a verification of the | |
484 | + DYNAMIC segment. Still the found address is the | |
485 | + best one GDB could find. */ | |
486 | + | |
487 | + warning (_(".dynamic section for \"%s\" " | |
488 | + "is not at the expected address " | |
489 | + "(wrong library or version mismatch?)"), | |
490 | + so->so_name); | |
491 | + } | |
492 | } | |
493 | } | |
494 | ||
495 | @@ -775,16 +894,10 @@ locate_base (struct svr4_info *info) | |
496 | return info->debug_base; | |
497 | } | |
498 | ||
499 | -/* Find the first element in the inferior's dynamic link map, and | |
500 | - return its address in the inferior. Return zero if the address | |
501 | - could not be determined. | |
502 | - | |
503 | - FIXME: Perhaps we should validate the info somehow, perhaps by | |
504 | - checking r_version for a known version number, or r_state for | |
505 | - RT_CONSISTENT. */ | |
506 | +/* Read the r_map field from the supplied r_debug structure. */ | |
507 | ||
508 | static CORE_ADDR | |
509 | -solib_svr4_r_map (struct svr4_info *info) | |
510 | +r_map_from_debug_base (CORE_ADDR debug_base) | |
511 | { | |
512 | struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); | |
513 | struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; | |
514 | @@ -793,13 +906,27 @@ solib_svr4_r_map (struct svr4_info *info | |
515 | ||
516 | TRY_CATCH (ex, RETURN_MASK_ERROR) | |
517 | { | |
518 | - addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset, | |
519 | + addr = read_memory_typed_address (debug_base + lmo->r_map_offset, | |
520 | ptr_type); | |
521 | } | |
522 | exception_print (gdb_stderr, ex); | |
523 | return addr; | |
524 | } | |
525 | ||
526 | +/* Find the first element in the inferior's dynamic link map, and | |
527 | + return its address in the inferior. Return zero if the address | |
528 | + could not be determined. | |
529 | + | |
530 | + FIXME: Perhaps we should validate the info somehow, perhaps by | |
531 | + checking r_version for a known version number, or r_state for | |
532 | + RT_CONSISTENT. */ | |
533 | + | |
534 | +static CORE_ADDR | |
535 | +solib_svr4_r_map (struct svr4_info *info) | |
536 | +{ | |
537 | + return r_map_from_debug_base (info->debug_base); | |
538 | +} | |
539 | + | |
540 | /* Find r_brk from the inferior's debug base. */ | |
541 | ||
542 | static CORE_ADDR | |
543 | @@ -1164,15 +1291,17 @@ svr4_default_sos (void) | |
544 | return new; | |
545 | } | |
546 | ||
547 | -/* Read the whole inferior libraries chain starting at address LM. Add the | |
548 | - entries to the tail referenced by LINK_PTR_PTR. Ignore the first entry if | |
549 | - IGNORE_FIRST and set global MAIN_LM_ADDR according to it. */ | |
550 | +/* Read the whole inferior libraries chain starting at address LM. | |
551 | + Expect the first entry in the chain's previous entry to be PREV_LM. | |
552 | + Add the entries to the tail referenced by LINK_PTR_PTR. Ignore the | |
553 | + first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according | |
554 | + to it. Returns nonzero upon success. */ | |
555 | ||
556 | -static void | |
557 | -svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, | |
558 | - int ignore_first) | |
559 | +static int | |
560 | +svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm, | |
561 | + struct so_list ***link_ptr_ptr, int ignore_first) | |
562 | { | |
563 | - CORE_ADDR prev_lm = 0, next_lm; | |
564 | + CORE_ADDR next_lm; | |
565 | ||
566 | for (; lm != 0; prev_lm = lm, lm = next_lm) | |
567 | { | |
568 | @@ -1189,7 +1318,7 @@ svr4_read_so_list (CORE_ADDR lm, struct | |
569 | if (new->lm_info == NULL) | |
570 | { | |
571 | do_cleanups (old_chain); | |
572 | - break; | |
573 | + return 0; | |
574 | } | |
575 | ||
576 | next_lm = new->lm_info->l_next; | |
577 | @@ -1200,7 +1329,7 @@ svr4_read_so_list (CORE_ADDR lm, struct | |
578 | paddress (target_gdbarch, prev_lm), | |
579 | paddress (target_gdbarch, new->lm_info->l_prev)); | |
580 | do_cleanups (old_chain); | |
581 | - break; | |
582 | + return 0; | |
583 | } | |
584 | ||
585 | /* For SVR4 versions, the first entry in the link map is for the | |
586 | @@ -1295,20 +1424,61 @@ svr4_read_so_list (CORE_ADDR lm, struct | |
587 | **link_ptr_ptr = new; | |
588 | *link_ptr_ptr = &new->next; | |
589 | } | |
590 | + | |
591 | + return 1; | |
592 | } | |
593 | ||
594 | -/* Implement the "current_sos" target_so_ops method. */ | |
595 | +/* Read the list of loaded libraries from the dynamic linker's base | |
596 | + structure. */ | |
597 | ||
598 | static struct so_list * | |
599 | -svr4_current_sos (void) | |
600 | +svr4_current_sos_from_debug_base (void) | |
601 | { | |
602 | + struct svr4_info *info = get_svr4_info (); | |
603 | CORE_ADDR lm; | |
604 | struct so_list *head = NULL; | |
605 | struct so_list **link_ptr = &head; | |
606 | - struct svr4_info *info; | |
607 | struct cleanup *back_to; | |
608 | int ignore_first; | |
609 | + | |
610 | + gdb_assert (info->debug_base); | |
611 | + | |
612 | + /* Assume that everything is a library if the dynamic loader was loaded | |
613 | + late by a static executable. */ | |
614 | + if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) | |
615 | + ignore_first = 0; | |
616 | + else | |
617 | + ignore_first = 1; | |
618 | + | |
619 | + back_to = make_cleanup (svr4_free_library_list, &head); | |
620 | + | |
621 | + /* Walk the inferior's link map list, and build our list of | |
622 | + `struct so_list' nodes. */ | |
623 | + lm = solib_svr4_r_map (info); | |
624 | + if (lm) | |
625 | + svr4_read_so_list (lm, 0, &link_ptr, ignore_first); | |
626 | + | |
627 | + /* On Solaris, the dynamic linker is not in the normal list of | |
628 | + shared objects, so make sure we pick it up too. Having | |
629 | + symbol information for the dynamic linker is quite crucial | |
630 | + for skipping dynamic linker resolver code. */ | |
631 | + lm = solib_svr4_r_ldsomap (info); | |
632 | + if (lm) | |
633 | + svr4_read_so_list (lm, 0, &link_ptr, 0); | |
634 | + | |
635 | + discard_cleanups (back_to); | |
636 | + | |
637 | + return head; | |
638 | +} | |
639 | + | |
640 | +/* Implement the "current_sos" target_so_ops method. */ | |
641 | + | |
642 | +static struct so_list * | |
643 | +svr4_current_sos (void) | |
644 | +{ | |
645 | + struct svr4_info *info; | |
646 | struct svr4_library_list library_list; | |
647 | + struct so_list *result; | |
648 | ||
649 | /* Fall back to manual examination of the target if the packet is not | |
650 | supported or gdbserver failed to find DT_DEBUG. gdb.server/solib-list.exp | |
651 | @@ -1331,6 +1501,10 @@ svr4_current_sos (void) | |
652 | ||
653 | info = get_svr4_info (); | |
654 | ||
655 | + /* If we have a namespace table then return a flattened copy. */ | |
656 | + if (info->namespace_table != NULL) | |
657 | + return namespace_table_flatten (info->namespace_table); | |
658 | + | |
659 | /* Always locate the debug struct, in case it has moved. */ | |
660 | info->debug_base = 0; | |
661 | locate_base (info); | |
662 | @@ -1340,35 +1514,12 @@ svr4_current_sos (void) | |
663 | if (! info->debug_base) | |
664 | return svr4_default_sos (); | |
665 | ||
666 | - /* Assume that everything is a library if the dynamic loader was loaded | |
667 | - late by a static executable. */ | |
668 | - if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) | |
669 | - ignore_first = 0; | |
670 | - else | |
671 | - ignore_first = 1; | |
672 | - | |
673 | - back_to = make_cleanup (svr4_free_library_list, &head); | |
674 | - | |
675 | - /* Walk the inferior's link map list, and build our list of | |
676 | - `struct so_list' nodes. */ | |
677 | - lm = solib_svr4_r_map (info); | |
678 | - if (lm) | |
679 | - svr4_read_so_list (lm, &link_ptr, ignore_first); | |
680 | - | |
681 | - /* On Solaris, the dynamic linker is not in the normal list of | |
682 | - shared objects, so make sure we pick it up too. Having | |
683 | - symbol information for the dynamic linker is quite crucial | |
684 | - for skipping dynamic linker resolver code. */ | |
685 | - lm = solib_svr4_r_ldsomap (info); | |
686 | - if (lm) | |
687 | - svr4_read_so_list (lm, &link_ptr, 0); | |
688 | - | |
689 | - discard_cleanups (back_to); | |
690 | + result = svr4_current_sos_from_debug_base (); | |
691 | ||
692 | - if (head == NULL) | |
693 | + if (result == NULL) | |
694 | return svr4_default_sos (); | |
695 | ||
696 | - return head; | |
697 | + return result; | |
698 | } | |
699 | ||
700 | /* Get the address of the link_map for a given OBJFILE. */ | |
701 | @@ -1450,6 +1601,498 @@ exec_entry_point (struct bfd *abfd, stru | |
702 | targ); | |
703 | } | |
704 | ||
705 | +/* A probe and its associated information structure. */ | |
706 | + | |
707 | +struct probe_and_info | |
708 | +{ | |
709 | + /* The probe. */ | |
710 | + struct probe *probe; | |
711 | + | |
712 | + /* The probe_info from which the probe was created. */ | |
713 | + const struct probe_info *info; | |
714 | +}; | |
715 | + | |
716 | +/* Get the solib event probe at the specified location, and the | |
717 | + probe_info the probe was created with. Fills in RESULT and | |
718 | + returns nonzero if a solib event probe was found at the | |
719 | + specified location. Returns zero if no solib event probe | |
720 | + was found. */ | |
721 | + | |
722 | +static int | |
723 | +solib_event_probe_at (struct svr4_info *info, struct bp_location *loc, | |
724 | + struct probe_and_info *result) | |
725 | +{ | |
726 | + int i; | |
727 | + | |
728 | + for (i = 0; i < NUM_PROBES; i++) | |
729 | + { | |
730 | + struct probe *probe; | |
731 | + int ix; | |
732 | + | |
733 | + for (ix = 0; VEC_iterate (probe_p, info->probes[i], ix, probe); ++ix) | |
734 | + { | |
735 | + if (loc->pspace == current_program_space | |
736 | + && loc->address == probe->address) | |
737 | + { | |
738 | + result->info = &probe_info[i]; | |
739 | + result->probe = probe; | |
740 | + | |
741 | + return 1; | |
742 | + } | |
743 | + } | |
744 | + } | |
745 | + | |
746 | + return 0; | |
747 | +} | |
748 | + | |
749 | +/* Decide what action to take when the specified solib event probe is | |
750 | + hit. */ | |
751 | + | |
752 | +static enum probe_action | |
753 | +solib_event_probe_action (struct probe_and_info *pi) | |
754 | +{ | |
755 | + enum probe_action action; | |
756 | + unsigned probe_argc; | |
757 | + | |
758 | + action = pi->info->action; | |
759 | + if (action == NAMESPACE_NO_ACTION || action == NAMESPACE_TABLE_INVALIDATE) | |
760 | + return action; | |
761 | + | |
762 | + gdb_assert (action == NAMESPACE_RELOAD | |
763 | + || action == NAMESPACE_UPDATE_OR_RELOAD); | |
764 | + | |
765 | + /* Check that an appropriate number of arguments has been supplied. | |
766 | + We expect: | |
767 | + arg0: Lmid_t lmid (mandatory) | |
768 | + arg1: struct r_debug *debug_base (mandatory) | |
769 | + arg2: struct link_map *new (optional, for incremental updates) */ | |
770 | + probe_argc = get_probe_argument_count (pi->probe); | |
771 | + if (probe_argc == 2) | |
772 | + action = NAMESPACE_RELOAD; | |
773 | + else if (probe_argc < 2) | |
774 | + action = NAMESPACE_TABLE_INVALIDATE; | |
775 | + | |
776 | + return action; | |
777 | +} | |
778 | + | |
779 | +/* A namespace in the dynamic linker. */ | |
780 | + | |
781 | +struct namespace | |
782 | +{ | |
783 | + /* Numeric link-map ID of the namespace. */ | |
784 | + LONGEST lmid; | |
785 | + | |
786 | + /* List of objects loaded into the namespace. */ | |
787 | + struct so_list *solist; | |
788 | +}; | |
789 | + | |
790 | +/* Returns a hash code for the namespace referenced by p. */ | |
791 | + | |
792 | +static hashval_t | |
793 | +hash_namespace (const void *p) | |
794 | +{ | |
795 | + const struct namespace *ns = p; | |
796 | + | |
797 | + return (hashval_t) ns->lmid; | |
798 | +} | |
799 | + | |
800 | +/* Returns non-zero if the namespaces referenced by p1 and p2 | |
801 | + are equal. */ | |
802 | + | |
803 | +static int | |
804 | +equal_namespace (const void *p1, const void *p2) | |
805 | +{ | |
806 | + const struct namespace *ns1 = p1; | |
807 | + const struct namespace *ns2 = p2; | |
808 | + | |
809 | + return ns1->lmid == ns2->lmid; | |
810 | +} | |
811 | + | |
812 | +/* Free a namespace. */ | |
813 | + | |
814 | +static void | |
815 | +free_namespace (void *p) | |
816 | +{ | |
817 | + struct namespace *ns = p; | |
818 | + | |
819 | + svr4_free_library_list (ns->solist); | |
820 | + xfree (ns); | |
821 | +} | |
822 | + | |
823 | +/* Populate this namespace by reading the entire list of shared | |
824 | + objects from the inferior. Returns nonzero on success. */ | |
825 | + | |
826 | +static int | |
827 | +namespace_update_full (struct svr4_info *info, LONGEST lmid, | |
828 | + CORE_ADDR debug_base, int is_initial_ns) | |
829 | +{ | |
830 | + struct so_list *result = NULL, *so; | |
831 | + struct namespace lookup, *ns; | |
832 | + void **slot; | |
833 | + | |
834 | + /* Read the list of shared objects from the inferior. The | |
835 | + initial namespace requires extra processing and is handled | |
836 | + separately. */ | |
837 | + if (is_initial_ns) | |
838 | + { | |
839 | + result = svr4_current_sos_from_debug_base (); | |
840 | + } | |
841 | + else | |
842 | + { | |
843 | + CORE_ADDR lm = r_map_from_debug_base (debug_base); | |
844 | + struct so_list **link_ptr = &result; | |
845 | + | |
846 | + if (!svr4_read_so_list (lm, 0, &link_ptr, 0)) | |
847 | + return 0; | |
848 | + } | |
849 | + | |
850 | + /* If the namespace is empty then delete it from the table. */ | |
851 | + if (result == NULL) | |
852 | + { | |
853 | + if (info->namespace_table != NULL) | |
854 | + { | |
855 | + lookup.lmid = lmid; | |
856 | + htab_remove_elt (info->namespace_table, &lookup); | |
857 | + } | |
858 | + | |
859 | + return 1; | |
860 | + } | |
861 | + | |
862 | + /* Fill in the link-map IDs and initial namespace flags. */ | |
863 | + for (so = result; so; so = so->next) | |
864 | + { | |
865 | + so->lm_info->lmid = lmid; | |
866 | + so->lm_info->in_initial_ns = is_initial_ns; | |
867 | + } | |
868 | + | |
869 | + /* Create the namespace table, if necessary. */ | |
870 | + if (info->namespace_table == NULL) | |
871 | + { | |
872 | + info->namespace_table = htab_create_alloc (1, hash_namespace, | |
873 | + equal_namespace, | |
874 | + free_namespace, | |
875 | + xcalloc, xfree); | |
876 | + } | |
877 | + | |
878 | + /* Update the namespace table with our new list. */ | |
879 | + lookup.lmid = lmid; | |
880 | + slot = htab_find_slot (info->namespace_table, &lookup, INSERT); | |
881 | + if (*slot == HTAB_EMPTY_ENTRY) | |
882 | + { | |
883 | + ns = XCNEW (struct namespace); | |
884 | + ns->lmid = lmid; | |
885 | + *slot = ns; | |
886 | + } | |
887 | + else | |
888 | + { | |
889 | + ns = *slot; | |
890 | + svr4_free_library_list (ns->solist); | |
891 | + } | |
892 | + ns->solist = result; | |
893 | + | |
894 | + return 1; | |
895 | +} | |
896 | + | |
897 | +/* Update this namespace starting from the link-map entry passed by | |
898 | + the linker in the probe's third argument. Returns nonzero if the | |
899 | + list was successfully updated, or zero to indicate failure. */ | |
900 | + | |
901 | +static int | |
902 | +namespace_update_incremental (struct svr4_info *info, LONGEST lmid, | |
903 | + CORE_ADDR lm, int is_initial_ns) | |
904 | +{ | |
905 | + struct namespace lookup, *ns; | |
906 | + struct so_list *tail, **link, *so; | |
907 | + struct value *val; | |
908 | + | |
909 | + /* Find our namespace in the table. */ | |
910 | + if (info->namespace_table == NULL) | |
911 | + return 0; | |
912 | + | |
913 | + lookup.lmid = lmid; | |
914 | + ns = htab_find (info->namespace_table, &lookup); | |
915 | + if (ns == NULL) | |
916 | + return 0; | |
917 | + | |
918 | + /* Walk to the end of the list. */ | |
919 | + tail = ns->solist; | |
920 | + if (tail == NULL) | |
921 | + return 0; | |
922 | + | |
923 | + while (tail->next) | |
924 | + tail = tail->next; | |
925 | + link = &tail->next; | |
926 | + | |
927 | + /* Read the new objects. */ | |
928 | + if (!svr4_read_so_list (lm, tail->lm_info->lm_addr, &link, 0)) | |
929 | + return 0; | |
930 | + | |
931 | + /* Fill in the link-map IDs and initial namespace flags. */ | |
932 | + for (so = tail; so; so = so->next) | |
933 | + { | |
934 | + so->lm_info->lmid = lmid; | |
935 | + so->lm_info->in_initial_ns = is_initial_ns; | |
936 | + } | |
937 | + | |
938 | + return 1; | |
939 | +} | |
940 | + | |
941 | +/* Update the namespace table as appropriate when using the | |
942 | + probes-based linker interface. Do nothing if using the | |
943 | + standard interface. */ | |
944 | + | |
945 | +static void | |
946 | +svr4_handle_solib_event (bpstat bs) | |
947 | +{ | |
948 | + struct svr4_info *info = get_svr4_info (); | |
949 | + struct probe_and_info buf, *pi = &buf; | |
950 | + enum probe_action action; | |
951 | + struct value *val; | |
952 | + LONGEST lmid; | |
953 | + CORE_ADDR debug_base, lm = 0; | |
954 | + int is_initial_ns; | |
955 | + | |
956 | + /* It is possible that this function will be called incorrectly | |
957 | + by the handle_solib_event in handle_inferior_event if GDB goes | |
958 | + fully multi-target. */ | |
959 | + gdb_assert (bs != NULL); | |
960 | + | |
961 | + if (!info->using_probes) | |
962 | + return; | |
963 | + | |
964 | + if (!solib_event_probe_at (info, bs->bp_location_at, pi)) | |
965 | + goto error; | |
966 | + | |
967 | + action = solib_event_probe_action (pi); | |
968 | + if (action == NAMESPACE_TABLE_INVALIDATE) | |
969 | + goto error; | |
970 | + | |
971 | + if (action == NAMESPACE_NO_ACTION) | |
972 | + return; | |
973 | + | |
974 | + val = evaluate_probe_argument (pi->probe, 0); | |
975 | + if (val == NULL) | |
976 | + goto error; | |
977 | + | |
978 | + lmid = value_as_long (val); | |
979 | + | |
980 | + val = evaluate_probe_argument (pi->probe, 1); | |
981 | + if (val == NULL) | |
982 | + goto error; | |
983 | + | |
984 | + debug_base = value_as_address (val); | |
985 | + if (debug_base == 0) | |
986 | + goto error; | |
987 | + | |
988 | + /* Always locate the debug struct, in case it moved. */ | |
989 | + info->debug_base = 0; | |
990 | + if (locate_base (info) == 0) | |
991 | + goto error; | |
992 | + | |
993 | + is_initial_ns = (debug_base == info->debug_base); | |
994 | + | |
995 | + if (action == NAMESPACE_UPDATE_OR_RELOAD) | |
996 | + { | |
997 | + val = evaluate_probe_argument (pi->probe, 2); | |
998 | + if (val != NULL) | |
999 | + lm = value_as_address (val); | |
1000 | + | |
1001 | + if (lm == 0) | |
1002 | + action = NAMESPACE_RELOAD; | |
1003 | + } | |
1004 | + | |
1005 | + if (action == NAMESPACE_UPDATE_OR_RELOAD) | |
1006 | + { | |
1007 | + if (namespace_update_incremental (info, lmid, lm, is_initial_ns)) | |
1008 | + return; | |
1009 | + | |
1010 | + action = NAMESPACE_RELOAD; | |
1011 | + } | |
1012 | + | |
1013 | + gdb_assert (action == NAMESPACE_RELOAD); | |
1014 | + | |
1015 | + if (namespace_update_full (info, lmid, debug_base, is_initial_ns)) | |
1016 | + return; | |
1017 | + | |
1018 | + error: | |
1019 | + | |
1020 | + /* We should never reach here, but if we do we disable the | |
1021 | + probes interface and revert to the original interface. | |
1022 | + We don't reset the breakpoints as the ones we've set up | |
1023 | + are adequate. */ | |
1024 | + warning (_("Probes-based dynamic linker interface failed.\n" | |
1025 | + "Reverting to original interface.\n")); | |
1026 | + | |
1027 | + free_namespace_table (info); | |
1028 | + free_probes (info); | |
1029 | + info->using_probes = 0; | |
1030 | +} | |
1031 | + | |
1032 | +/* Helper function for namespace_table_flatten. */ | |
1033 | + | |
1034 | +static int | |
1035 | +namespace_table_flatten_helper (void **slot, void *arg) | |
1036 | +{ | |
1037 | + struct namespace *ns = (struct namespace *) *slot; | |
1038 | + struct so_list *src = ns->solist; | |
1039 | + struct so_list **link = (struct so_list **) arg; | |
1040 | + | |
1041 | + while (*link) | |
1042 | + link = &(*link)->next; | |
1043 | + | |
1044 | + while (src != NULL) | |
1045 | + { | |
1046 | + struct so_list *dst; | |
1047 | + | |
1048 | + dst = xmalloc (sizeof (struct so_list)); | |
1049 | + memcpy (dst, src, sizeof (struct so_list)); | |
1050 | + | |
1051 | + dst->lm_info = xmalloc (sizeof (struct lm_info)); | |
1052 | + memcpy (dst->lm_info, src->lm_info, sizeof (struct lm_info)); | |
1053 | + | |
1054 | + *link = dst; | |
1055 | + link = &dst->next; | |
1056 | + | |
1057 | + src = src->next; | |
1058 | + } | |
1059 | + | |
1060 | + *link = NULL; | |
1061 | + | |
1062 | + return 1; /* Continue traversal. */ | |
1063 | +} | |
1064 | + | |
1065 | +/* Flatten the namespace table into a single list. */ | |
1066 | + | |
1067 | +static struct so_list * | |
1068 | +namespace_table_flatten (htab_t namespace_table) | |
1069 | +{ | |
1070 | + struct so_list *dst = NULL; | |
1071 | + | |
1072 | + htab_traverse (namespace_table, namespace_table_flatten_helper, &dst); | |
1073 | + | |
1074 | + return dst; | |
1075 | +} | |
1076 | + | |
1077 | +/* Helper function for svr4_update_solib_event_breakpoints. */ | |
1078 | + | |
1079 | +static int | |
1080 | +svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg) | |
1081 | +{ | |
1082 | + struct svr4_info *info = get_svr4_info (); | |
1083 | + struct bp_location *loc; | |
1084 | + | |
1085 | + if (b->type != bp_shlib_event) | |
1086 | + return 0; /* Continue iterating. */ | |
1087 | + | |
1088 | + for (loc = b->loc; loc; loc = loc->next) | |
1089 | + { | |
1090 | + struct probe_and_info buf, *pi = &buf; | |
1091 | + | |
1092 | + if (solib_event_probe_at (info, loc, pi)) | |
1093 | + { | |
1094 | + if (pi->info->action == NAMESPACE_NO_ACTION) | |
1095 | + b->enable_state = (stop_on_solib_events | |
1096 | + ? bp_enabled : bp_disabled); | |
1097 | + | |
1098 | + return 0; /* Continue iterating. */ | |
1099 | + } | |
1100 | + } | |
1101 | + | |
1102 | + return 0; /* Continue iterating. */ | |
1103 | +} | |
1104 | + | |
1105 | +/* Enable or disable optional solib event breakpoints as appropriate. | |
1106 | + Called whenever stop_on_solib_events is changed. */ | |
1107 | + | |
1108 | +static void | |
1109 | +svr4_update_solib_event_breakpoints (void) | |
1110 | +{ | |
1111 | + struct svr4_info *info = get_svr4_info (); | |
1112 | + | |
1113 | + if (info->using_probes) | |
1114 | + iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL); | |
1115 | +} | |
1116 | + | |
1117 | +/* Both the SunOS and the SVR4 dynamic linkers call a marker function | |
1118 | + before and after mapping and unmapping shared libraries. The sole | |
1119 | + purpose of this method is to allow debuggers to set a breakpoint so | |
1120 | + they can track these changes. | |
1121 | + | |
1122 | + Some versions of the glibc dynamic linker contain named probes | |
1123 | + to allow more fine grained stopping. Given the address of the | |
1124 | + original marker function, this function attempts to find these | |
1125 | + probes, and if found, sets breakpoints on those instead. If the | |
1126 | + probes aren't found, a single breakpoint is set on the original | |
1127 | + marker function. */ | |
1128 | + | |
1129 | +static void | |
1130 | +svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch, | |
1131 | + CORE_ADDR address) | |
1132 | +{ | |
1133 | + struct svr4_info *info = get_svr4_info (); | |
1134 | + struct obj_section *os; | |
1135 | + | |
1136 | + os = find_pc_section (address); | |
1137 | + if (os != NULL) | |
1138 | + { | |
1139 | + int with_prefix; | |
1140 | + | |
1141 | + for (with_prefix = 0; with_prefix <= 1; with_prefix++) | |
1142 | + { | |
1143 | + int all_probes_found = 1; | |
1144 | + int i; | |
1145 | + | |
1146 | + for (i = 0; i < NUM_PROBES; i++) | |
1147 | + { | |
1148 | + char name[32] = { '\0' }; | |
1149 | + | |
1150 | + /* Fedora 17, RHEL 6.2, and RHEL 6.3 shipped with an | |
1151 | + early version of the probes code in which the probes' | |
1152 | + names were prefixed with "rtld_". The locations and | |
1153 | + arguments of the probes are otherwise the same, so we | |
1154 | + check for the prefixed version if the unprefixed | |
1155 | + probes are not found. */ | |
1156 | + | |
1157 | + if (with_prefix) | |
1158 | + strncat (name, "rtld_", sizeof (name)); | |
1159 | + | |
1160 | + strncat (name, probe_info[i].name, sizeof (name) - sizeof ("rtld_")); | |
1161 | + | |
1162 | + info->probes[i] = find_probes_in_objfile (os->objfile, "rtld", | |
1163 | + name); | |
1164 | + | |
1165 | + if (!VEC_length (probe_p, info->probes[i])) | |
1166 | + { | |
1167 | + free_probes (info); | |
1168 | + all_probes_found = 0; | |
1169 | + break; | |
1170 | + } | |
1171 | + } | |
1172 | + | |
1173 | + if (all_probes_found) | |
1174 | + { | |
1175 | + info->using_probes = 1; | |
1176 | + | |
1177 | + for (i = 0; i < NUM_PROBES; i++) | |
1178 | + { | |
1179 | + struct probe *probe; | |
1180 | + int ix; | |
1181 | + | |
1182 | + for (ix = 0; | |
1183 | + VEC_iterate (probe_p, info->probes[i], ix, probe); | |
1184 | + ++ix) | |
1185 | + create_solib_event_breakpoint (gdbarch, probe->address); | |
1186 | + } | |
1187 | + | |
1188 | + svr4_update_solib_event_breakpoints (); | |
1189 | + return; | |
1190 | + } | |
1191 | + } | |
1192 | + } | |
1193 | + | |
1194 | + create_solib_event_breakpoint (gdbarch, address); | |
1195 | +} | |
1196 | + | |
1197 | /* Helper function for gdb_bfd_lookup_symbol. */ | |
1198 | ||
1199 | static int | |
1200 | @@ -1502,6 +2145,9 @@ enable_break (struct svr4_info *info, in | |
1201 | info->interp_text_sect_low = info->interp_text_sect_high = 0; | |
1202 | info->interp_plt_sect_low = info->interp_plt_sect_high = 0; | |
1203 | ||
1204 | + free_probes (info); | |
1205 | + info->using_probes = 0; | |
1206 | + | |
1207 | /* If we already have a shared library list in the target, and | |
1208 | r_debug contains r_brk, set the breakpoint there - this should | |
1209 | mean r_brk has already been relocated. Assume the dynamic linker | |
1210 | @@ -1533,7 +2179,7 @@ enable_break (struct svr4_info *info, in | |
1211 | That knowledge is encoded in the address, if it's Thumb the low bit | |
1212 | is 1. However, we've stripped that info above and it's not clear | |
1213 | what all the consequences are of passing a non-addr_bits_remove'd | |
1214 | - address to create_solib_event_breakpoint. The call to | |
1215 | + address to svr4_create_solib_event_breakpoints. The call to | |
1216 | find_pc_section verifies we know about the address and have some | |
1217 | hope of computing the right kind of breakpoint to use (via | |
1218 | symbol info). It does mean that GDB needs to be pointed at a | |
1219 | @@ -1571,7 +2217,7 @@ enable_break (struct svr4_info *info, in | |
1220 | + bfd_section_size (tmp_bfd, interp_sect); | |
1221 | } | |
1222 | ||
1223 | - create_solib_event_breakpoint (target_gdbarch, sym_addr); | |
1224 | + svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); | |
1225 | return 1; | |
1226 | } | |
1227 | } | |
1228 | @@ -1729,7 +2375,8 @@ enable_break (struct svr4_info *info, in | |
1229 | ||
1230 | if (sym_addr != 0) | |
1231 | { | |
1232 | - create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr); | |
1233 | + svr4_create_solib_event_breakpoints (target_gdbarch, | |
1234 | + load_addr + sym_addr); | |
1235 | xfree (interp_name); | |
1236 | return 1; | |
1237 | } | |
1238 | @@ -1755,7 +2402,7 @@ enable_break (struct svr4_info *info, in | |
1239 | sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, | |
1240 | sym_addr, | |
1241 | ¤t_target); | |
1242 | - create_solib_event_breakpoint (target_gdbarch, sym_addr); | |
1243 | + svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); | |
1244 | return 1; | |
1245 | } | |
1246 | } | |
1247 | @@ -1771,7 +2418,7 @@ enable_break (struct svr4_info *info, in | |
1248 | sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, | |
1249 | sym_addr, | |
1250 | ¤t_target); | |
1251 | - create_solib_event_breakpoint (target_gdbarch, sym_addr); | |
1252 | + svr4_create_solib_event_breakpoints (target_gdbarch, sym_addr); | |
1253 | return 1; | |
1254 | } | |
1255 | } | |
1256 | @@ -2281,6 +2928,9 @@ svr4_solib_create_inferior_hook (int fro | |
1257 | ||
1258 | info = get_svr4_info (); | |
1259 | ||
1260 | + /* Free the probes-based interface's namespace table. */ | |
1261 | + free_namespace_table (info); | |
1262 | + | |
1263 | /* Relocate the main executable if necessary. */ | |
1264 | svr4_relocate_main_executable (); | |
1265 | ||
1266 | @@ -2547,4 +3197,6 @@ _initialize_svr4_solib (void) | |
1267 | svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; | |
1268 | svr4_so_ops.same = svr4_same; | |
1269 | svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; | |
1270 | + svr4_so_ops.handle_solib_event = svr4_handle_solib_event; | |
1271 | + svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints; | |
1272 | } | |
1273 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen-solib.c | |
1274 | =================================================================== | |
1275 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1276 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen-solib.c 2012-08-14 17:34:44.330746591 +0200 | |
1277 | @@ -0,0 +1,24 @@ | |
1278 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1279 | + | |
1280 | + This program is free software; you can redistribute it and/or modify | |
1281 | + it under the terms of the GNU General Public License as published by | |
1282 | + the Free Software Foundation; either version 3 of the License, or | |
1283 | + (at your option) any later version. | |
1284 | + | |
1285 | + This program is distributed in the hope that it will be useful, | |
1286 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1287 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1288 | + GNU General Public License for more details. | |
1289 | + | |
1290 | + You should have received a copy of the GNU General Public License | |
1291 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1292 | + | |
1293 | +#include <stdio.h> | |
1294 | + | |
1295 | +int | |
1296 | +foo (int n) | |
1297 | +{ | |
1298 | + printf ("foo %d\n", n); | |
1299 | + | |
1300 | + return 0; | |
1301 | +} | |
1302 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.c | |
1303 | =================================================================== | |
1304 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1305 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.c 2012-08-14 17:34:44.339746576 +0200 | |
1306 | @@ -0,0 +1,58 @@ | |
1307 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1308 | + | |
1309 | + This program is free software; you can redistribute it and/or modify | |
1310 | + it under the terms of the GNU General Public License as published by | |
1311 | + the Free Software Foundation; either version 3 of the License, or | |
1312 | + (at your option) any later version. | |
1313 | + | |
1314 | + This program is distributed in the hope that it will be useful, | |
1315 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1316 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1317 | + GNU General Public License for more details. | |
1318 | + | |
1319 | + You should have received a copy of the GNU General Public License | |
1320 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1321 | + | |
1322 | +#define _GNU_SOURCE | |
1323 | +#include <dlfcn.h> | |
1324 | + | |
1325 | +void | |
1326 | +stop () | |
1327 | +{ | |
1328 | +} | |
1329 | + | |
1330 | +int | |
1331 | +main () | |
1332 | +{ | |
1333 | + void *handle1, *handle2, *handle3; | |
1334 | + void (*func)(int); | |
1335 | + | |
1336 | + handle1 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY); | |
1337 | + stop (); | |
1338 | + | |
1339 | + func = (void (*)(int)) dlsym (handle1, "foo"); | |
1340 | + func (1); | |
1341 | + | |
1342 | + handle2 = dlmopen (LM_ID_NEWLM, SHLIB_NAME, RTLD_LAZY); | |
1343 | + stop (); | |
1344 | + | |
1345 | + func = (void (*)(int)) dlsym (handle2, "foo"); | |
1346 | + func (2); | |
1347 | + | |
1348 | + handle3 = dlopen (SHLIB_NAME, RTLD_LAZY); | |
1349 | + stop (); | |
1350 | + | |
1351 | + func = (void (*)(int)) dlsym (handle3, "foo"); | |
1352 | + func (3); | |
1353 | + | |
1354 | + dlclose (handle1); | |
1355 | + stop (); | |
1356 | + | |
1357 | + dlclose (handle2); | |
1358 | + stop (); | |
1359 | + | |
1360 | + dlclose (handle3); | |
1361 | + stop (); | |
1362 | + | |
1363 | + return 0; | |
1364 | +} | |
1365 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.exp | |
1366 | =================================================================== | |
1367 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1368 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-dlmopen.exp 2012-08-14 17:34:44.343746563 +0200 | |
1369 | @@ -0,0 +1,125 @@ | |
1370 | +# Copyright 2012 Free Software Foundation, Inc. | |
1371 | + | |
1372 | +# This program is free software; you can redistribute it and/or modify | |
1373 | +# it under the terms of the GNU General Public License as published by | |
1374 | +# the Free Software Foundation; either version 3 of the License, or | |
1375 | +# (at your option) any later version. | |
1376 | +# | |
1377 | +# This program is distributed in the hope that it will be useful, | |
1378 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1379 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1380 | +# GNU General Public License for more details. | |
1381 | +# | |
1382 | +# You should have received a copy of the GNU General Public License | |
1383 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
1384 | + | |
1385 | +if { [skip_shlib_tests] || [is_remote target] } { | |
1386 | + return 0 | |
1387 | +} | |
1388 | + | |
1389 | +standard_testfile | |
1390 | + | |
1391 | +set libname $testfile-solib | |
1392 | +set srcfile_lib $srcdir/$subdir/$libname.c | |
1393 | +set binfile_lib [standard_output_file $libname.so] | |
1394 | + | |
1395 | +set normal_bp "_dl_debug_state" | |
1396 | +set probes_bp "dl_main" | |
1397 | + | |
1398 | +if { [gdb_compile_shlib $srcfile_lib $binfile_lib \ | |
1399 | + [list additional_flags=-fPIC]] != "" } { | |
1400 | + untested "Could not compile $binfile_lib." | |
1401 | + return -1 | |
1402 | +} | |
1403 | + | |
1404 | +if { [prepare_for_testing $testfile.exp $testfile $srcfile \ | |
1405 | + [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } { | |
1406 | + return -1 | |
1407 | +} | |
1408 | + | |
1409 | +# Run "info sharedlibrary" and check our library is shown the expected | |
1410 | +# number of times. | |
1411 | +proc check_info_shared { test expect } { | |
1412 | + global libname | |
1413 | + global gdb_prompt | |
1414 | + | |
1415 | + set actual 0 | |
1416 | + | |
1417 | + gdb_test_multiple "info sharedlibrary" $test { | |
1418 | + -re $libname { | |
1419 | + incr actual 1 | |
1420 | + exp_continue | |
1421 | + } | |
1422 | + -re "\r\n$gdb_prompt $" { | |
1423 | + if { $actual == $expect } { | |
1424 | + pass $test | |
1425 | + } else { | |
1426 | + fail $test | |
1427 | + } | |
1428 | + } | |
1429 | + } | |
1430 | +} | |
1431 | + | |
1432 | +# Enable stop-on-solib-events | |
1433 | +gdb_test_no_output "set stop-on-solib-events 1" | |
1434 | + | |
1435 | +# Run to the first stop | |
1436 | +gdb_test "run" ".*Stopped due to shared library event.*" | |
1437 | + | |
1438 | +# XFAIL if we are not using probes | |
1439 | +set test "ensure using probes" | |
1440 | +set using_probes 0 | |
1441 | +gdb_test_multiple "bt" $test { | |
1442 | + -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" { | |
1443 | + xfail $test | |
1444 | + } | |
1445 | + -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" { | |
1446 | + pass $test | |
1447 | + set using_probes 1 | |
1448 | + } | |
1449 | +} | |
1450 | + | |
1451 | +if { $using_probes } { | |
1452 | + # Set up breakpoints. | |
1453 | + gdb_test_no_output "set stop-on-solib-events 0" | |
1454 | + gdb_test "break stop" {Breakpoint [0-9]+ at .*} | |
1455 | + gdb_test_no_output "set breakpoint pending on" | |
1456 | + gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.} | |
1457 | + | |
1458 | + # Check our library isn't loaded. | |
1459 | + check_info_shared "info sharedlibrary #1" 0 | |
1460 | + | |
1461 | + # Run to the first stop and check our library loaded. | |
1462 | + gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1463 | + check_info_shared "info sharedlibrary #2" 1 | |
1464 | + | |
1465 | + # The next stop should be the function in the library. | |
1466 | + gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} | |
1467 | + | |
1468 | + # Run to the next stop and check our library is now loaded twice. | |
1469 | + gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1470 | + check_info_shared "info sharedlibrary #3" 2 | |
1471 | + | |
1472 | + # The next stop should be the function in the library. | |
1473 | + gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} | |
1474 | + | |
1475 | + # Run to the next stop and check our library is now loaded three | |
1476 | + # times. | |
1477 | + gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1478 | + check_info_shared "info sharedlibrary #4" 3 | |
1479 | + | |
1480 | + # The next stop should be the function in the library. | |
1481 | + gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} | |
1482 | + | |
1483 | + # Run to the next stop and check our library is now loaded twice. | |
1484 | + gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1485 | + check_info_shared "info sharedlibrary #5" 2 | |
1486 | + | |
1487 | + # Run to the next stop and check our library is now loaded once. | |
1488 | + gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1489 | + check_info_shared "info sharedlibrary #6" 1 | |
1490 | + | |
1491 | + # Run to the next stop and check our library is not loaded. | |
1492 | + gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1493 | + check_info_shared "info sharedlibrary #7" 0 | |
1494 | +} | |
1495 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-interp.exp | |
1496 | =================================================================== | |
1497 | --- gdb-7.4.91.20120814.orig/gdb/testsuite/gdb.base/break-interp.exp 2012-06-21 22:46:21.000000000 +0200 | |
1498 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-interp.exp 2012-08-14 17:34:44.344746565 +0200 | |
1499 | @@ -109,12 +109,19 @@ proc strip_debug {dest} { | |
1500 | } | |
1501 | } | |
1502 | ||
1503 | +# The marker function for the standard runtime linker interface is | |
1504 | +# _dl_debug_state. The probes-based interface has no specific marker | |
1505 | +# function; the probe we will stop on (init_start) is in dl_main so we | |
1506 | +# check for that. | |
1507 | + | |
1508 | +set solib_bp {(_dl_debug_state|dl_main)} | |
1509 | + | |
1510 | # Implementation of reach. | |
1511 | ||
1512 | proc reach_1 {func command displacement} { | |
1513 | - global gdb_prompt expect_out | |
1514 | + global gdb_prompt expect_out solib_bp | |
1515 | ||
1516 | - if {$func == "_dl_debug_state"} { | |
1517 | + if {$func == $solib_bp} { | |
1518 | # Breakpoint on _dl_debug_state can have problems due to its overlap | |
1519 | # with the existing internal breakpoint from GDB. | |
1520 | gdb_test_no_output "set stop-on-solib-events 1" | |
1521 | @@ -142,21 +149,21 @@ proc reach_1 {func command displacement} | |
1522 | exp_continue | |
1523 | } | |
1524 | -re "Breakpoint \[0-9\]+, \\.?(__GI_)?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" { | |
1525 | - if {$func == "_dl_debug_state"} { | |
1526 | + if {$func == $solib_bp} { | |
1527 | fail $test | |
1528 | } else { | |
1529 | pass $test | |
1530 | } | |
1531 | } | |
1532 | -re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?(__GI_)?$func \\(\\).*\r\n$gdb_prompt $" { | |
1533 | - if {$func == "_dl_debug_state"} { | |
1534 | + if {$func == $solib_bp} { | |
1535 | fail $test | |
1536 | } else { | |
1537 | pass $test | |
1538 | } | |
1539 | } | |
1540 | -re "Stopped due to (spurious )?shared library event.*\r\n$gdb_prompt $" { | |
1541 | - if {$func == "_dl_debug_state"} { | |
1542 | + if {$func == $solib_bp} { | |
1543 | if {$debug_state_count == 0} { | |
1544 | # First stop does not yet relocate the _start function | |
1545 | # descriptor on ppc64. | |
1546 | @@ -175,7 +182,7 @@ proc reach_1 {func command displacement} | |
1547 | fail $test_displacement | |
1548 | } | |
1549 | ||
1550 | - if {$func == "_dl_debug_state"} { | |
1551 | + if {$func == $solib_bp} { | |
1552 | gdb_test_no_output "set stop-on-solib-events 0" | |
1553 | } | |
1554 | } | |
1555 | @@ -357,7 +364,7 @@ proc test_attach {file displacement {rel | |
1556 | } | |
1557 | ||
1558 | proc test_ld {file ifmain trynosym displacement} { | |
1559 | - global srcdir subdir gdb_prompt expect_out inferior_exited_re | |
1560 | + global srcdir subdir gdb_prompt expect_out inferior_exited_re solib_bp | |
1561 | ||
1562 | # First test normal `file'-command loaded $FILE with symbols. | |
1563 | ||
1564 | @@ -385,9 +392,9 @@ proc test_ld {file ifmain trynosym displ | |
1565 | gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test" "set args OBJDIR/${subdir}/$binfile_test" | |
1566 | } | |
1567 | ||
1568 | - reach "_dl_debug_state" "run" $displacement | |
1569 | + reach $solib_bp "run" $displacement | |
1570 | ||
1571 | - gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?_dl_debug_state\\M.*" "dl bt" | |
1572 | + gdb_test "bt" "#0 +\[^\r\n\]*\\m(__GI_)?$solib_bp\\M.*" "dl bt" | |
1573 | ||
1574 | if $ifmain { | |
1575 | reach "main" continue "NONE" | |
1576 | @@ -399,7 +406,7 @@ proc test_ld {file ifmain trynosym displ | |
1577 | ||
1578 | # Try re-run if the new PIE displacement takes effect. | |
1579 | gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y" | |
1580 | - reach "_dl_debug_state" "run" $displacement | |
1581 | + reach $solib_bp "run" $displacement | |
1582 | ||
1583 | if $ifmain { | |
1584 | test_core $file $displacement | |
1585 | @@ -431,7 +438,7 @@ proc test_ld {file ifmain trynosym displ | |
1586 | gdb_test "exec-file $file" "exec-file $escapedfile" "load" | |
1587 | ||
1588 | if $ifmain { | |
1589 | - reach "_dl_debug_state" run $displacement | |
1590 | + reach $solib_bp run $displacement | |
1591 | ||
1592 | # Use two separate gdb_test_multiple statements to avoid timeouts due | |
1593 | # to slow processing of wildcard capturing long output | |
1594 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes-solib.c | |
1595 | =================================================================== | |
1596 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1597 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes-solib.c 2012-08-14 17:34:44.355746561 +0200 | |
1598 | @@ -0,0 +1,24 @@ | |
1599 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1600 | + | |
1601 | + This program is free software; you can redistribute it and/or modify | |
1602 | + it under the terms of the GNU General Public License as published by | |
1603 | + the Free Software Foundation; either version 3 of the License, or | |
1604 | + (at your option) any later version. | |
1605 | + | |
1606 | + This program is distributed in the hope that it will be useful, | |
1607 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1608 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1609 | + GNU General Public License for more details. | |
1610 | + | |
1611 | + You should have received a copy of the GNU General Public License | |
1612 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1613 | + | |
1614 | +#include <stdio.h> | |
1615 | + | |
1616 | +int | |
1617 | +foo (int n) | |
1618 | +{ | |
1619 | + printf ("foo %d\n", n); | |
1620 | + | |
1621 | + return 0; | |
1622 | +} | |
1623 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.c | |
1624 | =================================================================== | |
1625 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1626 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.c 2012-08-14 17:34:44.362746561 +0200 | |
1627 | @@ -0,0 +1,26 @@ | |
1628 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1629 | + | |
1630 | + This program is free software; you can redistribute it and/or modify | |
1631 | + it under the terms of the GNU General Public License as published by | |
1632 | + the Free Software Foundation; either version 3 of the License, or | |
1633 | + (at your option) any later version. | |
1634 | + | |
1635 | + This program is distributed in the hope that it will be useful, | |
1636 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1637 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1638 | + GNU General Public License for more details. | |
1639 | + | |
1640 | + You should have received a copy of the GNU General Public License | |
1641 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1642 | + | |
1643 | +#include <dlfcn.h> | |
1644 | + | |
1645 | +int | |
1646 | +main () | |
1647 | +{ | |
1648 | + void *handle = dlopen (SHLIB_NAME, RTLD_LAZY); | |
1649 | + | |
1650 | + dlclose (handle); | |
1651 | + | |
1652 | + return 0; | |
1653 | +} | |
1654 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.exp | |
1655 | =================================================================== | |
1656 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1657 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/break-probes.exp 2012-08-14 17:34:44.363746561 +0200 | |
1658 | @@ -0,0 +1,76 @@ | |
1659 | +# Copyright 2012 Free Software Foundation, Inc. | |
1660 | + | |
1661 | +# This program is free software; you can redistribute it and/or modify | |
1662 | +# it under the terms of the GNU General Public License as published by | |
1663 | +# the Free Software Foundation; either version 3 of the License, or | |
1664 | +# (at your option) any later version. | |
1665 | +# | |
1666 | +# This program is distributed in the hope that it will be useful, | |
1667 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1668 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1669 | +# GNU General Public License for more details. | |
1670 | +# | |
1671 | +# You should have received a copy of the GNU General Public License | |
1672 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
1673 | + | |
1674 | +if { [skip_shlib_tests] || [is_remote target] } { | |
1675 | + return 0 | |
1676 | +} | |
1677 | + | |
1678 | +standard_testfile | |
1679 | + | |
1680 | +set libname $testfile-solib | |
1681 | +set srcfile_lib $srcdir/$subdir/$libname.c | |
1682 | +set binfile_lib [standard_output_file $libname.so] | |
1683 | + | |
1684 | +set normal_bp "_dl_debug_state" | |
1685 | +set probes_bp "dl_main" | |
1686 | + | |
1687 | +if { [gdb_compile_shlib $srcfile_lib $binfile_lib \ | |
1688 | + [list additional_flags=-fPIC]] != "" } { | |
1689 | + untested "Could not compile $binfile_lib." | |
1690 | + return -1 | |
1691 | +} | |
1692 | + | |
1693 | +if { [prepare_for_testing $testfile.exp $testfile $srcfile \ | |
1694 | + [list additional_flags=-DSHLIB_NAME\=\"$binfile_lib\" libs=-ldl]] } { | |
1695 | + return -1 | |
1696 | +} | |
1697 | + | |
1698 | +# Enable stop-on-solib-events | |
1699 | +gdb_test_no_output "set stop-on-solib-events 1" | |
1700 | + | |
1701 | +# Run to the first stop | |
1702 | +gdb_test "run" ".*Stopped due to shared library event.*" | |
1703 | + | |
1704 | +# XFAIL if we are not using probes | |
1705 | +set test "ensure using probes" | |
1706 | +set using_probes 0 | |
1707 | +gdb_test_multiple "bt" $test { | |
1708 | + -re "#0 +\[^\r\n\]*\\m(__GI_)?$normal_bp\\M.*$gdb_prompt $" { | |
1709 | + xfail $test | |
1710 | + } | |
1711 | + -re "#0 +\[^\r\n\]*\\m(__GI_)?$probes_bp\\M.*$gdb_prompt $" { | |
1712 | + pass $test | |
1713 | + set using_probes 1 | |
1714 | + } | |
1715 | +} | |
1716 | + | |
1717 | +if { $using_probes } { | |
1718 | + # Run til it loads our library | |
1719 | + set test "run til our library loads" | |
1720 | + set loaded_library 0 | |
1721 | + while { !$loaded_library } { | |
1722 | + gdb_test_multiple "c" $test { | |
1723 | + -re "Inferior loaded $binfile_lib\\M.*$gdb_prompt $" { | |
1724 | + pass $test | |
1725 | + set loaded_library 1 | |
1726 | + } | |
1727 | + -re "Stopped due to shared library event\\M.*$gdb_prompt $" { | |
1728 | + } | |
1729 | + } | |
1730 | + } | |
1731 | + | |
1732 | + # Call something to ensure that relocation occurred | |
1733 | + gdb_test "call foo(23)" "foo 23.*\\\$.* = .*" | |
1734 | +} | |
1735 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib1.c | |
1736 | =================================================================== | |
1737 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1738 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib1.c 2012-08-14 17:34:44.365746561 +0200 | |
1739 | @@ -0,0 +1,24 @@ | |
1740 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1741 | + | |
1742 | + This program is free software; you can redistribute it and/or modify | |
1743 | + it under the terms of the GNU General Public License as published by | |
1744 | + the Free Software Foundation; either version 3 of the License, or | |
1745 | + (at your option) any later version. | |
1746 | + | |
1747 | + This program is distributed in the hope that it will be useful, | |
1748 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1749 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1750 | + GNU General Public License for more details. | |
1751 | + | |
1752 | + You should have received a copy of the GNU General Public License | |
1753 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1754 | + | |
1755 | +#include <stdio.h> | |
1756 | + | |
1757 | +int | |
1758 | +foo (int n) | |
1759 | +{ | |
1760 | + printf ("foo %d\n", n); | |
1761 | + | |
1762 | + return 0; | |
1763 | +} | |
1764 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib2.c | |
1765 | =================================================================== | |
1766 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1767 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared-solib2.c 2012-08-14 17:34:44.365746561 +0200 | |
1768 | @@ -0,0 +1,24 @@ | |
1769 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1770 | + | |
1771 | + This program is free software; you can redistribute it and/or modify | |
1772 | + it under the terms of the GNU General Public License as published by | |
1773 | + the Free Software Foundation; either version 3 of the License, or | |
1774 | + (at your option) any later version. | |
1775 | + | |
1776 | + This program is distributed in the hope that it will be useful, | |
1777 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1778 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1779 | + GNU General Public License for more details. | |
1780 | + | |
1781 | + You should have received a copy of the GNU General Public License | |
1782 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1783 | + | |
1784 | +#include <stdio.h> | |
1785 | + | |
1786 | +int | |
1787 | +bar (int n) | |
1788 | +{ | |
1789 | + printf ("bar %d\n", n); | |
1790 | + | |
1791 | + return 0; | |
1792 | +} | |
1793 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.c | |
1794 | =================================================================== | |
1795 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1796 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.c 2012-08-14 17:34:44.366746561 +0200 | |
1797 | @@ -0,0 +1,48 @@ | |
1798 | +/* Copyright 2012 Free Software Foundation, Inc. | |
1799 | + | |
1800 | + This program is free software; you can redistribute it and/or modify | |
1801 | + it under the terms of the GNU General Public License as published by | |
1802 | + the Free Software Foundation; either version 3 of the License, or | |
1803 | + (at your option) any later version. | |
1804 | + | |
1805 | + This program is distributed in the hope that it will be useful, | |
1806 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1807 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1808 | + GNU General Public License for more details. | |
1809 | + | |
1810 | + You should have received a copy of the GNU General Public License | |
1811 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1812 | + | |
1813 | +#include <dlfcn.h> | |
1814 | + | |
1815 | +void | |
1816 | +stop () | |
1817 | +{ | |
1818 | +} | |
1819 | + | |
1820 | +int | |
1821 | +main () | |
1822 | +{ | |
1823 | + void *handle1, *handle2; | |
1824 | + void (*func)(int); | |
1825 | + | |
1826 | + handle1 = dlopen (SHLIB1_NAME, RTLD_LAZY); | |
1827 | + stop (); | |
1828 | + | |
1829 | + handle2 = dlopen (SHLIB2_NAME, RTLD_LAZY); | |
1830 | + stop (); | |
1831 | + | |
1832 | + func = (void (*)(int)) dlsym (handle1, "foo"); | |
1833 | + func (1); | |
1834 | + | |
1835 | + func = (void (*)(int)) dlsym (handle2, "bar"); | |
1836 | + func (2); | |
1837 | + | |
1838 | + dlclose (handle1); | |
1839 | + stop (); | |
1840 | + | |
1841 | + dlclose (handle2); | |
1842 | + stop (); | |
1843 | + | |
1844 | + return 0; | |
1845 | +} | |
1846 | Index: gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.exp | |
1847 | =================================================================== | |
1848 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1849 | +++ gdb-7.4.91.20120814/gdb/testsuite/gdb.base/info-shared.exp 2012-08-14 17:34:44.367746561 +0200 | |
1850 | @@ -0,0 +1,139 @@ | |
1851 | +# Copyright 2012 Free Software Foundation, Inc. | |
1852 | + | |
1853 | +# This program is free software; you can redistribute it and/or modify | |
1854 | +# it under the terms of the GNU General Public License as published by | |
1855 | +# the Free Software Foundation; either version 3 of the License, or | |
1856 | +# (at your option) any later version. | |
1857 | +# | |
1858 | +# This program is distributed in the hope that it will be useful, | |
1859 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1860 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1861 | +# GNU General Public License for more details. | |
1862 | +# | |
1863 | +# You should have received a copy of the GNU General Public License | |
1864 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
1865 | + | |
1866 | +if { [skip_shlib_tests] || [is_remote target] } { | |
1867 | + return 0 | |
1868 | +} | |
1869 | + | |
1870 | +standard_testfile | |
1871 | + | |
1872 | +set lib1name $testfile-solib1 | |
1873 | +set srcfile_lib1 $srcdir/$subdir/$lib1name.c | |
1874 | +set binfile_lib1 [standard_output_file $lib1name.so] | |
1875 | +set define1 -DSHLIB1_NAME\=\"$binfile_lib1\" | |
1876 | + | |
1877 | +set lib2name $testfile-solib2 | |
1878 | +set srcfile_lib2 $srcdir/$subdir/$lib2name.c | |
1879 | +set binfile_lib2 [standard_output_file $lib2name.so] | |
1880 | +set define2 -DSHLIB2_NAME\=\"$binfile_lib2\" | |
1881 | + | |
1882 | +if { [gdb_compile_shlib $srcfile_lib1 $binfile_lib1 \ | |
1883 | + [list additional_flags=-fPIC]] != "" } { | |
1884 | + untested "Could not compile $binfile_lib1." | |
1885 | + return -1 | |
1886 | +} | |
1887 | + | |
1888 | +if { [gdb_compile_shlib $srcfile_lib2 $binfile_lib2 \ | |
1889 | + [list additional_flags=-fPIC]] != "" } { | |
1890 | + untested "Could not compile $binfile_lib2." | |
1891 | + return -1 | |
1892 | +} | |
1893 | + | |
1894 | +set cflags "$define1 $define2" | |
1895 | +if { [prepare_for_testing $testfile.exp $testfile $srcfile \ | |
1896 | + [list additional_flags=$cflags libs=-ldl]] } { | |
1897 | + return -1 | |
1898 | +} | |
1899 | + | |
1900 | +# Run "info sharedlibrary" and check for the presence or absence of | |
1901 | +# our libraries. | |
1902 | +proc check_info_shared { test expect1 expect2 } { | |
1903 | + global lib1name | |
1904 | + global lib2name | |
1905 | + global gdb_prompt | |
1906 | + | |
1907 | + set actual1 0 | |
1908 | + set actual2 0 | |
1909 | + | |
1910 | + gdb_test_multiple "info sharedlibrary" $test { | |
1911 | + -re $lib1name { | |
1912 | + set actual1 1 | |
1913 | + exp_continue | |
1914 | + } | |
1915 | + -re $lib2name { | |
1916 | + set actual2 1 | |
1917 | + exp_continue | |
1918 | + } | |
1919 | + -re "\r\n$gdb_prompt $" { | |
1920 | + if { $actual1 == $expect1 && $actual2 == $expect2 } { | |
1921 | + pass $test | |
1922 | + } else { | |
1923 | + fail $test | |
1924 | + } | |
1925 | + } | |
1926 | + } | |
1927 | +} | |
1928 | + | |
1929 | +# Set up breakpoints. | |
1930 | +gdb_test "break stop" {Breakpoint [0-9]+ at .*} | |
1931 | +gdb_test_no_output "set breakpoint pending on" | |
1932 | +gdb_test "break foo" {Breakpoint [0-9]+ \(foo\) pending\.} | |
1933 | +gdb_test "break bar" {Breakpoint [0-9]+ \(bar\) pending\.} | |
1934 | + | |
1935 | +# Check neither of the libraries are loaded at the start. | |
1936 | +gdb_test "start" {Temporary breakpoint [0-9]+, .* in main \(\)} | |
1937 | +check_info_shared "info sharedlibrary #1" 0 0 | |
1938 | + | |
1939 | +# Run to the first stop and check that only the first library is loaded. | |
1940 | +gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1941 | +check_info_shared "info sharedlibrary #2" 1 0 | |
1942 | + | |
1943 | +# Run to the second stop and check that both libraries are loaded. | |
1944 | +gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1945 | +check_info_shared "info sharedlibrary #3" 1 1 | |
1946 | + | |
1947 | +# Check that the next stop is in foo. | |
1948 | +gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} | |
1949 | + | |
1950 | +# Check that the next stop is in bar. | |
1951 | +gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*} | |
1952 | + | |
1953 | +# Restart the inferior and make sure there are no breakpoint reset | |
1954 | +# errors. These can happen with the probes-based runtime linker | |
1955 | +# interface if the cache is not cleared correctly. | |
1956 | +set test "restart" | |
1957 | +gdb_test_multiple "run" $test { | |
1958 | + -re {Start it from the beginning\? \(y or n\) } { | |
1959 | + send_gdb "y\n" | |
1960 | + exp_continue | |
1961 | + } | |
1962 | + -re {Error in re-setting breakpoint} { | |
1963 | + fail $test | |
1964 | + } | |
1965 | + -re "\r\n$gdb_prompt $" { | |
1966 | + pass $test | |
1967 | + } | |
1968 | +} | |
1969 | + | |
1970 | +# We're at the first stop. Check that only the first library is loaded. | |
1971 | +check_info_shared "info sharedlibrary #4" 1 0 | |
1972 | + | |
1973 | +# Run to the second stop and check that both libraries are loaded. | |
1974 | +gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1975 | +check_info_shared "info sharedlibrary #5" 1 1 | |
1976 | + | |
1977 | +# Check that the next stop is in foo. | |
1978 | +gdb_test "c" {Breakpoint [0-9]+, .* in foo \(\) from .*} | |
1979 | + | |
1980 | +# Check that the next stop is in bar. | |
1981 | +gdb_test "c" {Breakpoint [0-9]+, .* in bar \(\) from .*} | |
1982 | + | |
1983 | +# Run to the next stop and check that the first library has been unloaded. | |
1984 | +gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1985 | +check_info_shared "info sharedlibrary #6" 0 1 | |
1986 | + | |
1987 | +# Run to the last stop and check that both libraries are gone. | |
1988 | +gdb_test "c" {Breakpoint [0-9]+, .* in stop \(\)} | |
1989 | +check_info_shared "info sharedlibrary #7" 0 0 |