/* Handle PA64 shared libraries for GDB, the GNU Debugger.
- Copyright 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
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.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
HP in their infinite stupidity choose not to use standard ELF dynamic
linker interfaces. They also choose not to make their ELF dymamic
same functionality in all their libraries! */
#include "defs.h"
-#include <dlfcn.h>
-#include <elf.h>
-#include <elf_hp.h>
#include "symtab.h"
#include "bfd.h"
#include "symfile.h"
#include "hppa-tdep.h"
#include "solist.h"
+#include "solib.h"
#include "solib-pa64.h"
#undef SOLIB_PA64_DBG
-/* If we are building for a SOM-only target, then we don't need this. */
-#ifndef PA_SOM_ONLY
+/* We can build this file only when running natively on 64-bit HP/UX.
+ We check for that by checking for the elf_hp.h header file. */
+#ifdef HAVE_ELF_HP_H
+
+/* FIXME: kettenis/20041213: These includes should be eliminated. */
+#include <dlfcn.h>
+#include <elf.h>
+#include <elf_hp.h>
struct lm_info {
struct load_module_desc desc;
pa64_relocate_section_addresses (struct so_list *so,
struct section_table *sec)
{
+ asection *asec = sec->the_bfd_section;
+ CORE_ADDR load_offset;
+
+ /* Relocate all the sections based on where they got loaded. */
+
+ load_offset = bfd_section_vma (so->abfd, asec) - asec->filepos;
+
+ if (asec->flags & SEC_CODE)
+ {
+ sec->addr += so->lm_info->desc.text_base - load_offset;
+ sec->endaddr += so->lm_info->desc.text_base - load_offset;
+ }
+ else if (asec->flags & SEC_DATA)
+ {
+ sec->addr += so->lm_info->desc.data_base - load_offset;
+ sec->endaddr += so->lm_info->desc.data_base - load_offset;
+ }
}
static void
if (!dld_cache.is_valid)
{
if (symfile_objfile == NULL)
- error ("No object file symbols.");
+ error (_("No object file symbols."));
dyninfo_sect = bfd_get_section_by_name (symfile_objfile->obfd,
".dynamic");
}
if (!read_dynamic_info (dyninfo_sect, &dld_cache))
- error ("Unable to read in .dynamic section information.");
+ error (_("Unable to read in .dynamic section information."));
}
/* Read the load map pointer. */
sizeof (dld_cache.load_map))
!= 0)
{
- error ("Error while reading in load map pointer.");
+ error (_("Error while reading in load map pointer."));
}
/* Read in the dld load module descriptor */
dld_cache.load_map)
== 0)
{
- error ("Error trying to get information about dynamic linker.");
+ error (_("Error trying to get information about dynamic linker."));
}
/* Indicate that we have loaded the dld descriptor. */
CORE_ADDR dyn_ptr;
char *pbuf;
- pbuf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT);
+ pbuf = alloca (gdbarch_ptr_bit (current_gdbarch) / HOST_CHAR_BIT);
dyn_tag = bfd_h_get_64 (symfile_objfile->obfd,
(bfd_byte*) &x_dynp->d_tag);
sizeof (dld_cache_p->dld_flags))
!= 0)
{
- error ("Error while reading in .dynamic section of the program.");
+ error (_("Error while reading in .dynamic section of the program."));
}
}
else if (dyn_tag == DT_HP_LOAD_MAP)
sizeof (dld_cache_p->load_map_addr))
!= 0)
{
- error ("Error while reading in .dynamic section of the program.");
+ error (_("Error while reading in .dynamic section of the program."));
}
}
else
/* Read in the .dynamic section. */
if (! read_dynamic_info (shlib_info, &dld_cache))
- error ("Unable to read the .dynamic section.");
+ error (_("Unable to read the .dynamic section."));
/* Turn on the flags we care about. */
dld_cache.dld_flags |= DT_HP_DEBUG_PRIVATE;
(char *) &dld_cache.dld_flags,
sizeof (dld_cache.dld_flags));
if (status != 0)
- error ("Unable to modify dynamic linker flags.");
+ error (_("Unable to modify dynamic linker flags."));
/* Now we have to create a shared library breakpoint in the dynamic
linker. This can be somewhat tricky since the symbol is inside
/* 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);
return;
}
/* If the libraries were not mapped private, warn the user. */
if ((dld_cache.dld_flags & DT_HP_DEBUG_PRIVATE) == 0)
- warning ("The shared libraries were not privately mapped; setting a\n"
+ warning (_("The shared libraries were not privately mapped; setting a\n"
"breakpoint in a shared library will not work until you rerun "
- "the program.\n");
+ "the program.\n"));
- for (dll_index = 1; ; dll_index++)
+ for (dll_index = -1; ; dll_index++)
{
struct load_module_desc dll_desc;
char *dll_path;
struct so_list *new;
struct cleanup *old_chain;
+ if (dll_index == 0)
+ continue;
+
/* Read in the load module descriptor. */
if (dlgetmodinfo (dll_index, &dll_desc, sizeof (dll_desc),
pa64_target_read_memory, 0, dld_cache.load_map)
pa64_target_read_memory,
0, dld_cache.load_map);
- if (dll_path == NULL)
- dll_path = "";
-
new = (struct so_list *) xmalloc (sizeof (struct so_list));
memset (new, 0, sizeof (struct so_list));
new->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
&& ((so_list->lm_info->desc.text_base
+ so_list->lm_info->desc.text_size)
> addr))
- {
+ {
got_value = so_list->lm_info->desc.linkage_ptr;
- break;
+ break;
}
so_list = so_list->next;
}
/* Return the address of the handle of the shared library in which ADDR
- belongs. If ADDR isn't in any known shared library, return zero.
-
- This function is used in hppa_fix_call_dummy in hppa-tdep.c. */
+ belongs. If ADDR isn't in any known shared library, return zero. */
static CORE_ADDR
pa64_solib_get_solib_by_pc (CORE_ADDR addr)
return retval;
}
+/* pa64 libraries do not seem to set the section offsets in a standard (i.e.
+ SVr4) way; the text section offset stored in the file doesn't correspond
+ to the place where the library is actually loaded into memory. Instead,
+ we rely on the dll descriptor to tell us where things were loaded. */
+static CORE_ADDR
+pa64_solib_get_text_base (struct objfile *objfile)
+{
+ struct so_list *so;
+
+ for (so = master_so_list (); so; so = so->next)
+ if (so->objfile == objfile)
+ return so->lm_info->desc.text_base;
+
+ return 0;
+}
+
static struct target_so_ops pa64_so_ops;
extern initialize_file_ftype _initialize_pa64_solib; /* -Wmissing-prototypes */
memset (&dld_cache, 0, sizeof (dld_cache));
}
-void pa64_solib_select (struct gdbarch_tdep *tdep)
+void pa64_solib_select (struct gdbarch *gdbarch)
{
- current_target_so_ops = &pa64_so_ops;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ set_solib_ops (gdbarch, &pa64_so_ops);
tdep->solib_thread_start_addr = pa64_solib_thread_start_addr;
tdep->solib_get_got_by_pc = pa64_solib_get_got_by_pc;
tdep->solib_get_solib_by_pc = pa64_solib_get_solib_by_pc;
+ tdep->solib_get_text_base = pa64_solib_get_text_base;
}
-#else /* PA_SOM_ONLY */
+#else /* HAVE_ELF_HP_H */
extern initialize_file_ftype _initialize_pa64_solib; /* -Wmissing-prototypes */
{
}
-void pa64_solib_select (struct gdbarch_tdep *tdep)
+void pa64_solib_select (struct gdbarch *gdbarch)
{
/* For a SOM-only target, there is no pa64 solib support. This is needed
for hppa-hpux-tdep.c to build. */
- error ("Cannot select pa64 solib support for this configuration.\n");
+ error (_("Cannot select pa64 solib support for this configuration."));
}
#endif