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