198944Sobrien/* Handle OSF/1, Digital UNIX, and Tru64 shared libraries
298944Sobrien   for GDB, the GNU Debugger.
398944Sobrien   Copyright 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
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/* When handling shared libraries, GDB has to find out the pathnames
2498944Sobrien   of all shared libraries that are currently loaded (to read in their
2598944Sobrien   symbols) and where the shared libraries are loaded in memory
2698944Sobrien   (to relocate them properly from their prelinked addresses to the
2798944Sobrien   current load address).
2898944Sobrien
2998944Sobrien   Under OSF/1 there are two possibilities to get at this information:
3098944Sobrien
3198944Sobrien   1) Peek around in the runtime loader structures.
3298944Sobrien   These are not documented, and they are not defined in the system
3398944Sobrien   header files. The definitions below were obtained by experimentation,
3498944Sobrien   but they seem stable enough.
3598944Sobrien
3698944Sobrien   2) Use the libxproc.a library, which contains the equivalent ldr_*
3798944Sobrien   routines.  The library is documented in Tru64 5.x, but as of 5.1, it
3898944Sobrien   only allows a process to examine itself.  On earlier versions, it
3998944Sobrien   may require that the GDB executable be dynamically linked and that
4098944Sobrien   NAT_CLIBS include -lxproc -Wl,-expect_unresolved,ldr_process_context
4198944Sobrien   for GDB and all applications that are using libgdb.
4298944Sobrien
4398944Sobrien   We will use the peeking approach until libxproc.a works for other
4498944Sobrien   processes.  */
4598944Sobrien
4698944Sobrien#include "defs.h"
4798944Sobrien
4898944Sobrien#include <sys/types.h>
4998944Sobrien#include <signal.h>
5098944Sobrien#include "gdb_string.h"
5198944Sobrien
5298944Sobrien#include "bfd.h"
5398944Sobrien#include "symtab.h"
5498944Sobrien#include "symfile.h"
5598944Sobrien#include "objfiles.h"
5698944Sobrien#include "target.h"
5798944Sobrien#include "inferior.h"
5898944Sobrien#include "solist.h"
5998944Sobrien
6098944Sobrien#ifdef USE_LDR_ROUTINES
6198944Sobrien# include <loader.h>
6298944Sobrien#endif
6398944Sobrien
6498944Sobrien#ifndef USE_LDR_ROUTINES
6598944Sobrien/* Definition of runtime loader structures, found by experimentation.  */
6698944Sobrien#define RLD_CONTEXT_ADDRESS	0x3ffc0000000
6798944Sobrien
6898944Sobrien/* Per-module information structure referenced by ldr_context_t.head.  */
6998944Sobrien
7098944Sobrientypedef struct
7198944Sobrien  {
7298944Sobrien    CORE_ADDR next;
7398944Sobrien    CORE_ADDR previous;
7498944Sobrien    CORE_ADDR unknown1;
7598944Sobrien    CORE_ADDR module_name;
7698944Sobrien    CORE_ADDR modinfo_addr;	/* used by next_link_map_member() to detect
7798944Sobrien				   the end of the shared module list */
7898944Sobrien    long module_id;
7998944Sobrien    CORE_ADDR unknown2;
8098944Sobrien    CORE_ADDR unknown3;
8198944Sobrien    long region_count;
8298944Sobrien    CORE_ADDR regioninfo_addr;
8398944Sobrien  }
8498944Sobrienldr_module_info_t;
8598944Sobrien
8698944Sobrien/* Per-region structure referenced by ldr_module_info_t.regioninfo_addr.  */
8798944Sobrien
8898944Sobrientypedef struct
8998944Sobrien  {
9098944Sobrien    long unknown1;
9198944Sobrien    CORE_ADDR regionname_addr;
9298944Sobrien    long protection;
9398944Sobrien    CORE_ADDR vaddr;
9498944Sobrien    CORE_ADDR mapaddr;
9598944Sobrien    long size;
9698944Sobrien    long unknown2[5];
9798944Sobrien  }
9898944Sobrienldr_region_info_t;
9998944Sobrien
10098944Sobrien/* Structure at RLD_CONTEXT_ADDRESS specifying the start and finish addresses
10198944Sobrien   of the shared module list.  */
10298944Sobrien
10398944Sobrientypedef struct
10498944Sobrien  {
10598944Sobrien    CORE_ADDR unknown1;
10698944Sobrien    CORE_ADDR unknown2;
10798944Sobrien    CORE_ADDR head;
10898944Sobrien    CORE_ADDR tail;
10998944Sobrien  }
11098944Sobrienldr_context_t;
11198944Sobrien#endif   /* !USE_LDR_ROUTINES */
11298944Sobrien
11398944Sobrien/* Per-section information, stored in struct lm_info.secs.  */
11498944Sobrien
11598944Sobrienstruct lm_sec
11698944Sobrien  {
11798944Sobrien    CORE_ADDR offset;		/* difference between default and actual
11898944Sobrien				   virtual addresses of section .name */
11998944Sobrien    CORE_ADDR nameaddr;		/* address in inferior of section name */
12098944Sobrien    const char *name;		/* name of section, null if not fetched */
12198944Sobrien  };
12298944Sobrien
12398944Sobrien/* Per-module information, stored in struct so_list.lm_info.  */
12498944Sobrien
12598944Sobrienstruct lm_info
12698944Sobrien  {
12798944Sobrien    int isloader;		/* whether the module is /sbin/loader */
12898944Sobrien    int nsecs;			/* length of .secs */
12998944Sobrien    struct lm_sec secs[1];	/* variable-length array of sections, sorted
13098944Sobrien				   by name */
13198944Sobrien  };
13298944Sobrien
13398944Sobrien/* Context for iterating through the inferior's shared module list.  */
13498944Sobrien
13598944Sobrienstruct read_map_ctxt
13698944Sobrien  {
13798944Sobrien#ifdef USE_LDR_ROUTINES
13898944Sobrien    ldr_process_t proc;
13998944Sobrien    ldr_module_t next;
14098944Sobrien#else
14198944Sobrien    CORE_ADDR next;		/* next element in module list */
14298944Sobrien    CORE_ADDR tail;		/* last element in module list */
14398944Sobrien#endif
14498944Sobrien  };
14598944Sobrien
14698944Sobrien/* Forward declaration for this module's autoinit function.  */
14798944Sobrien
14898944Sobrienextern void _initialize_osf_solib (void);
14998944Sobrien
15098944Sobrien#ifdef USE_LDR_ROUTINES
15198944Sobrien# if 0
15298944Sobrien/* This routine is intended to be called by ldr_* routines to read memory from
15398944Sobrien   the current target.  Usage:
15498944Sobrien
15598944Sobrien     ldr_process = ldr_core_process ();
15698944Sobrien     ldr_set_core_reader (ldr_read_memory);
15798944Sobrien     ldr_xdetach (ldr_process);
15898944Sobrien     ldr_xattach (ldr_process);
15998944Sobrien
16098944Sobrien   ldr_core_process() and ldr_read_memory() are neither documented nor
16198944Sobrien   declared in system header files.  They work with OSF/1 2.x, and they might
16298944Sobrien   work with later versions as well.  */
16398944Sobrien
16498944Sobrienstatic int
16598944Sobrienldr_read_memory (CORE_ADDR memaddr, char *myaddr, int len, int readstring)
16698944Sobrien{
16798944Sobrien  int result;
16898944Sobrien  char *buffer;
16998944Sobrien
17098944Sobrien  if (readstring)
17198944Sobrien    {
17298944Sobrien      target_read_string (memaddr, &buffer, len, &result);
17398944Sobrien      if (result == 0)
17498944Sobrien	strcpy (myaddr, buffer);
17598944Sobrien      xfree (buffer);
17698944Sobrien    }
17798944Sobrien  else
17898944Sobrien    result = target_read_memory (memaddr, myaddr, len);
17998944Sobrien
18098944Sobrien  if (result != 0)
18198944Sobrien    result = -result;
18298944Sobrien  return result;
18398944Sobrien}
18498944Sobrien# endif   /* 0 */
18598944Sobrien#endif   /* USE_LDR_ROUTINES */
18698944Sobrien
18798944Sobrien/* Comparison for qsort() and bsearch(): return -1, 0, or 1 according to
18898944Sobrien   whether lm_sec *P1's name is lexically less than, equal to, or greater
18998944Sobrien   than that of *P2.  */
19098944Sobrien
19198944Sobrienstatic int
19298944Sobrienlm_sec_cmp (const void *p1, const void *p2)
19398944Sobrien{
19498944Sobrien  const struct lm_sec *lms1 = p1, *lms2 = p2;
19598944Sobrien  return strcmp (lms1->name, lms2->name);
19698944Sobrien}
19798944Sobrien
19898944Sobrien/* Sort LMI->secs so that osf_relocate_section_addresses() can binary-search
19998944Sobrien   it.  */
20098944Sobrien
20198944Sobrienstatic void
20298944Sobrienlm_secs_sort (struct lm_info *lmi)
20398944Sobrien{
20498944Sobrien  qsort (lmi->secs, lmi->nsecs, sizeof *lmi->secs, lm_sec_cmp);
20598944Sobrien}
20698944Sobrien
20798944Sobrien/* Populate name fields of LMI->secs.  */
20898944Sobrien
20998944Sobrienstatic void
21098944Sobrienfetch_sec_names (struct lm_info *lmi)
21198944Sobrien{
21298944Sobrien#ifndef USE_LDR_ROUTINES
21398944Sobrien  int i, errcode;
21498944Sobrien  struct lm_sec *lms;
21598944Sobrien  char *name;
21698944Sobrien
21798944Sobrien  for (i = 0; i < lmi->nsecs; i++)
21898944Sobrien    {
21998944Sobrien      lms = lmi->secs + i;
22098944Sobrien      target_read_string (lms->nameaddr, &name, PATH_MAX, &errcode);
22198944Sobrien      if (errcode != 0)
22298944Sobrien	{
22398944Sobrien	  warning ("unable to read shared sec name at 0x%lx", lms->nameaddr);
22498944Sobrien	  name = xstrdup ("");
22598944Sobrien	}
22698944Sobrien      lms->name = name;
22798944Sobrien    }
22898944Sobrien  lm_secs_sort (lmi);
22998944Sobrien#endif
23098944Sobrien}
23198944Sobrien
23298944Sobrien/* target_so_ops callback.  Adjust SEC's addresses after it's been mapped into
23398944Sobrien   the process.  */
23498944Sobrien
23598944Sobrienstatic void
23698944Sobrienosf_relocate_section_addresses (struct so_list *so,
23798944Sobrien				struct section_table *sec)
23898944Sobrien{
23998944Sobrien  struct lm_info *lmi;
24098944Sobrien  struct lm_sec lms_key, *lms;
24198944Sobrien
24298944Sobrien  /* Fetch SO's section names if we haven't done so already.  */
24398944Sobrien  lmi = so->lm_info;
24498944Sobrien  if (lmi->nsecs && !lmi->secs[0].name)
24598944Sobrien    fetch_sec_names (lmi);
24698944Sobrien
24798944Sobrien  /* Binary-search for offset information corresponding to SEC.  */
24898944Sobrien  lms_key.name = sec->the_bfd_section->name;
24998944Sobrien  lms = bsearch (&lms_key, lmi->secs, lmi->nsecs, sizeof *lms, lm_sec_cmp);
25098944Sobrien  if (lms)
25198944Sobrien    {
25298944Sobrien      sec->addr += lms->offset;
25398944Sobrien      sec->endaddr += lms->offset;
25498944Sobrien    }
25598944Sobrien}
25698944Sobrien
25798944Sobrien/* target_so_ops callback.  Free parts of SO allocated by this file.  */
25898944Sobrien
25998944Sobrienstatic void
26098944Sobrienosf_free_so (struct so_list *so)
26198944Sobrien{
26298944Sobrien  int i;
26398944Sobrien  const char *name;
26498944Sobrien
26598944Sobrien  for (i = 0; i < so->lm_info->nsecs; i++)
26698944Sobrien    {
26798944Sobrien      name = so->lm_info->secs[i].name;
26898944Sobrien      if (name)
26998944Sobrien	xfree ((void *) name);
27098944Sobrien    }
27198944Sobrien  xfree (so->lm_info);
27298944Sobrien}
27398944Sobrien
27498944Sobrien/* target_so_ops callback.  Discard information accumulated by this file and
27598944Sobrien   not freed by osf_free_so().  */
27698944Sobrien
27798944Sobrienstatic void
27898944Sobrienosf_clear_solib (void)
27998944Sobrien{
28098944Sobrien  return;
28198944Sobrien}
28298944Sobrien
28398944Sobrien/* target_so_ops callback.  Prepare to handle shared libraries after the
28498944Sobrien   inferior process has been created but before it's executed any
28598944Sobrien   instructions.
28698944Sobrien
28798944Sobrien   For a statically bound executable, the inferior's first instruction is the
28898944Sobrien   one at "_start", or a similar text label. No further processing is needed
28998944Sobrien   in that case.
29098944Sobrien
29198944Sobrien   For a dynamically bound executable, this first instruction is somewhere
29298944Sobrien   in the rld, and the actual user executable is not yet mapped in.
29398944Sobrien   We continue the inferior again, rld then maps in the actual user
29498944Sobrien   executable and any needed shared libraries and then sends
29598944Sobrien   itself a SIGTRAP.
29698944Sobrien
29798944Sobrien   At that point we discover the names of all shared libraries and
29898944Sobrien   read their symbols in.
29998944Sobrien
30098944Sobrien   FIXME
30198944Sobrien
30298944Sobrien   This code does not properly handle hitting breakpoints which the
30398944Sobrien   user might have set in the rld itself.  Proper handling would have
30498944Sobrien   to check if the SIGTRAP happened due to a kill call.
30598944Sobrien
30698944Sobrien   Also, what if child has exit()ed?  Must exit loop somehow.  */
30798944Sobrien
30898944Sobrienstatic void
30998944Sobrienosf_solib_create_inferior_hook (void)
31098944Sobrien{
31198944Sobrien  /* Nothing to do for statically bound executables.  */
31298944Sobrien
31398944Sobrien  if (symfile_objfile == NULL
31498944Sobrien      || symfile_objfile->obfd == NULL
31598944Sobrien      || ((bfd_get_file_flags (symfile_objfile->obfd) & DYNAMIC) == 0))
31698944Sobrien    return;
31798944Sobrien
31898944Sobrien  /* Now run the target.  It will eventually get a SIGTRAP, at
31998944Sobrien     which point all of the libraries will have been mapped in and we
32098944Sobrien     can go groveling around in the rld structures to find
32198944Sobrien     out what we need to know about them. */
32298944Sobrien
32398944Sobrien  clear_proceed_status ();
324130803Smarcel  stop_soon = STOP_QUIETLY;
32598944Sobrien  stop_signal = TARGET_SIGNAL_0;
32698944Sobrien  do
32798944Sobrien    {
32898944Sobrien      target_resume (minus_one_ptid, 0, stop_signal);
32998944Sobrien      wait_for_inferior ();
33098944Sobrien    }
33198944Sobrien  while (stop_signal != TARGET_SIGNAL_TRAP);
33298944Sobrien
33398944Sobrien  /*  solib_add will call reinit_frame_cache.
33498944Sobrien     But we are stopped in the runtime loader and we do not have symbols
33598944Sobrien     for the runtime loader. So heuristic_proc_start will be called
33698944Sobrien     and will put out an annoying warning.
337130803Smarcel     Delaying the resetting of stop_soon until after symbol loading
33898944Sobrien     suppresses the warning.  */
33998944Sobrien  solib_add ((char *) 0, 0, (struct target_ops *) 0, auto_solib_add);
340130803Smarcel  stop_soon = NO_STOP_QUIETLY;
34198944Sobrien
34298944Sobrien  /* Enable breakpoints disabled (unnecessarily) by clear_solib().  */
34398944Sobrien  re_enable_breakpoints_in_shlibs ();
34498944Sobrien}
34598944Sobrien
34698944Sobrien/* target_so_ops callback.  Do additional symbol handling, lookup, etc. after
34798944Sobrien   symbols for a shared object have been loaded.  */
34898944Sobrien
34998944Sobrienstatic void
35098944Sobrienosf_special_symbol_handling (void)
35198944Sobrien{
35298944Sobrien  return;
35398944Sobrien}
35498944Sobrien
35598944Sobrien/* Initialize CTXT in preparation for iterating through the inferior's module
35698944Sobrien   list using read_map().  Return success.  */
35798944Sobrien
35898944Sobrienstatic int
35998944Sobrienopen_map (struct read_map_ctxt *ctxt)
36098944Sobrien{
36198944Sobrien#ifdef USE_LDR_ROUTINES
362130803Smarcel  /* Note: As originally written, ldr_my_process() was used to obtain
363130803Smarcel     the value for ctxt->proc.  This is incorrect, however, since
364130803Smarcel     ldr_my_process() retrieves the "unique identifier" associated
365130803Smarcel     with the current process (i.e. GDB) and not the one being
366130803Smarcel     debugged.  Presumably, the pid of the process being debugged is
367130803Smarcel     compatible with the "unique identifier" used by the ldr_
368130803Smarcel     routines, so we use that.  */
369130803Smarcel  ctxt->proc = ptid_get_pid (inferior_ptid);
37098944Sobrien  if (ldr_xattach (ctxt->proc) != 0)
37198944Sobrien    return 0;
37298944Sobrien  ctxt->next = LDR_NULL_MODULE;
37398944Sobrien#else
37498944Sobrien  CORE_ADDR ldr_context_addr, prev, next;
37598944Sobrien  ldr_context_t ldr_context;
37698944Sobrien
37798944Sobrien  if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
37898944Sobrien			  (char *) &ldr_context_addr,
37998944Sobrien			  sizeof (CORE_ADDR)) != 0)
38098944Sobrien    return 0;
38198944Sobrien  if (target_read_memory (ldr_context_addr,
38298944Sobrien			  (char *) &ldr_context,
38398944Sobrien			  sizeof (ldr_context_t)) != 0)
38498944Sobrien    return 0;
38598944Sobrien  ctxt->next = ldr_context.head;
38698944Sobrien  ctxt->tail = ldr_context.tail;
38798944Sobrien#endif
38898944Sobrien  return 1;
38998944Sobrien}
39098944Sobrien
39198944Sobrien/* Initialize SO to have module NAME, /sbin/loader indicator ISLOADR, and
39298944Sobrien   space for NSECS sections.  */
39398944Sobrien
39498944Sobrienstatic void
39598944Sobrieninit_so (struct so_list *so, char *name, int isloader, int nsecs)
39698944Sobrien{
39798944Sobrien  int namelen, i;
39898944Sobrien
39998944Sobrien  /* solib.c requires various fields to be initialized to 0.  */
40098944Sobrien  memset (so, 0, sizeof *so);
40198944Sobrien
40298944Sobrien  /* Copy the name.  */
40398944Sobrien  namelen = strlen (name);
40498944Sobrien  if (namelen >= SO_NAME_MAX_PATH_SIZE)
40598944Sobrien    namelen = SO_NAME_MAX_PATH_SIZE - 1;
40698944Sobrien
40798944Sobrien  memcpy (so->so_original_name, name, namelen);
40898944Sobrien  so->so_original_name[namelen] = '\0';
40998944Sobrien  memcpy (so->so_name, so->so_original_name, namelen + 1);
41098944Sobrien
41198944Sobrien  /* Allocate section space.  */
41298944Sobrien  so->lm_info = xmalloc ((unsigned) &(((struct lm_info *)0)->secs) +
41398944Sobrien			 nsecs * sizeof *so->lm_info);
41498944Sobrien  so->lm_info->isloader = isloader;
41598944Sobrien  so->lm_info->nsecs = nsecs;
41698944Sobrien  for (i = 0; i < nsecs; i++)
41798944Sobrien    so->lm_info->secs[i].name = NULL;
41898944Sobrien}
41998944Sobrien
42098944Sobrien/* Initialize SO's section SECIDX with name address NAMEADDR, name string
42198944Sobrien   NAME, default virtual address VADDR, and actual virtual address
42298944Sobrien   MAPADDR.  */
42398944Sobrien
42498944Sobrienstatic void
42598944Sobrieninit_sec (struct so_list *so, int secidx, CORE_ADDR nameaddr,
42698944Sobrien	  const char *name, CORE_ADDR vaddr, CORE_ADDR mapaddr)
42798944Sobrien{
42898944Sobrien  struct lm_sec *lms;
42998944Sobrien
43098944Sobrien  lms = so->lm_info->secs + secidx;
43198944Sobrien  lms->nameaddr = nameaddr;
43298944Sobrien  lms->name = name;
43398944Sobrien  lms->offset = mapaddr - vaddr;
43498944Sobrien}
43598944Sobrien
43698944Sobrien/* If there are more elements starting at CTXT in inferior's module list,
43798944Sobrien   store the next element in SO, advance CTXT to the next element, and return
43898944Sobrien   1, else return 0.  */
43998944Sobrien
44098944Sobrienstatic int
44198944Sobrienread_map (struct read_map_ctxt *ctxt, struct so_list *so)
44298944Sobrien{
44398944Sobrien  ldr_module_info_t minf;
44498944Sobrien  ldr_region_info_t rinf;
44598944Sobrien
44698944Sobrien#ifdef USE_LDR_ROUTINES
44798944Sobrien  size_t size;
44898944Sobrien  ldr_region_t i;
44998944Sobrien
45098944Sobrien  /* Retrieve the next element.  */
45198944Sobrien  if (ldr_next_module (ctxt->proc, &ctxt->next) != 0)
45298944Sobrien    return 0;
45398944Sobrien  if (ctxt->next == LDR_NULL_MODULE)
45498944Sobrien    return 0;
45598944Sobrien  if (ldr_inq_module (ctxt->proc, ctxt->next, &minf, sizeof minf, &size) != 0)
45698944Sobrien    return 0;
45798944Sobrien
45898944Sobrien  /* Initialize the module name and section count.  */
45998944Sobrien  init_so (so, minf.lmi_name, 0, minf.lmi_nregion);
46098944Sobrien
46198944Sobrien  /* Retrieve section names and offsets.  */
46298944Sobrien  for (i = 0; i < minf.lmi_nregion; i++)
46398944Sobrien    {
46498944Sobrien      if (ldr_inq_region (ctxt->proc, ctxt->next, i, &rinf,
46598944Sobrien			  sizeof rinf, &size) != 0)
46698944Sobrien	goto err;
46798944Sobrien      init_sec (so, (int) i, 0, xstrdup (rinf.lri_name),
46898944Sobrien		(CORE_ADDR) rinf.lri_vaddr, (CORE_ADDR) rinf.lri_mapaddr);
46998944Sobrien    }
47098944Sobrien  lm_secs_sort (so->lm_info);
47198944Sobrien#else
47298944Sobrien  char *name;
47398944Sobrien  int errcode, i;
47498944Sobrien
47598944Sobrien  /* Retrieve the next element.  */
47698944Sobrien  if (!ctxt->next)
47798944Sobrien    return 0;
47898944Sobrien  if (target_read_memory (ctxt->next, (char *) &minf, sizeof minf) != 0)
47998944Sobrien    return 0;
48098944Sobrien  if (ctxt->next == ctxt->tail)
48198944Sobrien    ctxt->next = 0;
48298944Sobrien  else
48398944Sobrien    ctxt->next = minf.next;
48498944Sobrien
48598944Sobrien  /* Initialize the module name and section count.  */
48698944Sobrien  target_read_string (minf.module_name, &name, PATH_MAX, &errcode);
48798944Sobrien  if (errcode != 0)
48898944Sobrien    return 0;
48998944Sobrien  init_so (so, name, !minf.modinfo_addr, minf.region_count);
49098944Sobrien  xfree (name);
49198944Sobrien
49298944Sobrien  /* Retrieve section names and offsets.  */
49398944Sobrien  for (i = 0; i < minf.region_count; i++)
49498944Sobrien    {
49598944Sobrien      if (target_read_memory (minf.regioninfo_addr + i * sizeof rinf,
49698944Sobrien			      (char *) &rinf, sizeof rinf) != 0)
49798944Sobrien	goto err;
49898944Sobrien      init_sec (so, i, rinf.regionname_addr, NULL, rinf.vaddr, rinf.mapaddr);
49998944Sobrien    }
50098944Sobrien#endif   /* !USE_LDR_ROUTINES */
50198944Sobrien  return 1;
50298944Sobrien
50398944Sobrien err:
50498944Sobrien  osf_free_so (so);
50598944Sobrien  return 0;
50698944Sobrien}
50798944Sobrien
50898944Sobrien/* Free resources allocated by open_map (CTXT).  */
50998944Sobrien
51098944Sobrienstatic void
51198944Sobrienclose_map (struct read_map_ctxt *ctxt)
51298944Sobrien{
51398944Sobrien#ifdef USE_LDR_ROUTINES
51498944Sobrien  ldr_xdetach (ctxt->proc);
51598944Sobrien#endif
51698944Sobrien}
51798944Sobrien
51898944Sobrien/* target_so_ops callback.  Return a list of shared objects currently loaded
51998944Sobrien   in the inferior.  */
52098944Sobrien
52198944Sobrienstatic struct so_list *
52298944Sobrienosf_current_sos (void)
52398944Sobrien{
52498944Sobrien  struct so_list *head = NULL, *tail, *newtail, so;
52598944Sobrien  struct read_map_ctxt ctxt;
52698944Sobrien  int skipped_main;
52798944Sobrien
52898944Sobrien  if (!open_map (&ctxt))
52998944Sobrien    return NULL;
53098944Sobrien
53198944Sobrien  /* Read subsequent elements.  */
53298944Sobrien  for (skipped_main = 0;;)
53398944Sobrien    {
53498944Sobrien      if (!read_map (&ctxt, &so))
53598944Sobrien	break;
53698944Sobrien
53798944Sobrien      /* Skip the main program module, which is first in the list after
53898944Sobrien         /sbin/loader.  */
53998944Sobrien      if (!so.lm_info->isloader && !skipped_main)
54098944Sobrien	{
54198944Sobrien	  osf_free_so (&so);
54298944Sobrien	  skipped_main = 1;
54398944Sobrien	  continue;
54498944Sobrien	}
54598944Sobrien
54698944Sobrien      newtail = xmalloc (sizeof *newtail);
54798944Sobrien      if (!head)
54898944Sobrien	head = newtail;
54998944Sobrien      else
55098944Sobrien	tail->next = newtail;
55198944Sobrien      tail = newtail;
55298944Sobrien
55398944Sobrien      memcpy (tail, &so, sizeof so);
55498944Sobrien      tail->next = NULL;
55598944Sobrien    }
55698944Sobrien
55798944Sobrien done:
55898944Sobrien  close_map (&ctxt);
55998944Sobrien  return head;
56098944Sobrien}
56198944Sobrien
56298944Sobrien/* target_so_ops callback.  Attempt to locate and open the main symbol
56398944Sobrien   file.  */
56498944Sobrien
56598944Sobrienstatic int
56698944Sobrienosf_open_symbol_file_object (void *from_ttyp)
56798944Sobrien{
56898944Sobrien  struct read_map_ctxt ctxt;
56998944Sobrien  struct so_list so;
57098944Sobrien  int found;
57198944Sobrien
57298944Sobrien  if (symfile_objfile)
57398944Sobrien    if (!query ("Attempt to reload symbols from process? "))
57498944Sobrien      return 0;
57598944Sobrien
57698944Sobrien  /* The first module after /sbin/loader is the main program.  */
57798944Sobrien  if (!open_map (&ctxt))
57898944Sobrien    return 0;
57998944Sobrien  for (found = 0; !found;)
58098944Sobrien    {
58198944Sobrien      if (!read_map (&ctxt, &so))
58298944Sobrien	break;
58398944Sobrien      found = !so.lm_info->isloader;
58498944Sobrien      osf_free_so (&so);
58598944Sobrien    }
58698944Sobrien  close_map (&ctxt);
58798944Sobrien
58898944Sobrien  if (found)
58998944Sobrien    symbol_file_add_main (so.so_name, *(int *) from_ttyp);
59098944Sobrien  return found;
59198944Sobrien}
59298944Sobrien
59398944Sobrien/* target_so_ops callback.  Return whether PC is in the dynamic linker.  */
59498944Sobrien
59598944Sobrienstatic int
59698944Sobrienosf_in_dynsym_resolve_code (CORE_ADDR pc)
59798944Sobrien{
59898944Sobrien  /* This function currently always return False. This is a temporary
59998944Sobrien     solution which only consequence is to introduce a minor incovenience
60098944Sobrien     for the user: When stepping inside a subprogram located in a shared
60198944Sobrien     library, gdb might stop inside the dynamic loader code instead of
60298944Sobrien     inside the subprogram itself. See the explanations in infrun.c about
60398944Sobrien     the IN_SOLIB_DYNSYM_RESOLVE_CODE macro for more details. */
60498944Sobrien  return 0;
60598944Sobrien}
60698944Sobrien
60798944Sobrienstatic struct target_so_ops osf_so_ops;
60898944Sobrien
60998944Sobrienvoid
61098944Sobrien_initialize_osf_solib (void)
61198944Sobrien{
61298944Sobrien  osf_so_ops.relocate_section_addresses = osf_relocate_section_addresses;
61398944Sobrien  osf_so_ops.free_so = osf_free_so;
61498944Sobrien  osf_so_ops.clear_solib = osf_clear_solib;
61598944Sobrien  osf_so_ops.solib_create_inferior_hook = osf_solib_create_inferior_hook;
61698944Sobrien  osf_so_ops.special_symbol_handling = osf_special_symbol_handling;
61798944Sobrien  osf_so_ops.current_sos = osf_current_sos;
61898944Sobrien  osf_so_ops.open_symbol_file_object = osf_open_symbol_file_object;
61998944Sobrien  osf_so_ops.in_dynsym_resolve_code = osf_in_dynsym_resolve_code;
62098944Sobrien
62198944Sobrien  /* FIXME: Don't do this here.  *_gdbarch_init() should set so_ops. */
62298944Sobrien  current_target_so_ops = &osf_so_ops;
62398944Sobrien}
624