198944Sobrien/* Handle SunOS shared libraries for GDB, the GNU Debugger. 298944Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 3130803Smarcel 2001, 2004 498944Sobrien Free Software Foundation, Inc. 598944Sobrien 698944Sobrien This file is part of GDB. 798944Sobrien 898944Sobrien This program is free software; you can redistribute it and/or modify 998944Sobrien it under the terms of the GNU General Public License as published by 1098944Sobrien the Free Software Foundation; either version 2 of the License, or 1198944Sobrien (at your option) any later version. 1298944Sobrien 1398944Sobrien This program is distributed in the hope that it will be useful, 1498944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1598944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1698944Sobrien GNU General Public License for more details. 1798944Sobrien 1898944Sobrien You should have received a copy of the GNU General Public License 1998944Sobrien along with this program; if not, write to the Free Software 2098944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2198944Sobrien Boston, MA 02111-1307, USA. */ 2298944Sobrien 2398944Sobrien#include "defs.h" 2498944Sobrien 2598944Sobrien#include <sys/types.h> 2698944Sobrien#include <signal.h> 2798944Sobrien#include "gdb_string.h" 2898944Sobrien#include <sys/param.h> 2998944Sobrien#include <fcntl.h> 3098944Sobrien 3198944Sobrien /* SunOS shared libs need the nlist structure. */ 3298944Sobrien#include <a.out.h> 3398944Sobrien#include <link.h> 3498944Sobrien 3598944Sobrien#include "symtab.h" 3698944Sobrien#include "bfd.h" 3798944Sobrien#include "symfile.h" 3898944Sobrien#include "objfiles.h" 3998944Sobrien#include "gdbcore.h" 4098944Sobrien#include "inferior.h" 4198944Sobrien#include "solist.h" 42130803Smarcel#include "bcache.h" 43130803Smarcel#include "regcache.h" 4498944Sobrien 4598944Sobrien/* Link map info to include in an allocated so_list entry */ 4698944Sobrien 4798944Sobrienstruct lm_info 4898944Sobrien { 4998944Sobrien /* Pointer to copy of link map from inferior. The type is char * 5098944Sobrien rather than void *, so that we may use byte offsets to find the 5198944Sobrien various fields without the need for a cast. */ 5298944Sobrien char *lm; 5398944Sobrien }; 5498944Sobrien 5598944Sobrien 5698944Sobrien/* Symbols which are used to locate the base of the link map structures. */ 5798944Sobrien 5898944Sobrienstatic char *debug_base_symbols[] = 5998944Sobrien{ 6098944Sobrien "_DYNAMIC", 6198944Sobrien "_DYNAMIC__MGC", 6298944Sobrien NULL 6398944Sobrien}; 6498944Sobrien 6598944Sobrienstatic char *main_name_list[] = 6698944Sobrien{ 6798944Sobrien "main_$main", 6898944Sobrien NULL 6998944Sobrien}; 7098944Sobrien 71130803Smarcel/* Macro to extract an address from a solib structure. When GDB is 72130803Smarcel configured for some 32-bit targets (e.g. Solaris 2.7 sparc), BFD is 73130803Smarcel configured to handle 64-bit targets, so CORE_ADDR is 64 bits. We 74130803Smarcel have to extract only the significant bits of addresses to get the 75130803Smarcel right address when accessing the core file BFD. 7698944Sobrien 77130803Smarcel Assume that the address is unsigned. */ 78130803Smarcel 7998944Sobrien#define SOLIB_EXTRACT_ADDRESS(MEMBER) \ 80130803Smarcel extract_unsigned_integer (&(MEMBER), sizeof (MEMBER)) 8198944Sobrien 8298944Sobrien/* local data declarations */ 8398944Sobrien 8498944Sobrienstatic struct link_dynamic dynamic_copy; 8598944Sobrienstatic struct link_dynamic_2 ld_2_copy; 8698944Sobrienstatic struct ld_debug debug_copy; 8798944Sobrienstatic CORE_ADDR debug_addr; 8898944Sobrienstatic CORE_ADDR flag_addr; 8998944Sobrien 9098944Sobrien#ifndef offsetof 9198944Sobrien#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) 9298944Sobrien#endif 9398944Sobrien#define fieldsize(TYPE, MEMBER) (sizeof (((TYPE *)0)->MEMBER)) 9498944Sobrien 9598944Sobrien/* link map access functions */ 9698944Sobrien 9798944Sobrienstatic CORE_ADDR 9898944SobrienLM_ADDR (struct so_list *so) 9998944Sobrien{ 10098944Sobrien int lm_addr_offset = offsetof (struct link_map, lm_addr); 10198944Sobrien int lm_addr_size = fieldsize (struct link_map, lm_addr); 10298944Sobrien 10398944Sobrien return (CORE_ADDR) extract_signed_integer (so->lm_info->lm + lm_addr_offset, 10498944Sobrien lm_addr_size); 10598944Sobrien} 10698944Sobrien 10798944Sobrienstatic CORE_ADDR 10898944SobrienLM_NEXT (struct so_list *so) 10998944Sobrien{ 11098944Sobrien int lm_next_offset = offsetof (struct link_map, lm_next); 11198944Sobrien int lm_next_size = fieldsize (struct link_map, lm_next); 11298944Sobrien 113130803Smarcel /* Assume that the address is unsigned. */ 114130803Smarcel return extract_unsigned_integer (so->lm_info->lm + lm_next_offset, 115130803Smarcel lm_next_size); 11698944Sobrien} 11798944Sobrien 11898944Sobrienstatic CORE_ADDR 11998944SobrienLM_NAME (struct so_list *so) 12098944Sobrien{ 12198944Sobrien int lm_name_offset = offsetof (struct link_map, lm_name); 12298944Sobrien int lm_name_size = fieldsize (struct link_map, lm_name); 12398944Sobrien 124130803Smarcel /* Assume that the address is unsigned. */ 125130803Smarcel return extract_unsigned_integer (so->lm_info->lm + lm_name_offset, 126130803Smarcel lm_name_size); 12798944Sobrien} 12898944Sobrien 12998944Sobrienstatic CORE_ADDR debug_base; /* Base of dynamic linker structures */ 13098944Sobrien 13198944Sobrien/* Local function prototypes */ 13298944Sobrien 13398944Sobrienstatic int match_main (char *); 13498944Sobrien 13598944Sobrien/* Allocate the runtime common object file. */ 13698944Sobrien 13798944Sobrienstatic void 13898944Sobrienallocate_rt_common_objfile (void) 13998944Sobrien{ 14098944Sobrien struct objfile *objfile; 14198944Sobrien struct objfile *last_one; 14298944Sobrien 14398944Sobrien objfile = (struct objfile *) xmalloc (sizeof (struct objfile)); 14498944Sobrien memset (objfile, 0, sizeof (struct objfile)); 14598944Sobrien objfile->md = NULL; 146130803Smarcel objfile->psymbol_cache = bcache_xmalloc (); 147130803Smarcel objfile->macro_cache = bcache_xmalloc (); 148130803Smarcel obstack_init (&objfile->objfile_obstack); 14998944Sobrien objfile->name = mstrsave (objfile->md, "rt_common"); 15098944Sobrien 15198944Sobrien /* Add this file onto the tail of the linked list of other such files. */ 15298944Sobrien 15398944Sobrien objfile->next = NULL; 15498944Sobrien if (object_files == NULL) 15598944Sobrien object_files = objfile; 15698944Sobrien else 15798944Sobrien { 15898944Sobrien for (last_one = object_files; 15998944Sobrien last_one->next; 16098944Sobrien last_one = last_one->next); 16198944Sobrien last_one->next = objfile; 16298944Sobrien } 16398944Sobrien 16498944Sobrien rt_common_objfile = objfile; 16598944Sobrien} 16698944Sobrien 16798944Sobrien/* Read all dynamically loaded common symbol definitions from the inferior 16898944Sobrien and put them into the minimal symbol table for the runtime common 16998944Sobrien objfile. */ 17098944Sobrien 17198944Sobrienstatic void 17298944Sobriensolib_add_common_symbols (CORE_ADDR rtc_symp) 17398944Sobrien{ 17498944Sobrien struct rtc_symb inferior_rtc_symb; 17598944Sobrien struct nlist inferior_rtc_nlist; 17698944Sobrien int len; 17798944Sobrien char *name; 17898944Sobrien 17998944Sobrien /* Remove any runtime common symbols from previous runs. */ 18098944Sobrien 18198944Sobrien if (rt_common_objfile != NULL && rt_common_objfile->minimal_symbol_count) 18298944Sobrien { 183130803Smarcel obstack_free (&rt_common_objfile->objfile_obstack, 0); 184130803Smarcel obstack_init (&rt_common_objfile->objfile_obstack); 18598944Sobrien rt_common_objfile->minimal_symbol_count = 0; 18698944Sobrien rt_common_objfile->msymbols = NULL; 187130803Smarcel terminate_minimal_symbol_table (rt_common_objfile); 18898944Sobrien } 18998944Sobrien 19098944Sobrien init_minimal_symbol_collection (); 19198944Sobrien make_cleanup_discard_minimal_symbols (); 19298944Sobrien 19398944Sobrien while (rtc_symp) 19498944Sobrien { 19598944Sobrien read_memory (rtc_symp, 19698944Sobrien (char *) &inferior_rtc_symb, 19798944Sobrien sizeof (inferior_rtc_symb)); 19898944Sobrien read_memory (SOLIB_EXTRACT_ADDRESS (inferior_rtc_symb.rtc_sp), 19998944Sobrien (char *) &inferior_rtc_nlist, 20098944Sobrien sizeof (inferior_rtc_nlist)); 20198944Sobrien if (inferior_rtc_nlist.n_type == N_COMM) 20298944Sobrien { 20398944Sobrien /* FIXME: The length of the symbol name is not available, but in the 20498944Sobrien current implementation the common symbol is allocated immediately 20598944Sobrien behind the name of the symbol. */ 20698944Sobrien len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx; 20798944Sobrien 20898944Sobrien name = xmalloc (len); 20998944Sobrien read_memory (SOLIB_EXTRACT_ADDRESS (inferior_rtc_nlist.n_un.n_name), 21098944Sobrien name, len); 21198944Sobrien 21298944Sobrien /* Allocate the runtime common objfile if necessary. */ 21398944Sobrien if (rt_common_objfile == NULL) 21498944Sobrien allocate_rt_common_objfile (); 21598944Sobrien 21698944Sobrien prim_record_minimal_symbol (name, inferior_rtc_nlist.n_value, 21798944Sobrien mst_bss, rt_common_objfile); 21898944Sobrien xfree (name); 21998944Sobrien } 22098944Sobrien rtc_symp = SOLIB_EXTRACT_ADDRESS (inferior_rtc_symb.rtc_next); 22198944Sobrien } 22298944Sobrien 22398944Sobrien /* Install any minimal symbols that have been collected as the current 22498944Sobrien minimal symbols for the runtime common objfile. */ 22598944Sobrien 22698944Sobrien install_minimal_symbols (rt_common_objfile); 22798944Sobrien} 22898944Sobrien 22998944Sobrien 23098944Sobrien/* 23198944Sobrien 23298944Sobrien LOCAL FUNCTION 23398944Sobrien 23498944Sobrien locate_base -- locate the base address of dynamic linker structs 23598944Sobrien 23698944Sobrien SYNOPSIS 23798944Sobrien 23898944Sobrien CORE_ADDR locate_base (void) 23998944Sobrien 24098944Sobrien DESCRIPTION 24198944Sobrien 24298944Sobrien For both the SunOS and SVR4 shared library implementations, if the 24398944Sobrien inferior executable has been linked dynamically, there is a single 24498944Sobrien address somewhere in the inferior's data space which is the key to 24598944Sobrien locating all of the dynamic linker's runtime structures. This 24698944Sobrien address is the value of the debug base symbol. The job of this 24798944Sobrien function is to find and return that address, or to return 0 if there 24898944Sobrien is no such address (the executable is statically linked for example). 24998944Sobrien 25098944Sobrien For SunOS, the job is almost trivial, since the dynamic linker and 25198944Sobrien all of it's structures are statically linked to the executable at 25298944Sobrien link time. Thus the symbol for the address we are looking for has 25398944Sobrien already been added to the minimal symbol table for the executable's 25498944Sobrien objfile at the time the symbol file's symbols were read, and all we 25598944Sobrien have to do is look it up there. Note that we explicitly do NOT want 25698944Sobrien to find the copies in the shared library. 25798944Sobrien 25898944Sobrien The SVR4 version is a bit more complicated because the address 25998944Sobrien is contained somewhere in the dynamic info section. We have to go 26098944Sobrien to a lot more work to discover the address of the debug base symbol. 26198944Sobrien Because of this complexity, we cache the value we find and return that 26298944Sobrien value on subsequent invocations. Note there is no copy in the 26398944Sobrien executable symbol tables. 26498944Sobrien 26598944Sobrien */ 26698944Sobrien 26798944Sobrienstatic CORE_ADDR 26898944Sobrienlocate_base (void) 26998944Sobrien{ 27098944Sobrien struct minimal_symbol *msymbol; 27198944Sobrien CORE_ADDR address = 0; 27298944Sobrien char **symbolp; 27398944Sobrien 27498944Sobrien /* For SunOS, we want to limit the search for the debug base symbol to the 27598944Sobrien executable being debugged, since there is a duplicate named symbol in the 27698944Sobrien shared library. We don't want the shared library versions. */ 27798944Sobrien 27898944Sobrien for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++) 27998944Sobrien { 28098944Sobrien msymbol = lookup_minimal_symbol (*symbolp, NULL, symfile_objfile); 28198944Sobrien if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) 28298944Sobrien { 28398944Sobrien address = SYMBOL_VALUE_ADDRESS (msymbol); 28498944Sobrien return (address); 28598944Sobrien } 28698944Sobrien } 28798944Sobrien return (0); 28898944Sobrien} 28998944Sobrien 29098944Sobrien/* 29198944Sobrien 29298944Sobrien LOCAL FUNCTION 29398944Sobrien 29498944Sobrien first_link_map_member -- locate first member in dynamic linker's map 29598944Sobrien 29698944Sobrien SYNOPSIS 29798944Sobrien 29898944Sobrien static CORE_ADDR first_link_map_member (void) 29998944Sobrien 30098944Sobrien DESCRIPTION 30198944Sobrien 30298944Sobrien Find the first element in the inferior's dynamic link map, and 30398944Sobrien return its address in the inferior. This function doesn't copy the 30498944Sobrien link map entry itself into our address space; current_sos actually 30598944Sobrien does the reading. */ 30698944Sobrien 30798944Sobrienstatic CORE_ADDR 30898944Sobrienfirst_link_map_member (void) 30998944Sobrien{ 31098944Sobrien CORE_ADDR lm = 0; 31198944Sobrien 31298944Sobrien read_memory (debug_base, (char *) &dynamic_copy, sizeof (dynamic_copy)); 31398944Sobrien if (dynamic_copy.ld_version >= 2) 31498944Sobrien { 31598944Sobrien /* It is a version that we can deal with, so read in the secondary 31698944Sobrien structure and find the address of the link map list from it. */ 31798944Sobrien read_memory (SOLIB_EXTRACT_ADDRESS (dynamic_copy.ld_un.ld_2), 31898944Sobrien (char *) &ld_2_copy, sizeof (struct link_dynamic_2)); 31998944Sobrien lm = SOLIB_EXTRACT_ADDRESS (ld_2_copy.ld_loaded); 32098944Sobrien } 32198944Sobrien return (lm); 32298944Sobrien} 32398944Sobrien 32498944Sobrienstatic int 32598944Sobrienopen_symbol_file_object (void *from_ttyp) 32698944Sobrien{ 32798944Sobrien return 1; 32898944Sobrien} 32998944Sobrien 33098944Sobrien 33198944Sobrien/* LOCAL FUNCTION 33298944Sobrien 33398944Sobrien current_sos -- build a list of currently loaded shared objects 33498944Sobrien 33598944Sobrien SYNOPSIS 33698944Sobrien 33798944Sobrien struct so_list *current_sos () 33898944Sobrien 33998944Sobrien DESCRIPTION 34098944Sobrien 34198944Sobrien Build a list of `struct so_list' objects describing the shared 34298944Sobrien objects currently loaded in the inferior. This list does not 34398944Sobrien include an entry for the main executable file. 34498944Sobrien 34598944Sobrien Note that we only gather information directly available from the 34698944Sobrien inferior --- we don't examine any of the shared library files 34798944Sobrien themselves. The declaration of `struct so_list' says which fields 34898944Sobrien we provide values for. */ 34998944Sobrien 35098944Sobrienstatic struct so_list * 35198944Sobriensunos_current_sos (void) 35298944Sobrien{ 35398944Sobrien CORE_ADDR lm; 35498944Sobrien struct so_list *head = 0; 35598944Sobrien struct so_list **link_ptr = &head; 35698944Sobrien int errcode; 35798944Sobrien char *buffer; 35898944Sobrien 35998944Sobrien /* Make sure we've looked up the inferior's dynamic linker's base 36098944Sobrien structure. */ 36198944Sobrien if (! debug_base) 36298944Sobrien { 36398944Sobrien debug_base = locate_base (); 36498944Sobrien 36598944Sobrien /* If we can't find the dynamic linker's base structure, this 36698944Sobrien must not be a dynamically linked executable. Hmm. */ 36798944Sobrien if (! debug_base) 36898944Sobrien return 0; 36998944Sobrien } 37098944Sobrien 37198944Sobrien /* Walk the inferior's link map list, and build our list of 37298944Sobrien `struct so_list' nodes. */ 37398944Sobrien lm = first_link_map_member (); 37498944Sobrien while (lm) 37598944Sobrien { 37698944Sobrien struct so_list *new 37798944Sobrien = (struct so_list *) xmalloc (sizeof (struct so_list)); 37898944Sobrien struct cleanup *old_chain = make_cleanup (xfree, new); 37998944Sobrien 38098944Sobrien memset (new, 0, sizeof (*new)); 38198944Sobrien 38298944Sobrien new->lm_info = xmalloc (sizeof (struct lm_info)); 38398944Sobrien make_cleanup (xfree, new->lm_info); 38498944Sobrien 38598944Sobrien new->lm_info->lm = xmalloc (sizeof (struct link_map)); 38698944Sobrien make_cleanup (xfree, new->lm_info->lm); 38798944Sobrien memset (new->lm_info->lm, 0, sizeof (struct link_map)); 38898944Sobrien 38998944Sobrien read_memory (lm, new->lm_info->lm, sizeof (struct link_map)); 39098944Sobrien 39198944Sobrien lm = LM_NEXT (new); 39298944Sobrien 39398944Sobrien /* Extract this shared object's name. */ 39498944Sobrien target_read_string (LM_NAME (new), &buffer, 39598944Sobrien SO_NAME_MAX_PATH_SIZE - 1, &errcode); 39698944Sobrien if (errcode != 0) 39798944Sobrien { 39898944Sobrien warning ("current_sos: Can't read pathname for load map: %s\n", 39998944Sobrien safe_strerror (errcode)); 40098944Sobrien } 40198944Sobrien else 40298944Sobrien { 40398944Sobrien strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1); 40498944Sobrien new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; 40598944Sobrien xfree (buffer); 40698944Sobrien strcpy (new->so_original_name, new->so_name); 40798944Sobrien } 40898944Sobrien 40998944Sobrien /* If this entry has no name, or its name matches the name 41098944Sobrien for the main executable, don't include it in the list. */ 41198944Sobrien if (! new->so_name[0] 41298944Sobrien || match_main (new->so_name)) 41398944Sobrien free_so (new); 41498944Sobrien else 41598944Sobrien { 41698944Sobrien new->next = 0; 41798944Sobrien *link_ptr = new; 41898944Sobrien link_ptr = &new->next; 41998944Sobrien } 42098944Sobrien 42198944Sobrien discard_cleanups (old_chain); 42298944Sobrien } 42398944Sobrien 42498944Sobrien return head; 42598944Sobrien} 42698944Sobrien 42798944Sobrien 42898944Sobrien/* On some systems, the only way to recognize the link map entry for 42998944Sobrien the main executable file is by looking at its name. Return 43098944Sobrien non-zero iff SONAME matches one of the known main executable names. */ 43198944Sobrien 43298944Sobrienstatic int 43398944Sobrienmatch_main (char *soname) 43498944Sobrien{ 43598944Sobrien char **mainp; 43698944Sobrien 43798944Sobrien for (mainp = main_name_list; *mainp != NULL; mainp++) 43898944Sobrien { 43998944Sobrien if (strcmp (soname, *mainp) == 0) 44098944Sobrien return (1); 44198944Sobrien } 44298944Sobrien 44398944Sobrien return (0); 44498944Sobrien} 44598944Sobrien 44698944Sobrien 44798944Sobrienstatic int 44898944Sobriensunos_in_dynsym_resolve_code (CORE_ADDR pc) 44998944Sobrien{ 45098944Sobrien return 0; 45198944Sobrien} 45298944Sobrien 45398944Sobrien/* 45498944Sobrien 45598944Sobrien LOCAL FUNCTION 45698944Sobrien 45798944Sobrien disable_break -- remove the "mapping changed" breakpoint 45898944Sobrien 45998944Sobrien SYNOPSIS 46098944Sobrien 46198944Sobrien static int disable_break () 46298944Sobrien 46398944Sobrien DESCRIPTION 46498944Sobrien 46598944Sobrien Removes the breakpoint that gets hit when the dynamic linker 46698944Sobrien completes a mapping change. 46798944Sobrien 46898944Sobrien */ 46998944Sobrien 47098944Sobrienstatic int 47198944Sobriendisable_break (void) 47298944Sobrien{ 47398944Sobrien CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */ 47498944Sobrien 47598944Sobrien int in_debugger = 0; 47698944Sobrien 47798944Sobrien /* Read the debugger structure from the inferior to retrieve the 47898944Sobrien address of the breakpoint and the original contents of the 47998944Sobrien breakpoint address. Remove the breakpoint by writing the original 48098944Sobrien contents back. */ 48198944Sobrien 48298944Sobrien read_memory (debug_addr, (char *) &debug_copy, sizeof (debug_copy)); 48398944Sobrien 48498944Sobrien /* Set `in_debugger' to zero now. */ 48598944Sobrien 48698944Sobrien write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger)); 48798944Sobrien 48898944Sobrien breakpoint_addr = SOLIB_EXTRACT_ADDRESS (debug_copy.ldd_bp_addr); 48998944Sobrien write_memory (breakpoint_addr, (char *) &debug_copy.ldd_bp_inst, 49098944Sobrien sizeof (debug_copy.ldd_bp_inst)); 49198944Sobrien 49298944Sobrien /* For the SVR4 version, we always know the breakpoint address. For the 49398944Sobrien SunOS version we don't know it until the above code is executed. 49498944Sobrien Grumble if we are stopped anywhere besides the breakpoint address. */ 49598944Sobrien 49698944Sobrien if (stop_pc != breakpoint_addr) 49798944Sobrien { 49898944Sobrien warning ("stopped at unknown breakpoint while handling shared libraries"); 49998944Sobrien } 50098944Sobrien 50198944Sobrien return 1; 50298944Sobrien} 50398944Sobrien 50498944Sobrien 50598944Sobrien/* 50698944Sobrien 50798944Sobrien LOCAL FUNCTION 50898944Sobrien 50998944Sobrien enable_break -- arrange for dynamic linker to hit breakpoint 51098944Sobrien 51198944Sobrien SYNOPSIS 51298944Sobrien 51398944Sobrien int enable_break (void) 51498944Sobrien 51598944Sobrien DESCRIPTION 51698944Sobrien 51798944Sobrien Both the SunOS and the SVR4 dynamic linkers have, as part of their 51898944Sobrien debugger interface, support for arranging for the inferior to hit 51998944Sobrien a breakpoint after mapping in the shared libraries. This function 52098944Sobrien enables that breakpoint. 52198944Sobrien 52298944Sobrien For SunOS, there is a special flag location (in_debugger) which we 52398944Sobrien set to 1. When the dynamic linker sees this flag set, it will set 52498944Sobrien a breakpoint at a location known only to itself, after saving the 52598944Sobrien original contents of that place and the breakpoint address itself, 52698944Sobrien in it's own internal structures. When we resume the inferior, it 52798944Sobrien will eventually take a SIGTRAP when it runs into the breakpoint. 52898944Sobrien We handle this (in a different place) by restoring the contents of 52998944Sobrien the breakpointed location (which is only known after it stops), 53098944Sobrien chasing around to locate the shared libraries that have been 53198944Sobrien loaded, then resuming. 53298944Sobrien 53398944Sobrien For SVR4, the debugger interface structure contains a member (r_brk) 53498944Sobrien which is statically initialized at the time the shared library is 53598944Sobrien built, to the offset of a function (_r_debug_state) which is guaran- 53698944Sobrien teed to be called once before mapping in a library, and again when 53798944Sobrien the mapping is complete. At the time we are examining this member, 53898944Sobrien it contains only the unrelocated offset of the function, so we have 53998944Sobrien to do our own relocation. Later, when the dynamic linker actually 54098944Sobrien runs, it relocates r_brk to be the actual address of _r_debug_state(). 54198944Sobrien 54298944Sobrien The debugger interface structure also contains an enumeration which 54398944Sobrien is set to either RT_ADD or RT_DELETE prior to changing the mapping, 54498944Sobrien depending upon whether or not the library is being mapped or unmapped, 54598944Sobrien and then set to RT_CONSISTENT after the library is mapped/unmapped. 54698944Sobrien */ 54798944Sobrien 54898944Sobrienstatic int 54998944Sobrienenable_break (void) 55098944Sobrien{ 55198944Sobrien int success = 0; 55298944Sobrien int j; 55398944Sobrien int in_debugger; 55498944Sobrien 55598944Sobrien /* Get link_dynamic structure */ 55698944Sobrien 55798944Sobrien j = target_read_memory (debug_base, (char *) &dynamic_copy, 55898944Sobrien sizeof (dynamic_copy)); 55998944Sobrien if (j) 56098944Sobrien { 56198944Sobrien /* unreadable */ 56298944Sobrien return (0); 56398944Sobrien } 56498944Sobrien 56598944Sobrien /* Calc address of debugger interface structure */ 56698944Sobrien 56798944Sobrien debug_addr = SOLIB_EXTRACT_ADDRESS (dynamic_copy.ldd); 56898944Sobrien 56998944Sobrien /* Calc address of `in_debugger' member of debugger interface structure */ 57098944Sobrien 57198944Sobrien flag_addr = debug_addr + (CORE_ADDR) ((char *) &debug_copy.ldd_in_debugger - 57298944Sobrien (char *) &debug_copy); 57398944Sobrien 57498944Sobrien /* Write a value of 1 to this member. */ 57598944Sobrien 57698944Sobrien in_debugger = 1; 57798944Sobrien write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger)); 57898944Sobrien success = 1; 57998944Sobrien 58098944Sobrien return (success); 58198944Sobrien} 58298944Sobrien 58398944Sobrien/* 58498944Sobrien 58598944Sobrien LOCAL FUNCTION 58698944Sobrien 58798944Sobrien special_symbol_handling -- additional shared library symbol handling 58898944Sobrien 58998944Sobrien SYNOPSIS 59098944Sobrien 59198944Sobrien void special_symbol_handling () 59298944Sobrien 59398944Sobrien DESCRIPTION 59498944Sobrien 59598944Sobrien Once the symbols from a shared object have been loaded in the usual 59698944Sobrien way, we are called to do any system specific symbol handling that 59798944Sobrien is needed. 59898944Sobrien 59998944Sobrien For SunOS4, this consists of grunging around in the dynamic 60098944Sobrien linkers structures to find symbol definitions for "common" symbols 60198944Sobrien and adding them to the minimal symbol table for the runtime common 60298944Sobrien objfile. 60398944Sobrien 60498944Sobrien */ 60598944Sobrien 60698944Sobrienstatic void 60798944Sobriensunos_special_symbol_handling (void) 60898944Sobrien{ 60998944Sobrien int j; 61098944Sobrien 61198944Sobrien if (debug_addr == 0) 61298944Sobrien { 61398944Sobrien /* Get link_dynamic structure */ 61498944Sobrien 61598944Sobrien j = target_read_memory (debug_base, (char *) &dynamic_copy, 61698944Sobrien sizeof (dynamic_copy)); 61798944Sobrien if (j) 61898944Sobrien { 61998944Sobrien /* unreadable */ 62098944Sobrien return; 62198944Sobrien } 62298944Sobrien 62398944Sobrien /* Calc address of debugger interface structure */ 62498944Sobrien /* FIXME, this needs work for cross-debugging of core files 62598944Sobrien (byteorder, size, alignment, etc). */ 62698944Sobrien 62798944Sobrien debug_addr = SOLIB_EXTRACT_ADDRESS (dynamic_copy.ldd); 62898944Sobrien } 62998944Sobrien 63098944Sobrien /* Read the debugger structure from the inferior, just to make sure 63198944Sobrien we have a current copy. */ 63298944Sobrien 63398944Sobrien j = target_read_memory (debug_addr, (char *) &debug_copy, 63498944Sobrien sizeof (debug_copy)); 63598944Sobrien if (j) 63698944Sobrien return; /* unreadable */ 63798944Sobrien 63898944Sobrien /* Get common symbol definitions for the loaded object. */ 63998944Sobrien 64098944Sobrien if (debug_copy.ldd_cp) 64198944Sobrien { 64298944Sobrien solib_add_common_symbols (SOLIB_EXTRACT_ADDRESS (debug_copy.ldd_cp)); 64398944Sobrien } 64498944Sobrien} 64598944Sobrien 64698944Sobrien/* Relocate the main executable. This function should be called upon 64798944Sobrien stopping the inferior process at the entry point to the program. 64898944Sobrien The entry point from BFD is compared to the PC and if they are 64998944Sobrien different, the main executable is relocated by the proper amount. 65098944Sobrien 65198944Sobrien As written it will only attempt to relocate executables which 65298944Sobrien lack interpreter sections. It seems likely that only dynamic 65398944Sobrien linker executables will get relocated, though it should work 65498944Sobrien properly for a position-independent static executable as well. */ 65598944Sobrien 65698944Sobrienstatic void 65798944Sobriensunos_relocate_main_executable (void) 65898944Sobrien{ 65998944Sobrien asection *interp_sect; 66098944Sobrien CORE_ADDR pc = read_pc (); 66198944Sobrien 66298944Sobrien /* Decide if the objfile needs to be relocated. As indicated above, 66398944Sobrien we will only be here when execution is stopped at the beginning 66498944Sobrien of the program. Relocation is necessary if the address at which 66598944Sobrien we are presently stopped differs from the start address stored in 66698944Sobrien the executable AND there's no interpreter section. The condition 66798944Sobrien regarding the interpreter section is very important because if 66898944Sobrien there *is* an interpreter section, execution will begin there 66998944Sobrien instead. When there is an interpreter section, the start address 67098944Sobrien is (presumably) used by the interpreter at some point to start 67198944Sobrien execution of the program. 67298944Sobrien 67398944Sobrien If there is an interpreter, it is normal for it to be set to an 67498944Sobrien arbitrary address at the outset. The job of finding it is 67598944Sobrien handled in enable_break(). 67698944Sobrien 67798944Sobrien So, to summarize, relocations are necessary when there is no 67898944Sobrien interpreter section and the start address obtained from the 67998944Sobrien executable is different from the address at which GDB is 68098944Sobrien currently stopped. 68198944Sobrien 68298944Sobrien [ The astute reader will note that we also test to make sure that 68398944Sobrien the executable in question has the DYNAMIC flag set. It is my 68498944Sobrien opinion that this test is unnecessary (undesirable even). It 68598944Sobrien was added to avoid inadvertent relocation of an executable 68698944Sobrien whose e_type member in the ELF header is not ET_DYN. There may 68798944Sobrien be a time in the future when it is desirable to do relocations 68898944Sobrien on other types of files as well in which case this condition 68998944Sobrien should either be removed or modified to accomodate the new file 69098944Sobrien type. (E.g, an ET_EXEC executable which has been built to be 69198944Sobrien position-independent could safely be relocated by the OS if 69298944Sobrien desired. It is true that this violates the ABI, but the ABI 69398944Sobrien has been known to be bent from time to time.) - Kevin, Nov 2000. ] 69498944Sobrien */ 69598944Sobrien 69698944Sobrien interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); 69798944Sobrien if (interp_sect == NULL 69898944Sobrien && (bfd_get_file_flags (exec_bfd) & DYNAMIC) != 0 69998944Sobrien && bfd_get_start_address (exec_bfd) != pc) 70098944Sobrien { 70198944Sobrien struct cleanup *old_chain; 70298944Sobrien struct section_offsets *new_offsets; 70398944Sobrien int i, changed; 70498944Sobrien CORE_ADDR displacement; 70598944Sobrien 70698944Sobrien /* It is necessary to relocate the objfile. The amount to 70798944Sobrien relocate by is simply the address at which we are stopped 70898944Sobrien minus the starting address from the executable. 70998944Sobrien 71098944Sobrien We relocate all of the sections by the same amount. This 71198944Sobrien behavior is mandated by recent editions of the System V ABI. 71298944Sobrien According to the System V Application Binary Interface, 71398944Sobrien Edition 4.1, page 5-5: 71498944Sobrien 71598944Sobrien ... Though the system chooses virtual addresses for 71698944Sobrien individual processes, it maintains the segments' relative 71798944Sobrien positions. Because position-independent code uses relative 71898944Sobrien addressesing between segments, the difference between 71998944Sobrien virtual addresses in memory must match the difference 72098944Sobrien between virtual addresses in the file. The difference 72198944Sobrien between the virtual address of any segment in memory and 72298944Sobrien the corresponding virtual address in the file is thus a 72398944Sobrien single constant value for any one executable or shared 72498944Sobrien object in a given process. This difference is the base 72598944Sobrien address. One use of the base address is to relocate the 72698944Sobrien memory image of the program during dynamic linking. 72798944Sobrien 72898944Sobrien The same language also appears in Edition 4.0 of the System V 72998944Sobrien ABI and is left unspecified in some of the earlier editions. */ 73098944Sobrien 73198944Sobrien displacement = pc - bfd_get_start_address (exec_bfd); 73298944Sobrien changed = 0; 73398944Sobrien 73498944Sobrien new_offsets = xcalloc (symfile_objfile->num_sections, 73598944Sobrien sizeof (struct section_offsets)); 73698944Sobrien old_chain = make_cleanup (xfree, new_offsets); 73798944Sobrien 73898944Sobrien for (i = 0; i < symfile_objfile->num_sections; i++) 73998944Sobrien { 74098944Sobrien if (displacement != ANOFFSET (symfile_objfile->section_offsets, i)) 74198944Sobrien changed = 1; 74298944Sobrien new_offsets->offsets[i] = displacement; 74398944Sobrien } 74498944Sobrien 74598944Sobrien if (changed) 74698944Sobrien objfile_relocate (symfile_objfile, new_offsets); 74798944Sobrien 74898944Sobrien do_cleanups (old_chain); 74998944Sobrien } 75098944Sobrien} 75198944Sobrien 75298944Sobrien/* 75398944Sobrien 75498944Sobrien GLOBAL FUNCTION 75598944Sobrien 75698944Sobrien sunos_solib_create_inferior_hook -- shared library startup support 75798944Sobrien 75898944Sobrien SYNOPSIS 75998944Sobrien 76098944Sobrien void sunos_solib_create_inferior_hook() 76198944Sobrien 76298944Sobrien DESCRIPTION 76398944Sobrien 76498944Sobrien When gdb starts up the inferior, it nurses it along (through the 76598944Sobrien shell) until it is ready to execute it's first instruction. At this 76698944Sobrien point, this function gets called via expansion of the macro 76798944Sobrien SOLIB_CREATE_INFERIOR_HOOK. 76898944Sobrien 76998944Sobrien For SunOS executables, this first instruction is typically the 77098944Sobrien one at "_start", or a similar text label, regardless of whether 77198944Sobrien the executable is statically or dynamically linked. The runtime 77298944Sobrien startup code takes care of dynamically linking in any shared 77398944Sobrien libraries, once gdb allows the inferior to continue. 77498944Sobrien 77598944Sobrien For SVR4 executables, this first instruction is either the first 77698944Sobrien instruction in the dynamic linker (for dynamically linked 77798944Sobrien executables) or the instruction at "start" for statically linked 77898944Sobrien executables. For dynamically linked executables, the system 77998944Sobrien first exec's /lib/libc.so.N, which contains the dynamic linker, 78098944Sobrien and starts it running. The dynamic linker maps in any needed 78198944Sobrien shared libraries, maps in the actual user executable, and then 78298944Sobrien jumps to "start" in the user executable. 78398944Sobrien 78498944Sobrien For both SunOS shared libraries, and SVR4 shared libraries, we 78598944Sobrien can arrange to cooperate with the dynamic linker to discover the 78698944Sobrien names of shared libraries that are dynamically linked, and the 78798944Sobrien base addresses to which they are linked. 78898944Sobrien 78998944Sobrien This function is responsible for discovering those names and 79098944Sobrien addresses, and saving sufficient information about them to allow 79198944Sobrien their symbols to be read at a later time. 79298944Sobrien 79398944Sobrien FIXME 79498944Sobrien 79598944Sobrien Between enable_break() and disable_break(), this code does not 79698944Sobrien properly handle hitting breakpoints which the user might have 79798944Sobrien set in the startup code or in the dynamic linker itself. Proper 79898944Sobrien handling will probably have to wait until the implementation is 79998944Sobrien changed to use the "breakpoint handler function" method. 80098944Sobrien 80198944Sobrien Also, what if child has exit()ed? Must exit loop somehow. 80298944Sobrien */ 80398944Sobrien 80498944Sobrienstatic void 80598944Sobriensunos_solib_create_inferior_hook (void) 80698944Sobrien{ 80798944Sobrien /* Relocate the main executable if necessary. */ 80898944Sobrien sunos_relocate_main_executable (); 80998944Sobrien 81098944Sobrien if ((debug_base = locate_base ()) == 0) 81198944Sobrien { 81298944Sobrien /* Can't find the symbol or the executable is statically linked. */ 81398944Sobrien return; 81498944Sobrien } 81598944Sobrien 81698944Sobrien if (!enable_break ()) 81798944Sobrien { 81898944Sobrien warning ("shared library handler failed to enable breakpoint"); 81998944Sobrien return; 82098944Sobrien } 82198944Sobrien 82298944Sobrien /* SCO and SunOS need the loop below, other systems should be using the 82398944Sobrien special shared library breakpoints and the shared library breakpoint 82498944Sobrien service routine. 82598944Sobrien 82698944Sobrien Now run the target. It will eventually hit the breakpoint, at 82798944Sobrien which point all of the libraries will have been mapped in and we 82898944Sobrien can go groveling around in the dynamic linker structures to find 82998944Sobrien out what we need to know about them. */ 83098944Sobrien 83198944Sobrien clear_proceed_status (); 832130803Smarcel stop_soon = STOP_QUIETLY; 83398944Sobrien stop_signal = TARGET_SIGNAL_0; 83498944Sobrien do 83598944Sobrien { 83698944Sobrien target_resume (pid_to_ptid (-1), 0, stop_signal); 83798944Sobrien wait_for_inferior (); 83898944Sobrien } 83998944Sobrien while (stop_signal != TARGET_SIGNAL_TRAP); 840130803Smarcel stop_soon = NO_STOP_QUIETLY; 84198944Sobrien 84298944Sobrien /* We are now either at the "mapping complete" breakpoint (or somewhere 84398944Sobrien else, a condition we aren't prepared to deal with anyway), so adjust 84498944Sobrien the PC as necessary after a breakpoint, disable the breakpoint, and 84598944Sobrien add any shared libraries that were mapped in. */ 84698944Sobrien 84798944Sobrien if (DECR_PC_AFTER_BREAK) 84898944Sobrien { 84998944Sobrien stop_pc -= DECR_PC_AFTER_BREAK; 85098944Sobrien write_register (PC_REGNUM, stop_pc); 85198944Sobrien } 85298944Sobrien 85398944Sobrien if (!disable_break ()) 85498944Sobrien { 85598944Sobrien warning ("shared library handler failed to disable breakpoint"); 85698944Sobrien } 85798944Sobrien 85898944Sobrien solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add); 85998944Sobrien} 86098944Sobrien 86198944Sobrienstatic void 86298944Sobriensunos_clear_solib (void) 86398944Sobrien{ 86498944Sobrien debug_base = 0; 86598944Sobrien} 86698944Sobrien 86798944Sobrienstatic void 86898944Sobriensunos_free_so (struct so_list *so) 86998944Sobrien{ 87098944Sobrien xfree (so->lm_info->lm); 87198944Sobrien xfree (so->lm_info); 87298944Sobrien} 87398944Sobrien 87498944Sobrienstatic void 87598944Sobriensunos_relocate_section_addresses (struct so_list *so, 87698944Sobrien struct section_table *sec) 87798944Sobrien{ 87898944Sobrien sec->addr += LM_ADDR (so); 87998944Sobrien sec->endaddr += LM_ADDR (so); 88098944Sobrien} 88198944Sobrien 88298944Sobrienstatic struct target_so_ops sunos_so_ops; 88398944Sobrien 88498944Sobrienvoid 88598944Sobrien_initialize_sunos_solib (void) 88698944Sobrien{ 88798944Sobrien sunos_so_ops.relocate_section_addresses = sunos_relocate_section_addresses; 88898944Sobrien sunos_so_ops.free_so = sunos_free_so; 88998944Sobrien sunos_so_ops.clear_solib = sunos_clear_solib; 89098944Sobrien sunos_so_ops.solib_create_inferior_hook = sunos_solib_create_inferior_hook; 89198944Sobrien sunos_so_ops.special_symbol_handling = sunos_special_symbol_handling; 89298944Sobrien sunos_so_ops.current_sos = sunos_current_sos; 89398944Sobrien sunos_so_ops.open_symbol_file_object = open_symbol_file_object; 89498944Sobrien sunos_so_ops.in_dynsym_resolve_code = sunos_in_dynsym_resolve_code; 89598944Sobrien 89698944Sobrien /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ 89798944Sobrien current_target_so_ops = &sunos_so_ops; 89898944Sobrien} 899