* thread-db.c (check_event): Don't report an error if we encounter
[deliverable/binutils-gdb.git] / gdb / solib-aix5.c
1 /* Handle AIX5 shared libraries for GDB, the GNU Debugger.
2 Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
3 2001
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
10 the Free Software Foundation; either version 2 of the License, or
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
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 #include "defs.h"
24
25 #include <sys/types.h>
26 #include <signal.h>
27 #include "gdb_string.h"
28 #include <sys/param.h>
29 #include <fcntl.h>
30 #include <sys/procfs.h>
31
32 #include "elf/external.h"
33
34 #include "symtab.h"
35 #include "bfd.h"
36 #include "symfile.h"
37 #include "objfiles.h"
38 #include "gdbcore.h"
39 #include "command.h"
40 #include "target.h"
41 #include "frame.h"
42 #include "gdb_regex.h"
43 #include "inferior.h"
44 #include "environ.h"
45 #include "language.h"
46 #include "gdbcmd.h"
47
48 #include "solist.h"
49
50 /* Link map info to include in an allocated so_list entry */
51
52 enum maptype {
53 MT_READONLY = 0,
54 MT_READWRITE = 1,
55 MT_LAST = 2
56 };
57
58 struct lm_info
59 {
60 struct
61 {
62 CORE_ADDR addr; /* base address */
63 CORE_ADDR size; /* size of mapped object */
64 CORE_ADDR offset; /* offset into mapped object */
65 long flags; /* MA_ protection and attribute flags */
66 CORE_ADDR gp; /* global pointer value */
67 } mapping[MT_LAST];
68 char *mapname; /* name in /proc/pid/object */
69 char *pathname; /* full pathname to object */
70 char *membername; /* member name in archive file */
71 };
72
73 /* List of symbols in the dynamic linker where GDB can try to place
74 a breakpoint to monitor shared library events. */
75
76 static char *solib_break_names[] =
77 {
78 "_r_debug_state",
79 NULL
80 };
81
82 static void aix5_relocate_main_executable (void);
83
84 /*
85
86 LOCAL FUNCTION
87
88 bfd_lookup_symbol -- lookup the value for a specific symbol
89
90 SYNOPSIS
91
92 CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
93
94 DESCRIPTION
95
96 An expensive way to lookup the value of a single symbol for
97 bfd's that are only temporary anyway. This is used by the
98 shared library support to find the address of the debugger
99 interface structures in the shared library.
100
101 Note that 0 is specifically allowed as an error return (no
102 such symbol).
103 */
104
105 static CORE_ADDR
106 bfd_lookup_symbol (bfd *abfd, char *symname)
107 {
108 long storage_needed;
109 asymbol *sym;
110 asymbol **symbol_table;
111 unsigned int number_of_symbols;
112 unsigned int i;
113 struct cleanup *back_to;
114 CORE_ADDR symaddr = 0;
115
116 storage_needed = bfd_get_symtab_upper_bound (abfd);
117
118 if (storage_needed > 0)
119 {
120 symbol_table = (asymbol **) xmalloc (storage_needed);
121 back_to = make_cleanup (xfree, symbol_table);
122 number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
123
124 for (i = 0; i < number_of_symbols; i++)
125 {
126 sym = *symbol_table++;
127 if (strcmp (sym->name, symname) == 0)
128 {
129 /* Bfd symbols are section relative. */
130 symaddr = sym->value + sym->section->vma;
131 break;
132 }
133 }
134 do_cleanups (back_to);
135 }
136
137 if (symaddr)
138 return symaddr;
139
140 /* Look for the symbol in the dynamic string table too. */
141
142 storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd);
143
144 if (storage_needed > 0)
145 {
146 symbol_table = (asymbol **) xmalloc (storage_needed);
147 back_to = make_cleanup (xfree, symbol_table);
148 number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table);
149
150 for (i = 0; i < number_of_symbols; i++)
151 {
152 sym = *symbol_table++;
153 if (strcmp (sym->name, symname) == 0)
154 {
155 /* Bfd symbols are section relative. */
156 symaddr = sym->value + sym->section->vma;
157 break;
158 }
159 }
160 do_cleanups (back_to);
161 }
162
163 return symaddr;
164 }
165
166
167 /* Read /proc/PID/map and build a list of shared objects such that
168 the pr_mflags value AND'd with MATCH_MASK is equal to MATCH_VAL.
169 This gives us a convenient way to find all of the mappings that
170 don't belong to the main executable or vice versa. Here are
171 some of the possibilities:
172
173 - Fetch all mappings:
174 MATCH_MASK: 0
175 MATCH_VAL: 0
176 - Fetch all mappings except for main executable:
177 MATCH_MASK: MA_MAINEXEC
178 MATCH_VAL: 0
179 - Fetch only main executable:
180 MATCH_MASK: MA_MAINEXEC
181 MATCH_VAL: MA_MAINEXEC
182
183 A cleanup chain for the list allocations done by this function should
184 be established prior to calling build_so_list_from_mapfile(). */
185
186 static struct so_list *
187 build_so_list_from_mapfile (int pid, long match_mask, long match_val)
188 {
189 char *mapbuf = NULL;
190 struct prmap *prmap;
191 int mapbuf_size;
192 struct so_list *sos = NULL;
193
194 {
195 int mapbuf_allocation_size = 8192;
196 char *map_pathname;
197 int map_fd;
198
199 /* Open the map file */
200
201 xasprintf (&map_pathname, "/proc/%d/map", pid);
202 map_fd = open (map_pathname, O_RDONLY);
203 xfree (map_pathname);
204 if (map_fd < 0)
205 return 0;
206
207 /* Read the entire map file in */
208 do
209 {
210 if (mapbuf)
211 {
212 xfree (mapbuf);
213 mapbuf_allocation_size *= 2;
214 lseek (map_fd, 0, SEEK_SET);
215 }
216 mapbuf = xmalloc (mapbuf_allocation_size);
217 mapbuf_size = read (map_fd, mapbuf, mapbuf_allocation_size);
218 if (mapbuf_size < 0)
219 {
220 xfree (mapbuf);
221 /* FIXME: This warrants an error or a warning of some sort */
222 return 0;
223 }
224 } while (mapbuf_size == mapbuf_allocation_size);
225
226 close (map_fd);
227 }
228
229 for (prmap = (struct prmap *) mapbuf;
230 (char *) prmap < mapbuf + mapbuf_size;
231 prmap++)
232 {
233 char *mapname, *pathname, *membername;
234 struct so_list *sop;
235 enum maptype maptype;
236
237 if (prmap->pr_size == 0)
238 break;
239
240 /* Skip to the next entry if there's no path associated with the
241 map, unless we're looking for the kernel text region, in which
242 case it's okay if there's no path. */
243 if ((prmap->pr_pathoff == 0 || prmap->pr_pathoff >= mapbuf_size)
244 && ((match_mask & MA_KERNTEXT) == 0))
245 continue;
246
247 /* Skip to the next entry if our match conditions don't hold. */
248 if ((prmap->pr_mflags & match_mask) != match_val)
249 continue;
250
251 mapname = prmap->pr_mapname;
252 if (prmap->pr_pathoff == 0)
253 {
254 pathname = "";
255 membername = "";
256 }
257 else
258 {
259 pathname = mapbuf + prmap->pr_pathoff;
260 membername = pathname + strlen (pathname) + 1;
261 }
262
263 for (sop = sos; sop != NULL; sop = sop->next)
264 if (strcmp (pathname, sop->lm_info->pathname) == 0
265 && strcmp (membername, sop->lm_info->membername) == 0)
266 break;
267
268 if (sop == NULL)
269 {
270 sop = xcalloc (sizeof (struct so_list), 1);
271 make_cleanup (xfree, sop);
272 sop->lm_info = xcalloc (sizeof (struct lm_info), 1);
273 make_cleanup (xfree, sop->lm_info);
274 sop->lm_info->mapname = xstrdup (mapname);
275 make_cleanup (xfree, sop->lm_info->mapname);
276 /* FIXME: Eliminate the pathname field once length restriction
277 is lifted on so_name and so_original_name. */
278 sop->lm_info->pathname = xstrdup (pathname);
279 make_cleanup (xfree, sop->lm_info->pathname);
280 sop->lm_info->membername = xstrdup (membername);
281 make_cleanup (xfree, sop->lm_info->membername);
282
283 strncpy (sop->so_name, pathname, SO_NAME_MAX_PATH_SIZE - 1);
284 sop->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
285 strcpy (sop->so_original_name, sop->so_name);
286
287 sop->next = sos;
288 sos = sop;
289 }
290
291 maptype = (prmap->pr_mflags & MA_WRITE) ? MT_READWRITE : MT_READONLY;
292 sop->lm_info->mapping[maptype].addr = (CORE_ADDR) prmap->pr_vaddr;
293 sop->lm_info->mapping[maptype].size = prmap->pr_size;
294 sop->lm_info->mapping[maptype].offset = prmap->pr_off;
295 sop->lm_info->mapping[maptype].flags = prmap->pr_mflags;
296 sop->lm_info->mapping[maptype].gp = (CORE_ADDR) prmap->pr_gp;
297 }
298
299 xfree (mapbuf);
300 return sos;
301 }
302
303 /*
304
305 LOCAL FUNCTION
306
307 open_symbol_file_object
308
309 SYNOPSIS
310
311 void open_symbol_file_object (void *from_tty)
312
313 DESCRIPTION
314
315 If no open symbol file, attempt to locate and open the main symbol
316 file.
317
318 If FROM_TTYP dereferences to a non-zero integer, allow messages to
319 be printed. This parameter is a pointer rather than an int because
320 open_symbol_file_object() is called via catch_errors() and
321 catch_errors() requires a pointer argument. */
322
323 static int
324 open_symbol_file_object (void *from_ttyp)
325 {
326 CORE_ADDR lm, l_name;
327 char *filename;
328 int errcode;
329 int from_tty = *(int *)from_ttyp;
330 struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
331 struct so_list *sos;
332
333 sos = build_so_list_from_mapfile (PIDGET (inferior_pid),
334 MA_MAINEXEC, MA_MAINEXEC);
335
336
337 if (sos == NULL)
338 {
339 warning ("Could not find name of main executable in map file");
340 return 0;
341 }
342
343 symbol_file_command (sos->lm_info->pathname, from_tty);
344
345 do_cleanups (old_chain);
346
347 aix5_relocate_main_executable ();
348
349 return 1;
350 }
351
352 /* LOCAL FUNCTION
353
354 aix5_current_sos -- build a list of currently loaded shared objects
355
356 SYNOPSIS
357
358 struct so_list *aix5_current_sos ()
359
360 DESCRIPTION
361
362 Build a list of `struct so_list' objects describing the shared
363 objects currently loaded in the inferior. This list does not
364 include an entry for the main executable file.
365
366 Note that we only gather information directly available from the
367 inferior --- we don't examine any of the shared library files
368 themselves. The declaration of `struct so_list' says which fields
369 we provide values for. */
370
371 static struct so_list *
372 aix5_current_sos (void)
373 {
374 struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
375 struct so_list *sos;
376
377 /* Fetch the list of mappings, excluding the main executable. */
378 sos = build_so_list_from_mapfile (PIDGET (inferior_pid), MA_MAINEXEC, 0);
379
380 /* Reverse the list; it looks nicer when we print it if the mappings
381 are in the same order as in the map file. */
382 if (sos)
383 {
384 struct so_list *next = sos->next;
385
386 sos->next = 0;
387 while (next)
388 {
389 struct so_list *prev = sos;
390
391 sos = next;
392 next = next->next;
393 sos->next = prev;
394 }
395 }
396 discard_cleanups (old_chain);
397 return sos;
398 }
399
400
401 /* Return 1 if PC lies in the dynamic symbol resolution code of the
402 run time loader. */
403
404 static CORE_ADDR interp_text_sect_low;
405 static CORE_ADDR interp_text_sect_high;
406 static CORE_ADDR interp_plt_sect_low;
407 static CORE_ADDR interp_plt_sect_high;
408
409 static int
410 aix5_in_dynsym_resolve_code (CORE_ADDR pc)
411 {
412 return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
413 || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
414 || in_plt_section (pc, NULL));
415 }
416
417 /*
418
419 LOCAL FUNCTION
420
421 enable_break -- arrange for dynamic linker to hit breakpoint
422
423 SYNOPSIS
424
425 int enable_break (void)
426
427 DESCRIPTION
428
429 The dynamic linkers has, as part of its debugger interface, support
430 for arranging for the inferior to hit a breakpoint after mapping in
431 the shared libraries. This function enables that breakpoint.
432
433 */
434
435 static int
436 enable_break (void)
437 {
438 int success = 0;
439
440 struct minimal_symbol *msymbol;
441 char **bkpt_namep;
442 asection *interp_sect;
443
444 /* First, remove all the solib event breakpoints. Their addresses
445 may have changed since the last time we ran the program. */
446 remove_solib_event_breakpoints ();
447
448 interp_text_sect_low = interp_text_sect_high = 0;
449 interp_plt_sect_low = interp_plt_sect_high = 0;
450
451 /* Find the .interp section; if not found, warn the user and drop
452 into the old breakpoint at symbol code. */
453 interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
454 if (interp_sect)
455 {
456 unsigned int interp_sect_size;
457 char *buf;
458 CORE_ADDR load_addr;
459 bfd *tmp_bfd;
460 CORE_ADDR sym_addr = 0;
461
462 /* Read the contents of the .interp section into a local buffer;
463 the contents specify the dynamic linker this program uses. */
464 interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
465 buf = alloca (interp_sect_size);
466 bfd_get_section_contents (exec_bfd, interp_sect,
467 buf, 0, interp_sect_size);
468
469 /* Now we need to figure out where the dynamic linker was
470 loaded so that we can load its symbols and place a breakpoint
471 in the dynamic linker itself.
472
473 This address is stored on the stack. However, I've been unable
474 to find any magic formula to find it for Solaris (appears to
475 be trivial on GNU/Linux). Therefore, we have to try an alternate
476 mechanism to find the dynamic linker's base address. */
477 tmp_bfd = bfd_openr (buf, gnutarget);
478 if (tmp_bfd == NULL)
479 goto bkpt_at_symbol;
480
481 /* Make sure the dynamic linker's really a useful object. */
482 if (!bfd_check_format (tmp_bfd, bfd_object))
483 {
484 warning ("Unable to grok dynamic linker %s as an object file", buf);
485 bfd_close (tmp_bfd);
486 goto bkpt_at_symbol;
487 }
488
489 /* We find the dynamic linker's base address by examining the
490 current pc (which point at the entry point for the dynamic
491 linker) and subtracting the offset of the entry point. */
492 load_addr = read_pc () - tmp_bfd->start_address;
493
494 /* Record the relocated start and end address of the dynamic linker
495 text and plt section for aix5_in_dynsym_resolve_code. */
496 interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
497 if (interp_sect)
498 {
499 interp_text_sect_low =
500 bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
501 interp_text_sect_high =
502 interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
503 }
504 interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
505 if (interp_sect)
506 {
507 interp_plt_sect_low =
508 bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
509 interp_plt_sect_high =
510 interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
511 }
512
513 /* Now try to set a breakpoint in the dynamic linker. */
514 for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
515 {
516 sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
517 if (sym_addr != 0)
518 break;
519 }
520
521 /* We're done with the temporary bfd. */
522 bfd_close (tmp_bfd);
523
524 if (sym_addr != 0)
525 {
526 create_solib_event_breakpoint (load_addr + sym_addr);
527 return 1;
528 }
529
530 /* For whatever reason we couldn't set a breakpoint in the dynamic
531 linker. Warn and drop into the old code. */
532 bkpt_at_symbol:
533 warning ("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.");
534 }
535
536 /* Nothing good happened. */
537 success = 0;
538
539 return (success);
540 }
541
542 /*
543
544 LOCAL FUNCTION
545
546 special_symbol_handling -- additional shared library symbol handling
547
548 SYNOPSIS
549
550 void special_symbol_handling ()
551
552 DESCRIPTION
553
554 Once the symbols from a shared object have been loaded in the usual
555 way, we are called to do any system specific symbol handling that
556 is needed.
557
558 */
559
560 static void
561 aix5_special_symbol_handling (void)
562 {
563 /* Nothing needed (yet) for AIX5. */
564 }
565
566 #define SECTMAPMASK (~ (CORE_ADDR) 0x03ffffff)
567
568 static void
569 aix5_relocate_main_executable (void)
570 {
571 struct so_list *so;
572 struct section_offsets *new_offsets;
573 int i;
574 int changed = 0;
575 struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
576
577 /* Fetch the mappings for the main executable from the map file. */
578 so = build_so_list_from_mapfile (PIDGET (inferior_pid),
579 MA_MAINEXEC, MA_MAINEXEC);
580
581 /* Make sure we actually have some mappings to work with. */
582 if (so == NULL)
583 {
584 warning ("Could not find main executable in map file");
585 do_cleanups (old_chain);
586 return;
587 }
588
589 /* Allocate the data structure which'll contain the new offsets to
590 relocate by. Initialize it so it contains the current offsets. */
591 new_offsets = xcalloc (sizeof (struct section_offsets),
592 symfile_objfile->num_sections);
593 make_cleanup (xfree, new_offsets);
594 for (i = 0; i < symfile_objfile->num_sections; i++)
595 new_offsets->offsets[i] = ANOFFSET (symfile_objfile->section_offsets, i);
596
597 /* Iterate over the mappings in the main executable and compute
598 the new offset value as appropriate. */
599 for (i = 0; i < MT_LAST; i++)
600 {
601 CORE_ADDR increment = 0;
602 struct obj_section *sect;
603 bfd *obfd = symfile_objfile->obfd;
604
605 ALL_OBJFILE_OSECTIONS (symfile_objfile, sect)
606 {
607 int flags = bfd_get_section_flags (obfd, sect->the_bfd_section);
608 if (flags & SEC_ALLOC)
609 {
610 if (((so->lm_info->mapping[i].flags & MA_WRITE) == 0)
611 == ((flags & SEC_READONLY) != 0))
612 {
613 int idx = sect->the_bfd_section->index;
614
615 if (increment == 0)
616 increment = so->lm_info->mapping[i].addr
617 - (bfd_section_vma (obfd, sect->the_bfd_section)
618 & SECTMAPMASK);
619
620 if (increment != ANOFFSET (new_offsets, idx))
621 {
622 new_offsets->offsets[idx] = increment;
623 changed = 1;
624 }
625 }
626 }
627 }
628 }
629
630 /* If any of the offsets have changed, then relocate the objfile. */
631 if (changed)
632 objfile_relocate (symfile_objfile, new_offsets);
633
634 /* Free up all the space we've allocated. */
635 do_cleanups (old_chain);
636 }
637
638 /*
639
640 GLOBAL FUNCTION
641
642 aix5_solib_create_inferior_hook -- shared library startup support
643
644 SYNOPSIS
645
646 void aix5_solib_create_inferior_hook()
647
648 DESCRIPTION
649
650 When gdb starts up the inferior, it nurses it along (through the
651 shell) until it is ready to execute it's first instruction. At this
652 point, this function gets called via expansion of the macro
653 SOLIB_CREATE_INFERIOR_HOOK.
654
655 For AIX5 executables, this first instruction is the first
656 instruction in the dynamic linker (for dynamically linked
657 executables) or the instruction at "start" for statically linked
658 executables. For dynamically linked executables, the system
659 first exec's libc.so.N, which contains the dynamic linker,
660 and starts it running. The dynamic linker maps in any needed
661 shared libraries, maps in the actual user executable, and then
662 jumps to "start" in the user executable.
663
664 */
665
666 static void
667 aix5_solib_create_inferior_hook (void)
668 {
669 aix5_relocate_main_executable ();
670
671 if (!enable_break ())
672 {
673 warning ("shared library handler failed to enable breakpoint");
674 return;
675 }
676 }
677
678 static void
679 aix5_clear_solib (void)
680 {
681 }
682
683 static void
684 aix5_free_so (struct so_list *so)
685 {
686 xfree (so->lm_info->mapname);
687 xfree (so->lm_info->pathname);
688 xfree (so->lm_info->membername);
689 xfree (so->lm_info);
690 }
691
692 static void
693 aix5_relocate_section_addresses (struct so_list *so,
694 struct section_table *sec)
695 {
696 int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
697
698 if (flags & SEC_ALLOC)
699 {
700 int idx = (flags & SEC_READONLY) ? MT_READONLY : MT_READWRITE;
701 CORE_ADDR addr = so->lm_info->mapping[idx].addr;
702
703 sec->addr += addr;
704 sec->endaddr += addr;
705 }
706 }
707
708 /* Find the global pointer for the given function address ADDR. */
709
710 static CORE_ADDR
711 aix5_find_global_pointer (CORE_ADDR addr)
712 {
713 struct so_list *sos, *so;
714 CORE_ADDR global_pointer = 0;
715 struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
716
717 sos = build_so_list_from_mapfile (PIDGET (inferior_pid), 0, 0);
718
719 for (so = sos; so != NULL; so = so->next)
720 {
721 if (so->lm_info->mapping[MT_READONLY].addr <= addr
722 && addr <= so->lm_info->mapping[MT_READONLY].addr
723 + so->lm_info->mapping[MT_READONLY].size)
724 {
725 global_pointer = so->lm_info->mapping[MT_READWRITE].gp;
726 break;
727 }
728 }
729
730 do_cleanups (old_chain);
731
732 return global_pointer;
733 }
734
735 /* Find the execute-only kernel region known as the gate page. This
736 page is where the signal trampoline lives. It may be found by
737 querying the map file and looking for the MA_KERNTEXT flag. */
738 static void
739 aix5_find_gate_addresses (CORE_ADDR *start, CORE_ADDR *end)
740 {
741 struct so_list *so;
742 struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
743
744 /* Fetch the mappings for the main executable from the map file. */
745 so = build_so_list_from_mapfile (PIDGET (inferior_pid),
746 MA_KERNTEXT, MA_KERNTEXT);
747
748 /* Make sure we actually have some mappings to work with. */
749 if (so == NULL)
750 {
751 warning ("Could not find gate page in map file");
752 *start = 0;
753 *end = 0;
754 do_cleanups (old_chain);
755 return;
756 }
757
758 /* There should only be on kernel mapping for the gate page and
759 it'll be in the read-only (even though it's execute-only)
760 mapping in the lm_info struct. */
761
762 *start = so->lm_info->mapping[MT_READONLY].addr;
763 *end = *start + so->lm_info->mapping[MT_READONLY].size;
764
765 /* Free up all the space we've allocated. */
766 do_cleanups (old_chain);
767 }
768
769 /* From ia64-tdep.c. FIXME: If we end up using this for rs6000 too,
770 we'll need to make the names match. */
771 extern CORE_ADDR (*native_find_global_pointer) (CORE_ADDR);
772
773 /* From ia64-aix-tdep.c. Hook for finding the starting and
774 ending gate page addresses. The only reason that this hook
775 is in this file is because this is where the map file reading
776 code is located. */
777 extern void (*aix5_find_gate_addresses_hook) (CORE_ADDR *, CORE_ADDR *);
778
779 static struct target_so_ops aix5_so_ops;
780
781 void
782 _initialize_aix5_solib (void)
783 {
784 aix5_so_ops.relocate_section_addresses = aix5_relocate_section_addresses;
785 aix5_so_ops.free_so = aix5_free_so;
786 aix5_so_ops.clear_solib = aix5_clear_solib;
787 aix5_so_ops.solib_create_inferior_hook = aix5_solib_create_inferior_hook;
788 aix5_so_ops.special_symbol_handling = aix5_special_symbol_handling;
789 aix5_so_ops.current_sos = aix5_current_sos;
790 aix5_so_ops.open_symbol_file_object = open_symbol_file_object;
791 aix5_so_ops.in_dynsym_resolve_code = aix5_in_dynsym_resolve_code;
792
793 native_find_global_pointer = aix5_find_global_pointer;
794 aix5_find_gate_addresses_hook = aix5_find_gate_addresses;
795
796 /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */
797 current_target_so_ops = &aix5_so_ops;
798 }
This page took 0.045358 seconds and 4 git commands to generate.