import strstr and strerror modules
[deliverable/binutils-gdb.git] / gdb / solib-aix.c
CommitLineData
4d1eb6b4
JB
1/* Copyright (C) 2013 Free Software Foundation, Inc.
2
3 This file is part of GDB.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "defs.h"
19#include "solib-aix.h"
20#include "solist.h"
21#include "inferior.h"
22#include "gdb_bfd.h"
23#include "gdbcore.h"
24#include "objfiles.h"
25#include "symtab.h"
26#include "xcoffread.h"
27#include "observer.h"
28#include "gdbcmd.h"
29
30/* Variable controlling the output of the debugging traces for
31 this module. */
32static int solib_aix_debug;
33
34/* Our private data in struct so_list. */
35
36struct lm_info
37{
38 /* The name of the file mapped by the loader. Apart from the entry
39 for the main executable, this is usually a shared library (which,
40 on AIX, is an archive library file, created using the "ar"
41 command). */
42 char *filename;
43
44 /* The name of the shared object file with the actual dynamic
45 loading dependency. This may be NULL (Eg. main executable). */
46 char *member_name;
47
48 /* The address in inferior memory where the text section got mapped. */
49 CORE_ADDR text_addr;
50
51 /* The size of the text section, obtained via the loader data. */
52 ULONGEST text_size;
53
54 /* The address in inferior memory where the data section got mapped. */
55 CORE_ADDR data_addr;
56
57 /* The size of the data section, obtained via the loader data. */
58 ULONGEST data_size;
59};
60
61typedef struct lm_info *lm_info_p;
62DEF_VEC_P(lm_info_p);
63
64/* Return a deep copy of the given struct lm_info object. */
65
66static struct lm_info *
67solib_aix_new_lm_info (struct lm_info *info)
68{
69 struct lm_info *result = xmalloc (sizeof (struct lm_info));
70
71 memcpy (result, info, sizeof (struct lm_info));
72 result->filename = xstrdup (info->filename);
73 if (info->member_name != NULL)
74 result->member_name = xstrdup (info->member_name);
75
76 return result;
77}
78
79/* Free the memory allocated for the given lm_info. */
80
81static void
82solib_aix_xfree_lm_info (struct lm_info *info)
83{
84 xfree (info->filename);
85 xfree (info->member_name);
86 xfree (info);
87}
88
89/* This module's per-inferior data. */
90
91struct solib_aix_inferior_data
92{
93 /* The list of shared libraries. NULL if not computed yet.
94
95 Note that the first element of this list is always the main
96 executable, which is not technically a shared library. But
97 we need that information to perform its relocation, and
98 the same principles applied to shared libraries also apply
99 to the main executable. So it's simpler to keep it as part
100 of this list. */
101 VEC (lm_info_p) *library_list;
102};
103
104/* Key to our per-inferior data. */
105static const struct inferior_data *solib_aix_inferior_data_handle;
106
107/* Return this module's data for the given inferior.
108 If none is found, add a zero'ed one now. */
109
110static struct solib_aix_inferior_data *
111get_solib_aix_inferior_data (struct inferior *inf)
112{
113 struct solib_aix_inferior_data *data;
114
115 data = inferior_data (inf, solib_aix_inferior_data_handle);
116 if (data == NULL)
117 {
118 data = XZALLOC (struct solib_aix_inferior_data);
119 set_inferior_data (inf, solib_aix_inferior_data_handle, data);
120 }
121
122 return data;
123}
124
125#if !defined(HAVE_LIBEXPAT)
126
127/* Dummy implementation if XML support is not compiled in. */
128
129static VEC (lm_info_p) *
130solib_aix_parse_libraries (const char *library)
131{
132 static int have_warned;
133
134 if (!have_warned)
135 {
136 have_warned = 1;
137 warning (_("Can not parse XML library list; XML support was disabled "
138 "at compile time"));
139 }
140
141 return NULL;
142}
143
814a3ff7
JB
144/* Dummy implementation if XML support is not compiled in. */
145
146static void
147solib_aix_free_library_list (void *p)
148{
149}
150
4d1eb6b4
JB
151#else /* HAVE_LIBEXPAT */
152
153#include "xml-support.h"
154
155/* Handle the start of a <library> element. */
156
157static void
158library_list_start_library (struct gdb_xml_parser *parser,
159 const struct gdb_xml_element *element,
160 void *user_data,
161 VEC (gdb_xml_value_s) *attributes)
162{
163 VEC (lm_info_p) **list = user_data;
164 struct lm_info *item = XZALLOC (struct lm_info);
165 struct gdb_xml_value *attr;
166
167 attr = xml_find_attribute (attributes, "name");
168 item->filename = xstrdup (attr->value);
169
170 attr = xml_find_attribute (attributes, "member");
171 if (attr != NULL)
172 item->member_name = xstrdup (attr->value);
173
174 attr = xml_find_attribute (attributes, "text_addr");
175 item->text_addr = * (ULONGEST *) attr->value;
176
177 attr = xml_find_attribute (attributes, "text_size");
178 item->text_size = * (ULONGEST *) attr->value;
179
180 attr = xml_find_attribute (attributes, "data_addr");
181 item->data_addr = * (ULONGEST *) attr->value;
182
183 attr = xml_find_attribute (attributes, "data_size");
184 item->data_size = * (ULONGEST *) attr->value;
185
186 VEC_safe_push (lm_info_p, *list, item);
187}
188
8c56e112 189/* Handle the start of a <library-list-aix> element. */
4d1eb6b4
JB
190
191static void
192library_list_start_list (struct gdb_xml_parser *parser,
193 const struct gdb_xml_element *element,
194 void *user_data, VEC (gdb_xml_value_s) *attributes)
195{
196 char *version = xml_find_attribute (attributes, "version")->value;
197
198 if (strcmp (version, "1.0") != 0)
199 gdb_xml_error (parser,
200 _("Library list has unsupported version \"%s\""),
201 version);
202}
203
204/* Discard the constructed library list. */
205
206static void
207solib_aix_free_library_list (void *p)
208{
209 VEC (lm_info_p) **result = p;
210 struct lm_info *info;
211 int ix;
212
213 if (solib_aix_debug)
214 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_library_list\n");
215
216 for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
217 solib_aix_xfree_lm_info (info);
218 VEC_free (lm_info_p, *result);
219 *result = NULL;
220}
221
222/* The allowed elements and attributes for an AIX library list
8c56e112 223 described in XML format. The root element is a <library-list-aix>. */
4d1eb6b4
JB
224
225static const struct gdb_xml_attribute library_attributes[] =
226{
227 { "name", GDB_XML_AF_NONE, NULL, NULL },
228 { "member", GDB_XML_AF_OPTIONAL, NULL, NULL },
229 { "text_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
230 { "text_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
231 { "data_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
232 { "data_size", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
233 { NULL, GDB_XML_AF_NONE, NULL, NULL }
234};
235
236static const struct gdb_xml_element library_list_children[] =
237{
238 { "library", library_attributes, NULL,
239 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
240 library_list_start_library, NULL},
241 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
242};
243
244static const struct gdb_xml_attribute library_list_attributes[] =
245{
246 { "version", GDB_XML_AF_NONE, NULL, NULL },
247 { NULL, GDB_XML_AF_NONE, NULL, NULL }
248};
249
250static const struct gdb_xml_element library_list_elements[] =
251{
8c56e112 252 { "library-list-aix", library_list_attributes, library_list_children,
4d1eb6b4
JB
253 GDB_XML_EF_NONE, library_list_start_list, NULL },
254 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
255};
256
257/* Parse LIBRARY, a string containing the loader info in XML format,
258 and return an lm_info_p vector.
259
260 Return NULL if the parsing failed. */
261
262static VEC (lm_info_p) *
263solib_aix_parse_libraries (const char *library)
264{
265 VEC (lm_info_p) *result = NULL;
266 struct cleanup *back_to = make_cleanup (solib_aix_free_library_list,
267 &result);
268
269 if (gdb_xml_parse_quick (_("aix library list"), "library-list-aix.dtd",
270 library_list_elements, library, &result) == 0)
271 {
272 /* Parsed successfully, keep the result. */
273 discard_cleanups (back_to);
274 return result;
275 }
276
277 do_cleanups (back_to);
278 return NULL;
279}
280
281#endif /* HAVE_LIBEXPAT */
282
283/* Return the loader info for the given inferior (INF), or NULL if
284 the list could not be computed.
285
286 Cache the result in per-inferior data, so as to avoid recomputing it
287 each time this function is called.
288
289 If an error occurs while computing this list, and WARNING_MSG
290 is not NULL, then print a warning including WARNING_MSG and
291 a description of the error. */
292
293static VEC (lm_info_p) *
294solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
295{
296 struct solib_aix_inferior_data *data;
297 char *library_document;
298 struct cleanup *cleanup;
299
300 /* If already computed, return the cached value. */
301 data = get_solib_aix_inferior_data (inf);
302 if (data->library_list != NULL)
303 return data->library_list;
304
305 library_document = target_read_stralloc (&current_target,
ff99b71b 306 TARGET_OBJECT_LIBRARIES_AIX,
4d1eb6b4
JB
307 NULL);
308 if (library_document == NULL && warning_msg != NULL)
309 {
ff99b71b 310 warning (_("%s (failed to read TARGET_OBJECT_LIBRARIES_AIX)"),
4d1eb6b4
JB
311 warning_msg);
312 return NULL;
313 }
314 cleanup = make_cleanup (xfree, library_document);
315
316 if (solib_aix_debug)
317 fprintf_unfiltered (gdb_stdlog,
ff99b71b 318 "DEBUG: TARGET_OBJECT_LIBRARIES_AIX = \n%s\n",
4d1eb6b4
JB
319 library_document);
320
321 data->library_list = solib_aix_parse_libraries (library_document);
322 if (data->library_list == NULL && warning_msg != NULL)
323 {
324 warning (_("%s (missing XML support?)"), warning_msg);
325 do_cleanups (cleanup);
326 return NULL;
327 }
328
329 do_cleanups (cleanup);
330 return data->library_list;
331}
332
333/* If the .bss section's VMA is set to an address located before
334 the end of the .data section, causing the two sections to overlap,
335 return the overlap in bytes. Otherwise, return zero.
336
337 Motivation:
338
339 The GNU linker sometimes sets the start address of the .bss session
340 before the end of the .data section, making the 2 sections overlap.
341 The loader appears to handle this situation gracefully, by simply
342 loading the bss section right after the end of the .data section.
343
344 This means that the .data and the .bss sections are sometimes
345 no longer relocated by the same amount. The problem is that
346 the ldinfo data does not contain any information regarding
347 the relocation of the .bss section, assuming that it would be
348 identical to the information provided for the .data section
349 (this is what would normally happen if the program was linked
350 correctly).
351
352 GDB therefore needs to detect those cases, and make the corresponding
353 adjustment to the .bss section offset computed from the ldinfo data
354 when necessary. This function returns the adjustment amount (or
355 zero when no adjustment is needed). */
356
357static CORE_ADDR
358solib_aix_bss_data_overlap (bfd *abfd)
359{
360 struct bfd_section *data_sect, *bss_sect;
361
362 data_sect = bfd_get_section_by_name (abfd, ".data");
363 if (data_sect == NULL)
364 return 0; /* No overlap possible. */
365
366 bss_sect = bfd_get_section_by_name (abfd, ".bss");
367 if (bss_sect == NULL)
368 return 0; /* No overlap possible. */
369
370 /* Assume the problem only occurs with linkers that place the .bss
371 section after the .data section (the problem has only been
372 observed when using the GNU linker, and the default linker
373 script always places the .data and .bss sections in that order). */
374 if (bfd_section_vma (abfd, bss_sect)
375 < bfd_section_vma (abfd, data_sect))
376 return 0;
377
378 if (bfd_section_vma (abfd, bss_sect)
379 < bfd_section_vma (abfd, data_sect) + bfd_get_section_size (data_sect))
380 return ((bfd_section_vma (abfd, data_sect)
381 + bfd_get_section_size (data_sect))
382 - bfd_section_vma (abfd, bss_sect));
383
384 return 0;
385}
386
387/* Implement the "relocate_section_addresses" target_so_ops method. */
388
389static void
390solib_aix_relocate_section_addresses (struct so_list *so,
391 struct target_section *sec)
392{
4d1eb6b4 393 struct bfd_section *bfd_sect = sec->the_bfd_section;
57e6060e 394 bfd *abfd = bfd_sect->owner;
4d1eb6b4
JB
395 const char *section_name = bfd_section_name (abfd, bfd_sect);
396 struct lm_info *info = so->lm_info;
397
398 if (strcmp (section_name, ".text") == 0)
399 {
400 sec->addr = info->text_addr;
401 sec->endaddr = sec->addr + info->text_size;
402
403 /* The text address given to us by the loader contains
404 XCOFF headers, so we need to adjust by this much. */
405 sec->addr += bfd_sect->filepos;
406 }
407 else if (strcmp (section_name, ".data") == 0)
408 {
409 sec->addr = info->data_addr;
410 sec->endaddr = sec->addr + info->data_size;
411 }
412 else if (strcmp (section_name, ".bss") == 0)
413 {
060cfbef
JB
414 /* The information provided by the loader does not include
415 the address of the .bss section, but we know that it gets
416 relocated by the same offset as the .data section. So,
417 compute the relocation offset for the .data section, and
418 apply it to the .bss section as well. If the .data section
419 is not defined (which seems highly unlikely), do our best
420 by assuming no relocation. */
421 struct bfd_section *data_sect
422 = bfd_get_section_by_name (abfd, ".data");
423 CORE_ADDR data_offset = 0;
424
425 if (data_sect != NULL)
426 data_offset = info->data_addr - bfd_section_vma (abfd, data_sect);
427
428 sec->addr = bfd_section_vma (abfd, bfd_sect) + data_offset;
4d1eb6b4
JB
429 sec->addr += solib_aix_bss_data_overlap (abfd);
430 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
431 }
432 else
433 {
434 /* All other sections should not be relocated. */
4d1eb6b4
JB
435 sec->addr = bfd_section_vma (abfd, bfd_sect);
436 sec->endaddr = sec->addr + bfd_section_size (abfd, bfd_sect);
437 }
438}
439
440/* Implement the "free_so" target_so_ops method. */
441
442static void
443solib_aix_free_so (struct so_list *so)
444{
445 if (solib_aix_debug)
446 fprintf_unfiltered (gdb_stdlog, "DEBUG: solib_aix_free_so (%s)\n",
447 so->so_name);
448 solib_aix_xfree_lm_info (so->lm_info);
449}
450
451/* Implement the "clear_solib" target_so_ops method. */
452
453static void
454solib_aix_clear_solib (void)
455{
456 /* Nothing needed. */
457}
458
459/* Compute and return the OBJFILE's section_offset array, using
460 the associated loader info (INFO).
461
462 The resulting array is computed on the heap and must be
463 deallocated after use. */
464
465static struct section_offsets *
466solib_aix_get_section_offsets (struct objfile *objfile,
467 struct lm_info *info)
468{
469 struct section_offsets *offsets;
470 bfd *abfd = objfile->obfd;
471 int i;
472
473 offsets = XCALLOC (objfile->num_sections, struct section_offsets);
474
475 /* .text */
476
477 if (objfile->sect_index_text != -1)
478 {
479 struct bfd_section *sect
480 = objfile->sections[objfile->sect_index_text].the_bfd_section;
481
482 offsets->offsets[objfile->sect_index_text]
483 = info->text_addr + sect->filepos - bfd_section_vma (abfd, sect);
484 }
485
486 /* .data */
487
488 if (objfile->sect_index_data != -1)
489 {
490 struct bfd_section *sect
491 = objfile->sections[objfile->sect_index_data].the_bfd_section;
492
493 offsets->offsets[objfile->sect_index_data]
494 = info->data_addr - bfd_section_vma (abfd, sect);
495 }
496
497 /* .bss
498
499 The offset of the .bss section should be identical to the offset
500 of the .data section. If no .data section (which seems hard to
501 believe it is possible), assume it is zero. */
502
503 if (objfile->sect_index_bss != -1
504 && objfile->sect_index_data != -1)
505 {
506 offsets->offsets[objfile->sect_index_bss]
507 = (offsets->offsets[objfile->sect_index_data]
508 + solib_aix_bss_data_overlap (abfd));
509 }
510
511 /* All other sections should not need relocation. */
512
513 return offsets;
514}
515
516/* Implement the "solib_create_inferior_hook" target_so_ops method. */
517
518static void
519solib_aix_solib_create_inferior_hook (int from_tty)
520{
521 const char *warning_msg = "unable to relocate main executable";
522 VEC (lm_info_p) *library_list;
523 struct lm_info *exec_info;
524
525 /* We need to relocate the main executable... */
526
527 library_list = solib_aix_get_library_list (current_inferior (),
528 warning_msg);
529 if (library_list == NULL)
530 return; /* Warning already printed. */
531
532 if (VEC_length (lm_info_p, library_list) < 1)
533 {
534 warning (_("unable to relocate main executable (no info from loader)"));
535 return;
536 }
537
538 exec_info = VEC_index (lm_info_p, library_list, 0);
539
540 if (symfile_objfile != NULL)
541 {
542 struct section_offsets *offsets
543 = solib_aix_get_section_offsets (symfile_objfile, exec_info);
544 struct cleanup *cleanup = make_cleanup (xfree, offsets);
545
546 objfile_relocate (symfile_objfile, offsets);
547 do_cleanups (cleanup);
548 }
549}
550
551/* Implement the "special_symbol_handling" target_so_ops method. */
552
553static void
554solib_aix_special_symbol_handling (void)
555{
556 /* Nothing needed. */
557}
558
559/* Implement the "current_sos" target_so_ops method. */
560
561static struct so_list *
562solib_aix_current_sos (void)
563{
564 struct so_list *start = NULL, *last = NULL;
565 VEC (lm_info_p) *library_list;
566 struct lm_info *info;
567 int ix;
568
569 library_list = solib_aix_get_library_list (current_inferior (), NULL);
570 if (library_list == NULL)
571 return NULL;
572
573 /* Build a struct so_list for each entry on the list.
574 We skip the first entry, since this is the entry corresponding
575 to the main executable, not a shared library. */
576 for (ix = 1; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
577 {
578 struct so_list *new_solib = XZALLOC (struct so_list);
579 char *so_name;
580
581 if (info->member_name == NULL)
582 {
583 /* INFO->FILENAME is probably not an archive, but rather
584 a shared object. Unusual, but it should be possible
585 to link a program against a shared object directory,
586 without having to put it in an archive first. */
587 so_name = xstrdup (info->filename);
588 }
589 else
590 {
591 /* This is the usual case on AIX, where the shared object
592 is a member of an archive. Create a synthetic so_name
593 that follows the same convention as AIX's ldd tool
594 (Eg: "/lib/libc.a(shr.o)"). */
595 so_name = xstrprintf ("%s(%s)", info->filename, info->member_name);
596 }
597 strncpy (new_solib->so_original_name, so_name,
598 SO_NAME_MAX_PATH_SIZE - 1);
599 new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
600 memcpy (new_solib->so_name, new_solib->so_original_name,
601 SO_NAME_MAX_PATH_SIZE);
602 new_solib->lm_info = solib_aix_new_lm_info (info);
603
604 /* Add it to the list. */
605 if (!start)
606 last = start = new_solib;
607 else
608 {
609 last->next = new_solib;
610 last = new_solib;
611 }
612 }
613
614 return start;
615}
616
617/* Implement the "open_symbol_file_object" target_so_ops method. */
618
619static int
620solib_aix_open_symbol_file_object (void *from_ttyp)
621{
622 return 0;
623}
624
625/* Implement the "in_dynsym_resolve_code" target_so_ops method. */
626
627static int
628solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
629{
630 return 0;
631}
632
633/* Implement the "bfd_open" target_so_ops method. */
634
635static bfd *
636solib_aix_bfd_open (char *pathname)
637{
638 /* The pathname is actually a synthetic filename with the following
639 form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
640 split this into archive name and member name.
641
642 FIXME: This is a little hacky. Perhaps we should provide access
643 to the solib's lm_info here? */
644 const int path_len = strlen (pathname);
645 char *sep;
646 char *filename;
647 int filename_len;
648 char *member_name;
649 bfd *archive_bfd, *object_bfd;
e35ac9bf 650 struct cleanup *cleanup;
4d1eb6b4
JB
651
652 if (pathname[path_len - 1] != ')')
653 return solib_bfd_open (pathname);
654
655 /* Search for the associated parens. */
656 sep = strrchr (pathname, '(');
657 if (sep == NULL)
658 {
659 /* Should never happen, but recover as best as we can (trying
660 to open pathname without decoding, possibly leading to
661 a failure), rather than triggering an assert failure). */
662 warning (_("missing '(' in shared object pathname: %s"), pathname);
663 return solib_bfd_open (pathname);
664 }
665 filename_len = sep - pathname;
666
667 filename = xstrprintf ("%.*s", filename_len, pathname);
e35ac9bf 668 cleanup = make_cleanup (xfree, filename);
4d1eb6b4
JB
669 member_name = xstrprintf ("%.*s", path_len - filename_len - 2, sep + 1);
670 make_cleanup (xfree, member_name);
671
672 archive_bfd = gdb_bfd_open (filename, gnutarget, -1);
673 if (archive_bfd == NULL)
674 {
675 warning (_("Could not open `%s' as an executable file: %s"),
676 filename, bfd_errmsg (bfd_get_error ()));
677 do_cleanups (cleanup);
678 return NULL;
679 }
680
681 if (bfd_check_format (archive_bfd, bfd_object))
682 {
683 do_cleanups (cleanup);
684 return archive_bfd;
685 }
686
687 if (! bfd_check_format (archive_bfd, bfd_archive))
688 {
689 warning (_("\"%s\": not in executable format: %s."),
690 filename, bfd_errmsg (bfd_get_error ()));
691 gdb_bfd_unref (archive_bfd);
692 do_cleanups (cleanup);
693 return NULL;
694 }
695
696 object_bfd = gdb_bfd_openr_next_archived_file (archive_bfd, NULL);
697 while (object_bfd != NULL)
698 {
699 bfd *next;
700
701 if (strcmp (member_name, object_bfd->filename) == 0)
702 break;
703
704 next = gdb_bfd_openr_next_archived_file (archive_bfd, object_bfd);
705 gdb_bfd_unref (object_bfd);
706 object_bfd = next;
707 }
708
709 if (object_bfd == NULL)
710 {
711 warning (_("\"%s\": member \"%s\" missing."), filename, member_name);
712 gdb_bfd_unref (archive_bfd);
713 do_cleanups (cleanup);
714 return NULL;
715 }
716
717 if (! bfd_check_format (object_bfd, bfd_object))
718 {
719 warning (_("%s(%s): not in object format: %s."),
720 filename, member_name, bfd_errmsg (bfd_get_error ()));
721 gdb_bfd_unref (archive_bfd);
722 gdb_bfd_unref (object_bfd);
723 do_cleanups (cleanup);
724 return NULL;
725 }
726
727 gdb_bfd_unref (archive_bfd);
728 do_cleanups (cleanup);
729 return object_bfd;
730}
731
732/* Return the obj_section corresponding to OBJFILE's data section,
733 or NULL if not found. */
734/* FIXME: Define in a more general location? */
735
736static struct obj_section *
737data_obj_section_from_objfile (struct objfile *objfile)
738{
739 struct obj_section *osect;
740
741 ALL_OBJFILE_OSECTIONS (objfile, osect)
742 if (strcmp (bfd_section_name (objfile->obfd, osect->the_bfd_section),
743 ".data") == 0)
744 return osect;
745
746 return NULL;
747}
748
749/* Return the TOC value corresponding to the given PC address,
750 or raise an error if the value could not be determined. */
751
752CORE_ADDR
753solib_aix_get_toc_value (CORE_ADDR pc)
754{
755 struct obj_section *pc_osect = find_pc_section (pc);
756 struct obj_section *data_osect;
757 CORE_ADDR result;
758
759 if (pc_osect == NULL)
760 error (_("unable to find TOC entry for pc %s "
761 "(no section contains this PC)"),
762 core_addr_to_string (pc));
763
764 data_osect = data_obj_section_from_objfile (pc_osect->objfile);
765 if (data_osect == NULL)
766 error (_("unable to find TOC entry for pc %s "
767 "(%s has no data section)"),
4262abfb 768 core_addr_to_string (pc), objfile_name (pc_osect->objfile));
4d1eb6b4
JB
769
770 result = (obj_section_addr (data_osect)
771 + xcoff_get_toc_offset (pc_osect->objfile));
772 if (solib_aix_debug)
773 fprintf_unfiltered (gdb_stdlog,
774 "DEBUG: solib_aix_get_toc_value (pc=%s) -> %s\n",
775 core_addr_to_string (pc),
776 core_addr_to_string (result));
777
778 return result;
779}
780
781/* This module's normal_stop observer. */
782
783static void
784solib_aix_normal_stop_observer (struct bpstats *unused_1, int unused_2)
785{
786 struct solib_aix_inferior_data *data
787 = get_solib_aix_inferior_data (current_inferior ());
788
789 /* The inferior execution has been resumed, and it just stopped
790 again. This means that the list of shared libraries may have
791 evolved. Reset our cached value. */
792 solib_aix_free_library_list (&data->library_list);
793}
794
795/* Implements the "show debug aix-solib" command. */
796
797static void
798show_solib_aix_debug (struct ui_file *file, int from_tty,
799 struct cmd_list_element *c, const char *value)
800{
801 fprintf_filtered (file, _("solib-aix debugging is %s.\n"), value);
802}
803
804/* The target_so_ops for AIX targets. */
805struct target_so_ops solib_aix_so_ops;
806
807/* -Wmissing-prototypes */
808extern initialize_file_ftype _initialize_solib_aix;
809
810void
811_initialize_solib_aix (void)
812{
813 solib_aix_so_ops.relocate_section_addresses
814 = solib_aix_relocate_section_addresses;
815 solib_aix_so_ops.free_so = solib_aix_free_so;
816 solib_aix_so_ops.clear_solib = solib_aix_clear_solib;
817 solib_aix_so_ops.solib_create_inferior_hook
818 = solib_aix_solib_create_inferior_hook;
819 solib_aix_so_ops.special_symbol_handling
820 = solib_aix_special_symbol_handling;
821 solib_aix_so_ops.current_sos = solib_aix_current_sos;
822 solib_aix_so_ops.open_symbol_file_object
823 = solib_aix_open_symbol_file_object;
824 solib_aix_so_ops.in_dynsym_resolve_code
825 = solib_aix_in_dynsym_resolve_code;
826 solib_aix_so_ops.bfd_open = solib_aix_bfd_open;
827
828 solib_aix_inferior_data_handle = register_inferior_data ();
829
830 observer_attach_normal_stop (solib_aix_normal_stop_observer);
831
832 /* Debug this file's internals. */
833 add_setshow_boolean_cmd ("aix-solib", class_maintenance,
834 &solib_aix_debug, _("\
835Control the debugging traces for the solib-aix module."), _("\
836Show whether solib-aix debugging traces are enabled."), _("\
837When on, solib-aix debugging traces are enabled."),
838 NULL,
839 show_solib_aix_debug,
840 &setdebuglist, &showdebuglist);
841}
This page took 0.113722 seconds and 4 git commands to generate.