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