* mn10300.igen (OP_F0F4): Need to load contents of register AN0
[platform/upstream/binutils.git] / gdb / somsolib.c
1 /* Handle HP SOM shared libraries for GDB, the GNU Debugger.
2    Copyright 1993, 1996 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 Written by the Center for Software Science at the Univerity of Utah
21 and by Cygnus Support.  */
22
23
24 #include "defs.h"
25
26 #include "frame.h"
27 #include "bfd.h"
28 #include "som.h"
29 #include "libhppa.h"
30 #include "gdbcore.h"
31 #include "symtab.h"
32 #include "breakpoint.h"
33 #include "symfile.h"
34 #include "objfiles.h"
35 #include "inferior.h"
36 #include "gdb-stabs.h"
37 #include "gdb_stat.h"
38 #include "gdbcmd.h"
39 #include "language.h"
40
41 /* TODO:
42
43    * Most of this code should work for hp300 shared libraries.  Does
44    anyone care enough to weed out any SOM-isms.
45
46    * Support for hpux8 dynamic linker.  */
47
48 /* The basic structure which describes a dynamically loaded object.  This
49    data structure is private to the dynamic linker and isn't found in
50    any HPUX include file.  */
51
52 struct som_solib_mapped_entry
53 {
54   /* The name of the library.  */
55   char *name;
56
57   /* Version of this structure (it is expected to change again in hpux10).  */
58   unsigned char struct_version;
59
60   /* Binding mode for this library.  */
61   unsigned char bind_mode;
62
63   /* Version of this library.  */
64   short library_version;
65
66   /* Start of text address, link-time text location, end of text address.  */
67   CORE_ADDR text_addr;
68   CORE_ADDR text_link_addr;
69   CORE_ADDR text_end;
70
71   /* Start of data, start of bss and end of data.  */
72   CORE_ADDR data_start;
73   CORE_ADDR bss_start;
74   CORE_ADDR data_end;
75
76   /* Value of linkage pointer (%r19).  */
77   CORE_ADDR got_value;
78
79   /* Next entry.  */
80   struct som_solib_mapped_entry *next;
81
82   /* There are other fields, but I don't have information as to what is
83      contained in them.  */
84 };
85
86 /* A structure to keep track of all the known shared objects.  */
87 struct so_list
88 {
89   struct som_solib_mapped_entry som_solib;
90   struct objfile *objfile;
91   bfd *abfd;
92   struct section_table *sections;
93   struct section_table *sections_end;
94   struct so_list *next;
95 };
96
97 static struct so_list *so_list_head;
98
99 static void som_sharedlibrary_info_command PARAMS ((char *, int));
100
101 static void som_solib_sharedlibrary_command PARAMS ((char *, int));
102
103 /* Add symbols from shared libraries into the symtab list.  */
104
105 void
106 som_solib_add (arg_string, from_tty, target)
107      char *arg_string;
108      int from_tty;
109      struct target_ops *target;
110 {
111   struct minimal_symbol *msymbol;
112   struct so_list *so_list_tail;
113   CORE_ADDR addr;
114   asection *shlib_info;
115   int status;
116   unsigned int dld_flags;
117   char buf[4], *re_err;
118
119   /* First validate our arguments.  */
120   if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
121     {
122       error ("Invalid regexp: %s", re_err);
123     }
124
125   /* If we're debugging a core file, or have attached to a running
126      process, then som_solib_create_inferior_hook will not have been
127      called.
128
129      We need to first determine if we're dealing with a dynamically
130      linked executable.  If not, then return without an error or warning.
131
132      We also need to examine __dld_flags to determine if the shared library
133      list is valid and to determine if the libraries have been privately
134      mapped.  */
135   if (symfile_objfile == NULL)
136     return;
137
138   /* First see if the objfile was dynamically linked.  */
139   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
140   if (!shlib_info)
141     return;
142
143   /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
144   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
145     return;
146
147   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
148   if (msymbol == NULL)
149     {
150       error ("Unable to find __dld_flags symbol in object file.\n");
151       return;
152     }
153
154   addr = SYMBOL_VALUE_ADDRESS (msymbol);
155   /* Read the current contents.  */
156   status = target_read_memory (addr, buf, 4);
157   if (status != 0)
158     {
159       error ("Unable to read __dld_flags\n");
160       return;
161     }
162   dld_flags = extract_unsigned_integer (buf, 4);
163
164   /* __dld_list may not be valid.  If it's not valid tell the user.  */
165   if ((dld_flags & 4) == 0)
166     {
167       error ("__dld_list is not valid according to __dld_flags.\n");
168       return;
169     }
170
171   /* If the libraries were not mapped private, warn the user.  */
172   if ((dld_flags & 1) == 0)
173     warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
174
175   msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
176   if (!msymbol)
177     {
178       /* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
179          but the data is still available if you know where to look.  */
180       msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
181       if (!msymbol)
182         {
183           error ("Unable to find dynamic library list.\n");
184           return;
185         }
186       addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
187     }
188   else
189     addr = SYMBOL_VALUE_ADDRESS (msymbol);
190
191   status = target_read_memory (addr, buf, 4);
192   if (status != 0)
193     {
194       error ("Unable to find dynamic library list.\n");
195       return;
196     }
197
198   addr = extract_unsigned_integer (buf, 4);
199
200   /* If addr is zero, then we're using an old dynamic loader which
201      doesn't maintain __dld_list.  We'll have to use a completely
202      different approach to get shared library information.  */
203   if (addr == 0)
204     goto old_dld;
205
206   /* Using the information in __dld_list is the preferred method
207      to get at shared library information.  It doesn't depend on
208      any functions in /usr/lib/end.o and has a chance of working
209      with hpux10 when it is released.  */
210   status = target_read_memory (addr, buf, 4);
211   if (status != 0)
212     {
213       error ("Unable to find dynamic library list.\n");
214       return;
215     }
216
217   /* addr now holds the address of the first entry in the dynamic
218      library list.  */
219   addr = extract_unsigned_integer (buf, 4);
220
221   /* Now that we have a pointer to the dynamic library list, walk
222      through it and add the symbols for each library.  */
223
224   so_list_tail = so_list_head;
225   /* Find the end of the list of shared objects.  */
226   while (so_list_tail && so_list_tail->next)
227     so_list_tail = so_list_tail->next;
228
229   while (1)
230     {
231       CORE_ADDR name_addr, text_addr;
232       unsigned int name_len;
233       char *name;
234       struct so_list *new_so;
235       struct so_list *so_list = so_list_head;
236       struct section_table *p;
237       struct stat statbuf;
238
239       if (addr == 0)
240         break;
241
242       /* Get a pointer to the name of this library.  */
243       status = target_read_memory (addr, buf, 4);
244       if (status != 0)
245         goto err;
246
247       name_addr = extract_unsigned_integer (buf, 4);
248       name_len = 0;
249       while (1)
250         {
251           target_read_memory (name_addr + name_len, buf, 1);
252           if (status != 0)
253             goto err;
254
255           name_len++;
256           if (*buf == '\0')
257             break;
258         }
259       name = alloca (name_len);
260       status = target_read_memory (name_addr, name, name_len);
261       if (status != 0)
262         goto err;
263
264       /* See if we've already loaded something with this name.  */
265       while (so_list)
266         {
267           if (!strcmp (so_list->som_solib.name, name))
268             break;
269           so_list = so_list->next;
270         }
271
272       /* See if the file exists.  If not, give a warning, but don't
273          die.  */
274       status = stat (name, &statbuf);
275       if (status == -1)
276         {
277           warning ("Can't find file %s referenced in dld_list.", name);
278
279           status = target_read_memory (addr + 36, buf, 4);
280           if (status != 0)
281             goto err;
282
283           addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
284           continue;
285         }
286
287       /* If we've already loaded this one or it's the main program, skip it.  */
288       if (so_list || !strcmp (name, symfile_objfile->name))
289         {
290           status = target_read_memory (addr + 36, buf, 4);
291           if (status != 0)
292             goto err;
293
294           addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
295           continue;
296         }
297
298       name = obsavestring (name, name_len - 1,
299                            &symfile_objfile->symbol_obstack);
300
301       status = target_read_memory (addr + 8, buf, 4);
302       if (status != 0)
303         goto err;
304
305       text_addr = extract_unsigned_integer (buf, 4);
306
307
308       new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
309       memset ((char *)new_so, 0, sizeof (struct so_list));
310       if (so_list_head == NULL)
311         {
312           so_list_head = new_so;
313           so_list_tail = new_so;
314         }
315       else
316         {
317           so_list_tail->next = new_so;
318           so_list_tail = new_so;
319         }
320
321       /* Fill in all the entries in GDB's shared library list.  */
322       new_so->som_solib.name = name;
323       status = target_read_memory (addr + 4, buf, 4);
324       if (status != 0)
325         goto err;
326
327       new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
328       new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
329       new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
330       new_so->som_solib.text_addr = text_addr;
331
332       status = target_read_memory (addr + 12, buf, 4);
333       if (status != 0)
334         goto err;
335
336       new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
337
338       status = target_read_memory (addr + 16, buf, 4);
339       if (status != 0)
340         goto err;
341
342       new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
343
344       status = target_read_memory (addr + 20, buf, 4);
345       if (status != 0)
346         goto err;
347
348       new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
349
350       status = target_read_memory (addr + 24, buf, 4);
351       if (status != 0)
352         goto err;
353
354       new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
355
356       status = target_read_memory (addr + 28, buf, 4);
357       if (status != 0)
358         goto err;
359
360       new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
361
362       status = target_read_memory (addr + 32, buf, 4);
363       if (status != 0)
364         goto err;
365
366       new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
367
368       status = target_read_memory (addr + 36, buf, 4);
369       if (status != 0)
370         goto err;
371
372       new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
373       addr = (CORE_ADDR)new_so->som_solib.next;
374
375       new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
376       new_so->abfd = new_so->objfile->obfd;
377
378       if (!bfd_check_format (new_so->abfd, bfd_object))
379         {
380           error ("\"%s\": not in executable format: %s.",
381                  name, bfd_errmsg (bfd_get_error ()));
382         }
383
384       /* Now we need to build a section table for this library since
385          we might be debugging a core file from a dynamically linked
386          executable in which the libraries were not privately mapped.  */
387       if (build_section_table (new_so->abfd,
388                                &new_so->sections,
389                                &new_so->sections_end))
390         {
391           error ("Unable to build section table for shared library\n.");
392           return;
393         }
394
395       /* Relocate all the sections based on where they got loaded.  */
396       for (p = new_so->sections; p < new_so->sections_end; p++)
397         {
398           if (p->the_bfd_section->flags & SEC_CODE)
399             {
400               p->addr += text_addr - new_so->som_solib.text_link_addr;
401               p->endaddr += text_addr - new_so->som_solib.text_link_addr;
402             }
403           else if (p->the_bfd_section->flags & SEC_DATA)
404             {
405               p->addr += new_so->som_solib.data_start;
406               p->endaddr += new_so->som_solib.data_start;
407             }
408         }
409
410       /* Now see if we need to map in the text and data for this shared
411          library (for example debugging a core file which does not use
412          private shared libraries.). 
413
414          Carefully peek at the first text address in the library.  If the
415          read succeeds, then the libraries were privately mapped and were
416          included in the core dump file.
417
418          If the peek failed, then the libraries were not privately mapped
419          and are not in the core file, we'll have to read them in ourselves.  */
420       status = target_read_memory (text_addr, buf, 4);
421       if (status != 0)
422         {
423           int old, new;
424           int update_coreops;
425
426           /* We must update the to_sections field in the core_ops structure
427              here, otherwise we dereference a potential dangling pointer
428              for each call to target_read/write_memory within this routine.  */
429           update_coreops = core_ops.to_sections == target->to_sections;
430
431           new = new_so->sections_end - new_so->sections;
432           /* Add sections from the shared library to the core target.  */
433           if (target->to_sections)
434             {
435               old = target->to_sections_end - target->to_sections;
436               target->to_sections = (struct section_table *)
437                 xrealloc ((char *)target->to_sections,
438                           ((sizeof (struct section_table)) * (old + new)));
439             }
440           else
441             {
442               old = 0;
443               target->to_sections = (struct section_table *)
444                 xmalloc ((sizeof (struct section_table)) * new);
445             }
446           target->to_sections_end = (target->to_sections + old + new);
447
448           /* Update the to_sections field in the core_ops structure
449              if needed.  */
450           if (update_coreops)
451             {
452               core_ops.to_sections = target->to_sections;
453               core_ops.to_sections_end = target->to_sections_end;
454             }
455
456           /* Copy over the old data before it gets clobbered.  */
457           memcpy ((char *)(target->to_sections + old),
458                   new_so->sections,
459                   ((sizeof (struct section_table)) * new));
460         }
461     }
462
463   /* Getting new symbols may change our opinion about what is
464      frameless.  */
465   reinit_frame_cache ();
466   return;
467
468 old_dld:
469   error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
470   return;
471
472 err:
473   error ("Error while reading dynamic library list.\n");
474   return;
475 }
476
477
478 /* This hook gets called just before the first instruction in the
479    inferior process is executed.
480
481    This is our opportunity to set magic flags in the inferior so
482    that GDB can be notified when a shared library is mapped in and
483    to tell the dynamic linker that a private copy of the library is
484    needed (so GDB can set breakpoints in the library).
485
486    __dld_flags is the location of the magic flags; as of this implementation
487    there are 3 flags of interest:
488
489    bit 0 when set indicates that private copies of the libraries are needed
490    bit 1 when set indicates that the callback hook routine is valid
491    bit 2 when set indicates that the dynamic linker should maintain the
492          __dld_list structure when loading/unloading libraries.
493
494    Note that shared libraries are not mapped in at this time, so we have
495    run the inferior until the libraries are mapped in.  Typically this
496    means running until the "_start" is called.  */
497
498 void
499 som_solib_create_inferior_hook()
500 {
501   struct minimal_symbol *msymbol;
502   unsigned int dld_flags, status, have_endo;
503   asection *shlib_info;
504   char buf[4];
505   struct objfile *objfile;
506   CORE_ADDR anaddr;
507
508   /* First, remove all the solib event breakpoints.  Their addresses
509      may have changed since the last time we ran the program.  */
510   remove_solib_event_breakpoints ();
511
512   if (symfile_objfile == NULL)
513     return; 
514
515   /* First see if the objfile was dynamically linked.  */
516   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
517   if (!shlib_info)
518     return;
519
520   /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
521   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
522     return;
523
524   have_endo = 0;
525   /* If __d_pid is present, then put the inferior's pid into __d_pid.  hpux9
526      requires __d_pid to be set.  hpux10 doesn't require __d_pid to be set
527      and the symbol may not be available. 
528
529      Never warn about __d_pid.  */
530   msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
531   if (msymbol != NULL)
532     {
533       anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
534       store_unsigned_integer (buf, 4, inferior_pid);
535       status = target_write_memory (anaddr, buf, 4);
536       if (status != 0)
537         {
538           warning ("Unable to write __d_pid");
539           goto keep_going;
540         }
541     }
542
543   /* If __d_trap_fptr exists, then load whatever's at that address
544      and put it into __dld_hook.  */
545   msymbol = lookup_minimal_symbol ("__d_trap_fptr", NULL, symfile_objfile);
546   if (msymbol != NULL)
547     {
548       anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
549       status = target_read_memory (anaddr, buf, 4);
550       anaddr = extract_unsigned_integer (buf, 4);
551
552       /* If it's a plabel, then get the address of the real function.
553          Egad.  This is just the opposite of how hpux9 and _DLD_HOOK
554          works.  */
555       if (anaddr | 0x2)
556         {
557           status = target_read_memory (anaddr & ~0x2, buf, 4);
558           anaddr = extract_unsigned_integer (buf, 4);
559         }
560     }
561   else
562     {
563       /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook;
564          This will force the dynamic linker to call __d_trap when significant
565          events occur.  */
566       msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
567       if (msymbol == NULL)
568         {
569           warning ("Unable to find _DLD_HOOK symbol in object file.");
570           warning ("Suggest linking with /usr/lib/end.o.");
571           warning ("GDB will be unable to track shl_load/shl_unload calls");
572           goto keep_going;
573         }
574       anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
575
576       /* Grrr, this might not be an export symbol!  We have to find the
577          export stub.  */
578       ALL_OBJFILES (objfile)
579         {
580           extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
581
582           /* What a crock.  */
583           msymbol
584             = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
585                                                       NULL, objfile);
586           /* Found a symbol with the right name.  */
587           if (msymbol)
588             {
589               struct unwind_table_entry *u;
590               /* It must be a shared library trampoline.  */
591               if (MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
592                 continue;
593
594               /* It must also be an export stub.  */
595               u = find_unwind_entry (SYMBOL_VALUE (msymbol));
596               if (!u || u->stub_type != EXPORT)
597                 continue;
598
599               /* OK.  Looks like the correct import stub.  */
600               anaddr = SYMBOL_VALUE (msymbol);
601               break;
602             }
603         }
604      }
605   store_unsigned_integer (buf, 4, anaddr);
606
607   msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
608   if (msymbol == NULL)
609     {
610       warning ("Unable to find __dld_hook symbol in object file.");
611       warning ("Suggest linking with /usr/lib/end.o.");
612       warning ("GDB will be unable to track shl_load/shl_unload calls");
613       goto keep_going;
614     }
615   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
616   status = target_write_memory (anaddr, buf, 4);
617   
618   /* Now set a shlib_event breakpoint at __d_trap so we can track
619      significant shared library events.  */
620   msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
621   if (msymbol == NULL)
622     {
623       warning ("Unable to find __dld_d_trap symbol in object file.");
624       warning ("Suggest linking with /usr/lib/end.o.");
625       warning ("GDB will be unable to track shl_load/shl_unload calls");
626       goto keep_going;
627     }
628   create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
629
630   /* We have all the support usually found in end.o, so we can track
631      shl_load and shl_unload calls.  */
632   have_endo = 1;
633
634 keep_going:
635
636   /* Get the address of __dld_flags, if no such symbol exists, then we can
637      not debug the shared code.  */
638   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
639   if (msymbol == NULL)
640     {
641       error ("Unable to find __dld_flags symbol in object file.\n");
642       goto keep_going;
643       return;
644     }
645
646   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
647   /* Read the current contents.  */
648   status = target_read_memory (anaddr, buf, 4);
649   if (status != 0)
650     {
651       error ("Unable to read __dld_flags\n");
652       return;
653     }
654   dld_flags = extract_unsigned_integer (buf, 4);
655
656   /* Turn on the flags we care about.  */
657   dld_flags |= (0x5 | (have_endo << 1));
658   store_unsigned_integer (buf, 4, dld_flags);
659   status = target_write_memory (anaddr, buf, 4);
660   if (status != 0)
661     {
662       error ("Unable to write __dld_flags\n");
663       return;
664     }
665
666   /* Now find the address of _start and set a breakpoint there. 
667      We still need this code for two reasons:
668
669         * Not all sites have /usr/lib/end.o, so it's not always
670         possible to track the dynamic linker's events.
671
672         * At this time no events are triggered for shared libraries
673         loaded at startup time (what a crock).  */
674         
675   msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
676   if (msymbol == NULL)
677     {
678       error ("Unable to find _start symbol in object file.\n");
679       return;
680     }
681
682   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
683
684   /* Make the breakpoint at "_start" a shared library event breakpoint.  */
685   create_solib_event_breakpoint (anaddr);
686
687   /* Wipe out all knowledge of old shared libraries since their
688      mapping can change from one exec to another!  */
689   while (so_list_head)
690     {
691       struct so_list *temp;
692
693       free_objfile (so_list_head->objfile);
694       temp = so_list_head;
695       free (so_list_head);
696       so_list_head = temp->next;
697     }
698   clear_symtab_users ();
699 }
700
701 /* Return the GOT value for the shared library in which ADDR belongs.  If
702    ADDR isn't in any known shared library, return zero.  */
703
704 CORE_ADDR
705 som_solib_get_got_by_pc (addr)
706      CORE_ADDR addr;
707 {
708   struct so_list *so_list = so_list_head;
709   CORE_ADDR got_value = 0;
710
711   while (so_list)
712     {
713       if (so_list->som_solib.text_addr <= addr
714           && so_list->som_solib.text_end > addr)
715         {
716           got_value = so_list->som_solib.got_value;
717           break;
718         }
719       so_list = so_list->next;
720     }
721   return got_value;
722 }
723
724 int
725 som_solib_section_offsets (objfile, offsets)
726      struct objfile *objfile;
727      struct section_offsets *offsets;
728 {
729   struct so_list *so_list = so_list_head;
730
731   while (so_list)
732     {
733       /* Oh what a pain!  We need the offsets before so_list->objfile
734          is valid.  The BFDs will never match.  Make a best guess.  */
735       if (strstr (objfile->name, so_list->som_solib.name))
736         {
737           asection *private_section;
738
739           /* The text offset is easy.  */
740           ANOFFSET (offsets, SECT_OFF_TEXT)
741             = (so_list->som_solib.text_addr
742                - so_list->som_solib.text_link_addr);
743           ANOFFSET (offsets, SECT_OFF_RODATA)
744             = ANOFFSET (offsets, SECT_OFF_TEXT);
745
746           /* We should look at presumed_dp in the SOM header, but
747              that's not easily available.  This should be OK though.  */
748           private_section = bfd_get_section_by_name (objfile->obfd,
749                                                      "$PRIVATE$");
750           if (!private_section)
751             {
752               warning ("Unable to find $PRIVATE$ in shared library!");
753               ANOFFSET (offsets, SECT_OFF_DATA) = 0;
754               ANOFFSET (offsets, SECT_OFF_BSS) = 0;
755               return 1;
756             }
757           ANOFFSET (offsets, SECT_OFF_DATA)
758             = (so_list->som_solib.data_start - private_section->vma);
759           ANOFFSET (offsets, SECT_OFF_BSS)
760             = ANOFFSET (offsets, SECT_OFF_DATA);
761           return 1;
762         }
763       so_list = so_list->next;
764     }
765   return 0;
766 }
767
768 /* Dump information about all the currently loaded shared libraries.  */
769
770 static void
771 som_sharedlibrary_info_command (ignore, from_tty)
772      char *ignore;
773      int from_tty;
774 {
775   struct so_list *so_list = so_list_head;
776
777   if (exec_bfd == NULL)
778     {
779       printf_unfiltered ("no exec file.\n");
780       return;
781     }
782
783   if (so_list == NULL)
784     {
785       printf_unfiltered ("No shared libraries loaded at this time.\n");
786       return;
787     }
788
789   printf_unfiltered ("Shared Object Libraries\n");
790   printf_unfiltered ("    %-12s%-12s%-12s%-12s%-12s%-12s\n",
791                      "  flags", "  tstart", "   tend", "  dstart", "   dend", "   dlt");
792   while (so_list)
793     {
794       unsigned int flags;
795
796       flags = so_list->som_solib.struct_version << 24;
797       flags |= so_list->som_solib.bind_mode << 16;
798       flags |= so_list->som_solib.library_version;
799       printf_unfiltered ("%s\n", so_list->som_solib.name);
800       printf_unfiltered ("    %-12s", local_hex_string_custom (flags, "08l"));
801       printf_unfiltered ("%-12s",
802               local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
803       printf_unfiltered ("%-12s",
804               local_hex_string_custom (so_list->som_solib.text_end, "08l"));
805       printf_unfiltered ("%-12s",
806               local_hex_string_custom (so_list->som_solib.data_start, "08l"));
807       printf_unfiltered ("%-12s",
808               local_hex_string_custom (so_list->som_solib.data_end, "08l"));
809       printf_unfiltered ("%-12s\n",
810               local_hex_string_custom (so_list->som_solib.got_value, "08l"));
811       so_list = so_list->next;
812     }
813 }
814
815 static void
816 som_solib_sharedlibrary_command (args, from_tty)
817      char *args;
818      int from_tty;
819 {
820   dont_repeat ();
821   som_solib_add (args, from_tty, (struct target_ops *) 0);
822 }
823
824 void
825 _initialize_som_solib ()
826 {
827   add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
828            "Load shared object library symbols for files matching REGEXP.");
829   add_info ("sharedlibrary", som_sharedlibrary_info_command,
830             "Status of loaded shared object libraries.");
831   add_show_from_set
832     (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
833                   (char *) &auto_solib_add,
834                   "Set autoloading of shared library symbols at startup.\n\
835 If nonzero, symbols from all shared object libraries will be loaded\n\
836 automatically when the inferior begins execution or when the dynamic linker\n\
837 informs gdb that a new library has been loaded.  Otherwise, symbols\n\
838 must be loaded manually, using `sharedlibrary'.",
839                   &setlist),
840      &showlist);
841
842 }