GDB (API)
/home/stan/gdb/src/gdb/solib-ia64-hpux.c
Go to the documentation of this file.
00001 /* Copyright (C) 2010-2013 Free Software Foundation, Inc.
00002 
00003    This file is part of GDB.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 #include "defs.h"
00019 #include "ia64-tdep.h"
00020 #include "ia64-hpux-tdep.h"
00021 #include "solib-ia64-hpux.h"
00022 #include "solist.h"
00023 #include "solib.h"
00024 #include "target.h"
00025 #include "gdbtypes.h"
00026 #include "inferior.h"
00027 #include "gdbcore.h"
00028 #include "regcache.h"
00029 #include "opcode/ia64.h"
00030 #include "symfile.h"
00031 #include "objfiles.h"
00032 #include "elf-bfd.h"
00033 #include "exceptions.h"
00034 
00035 /* Need to define the following macro in order to get the complete
00036    load_module_desc struct definition in dlfcn.h  Otherwise, it doesn't
00037    match the size of the struct the loader is providing us during load
00038    events.  */
00039 #define _LOAD_MODULE_DESC_EXT
00040 
00041 #include <sys/ttrace.h>
00042 #include <dlfcn.h>
00043 #include <elf.h>
00044 #include <service_mgr.h>
00045 
00046 /* The following is to have access to the definition of type load_info_t.  */
00047 #include <crt0.h>
00048 
00049 /* The r32 pseudo-register number.
00050 
00051    Like all stacked registers, r32 is treated as a pseudo-register,
00052    because it is not always available for read/write via the ttrace
00053    interface.  */
00054 /* This is a bit of a hack, as we duplicate something hidden inside
00055    ia64-tdep.c, but oh well...  */
00056 #define IA64_R32_PSEUDO_REGNUM (IA64_NAT127_REGNUM + 2)
00057 
00058 /* Our struct so_list private data structure.  */
00059 
00060 struct lm_info
00061 {
00062   /* The shared library module descriptor.  We extract this structure
00063      from the loader at the time the shared library gets mapped.  */
00064   struct load_module_desc module_desc;
00065 
00066   /* The text segment address as defined in the shared library object
00067      (this is not the address where this segment got loaded).  This
00068      field is initially set to zero, and computed lazily.  */
00069   CORE_ADDR text_start;
00070 
00071   /* The data segment address as defined in the shared library object
00072      (this is not the address where this segment got loaded).  This
00073      field is initially set to zero, and computed lazily.  */
00074   CORE_ADDR data_start;
00075 };
00076 
00077 /* The list of shared libraries currently mapped by the inferior.  */
00078 
00079 static struct so_list *so_list_head = NULL;
00080 
00081 /* Create a new so_list element.  The result should be deallocated
00082    when no longer in use.  */
00083 
00084 static struct so_list *
00085 new_so_list (char *so_name, struct load_module_desc module_desc)
00086 {
00087   struct so_list *new_so;
00088 
00089   new_so = (struct so_list *) XZALLOC (struct so_list);
00090   new_so->lm_info = (struct lm_info *) XZALLOC (struct lm_info);
00091   new_so->lm_info->module_desc = module_desc;
00092 
00093   strncpy (new_so->so_name, so_name, SO_NAME_MAX_PATH_SIZE - 1);
00094   new_so->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
00095   strcpy (new_so->so_original_name, new_so->so_name);
00096 
00097   return new_so;
00098 }
00099 
00100 /* Return non-zero if the instruction at the current PC is a breakpoint
00101    part of the dynamic loading process.
00102 
00103    We identify such instructions by checking that the instruction at
00104    the current pc is a break insn where no software breakpoint has been
00105    inserted by us.  We also verify that the operands have specific
00106    known values, to be extra certain.
00107 
00108    PTID is the ptid of the thread that should be checked, but this
00109    function also assumes that inferior_ptid is already equal to PTID.
00110    Ideally, we would like to avoid the requirement on inferior_ptid,
00111    but many routines still use the inferior_ptid global to access
00112    the relevant thread's register and memory.  We still have the ptid
00113    as parameter to be able to pass it to the routines that do take a ptid
00114    - that way we avoid increasing explicit uses of the inferior_ptid
00115    global.  */
00116 
00117 static int
00118 ia64_hpux_at_dld_breakpoint_1_p (ptid_t ptid)
00119 {
00120   struct regcache *regcache = get_thread_regcache (ptid);
00121   CORE_ADDR pc = regcache_read_pc (regcache);
00122   struct address_space *aspace = get_regcache_aspace (regcache);
00123   ia64_insn t0, t1, slot[3], template, insn;
00124   int slotnum;
00125   bfd_byte bundle[16];
00126 
00127   /* If this is a regular breakpoint, then it can not be a dld one.  */
00128   if (breakpoint_inserted_here_p (aspace, pc))
00129     return 0;
00130 
00131   slotnum = ((long) pc) & 0xf;
00132   if (slotnum > 2)
00133     internal_error (__FILE__, __LINE__,
00134                     "invalid slot (%d) for address %s", slotnum,
00135                     paddress (get_regcache_arch (regcache), pc));
00136 
00137   pc -= (pc & 0xf);
00138   read_memory (pc, bundle, sizeof (bundle));
00139 
00140   /* bundles are always in little-endian byte order */
00141   t0 = bfd_getl64 (bundle);
00142   t1 = bfd_getl64 (bundle + 8);
00143   template = (t0 >> 1) & 0xf;
00144   slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
00145   slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
00146   slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
00147 
00148   if (template == 2 && slotnum == 1)
00149     {
00150       /* skip L slot in MLI template: */
00151       slotnum = 2;
00152     }
00153 
00154   insn = slot[slotnum];
00155 
00156   return (insn == 0x1c0c9c0       /* break.i 0x070327 */
00157           || insn == 0x3c0c9c0);  /* break.i 0x0f0327 */
00158 }
00159 
00160 /* Same as ia64_hpux_at_dld_breakpoint_1_p above, with the following
00161    differences: It temporarily sets inferior_ptid to PTID, and also
00162    contains any exception being raised.  */
00163 
00164 int
00165 ia64_hpux_at_dld_breakpoint_p (ptid_t ptid)
00166 {
00167   volatile struct gdb_exception e;
00168   ptid_t saved_ptid = inferior_ptid;
00169   int result = 0;
00170 
00171   inferior_ptid = ptid;
00172   TRY_CATCH (e, RETURN_MASK_ALL)
00173     {
00174       result = ia64_hpux_at_dld_breakpoint_1_p (ptid);
00175     }
00176   inferior_ptid = saved_ptid;
00177   if (e.reason < 0)
00178     warning (_("error while checking for dld breakpoint: %s"), e.message);
00179 
00180   return result;
00181 }
00182 
00183 /* Handler for library load event: Read the information provided by
00184    the loader, and then use it to read the shared library symbols.  */
00185 
00186 static void
00187 ia64_hpux_handle_load_event (struct regcache *regcache)
00188 {
00189   CORE_ADDR module_desc_addr;
00190   ULONGEST module_desc_size;
00191   CORE_ADDR so_path_addr;
00192   char so_path[PATH_MAX];
00193   struct load_module_desc module_desc;
00194   struct so_list *new_so;
00195 
00196   /* Extract the data provided by the loader as follow:
00197        - r33: Address of load_module_desc structure
00198        - r34: size of struct load_module_desc
00199        - r35: Address of string holding shared library path
00200    */
00201   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 1,
00202                                  &module_desc_addr);
00203   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 2,
00204                                  &module_desc_size);
00205   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM + 3,
00206                                  &so_path_addr);
00207 
00208   if (module_desc_size != sizeof (struct load_module_desc))
00209     warning (_("load_module_desc size (%ld) != size returned by kernel (%s)"),
00210              sizeof (struct load_module_desc),
00211              pulongest (module_desc_size));
00212 
00213   read_memory_string (so_path_addr, so_path, PATH_MAX);
00214   read_memory (module_desc_addr, (gdb_byte *) &module_desc,
00215                sizeof (module_desc));
00216 
00217   /* Create a new so_list element and insert it at the start of our
00218      so_list_head (we insert at the start of the list only because
00219      it is less work compared to inserting it elsewhere).  */
00220   new_so = new_so_list (so_path, module_desc);
00221   new_so->next = so_list_head;
00222   so_list_head = new_so;
00223 }
00224 
00225 /* Update the value of the PC to point to the begining of the next
00226    instruction bundle.  */
00227 
00228 static void
00229 ia64_hpux_move_pc_to_next_bundle (struct regcache *regcache)
00230 {
00231   CORE_ADDR pc = regcache_read_pc (regcache);
00232 
00233   pc -= pc & 0xf;
00234   pc += 16;
00235   ia64_write_pc (regcache, pc);
00236 }
00237 
00238 /* Handle loader events.
00239 
00240    PTID is the ptid of the thread corresponding to the event being
00241    handled.  Similarly to ia64_hpux_at_dld_breakpoint_1_p, this
00242    function assumes that inferior_ptid is set to PTID.  */
00243 
00244 static void
00245 ia64_hpux_handle_dld_breakpoint_1 (ptid_t ptid)
00246 {
00247   struct regcache *regcache = get_thread_regcache (ptid);
00248   ULONGEST arg0;
00249 
00250   /* The type of event is provided by the loaded via r32.  */
00251   regcache_cooked_read_unsigned (regcache, IA64_R32_PSEUDO_REGNUM, &arg0);
00252   switch (arg0)
00253     {
00254       case BREAK_DE_SVC_LOADED:
00255         /* Currently, the only service loads are uld and dld,
00256            so we shouldn't need to do anything.  Just ignore.  */
00257         break;
00258       case BREAK_DE_LIB_LOADED:
00259         ia64_hpux_handle_load_event (regcache);
00260         solib_add (NULL, 0, &current_target, auto_solib_add);
00261         break;
00262       case BREAK_DE_LIB_UNLOADED:
00263       case BREAK_DE_LOAD_COMPLETE:
00264       case BREAK_DE_BOR:
00265         /* Ignore for now.  */
00266         break;
00267     }
00268 
00269   /* Now that we have handled the event, we can move the PC to
00270      the next instruction bundle, past the break instruction.  */
00271   ia64_hpux_move_pc_to_next_bundle (regcache);
00272 }
00273 
00274 /* Same as ia64_hpux_handle_dld_breakpoint_1 above, with the following
00275    differences: This function temporarily sets inferior_ptid to PTID,
00276    and also contains any exception.  */
00277 
00278 void
00279 ia64_hpux_handle_dld_breakpoint (ptid_t ptid)
00280 {
00281   volatile struct gdb_exception e;
00282   ptid_t saved_ptid = inferior_ptid;
00283 
00284   inferior_ptid = ptid;
00285   TRY_CATCH (e, RETURN_MASK_ALL)
00286     {
00287       ia64_hpux_handle_dld_breakpoint_1 (ptid);
00288     }
00289   inferior_ptid = saved_ptid;
00290   if (e.reason < 0)
00291     warning (_("error detected while handling dld breakpoint: %s"), e.message);
00292 }
00293 
00294 /* Find the address of the code and data segments in ABFD, and update
00295    TEXT_START and DATA_START accordingly.  */
00296 
00297 static void
00298 ia64_hpux_find_start_vma (bfd *abfd, CORE_ADDR *text_start,
00299                           CORE_ADDR *data_start)
00300 {
00301   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
00302   Elf64_Phdr phdr;
00303   int i;
00304 
00305   *text_start = 0;
00306   *data_start = 0;
00307 
00308   if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
00309     error (_("invalid program header offset in %s"), abfd->filename);
00310 
00311   for (i = 0; i < i_ehdrp->e_phnum; i++)
00312     {
00313       if (bfd_bread (&phdr, sizeof (phdr), abfd) != sizeof (phdr))
00314         error (_("failed to read segment %d in %s"), i, abfd->filename);
00315 
00316       if (phdr.p_flags & PF_X
00317           && (*text_start == 0 || phdr.p_vaddr < *text_start))
00318         *text_start = phdr.p_vaddr;
00319 
00320       if (phdr.p_flags & PF_W
00321           && (*data_start == 0 || phdr.p_vaddr < *data_start))
00322         *data_start = phdr.p_vaddr;
00323     }
00324 }
00325 
00326 /* The "relocate_section_addresses" target_so_ops routine for ia64-hpux.  */
00327 
00328 static void
00329 ia64_hpux_relocate_section_addresses (struct so_list *so,
00330                                       struct target_section *sec)
00331 {
00332   CORE_ADDR offset = 0;
00333 
00334   /* If we haven't computed the text & data segment addresses, do so now.
00335      We do this here, because we now have direct access to the associated
00336      bfd, whereas we would have had to open our own if we wanted to do it
00337      while processing the library-load event.  */
00338   if (so->lm_info->text_start == 0 && so->lm_info->data_start == 0)
00339     ia64_hpux_find_start_vma (sec->the_bfd_section->owner,
00340                               &so->lm_info->text_start,
00341                               &so->lm_info->data_start);
00342 
00343   /* Determine the relocation offset based on which segment
00344      the section belongs to.  */
00345   if ((so->lm_info->text_start < so->lm_info->data_start
00346        && sec->addr < so->lm_info->data_start)
00347       || (so->lm_info->text_start > so->lm_info->data_start
00348           && sec->addr >= so->lm_info->text_start))
00349     offset = so->lm_info->module_desc.text_base - so->lm_info->text_start;
00350   else if ((so->lm_info->text_start < so->lm_info->data_start
00351             && sec->addr >= so->lm_info->data_start)
00352            || (so->lm_info->text_start > so->lm_info->data_start
00353                && sec->addr < so->lm_info->text_start))
00354     offset = so->lm_info->module_desc.data_base - so->lm_info->data_start;
00355 
00356   /* And now apply the relocation.  */
00357   sec->addr += offset;
00358   sec->endaddr += offset;
00359 
00360   /* Best effort to set addr_high/addr_low.  This is used only by
00361      'info sharedlibrary'.  */
00362   if (so->addr_low == 0 || sec->addr < so->addr_low)
00363     so->addr_low = sec->addr;
00364 
00365   if (so->addr_high == 0 || sec->endaddr > so->addr_high)
00366     so->addr_high = sec->endaddr;
00367 }
00368 
00369 /* The "free_so" target_so_ops routine for ia64-hpux.  */
00370 
00371 static void
00372 ia64_hpux_free_so (struct so_list *so)
00373 {
00374   xfree (so->lm_info);
00375 }
00376 
00377 /* The "clear_solib" target_so_ops routine for ia64-hpux.  */
00378 
00379 static void
00380 ia64_hpux_clear_solib (void)
00381 {
00382   struct so_list *so;
00383 
00384   while (so_list_head != NULL)
00385     {
00386       so = so_list_head;
00387       so_list_head = so_list_head->next;
00388 
00389       ia64_hpux_free_so (so);
00390       xfree (so);
00391     }
00392 }
00393 
00394 /* Assuming the inferior just stopped on an EXEC event, return
00395    the address of the load_info_t structure.  */
00396 
00397 static CORE_ADDR
00398 ia64_hpux_get_load_info_addr (void)
00399 {
00400   struct type *data_ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
00401   CORE_ADDR addr;
00402   int status;
00403 
00404   /* The address of the load_info_t structure is stored in the 4th
00405      argument passed to the initial thread of the process (in other
00406      words, in argv[3]).  So get the address of these arguments,
00407      and extract the 4th one.  */
00408   status = ttrace (TT_PROC_GET_ARGS, ptid_get_pid (inferior_ptid),
00409                    0, (uintptr_t) &addr, sizeof (CORE_ADDR), 0);
00410   if (status == -1 && errno)
00411     perror_with_name (_("Unable to get argument list"));
00412   return (read_memory_typed_address (addr + 3 * 8, data_ptr_type));
00413 }
00414 
00415 /* A structure used to aggregate some information extracted from
00416    the dynamic section of the main executable.  */
00417 
00418 struct dld_info
00419 {
00420   ULONGEST dld_flags;
00421   CORE_ADDR load_map;
00422 };
00423 
00424 /* Scan the ".dynamic" section referenced by ABFD and DYN_SECT,
00425    and extract the information needed to fill in INFO.  */
00426 
00427 static void
00428 ia64_hpux_read_dynamic_info (struct gdbarch *gdbarch, bfd *abfd,
00429                              asection *dyn_sect, struct dld_info *info)
00430 {
00431   int sect_size;
00432   char *buf;
00433   char *buf_end;
00434 
00435   /* Make sure that info always has initialized data, even if we fail
00436      to read the syn_sect section.  */
00437   memset (info, 0, sizeof (struct dld_info));
00438 
00439   sect_size = bfd_section_size (abfd, dyn_sect);
00440   buf = alloca (sect_size);
00441   buf_end = buf + sect_size;
00442 
00443   if (bfd_seek (abfd, dyn_sect->filepos, SEEK_SET) != 0
00444       || bfd_bread (buf, sect_size, abfd) != sect_size)
00445     error (_("failed to read contents of .dynamic section"));
00446 
00447   for (; buf < buf_end; buf += sizeof (Elf64_Dyn))
00448     {
00449       Elf64_Dyn *dynp = (Elf64_Dyn *) buf;
00450       Elf64_Sxword d_tag;
00451 
00452       d_tag = bfd_h_get_64 (abfd, &dynp->d_tag);
00453       switch (d_tag)
00454         {
00455           case DT_HP_DLD_FLAGS:
00456             info->dld_flags = bfd_h_get_64 (abfd, &dynp->d_un);
00457             break;
00458 
00459           case DT_HP_LOAD_MAP:
00460             {
00461               CORE_ADDR load_map_addr = bfd_h_get_64 (abfd, &dynp->d_un.d_ptr);
00462 
00463               if (target_read_memory (load_map_addr,
00464                                       (gdb_byte *) &info->load_map,
00465                                       sizeof (info->load_map)) != 0)
00466                 error (_("failed to read load map at %s"),
00467                        paddress (gdbarch, load_map_addr));
00468             }
00469             break;
00470         }
00471     }
00472 }
00473 
00474 /* Wrapper around target_read_memory used with libdl.  */
00475 
00476 static void *
00477 ia64_hpux_read_tgt_mem (void *buffer, uint64_t ptr, size_t bufsiz, int ident)
00478 {
00479   if (target_read_memory (ptr, (gdb_byte *) buffer, bufsiz) != 0)
00480     return 0;
00481   else
00482     return buffer;
00483 }
00484 
00485 /* Create a new so_list object for a shared library, and store that
00486    new so_list object in our SO_LIST_HEAD list.
00487 
00488    SO_INDEX is an index specifying the placement of the loaded shared
00489    library in the dynamic loader's search list.  Normally, this index
00490    is strictly positive, but an index of -1 refers to the loader itself.
00491 
00492    Return nonzero if the so_list object could be created.  A null
00493    return value with a positive SO_INDEX normally means that there are
00494    no more entries in the dynamic loader's search list at SO_INDEX or
00495    beyond.  */
00496 
00497 static int
00498 ia64_hpux_add_so_from_dld_info (struct dld_info info, int so_index)
00499 {
00500   struct load_module_desc module_desc;
00501   uint64_t so_handle;
00502   char *so_path;
00503   struct so_list *so;
00504 
00505   so_handle = dlgetmodinfo (so_index, &module_desc, sizeof (module_desc),
00506                             ia64_hpux_read_tgt_mem, 0, info.load_map);
00507 
00508   if (so_handle == 0)
00509     /* No such entry.  We probably reached the end of the list.  */
00510     return 0;
00511 
00512   so_path = dlgetname (&module_desc, sizeof (module_desc),
00513                        ia64_hpux_read_tgt_mem, 0, info.load_map);
00514   if (so_path == NULL)
00515     {
00516       /* Should never happen, but let's not crash if it does.  */
00517       warning (_("unable to get shared library name, symbols not loaded"));
00518       return 0;
00519     }
00520 
00521   /* Create a new so_list and insert it at the start of our list.
00522      The order is not extremely important, but it's less work to do so
00523      at the end of the list.  */
00524   so = new_so_list (so_path, module_desc);
00525   so->next = so_list_head;
00526   so_list_head = so;
00527 
00528   return 1;
00529 }
00530 
00531 /* Assuming we just attached to a process, update our list of shared
00532    libraries (SO_LIST_HEAD) as well as GDB's list.  */
00533 
00534 static void
00535 ia64_hpux_solib_add_after_attach (void)
00536 {
00537   bfd *abfd;
00538   asection *dyn_sect;
00539   struct dld_info info;
00540   int i;
00541 
00542   if (symfile_objfile == NULL)
00543     return;
00544 
00545   abfd = symfile_objfile->obfd;
00546   dyn_sect = bfd_get_section_by_name (abfd, ".dynamic");
00547 
00548   if (dyn_sect == NULL || bfd_section_size (abfd, dyn_sect) == 0)
00549     return;
00550 
00551   ia64_hpux_read_dynamic_info (get_objfile_arch (symfile_objfile), abfd,
00552                                dyn_sect, &info);
00553 
00554   if ((info.dld_flags & DT_HP_DEBUG_PRIVATE) == 0)
00555     {
00556       warning (_(
00557 "The shared libraries were not privately mapped; setting a breakpoint\n\
00558 in a shared library will not work until you rerun the program.\n\
00559 Use the following command to enable debugging of shared libraries.\n\
00560 chatr +dbg enable a.out"));
00561     }
00562 
00563   /* Read the symbols of the dynamic loader (dld.so).  */
00564   ia64_hpux_add_so_from_dld_info (info, -1);
00565 
00566   /* Read the symbols of all the other shared libraries.  */
00567   for (i = 1; ; i++)
00568     if (!ia64_hpux_add_so_from_dld_info (info, i))
00569       break;  /* End of list.  */
00570 
00571   /* Resync the library list at the core level.  */
00572   solib_add (NULL, 1, &current_target, auto_solib_add);
00573 }
00574 
00575 /* The "create_inferior_hook" target_so_ops routine for ia64-hpux.  */
00576 
00577 static void
00578 ia64_hpux_solib_create_inferior_hook (int from_tty)
00579 {
00580   CORE_ADDR load_info_addr;
00581   load_info_t load_info;
00582 
00583   /* Initially, we were thinking about adding a check that the program
00584      (accessible through symfile_objfile) was linked against some shared
00585      libraries, by searching for a ".dynamic" section.  However, could
00586      this break in the case of a statically linked program that later
00587      uses dlopen?  Programs that are fully statically linked are very
00588      rare, and we will worry about them when we encounter one that
00589      causes trouble.  */
00590 
00591   /* Set the LI_TRACE flag in the load_info_t structure.  This enables
00592      notifications when shared libraries are being mapped.  */
00593   load_info_addr = ia64_hpux_get_load_info_addr ();
00594   read_memory (load_info_addr, (gdb_byte *) &load_info, sizeof (load_info));
00595   load_info.li_flags |= LI_TRACE;
00596   write_memory (load_info_addr, (gdb_byte *) &load_info, sizeof (load_info));
00597 
00598   /* If we just attached to our process, some shard libraries have
00599      already been mapped.  Find which ones they are...  */
00600   if (current_inferior ()->attach_flag)
00601     ia64_hpux_solib_add_after_attach ();
00602 }
00603 
00604 /* The "special_symbol_handling" target_so_ops routine for ia64-hpux.  */
00605 
00606 static void
00607 ia64_hpux_special_symbol_handling (void)
00608 {
00609   /* Nothing to do.  */
00610 }
00611 
00612 /* The "current_sos" target_so_ops routine for ia64-hpux.  */
00613 
00614 static struct so_list *
00615 ia64_hpux_current_sos (void)
00616 {
00617   /* Return a deep copy of our own list.  */
00618   struct so_list *new_head = NULL, *prev_new_so = NULL;
00619   struct so_list *our_so;
00620 
00621   for (our_so = so_list_head; our_so != NULL; our_so = our_so->next)
00622     {
00623       struct so_list *new_so;
00624 
00625       new_so = new_so_list (our_so->so_name, our_so->lm_info->module_desc);
00626       if (prev_new_so != NULL)
00627         prev_new_so->next = new_so;
00628       prev_new_so = new_so;
00629       if (new_head == NULL)
00630         new_head = new_so;
00631     }
00632 
00633   return new_head;
00634 }
00635 
00636 /* The "open_symbol_file_object" target_so_ops routine for ia64-hpux.  */
00637 
00638 static int
00639 ia64_hpux_open_symbol_file_object (void *from_ttyp)
00640 {
00641   return 0;
00642 }
00643 
00644 /* The "in_dynsym_resolve_code" target_so_ops routine for ia64-hpux.  */
00645 
00646 static int
00647 ia64_hpux_in_dynsym_resolve_code (CORE_ADDR pc)
00648 {
00649   return 0;
00650 }
00651 
00652 /* If FADDR is the address of a function inside one of the shared
00653    libraries, return the shared library linkage address.  */
00654 
00655 CORE_ADDR
00656 ia64_hpux_get_solib_linkage_addr (CORE_ADDR faddr)
00657 {
00658   struct so_list *so = so_list_head;
00659 
00660   while (so != NULL)
00661     {
00662       struct load_module_desc module_desc = so->lm_info->module_desc;
00663 
00664       if (module_desc.text_base <= faddr
00665           && (module_desc.text_base + module_desc.text_size) > faddr)
00666         return module_desc.linkage_ptr;
00667 
00668       so = so->next;
00669     }
00670 
00671   return 0;
00672 }
00673 
00674 /* Create a new target_so_ops structure suitable for ia64-hpux, and
00675    return its address.  */
00676 
00677 static struct target_so_ops *
00678 ia64_hpux_target_so_ops (void)
00679 {
00680   struct target_so_ops *ops = XZALLOC (struct target_so_ops);
00681 
00682   ops->relocate_section_addresses = ia64_hpux_relocate_section_addresses;
00683   ops->free_so = ia64_hpux_free_so;
00684   ops->clear_solib = ia64_hpux_clear_solib;
00685   ops->solib_create_inferior_hook = ia64_hpux_solib_create_inferior_hook;
00686   ops->special_symbol_handling = ia64_hpux_special_symbol_handling;
00687   ops->current_sos = ia64_hpux_current_sos;
00688   ops->open_symbol_file_object = ia64_hpux_open_symbol_file_object;
00689   ops->in_dynsym_resolve_code = ia64_hpux_in_dynsym_resolve_code;
00690   ops->bfd_open = solib_bfd_open;
00691 
00692   return ops;
00693 }
00694 
00695 /* Prevent warning from -Wmissing-prototypes.  */
00696 void _initialize_solib_ia64_hpux (void);
00697 
00698 void
00699 _initialize_solib_ia64_hpux (void)
00700 {
00701   ia64_hpux_so_ops = ia64_hpux_target_so_ops ();
00702 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines