1/* Handle SOM shared libraries.
2
3   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011
4   Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21#include "defs.h"
22#include "symtab.h"
23#include "bfd.h"
24#include "symfile.h"
25#include "objfiles.h"
26#include "gdbcore.h"
27#include "target.h"
28#include "inferior.h"
29
30#include "hppa-tdep.h"
31#include "solist.h"
32#include "solib.h"
33#include "solib-som.h"
34
35#include <string.h>
36
37#undef SOLIB_SOM_DBG
38
39/* These ought to be defined in some public interface, but aren't.  They
40   define the meaning of the various bits in the distinguished __dld_flags
41   variable that is declared in every debuggable a.out on HP-UX, and that
42   is shared between the debugger and the dynamic linker.  */
43
44#define DLD_FLAGS_MAPPRIVATE    0x1
45#define DLD_FLAGS_HOOKVALID     0x2
46#define DLD_FLAGS_LISTVALID     0x4
47#define DLD_FLAGS_BOR_ENABLE    0x8
48
49struct lm_info
50  {
51    /* Version of this structure (it is expected to change again in
52       hpux10).  */
53    unsigned char struct_version;
54
55    /* Binding mode for this library.  */
56    unsigned char bind_mode;
57
58    /* Version of this library.  */
59    short library_version;
60
61    /* Start of text address,
62       link-time text location (length of text area),
63       end of text address.  */
64    CORE_ADDR text_addr;
65    CORE_ADDR text_link_addr;
66    CORE_ADDR text_end;
67
68    /* Start of data, start of bss and end of data.  */
69    CORE_ADDR data_start;
70    CORE_ADDR bss_start;
71    CORE_ADDR data_end;
72
73    /* Value of linkage pointer (%r19).  */
74    CORE_ADDR got_value;
75
76    /* Address in target of offset from thread-local register of
77       start of this thread's data.  I.e., the first thread-local
78       variable in this shared library starts at *(tsd_start_addr)
79       from that area pointed to by cr27 (mpsfu_hi).
80
81       We do the indirection as soon as we read it, so from then
82       on it's the offset itself.  */
83    CORE_ADDR tsd_start_addr;
84
85    /* Address of the link map entry in the loader.  */
86    CORE_ADDR lm_addr;
87  };
88
89/* These addresses should be filled in by som_solib_create_inferior_hook.
90   They are also used elsewhere in this module.  */
91
92typedef struct
93  {
94    CORE_ADDR address;
95    struct unwind_table_entry *unwind;
96  }
97addr_and_unwind_t;
98
99/* When adding fields, be sure to clear them in _initialize_som_solib.  */
100static struct
101  {
102    int is_valid;
103    addr_and_unwind_t hook;
104    addr_and_unwind_t hook_stub;
105    addr_and_unwind_t load;
106    addr_and_unwind_t load_stub;
107    addr_and_unwind_t unload;
108    addr_and_unwind_t unload2;
109    addr_and_unwind_t unload_stub;
110  }
111dld_cache;
112
113static void
114som_relocate_section_addresses (struct so_list *so,
115				struct target_section *sec)
116{
117  flagword aflag = bfd_get_section_flags(so->abfd, sec->the_bfd_section);
118
119  if (aflag & SEC_CODE)
120    {
121      sec->addr    += so->lm_info->text_addr - so->lm_info->text_link_addr;
122      sec->endaddr += so->lm_info->text_addr - so->lm_info->text_link_addr;
123    }
124  else if (aflag & SEC_DATA)
125    {
126      sec->addr    += so->lm_info->data_start;
127      sec->endaddr += so->lm_info->data_start;
128    }
129  else
130    ;
131}
132
133
134/* Variable storing HP-UX major release number.
135
136   On non-native system, simply assume that the major release number
137   is 11.  On native systems, hppa-hpux-nat.c initialization code
138   sets this number to the real one on startup.
139
140   We cannot compute this value here, because we need to make a native
141   call to "uname".  We are are not allowed to do that from here, as
142   this file is used for both native and cross debugging.  */
143
144#define DEFAULT_HPUX_MAJOR_RELEASE 11
145int hpux_major_release = DEFAULT_HPUX_MAJOR_RELEASE;
146
147static int
148get_hpux_major_release (void)
149{
150  return hpux_major_release;
151}
152
153/* DL header flag defines.  */
154#define SHLIB_TEXT_PRIVATE_ENABLE 0x4000
155
156/* The DL header is documented in <shl.h>.  We are only interested
157   in the flags field to determine whether the executable wants shared
158   libraries mapped private.  */
159struct {
160    short junk[37];
161    short flags;
162} dl_header;
163
164/* This hook gets called just before the first instruction in the
165   inferior process is executed.
166
167   This is our opportunity to set magic flags in the inferior so
168   that GDB can be notified when a shared library is mapped in and
169   to tell the dynamic linker that a private copy of the library is
170   needed (so GDB can set breakpoints in the library).
171
172   __dld_flags is the location of the magic flags; as of this implementation
173   there are 3 flags of interest:
174
175   bit 0 when set indicates that private copies of the libraries are needed
176   bit 1 when set indicates that the callback hook routine is valid
177   bit 2 when set indicates that the dynamic linker should maintain the
178   __dld_list structure when loading/unloading libraries.
179
180   Note that shared libraries are not mapped in at this time, so we have
181   run the inferior until the libraries are mapped in.  Typically this
182   means running until the "_start" is called.  */
183
184static void
185som_solib_create_inferior_hook (int from_tty)
186{
187  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
188  struct minimal_symbol *msymbol;
189  unsigned int dld_flags, status, have_endo;
190  asection *shlib_info;
191  char buf[4];
192  CORE_ADDR anaddr;
193
194  if (symfile_objfile == NULL)
195    return;
196
197  /* First see if the objfile was dynamically linked.  */
198  shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
199  if (!shlib_info)
200    return;
201
202  /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
203  if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
204    return;
205
206  /* Read the DL header.  */
207  bfd_get_section_contents (symfile_objfile->obfd, shlib_info,
208			    (char *) &dl_header, 0, sizeof (dl_header));
209
210  have_endo = 0;
211  /* Slam the pid of the process into __d_pid.
212
213     We used to warn when this failed, but that warning is only useful
214     on very old HP systems (hpux9 and older).  The warnings are an
215     annoyance to users of modern systems and foul up the testsuite as
216     well.  As a result, the warnings have been disabled.  */
217  msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
218  if (msymbol == NULL)
219    goto keep_going;
220
221  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
222  store_unsigned_integer (buf, 4, byte_order, PIDGET (inferior_ptid));
223  status = target_write_memory (anaddr, buf, 4);
224  if (status != 0)
225    {
226      warning (_("\
227Unable to write __d_pid.\n\
228Suggest linking with /opt/langtools/lib/end.o.\n\
229GDB will be unable to track shl_load/shl_unload calls"));
230      goto keep_going;
231    }
232
233  /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook;
234     This will force the dynamic linker to call __d_trap when significant
235     events occur.
236
237     Note that the above is the pre-HP-UX 9.0 behaviour.  At 9.0 and above,
238     the dld provides an export stub named "__d_trap" as well as the
239     function named "__d_trap" itself, but doesn't provide "_DLD_HOOK".
240     We'll look first for the old flavor and then the new.  */
241
242  msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
243  if (msymbol == NULL)
244    msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
245  if (msymbol == NULL)
246    {
247      warning (_("\
248Unable to find _DLD_HOOK symbol in object file.\n\
249Suggest linking with /opt/langtools/lib/end.o.\n\
250GDB will be unable to track shl_load/shl_unload calls"));
251      goto keep_going;
252    }
253  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
254  dld_cache.hook.address = anaddr;
255
256  /* Grrr, this might not be an export symbol!  We have to find the
257     export stub.  */
258  msymbol = hppa_lookup_stub_minimal_symbol (SYMBOL_LINKAGE_NAME (msymbol),
259                                             EXPORT);
260  if (msymbol != NULL)
261    {
262      anaddr = SYMBOL_VALUE (msymbol);
263      dld_cache.hook_stub.address = anaddr;
264    }
265  store_unsigned_integer (buf, 4, byte_order, anaddr);
266
267  msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
268  if (msymbol == NULL)
269    {
270      warning (_("\
271Unable to find __dld_hook symbol in object file.\n\
272Suggest linking with /opt/langtools/lib/end.o.\n\
273GDB will be unable to track shl_load/shl_unload calls"));
274      goto keep_going;
275    }
276  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
277  status = target_write_memory (anaddr, buf, 4);
278
279  /* Now set a shlib_event breakpoint at __d_trap so we can track
280     significant shared library events.  */
281  msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
282  if (msymbol == NULL)
283    {
284      warning (_("\
285Unable to find __dld_d_trap symbol in object file.\n\
286Suggest linking with /opt/langtools/lib/end.o.\n\
287GDB will be unable to track shl_load/shl_unload calls"));
288      goto keep_going;
289    }
290  create_solib_event_breakpoint (target_gdbarch,
291				 SYMBOL_VALUE_ADDRESS (msymbol));
292
293  /* We have all the support usually found in end.o, so we can track
294     shl_load and shl_unload calls.  */
295  have_endo = 1;
296
297keep_going:
298
299  /* Get the address of __dld_flags, if no such symbol exists, then we can
300     not debug the shared code.  */
301  msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
302  if (msymbol == NULL)
303    {
304      error (_("Unable to find __dld_flags symbol in object file."));
305    }
306
307  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
308
309  /* Read the current contents.  */
310  status = target_read_memory (anaddr, buf, 4);
311  if (status != 0)
312    error (_("Unable to read __dld_flags."));
313  dld_flags = extract_unsigned_integer (buf, 4, byte_order);
314
315  /* If the libraries were not mapped private on HP-UX 11 and later, warn
316     the user.  On HP-UX 10 and earlier, there is no easy way to specify
317     that shared libraries should be privately mapped.  So, we just force
318     private mapping.  */
319  if (get_hpux_major_release () >= 11
320      && (dl_header.flags & SHLIB_TEXT_PRIVATE_ENABLE) == 0
321      && (dld_flags & DLD_FLAGS_MAPPRIVATE) == 0)
322    warning
323      (_("\
324Private mapping of shared library text was not specified\n\
325by the executable; setting a breakpoint in a shared library which\n\
326is not privately mapped will not work.  See the HP-UX 11i v3 chatr\n\
327manpage for methods to privately map shared library text."));
328
329  /* Turn on the flags we care about.  */
330  if (get_hpux_major_release () < 11)
331    dld_flags |= DLD_FLAGS_MAPPRIVATE;
332  if (have_endo)
333    dld_flags |= DLD_FLAGS_HOOKVALID;
334  store_unsigned_integer (buf, 4, byte_order, dld_flags);
335  status = target_write_memory (anaddr, buf, 4);
336  if (status != 0)
337    error (_("Unable to write __dld_flags."));
338
339  /* Now find the address of _start and set a breakpoint there.
340     We still need this code for two reasons:
341
342     * Not all sites have /opt/langtools/lib/end.o, so it's not always
343     possible to track the dynamic linker's events.
344
345     * At this time no events are triggered for shared libraries
346     loaded at startup time (what a crock).  */
347
348  msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
349  if (msymbol == NULL)
350    error (_("Unable to find _start symbol in object file."));
351
352  anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
353
354  /* Make the breakpoint at "_start" a shared library event breakpoint.  */
355  create_solib_event_breakpoint (target_gdbarch, anaddr);
356
357  clear_symtab_users (0);
358}
359
360static void
361som_special_symbol_handling (void)
362{
363}
364
365static void
366som_solib_desire_dynamic_linker_symbols (void)
367{
368  struct objfile *objfile;
369  struct unwind_table_entry *u;
370  struct minimal_symbol *dld_msymbol;
371
372  /* Do we already know the value of these symbols?  If so, then
373     we've no work to do.
374
375     (If you add clauses to this test, be sure to likewise update the
376     test within the loop.)  */
377
378  if (dld_cache.is_valid)
379    return;
380
381  ALL_OBJFILES (objfile)
382  {
383    dld_msymbol = lookup_minimal_symbol ("shl_load", NULL, objfile);
384    if (dld_msymbol != NULL)
385      {
386	dld_cache.load.address = SYMBOL_VALUE (dld_msymbol);
387	dld_cache.load.unwind = find_unwind_entry (dld_cache.load.address);
388      }
389
390    dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_load",
391							  objfile);
392    if (dld_msymbol != NULL)
393      {
394	if (MSYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
395	  {
396	    u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
397	    if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
398	      {
399		dld_cache.load_stub.address = SYMBOL_VALUE (dld_msymbol);
400		dld_cache.load_stub.unwind = u;
401	      }
402	  }
403      }
404
405    dld_msymbol = lookup_minimal_symbol ("shl_unload", NULL, objfile);
406    if (dld_msymbol != NULL)
407      {
408	dld_cache.unload.address = SYMBOL_VALUE (dld_msymbol);
409	dld_cache.unload.unwind = find_unwind_entry (dld_cache.unload.address);
410
411	/* ??rehrauer: I'm not sure exactly what this is, but it appears
412	   that on some HPUX 10.x versions, there's two unwind regions to
413	   cover the body of "shl_unload", the second being 4 bytes past
414	   the end of the first.  This is a large hack to handle that
415	   case, but since I don't seem to have any legitimate way to
416	   look for this thing via the symbol table...  */
417
418	if (dld_cache.unload.unwind != NULL)
419	  {
420	    u = find_unwind_entry (dld_cache.unload.unwind->region_end + 4);
421	    if (u != NULL)
422	      {
423		dld_cache.unload2.address = u->region_start;
424		dld_cache.unload2.unwind = u;
425	      }
426	  }
427      }
428
429    dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_unload",
430							  objfile);
431    if (dld_msymbol != NULL)
432      {
433	if (MSYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
434	  {
435	    u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
436	    if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
437	      {
438		dld_cache.unload_stub.address = SYMBOL_VALUE (dld_msymbol);
439		dld_cache.unload_stub.unwind = u;
440	      }
441	  }
442      }
443
444    /* Did we find everything we were looking for?  If so, stop.  */
445    if ((dld_cache.load.address != 0)
446	&& (dld_cache.load_stub.address != 0)
447	&& (dld_cache.unload.address != 0)
448	&& (dld_cache.unload_stub.address != 0))
449      {
450	dld_cache.is_valid = 1;
451	break;
452      }
453  }
454
455  dld_cache.hook.unwind = find_unwind_entry (dld_cache.hook.address);
456  dld_cache.hook_stub.unwind = find_unwind_entry (dld_cache.hook_stub.address);
457
458  /* We're prepared not to find some of these symbols, which is why
459     this function is a "desire" operation, and not a "require".  */
460}
461
462static int
463som_in_dynsym_resolve_code (CORE_ADDR pc)
464{
465  struct unwind_table_entry *u_pc;
466
467  /* Are we in the dld itself?
468
469     ??rehrauer: Large hack -- We'll assume that any address in a
470     shared text region is the dld's text.  This would obviously
471     fall down if the user attached to a process, whose shlibs
472     weren't mapped to a (writeable) private region.  However, in
473     that case the debugger probably isn't able to set the fundamental
474     breakpoint in the dld callback anyways, so this hack should be
475     safe.  */
476
477  if ((pc & (CORE_ADDR) 0xc0000000) == (CORE_ADDR) 0xc0000000)
478    return 1;
479
480  /* Cache the address of some symbols that are part of the dynamic
481     linker, if not already known.  */
482
483  som_solib_desire_dynamic_linker_symbols ();
484
485  /* Are we in the dld callback?  Or its export stub?  */
486  u_pc = find_unwind_entry (pc);
487  if (u_pc == NULL)
488    return 0;
489
490  if ((u_pc == dld_cache.hook.unwind) || (u_pc == dld_cache.hook_stub.unwind))
491    return 1;
492
493  /* Or the interface of the dld (i.e., "shl_load" or friends)?  */
494  if ((u_pc == dld_cache.load.unwind)
495      || (u_pc == dld_cache.unload.unwind)
496      || (u_pc == dld_cache.unload2.unwind)
497      || (u_pc == dld_cache.load_stub.unwind)
498      || (u_pc == dld_cache.unload_stub.unwind))
499    return 1;
500
501  /* Apparently this address isn't part of the dld's text.  */
502  return 0;
503}
504
505static void
506som_clear_solib (void)
507{
508}
509
510struct dld_list {
511  char name[4];
512  char info[4];
513  char text_addr[4];
514  char text_link_addr[4];
515  char text_end[4];
516  char data_start[4];
517  char bss_start[4];
518  char data_end[4];
519  char got_value[4];
520  char next[4];
521  char tsd_start_addr_ptr[4];
522};
523
524static CORE_ADDR
525link_map_start (void)
526{
527  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
528  struct minimal_symbol *sym;
529  CORE_ADDR addr;
530  char buf[4];
531  unsigned int dld_flags;
532
533  sym = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
534  if (!sym)
535    error (_("Unable to find __dld_flags symbol in object file."));
536  addr = SYMBOL_VALUE_ADDRESS (sym);
537  read_memory (addr, buf, 4);
538  dld_flags = extract_unsigned_integer (buf, 4, byte_order);
539  if ((dld_flags & DLD_FLAGS_LISTVALID) == 0)
540    error (_("__dld_list is not valid according to __dld_flags."));
541
542  sym = lookup_minimal_symbol ("__dld_list", NULL, NULL);
543  if (!sym)
544    {
545      /* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
546         but the data is still available if you know where to look.  */
547      sym = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
548      if (!sym)
549	{
550	  error (_("Unable to find dynamic library list."));
551	  return 0;
552	}
553      addr = SYMBOL_VALUE_ADDRESS (sym) - 8;
554    }
555  else
556    addr = SYMBOL_VALUE_ADDRESS (sym);
557
558  read_memory (addr, buf, 4);
559  addr = extract_unsigned_integer (buf, 4, byte_order);
560  if (addr == 0)
561    return 0;
562
563  read_memory (addr, buf, 4);
564  return extract_unsigned_integer (buf, 4, byte_order);
565}
566
567/* Does this so's name match the main binary?  */
568static int
569match_main (const char *name)
570{
571  return strcmp (name, symfile_objfile->name) == 0;
572}
573
574static struct so_list *
575som_current_sos (void)
576{
577  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
578  CORE_ADDR lm;
579  struct so_list *head = 0;
580  struct so_list **link_ptr = &head;
581
582  for (lm = link_map_start (); lm; )
583    {
584      char *namebuf;
585      CORE_ADDR addr;
586      struct so_list *new;
587      struct cleanup *old_chain;
588      int errcode;
589      struct dld_list dbuf;
590      char tsdbuf[4];
591
592      new = (struct so_list *) xmalloc (sizeof (struct so_list));
593      old_chain = make_cleanup (xfree, new);
594
595      memset (new, 0, sizeof (*new));
596      new->lm_info = xmalloc (sizeof (struct lm_info));
597      make_cleanup (xfree, new->lm_info);
598
599      read_memory (lm, (gdb_byte *)&dbuf, sizeof (struct dld_list));
600
601      addr = extract_unsigned_integer ((gdb_byte *)&dbuf.name,
602				       sizeof (dbuf.name), byte_order);
603      target_read_string (addr, &namebuf, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
604      if (errcode != 0)
605	warning (_("Can't read pathname for load map: %s."),
606		 safe_strerror (errcode));
607      else
608	{
609	  strncpy (new->so_name, namebuf, SO_NAME_MAX_PATH_SIZE - 1);
610	  new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
611	  xfree (namebuf);
612	  strcpy (new->so_original_name, new->so_name);
613	}
614
615	if (new->so_name[0] && !match_main (new->so_name))
616	  {
617	    struct lm_info *lmi = new->lm_info;
618	    unsigned int tmp;
619
620	    lmi->lm_addr = lm;
621
622#define EXTRACT(_fld) \
623  extract_unsigned_integer ((gdb_byte *)&dbuf._fld, \
624			    sizeof (dbuf._fld), byte_order);
625
626	    lmi->text_addr = EXTRACT (text_addr);
627	    tmp = EXTRACT (info);
628	    lmi->library_version = (tmp >> 16) & 0xffff;
629	    lmi->bind_mode = (tmp >> 8) & 0xff;
630	    lmi->struct_version = tmp & 0xff;
631	    lmi->text_link_addr = EXTRACT (text_link_addr);
632	    lmi->text_end = EXTRACT (text_end);
633	    lmi->data_start = EXTRACT (data_start);
634	    lmi->bss_start = EXTRACT (bss_start);
635	    lmi->data_end = EXTRACT (data_end);
636	    lmi->got_value = EXTRACT (got_value);
637	    tmp = EXTRACT (tsd_start_addr_ptr);
638	    read_memory (tmp, tsdbuf, 4);
639	    lmi->tsd_start_addr
640	      = extract_unsigned_integer (tsdbuf, 4, byte_order);
641
642#ifdef SOLIB_SOM_DBG
643	    printf ("\n+ library \"%s\" is described at %s\n", new->so_name,
644	    	    paddress (target_gdbarch, lm));
645	    printf ("  'version' is %d\n", new->lm_info->struct_version);
646	    printf ("  'bind_mode' is %d\n", new->lm_info->bind_mode);
647	    printf ("  'library_version' is %d\n",
648	    	    new->lm_info->library_version);
649	    printf ("  'text_addr' is %s\n",
650	    	    paddress (target_gdbarch, new->lm_info->text_addr));
651	    printf ("  'text_link_addr' is %s\n",
652	    	    paddress (target_gdbarch, new->lm_info->text_link_addr));
653	    printf ("  'text_end' is %s\n",
654	    	    paddress (target_gdbarch, new->lm_info->text_end));
655	    printf ("  'data_start' is %s\n",
656	    	    paddress (target_gdbarch, new->lm_info->data_start));
657	    printf ("  'bss_start' is %s\n",
658	    	    paddress (target_gdbarch, new->lm_info->bss_start));
659	    printf ("  'data_end' is %s\n",
660	    	    paddress (target_gdbarch, new->lm_info->data_end));
661	    printf ("  'got_value' is %s\n",
662	    	    paddress (target_gdbarch, new->lm_info->got_value));
663	    printf ("  'tsd_start_addr' is %s\n",
664	    	    paddress (target_gdbarch, new->lm_info->tsd_start_addr));
665#endif
666
667	    new->addr_low = lmi->text_addr;
668	    new->addr_high = lmi->text_end;
669
670	    /* Link the new object onto the list.  */
671	    new->next = NULL;
672	    *link_ptr = new;
673	    link_ptr = &new->next;
674	  }
675 	else
676	  {
677	    free_so (new);
678	  }
679
680      lm = EXTRACT (next);
681      discard_cleanups (old_chain);
682#undef EXTRACT
683    }
684
685  /* TODO: The original somsolib code has logic to detect and eliminate
686     duplicate entries.  Do we need that?  */
687
688  return head;
689}
690
691static int
692som_open_symbol_file_object (void *from_ttyp)
693{
694  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
695  CORE_ADDR lm, l_name;
696  char *filename;
697  int errcode;
698  int from_tty = *(int *)from_ttyp;
699  char buf[4];
700
701  if (symfile_objfile)
702    if (!query (_("Attempt to reload symbols from process? ")))
703      return 0;
704
705  /* First link map member should be the executable.  */
706  if ((lm = link_map_start ()) == 0)
707    return 0;	/* failed somehow...  */
708
709  /* Read address of name from target memory to GDB.  */
710  read_memory (lm + offsetof (struct dld_list, name), buf, 4);
711
712  /* Convert the address to host format.  Assume that the address is
713     unsigned.  */
714  l_name = extract_unsigned_integer (buf, 4, byte_order);
715
716  if (l_name == 0)
717    return 0;		/* No filename.  */
718
719  /* Now fetch the filename from target memory.  */
720  target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
721
722  if (errcode)
723    {
724      warning (_("failed to read exec filename from attached file: %s"),
725	       safe_strerror (errcode));
726      return 0;
727    }
728
729  make_cleanup (xfree, filename);
730  /* Have a pathname: read the symbol file.  */
731  symbol_file_add_main (filename, from_tty);
732
733  return 1;
734}
735
736static void
737som_free_so (struct so_list *so)
738{
739  xfree (so->lm_info);
740}
741
742static CORE_ADDR
743som_solib_thread_start_addr (struct so_list *so)
744{
745  return so->lm_info->tsd_start_addr;
746}
747
748/* Return the GOT value for the shared library in which ADDR belongs.  If
749   ADDR isn't in any known shared library, return zero.  */
750
751static CORE_ADDR
752som_solib_get_got_by_pc (CORE_ADDR addr)
753{
754  struct so_list *so_list = master_so_list ();
755  CORE_ADDR got_value = 0;
756
757  while (so_list)
758    {
759      if (so_list->lm_info->text_addr <= addr
760	  && so_list->lm_info->text_end > addr)
761	{
762	  got_value = so_list->lm_info->got_value;
763	  break;
764	}
765      so_list = so_list->next;
766    }
767  return got_value;
768}
769
770/* Return the address of the handle of the shared library in which
771   ADDR belongs.  If ADDR isn't in any known shared library, return
772   zero.  */
773/* This function is used in initialize_hp_cxx_exception_support in
774   hppa-hpux-tdep.c.  */
775
776static CORE_ADDR
777som_solib_get_solib_by_pc (CORE_ADDR addr)
778{
779  struct so_list *so_list = master_so_list ();
780
781  while (so_list)
782    {
783      if (so_list->lm_info->text_addr <= addr
784	  && so_list->lm_info->text_end > addr)
785	{
786	  break;
787	}
788      so_list = so_list->next;
789    }
790  if (so_list)
791    return so_list->lm_info->lm_addr;
792  else
793    return 0;
794}
795
796
797static struct target_so_ops som_so_ops;
798
799extern initialize_file_ftype _initialize_som_solib; /* -Wmissing-prototypes */
800
801void
802_initialize_som_solib (void)
803{
804  som_so_ops.relocate_section_addresses = som_relocate_section_addresses;
805  som_so_ops.free_so = som_free_so;
806  som_so_ops.clear_solib = som_clear_solib;
807  som_so_ops.solib_create_inferior_hook = som_solib_create_inferior_hook;
808  som_so_ops.special_symbol_handling = som_special_symbol_handling;
809  som_so_ops.current_sos = som_current_sos;
810  som_so_ops.open_symbol_file_object = som_open_symbol_file_object;
811  som_so_ops.in_dynsym_resolve_code = som_in_dynsym_resolve_code;
812  som_so_ops.bfd_open = solib_bfd_open;
813}
814
815void
816som_solib_select (struct gdbarch *gdbarch)
817{
818  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
819
820  set_solib_ops (gdbarch, &som_so_ops);
821  tdep->solib_thread_start_addr = som_solib_thread_start_addr;
822  tdep->solib_get_got_by_pc = som_solib_get_got_by_pc;
823  tdep->solib_get_solib_by_pc = som_solib_get_solib_by_pc;
824}
825
826/* The rest of these functions are not part of the solib interface; they
827   are used by somread.c or hppa-hpux-tdep.c.  */
828
829int
830som_solib_section_offsets (struct objfile *objfile,
831			   struct section_offsets *offsets)
832{
833  struct so_list *so_list = master_so_list ();
834
835  while (so_list)
836    {
837      /* Oh what a pain!  We need the offsets before so_list->objfile
838         is valid.  The BFDs will never match.  Make a best guess.  */
839      if (strstr (objfile->name, so_list->so_name))
840	{
841	  asection *private_section;
842
843	  /* The text offset is easy.  */
844	  offsets->offsets[SECT_OFF_TEXT (objfile)]
845	    = (so_list->lm_info->text_addr
846	       - so_list->lm_info->text_link_addr);
847	  offsets->offsets[SECT_OFF_RODATA (objfile)]
848	    = ANOFFSET (offsets, SECT_OFF_TEXT (objfile));
849
850	  /* We should look at presumed_dp in the SOM header, but
851	     that's not easily available.  This should be OK though.  */
852	  private_section = bfd_get_section_by_name (objfile->obfd,
853						     "$PRIVATE$");
854	  if (!private_section)
855	    {
856	      warning (_("Unable to find $PRIVATE$ in shared library!"));
857	      offsets->offsets[SECT_OFF_DATA (objfile)] = 0;
858	      offsets->offsets[SECT_OFF_BSS (objfile)] = 0;
859	      return 1;
860	    }
861	  offsets->offsets[SECT_OFF_DATA (objfile)]
862	    = (so_list->lm_info->data_start - private_section->vma);
863	  offsets->offsets[SECT_OFF_BSS (objfile)]
864	    = ANOFFSET (offsets, SECT_OFF_DATA (objfile));
865	  return 1;
866	}
867      so_list = so_list->next;
868    }
869  return 0;
870}
871