/* Handle AIX5 shared libraries for GDB, the GNU Debugger.
- Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
2001
Free Software Foundation, Inc.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
/* Open the map file */
- xasprintf (&map_pathname, "/proc/%d/map", pid);
+ map_pathname = xstrprintf ("/proc/%d/map", pid);
map_fd = open (map_pathname, O_RDONLY);
xfree (map_pathname);
if (map_fd < 0)
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);
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);
if (sos == NULL)
{
- warning ("Could not find name of main executable in map file");
+ warning (_("Could not find name of main executable in map file"));
return 0;
}
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. */
/* Make sure the dynamic linker's really a useful object. */
if (!bfd_check_format (tmp_bfd, bfd_object))
{
- warning ("Unable to grok dynamic linker %s as an object file", buf);
+ warning (_("Unable to grok dynamic linker %s as an object file"), buf);
bfd_close (tmp_bfd);
goto bkpt_at_symbol;
}
/* For whatever reason we couldn't set a breakpoint in the dynamic
linker. Warn and drop into the old code. */
bkpt_at_symbol:
- warning ("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.");
+ warning (_("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code."));
}
/* Nothing good happened. */
/* 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 (_("Ignoring section %s when relocating the executable."),
+ name);
+ return 0;
+}
+
#define SECTMAPMASK (~ (CORE_ADDR) 0x03ffffff)
static 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. */
if (so == NULL)
{
- warning ("Could not find main executable in map file");
+ warning (_("Could not find main executable in map file"));
do_cleanups (old_chain);
return;
}
/* 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);
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;
SYNOPSIS
- void aix5_solib_create_inferior_hook()
+ void aix5_solib_create_inferior_hook ()
DESCRIPTION
if (!enable_break ())
{
- warning ("shared library handler failed to enable breakpoint");
+ warning (_("shared library handler failed to enable breakpoint"));
return;
}
}
if (idx >= so->lm_info->nmappings)
internal_error (__FILE__, __LINE__,
- "aix_relocate_section_addresses: Can't find mapping for section %s",
+ _("aix_relocate_section_addresses: Can't find mapping for section %s"),
bfd_get_section_name (sec->bfd, sec->the_bfd_section));
addr = so->lm_info->mapping[idx].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)
{
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. */
if (so == NULL)
{
- warning ("Could not find gate page in map file");
+ warning (_("Could not find gate page in map file"));
*start = 0;
*end = 0;
do_cleanups (old_chain);