X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fsolib-aix5.c;h=1a8c9dfeea94d8ae575f0e25eb25decb2803bd82;hb=7c46b9fb41fd107882032ecc34897a8e86e8264a;hp=314408ec3687b86f1459fc6e29d1bb477d7f1669;hpb=6c98e688d5bbc670851c9e092c132a565eb67519;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/solib-aix5.c b/gdb/solib-aix5.c index 314408ec36..1a8c9dfeea 100644 --- a/gdb/solib-aix5.c +++ b/gdb/solib-aix5.c @@ -262,9 +262,9 @@ build_so_list_from_mapfile (int pid, long match_mask, long match_val) if (sop == NULL) { - sop = xcalloc (sizeof (struct so_list), 1); + sop = xcalloc (1, sizeof (struct so_list)); make_cleanup (xfree, sop); - sop->lm_info = xcalloc (sizeof (struct lm_info), 1); + sop->lm_info = xcalloc (1, sizeof (struct lm_info)); make_cleanup (xfree, sop->lm_info); sop->lm_info->mapname = xstrdup (mapname); make_cleanup (xfree, sop->lm_info->mapname); @@ -329,7 +329,7 @@ open_symbol_file_object (void *from_ttyp) struct cleanup *old_chain = make_cleanup (null_cleanup, 0); struct so_list *sos; - sos = build_so_list_from_mapfile (PIDGET (inferior_pid), + sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_MAINEXEC, MA_MAINEXEC); @@ -374,7 +374,7 @@ aix5_current_sos (void) struct so_list *sos; /* Fetch the list of mappings, excluding the main executable. */ - sos = build_so_list_from_mapfile (PIDGET (inferior_pid), MA_MAINEXEC, 0); + sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_MAINEXEC, 0); /* Reverse the list; it looks nicer when we print it if the mappings are in the same order as in the map file. */ @@ -562,6 +562,133 @@ aix5_special_symbol_handling (void) /* Nothing needed (yet) for AIX5. */ } +/* On AIX5, the /proc/PID/map information is used to determine + the relocation offsets needed for relocating the main executable. + There is no problem determining which map entries correspond + to the main executable, because these will have the MA_MAINEXEC + flag set. The tricky part is determining which sections correspond + to which map entries. To date, the following approaches have + been tried: + + - Use the MA_WRITE attribute of pr_mflags to distinguish the read-only + mapping from the read/write mapping. (This assumes that there are + only two mappings for the main executable.) All writable sections + are associated with the read/write mapping and all non-writable + sections are associated with the read-only mapping. + + This approach worked quite well until we came across executables + which didn't have a read-only mapping. Both mappings had the + same attributes represented in pr_mflags and it was impossible + to tell them apart. + + - Use the pr_off field (which represents the offset into the + executable) to determine the section-to-mapping relationship. + Unfortunately, this approach doesn't work either, because the + offset value contained in the mapping is rounded down by some + moderately large power-of-2 value (4096 is a typical value). + A small (e.g. "Hello World") program will appear to have all + of its sections belonging to both mappings. + + Also, the following approach has been considered, but dismissed: + + - The section vma values typically look (something) like + 0x00000001xxxxxxxx or 0x00000002xxxxxxxx. Furthermore, the + 0x00000001xxxxxxxx values always belong to one mapping and + the 0x00000002xxxxxxxx values always belong to the other. + Thus it seems conceivable that GDB could use the bit patterns + in the upper portion (for some definition of "upper") in a + section's vma to help determine the section-to-mapping + relationship. + + This approach was dismissed because there is nothing to prevent + the linker from lumping the section vmas together in one large + contiguous space and still expecting the dynamic linker to + separate them and relocate them independently. Also, different + linkers have been observed to use different patterns for the + upper portions of the vma addresses and it isn't clear what the + mask ought to be for distinguishing these patterns. + + The current (admittedly inelegant) approach uses a lookup + table which associates section names with the map index that + they're permitted to be in. This is inelegant because we are + making the following assumptions: + + 1) There will only be two mappings. + 2) The relevant (i.e. main executable) mappings will always appear + in the same order in the map file. + 3) The sections named in the table will always belong to the + indicated mapping. + 4) The table completely enumerates all possible section names. + + IMO, any of these deficiencies alone will normally be sufficient + to disqualify this approach, but I haven't been able to think of + a better way to do it. + + map_index_vs_section_name_okay() is a predicate which returns + true iff the section name NAME is associated with the map index + IDX in its builtin table. Of course, there's no guarantee that + this association is actually valid... */ + +static int +map_index_vs_section_name_okay (int idx, const char *name) +{ + static struct + { + char *name; + int idx; + } okay[] = + { + { ".interp", 0 }, + { ".hash", 0 }, + { ".dynsym", 0 }, + { ".dynstr", 0 }, + { ".rela.text", 0 }, + { ".rela.rodata", 0 }, + { ".rela.data", 0 }, + { ".rela.ctors", 0 }, + { ".rela.dtors", 0 }, + { ".rela.got", 0 }, + { ".rela.sdata", 0 }, + { ".rela.IA_64.pltoff", 0 }, + { ".rel.data", 0 }, + { ".rel.sdata", 0 }, + { ".rel.got", 0 }, + { ".rel.AIX.pfdesc", 0 }, + { ".rel.IA_64.pltoff", 0 }, + { ".dynamic", 0 }, + { ".init", 0 }, + { ".plt", 0 }, + { ".text", 0 }, + { ".fini", 0 }, + { ".rodata", 0 }, + { ".IA_64.unwind_info", 0 }, + { ".IA_64.unwind", 0 }, + { ".AIX.mustrel", 0 }, + + { ".data", 1 }, + { ".ctors", 1 }, + { ".dtors", 1 }, + { ".got", 1 }, + { ".dynamic", 1}, + { ".sdata", 1 }, + { ".IA_64.pltoff", 1 }, + { ".sbss", 1 }, + { ".bss", 1 }, + { ".AIX.pfdesc", 1 } + }; + int i; + + for (i = 0; i < sizeof (okay) / sizeof (okay[0]); i++) + { + if (strcmp (name, okay[i].name) == 0) + return idx == okay[i].idx; + } + + warning ("solib-aix5.c: Ignoring section %s when relocating the executable\n", + name); + return 0; +} + #define SECTMAPMASK (~ (CORE_ADDR) 0x03ffffff) static void @@ -574,7 +701,7 @@ aix5_relocate_main_executable (void) struct cleanup *old_chain = make_cleanup (null_cleanup, 0); /* Fetch the mappings for the main executable from the map file. */ - so = build_so_list_from_mapfile (PIDGET (inferior_pid), + so = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_MAINEXEC, MA_MAINEXEC); /* Make sure we actually have some mappings to work with. */ @@ -587,8 +714,8 @@ aix5_relocate_main_executable (void) /* Allocate the data structure which'll contain the new offsets to relocate by. Initialize it so it contains the current offsets. */ - new_offsets = xcalloc (sizeof (struct section_offsets), - symfile_objfile->num_sections); + new_offsets = xcalloc (symfile_objfile->num_sections, + sizeof (struct section_offsets)); make_cleanup (xfree, new_offsets); for (i = 0; i < symfile_objfile->num_sections; i++) new_offsets->offsets[i] = ANOFFSET (symfile_objfile->section_offsets, i); @@ -608,8 +735,8 @@ aix5_relocate_main_executable (void) if (flags & SEC_ALLOC) { file_ptr filepos = sect->the_bfd_section->filepos; - if (mapping->offset <= filepos - && filepos <= mapping->offset + mapping->size) + if (map_index_vs_section_name_okay (i, + bfd_get_section_name (obfd, sect->the_bfd_section))) { int idx = sect->the_bfd_section->index; @@ -731,7 +858,7 @@ aix5_find_global_pointer (CORE_ADDR addr) CORE_ADDR global_pointer = 0; struct cleanup *old_chain = make_cleanup (null_cleanup, 0); - sos = build_so_list_from_mapfile (PIDGET (inferior_pid), 0, 0); + sos = build_so_list_from_mapfile (PIDGET (inferior_ptid), 0, 0); for (so = sos; so != NULL; so = so->next) { @@ -775,7 +902,7 @@ aix5_find_gate_addresses (CORE_ADDR *start, CORE_ADDR *end) struct cleanup *old_chain = make_cleanup (null_cleanup, 0); /* Fetch the mappings for the main executable from the map file. */ - so = build_so_list_from_mapfile (PIDGET (inferior_pid), + so = build_so_list_from_mapfile (PIDGET (inferior_ptid), MA_KERNTEXT, MA_KERNTEXT); /* Make sure we actually have some mappings to work with. */