GDB (API)
|
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, ¤t_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, ¤t_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 }