OSDN Git Service

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