]> Git Repo - binutils.git/blob - gdb/somsolib.c
* gdb.base/scope.exp (text_at_main): Add "hppa*-*-hpux*"
[binutils.git] / gdb / somsolib.c
1 /* Handle HP SOM shared libraries for GDB, the GNU Debugger.
2    Copyright 1993 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
38 /* TODO:
39
40    * Most of this code should work for hp300 shared libraries.  Does
41    anyone care enough to weed out any SOM-isms.
42
43    * Do we need/want a command to load a shared library?
44
45    * Support for hpux8 dynamic linker.
46
47    * Support for tracking user calls to dld_load, dld_unload.  */
48
49 /* The basic structure which describes a dynamically loaded object.  This
50    data structure is private to the dynamic linker and isn't found in
51    any HPUX include file.  */
52
53 struct som_solib_mapped_entry
54 {
55   /* The name of the library.  */
56   char *name;
57
58   /* Version of this structure (it is expected to change again in hpux10).  */
59   unsigned char struct_version;
60
61   /* Binding mode for this library.  */
62   unsigned char bind_mode;
63
64   /* Version of this library.  */
65   short library_version;
66
67   /* Start of text address, link-time text location, end of text address.  */
68   CORE_ADDR text_addr;
69   CORE_ADDR text_link_addr;
70   CORE_ADDR text_end;
71
72   /* Start of data, start of bss and end of data.  */
73   CORE_ADDR data_start;
74   CORE_ADDR bss_start;
75   CORE_ADDR data_end;
76
77   /* Value of linkage pointer (%r19).  */
78   CORE_ADDR got_value;
79
80   /* Next entry.  */
81   struct som_solib_mapped_entry *next;
82
83   /* There are other fields, but I don't have information as to what is
84      contained in them.  */
85 };
86
87 /* A structure to keep track of all the known shared objects.  */
88 struct so_list
89 {
90   struct som_solib_mapped_entry som_solib;
91   struct objfile *objfile;
92   bfd *abfd;
93   struct section_table *sections;
94   struct section_table *sections_end;
95   struct so_list *next;
96 };
97
98 static struct so_list *so_list_head;
99
100 static void som_sharedlibrary_info_command PARAMS ((char *, int));
101
102 /* Add symbols from shared libraries into the symtab list.  */
103
104 void
105 som_solib_add (arg_string, from_tty, target)
106      char *arg_string;
107      int from_tty;
108      struct target_ops *target;
109 {
110   struct minimal_symbol *msymbol;
111   struct so_list *so_list_tail;
112   CORE_ADDR addr;
113   asection *shlib_info;
114   int status;
115   unsigned int dld_flags;
116   char buf[4], *re_err;
117
118   /* First validate our arguments.  */
119   if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
120     {
121       error ("Invalid regexp: %s", re_err);
122     }
123
124   /* If we're debugging a core file, or have attached to a running
125      process, then som_solib_create_inferior_hook will not have been
126      called.
127
128      We need to first determine if we're dealing with a dynamically
129      linked executable.  If not, then return without an error or warning.
130
131      We also need to examine __dld_flags to determine if the shared library
132      list is valid and to determine if the libraries have been privately
133      mapped.  */
134   if (symfile_objfile == NULL)
135     return;
136
137   /* First see if the objfile was dynamically linked.  */
138   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
139   if (!shlib_info)
140     return;
141
142   /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
143   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
144     return;
145
146   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
147   if (msymbol == NULL)
148     {
149       error ("Unable to find __dld_flags symbol in object file.\n");
150       return;
151     }
152
153   addr = SYMBOL_VALUE_ADDRESS (msymbol);
154   /* Read the current contents.  */
155   status = target_read_memory (addr, buf, 4);
156   if (status != 0)
157     {
158       error ("Unable to read __dld_flags\n");
159       return;
160     }
161   dld_flags = extract_unsigned_integer (buf, 4);
162
163   /* __dld_list may not be valid.  If it's not valid tell the user.  */
164   if ((dld_flags & 4) == 0)
165     {
166       error ("__dld_list is not valid according to __dld_flags.\n");
167       return;
168     }
169
170   /* If the libraries were not mapped private, warn the user.  */
171   if ((dld_flags & 1) == 0)
172     warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
173
174   msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
175   if (!msymbol)
176     {
177       /* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
178          but the data is still available if you know where to look.  */
179       msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
180       if (!msymbol)
181         {
182           error ("Unable to find dynamic library list.\n");
183           return;
184         }
185       addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
186     }
187   else
188     addr = SYMBOL_VALUE_ADDRESS (msymbol);
189
190   status = target_read_memory (addr, buf, 4);
191   if (status != 0)
192     {
193       error ("Unable to find dynamic library list.\n");
194       return;
195     }
196
197   addr = extract_unsigned_integer (buf, 4);
198
199   /* If addr is zero, then we're using an old dynamic loader which
200      doesn't maintain __dld_list.  We'll have to use a completely
201      different approach to get shared library information.  */
202   if (addr == 0)
203     goto old_dld;
204
205   /* Using the information in __dld_list is the preferred method
206      to get at shared library information.  It doesn't depend on
207      any functions in /usr/lib/end.o and has a chance of working
208      with hpux10 when it is released.  */
209   status = target_read_memory (addr, buf, 4);
210   if (status != 0)
211     {
212       error ("Unable to find dynamic library list.\n");
213       return;
214     }
215
216   /* addr now holds the address of the first entry in the dynamic
217      library list.  */
218   addr = extract_unsigned_integer (buf, 4);
219
220   /* Now that we have a pointer to the dynamic library list, walk
221      through it and add the symbols for each library.  */
222
223   so_list_tail = so_list_head;
224   /* Find the end of the list of shared objects.  */
225   while (so_list_tail && so_list_tail->next)
226     so_list_tail = so_list_tail->next;
227
228   while (1)
229     {
230       CORE_ADDR name_addr, text_addr;
231       unsigned int name_len;
232       char *name;
233       struct so_list *new_so;
234       struct so_list *so_list = so_list_head;
235       struct section_table *p;
236
237       if (addr == 0)
238         break;
239
240       /* Get a pointer to the name of this library.  */
241       status = target_read_memory (addr, buf, 4);
242       if (status != 0)
243         goto err;
244
245       name_addr = extract_unsigned_integer (buf, 4);
246       name_len = 0;
247       while (1)
248         {
249           target_read_memory (name_addr + name_len, buf, 1);
250           if (status != 0)
251             goto err;
252
253           name_len++;
254           if (*buf == '\0')
255             break;
256         }
257       name = alloca (name_len);
258       status = target_read_memory (name_addr, name, name_len);
259       if (status != 0)
260         goto err;
261
262       /* See if we've already loaded something with this name.  */
263       while (so_list)
264         {
265           if (!strcmp (so_list->som_solib.name, name))
266             break;
267           so_list = so_list->next;
268         }
269
270       /* We've already loaded this one or it's the main program, skip it.  */
271       if (so_list || !strcmp (name, symfile_objfile->name))
272         {
273           status = target_read_memory (addr + 36, buf, 4);
274           if (status != 0)
275             goto err;
276
277           addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
278           continue;
279         }
280
281       name = obsavestring (name, name_len - 1,
282                            &symfile_objfile->symbol_obstack);
283
284       status = target_read_memory (addr + 8, buf, 4);
285       if (status != 0)
286         goto err;
287
288       text_addr = extract_unsigned_integer (buf, 4);
289
290
291       new_so = (struct so_list *) malloc (sizeof (struct so_list));
292       memset ((char *)new_so, 0, sizeof (struct so_list));
293       if (so_list_head == NULL)
294         {
295           so_list_head = new_so;
296           so_list_tail = new_so;
297         }
298       else
299         {
300           so_list_tail->next = new_so;
301           so_list_tail = new_so;
302         }
303
304       /* Fill in all the entries in GDB's shared library list.  */
305       new_so->som_solib.name = name;
306       status = target_read_memory (addr + 4, buf, 4);
307       if (status != 0)
308         goto err;
309
310       new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
311       new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
312       new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
313       new_so->som_solib.text_addr = text_addr;
314
315       status = target_read_memory (addr + 12, buf, 4);
316       if (status != 0)
317         goto err;
318
319       new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
320
321       status = target_read_memory (addr + 16, buf, 4);
322       if (status != 0)
323         goto err;
324
325       new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
326
327       status = target_read_memory (addr + 20, buf, 4);
328       if (status != 0)
329         goto err;
330
331       new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
332
333       status = target_read_memory (addr + 24, buf, 4);
334       if (status != 0)
335         goto err;
336
337       new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
338
339       status = target_read_memory (addr + 28, buf, 4);
340       if (status != 0)
341         goto err;
342
343       new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
344
345       status = target_read_memory (addr + 32, buf, 4);
346       if (status != 0)
347         goto err;
348
349       new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
350
351       status = target_read_memory (addr + 36, buf, 4);
352       if (status != 0)
353         goto err;
354
355       new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
356       addr = (CORE_ADDR)new_so->som_solib.next;
357
358       new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
359       new_so->abfd = new_so->objfile->obfd;
360
361       if (!bfd_check_format (new_so->abfd, bfd_object))
362         {
363           error ("\"%s\": not in executable format: %s.",
364                  name, bfd_errmsg (bfd_get_error ()));
365         }
366
367       /* Now we need to build a section table for this library since
368          we might be debugging a core file from a dynamically linked
369          executable in which the libraries were not privately mapped.  */
370       if (build_section_table (new_so->abfd,
371                                &new_so->sections,
372                                &new_so->sections_end))
373         {
374           error ("Unable to build section table for shared library\n.");
375           return;
376         }
377
378       /* Relocate all the sections based on where they got loaded.  */
379       for (p = new_so->sections; p < new_so->sections_end; p++)
380         {
381           if (p->the_bfd_section->flags & SEC_CODE)
382             {
383               p->addr += text_addr - new_so->som_solib.text_link_addr;
384               p->endaddr += text_addr - new_so->som_solib.text_link_addr;
385             }
386           else if (p->the_bfd_section->flags & SEC_DATA)
387             {
388               p->addr += new_so->som_solib.data_start;
389               p->endaddr += new_so->som_solib.data_start;
390             }
391         }
392
393       /* Now see if we need to map in the text and data for this shared
394          library (for example debugging a core file which does not use
395          private shared libraries.). 
396
397          Carefully peek at the first text address in the library.  If the
398          read succeeds, then the libraries were privately mapped and were
399          included in the core dump file.
400
401          If the peek failed, then the libraries were not privately mapped
402          and are not in the core file, we'll have to read them in ourselves.  */
403       status = target_read_memory (text_addr, buf, 4);
404       if (status != 0)
405         {
406           int old, new;
407
408           new = new_so->sections_end - new_so->sections;
409           /* Add sections from the shared library to the core target.  */
410           if (target->to_sections)
411             {
412               old = target->to_sections_end - target->to_sections;
413               target->to_sections = (struct section_table *)
414                 xrealloc ((char *)target->to_sections,
415                           ((sizeof (struct section_table)) * (old + new)));
416             }
417           else
418             {
419               old = 0;
420               target->to_sections = (struct section_table *)
421                 xmalloc ((sizeof (struct section_table)) * new);
422             }
423           target->to_sections_end = (target->to_sections + old + new);
424           memcpy ((char *)(target->to_sections + old),
425                   new_so->sections,
426                   ((sizeof (struct section_table)) * new));
427         }
428     }
429
430   /* Getting new symbols may change our opinion about what is
431      frameless.  */
432   reinit_frame_cache ();
433   return;
434
435 old_dld:
436   error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
437   return;
438
439 err:
440   error ("Error while reading dynamic library list.\n");
441   return;
442 }
443
444
445 /* This hook gets called just before the first instruction in the
446    inferior process is executed.
447
448    This is our opportunity to set magic flags in the inferior so
449    that GDB can be notified when a shared library is mapped in and
450    to tell the dynamic linker that a private copy of the library is
451    needed (so GDB can set breakpoints in the library).
452
453    __dld_flags is the location of the magic flags; as of this implementation
454    there are 3 flags of interest:
455
456    bit 0 when set indicates that private copies of the libraries are needed
457    bit 1 when set indicates that the callback hook routine is valid
458    bit 2 when set indicates that the dynamic linker should maintain the
459          __dld_list structure when loading/unloading libraries.
460
461    Note that shared libraries are not mapped in at this time, so we have
462    run the inferior until the libraries are mapped in.  Typically this
463    means running until the "_start" is called.  */
464
465 void
466 som_solib_create_inferior_hook()
467 {
468   struct minimal_symbol *msymbol;
469   unsigned int dld_flags, status;
470   asection *shlib_info;
471   char shadow_contents[BREAKPOINT_MAX], buf[4];
472   CORE_ADDR anaddr;
473
474   if (symfile_objfile == NULL)
475     return; 
476
477   /* First see if the objfile was dynamically linked.  */
478   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
479   if (!shlib_info)
480     return;
481
482   /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
483   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
484     return;
485
486   /* Get the address of __dld_flags, if no such symbol exists, then we can
487      not debug the shared code.  */
488   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
489   if (msymbol == NULL)
490     {
491       error ("Unable to find __dld_flags symbol in object file.\n");
492       return;
493     }
494
495   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
496   /* Read the current contents.  */
497   status = target_read_memory (anaddr, buf, 4);
498   if (status != 0)
499     {
500       error ("Unable to read __dld_flags\n");
501       return;
502     }
503   dld_flags = extract_unsigned_integer (buf, 4);
504
505   /* Turn on the flags we care about.  */
506   dld_flags |= 0x5;
507   store_unsigned_integer (buf, 4, dld_flags);
508   status = target_write_memory (anaddr, buf, 4);
509   if (status != 0)
510     {
511       error ("Unable to write __dld_flags\n");
512       return;
513     }
514
515   /* Now find the address of _start and set a breakpoint there.  */
516   msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
517   if (msymbol == NULL)
518     {
519       error ("Unable to find _start symbol in object file.\n");
520       return;
521     }
522
523   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
524   if (target_insert_breakpoint (anaddr, shadow_contents))
525     {
526       error ("Unable to set breakpoint at _start.\n");
527       return;
528     }
529
530   /* Wipe out all knowledge of old shared libraries since their
531      mapping can change from one exec to another!  */
532   while (so_list_head)
533     {
534       struct so_list *temp;
535
536       free_objfile (so_list_head->objfile);
537       temp = so_list_head;
538       free (so_list_head);
539       so_list_head = temp->next;
540     }
541
542   /* Start the process again and wait for it to hit our breakpoint.  */
543   clear_proceed_status ();
544   stop_soon_quietly = 1;
545   stop_signal = TARGET_SIGNAL_0;
546   do
547     {
548       target_resume (-1, 0, stop_signal);
549       wait_for_inferior ();
550     }
551   while (stop_signal != TARGET_SIGNAL_TRAP);
552   stop_soon_quietly = 0;
553
554   /* All the libraries should be mapped in now.  Remove our breakpoint and
555      read in the symbol tables from the shared libraries.  */
556   if (target_remove_breakpoint (anaddr, shadow_contents))
557     {
558       error ("Unable to remove breakpoint at _start.\n");
559       return;
560     }
561
562   som_solib_add ((char *) 0, 0, (struct target_ops *) 0);
563 }
564
565 /* Return the GOT value for the shared library in which ADDR belongs.  If
566    ADDR isn't in any known shared library, return zero.  */
567
568 CORE_ADDR
569 som_solib_get_got_by_pc (addr)
570      CORE_ADDR addr;
571 {
572   struct so_list *so_list = so_list_head;
573   CORE_ADDR got_value = 0;
574
575   while (so_list)
576     {
577       if (so_list->som_solib.text_addr <= addr
578           && so_list->som_solib.text_end > addr)
579         {
580           got_value = so_list->som_solib.got_value;
581           break;
582         }
583       so_list = so_list->next;
584     }
585   return got_value;
586 }
587
588 int
589 som_solib_section_offsets (objfile, offsets)
590      struct objfile *objfile;
591      struct section_offsets *offsets;
592 {
593   struct so_list *so_list = so_list_head;
594
595   while (so_list)
596     {
597       /* Oh what a pain!  We need the offsets before so_list->objfile
598          is valid.  The BFDs will never match.  Make a best guess.  */
599       if (strstr (objfile->name, so_list->som_solib.name))
600         {
601           asection *private_section;
602
603           /* The text offset is easy.  */
604           ANOFFSET (offsets, SECT_OFF_TEXT)
605             = (so_list->som_solib.text_addr
606                - so_list->som_solib.text_link_addr);
607           ANOFFSET (offsets, SECT_OFF_RODATA)
608             = ANOFFSET (offsets, SECT_OFF_TEXT);
609
610           /* We should look at presumed_dp in the SOM header, but
611              that's not easily available.  This should be OK though.  */
612           private_section = bfd_get_section_by_name (objfile->obfd,
613                                                      "$PRIVATE$");
614           if (!private_section)
615             {
616               warning ("Unable to find $PRIVATE$ in shared library!");
617               ANOFFSET (offsets, SECT_OFF_DATA) = 0;
618               ANOFFSET (offsets, SECT_OFF_BSS) = 0;
619               return 1;
620             }
621           ANOFFSET (offsets, SECT_OFF_DATA)
622             = (so_list->som_solib.data_start - private_section->vma);
623           ANOFFSET (offsets, SECT_OFF_BSS)
624             = ANOFFSET (offsets, SECT_OFF_DATA);
625           return 1;
626         }
627       so_list = so_list->next;
628     }
629   return 0;
630 }
631
632 /* Dump information about all the currently loaded shared libraries.  */
633
634 static void
635 som_sharedlibrary_info_command (ignore, from_tty)
636      char *ignore;
637      int from_tty;
638 {
639   struct so_list *so_list = so_list_head;
640
641   if (exec_bfd == NULL)
642     {
643       printf_unfiltered ("no exec file.\n");
644       return;
645     }
646
647   if (so_list == NULL)
648     {
649       printf_unfiltered ("No shared libraries loaded at this time.\n");
650       return;
651     }
652
653   printf_unfiltered ("Shared Object Libraries\n");
654   printf_unfiltered ("    %-12s%-12s%-12s%-12s%-12s%-12s\n",
655                      "  flags", "  tstart", "   tend", "  dstart", "   dend", "   dlt");
656   while (so_list)
657     {
658       unsigned int flags;
659
660       flags = so_list->som_solib.struct_version << 24;
661       flags |= so_list->som_solib.bind_mode << 16;
662       flags |= so_list->som_solib.library_version;
663       printf_unfiltered ("%s\n", so_list->som_solib.name);
664       printf_unfiltered ("    %-12s", local_hex_string_custom (flags, "08l"));
665       printf_unfiltered ("%-12s",
666               local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
667       printf_unfiltered ("%-12s",
668               local_hex_string_custom (so_list->som_solib.text_end, "08l"));
669       printf_unfiltered ("%-12s",
670               local_hex_string_custom (so_list->som_solib.data_start, "08l"));
671       printf_unfiltered ("%-12s",
672               local_hex_string_custom (so_list->som_solib.data_end, "08l"));
673       printf_unfiltered ("%-12s\n",
674               local_hex_string_custom (so_list->som_solib.got_value, "08l"));
675       so_list = so_list->next;
676     }
677 }
678
679 static void
680 som_solib_sharedlibrary_command (args, from_tty)
681      char *args;
682      int from_tty;
683 {
684   dont_repeat ();
685   som_solib_add (args, from_tty, (struct target_ops *) 0);
686 }
687
688 void
689 _initialize_som_solib ()
690 {
691   add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
692            "Load shared object library symbols for files matching REGEXP.");
693   add_info ("sharedlibrary", som_sharedlibrary_info_command,
694             "Status of loaded shared object libraries.");
695 }
This page took 0.063279 seconds and 4 git commands to generate.