#include "defs.h"
#include "frame.h"
#include "bfd.h"
#include "som.h"
#include "libhppa.h"
#include "gdbcore.h"
#include "symtab.h"
#include "breakpoint.h"
#include "symfile.h"
#include "objfiles.h"
#include "inferior.h"
#include "gdb-stabs.h"
#include "gdb_stat.h"
#include "gdbcmd.h"
#include "assert.h"
#include "language.h"
#include "regcache.h"
#include <fcntl.h>
#ifndef O_BINARY
#define O_BINARY 0
#endif
extern struct target_ops exec_ops;
extern struct unwind_table_entry *find_unwind_entry (CORE_ADDR pc);
#define DLD_FLAGS_MAPPRIVATE 0x1
#define DLD_FLAGS_HOOKVALID 0x2
#define DLD_FLAGS_LISTVALID 0x4
#define DLD_FLAGS_BOR_ENABLE 0x8
struct som_solib_mapped_entry
{
char *name;
unsigned char struct_version;
unsigned char bind_mode;
short library_version;
CORE_ADDR text_addr;
CORE_ADDR text_link_addr;
CORE_ADDR text_end;
CORE_ADDR data_start;
CORE_ADDR bss_start;
CORE_ADDR data_end;
CORE_ADDR got_value;
struct som_solib_mapped_entry *next;
CORE_ADDR tsd_start_addr;
};
struct so_list
{
struct som_solib_mapped_entry som_solib;
struct objfile *objfile;
bfd *abfd;
struct section_table *sections;
struct section_table *sections_end;
CORE_ADDR solib_addr;
struct so_list *next;
};
static struct so_list *so_list_head;
static LONGEST som_solib_total_st_size;
static int som_solib_st_size_threshold_exceeded;
typedef struct
{
CORE_ADDR address;
struct unwind_table_entry *unwind;
}
addr_and_unwind_t;
static struct
{
boolean is_valid;
addr_and_unwind_t hook;
addr_and_unwind_t hook_stub;
addr_and_unwind_t load;
addr_and_unwind_t load_stub;
addr_and_unwind_t unload;
addr_and_unwind_t unload2;
addr_and_unwind_t unload_stub;
}
dld_cache;
static void som_sharedlibrary_info_command (char *, int);
static void som_solib_sharedlibrary_command (char *, int);
static LONGEST
som_solib_sizeof_symbol_table (char *filename)
{
bfd *abfd;
int desc;
char *absolute_name;
LONGEST st_size = (LONGEST) 0;
asection *sect;
desc = openp (getenv ("PATH"), 1, filename, O_RDONLY | O_BINARY, 0, &absolute_name);
if (desc < 0)
{
perror_with_name (filename);
}
filename = absolute_name;
abfd = bfd_fdopenr (filename, gnutarget, desc);
if (!abfd)
{
close (desc);
make_cleanup (xfree, filename);
error ("\"%s\": can't open to read symbols: %s.", filename,
bfd_errmsg (bfd_get_error ()));
}
if (!bfd_check_format (abfd, bfd_object))
{
bfd_close (abfd);
make_cleanup (xfree, filename);
error ("\"%s\": can't read symbols: %s.", filename,
bfd_errmsg (bfd_get_error ()));
}
sect = bfd_get_section_by_name (abfd, "$DEBUG$");
if (sect)
st_size += (LONGEST) bfd_section_size (abfd, sect);
sect = bfd_get_section_by_name (abfd, "$PINFO$");
if (sect)
st_size += (LONGEST) bfd_section_size (abfd, sect);
bfd_close (abfd);
xfree (filename);
return st_size * (LONGEST) 10;
}
static void
som_solib_add_solib_objfile (struct so_list *so, char *name, int from_tty,
CORE_ADDR text_addr)
{
obj_private_data_t *obj_private;
struct obj_section *s;
so->objfile = symbol_file_add (name, from_tty, NULL, 0, OBJF_SHARED);
so->abfd = so->objfile->obfd;
for (s = so->objfile->sections; s < so->objfile->sections_end; s++)
{
flagword aflag = bfd_get_section_flags(so->abfd, s->the_bfd_section);
if (aflag & SEC_CODE)
{
s->addr += so->som_solib.text_addr - so->som_solib.text_link_addr;
s->endaddr += so->som_solib.text_addr - so->som_solib.text_link_addr;
}
else if (aflag & SEC_DATA)
{
s->addr += so->som_solib.data_start;
s->endaddr += so->som_solib.data_start;
}
else
;
}
so->objfile->flags |= OBJF_SHARED;
if (so->objfile->obj_private == NULL)
{
obj_private = (obj_private_data_t *)
obstack_alloc (&so->objfile->psymbol_obstack,
sizeof (obj_private_data_t));
obj_private->unwind_info = NULL;
obj_private->so_info = NULL;
so->objfile->obj_private = (PTR) obj_private;
}
obj_private = (obj_private_data_t *) so->objfile->obj_private;
obj_private->so_info = so;
if (!bfd_check_format (so->abfd, bfd_object))
{
error ("\"%s\": not in executable format: %s.",
name, bfd_errmsg (bfd_get_error ()));
}
}
static void
som_solib_load_symbols (struct so_list *so, char *name, int from_tty,
CORE_ADDR text_addr, struct target_ops *target)
{
struct section_table *p;
int status;
char buf[4];
CORE_ADDR presumed_data_start;
#ifdef SOLIB_DEBUG
printf ("--Adding symbols for shared library \"%s\"\n", name);
#endif
som_solib_add_solib_objfile (so, name, from_tty, text_addr);
if (build_section_table (so->abfd,
&so->sections,
&so->sections_end))
{
error ("Unable to build section table for shared library\n.");
return;
}
for (p = so->sections; p < so->sections_end; p++)
{
if (p->the_bfd_section->flags & SEC_CODE)
{
p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile));
p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_TEXT (so->objfile));
}
else if (p->the_bfd_section->flags & SEC_DATA)
{
p->addr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile));
p->endaddr += ANOFFSET (so->objfile->section_offsets, SECT_OFF_DATA (so->objfile));
}
}
status = target_read_memory (text_addr, buf, 4);
if (status != 0)
{
int old, new;
new = so->sections_end - so->sections;
old = target_resize_to_sections (target, new);
memcpy ((char *) (target->to_sections + old),
so->sections,
((sizeof (struct section_table)) * new));
}
}
void
som_solib_add (char *arg_string, int from_tty, struct target_ops *target, int readsyms)
{
struct minimal_symbol *msymbol;
struct so_list *so_list_tail;
CORE_ADDR addr;
asection *shlib_info;
int status;
unsigned int dld_flags;
char buf[4], *re_err;
int threshold_warning_given = 0;
if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
{
error ("Invalid regexp: %s", re_err);
}
if (symfile_objfile == NULL)
return;
shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
if (!shlib_info)
return;
if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
return;
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
if (msymbol == NULL)
{
error ("Unable to find __dld_flags symbol in object file.\n");
return;
}
addr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_read_memory (addr, buf, 4);
if (status != 0)
{
error ("Unable to read __dld_flags\n");
return;
}
dld_flags = extract_unsigned_integer (buf, 4);
if ((dld_flags & DLD_FLAGS_LISTVALID) == 0)
{
if (from_tty)
error ("__dld_list is not valid according to __dld_flags.\n");
return;
}
if ((dld_flags & DLD_FLAGS_MAPPRIVATE) == 0)
warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
if (!msymbol)
{
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
if (!msymbol)
{
error ("Unable to find dynamic library list.\n");
return;
}
addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
}
else
addr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_read_memory (addr, buf, 4);
if (status != 0)
{
error ("Unable to find dynamic library list.\n");
return;
}
addr = extract_unsigned_integer (buf, 4);
if (addr == 0)
goto old_dld;
status = target_read_memory (addr, buf, 4);
if (status != 0)
{
error ("Unable to find dynamic library list.\n");
return;
}
addr = extract_unsigned_integer (buf, 4);
so_list_tail = so_list_head;
while (so_list_tail && so_list_tail->next)
so_list_tail = so_list_tail->next;
#ifdef SOLIB_DEBUG
printf ("--About to read shared library list data\n");
#endif
while (1)
{
CORE_ADDR name_addr, text_addr;
unsigned int name_len;
char *name;
struct so_list *new_so;
struct so_list *so_list = so_list_head;
struct stat statbuf;
LONGEST st_size;
int is_main_program;
if (addr == 0)
break;
status = target_read_memory (addr, buf, 4);
if (status != 0)
goto err;
name_addr = extract_unsigned_integer (buf, 4);
name_len = 0;
while (1)
{
target_read_memory (name_addr + name_len, buf, 1);
if (status != 0)
goto err;
name_len++;
if (*buf == '\0')
break;
}
name = alloca (name_len);
status = target_read_memory (name_addr, name, name_len);
if (status != 0)
goto err;
while (so_list)
{
if (!strcmp (so_list->som_solib.name, name))
break;
so_list = so_list->next;
}
status = stat (name, &statbuf);
if (status == -1)
{
warning ("Can't find file %s referenced in dld_list.", name);
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
goto err;
addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
continue;
}
is_main_program = (strcmp (name, symfile_objfile->name) == 0);
if (so_list || is_main_program)
{
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
goto err;
addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
if (is_main_program && !so_list)
{
st_size = som_solib_sizeof_symbol_table (name);
som_solib_total_st_size += st_size;
}
if (from_tty && so_list && !is_main_program && (so_list->objfile == NULL))
som_solib_load_symbols (so_list,
name,
from_tty,
so_list->som_solib.text_addr,
target);
continue;
}
name = obsavestring (name, name_len - 1,
&symfile_objfile->symbol_obstack);
status = target_read_memory (addr + 8, buf, 4);
if (status != 0)
goto err;
text_addr = extract_unsigned_integer (buf, 4);
new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
memset ((char *) new_so, 0, sizeof (struct so_list));
if (so_list_head == NULL)
{
so_list_head = new_so;
so_list_tail = new_so;
}
else
{
so_list_tail->next = new_so;
so_list_tail = new_so;
}
new_so->solib_addr = addr;
new_so->som_solib.name = name;
status = target_read_memory (addr + 4, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
new_so->som_solib.text_addr = text_addr;
status = target_read_memory (addr + 12, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 16, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 20, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 24, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 28, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 32, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
status = target_read_memory (addr + 36, buf, 4);
if (status != 0)
goto err;
new_so->som_solib.next =
address_to_host_pointer (extract_unsigned_integer (buf, 4));
status = target_read_memory (addr + 40, buf, 4);
new_so->som_solib.tsd_start_addr = extract_unsigned_integer (buf, 4);
if (status != 0)
goto err;
status = target_read_memory (new_so->som_solib.tsd_start_addr, buf, 4);
new_so->som_solib.tsd_start_addr = extract_unsigned_integer (buf, 4);
if (status != 0)
goto err;
#ifdef SOLIB_DEBUG
printf ("\n+ library \"%s\" is described at 0x%x\n", name, addr);
printf (" 'version' is %d\n", new_so->som_solib.struct_version);
printf (" 'bind_mode' is %d\n", new_so->som_solib.bind_mode);
printf (" 'library_version' is %d\n", new_so->som_solib.library_version);
printf (" 'text_addr' is 0x%x\n", new_so->som_solib.text_addr);
printf (" 'text_link_addr' is 0x%x\n", new_so->som_solib.text_link_addr);
printf (" 'text_end' is 0x%x\n", new_so->som_solib.text_end);
printf (" 'data_start' is 0x%x\n", new_so->som_solib.data_start);
printf (" 'bss_start' is 0x%x\n", new_so->som_solib.bss_start);
printf (" 'data_end' is 0x%x\n", new_so->som_solib.data_end);
printf (" 'got_value' is %x\n", new_so->som_solib.got_value);
printf (" 'next' is 0x%x\n", new_so->som_solib.next);
printf (" 'tsd_start_addr' is 0x%x\n", new_so->som_solib.tsd_start_addr);
#endif
addr = (CORE_ADDR) new_so->som_solib.next;
st_size = som_solib_sizeof_symbol_table (name);
som_solib_st_size_threshold_exceeded =
!from_tty &&
auto_solib_limit > 0 &&
readsyms &&
((st_size + som_solib_total_st_size) > (auto_solib_limit * (LONGEST) (1024 * 1024)));
if (som_solib_st_size_threshold_exceeded)
{
if (!threshold_warning_given)
warning ("Symbols for some libraries have not been loaded, because\ndoing so would exceed the size threshold specified by auto-solib-limit.\nTo manually load symbols, use the 'sharedlibrary' command.\nTo raise the threshold, set auto-solib-limit to a larger value and rerun\nthe program.\n");
threshold_warning_given = 1;
som_solib_add_solib_objfile (new_so, name, from_tty, text_addr);
continue;
}
som_solib_total_st_size += st_size;
som_solib_load_symbols (new_so, name, from_tty, text_addr, target);
}
#ifdef SOLIB_DEBUG
printf ("--Done reading shared library data\n");
#endif
reinit_frame_cache ();
return;
old_dld:
error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
return;
err:
error ("Error while reading dynamic library list.\n");
return;
}
void
som_solib_create_inferior_hook (void)
{
struct minimal_symbol *msymbol;
unsigned int dld_flags, status, have_endo;
asection *shlib_info;
char buf[4];
struct objfile *objfile;
CORE_ADDR anaddr;
remove_solib_event_breakpoints ();
if (symfile_objfile == NULL)
return;
shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
if (!shlib_info)
return;
if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
return;
have_endo = 0;
msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
if (msymbol == NULL)
goto keep_going;
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
store_unsigned_integer (buf, 4, PIDGET (inferior_ptid));
status = target_write_memory (anaddr, buf, 4);
if (status != 0)
{
warning ("Unable to write __d_pid");
warning ("Suggest linking with /opt/langtools/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
if (msymbol == NULL)
msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find _DLD_HOOK symbol in object file.");
warning ("Suggest linking with /opt/langtools/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
dld_cache.hook.address = anaddr;
ALL_OBJFILES (objfile)
{
struct unwind_table_entry *u;
struct minimal_symbol *msymbol2;
msymbol2 = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
NULL, objfile);
if (msymbol2)
{
struct unwind_table_entry *u;
if (SYMBOL_TYPE (msymbol2) != mst_solib_trampoline)
continue;
u = find_unwind_entry (SYMBOL_VALUE (msymbol2));
if (!u || u->stub_unwind.stub_type != EXPORT)
continue;
anaddr = SYMBOL_VALUE (msymbol2);
dld_cache.hook_stub.address = anaddr;
}
}
store_unsigned_integer (buf, 4, anaddr);
msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find __dld_hook symbol in object file.");
warning ("Suggest linking with /opt/langtools/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_write_memory (anaddr, buf, 4);
msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
if (msymbol == NULL)
{
warning ("Unable to find __dld_d_trap symbol in object file.");
warning ("Suggest linking with /opt/langtools/lib/end.o.");
warning ("GDB will be unable to track shl_load/shl_unload calls");
goto keep_going;
}
create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
have_endo = 1;
keep_going:
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
if (msymbol == NULL)
{
error ("Unable to find __dld_flags symbol in object file.\n");
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_read_memory (anaddr, buf, 4);
if (status != 0)
{
error ("Unable to read __dld_flags\n");
}
dld_flags = extract_unsigned_integer (buf, 4);
dld_flags |= DLD_FLAGS_MAPPRIVATE;
if (have_endo)
dld_flags |= DLD_FLAGS_HOOKVALID;
store_unsigned_integer (buf, 4, dld_flags);
status = target_write_memory (anaddr, buf, 4);
if (status != 0)
{
error ("Unable to write __dld_flags\n");
}
msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
if (msymbol == NULL)
{
error ("Unable to find _start symbol in object file.\n");
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
create_solib_event_breakpoint (anaddr);
while (so_list_head)
{
struct so_list *temp;
temp = so_list_head;
xfree (so_list_head);
so_list_head = temp->next;
}
clear_symtab_users ();
}
void
som_solib_remove_inferior_hook (int pid)
{
CORE_ADDR addr;
struct minimal_symbol *msymbol;
int status;
char dld_flags_buffer[TARGET_INT_BIT / TARGET_CHAR_BIT];
unsigned int dld_flags_value;
struct cleanup *old_cleanups = save_inferior_ptid ();
inferior_ptid = pid_to_ptid (pid);
msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
addr = SYMBOL_VALUE_ADDRESS (msymbol);
status = target_read_memory (addr, dld_flags_buffer, TARGET_INT_BIT / TARGET_CHAR_BIT);
dld_flags_value = extract_unsigned_integer (dld_flags_buffer,
sizeof (dld_flags_value));
dld_flags_value &= ~DLD_FLAGS_HOOKVALID;
store_unsigned_integer (dld_flags_buffer,
sizeof (dld_flags_value),
dld_flags_value);
status = target_write_memory (addr, dld_flags_buffer, TARGET_INT_BIT / TARGET_CHAR_BIT);
do_cleanups (old_cleanups);
}
void
som_solib_create_catch_load_hook (int pid, int tempflag, char *filename,
char *cond_string)
{
create_solib_load_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
}
void
som_solib_create_catch_unload_hook (int pid, int tempflag, char *filename,
char *cond_string)
{
create_solib_unload_event_breakpoint ("__d_trap", tempflag, filename, cond_string);
}
int
som_solib_have_load_event (int pid)
{
CORE_ADDR event_kind;
event_kind = read_register (ARG0_REGNUM);
return (event_kind == SHL_LOAD);
}
int
som_solib_have_unload_event (int pid)
{
CORE_ADDR event_kind;
event_kind = read_register (ARG0_REGNUM);
return (event_kind == SHL_UNLOAD);
}
static char *
som_solib_library_pathname (int pid)
{
CORE_ADDR dll_handle_address;
CORE_ADDR dll_pathname_address;
struct som_solib_mapped_entry dll_descriptor;
char *p;
static char dll_pathname[1024];
dll_handle_address = read_register (ARG1_REGNUM);
read_memory (dll_handle_address, (char *) &dll_descriptor, sizeof (dll_descriptor));
dll_pathname_address = (CORE_ADDR) dll_descriptor.name;
p = dll_pathname;
for (;;)
{
char b;
read_memory (dll_pathname_address++, (char *) &b, 1);
*p++ = b;
if (b == '\0')
break;
}
return dll_pathname;
}
char *
som_solib_loaded_library_pathname (int pid)
{
if (!som_solib_have_load_event (pid))
error ("Must have a load event to use this query");
return som_solib_library_pathname (pid);
}
char *
som_solib_unloaded_library_pathname (int pid)
{
if (!som_solib_have_unload_event (pid))
error ("Must have an unload event to use this query");
return som_solib_library_pathname (pid);
}
static void
som_solib_desire_dynamic_linker_symbols (void)
{
struct objfile *objfile;
struct unwind_table_entry *u;
struct minimal_symbol *dld_msymbol;
if (dld_cache.is_valid)
return;
ALL_OBJFILES (objfile)
{
dld_msymbol = lookup_minimal_symbol ("shl_load", NULL, objfile);
if (dld_msymbol != NULL)
{
dld_cache.load.address = SYMBOL_VALUE (dld_msymbol);
dld_cache.load.unwind = find_unwind_entry (dld_cache.load.address);
}
dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_load",
NULL,
objfile);
if (dld_msymbol != NULL)
{
if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
{
u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
{
dld_cache.load_stub.address = SYMBOL_VALUE (dld_msymbol);
dld_cache.load_stub.unwind = u;
}
}
}
dld_msymbol = lookup_minimal_symbol ("shl_unload", NULL, objfile);
if (dld_msymbol != NULL)
{
dld_cache.unload.address = SYMBOL_VALUE (dld_msymbol);
dld_cache.unload.unwind = find_unwind_entry (dld_cache.unload.address);
if (dld_cache.unload.unwind != NULL)
{
u = find_unwind_entry (dld_cache.unload.unwind->region_end + 4);
if (u != NULL)
{
dld_cache.unload2.address = u->region_start;
dld_cache.unload2.unwind = u;
}
}
}
dld_msymbol = lookup_minimal_symbol_solib_trampoline ("shl_unload",
NULL,
objfile);
if (dld_msymbol != NULL)
{
if (SYMBOL_TYPE (dld_msymbol) == mst_solib_trampoline)
{
u = find_unwind_entry (SYMBOL_VALUE (dld_msymbol));
if ((u != NULL) && (u->stub_unwind.stub_type == EXPORT))
{
dld_cache.unload_stub.address = SYMBOL_VALUE (dld_msymbol);
dld_cache.unload_stub.unwind = u;
}
}
}
if ((dld_cache.load.address != 0)
&& (dld_cache.load_stub.address != 0)
&& (dld_cache.unload.address != 0)
&& (dld_cache.unload_stub.address != 0))
{
dld_cache.is_valid = 1;
break;
}
}
dld_cache.hook.unwind = find_unwind_entry (dld_cache.hook.address);
dld_cache.hook_stub.unwind = find_unwind_entry (dld_cache.hook_stub.address);
}
int
som_solib_in_dynamic_linker (int pid, CORE_ADDR pc)
{
struct unwind_table_entry *u_pc;
if ((pc & (CORE_ADDR) 0xc0000000) == (CORE_ADDR) 0xc0000000)
return 1;
som_solib_desire_dynamic_linker_symbols ();
u_pc = find_unwind_entry (pc);
if (u_pc == NULL)
return 0;
if ((u_pc == dld_cache.hook.unwind) || (u_pc == dld_cache.hook_stub.unwind))
return 1;
if ((u_pc == dld_cache.load.unwind)
|| (u_pc == dld_cache.unload.unwind)
|| (u_pc == dld_cache.unload2.unwind)
|| (u_pc == dld_cache.load_stub.unwind)
|| (u_pc == dld_cache.unload_stub.unwind))
return 1;
return 0;
}
CORE_ADDR
som_solib_get_got_by_pc (CORE_ADDR addr)
{
struct so_list *so_list = so_list_head;
CORE_ADDR got_value = 0;
while (so_list)
{
if (so_list->som_solib.text_addr <= addr
&& so_list->som_solib.text_end > addr)
{
got_value = so_list->som_solib.got_value;
break;
}
so_list = so_list->next;
}
return got_value;
}
CORE_ADDR
som_solib_get_solib_by_pc (CORE_ADDR addr)
{
struct so_list *so_list = so_list_head;
while (so_list)
{
if (so_list->som_solib.text_addr <= addr
&& so_list->som_solib.text_end > addr)
{
break;
}
so_list = so_list->next;
}
if (so_list)
return so_list->solib_addr;
else
return 0;
}
int
som_solib_section_offsets (struct objfile *objfile,
struct section_offsets *offsets)
{
struct so_list *so_list = so_list_head;
while (so_list)
{
if (strstr (objfile->name, so_list->som_solib.name))
{
asection *private_section;
offsets->offsets[SECT_OFF_TEXT (objfile)]
= (so_list->som_solib.text_addr
- so_list->som_solib.text_link_addr);
offsets->offsets[SECT_OFF_RODATA (objfile)]
= ANOFFSET (offsets, SECT_OFF_TEXT (objfile));
private_section = bfd_get_section_by_name (objfile->obfd,
"$PRIVATE$");
if (!private_section)
{
warning ("Unable to find $PRIVATE$ in shared library!");
offsets->offsets[SECT_OFF_DATA (objfile)] = 0;
offsets->offsets[SECT_OFF_BSS (objfile)] = 0;
return 1;
}
offsets->offsets[SECT_OFF_DATA (objfile)]
= (so_list->som_solib.data_start - private_section->vma);
offsets->offsets[SECT_OFF_BSS (objfile)]
= ANOFFSET (offsets, SECT_OFF_DATA (objfile));
return 1;
}
so_list = so_list->next;
}
return 0;
}
static void
som_sharedlibrary_info_command (char *ignore, int from_tty)
{
struct so_list *so_list = so_list_head;
if (exec_bfd == NULL)
{
printf_unfiltered ("No executable file.\n");
return;
}
if (so_list == NULL)
{
printf_unfiltered ("No shared libraries loaded at this time.\n");
return;
}
printf_unfiltered ("Shared Object Libraries\n");
printf_unfiltered (" %-12s%-12s%-12s%-12s%-12s%-12s\n",
" flags", " tstart", " tend", " dstart", " dend", " dlt");
while (so_list)
{
unsigned int flags;
flags = so_list->som_solib.struct_version << 24;
flags |= so_list->som_solib.bind_mode << 16;
flags |= so_list->som_solib.library_version;
printf_unfiltered ("%s", so_list->som_solib.name);
if (so_list->objfile == NULL)
printf_unfiltered (" (symbols not loaded)");
printf_unfiltered ("\n");
printf_unfiltered (" %-12s", local_hex_string_custom (flags, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.text_end, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.data_start, "08l"));
printf_unfiltered ("%-12s",
local_hex_string_custom (so_list->som_solib.data_end, "08l"));
printf_unfiltered ("%-12s\n",
local_hex_string_custom (so_list->som_solib.got_value, "08l"));
so_list = so_list->next;
}
}
static void
som_solib_sharedlibrary_command (char *args, int from_tty)
{
dont_repeat ();
som_solib_add (args, from_tty, (struct target_ops *) 0, 1);
}
char *
som_solib_address (CORE_ADDR addr)
{
struct so_list *so = so_list_head;
while (so)
{
if ((addr >= so->som_solib.text_addr) && (addr <= so->som_solib.text_end))
return so->som_solib.name;
so = so->next;
}
return NULL;
}
void
som_solib_restart (void)
{
struct so_list *sl = so_list_head;
disable_breakpoints_in_shlibs (0);
while (sl)
{
struct so_list *next_sl = sl->next;
xfree (sl);
sl = next_sl;
}
so_list_head = NULL;
som_solib_total_st_size = (LONGEST) 0;
som_solib_st_size_threshold_exceeded = 0;
dld_cache.is_valid = 0;
dld_cache.hook.address = 0;
dld_cache.hook.unwind = NULL;
dld_cache.hook_stub.address = 0;
dld_cache.hook_stub.unwind = NULL;
dld_cache.load.address = 0;
dld_cache.load.unwind = NULL;
dld_cache.load_stub.address = 0;
dld_cache.load_stub.unwind = NULL;
dld_cache.unload.address = 0;
dld_cache.unload.unwind = NULL;
dld_cache.unload2.address = 0;
dld_cache.unload2.unwind = NULL;
dld_cache.unload_stub.address = 0;
dld_cache.unload_stub.unwind = NULL;
}
void
no_shared_libraries (char *ignored, int from_tty)
{
}
void
_initialize_som_solib (void)
{
add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
"Load shared object library symbols for files matching REGEXP.");
add_info ("sharedlibrary", som_sharedlibrary_info_command,
"Status of loaded shared object libraries.");
add_show_from_set
(add_set_cmd ("auto-solib-add", class_support, var_boolean,
(char *) &auto_solib_add,
"Set autoloading of shared library symbols.\n\
If \"on\", symbols from all shared object libraries will be loaded\n\
automatically when the inferior begins execution, when the dynamic linker\n\
informs gdb that a new library has been loaded, or when attaching to the\n\
inferior. Otherwise, symbols must be loaded manually, using `sharedlibrary'.",
&setlist),
&showlist);
add_show_from_set
(add_set_cmd ("auto-solib-limit", class_support, var_zinteger,
(char *) &auto_solib_limit,
"Set threshold (in Mb) for autoloading shared library symbols.\n\
When shared library autoloading is enabled, new libraries will be loaded\n\
only until the total size of shared library symbols exceeds this\n\
threshold in megabytes. Is ignored when using `sharedlibrary'.",
&setlist),
&showlist);
auto_solib_limit = 100;
som_solib_restart ();
}
CORE_ADDR
so_lib_thread_start_addr (struct so_list *so)
{
return so->som_solib.tsd_start_addr;
}