gdb/solib-ia64-hpux.c - gdb

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. /* Copyright (C) 2010-2015 Free Software Foundation, Inc.

  2.    This file is part of GDB.

  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 3 of the License, or
  6.    (at your option) any later version.

  7.    This program is distributed in the hope that it will be useful,
  8.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.    GNU General Public License for more details.

  11.    You should have received a copy of the GNU General Public License
  12.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  13. #include "defs.h"
  14. #include "ia64-tdep.h"
  15. #include "ia64-hpux-tdep.h"
  16. #include "solib-ia64-hpux.h"
  17. #include "solist.h"
  18. #include "solib.h"
  19. #include "target.h"
  20. #include "gdbtypes.h"
  21. #include "inferior.h"
  22. #include "gdbcore.h"
  23. #include "regcache.h"
  24. #include "opcode/ia64.h"
  25. #include "symfile.h"
  26. #include "objfiles.h"
  27. #include "elf-bfd.h"

  28. /* Need to define the following macro in order to get the complete
  29.    load_module_desc struct definition in dlfcn.h  Otherwise, it doesn't
  30.    match the size of the struct the loader is providing us during load
  31.    events.  */
  32. #define _LOAD_MODULE_DESC_EXT

  33. #include <sys/ttrace.h>
  34. #include <dlfcn.h>
  35. #include <elf.h>
  36. #include <service_mgr.h>

  37. /* The following is to have access to the definition of type load_info_t.  */
  38. #include <crt0.h>

  39. /* The r32 pseudo-register number.

  40.    Like all stacked registers, r32 is treated as a pseudo-register,
  41.    because it is not always available for read/write via the ttrace
  42.    interface.  */
  43. /* This is a bit of a hack, as we duplicate something hidden inside
  44.    ia64-tdep.c, but oh well...  */
  45. #define IA64_R32_PSEUDO_REGNUM (IA64_NAT127_REGNUM + 2)

  46. /* Our struct so_list private data structure.  */

  47. struct lm_info
  48. {
  49.   /* The shared library module descriptor.  We extract this structure
  50.      from the loader at the time the shared library gets mapped.  */
  51.   struct load_module_desc module_desc;

  52.   /* The text segment address as defined in the shared library object
  53.      (this is not the address where this segment got loaded).  This
  54.      field is initially set to zero, and computed lazily.  */
  55.   CORE_ADDR text_start;

  56.   /* The data segment address as defined in the shared library object
  57.      (this is not the address where this segment got loaded).  This
  58.      field is initially set to zero, and computed lazily.  */
  59.   CORE_ADDR data_start;
  60. };

  61. /* The list of shared libraries currently mapped by the inferior.  */

  62. static struct so_list *so_list_head = NULL;

  63. /* Create a new so_list element.  The result should be deallocated
  64.    when no longer in use.  */

  65. static struct so_list *
  66. new_so_list (char *so_name, struct load_module_desc module_desc)
  67. {
  68.   struct so_list *new_so;

  69.   new_so = (struct so_list *) XCNEW (struct so_list);
  70.   new_so->lm_info = (struct lm_info *) XCNEW (struct lm_info);
  71.   new_so->lm_info->module_desc = module_desc;

  72.   strncpy (new_so->so_name, so_name, SO_NAME_MAX_PATH_SIZE - 1);
  73.   new_so->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
  74.   strcpy (new_so->so_original_name, new_so->so_name);

  75.   return new_so;
  76. }

  77. /* Return non-zero if the instruction at the current PC is a breakpoint
  78.    part of the dynamic loading process.

  79.    We identify such instructions by checking that the instruction at
  80.    the current pc is a break insn where no software breakpoint has been
  81.    inserted by us.  We also verify that the operands have specific
  82.    known values, to be extra certain.

  83.    PTID is the ptid of the thread that should be checked, but this
  84.    function also assumes that inferior_ptid is already equal to PTID.
  85.    Ideally, we would like to avoid the requirement on inferior_ptid,
  86.    but many routines still use the inferior_ptid global to access
  87.    the relevant thread's register and memory.  We still have the ptid
  88.    as parameter to be able to pass it to the routines that do take a ptid
  89.    - that way we avoid increasing explicit uses of the inferior_ptid
  90.    global.  */

  91. static int
  92. ia64_hpux_at_dld_breakpoint_1_p (ptid_t ptid)
  93. {
  94.   struct regcache *regcache = get_thread_regcache (ptid);
  95.   CORE_ADDR pc = regcache_read_pc (regcache);
  96.   struct address_space *aspace = get_regcache_aspace (regcache);
  97.   ia64_insn t0, t1, slot[3], template, insn;
  98.   int slotnum;
  99.   bfd_byte bundle[16];

  100.   /* If this is a regular breakpoint, then it can not be a dld one.  */
  101.   if (breakpoint_inserted_here_p (aspace, pc))
  102.     return 0;

  103.   slotnum = ((long) pc) & 0xf;
  104.   if (slotnum > 2)
  105.     internal_error (__FILE__, __LINE__,
  106.                     "invalid slot (%d) for address %s", slotnum,
  107.                     paddress (get_regcache_arch (regcache), pc));

  108.   pc -= (pc & 0xf);
  109.   read_memory (pc, bundle, sizeof (bundle));

  110.   /* bundles are always in little-endian byte order */
  111.   t0 = bfd_getl64 (bundle);
  112.   t1 = bfd_getl64 (bundle + 8);
  113.   template = (t0 >> 1) & 0xf;
  114.   slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
  115.   slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
  116.   slot[2] = (t1 >> 23) & 0x1ffffffffffLL;

  117.   if (template == 2 && slotnum == 1)
  118.     {
  119.       /* skip L slot in MLI template: */
  120.       slotnum = 2;
  121.     }

  122.   insn = slot[slotnum];

  123.   return (insn == 0x1c0c9c0       /* break.i 0x070327 */
  124.           || insn == 0x3c0c9c0);  /* break.i 0x0f0327 */
  125. }

  126. /* Same as ia64_hpux_at_dld_breakpoint_1_p above, with the following
  127.    differences: It temporarily sets inferior_ptid to PTID, and also
  128.    contains any exception being raised.  */

  129. int
  130. ia64_hpux_at_dld_breakpoint_p (ptid_t ptid)
  131. {
  132.   volatile struct gdb_exception e;
  133.   ptid_t saved_ptid = inferior_ptid;
  134.   int result = 0;

  135.   inferior_ptid = ptid;
  136.   TRY_CATCH (e, RETURN_MASK_ALL)
  137.     {
  138.       result = ia64_hpux_at_dld_breakpoint_1_p (ptid);
  139.     }
  140.   inferior_ptid = saved_ptid;
  141.   if (e.reason < 0)
  142.     warning (_("error while checking for dld breakpoint: %s"), e.message);

  143.   return result;
  144. }

  145. /* Handler for library load event: Read the information provided by
  146.    the loader, and then use it to read the shared library symbols.  */

  147. static void
  148. ia64_hpux_handle_load_event (struct regcache *regcache)
  149. {
  150.   CORE_ADDR module_desc_addr;
  151.   ULONGEST module_desc_size;
  152.   CORE_ADDR so_path_addr;
  153.   char so_path[PATH_MAX];
  154.   struct load_module_desc module_desc;
  155.   struct so_list *new_so;

  156.   /* Extract the data provided by the loader as follow:
  157.        - r33: Address of load_module_desc structure
  158.        - r34: size of struct load_module_desc
  159.        - r35: Address of string holding shared library path
  160.    */
  161.   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 1,
  162.                                  &module_desc_addr);
  163.   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 2,
  164.                                  &module_desc_size);
  165.   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 3,
  166.                                  &so_path_addr);

  167.   if (module_desc_size != sizeof (struct load_module_desc))
  168.     warning (_("load_module_desc size (%ld) != size returned by kernel (%s)"),
  169.              sizeof (struct load_module_desc),
  170.              pulongest (module_desc_size));

  171.   read_memory_string (so_path_addr, so_path, PATH_MAX);
  172.   read_memory (module_desc_addr, (gdb_byte *) &module_desc,
  173.                sizeof (module_desc));

  174.   /* Create a new so_list element and insert it at the start of our
  175.      so_list_head (we insert at the start of the list only because
  176.      it is less work compared to inserting it elsewhere).  */
  177.   new_so = new_so_list (so_path, module_desc);
  178.   new_so->next = so_list_head;
  179.   so_list_head = new_so;
  180. }

  181. /* Update the value of the PC to point to the begining of the next
  182.    instruction bundle.  */

  183. static void
  184. ia64_hpux_move_pc_to_next_bundle (struct regcache *regcache)
  185. {
  186.   CORE_ADDR pc = regcache_read_pc (regcache);

  187.   pc -= pc & 0xf;
  188.   pc += 16;
  189.   ia64_write_pc (regcache, pc);
  190. }

  191. /* Handle loader events.

  192.    PTID is the ptid of the thread corresponding to the event being
  193.    handled.  Similarly to ia64_hpux_at_dld_breakpoint_1_p, this
  194.    function assumes that inferior_ptid is set to PTID.  */

  195. static void
  196. ia64_hpux_handle_dld_breakpoint_1 (ptid_t ptid)
  197. {
  198.   struct regcache *regcache = get_thread_regcache (ptid);
  199.   ULONGEST arg0;

  200.   /* The type of event is provided by the loaded via r32.  */
  201.   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM, &arg0);
  202.   switch (arg0)
  203.     {
  204.       case BREAK_DE_SVC_LOADED:
  205.         /* Currently, the only service loads are uld and dld,
  206.            so we shouldn't need to do anything.  Just ignore.  */
  207.         break;
  208.       case BREAK_DE_LIB_LOADED:
  209.         ia64_hpux_handle_load_event (regcache);
  210.         solib_add (NULL, 0, &current_target, auto_solib_add);
  211.         break;
  212.       case BREAK_DE_LIB_UNLOADED:
  213.       case BREAK_DE_LOAD_COMPLETE:
  214.       case BREAK_DE_BOR:
  215.         /* Ignore for now.  */
  216.         break;
  217.     }

  218.   /* Now that we have handled the event, we can move the PC to
  219.      the next instruction bundle, past the break instruction.  */
  220.   ia64_hpux_move_pc_to_next_bundle (regcache);
  221. }

  222. /* Same as ia64_hpux_handle_dld_breakpoint_1 above, with the following
  223.    differences: This function temporarily sets inferior_ptid to PTID,
  224.    and also contains any exception.  */

  225. void
  226. ia64_hpux_handle_dld_breakpoint (ptid_t ptid)
  227. {
  228.   volatile struct gdb_exception e;
  229.   ptid_t saved_ptid = inferior_ptid;

  230.   inferior_ptid = ptid;
  231.   TRY_CATCH (e, RETURN_MASK_ALL)
  232.     {
  233.       ia64_hpux_handle_dld_breakpoint_1 (ptid);
  234.     }
  235.   inferior_ptid = saved_ptid;
  236.   if (e.reason < 0)
  237.     warning (_("error detected while handling dld breakpoint: %s"), e.message);
  238. }

  239. /* Find the address of the code and data segments in ABFD, and update
  240.    TEXT_START and DATA_START accordingly.  */

  241. static void
  242. ia64_hpux_find_start_vma (bfd *abfd, CORE_ADDR *text_start,
  243.                           CORE_ADDR *data_start)
  244. {
  245.   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
  246.   Elf64_Phdr phdr;
  247.   int i;

  248.   *text_start = 0;
  249.   *data_start = 0;

  250.   if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
  251.     error (_("invalid program header offset in %s"), abfd->filename);

  252.   for (i = 0; i < i_ehdrp->e_phnum; i++)
  253.     {
  254.       if (bfd_bread (&phdr, sizeof (phdr), abfd) != sizeof (phdr))
  255.         error (_("failed to read segment %d in %s"), i, abfd->filename);

  256.       if (phdr.p_flags & PF_X
  257.           && (*text_start == 0 || phdr.p_vaddr < *text_start))
  258.         *text_start = phdr.p_vaddr;

  259.       if (phdr.p_flags & PF_W
  260.           && (*data_start == 0 || phdr.p_vaddr < *data_start))
  261.         *data_start = phdr.p_vaddr;
  262.     }
  263. }

  264. /* The "relocate_section_addresses" target_so_ops routine for ia64-hpux.  */

  265. static void
  266. ia64_hpux_relocate_section_addresses (struct so_list *so,
  267.                                       struct target_section *sec)
  268. {
  269.   CORE_ADDR offset = 0;

  270.   /* If we haven't computed the text & data segment addresses, do so now.
  271.      We do this here, because we now have direct access to the associated
  272.      bfd, whereas we would have had to open our own if we wanted to do it
  273.      while processing the library-load event.  */
  274.   if (so->lm_info->text_start == 0 && so->lm_info->data_start == 0)
  275.     ia64_hpux_find_start_vma (sec->the_bfd_section->owner,
  276.                               &so->lm_info->text_start,
  277.                               &so->lm_info->data_start);

  278.   /* Determine the relocation offset based on which segment
  279.      the section belongs to.  */
  280.   if ((so->lm_info->text_start < so->lm_info->data_start
  281.        && sec->addr < so->lm_info->data_start)
  282.       || (so->lm_info->text_start > so->lm_info->data_start
  283.           && sec->addr >= so->lm_info->text_start))
  284.     offset = so->lm_info->module_desc.text_base - so->lm_info->text_start;
  285.   else if ((so->lm_info->text_start < so->lm_info->data_start
  286.             && sec->addr >= so->lm_info->data_start)
  287.            || (so->lm_info->text_start > so->lm_info->data_start
  288.                && sec->addr < so->lm_info->text_start))
  289.     offset = so->lm_info->module_desc.data_base - so->lm_info->data_start;

  290.   /* And now apply the relocation.  */
  291.   sec->addr += offset;
  292.   sec->endaddr += offset;

  293.   /* Best effort to set addr_high/addr_low.  This is used only by
  294.      'info sharedlibrary'.  */
  295.   if (so->addr_low == 0 || sec->addr < so->addr_low)
  296.     so->addr_low = sec->addr;

  297.   if (so->addr_high == 0 || sec->endaddr > so->addr_high)
  298.     so->addr_high = sec->endaddr;
  299. }

  300. /* The "free_so" target_so_ops routine for ia64-hpux.  */

  301. static void
  302. ia64_hpux_free_so (struct so_list *so)
  303. {
  304.   xfree (so->lm_info);
  305. }

  306. /* The "clear_solib" target_so_ops routine for ia64-hpux.  */

  307. static void
  308. ia64_hpux_clear_solib (void)
  309. {
  310.   struct so_list *so;

  311.   while (so_list_head != NULL)
  312.     {
  313.       so = so_list_head;
  314.       so_list_head = so_list_head->next;

  315.       ia64_hpux_free_so (so);
  316.       xfree (so);
  317.     }
  318. }

  319. /* Assuming the inferior just stopped on an EXEC event, return
  320.    the address of the load_info_t structure.  */

  321. static CORE_ADDR
  322. ia64_hpux_get_load_info_addr (void)
  323. {
  324.   struct type *data_ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
  325.   CORE_ADDR addr;
  326.   int status;

  327.   /* The address of the load_info_t structure is stored in the 4th
  328.      argument passed to the initial thread of the process (in other
  329.      words, in argv[3]).  So get the address of these arguments,
  330.      and extract the 4th one.  */
  331.   status = ttrace (TT_PROC_GET_ARGS, ptid_get_pid (inferior_ptid),
  332.                    0, (uintptr_t) &addr, sizeof (CORE_ADDR), 0);
  333.   if (status == -1 && errno)
  334.     perror_with_name (_("Unable to get argument list"));
  335.   return (read_memory_typed_address (addr + 3 * 8, data_ptr_type));
  336. }

  337. /* A structure used to aggregate some information extracted from
  338.    the dynamic section of the main executable.  */

  339. struct dld_info
  340. {
  341.   ULONGEST dld_flags;
  342.   CORE_ADDR load_map;
  343. };

  344. /* Scan the ".dynamic" section referenced by ABFD and DYN_SECT,
  345.    and extract the information needed to fill in INFO.  */

  346. static void
  347. ia64_hpux_read_dynamic_info (struct gdbarch *gdbarch, bfd *abfd,
  348.                              asection *dyn_sect, struct dld_info *info)
  349. {
  350.   int sect_size;
  351.   char *buf;
  352.   char *buf_end;

  353.   /* Make sure that info always has initialized data, even if we fail
  354.      to read the syn_sect section.  */
  355.   memset (info, 0, sizeof (struct dld_info));

  356.   sect_size = bfd_section_size (abfd, dyn_sect);
  357.   buf = alloca (sect_size);
  358.   buf_end = buf + sect_size;

  359.   if (bfd_seek (abfd, dyn_sect->filepos, SEEK_SET) != 0
  360.       || bfd_bread (buf, sect_size, abfd) != sect_size)
  361.     error (_("failed to read contents of .dynamic section"));

  362.   for (; buf < buf_end; buf += sizeof (Elf64_Dyn))
  363.     {
  364.       Elf64_Dyn *dynp = (Elf64_Dyn *) buf;
  365.       Elf64_Sxword d_tag;

  366.       d_tag = bfd_h_get_64 (abfd, &dynp->d_tag);
  367.       switch (d_tag)
  368.         {
  369.           case DT_HP_DLD_FLAGS:
  370.             info->dld_flags = bfd_h_get_64 (abfd, &dynp->d_un);
  371.             break;

  372.           case DT_HP_LOAD_MAP:
  373.             {
  374.               CORE_ADDR load_map_addr = bfd_h_get_64 (abfd, &dynp->d_un.d_ptr);

  375.               if (target_read_memory (load_map_addr,
  376.                                       (gdb_byte *) &info->load_map,
  377.                                       sizeof (info->load_map)) != 0)
  378.                 error (_("failed to read load map at %s"),
  379.                        paddress (gdbarch, load_map_addr));
  380.             }
  381.             break;
  382.         }
  383.     }
  384. }

  385. /* Wrapper around target_read_memory used with libdl.  */

  386. static void *
  387. ia64_hpux_read_tgt_mem (void *buffer, uint64_t ptr, size_t bufsiz, int ident)
  388. {
  389.   if (target_read_memory (ptr, (gdb_byte *) buffer, bufsiz) != 0)
  390.     return 0;
  391.   else
  392.     return buffer;
  393. }

  394. /* Create a new so_list object for a shared library, and store that
  395.    new so_list object in our SO_LIST_HEAD list.

  396.    SO_INDEX is an index specifying the placement of the loaded shared
  397.    library in the dynamic loader's search list.  Normally, this index
  398.    is strictly positive, but an index of -1 refers to the loader itself.

  399.    Return nonzero if the so_list object could be created.  A null
  400.    return value with a positive SO_INDEX normally means that there are
  401.    no more entries in the dynamic loader's search list at SO_INDEX or
  402.    beyond.  */

  403. static int
  404. ia64_hpux_add_so_from_dld_info (struct dld_info info, int so_index)
  405. {
  406.   struct load_module_desc module_desc;
  407.   uint64_t so_handle;
  408.   char *so_path;
  409.   struct so_list *so;

  410.   so_handle = dlgetmodinfo (so_index, &module_desc, sizeof (module_desc),
  411.                             ia64_hpux_read_tgt_mem, 0, info.load_map);

  412.   if (so_handle == 0)
  413.     /* No such entry.  We probably reached the end of the list.  */
  414.     return 0;

  415.   so_path = dlgetname (&module_desc, sizeof (module_desc),
  416.                        ia64_hpux_read_tgt_mem, 0, info.load_map);
  417.   if (so_path == NULL)
  418.     {
  419.       /* Should never happen, but let's not crash if it does.  */
  420.       warning (_("unable to get shared library name, symbols not loaded"));
  421.       return 0;
  422.     }

  423.   /* Create a new so_list and insert it at the start of our list.
  424.      The order is not extremely important, but it's less work to do so
  425.      at the end of the list.  */
  426.   so = new_so_list (so_path, module_desc);
  427.   so->next = so_list_head;
  428.   so_list_head = so;

  429.   return 1;
  430. }

  431. /* Assuming we just attached to a process, update our list of shared
  432.    libraries (SO_LIST_HEAD) as well as GDB's list.  */

  433. static void
  434. ia64_hpux_solib_add_after_attach (void)
  435. {
  436.   bfd *abfd;
  437.   asection *dyn_sect;
  438.   struct dld_info info;
  439.   int i;

  440.   if (symfile_objfile == NULL)
  441.     return;

  442.   abfd = symfile_objfile->obfd;
  443.   dyn_sect = bfd_get_section_by_name (abfd, ".dynamic");

  444.   if (dyn_sect == NULL || bfd_section_size (abfd, dyn_sect) == 0)
  445.     return;

  446.   ia64_hpux_read_dynamic_info (get_objfile_arch (symfile_objfile), abfd,
  447.                                dyn_sect, &info);

  448.   if ((info.dld_flags & DT_HP_DEBUG_PRIVATE) == 0)
  449.     {
  450.       warning (_(
  451. "The shared libraries were not privately mapped; setting a breakpoint\n\
  452. in a shared library will not work until you rerun the program.\n\
  453. Use the following command to enable debugging of shared libraries.\n\
  454. chatr +dbg enable a.out"));
  455.     }

  456.   /* Read the symbols of the dynamic loader (dld.so).  */
  457.   ia64_hpux_add_so_from_dld_info (info, -1);

  458.   /* Read the symbols of all the other shared libraries.  */
  459.   for (i = 1; ; i++)
  460.     if (!ia64_hpux_add_so_from_dld_info (info, i))
  461.       break/* End of list.  */

  462.   /* Resync the library list at the core level.  */
  463.   solib_add (NULL, 1, &current_target, auto_solib_add);
  464. }

  465. /* The "create_inferior_hook" target_so_ops routine for ia64-hpux.  */

  466. static void
  467. ia64_hpux_solib_create_inferior_hook (int from_tty)
  468. {
  469.   CORE_ADDR load_info_addr;
  470.   load_info_t load_info;

  471.   /* Initially, we were thinking about adding a check that the program
  472.      (accessible through symfile_objfile) was linked against some shared
  473.      libraries, by searching for a ".dynamic" section.  However, could
  474.      this break in the case of a statically linked program that later
  475.      uses dlopen?  Programs that are fully statically linked are very
  476.      rare, and we will worry about them when we encounter one that
  477.      causes trouble.  */

  478.   /* Set the LI_TRACE flag in the load_info_t structure.  This enables
  479.      notifications when shared libraries are being mapped.  */
  480.   load_info_addr = ia64_hpux_get_load_info_addr ();
  481.   read_memory (load_info_addr, (gdb_byte *) &load_info, sizeof (load_info));
  482.   load_info.li_flags |= LI_TRACE;
  483.   write_memory (load_info_addr, (gdb_byte *) &load_info, sizeof (load_info));

  484.   /* If we just attached to our process, some shard libraries have
  485.      already been mapped.  Find which ones they are...  */
  486.   if (current_inferior ()->attach_flag)
  487.     ia64_hpux_solib_add_after_attach ();
  488. }

  489. /* The "special_symbol_handling" target_so_ops routine for ia64-hpux.  */

  490. static void
  491. ia64_hpux_special_symbol_handling (void)
  492. {
  493.   /* Nothing to do.  */
  494. }

  495. /* The "current_sos" target_so_ops routine for ia64-hpux.  */

  496. static struct so_list *
  497. ia64_hpux_current_sos (void)
  498. {
  499.   /* Return a deep copy of our own list.  */
  500.   struct so_list *new_head = NULL, *prev_new_so = NULL;
  501.   struct so_list *our_so;

  502.   for (our_so = so_list_head; our_so != NULL; our_so = our_so->next)
  503.     {
  504.       struct so_list *new_so;

  505.       new_so = new_so_list (our_so->so_name, our_so->lm_info->module_desc);
  506.       if (prev_new_so != NULL)
  507.         prev_new_so->next = new_so;
  508.       prev_new_so = new_so;
  509.       if (new_head == NULL)
  510.         new_head = new_so;
  511.     }

  512.   return new_head;
  513. }

  514. /* The "open_symbol_file_object" target_so_ops routine for ia64-hpux.  */

  515. static int
  516. ia64_hpux_open_symbol_file_object (void *from_ttyp)
  517. {
  518.   return 0;
  519. }

  520. /* The "in_dynsym_resolve_code" target_so_ops routine for ia64-hpux.  */

  521. static int
  522. ia64_hpux_in_dynsym_resolve_code (CORE_ADDR pc)
  523. {
  524.   return 0;
  525. }

  526. /* If FADDR is the address of a function inside one of the shared
  527.    libraries, return the shared library linkage address.  */

  528. CORE_ADDR
  529. ia64_hpux_get_solib_linkage_addr (CORE_ADDR faddr)
  530. {
  531.   struct so_list *so = so_list_head;

  532.   while (so != NULL)
  533.     {
  534.       struct load_module_desc module_desc = so->lm_info->module_desc;

  535.       if (module_desc.text_base <= faddr
  536.           && (module_desc.text_base + module_desc.text_size) > faddr)
  537.         return module_desc.linkage_ptr;

  538.       so = so->next;
  539.     }

  540.   return 0;
  541. }

  542. /* Create a new target_so_ops structure suitable for ia64-hpux, and
  543.    return its address.  */

  544. static struct target_so_ops *
  545. ia64_hpux_target_so_ops (void)
  546. {
  547.   struct target_so_ops *ops = XCNEW (struct target_so_ops);

  548.   ops->relocate_section_addresses = ia64_hpux_relocate_section_addresses;
  549.   ops->free_so = ia64_hpux_free_so;
  550.   ops->clear_solib = ia64_hpux_clear_solib;
  551.   ops->solib_create_inferior_hook = ia64_hpux_solib_create_inferior_hook;
  552.   ops->special_symbol_handling = ia64_hpux_special_symbol_handling;
  553.   ops->current_sos = ia64_hpux_current_sos;
  554.   ops->open_symbol_file_object = ia64_hpux_open_symbol_file_object;
  555.   ops->in_dynsym_resolve_code = ia64_hpux_in_dynsym_resolve_code;
  556.   ops->bfd_open = solib_bfd_open;

  557.   return ops;
  558. }

  559. /* Prevent warning from -Wmissing-prototypes.  */
  560. void _initialize_solib_ia64_hpux (void);

  561. void
  562. _initialize_solib_ia64_hpux (void)
  563. {
  564.   ia64_hpux_so_ops = ia64_hpux_target_so_ops ();
  565. }