* Makefile.in (copying.c): Use the top-level COPYING3 as the file
[deliverable/binutils-gdb.git] / gdb / solib-target.c
CommitLineData
cfa9d6d9
DJ
1/* Definitions for targets which report shared library events.
2
3 Copyright (C) 2007
4 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
cfa9d6d9
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
cfa9d6d9
DJ
20
21#include "defs.h"
22#include "objfiles.h"
23#include "solist.h"
24#include "symtab.h"
25#include "symfile.h"
26#include "target.h"
27#include "vec.h"
28
29#include "gdb_string.h"
30
31DEF_VEC_O(CORE_ADDR);
32
33/* Private data for each loaded library. */
34struct lm_info
35{
36 /* The library's name. The name is normally kept in the struct
37 so_list; it is only here during XML parsing. */
38 char *name;
39
40 /* The base addresses for each independently relocatable segment of
41 this shared library. */
42 VEC(CORE_ADDR) *segment_bases;
43
44 /* The cached offsets for each section of this shared library,
45 determined from SEGMENT_BASES. */
46 struct section_offsets *offsets;
47};
48
49typedef struct lm_info *lm_info_p;
50DEF_VEC_P(lm_info_p);
51
52#if !defined(HAVE_LIBEXPAT)
53
54static VEC(lm_info_p)
55solib_target_parse_libraries (const char *library)
56{
57 static int have_warned;
58
59 if (!have_warned)
60 {
61 have_warned = 1;
62 warning (_("Can not parse XML library list; XML support was disabled "
63 "at compile time"));
64 }
65
66 return NULL;
67}
68
69#else /* HAVE_LIBEXPAT */
70
71#include "xml-support.h"
72
73/* Handle the start of a <segment> element. */
74
75static void
76library_list_start_segment (struct gdb_xml_parser *parser,
77 const struct gdb_xml_element *element,
78 void *user_data, VEC(gdb_xml_value_s) *attributes)
79{
80 VEC(lm_info_p) **list = user_data;
81 struct lm_info *last = VEC_last (lm_info_p, *list);
82 ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value;
358eb95e 83 CORE_ADDR address = (CORE_ADDR) *address_p;
cfa9d6d9 84
358eb95e 85 VEC_safe_push (CORE_ADDR, last->segment_bases, &address);
cfa9d6d9
DJ
86}
87
88/* Handle the start of a <library> element. */
89
90static void
91library_list_start_library (struct gdb_xml_parser *parser,
92 const struct gdb_xml_element *element,
93 void *user_data, VEC(gdb_xml_value_s) *attributes)
94{
95 VEC(lm_info_p) **list = user_data;
96 struct lm_info *item = XZALLOC (struct lm_info);
97 const char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value;
98
99 item->name = xstrdup (name);
100 VEC_safe_push (lm_info_p, *list, item);
101}
102
103/* Handle the start of a <library-list> element. */
104
105static void
106library_list_start_list (struct gdb_xml_parser *parser,
107 const struct gdb_xml_element *element,
108 void *user_data, VEC(gdb_xml_value_s) *attributes)
109{
110 char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value;
111
112 if (strcmp (version, "1.0") != 0)
113 gdb_xml_error (parser,
114 _("Library list has unsupported version \"%s\""),
115 version);
116}
117
118/* Discard the constructed library list. */
119
120static void
121solib_target_free_library_list (void *p)
122{
123 VEC(lm_info_p) **result = p;
124 struct lm_info *info;
125 int ix;
126
127 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
128 {
129 xfree (info->name);
130 VEC_free (CORE_ADDR, info->segment_bases);
131 xfree (info);
132 }
133 VEC_free (lm_info_p, *result);
134 *result = NULL;
135}
136
137/* The allowed elements and attributes for an XML library list.
138 The root element is a <library-list>. */
139
140const struct gdb_xml_attribute segment_attributes[] = {
141 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
142 { NULL, GDB_XML_AF_NONE, NULL, NULL }
143};
144
145const struct gdb_xml_element library_children[] = {
146 { "segment", segment_attributes, NULL, GDB_XML_EF_REPEATABLE,
147 library_list_start_segment, NULL },
148 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
149};
150
151const struct gdb_xml_attribute library_attributes[] = {
152 { "name", GDB_XML_AF_NONE, NULL, NULL },
153 { NULL, GDB_XML_AF_NONE, NULL, NULL }
154};
155
156const struct gdb_xml_element library_list_children[] = {
157 { "library", library_attributes, library_children,
158 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
159 library_list_start_library, NULL },
160 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
161};
162
163const struct gdb_xml_attribute library_list_attributes[] = {
164 { "version", GDB_XML_AF_NONE, NULL, NULL },
165 { NULL, GDB_XML_AF_NONE, NULL, NULL }
166};
167
168const struct gdb_xml_element library_list_elements[] = {
169 { "library-list", library_list_attributes, library_list_children,
170 GDB_XML_EF_NONE, library_list_start_list, NULL },
171 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
172};
173
174static VEC(lm_info_p) *
175solib_target_parse_libraries (const char *library)
176{
177 struct gdb_xml_parser *parser;
178 VEC(lm_info_p) *result = NULL;
179 struct cleanup *before_deleting_result, *back_to;
180
181 back_to = make_cleanup (null_cleanup, NULL);
182 parser = gdb_xml_create_parser_and_cleanup (_("target library list"),
183 library_list_elements, &result);
184 gdb_xml_use_dtd (parser, "library-list.dtd");
185
186 before_deleting_result = make_cleanup (solib_target_free_library_list,
187 &result);
188
189 if (gdb_xml_parse (parser, library) == 0)
190 /* Parsed successfully, don't need to delete the result. */
191 discard_cleanups (before_deleting_result);
192
193 do_cleanups (back_to);
194 return result;
195}
196#endif
197
198static struct so_list *
199solib_target_current_sos (void)
200{
201 struct so_list *new_solib, *start = NULL, *last = NULL;
202 const char *library_document;
203 VEC(lm_info_p) *library_list;
204 struct lm_info *info;
205 int ix;
206
207 /* Fetch the list of shared libraries. */
208 library_document = target_read_stralloc (&current_target,
209 TARGET_OBJECT_LIBRARIES,
210 NULL);
211 if (library_document == NULL)
212 return NULL;
213
214 /* Parse the list. */
215 library_list = solib_target_parse_libraries (library_document);
216 if (library_list == NULL)
217 return NULL;
218
219 /* Build a struct so_list for each entry on the list. */
220 for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
221 {
222 new_solib = XZALLOC (struct so_list);
223 strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
224 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
225 strncpy (new_solib->so_original_name, info->name,
226 SO_NAME_MAX_PATH_SIZE - 1);
227 new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
228 new_solib->lm_info = info;
229
230 /* We no longer need this copy of the name. */
231 xfree (info->name);
232 info->name = NULL;
233
234 /* Add it to the list. */
235 if (!start)
236 last = start = new_solib;
237 else
238 {
239 last->next = new_solib;
240 last = new_solib;
241 }
242 }
243
244 /* Free the library list, but not its members. */
245 VEC_free (lm_info_p, library_list);
246
247 return start;
248}
249
250static void
251solib_target_special_symbol_handling (void)
252{
253 /* Nothing needed. */
254}
255
256static void
257solib_target_solib_create_inferior_hook (void)
258{
259 /* Nothing needed. */
260}
261
262static void
263solib_target_clear_solib (void)
264{
265 /* Nothing needed. */
266}
267
268static void
269solib_target_free_so (struct so_list *so)
270{
271 gdb_assert (so->lm_info->name == NULL);
272 xfree (so->lm_info->offsets);
273 VEC_free (CORE_ADDR, so->lm_info->segment_bases);
274 xfree (so->lm_info);
275}
276
277static void
278solib_target_relocate_section_addresses (struct so_list *so,
279 struct section_table *sec)
280{
281 int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
282 CORE_ADDR offset;
283
284 /* Build the offset table only once per object file. We can not do
285 it any earlier, since we need to open the file first. */
286 if (so->lm_info->offsets == NULL)
287 {
288 struct symfile_segment_data *data;
289 int num_sections = bfd_count_sections (so->abfd);
290
291 so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
292
293 data = get_symfile_segment_data (so->abfd);
294 if (data == NULL)
295 warning (_("Could not relocate shared library \"%s\": no segments"),
296 so->so_name);
297 else
298 {
299 ULONGEST orig_delta;
300 int i;
301 int num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
302 CORE_ADDR *segment_bases = VEC_address (CORE_ADDR,
303 so->lm_info->segment_bases);
304
305 if (!symfile_map_offsets_to_segments (so->abfd, data,
306 so->lm_info->offsets,
307 num_bases, segment_bases))
308 warning (_("Could not relocate shared library \"%s\": bad offsets"),
309 so->so_name);
310
311 /* Find the range of addresses to report for this library in
312 "info sharedlibrary". Report any consecutive segments
313 which were relocated as a single unit. */
314 gdb_assert (num_bases > 0);
315 orig_delta = segment_bases[0] - data->segment_bases[0];
316
317 for (i = 1; i < data->num_segments; i++)
318 {
319 /* If we have run out of offsets, assume all remaining segments
320 have the same offset. */
321 if (i >= num_bases)
322 continue;
323
324 /* If this segment does not have the same offset, do not include
325 it in the library's range. */
326 if (segment_bases[i] - data->segment_bases[i] != orig_delta)
327 break;
328 }
329
330 so->addr_low = segment_bases[0];
331 so->addr_high = (data->segment_bases[i - 1]
332 + data->segment_sizes[i - 1]
5d9643ba
PA
333 + orig_delta);
334 gdb_assert (so->addr_low <= so->addr_high);
cfa9d6d9
DJ
335
336 free_symfile_segment_data (data);
337 }
338 }
339
340 offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
341 sec->addr += offset;
342 sec->endaddr += offset;
343}
344
345static int
346solib_target_open_symbol_file_object (void *from_ttyp)
347{
348 /* We can't locate the main symbol file based on the target's
349 knowledge; the user has to specify it. */
350 return 0;
351}
352
353static int
354solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
355{
356 /* We don't have a range of addresses for the dynamic linker; there
357 may not be one in the program's address space. So only report
358 PLT entries (which may be import stubs). */
359 return in_plt_section (pc, NULL);
360}
361
362static struct target_so_ops solib_target_so_ops;
363
364extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */
365
366void
367_initialize_solib_target (void)
368{
369 solib_target_so_ops.relocate_section_addresses
370 = solib_target_relocate_section_addresses;
371 solib_target_so_ops.free_so = solib_target_free_so;
372 solib_target_so_ops.clear_solib = solib_target_clear_solib;
373 solib_target_so_ops.solib_create_inferior_hook
374 = solib_target_solib_create_inferior_hook;
375 solib_target_so_ops.special_symbol_handling
376 = solib_target_special_symbol_handling;
377 solib_target_so_ops.current_sos = solib_target_current_sos;
378 solib_target_so_ops.open_symbol_file_object
379 = solib_target_open_symbol_file_object;
380 solib_target_so_ops.in_dynsym_resolve_code
381 = solib_target_in_dynsym_resolve_code;
382
383 current_target_so_ops = &solib_target_so_ops;
384}
This page took 0.063998 seconds and 4 git commands to generate.