2004-04-17 Randolph Chung <tausq@debian.org>
[deliverable/binutils-gdb.git] / gdb / solib-aix5.c
index 314408ec3687b86f1459fc6e29d1bb477d7f1669..1a8c9dfeea94d8ae575f0e25eb25decb2803bd82 100644 (file)
@@ -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.  */
This page took 0.032286 seconds and 4 git commands to generate.