Zap static data problem off the TODO list.
[external/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., 675 Mass Ave, Cambridge, MA 02139, 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];
117
118   /* If we're debugging a core file, or have attached to a running
119      process, then som_solib_create_inferior_hook will not have been
120      called.
121
122      We need to first determine if we're dealing with a dynamically
123      linked executable.  If not, then return without an error or warning.
124
125      We also need to examine __dld_flags to determine if the shared library
126      list is valid and to determine if the libraries have been privately
127      mapped.  */
128   if (symfile_objfile == NULL)
129     return;
130
131   /* First see if the objfile was dynamically linked.  */
132   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
133   if (!shlib_info)
134     return;
135
136   /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
137   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
138     return;
139
140   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
141   if (msymbol == NULL)
142     {
143       error ("Unable to find __dld_flags symbol in object file.\n");
144       return;
145     }
146
147   addr = SYMBOL_VALUE_ADDRESS (msymbol);
148   /* Read the current contents.  */
149   status = target_read_memory (addr, buf, 4);
150   if (status != 0)
151     {
152       error ("Unable to read __dld_flags\n");
153       return;
154     }
155   dld_flags = extract_unsigned_integer (buf, 4);
156
157   /* __dld_list may not be valid.  If it's not valid tell the user.  */
158   if ((dld_flags & 4) == 0)
159     {
160       error ("__dld_list is not valid according to __dld_flags.\n");
161       return;
162     }
163
164   /* If the libraries were not mapped private, warn the user.  */
165   if ((dld_flags & 1) == 0)
166     warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
167
168   msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
169   if (!msymbol)
170     {
171       /* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
172          but the data is still available if you know where to look.  */
173       msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
174       if (!msymbol)
175         {
176           error ("Unable to find dynamic library list.\n");
177           return;
178         }
179       addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
180     }
181   else
182     addr = SYMBOL_VALUE_ADDRESS (msymbol);
183
184   status = target_read_memory (addr, buf, 4);
185   if (status != 0)
186     {
187       error ("Unable to find dynamic library list.\n");
188       return;
189     }
190
191   addr = extract_unsigned_integer (buf, 4);
192
193   /* If addr is zero, then we're using an old dynamic loader which
194      doesn't maintain __dld_list.  We'll have to use a completely
195      different approach to get shared library information.  */
196   if (addr == 0)
197     goto old_dld;
198
199   /* Using the information in __dld_list is the preferred method
200      to get at shared library information.  It doesn't depend on
201      any functions in /usr/lib/end.o and has a chance of working
202      with hpux10 when it is released.  */
203   status = target_read_memory (addr, buf, 4);
204   if (status != 0)
205     {
206       error ("Unable to find dynamic library list.\n");
207       return;
208     }
209
210   /* addr now holds the address of the first entry in the dynamic
211      library list.  */
212   addr = extract_unsigned_integer (buf, 4);
213
214   /* Now that we have a pointer to the dynamic library list, walk
215      through it and add the symbols for each library.
216
217      Skip the first entry since it's our executable.  */
218   status = target_read_memory (addr + 36, buf, 4);
219   if (status != 0)
220     goto err;
221
222   addr = extract_unsigned_integer (buf, 4);
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 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       name = obsavestring (name, name_len - 1,
263                            &symfile_objfile->symbol_obstack);
264
265       status = target_read_memory (addr + 8, buf, 4);
266       if (status != 0)
267         goto err;
268
269       text_addr = extract_unsigned_integer (buf, 4);
270
271
272       new_so = (struct so_list *) malloc (sizeof (struct so_list));
273       memset ((char *)new_so, 0, sizeof (struct so_list));
274       if (so_list_head == NULL)
275         {
276           so_list_head = new_so;
277           so_list_tail = new_so;
278         }
279       else
280         {
281           so_list_tail->next = new_so;
282           so_list_tail = new_so;
283         }
284
285       /* Fill in all the entries in GDB's shared library list.  */
286       new_so->som_solib.name = name;
287       status = target_read_memory (addr + 4, buf, 4);
288       if (status != 0)
289         goto err;
290
291       new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
292       new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
293       new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
294       new_so->som_solib.text_addr = text_addr;
295
296       status = target_read_memory (addr + 12, buf, 4);
297       if (status != 0)
298         goto err;
299
300       new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
301
302       status = target_read_memory (addr + 16, buf, 4);
303       if (status != 0)
304         goto err;
305
306       new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
307
308       status = target_read_memory (addr + 20, buf, 4);
309       if (status != 0)
310         goto err;
311
312       new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
313
314       status = target_read_memory (addr + 24, buf, 4);
315       if (status != 0)
316         goto err;
317
318       new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
319
320       status = target_read_memory (addr + 28, buf, 4);
321       if (status != 0)
322         goto err;
323
324       new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
325
326       status = target_read_memory (addr + 32, buf, 4);
327       if (status != 0)
328         goto err;
329
330       new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
331
332       status = target_read_memory (addr + 36, buf, 4);
333       if (status != 0)
334         goto err;
335
336       new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
337       addr = (CORE_ADDR)new_so->som_solib.next;
338
339       new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
340       new_so->abfd = new_so->objfile->obfd;
341
342       if (!bfd_check_format (new_so->abfd, bfd_object))
343         {
344           error ("\"%s\": not in executable format: %s.",
345                  name, bfd_errmsg (bfd_get_error ()));
346         }
347
348       /* Now we need to build a section table for this library since
349          we might be debugging a core file from a dynamically linked
350          executable in which the libraries were not privately mapped.  */
351       if (build_section_table (new_so->abfd,
352                                &new_so->sections,
353                                &new_so->sections_end))
354         {
355           error ("Unable to build section table for shared library\n.");
356           return;
357         }
358
359       /* Relocate all the sections based on where they got loaded.  */
360       for (p = new_so->sections; p < new_so->sections_end; p++)
361         {
362           if (p->the_bfd_section->flags & SEC_CODE)
363             {
364               p->addr += text_addr - new_so->som_solib.text_link_addr;
365               p->endaddr += text_addr - new_so->som_solib.text_link_addr;
366             }
367           else if (p->the_bfd_section->flags & SEC_DATA)
368             {
369               p->addr += new_so->som_solib.data_start;
370               p->endaddr += new_so->som_solib.data_start;
371             }
372         }
373
374       /* Now see if we need to map in the text and data for this shared
375          library (for example debugging a core file which does not use
376          private shared libraries.). 
377
378          Carefully peek at the first text address in the library.  If the
379          read succeeds, then the libraries were privately mapped and were
380          included in the core dump file.
381
382          If the peek failed, then the libraries were not privately mapped
383          and are not in the core file, we'll have to read them in ourselves.  */
384       status = target_read_memory (text_addr, buf, 4);
385       if (status != 0)
386         {
387           int old, new;
388
389           new = new_so->sections_end - new_so->sections;
390           /* Add sections from the shared library to the core target.  */
391           if (target->to_sections)
392             {
393               old = target->to_sections_end - target->to_sections;
394               target->to_sections = (struct section_table *)
395                 xrealloc ((char *)target->to_sections,
396                           ((sizeof (struct section_table)) * (old + new)));
397             }
398           else
399             {
400               old = 0;
401               target->to_sections = (struct section_table *)
402                 xmalloc ((sizeof (struct section_table)) * new);
403             }
404           target->to_sections_end = (target->to_sections + old + new);
405           memcpy ((char *)(target->to_sections + old),
406                   new_so->sections,
407                   ((sizeof (struct section_table)) * new));
408         }
409     }
410
411   /* Getting new symbols may change our opinion about what is
412      frameless.  */
413   reinit_frame_cache ();
414   return;
415
416 old_dld:
417   error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
418   return;
419
420 err:
421   error ("Error while reading dynamic library list.\n");
422   return;
423 }
424
425
426 /* This hook gets called just before the first instruction in the
427    inferior process is executed.
428
429    This is our opportunity to set magic flags in the inferior so
430    that GDB can be notified when a shared library is mapped in and
431    to tell the dynamic linker that a private copy of the library is
432    needed (so GDB can set breakpoints in the library).
433
434    __dld_flags is the location of the magic flags; as of this implementation
435    there are 3 flags of interest:
436
437    bit 0 when set indicates that private copies of the libraries are needed
438    bit 1 when set indicates that the callback hook routine is valid
439    bit 2 when set indicates that the dynamic linker should maintain the
440          __dld_list structure when loading/unloading libraries.
441
442    Note that shared libraries are not mapped in at this time, so we have
443    run the inferior until the libraries are mapped in.  Typically this
444    means running until the "_start" is called.  */
445
446 void
447 som_solib_create_inferior_hook()
448 {
449   struct minimal_symbol *msymbol;
450   unsigned int dld_flags, status;
451   asection *shlib_info;
452   char shadow_contents[BREAKPOINT_MAX], buf[4];
453   CORE_ADDR anaddr;
454
455   if (symfile_objfile == NULL)
456     return; 
457
458   /* First see if the objfile was dynamically linked.  */
459   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
460   if (!shlib_info)
461     return;
462
463   /* It's got a $SHLIB_INFO$ section, make sure it's not empty.  */
464   if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
465     return;
466
467   /* Get the address of __dld_flags, if no such symbol exists, then we can
468      not debug the shared code.  */
469   msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
470   if (msymbol == NULL)
471     {
472       error ("Unable to find __dld_flags symbol in object file.\n");
473       return;
474     }
475
476   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
477   /* Read the current contents.  */
478   status = target_read_memory (anaddr, buf, 4);
479   if (status != 0)
480     {
481       error ("Unable to read __dld_flags\n");
482       return;
483     }
484   dld_flags = extract_unsigned_integer (buf, 4);
485
486   /* Turn on the flags we care about.  */
487   dld_flags |= 0x5;
488   store_unsigned_integer (buf, 4, dld_flags);
489   status = target_write_memory (anaddr, buf, 4);
490   if (status != 0)
491     {
492       error ("Unable to write __dld_flags\n");
493       return;
494     }
495
496   /* Now find the address of _start and set a breakpoint there.  */
497   msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
498   if (msymbol == NULL)
499     {
500       error ("Unable to find _start symbol in object file.\n");
501       return;
502     }
503
504   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
505   if (target_insert_breakpoint (anaddr, shadow_contents))
506     {
507       error ("Unable to set breakpoint at _start.\n");
508       return;
509     }
510
511   /* Wipe out all knowledge of old shared libraries since their
512      mapping can change from one exec to another!  */
513   while (so_list_head)
514     {
515       struct so_list *temp;
516
517       free_objfile (so_list_head->objfile);
518       temp = so_list_head;
519       free (so_list_head);
520       so_list_head = temp->next;
521     }
522
523   /* Start the process again and wait for it to hit our breakpoint.  */
524   clear_proceed_status ();
525   stop_soon_quietly = 1;
526   stop_signal = TARGET_SIGNAL_0;
527   do
528     {
529       target_resume (-1, 0, stop_signal);
530       wait_for_inferior ();
531     }
532   while (stop_signal != TARGET_SIGNAL_TRAP);
533   stop_soon_quietly = 0;
534
535   /* All the libraries should be mapped in now.  Remove our breakpoint and
536      read in the symbol tables from the shared libraries.  */
537   if (target_remove_breakpoint (anaddr, shadow_contents))
538     {
539       error ("Unable to remove breakpoint at _start.\n");
540       return;
541     }
542
543   som_solib_add ((char *) 0, 0, (struct target_ops *) 0);
544 }
545
546 /* Return the GOT value for the shared library in which ADDR belongs.  If
547    ADDR isn't in any known shared library, return zero.  */
548
549 CORE_ADDR
550 som_solib_get_got_by_pc (addr)
551      CORE_ADDR addr;
552 {
553   struct so_list *so_list = so_list_head;
554   CORE_ADDR got_value = 0;
555
556   while (so_list)
557     {
558       if (so_list->som_solib.text_addr <= addr
559           && so_list->som_solib.text_end > addr)
560         {
561           got_value = so_list->som_solib.got_value;
562           break;
563         }
564       so_list = so_list->next;
565     }
566   return got_value;
567 }
568
569 int
570 som_solib_section_offsets (objfile, offsets)
571      struct objfile *objfile;
572      struct section_offsets *offsets;
573 {
574   struct so_list *so_list = so_list_head;
575
576   while (so_list)
577     {
578       /* Oh what a pain!  We need the offsets before so_list->objfile
579          is valid.  The BFDs will never match.  Make a best guess.  */
580       if (strstr (objfile->name, so_list->som_solib.name))
581         {
582           asection *private_section;
583
584           /* The text offset is easy.  */
585           ANOFFSET (offsets, SECT_OFF_TEXT)
586             = (so_list->som_solib.text_addr
587                - so_list->som_solib.text_link_addr);
588           ANOFFSET (offsets, SECT_OFF_RODATA)
589             = ANOFFSET (offsets, SECT_OFF_TEXT);
590
591           /* We should look at presumed_dp in the SOM header, but
592              that's not easily available.  This should be OK though.  */
593           private_section = bfd_get_section_by_name (objfile->obfd,
594                                                      "$PRIVATE$");
595           if (!private_section)
596             {
597               warning ("Unable to find $PRIVATE$ in shared library!");
598               ANOFFSET (offsets, SECT_OFF_DATA) = 0;
599               ANOFFSET (offsets, SECT_OFF_BSS) = 0;
600               return 1;
601             }
602           ANOFFSET (offsets, SECT_OFF_DATA)
603             = (so_list->som_solib.data_start - private_section->vma);
604           ANOFFSET (offsets, SECT_OFF_BSS)
605             = ANOFFSET (offsets, SECT_OFF_DATA);
606           return 1;
607         }
608       so_list = so_list->next;
609     }
610   return 0;
611 }
612
613 /* Dump information about all the currently loaded shared libraries.  */
614
615 static void
616 som_sharedlibrary_info_command (ignore, from_tty)
617      char *ignore;
618      int from_tty;
619 {
620   struct so_list *so_list = so_list_head;
621
622   if (exec_bfd == NULL)
623     {
624       printf_unfiltered ("no exec file.\n");
625       return;
626     }
627
628   if (so_list == NULL)
629     {
630       printf_unfiltered ("No shared libraries loaded at this time.\n");
631       return;
632     }
633
634   printf_unfiltered ("Shared Object Libraries\n");
635   printf_unfiltered ("    %-12s%-12s%-12s%-12s%-12s%-12s\n",
636                      "  flags", "  tstart", "   tend", "  dstart", "   dend", "   dlt");
637   while (so_list)
638     {
639       unsigned int flags;
640
641       flags = so_list->som_solib.struct_version << 24;
642       flags |= so_list->som_solib.bind_mode << 16;
643       flags |= so_list->som_solib.library_version;
644       printf_unfiltered ("%s\n", so_list->som_solib.name);
645       printf_unfiltered ("    %-12s", local_hex_string_custom (flags, "08l"));
646       printf_unfiltered ("%-12s",
647               local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
648       printf_unfiltered ("%-12s",
649               local_hex_string_custom (so_list->som_solib.text_end, "08l"));
650       printf_unfiltered ("%-12s",
651               local_hex_string_custom (so_list->som_solib.data_start, "08l"));
652       printf_unfiltered ("%-12s",
653               local_hex_string_custom (so_list->som_solib.data_end, "08l"));
654       printf_unfiltered ("%-12s\n",
655               local_hex_string_custom (so_list->som_solib.got_value, "08l"));
656       so_list = so_list->next;
657     }
658 }
659
660 void
661 _initialize_som_solib ()
662 {
663   add_info ("sharedlibrary", som_sharedlibrary_info_command,
664             "Status of loaded shared object libraries.");
665 }