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