-#ifdef SVR4_SHARED_LIBS
-
-/* Return 1 if PC lies in the dynamic symbol resolution code of the
- SVR4 run time loader. */
-
-static CORE_ADDR interp_text_sect_low;
-static CORE_ADDR interp_text_sect_high;
-static CORE_ADDR interp_plt_sect_low;
-static CORE_ADDR interp_plt_sect_high;
-
-int
-in_svr4_dynsym_resolve_code (pc)
- CORE_ADDR pc;
-{
- return ((pc >= interp_text_sect_low && pc < interp_text_sect_high)
- || (pc >= interp_plt_sect_low && pc < interp_plt_sect_high)
- || in_plt_section (pc, NULL));
-}
-#endif
-
-/*
-
- LOCAL FUNCTION
-
- disable_break -- remove the "mapping changed" breakpoint
-
- SYNOPSIS
-
- static int disable_break ()
-
- DESCRIPTION
-
- Removes the breakpoint that gets hit when the dynamic linker
- completes a mapping change.
-
- */
-
-#ifndef SVR4_SHARED_LIBS
-
-static int
-disable_break ()
-{
- int status = 1;
-
-#ifndef SVR4_SHARED_LIBS
-
- int in_debugger = 0;
-
- /* Read the debugger structure from the inferior to retrieve the
- address of the breakpoint and the original contents of the
- breakpoint address. Remove the breakpoint by writing the original
- contents back. */
-
- read_memory (debug_addr, (char *) &debug_copy, sizeof (debug_copy));
-
- /* Set `in_debugger' to zero now. */
-
- write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
-
- breakpoint_addr = (CORE_ADDR) debug_copy.ldd_bp_addr;
- write_memory (breakpoint_addr, (char *) &debug_copy.ldd_bp_inst,
- sizeof (debug_copy.ldd_bp_inst));
-
-#else /* SVR4_SHARED_LIBS */
-
- /* Note that breakpoint address and original contents are in our address
- space, so we just need to write the original contents back. */
-
- if (memory_remove_breakpoint (breakpoint_addr, shadow_contents) != 0)
- {
- status = 0;
- }
-
-#endif /* !SVR4_SHARED_LIBS */
-
- /* For the SVR4 version, we always know the breakpoint address. For the
- SunOS version we don't know it until the above code is executed.
- Grumble if we are stopped anywhere besides the breakpoint address. */
-
- if (stop_pc != breakpoint_addr)
- {
- warning ("stopped at unknown breakpoint while handling shared libraries");
- }
-
- return (status);
-}
-
-#endif /* #ifdef SVR4_SHARED_LIBS */
-
-/*
-
- LOCAL FUNCTION
-
- enable_break -- arrange for dynamic linker to hit breakpoint
-
- SYNOPSIS
-
- int enable_break (void)
-
- DESCRIPTION
-
- Both the SunOS and the SVR4 dynamic linkers have, as part of their
- debugger interface, support for arranging for the inferior to hit
- a breakpoint after mapping in the shared libraries. This function
- enables that breakpoint.
-
- For SunOS, there is a special flag location (in_debugger) which we
- set to 1. When the dynamic linker sees this flag set, it will set
- a breakpoint at a location known only to itself, after saving the
- original contents of that place and the breakpoint address itself,
- in it's own internal structures. When we resume the inferior, it
- will eventually take a SIGTRAP when it runs into the breakpoint.
- We handle this (in a different place) by restoring the contents of
- the breakpointed location (which is only known after it stops),
- chasing around to locate the shared libraries that have been
- loaded, then resuming.
-
- For SVR4, the debugger interface structure contains a member (r_brk)
- which is statically initialized at the time the shared library is
- built, to the offset of a function (_r_debug_state) which is guaran-
- teed to be called once before mapping in a library, and again when
- the mapping is complete. At the time we are examining this member,
- it contains only the unrelocated offset of the function, so we have
- to do our own relocation. Later, when the dynamic linker actually
- runs, it relocates r_brk to be the actual address of _r_debug_state().
-
- The debugger interface structure also contains an enumeration which
- is set to either RT_ADD or RT_DELETE prior to changing the mapping,
- depending upon whether or not the library is being mapped or unmapped,
- and then set to RT_CONSISTENT after the library is mapped/unmapped.
- */
-
-static int
-enable_break ()
-{
- int success = 0;
-
-#ifndef SVR4_SHARED_LIBS
-
- int j;
- int in_debugger;
-
- /* Get link_dynamic structure */
-
- j = target_read_memory (debug_base, (char *) &dynamic_copy,
- sizeof (dynamic_copy));
- if (j)
- {
- /* unreadable */
- return (0);
- }
-
- /* Calc address of debugger interface structure */
-
- debug_addr = (CORE_ADDR) dynamic_copy.ldd;
-
- /* Calc address of `in_debugger' member of debugger interface structure */
-
- flag_addr = debug_addr + (CORE_ADDR) ((char *) &debug_copy.ldd_in_debugger -
- (char *) &debug_copy);
-
- /* Write a value of 1 to this member. */
-
- in_debugger = 1;
- write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
- success = 1;
-
-#else /* SVR4_SHARED_LIBS */
-
-#ifdef BKPT_AT_SYMBOL
-
- struct minimal_symbol *msymbol;
- char **bkpt_namep;
- asection *interp_sect;
-
- /* First, remove all the solib event breakpoints. Their addresses
- may have changed since the last time we ran the program. */
- remove_solib_event_breakpoints ();
-
-#ifdef SVR4_SHARED_LIBS
- interp_text_sect_low = interp_text_sect_high = 0;
- interp_plt_sect_low = interp_plt_sect_high = 0;
-
- /* Find the .interp section; if not found, warn the user and drop
- into the old breakpoint at symbol code. */
- interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
- if (interp_sect)
- {
- unsigned int interp_sect_size;
- char *buf;
- CORE_ADDR load_addr;
- bfd *tmp_bfd;
- CORE_ADDR sym_addr = 0;
-
- /* Read the contents of the .interp section into a local buffer;
- the contents specify the dynamic linker this program uses. */
- interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
- buf = alloca (interp_sect_size);
- bfd_get_section_contents (exec_bfd, interp_sect,
- buf, 0, interp_sect_size);
-
- /* Now we need to figure out where the dynamic linker was
- loaded so that we can load its symbols and place a breakpoint
- in the dynamic linker itself.
-
- This address is stored on the stack. However, I've been unable
- to find any magic formula to find it for Solaris (appears to
- be trivial on GNU/Linux). Therefore, we have to try an alternate
- mechanism to find the dynamic linker's base address. */
- tmp_bfd = bfd_openr (buf, gnutarget);
- if (tmp_bfd == NULL)
- goto bkpt_at_symbol;
-
- /* Make sure the dynamic linker's really a useful object. */
- if (!bfd_check_format (tmp_bfd, bfd_object))
- {
- warning ("Unable to grok dynamic linker %s as an object file", buf);
- bfd_close (tmp_bfd);
- goto bkpt_at_symbol;
- }
-
- /* We find the dynamic linker's base address by examining the
- current pc (which point at the entry point for the dynamic
- linker) and subtracting the offset of the entry point. */
- load_addr = read_pc () - tmp_bfd->start_address;
-
- /* Record the relocated start and end address of the dynamic linker
- text and plt section for in_svr4_dynsym_resolve_code. */
- interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
- if (interp_sect)
- {
- interp_text_sect_low =
- bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
- interp_text_sect_high =
- interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect);
- }
- interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
- if (interp_sect)
- {
- interp_plt_sect_low =
- bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
- interp_plt_sect_high =
- interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect);
- }
-
- /* Now try to set a breakpoint in the dynamic linker. */
- for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
- {
- sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
- if (sym_addr != 0)
- break;
- }
-
- /* We're done with the temporary bfd. */
- bfd_close (tmp_bfd);
-
- if (sym_addr != 0)
- {
- create_solib_event_breakpoint (load_addr + sym_addr);
- return 1;
- }
-
- /* For whatever reason we couldn't set a breakpoint in the dynamic
- linker. Warn and drop into the old code. */
- bkpt_at_symbol:
- warning ("Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code.");
- }
-#endif
-
- /* Scan through the list of symbols, trying to look up the symbol and
- set a breakpoint there. Terminate loop when we/if we succeed. */
-
- breakpoint_addr = 0;
- for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
- {
- msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
- if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
- {
- create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
- return 1;
- }
- }
-
- /* Nothing good happened. */
- success = 0;
-
-#endif /* BKPT_AT_SYMBOL */
-
-#endif /* !SVR4_SHARED_LIBS */
-
- return (success);
-}
-
-/*
-
- GLOBAL FUNCTION