#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <mach/mach_types.h>
#include <mach/vm_types.h>
#include <mach/vm_region.h>
#include <mach/machine/vm_param.h>
#include <mach-o/loader.h>
#include <mach/task_info.h>
#include <sys/time.h>
#include "defs.h"
#include "inferior.h"
#include "target.h"
#include "gdbcmd.h"
#include "annotate.h"
#include "mach-o.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdb_assert.h"
#include "gdb_stat.h"
#include "regcache.h"
#include "bfd.h"
#include "gdb-stabs.h"
#include "objc-lang.h"
#include "gdbarch.h"
#include "arch-utils.h"
#include "ui-out.h"
#include "osabi.h"
#include "exceptions.h"
#include "remote.h"
#ifdef USE_MMALLOC
#include <mmalloc.h>
#endif
#include "macosx-nat-dyld.h"
#include "macosx-nat-dyld-path.h"
#include "macosx-nat-inferior.h"
#include "macosx-nat-inferior-debug.h"
#include "macosx-nat-mutils.h"
#include "macosx-nat-dyld.h"
#include "macosx-nat-dyld-io.h"
#include "macosx-nat-dyld-info.h"
#include "macosx-nat-dyld-path.h"
#include "macosx-nat-dyld-process.h"
#include "macosx-tdep.h"
#include <AvailabilityMacros.h>
#include <mach/mach_vm.h>
#if defined(TARGET_POWERPC)
#include "ppc-tdep.h"
#elif defined (TARGET_I386)
#include "amd64-tdep.h"
#include "i386-tdep.h"
#elif defined (TARGET_ARM)
#include "arm-tdep.h"
#else
#error "Unrecognized target architecture."
#endif
#if WITH_CFM
#include "macosx-nat-cfm.h"
#endif
#define INVALID_ADDRESS ((CORE_ADDR) (-1))
#if defined (NM_NEXTSTEP)
extern macosx_inferior_status *macosx_status;
#endif
extern struct target_ops exec_ops;
macosx_dyld_thread_status macosx_dyld_status;
static struct dyld_objfile_entry *macosx_solib_add_dyld_objfile_entries = NULL;
static int num_macosx_solib_add_dyld_objfile_entries = 0;
int dyld_preload_libraries_flag = 1;
int dyld_filter_events_flag = 1;
int dyld_always_read_from_memory_flag = 0;
char *dyld_symbols_prefix = "__dyld_";
int dyld_load_dyld_symbols_flag = 1;
int dyld_load_dyld_shlib_symbols_flag = 1;
int dyld_load_cfm_shlib_symbols_flag = 1;
int dyld_print_basenames_flag = 0;
int dyld_reload_on_downgrade_flag = 0;
static int pre_slide_libraries_flag = 1;
char *dyld_load_rules = NULL;
char *dyld_minimal_load_rules = NULL;
static char *shlib_path_subst_cmd_args = NULL;
static char **shlib_path_substitutions = NULL;
FILE *dyld_stderr = NULL;
int dyld_debug_flag = 0;
int inferior_auto_start_cfm_flag = 0;
int inferior_auto_start_dyld_flag = 1;
int dyld_stop_on_shlibs_added = 1;
int dyld_stop_on_shlibs_updated = 1;
int dyld_combine_shlibs_added = 1;
char *malloc_inited_callback = "_Z21registerThreadHelpersPKN4dyld16LibSystemHelpersE";
char *malloc_inited_callback_alt = "_ZL21registerThreadHelpersPKN4dyld16LibSystemHelpersE";
struct dyld_raw_infos
{
uint32_t version;
uint32_t num_info;
CORE_ADDR info_array;
CORE_ADDR dyld_notify;
int process_detached_from_shared_region;
int libsystem_initialized;
CORE_ADDR dyld_actual_load_address;
CORE_ADDR dyld_intended_load_address;
};
struct dyld_raw_info
{
CORE_ADDR addr;
CORE_ADDR name;
uint64_t modtime;
};
static void info_sharedlibrary_address (CORE_ADDR);
static void set_load_state_1 (struct dyld_objfile_entry *e,
const struct dyld_path_info *d,
int index,
int load_state);
static void dyld_read_raw_infos (CORE_ADDR addr, struct dyld_raw_infos *info);
static void dyld_info_read_raw (struct macosx_dyld_thread_status *status,
struct dyld_raw_info **rinfo,
int *rninfo);
static void dyld_info_read_raw_data (CORE_ADDR addr, int num,
struct dyld_raw_info *rinfo);
static int dyld_starts_here_p (mach_vm_address_t addr);
static int dyld_info_process_raw (struct macosx_dyld_thread_status *status,
struct dyld_objfile_entry *entry,
CORE_ADDR name, uint64_t modtime,
CORE_ADDR header_addr);
static void macosx_set_auto_start_dyld (char *args, int from_tty,
struct cmd_list_element *c);
static int target_read_dylib_command (CORE_ADDR addr,
struct dylib_command *dcmd);
static CORE_ADDR find_text_segment_load_address (CORE_ADDR mem_addr);
void
dyld_debug (const char *fmt, ...)
{
va_list ap;
if (dyld_debug_flag >= 1)
{
va_start (ap, fmt);
fprintf (dyld_stderr, "[%d dyld]: ", getpid ());
vfprintf (dyld_stderr, fmt, ap);
va_end (ap);
fflush (dyld_stderr);
}
}
void
dyld_print_status_info (struct macosx_dyld_thread_status *s,
unsigned int mask, char *args)
{
switch (s->state)
{
case dyld_clear:
ui_out_text (uiout,
"The DYLD shared library state has not yet been initialized.\n");
break;
case dyld_initialized:
ui_out_text (uiout,
"The DYLD shared library state has been initialized from the "
"executable's shared library information. All symbols should be "
"present, but the addresses of some symbols may move when the program "
"is executed, as DYLD may relocate library load addresses if "
"necessary.\n");
break;
case dyld_started:
ui_out_text (uiout,
"DYLD shared library information has been read from "
"the DYLD debugging thread.\n");
break;
default:
internal_error (__FILE__, __LINE__, "invalid value for s->dyld_state");
break;
}
dyld_print_shlib_info (&s->current_info, mask, 1, args);
}
void
macosx_clear_start_breakpoint (void)
{
remove_solib_event_breakpoints ();
}
int
target_is_remote ()
{
if (strstr (current_target.to_shortname, "remote") == NULL
&& strstr (current_target.to_shortname, "async") == NULL)
return 0;
if (strcmp (current_target.to_shortname, "remote"))
return 1;
if (strcmp (current_target.to_shortname, "remote-mobile"))
return 1;
if (strcmp (current_target.to_shortname, "remote-macosx"))
return 1;
if (strcmp (current_target.to_shortname, "extended-remote"))
return 1;
if (strcmp (current_target.to_shortname, "extended-async"))
return 1;
if (strcmp (current_target.to_shortname, "async"))
return 1;
return 0;
}
int
target_is_kdp_remote ()
{
if (strcmp (current_target.to_shortname, "remote-kdp") == 0)
return 1;
return 0;
}
static CORE_ADDR
lookup_dyld_address (macosx_dyld_thread_status *status, const char *s)
{
struct minimal_symbol *msym = NULL;
CORE_ADDR sym_addr;
char *ns = NULL;
xasprintf (&ns, "%s%s", dyld_symbols_prefix, s);
msym = lookup_minimal_symbol (ns, NULL, NULL);
xfree (ns);
if (msym == NULL)
return INVALID_ADDRESS;
sym_addr = SYMBOL_VALUE_ADDRESS (msym);
if (status->dyld_slide != INVALID_ADDRESS
&& status->dyld_minsyms_have_been_relocated == 0)
{
sym_addr += status->dyld_slide;
}
return sym_addr;
}
void
macosx_init_addresses (macosx_dyld_thread_status *s)
{
struct dyld_raw_infos infos;
struct objfile *dyld_objfile = find_objfile_by_name ("dyld", 0);
if (dyld_objfile && dyld_objfile->obfd)
{
if (gdbarch_lookup_osabi_from_bfd (dyld_objfile->obfd) !=
osabi_seen_in_attached_dyld)
{
const char *osabi_name = gdbarch_osabi_name (osabi_seen_in_attached_dyld);
set_osabi_option (osabi_name);
reread_symbols_for_objfile (dyld_objfile, 0,
osabi_seen_in_attached_dyld, NULL);
}
}
if (s->dyld_image_infos == INVALID_ADDRESS)
{
s->dyld_image_infos = lookup_dyld_address (s, "dyld_all_image_infos");
if (s->dyld_image_infos == INVALID_ADDRESS)
return;
}
dyld_read_raw_infos (s->dyld_image_infos, &infos);
s->libsystem_initialized = infos.libsystem_initialized;
macosx_set_malloc_inited (s->libsystem_initialized);
s->dyld_notify = infos.dyld_notify;
s->dyld_slide = infos.dyld_actual_load_address - infos.dyld_intended_load_address;
}
#define EXTRACT_INT_MEMBER(type, struct_ptr, member) \
struct_ptr -> member = extract_unsigned_integer ( \
(gdb_byte *)struct_ptr + offsetof(type, member), \
sizeof( struct_ptr -> member))
#define EXTRACT_INT_MEMBER_FROM_BUF(buf, type, struct_ptr, member) \
struct_ptr -> member = extract_unsigned_integer ( \
(gdb_byte *)buf + offsetof(type, member), \
sizeof( struct_ptr -> member))
int
target_read_mach_header (CORE_ADDR addr, struct mach_header *s)
{
int error;
gdb_assert (addr != INVALID_ADDRESS);
error = target_read_memory (addr, (gdb_byte *)s, sizeof (*s));
if (error == 0)
{
EXTRACT_INT_MEMBER (struct mach_header, s, magic);
EXTRACT_INT_MEMBER (struct mach_header, s, cputype);
EXTRACT_INT_MEMBER (struct mach_header, s, cpusubtype);
EXTRACT_INT_MEMBER (struct mach_header, s, filetype);
EXTRACT_INT_MEMBER (struct mach_header, s, ncmds);
EXTRACT_INT_MEMBER (struct mach_header, s, sizeofcmds);
EXTRACT_INT_MEMBER (struct mach_header, s, flags);
}
return error;
}
int
target_read_minimal_segment_32 (CORE_ADDR addr, struct segment_command *s)
{
int error;
gdb_assert (addr != INVALID_ADDRESS);
bzero (s, sizeof(*s));
error = target_read_memory (addr, (gdb_byte *)s, offsetof (struct segment_command, fileoff));
if (error == 0)
{
EXTRACT_INT_MEMBER (struct segment_command, s, cmd);
EXTRACT_INT_MEMBER (struct segment_command, s, cmdsize);
EXTRACT_INT_MEMBER (struct segment_command, s, vmaddr);
EXTRACT_INT_MEMBER (struct segment_command, s, vmsize);
}
return error;
}
int
target_read_minimal_segment_64 (CORE_ADDR addr, struct segment_command_64 *s)
{
int error;
gdb_assert (addr != INVALID_ADDRESS);
bzero (s, sizeof(*s));
error = target_read_memory (addr, (gdb_byte *)s, offsetof (struct segment_command_64, fileoff));
if (error == 0)
{
EXTRACT_INT_MEMBER (struct segment_command_64, s, cmd);
EXTRACT_INT_MEMBER (struct segment_command_64, s, cmdsize);
EXTRACT_INT_MEMBER (struct segment_command_64, s, vmaddr);
EXTRACT_INT_MEMBER (struct segment_command_64, s, vmsize);
}
return error;
}
int
target_get_mach_header_size (struct mach_header *header)
{
if (header->magic == 0xfeedfacf)
return sizeof (struct mach_header_64);
else
return sizeof (struct mach_header);
}
int
target_read_load_command (CORE_ADDR addr, struct load_command *s)
{
int error;
gdb_assert (addr != INVALID_ADDRESS);
error = target_read_memory (addr, (gdb_byte *)s, sizeof (*s));
if (error == 0)
{
EXTRACT_INT_MEMBER (struct load_command, s, cmd);
EXTRACT_INT_MEMBER (struct load_command, s, cmdsize);
}
return error;
}
int
target_read_uuid (CORE_ADDR addr, unsigned char *uuid)
{
int error;
struct uuid_command s;
gdb_assert (addr != INVALID_ADDRESS);
error = target_read_memory (addr, (gdb_byte *)&s, sizeof (s));
if (error == 0)
{
memcpy (uuid, s.uuid, 16);
}
return error;
}
int
target_read_dylib_command (CORE_ADDR addr, struct dylib_command *s)
{
int error;
gdb_assert (addr != INVALID_ADDRESS);
error = target_read_memory (addr, (gdb_byte *)s, sizeof (*s));
if (error == 0)
{
EXTRACT_INT_MEMBER (struct dylib_command, s, cmd);
EXTRACT_INT_MEMBER (struct dylib_command, s, cmdsize);
EXTRACT_INT_MEMBER (struct dylib_command, s, dylib.name.offset);
EXTRACT_INT_MEMBER (struct dylib_command, s, dylib.timestamp);
EXTRACT_INT_MEMBER (struct dylib_command, s, dylib.current_version);
EXTRACT_INT_MEMBER (struct dylib_command, s, dylib.compatibility_version);
}
return error;
}
static int
dyld_starts_here_in_memory (CORE_ADDR addr)
{
struct mach_header mh;
if (target_read_mach_header (addr, &mh) == 0)
return (mh.magic == MH_MAGIC || mh.magic == MH_MAGIC_64) &&
mh.filetype == MH_DYLINKER;
return 0;
}
static int
dyld_starts_here_p (mach_vm_address_t addr)
{
if (target_is_remote ())
return dyld_starts_here_in_memory (addr);
#if defined (NM_NEXTSTEP)
mach_vm_address_t address = addr;
mach_vm_size_t size = 0;
vm_region_basic_info_data_64_t info;
mach_msg_type_number_t info_cnt = sizeof (vm_region_basic_info_data_64_t);
kern_return_t ret;
mach_port_t object_name;
vm_offset_t data;
mach_msg_type_number_t data_count;
struct mach_header *mh;
info_cnt = VM_REGION_BASIC_INFO_COUNT_64;
ret = mach_vm_region (macosx_status->task, &address, &size,
VM_REGION_BASIC_INFO_64, (vm_region_info_t) &info,
&info_cnt, &object_name);
if (ret != KERN_SUCCESS)
return 0;
if ((info.protection & VM_PROT_READ) == 0)
return 0;
ret = mach_vm_read (macosx_status->task, address, size, &data, &data_count);
if (ret != KERN_SUCCESS)
{
return 0;
}
if (data_count < sizeof (struct mach_header))
{
ret = vm_deallocate (mach_task_self (), data, data_count);
return 0;
}
mh = (struct mach_header *) data;
if ((mh->magic != MH_MAGIC && mh->magic != MH_MAGIC_64) ||
mh->filetype != MH_DYLINKER ||
data_count < sizeof (struct mach_header) + mh->sizeofcmds)
{
ret = vm_deallocate (mach_task_self (), data, data_count);
return 0;
}
#ifdef TARGET_POWERPC
if (mh->magic == MH_MAGIC_64)
{
struct gdbarch_info info;
gdbarch_info_init (&info);
gdbarch_info_fill (current_gdbarch, &info);
info.byte_order = gdbarch_byte_order (current_gdbarch);
info.osabi = GDB_OSABI_DARWIN64;
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_powerpc, bfd_mach_ppc64);
gdbarch_update_p (info);
}
#endif
if (mh->magic == MH_MAGIC_64)
{
if (exec_bfd
&& gdbarch_lookup_osabi_from_bfd (exec_bfd) != GDB_OSABI_DARWIN64)
{
error ("The exec file is 32 bits but the attach target is 64 bits.\n"
"Quit gdb & restart, using \"--arch\" to select the 64 bit fork of the executable.");
}
}
else if (mh->magic == MH_MAGIC)
{
if (exec_bfd
&& gdbarch_lookup_osabi_from_bfd (exec_bfd) != GDB_OSABI_DARWIN
&& gdbarch_lookup_osabi_from_bfd (exec_bfd) != GDB_OSABI_DARWINV6
&& gdbarch_lookup_osabi_from_bfd (exec_bfd) != GDB_OSABI_DARWINV7)
{
error ("The exec file is 64 bits but the attach target is 32 bits.\n"
"Quit gdb & restart, using \"--arch\" to select the 32 bit fork of the executable.");
}
}
ret = vm_deallocate (mach_task_self (), data, data_count);
return 1;
#else
return 0;
#endif
}
static int
macosx_lookup_dyld_name (bfd *abfd, const char **rname)
{
struct mach_o_data_struct *mdata = NULL;
char *name = NULL;
char buf[PATH_MAX];
int i;
if (abfd == NULL)
return -1;
if (!bfd_mach_o_valid (abfd))
return -1;
mdata = abfd->tdata.mach_o_data;
CHECK_FATAL (mdata != NULL);
CHECK_FATAL (rname != NULL);
for (i = 0; i < mdata->header.ncmds; i++)
{
struct bfd_mach_o_load_command *cmd = &mdata->commands[i];
if (cmd->type == BFD_MACH_O_LC_LOAD_DYLINKER)
{
bfd_mach_o_dylinker_command *dcmd = &cmd->command.dylinker;
name = xmalloc (dcmd->name_len + 1);
bfd_seek (abfd, dcmd->name_offset, SEEK_SET);
if (bfd_bread (name, dcmd->name_len, abfd) != dcmd->name_len)
{
warning ("Unable to find library name for LC_LOAD_DYLINKER "
"or LD_ID_DYLINKER command; ignoring");
xfree (name);
name = NULL;
continue;
}
else
{
char *fixed_name = dyld_fix_path (name);
xfree (name);
name = fixed_name;
break;
}
}
}
if (name != NULL && realpath (name, buf) != NULL)
{
xfree (name);
name = xstrdup (buf);
}
*rname = name;
return (name == NULL) ? 0 : 1;
}
static int
macosx_lookup_dyld_file_load_address (const char *name, CORE_ADDR *loadaddr)
{
if (name == NULL || name[0] == '\0' || loadaddr == NULL)
return 0;
struct objfile *o;
o = find_objfile_by_name (name, 1);
if (o == NULL)
return 0;
*loadaddr = o->sections[o->sect_index_text].the_bfd_section->vma;
return 1;
}
static int
macosx_locate_dyld_via_taskinfo (macosx_dyld_thread_status *s)
{
if (s == NULL)
return 0;
if (s->dyld_image_infos == INVALID_ADDRESS)
{
CORE_ADDR all_image_info_addr = INVALID_ADDRESS;
if (target_is_kdp_remote ())
return 0;
if (target_is_remote ())
{
all_image_info_addr = remote_macosx_get_all_image_infos_addr ();
}
else
{
#if defined (NM_NEXTSTEP)
if (macosx_status->task == TASK_NULL)
return 0;
struct task_dyld_info task_dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
kern_return_t kret;
kret = task_info (macosx_status->task, TASK_DYLD_INFO,
(task_info_t) &task_dyld_info, &count);
if (kret != KERN_SUCCESS ||
task_dyld_info.all_image_info_addr == 0 ||
task_dyld_info.all_image_info_size == 0)
return 0;
all_image_info_addr = task_dyld_info.all_image_info_addr;
#else
return 0;
#endif // NM_NEXTSTEP
}
#if defined (TARGET_ARM)
if (target_is_remote () && all_image_info_addr == INVALID_ADDRESS
&& dyld_starts_here_p (0x2fe00000))
{
s->dyld_addr = 0x2fe00000;
s->dyld_slide = 0;
return 1;
}
#endif
if (all_image_info_addr == INVALID_ADDRESS)
return 0;
s->dyld_image_infos = all_image_info_addr;
}
if (s->dyld_image_infos != INVALID_ADDRESS)
{
struct dyld_raw_infos raw_infos;
struct gdb_exception e;
TRY_CATCH (e, RETURN_MASK_ERROR)
{
dyld_read_raw_infos (s->dyld_image_infos, &raw_infos);
}
if (e.reason != NO_ERROR)
return 0;
if (raw_infos.dyld_actual_load_address != INVALID_ADDRESS
&& raw_infos.dyld_actual_load_address != 0
&& dyld_starts_here_p (raw_infos.dyld_actual_load_address))
{
if (raw_infos.version >= 9
&& raw_infos.dyld_intended_load_address != INVALID_ADDRESS
&& dyld_starts_here_p (raw_infos.dyld_actual_load_address))
{
s->dyld_addr = raw_infos.dyld_actual_load_address;
s->dyld_slide = raw_infos.dyld_actual_load_address - raw_infos.dyld_intended_load_address;
return 1;
}
}
if (raw_infos.dyld_intended_load_address == INVALID_ADDRESS
&& raw_infos.dyld_actual_load_address != INVALID_ADDRESS
&& raw_infos.version >= 9
&& s->dyld_name != NULL
&& s->dyld_name[0] != '\0'
&& dyld_starts_here_p (raw_infos.dyld_actual_load_address))
{
CORE_ADDR dyld_file_vma;
CORE_ADDR dyld_here;
if (macosx_lookup_dyld_file_load_address (s->dyld_name, &dyld_file_vma) == 0)
return 0;
s->dyld_addr = raw_infos.dyld_actual_load_address;
s->dyld_slide = raw_infos.dyld_actual_load_address - dyld_file_vma;
return 1;
}
}
return 0;
}
static int
macosx_locate_dyld (CORE_ADDR *value, CORE_ADDR hint)
{
if (target_is_remote ())
{
if (hint != INVALID_ADDRESS && dyld_starts_here_p (hint))
{
*value = hint;
return 1;
}
return 0;
}
#if defined (NM_NEXTSTEP)
kern_return_t kret = KERN_SUCCESS;
vm_region_basic_info_data_64_t info;
mach_msg_type_number_t info_cnt = sizeof (vm_region_basic_info_data_64_t);
mach_vm_address_t test_addr = VM_MIN_ADDRESS;
mach_vm_size_t size = 0;
mach_port_t object_name = MACH_PORT_NULL;
task_t target_task = macosx_status->task;
info_cnt = VM_REGION_BASIC_INFO_COUNT_64;
do
{
kret = mach_vm_region (target_task, &test_addr,
&size, VM_REGION_BASIC_INFO_64,
(vm_region_info_t) &info, &info_cnt,
&object_name);
if (kret != KERN_SUCCESS)
return -1;
if (dyld_starts_here_p (test_addr))
{
*value = test_addr;
return 1;
}
test_addr += size;
}
while (size != 0);
#endif
return 0;
}
int
macosx_locate_dyld_static (macosx_dyld_thread_status *s, CORE_ADDR *value)
{
struct objfile *objfile = NULL;
const char *dyld_name = s->dyld_name;
if (dyld_name == NULL)
dyld_name = "/usr/lib/dyld";
ALL_OBJFILES (objfile)
{
asection *text_section = NULL;
if (core_bfd)
{
const char *bfd_filename = bfd_get_filename (objfile->obfd);
if (strstr (bfd_filename, "[memory object \"/usr/lib/dyld\"") == bfd_filename)
{
text_section = bfd_get_section_by_name (objfile->obfd,
"LC_SEGMENT.__TEXT");
*value = bfd_section_vma (objfile->obfd, text_section);
return 1;
}
}
if (strcmp (dyld_name, bfd_get_filename (objfile->obfd)) == 0)
{
text_section = bfd_get_section_by_name (objfile->obfd,
"LC_SEGMENT.__TEXT");
*value = bfd_section_vma (objfile->obfd, text_section);
return 1;
}
}
return 0;
}
#if WITH_CFM
int
macosx_cfm_init (macosx_cfm_thread_status *s)
{
if (inferior_auto_start_cfm_flag == 0)
return 0;
if (s->cfm_breakpoint != NULL)
return 0;
macosx_cfm_thread_create (s);
if (s->cfm_breakpoint == NULL)
return 0;
return 1;
}
#endif
static CORE_ADDR
find_text_segment_load_address (CORE_ADDR mem_addr)
{
struct bfd_section *mem_sect;
struct cleanup *bfd_cleanups = NULL;
bfd *mem_bfd = NULL;
struct mach_header h;
target_read_mach_header (mem_addr, &h);
int header_size = target_get_mach_header_size (&h);
gdb_byte *buf = (gdb_byte *) xmalloc (h.sizeofcmds + header_size);
bfd_cleanups = make_cleanup (xfree, buf);
if (target_read_memory (mem_addr, buf, h.sizeofcmds + header_size) == 0)
{
mem_bfd = bfd_memopenr ("tempbfd", NULL, buf, h.sizeofcmds + header_size);
if (mem_bfd && bfd_check_format (mem_bfd, bfd_object))
{
make_cleanup_bfd_close (mem_bfd);
for (mem_sect = mem_bfd->sections;
mem_sect != NULL;
mem_sect = mem_sect->next)
{
if (mem_sect->name && strcmp (mem_sect->name, "LC_SEGMENT.__TEXT") == 0)
{
do_cleanups (bfd_cleanups);
return mem_sect->vma;
}
}
}
}
if (bfd_cleanups)
do_cleanups (bfd_cleanups);
return INVALID_ADDRESS;
}
void
macosx_dyld_create_inferior_hook (CORE_ADDR all_image_info_addr)
{
macosx_clear_start_breakpoint ();
dyld_init_paths (&macosx_dyld_status.path_info);
macosx_dyld_thread_init (&macosx_dyld_status);
macosx_dyld_status.dyld_image_infos = all_image_info_addr;
if (inferior_auto_start_dyld_flag)
{
macosx_dyld_init (&macosx_dyld_status, exec_bfd);
}
}
int
macosx_dyld_init (macosx_dyld_thread_status *s, bfd *exec_bfd)
{
CORE_ADDR static_dyld_address = INVALID_ADDRESS;
CORE_ADDR dyld_address = INVALID_ADDRESS;
CORE_ADDR prev_dyld_address = INVALID_ADDRESS;
int ret = 0;
if (s->dyld_slide != INVALID_ADDRESS)
return 0;
if (s->dyld_name == NULL)
macosx_lookup_dyld_name (exec_bfd, &s->dyld_name);
prev_dyld_address = s->dyld_addr;
ret = macosx_locate_dyld_via_taskinfo (s);
if (ret == 1
&& s->dyld_addr != 0
&& s->dyld_addr != INVALID_ADDRESS
&& s->dyld_slide != 0
&& s->dyld_slide != INVALID_ADDRESS
&& s->dyld_name != NULL)
{
struct objfile *o = find_objfile_by_name (s->dyld_name, 1);
if (o)
{
dyld_slide_objfile (o, s->dyld_slide, NULL);
s->dyld_minsyms_have_been_relocated = 1;
}
}
if (ret == 1)
{
ret = macosx_locate_dyld (&dyld_address, s->dyld_addr);
}
if (ret != 1)
{
macosx_locate_dyld_static (s, &static_dyld_address);
if (s->dyld_addr != INVALID_ADDRESS)
ret = macosx_locate_dyld (&dyld_address, s->dyld_addr);
else if (static_dyld_address != INVALID_ADDRESS)
ret = macosx_locate_dyld (&dyld_address, static_dyld_address);
else
ret = macosx_locate_dyld (&dyld_address, INVALID_ADDRESS);
}
if (ret != 1 && target_is_remote ())
{
ret = macosx_locate_dyld (&dyld_address, 0x2fe00000ull);
if (ret != 1)
ret = macosx_locate_dyld (&dyld_address, 0x8fc00000ull);
}
if (ret != 1)
{
if (core_bfd)
{
if (dyld_starts_here_in_memory (0x8fe00000ull))
{
dyld_address = 0x8fe00000ull;
ret = 1;
}
else if (dyld_starts_here_in_memory (0x00007fff5fc00000ull))
{
dyld_address = 0x00007fff5fc00000ull;
ret = 1;
}
else
{
int i = 0;
struct bfd_section *core_segment;
for (i=0, core_segment = core_bfd->sections;
core_segment != NULL && i<core_bfd->section_count;
i++, core_segment = core_segment->next)
{
if (dyld_starts_here_in_memory (core_segment->vma))
{
dyld_address = core_segment->vma;
ret = 1;
break;
}
}
}
}
}
if (ret != 1)
return 0;
CHECK_FATAL (dyld_address != INVALID_ADDRESS);
if (dyld_address != INVALID_ADDRESS)
{
target_read_mach_header (dyld_address, &s->dyld_mem_header);
if (s->dyld_name == NULL)
s->dyld_name = dyld_find_dylib_name (dyld_address,
s->dyld_mem_header.cputype,
s->dyld_mem_header.ncmds);
if (s->dyld_mem_header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC ||
s->dyld_mem_header.cputype == BFD_MACH_O_CPU_TYPE_I386)
osabi_seen_in_attached_dyld = GDB_OSABI_DARWIN;
else if (s->dyld_mem_header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64 ||
s->dyld_mem_header.cputype == BFD_MACH_O_CPU_TYPE_X86_64)
osabi_seen_in_attached_dyld = GDB_OSABI_DARWIN64;
#if defined (TARGET_ARM)
else if (s->dyld_mem_header.cputype == BFD_MACH_O_CPU_TYPE_ARM)
{
if (s->dyld_mem_header.cpusubtype == BFD_MACH_O_CPU_SUBTYPE_ARM_6)
osabi_seen_in_attached_dyld = GDB_OSABI_DARWINV6;
else if (s->dyld_mem_header.cpusubtype == BFD_MACH_O_CPU_SUBTYPE_ARM_7)
osabi_seen_in_attached_dyld = GDB_OSABI_DARWINV7;
else if (s->dyld_mem_header.cpusubtype == BFD_MACH_O_CPU_SUBTYPE_ARM_7F)
osabi_seen_in_attached_dyld = GDB_OSABI_DARWINV7F;
else if (s->dyld_mem_header.cpusubtype == BFD_MACH_O_CPU_SUBTYPE_ARM_7K)
osabi_seen_in_attached_dyld = GDB_OSABI_DARWINV7K;
else
osabi_seen_in_attached_dyld = GDB_OSABI_DARWIN;
}
#endif
}
s->dyld_addr = dyld_address;
macosx_dyld_update (1);
if (s->dyld_addr == INVALID_ADDRESS || s->dyld_slide == INVALID_ADDRESS)
{
macosx_locate_dyld_static (s, &static_dyld_address);
if (static_dyld_address == INVALID_ADDRESS)
return 0;
s->dyld_addr = dyld_address;
s->dyld_minsyms_have_been_relocated = 1;
if (s->dyld_slide == INVALID_ADDRESS)
{
s->dyld_slide = dyld_address - static_dyld_address;
if (s->dyld_slide != 0)
{
s->dyld_minsyms_have_been_relocated = 0;
}
}
}
else
{
if (s->dyld_slide == 0)
s->dyld_minsyms_have_been_relocated = 1;
else
s->dyld_minsyms_have_been_relocated = 0;
}
macosx_init_addresses (s);
macosx_set_start_breakpoint (s, exec_bfd);
breakpoints_changed ();
return 1;
}
void
macosx_set_start_breakpoint (macosx_dyld_thread_status *s, bfd *exec_bfd)
{
struct macosx_dyld_thread_status *status = &macosx_dyld_status;
struct minimal_symbol *malloc_inited;
int changed_breakpoints = 0;
if (status->dyld_breakpoint == NULL)
{
status->dyld_breakpoint = create_solib_event_breakpoint
(status->dyld_notify);
changed_breakpoints = 1;
}
if (s->dyld_version == 1)
{
if (status->malloc_inited_breakpoint == NULL)
{
struct cleanup *free_adorned;
char *adorned_name = xmalloc (strlen (malloc_inited_callback) +
strlen (dyld_symbols_prefix) + 1);
free_adorned = make_cleanup (xfree, adorned_name);
strcpy (adorned_name, dyld_symbols_prefix);
strcat (adorned_name, malloc_inited_callback);
char *adorned_name_alt = xmalloc (strlen (malloc_inited_callback_alt)
+ strlen (dyld_symbols_prefix) + 1);
make_cleanup (xfree, adorned_name_alt);
strcpy (adorned_name_alt, dyld_symbols_prefix);
strcat (adorned_name_alt, malloc_inited_callback_alt);
malloc_inited = lookup_minimal_symbol (adorned_name, NULL, NULL);
if (malloc_inited == NULL)
malloc_inited = lookup_minimal_symbol (adorned_name_alt, NULL, NULL);
do_cleanups (free_adorned);
if (malloc_inited != NULL)
{
status->malloc_inited_breakpoint = create_solib_event_breakpoint
(SYMBOL_VALUE_ADDRESS (malloc_inited));
changed_breakpoints = 1;
}
else
{
warning ("Could not find malloc init callback function. "
"\nMake sure malloc is initialized before calling functions.");
macosx_set_malloc_inited (1);
}
}
}
if (changed_breakpoints)
breakpoints_changed ();
}
#if defined (TARGET_POWERPC)
static ULONGEST
FETCH_ARGUMENT (int i)
{
return read_register (3 + i);
}
#elif defined (TARGET_I386)
static ULONGEST
FETCH_ARGUMENT (int i)
{
if (gdbarch_osabi (current_gdbarch) == GDB_OSABI_DARWIN64)
{
int reg = 0;
switch (i)
{
case 0:
reg = AMD64_RDI_REGNUM;
break;
case 1:
reg = AMD64_RSI_REGNUM;
break;
case 2:
reg = AMD64_RDX_REGNUM;
break;
}
return read_register (reg);
}
else
{
CORE_ADDR stack = read_register (SP_REGNUM);
return read_memory_unsigned_integer (stack + (4 * (i + 1)), 4);
}
}
#elif defined (TARGET_ARM) // NGK XXX hack
static ULONGEST
FETCH_ARGUMENT (int i)
{
return read_register (i);
}
#else
#error "unknown architecture"
#endif
void
macosx_dyld_remove_libraries (struct macosx_dyld_thread_status *dyld_status,
struct dyld_objfile_entry *entries,
int num)
{
int i;
for (i = 0; i < num; i++)
{
struct dyld_objfile_entry *e;
int found_it = 0;
int k;
DYLD_ALL_OBJFILE_INFO_ENTRIES (&dyld_status->current_info, e, k)
{
if (dyld_libraries_compatible (&dyld_status->path_info, e, &entries[i]))
{
if (e->objfile)
{
tell_breakpoints_objfile_removed (e->objfile);
tell_objc_msgsend_cacher_objfile_changed (e->objfile);
}
if (ui_out_is_mi_like_p (uiout))
{
struct cleanup *notify_cleanup;
notify_cleanup = make_cleanup_ui_out_notify_begin_end (uiout,
"shlibs-removed");
dyld_print_entry_info (e, k, 0);
do_cleanups (notify_cleanup);
}
dyld_remove_objfile (e);
dyld_objfile_entry_clear (e);
found_it = 1;
break;
}
}
if (!found_it)
warning ("Tried to remove a non-existent library: %s",
entries[i].dyld_name ? entries[i].dyld_name : "<unknown>");
}
}
void
macosx_dyld_add_libraries (struct macosx_dyld_thread_status *dyld_status,
struct dyld_objfile_entry *entries,
int num)
{
int i;
int shlibnum;
static int timer_id = -1;
struct cleanup *timer_cleanup = NULL;
if (maint_use_timers)
timer_cleanup = start_timer (&timer_id, "macosx_dyld_add_libraries", "");
for (i = 0; i < num; i++)
{
struct dyld_objfile_entry *pentry;
dyld_merge_shlib (dyld_status, &dyld_status->path_info,
&dyld_status->current_info, &entries[i]);
dyld_prune_shlib (&dyld_status->path_info,
&dyld_status->current_info, &entries[i]);
pentry = dyld_objfile_entry_alloc (&dyld_status->current_info);
*pentry = entries[i];
}
dyld_update_shlibs (&dyld_status->path_info, &dyld_status->current_info);
if (! ui_out_is_mi_like_p (uiout))
{
if (maint_use_timers)
do_cleanups (timer_cleanup);
return;
}
for (i = 0; i < num; i++)
{
struct dyld_objfile_entry *entry;
int j;
DYLD_ALL_OBJFILE_INFO_ENTRIES (&dyld_status->current_info, entry, j)
if (dyld_libraries_compatible (&dyld_status->path_info, entry,
&entries[i]))
{
CHECK_FATAL (dyld_entry_shlib_num (&dyld_status->current_info,
entry, &shlibnum) == 0);
struct cleanup *notify_cleanup;
notify_cleanup = make_cleanup_ui_out_notify_begin_end (uiout,
"shlibs-added");
dyld_print_entry_info (entry, shlibnum, 0);
if (ui_out_is_mi_like_p (uiout))
{
struct timeval t;
make_cleanup_ui_out_tuple_begin_end (uiout, "time");
gettimeofday (&t, NULL);
ui_out_field_fmt (uiout, "now", "%u.%06u",
(unsigned int) t.tv_sec, (unsigned int) t.tv_usec);
}
do_cleanups (notify_cleanup);
if (entry->objfile != NULL)
breakpoint_re_set (entry->objfile);
}
}
if (maint_use_timers)
do_cleanups (timer_cleanup);
}
int
macosx_solib_add (const char *filename, int from_tty,
struct target_ops *targ, int loadsyms)
{
struct macosx_dyld_thread_status *dyld_status = NULL;
#if WITH_CFM
struct macosx_cfm_thread_status *cfm_status = NULL;
#endif
int libraries_changed = 0;
int notify = 0;
int started_dyld = 0;
int started_cfm = 0;
dyld_status = &macosx_dyld_status;
#if WITH_CFM
CHECK_FATAL (macosx_status != NULL);
cfm_status = &macosx_status->cfm_status;
#endif
started_dyld = macosx_dyld_init (dyld_status, exec_bfd);
#if WITH_CFM
started_cfm = macosx_cfm_init (cfm_status);
#endif
if (dyld_status->dyld_addr == INVALID_ADDRESS)
return 0;
if (dyld_status->dyld_version >= 2
&& macosx_get_malloc_inited () != 1
&& dyld_status->dyld_image_infos != INVALID_ADDRESS)
{
struct dyld_raw_infos info;
dyld_read_raw_infos (dyld_status->dyld_image_infos, &info);
dyld_status->libsystem_initialized = info.libsystem_initialized;
macosx_set_malloc_inited (dyld_status->libsystem_initialized);
}
if (started_dyld || started_cfm)
{
libraries_changed = macosx_dyld_update (0);
notify = libraries_changed && dyld_stop_on_shlibs_updated;
}
else if (read_pc () == 0)
{
libraries_changed = macosx_dyld_update (0);
notify = libraries_changed && dyld_stop_on_shlibs_updated;
}
#if WITH_CFM
else if (cfm_status->cfm_breakpoint != NULL
&& cfm_status->cfm_breakpoint->loc->address == read_pc ())
{
libraries_changed = macosx_dyld_update (0);
notify = libraries_changed && dyld_stop_on_shlibs_updated;
}
#endif
else if (dyld_status->malloc_inited_breakpoint != NULL
&& dyld_status->malloc_inited_breakpoint->loc->address == read_pc ())
{
macosx_set_malloc_inited (1);
}
else if (dyld_status->dyld_breakpoint != NULL
&& dyld_status->dyld_breakpoint->loc->address == read_pc ())
{
static struct dyld_raw_info *rinfo = NULL;
static struct dyld_objfile_entry *tinfo = NULL;
static unsigned int maxent = 0;
unsigned int i;
unsigned int j;
int mode = FETCH_ARGUMENT (0);
int count = FETCH_ARGUMENT (1);
CORE_ADDR addr = FETCH_ARGUMENT (2);
static int breakpoint_timer = -1;
struct cleanup *timer_cleanup = NULL;
num_macosx_solib_add_dyld_objfile_entries = 0;
macosx_solib_add_dyld_objfile_entries = NULL;
if (count > maxent)
{
maxent = (count >= 16) ? count : 16;
rinfo = xrealloc (rinfo, maxent * sizeof (struct dyld_raw_info));
tinfo = xrealloc (tinfo, maxent * sizeof (struct dyld_objfile_entry));
}
macosx_solib_add_dyld_objfile_entries = tinfo;
dyld_info_read_raw_data (addr, count, rinfo);
j = 0;
for (i = 0; i < count; i++)
{
dyld_objfile_entry_clear (&tinfo[j]);
tinfo[j].allocated = 1;
tinfo[j].reason = dyld_reason_dyld;
tinfo[j].dyld_valid = 1;
num_macosx_solib_add_dyld_objfile_entries = j + 1;
if (dyld_info_process_raw (dyld_status, &tinfo[j], rinfo[i].name,
rinfo[i].modtime, rinfo[i].addr) == 1)
j++;
}
if (mode == 0)
{
macosx_dyld_add_libraries (& macosx_dyld_status, tinfo, j);
}
else if (mode == 1)
{
macosx_dyld_remove_libraries (dyld_status, tinfo, j);
}
else
{
internal_error (__FILE__, __LINE__, "Wrong mode value %d from dyld notification.", mode);
}
#if WITH_CFM
macosx_cfm_init (cfm_status);
#endif
libraries_changed = 1;
if (maint_use_timers)
timer_cleanup = start_timer (&breakpoint_timer, "shlib-bkpt-reset", "");
breakpoint_update ();
objc_clear_caches ();
if (maint_use_timers)
do_cleanups (timer_cleanup);
notify = libraries_changed && dyld_stop_on_shlibs_updated;
}
else if (objc_handle_update (read_pc ()) == 1)
{
}
else if (dyld_status->dyld_breakpoint != NULL || core_bfd)
{
libraries_changed = macosx_dyld_update (0);
notify = libraries_changed && dyld_stop_on_shlibs_updated;
}
else
{
if (target_is_remote ())
{
printf_filtered ("Communication packet log leading up to internal error:\n");
dump_packets_command ("", 0);
printf_filtered ("\n\nPlease include all of the above log output in your bug report.\n");
printf_filtered ("\n");
}
internal_error (__FILE__, __LINE__,
"unrecognized shared library breakpoint, stopped at 0x%s",
paddr_nz (read_pc()));
notify = 0;
}
return notify;
}
void
macosx_dyld_thread_init (macosx_dyld_thread_status *s)
{
macosx_clear_start_breakpoint ();
s->dyld_name = NULL;
s->dyld_addr = INVALID_ADDRESS;
s->dyld_slide = INVALID_ADDRESS;
s->dyld_minsyms_have_been_relocated = 0;
s->dyld_image_infos = INVALID_ADDRESS;
s->dyld_version = 0;
s->dyld_breakpoint = NULL;
s->malloc_inited_breakpoint = NULL;
dyld_zero_path_info (&s->path_info);
}
void
macosx_dyld_thread_clear (macosx_dyld_thread_status *s)
{
if (s->dyld_name)
xfree ((char *) s->dyld_name);
if (s->path_info.framework_path != NULL)
xfree (s->path_info.framework_path);
if (s->path_info.library_path != NULL)
xfree (s->path_info.library_path);
if (s->path_info.fallback_framework_path != NULL)
xfree (s->path_info.fallback_framework_path);
if (s->path_info.fallback_library_path != NULL)
xfree (s->path_info.fallback_library_path);
if (s->path_info.image_suffix != NULL)
xfree (s->path_info.image_suffix);
if (s->path_info.insert_libraries != NULL)
xfree (s->path_info.insert_libraries);
macosx_clear_start_breakpoint ();
macosx_dyld_thread_init (s);
}
void
macosx_add_shared_symbol_files (void)
{
macosx_dyld_update (0);
}
void
macosx_init_dyld_from_core (void)
{
struct dyld_objfile_info *info;
struct dyld_objfile_entry *e;
struct target_ops *target;
int i;
if (!inferior_auto_start_dyld_flag)
return;
info = &macosx_dyld_status.current_info;
target = &exec_ops;
DYLD_ALL_OBJFILE_INFO_ENTRIES (info, e, i)
{
dyld_remove_objfile (e);
dyld_objfile_entry_clear (e);
}
macosx_dyld_mourn_inferior ();
macosx_dyld_thread_clear (&macosx_dyld_status);
reinitialize_objc ();
if (target->to_sections != NULL)
{
xfree (target->to_sections);
target->to_sections = target->to_sections_end = NULL;
}
macosx_solib_add (NULL, 0, NULL, 0);
}
void
macosx_init_dyld (struct macosx_dyld_thread_status *s,
struct objfile *o, bfd *abfd)
{
struct dyld_objfile_entry *e;
int i;
struct dyld_objfile_info previous_info;
static int timer_id = -1;
struct cleanup *timer_cleanup = NULL;
if (maint_use_timers)
timer_cleanup = start_timer (&timer_id, "macosx_init_dyld", "");
DYLD_ALL_OBJFILE_INFO_ENTRIES (&s->current_info, e, i)
if (e->reason & dyld_reason_executable_mask)
dyld_objfile_entry_clear (e);
dyld_init_paths (&s->path_info);
dyld_objfile_info_init (&previous_info);
if (pre_slide_libraries_flag && s->pre_run_memory_map == NULL && abfd != NULL)
s->pre_run_memory_map = create_pre_run_memory_map (abfd);
dyld_objfile_info_copy (&previous_info, &s->current_info);
dyld_objfile_info_free (&s->current_info);
if (o != NULL)
{
char *objfile_name = NULL;
struct dyld_objfile_entry *e;
if (bfd_get_filename (o->obfd) != NULL)
{
char buf[PATH_MAX];
if (realpath (bfd_get_filename (o->obfd), buf) != NULL)
{
objfile_name = xstrdup (buf);
}
else
objfile_name = bfd_get_filename (o->obfd);
}
e = dyld_objfile_entry_alloc (&s->current_info);
e->text_name_valid = 1;
e->reason = dyld_reason_executable;
e->objfile = o;
e->load_flag = o->symflags;
e->text_name = objfile_name;
e->loaded_from_memory = 0;
e->loaded_name = e->text_name;
e->loaded_addr = 0;
e->loaded_addrisoffset = 1;
}
if (dyld_preload_libraries_flag)
{
dyld_add_inserted_libraries (&s->current_info, &s->path_info);
if (abfd != NULL)
{
dyld_add_image_libraries (&s->current_info, abfd);
}
}
dyld_merge_shlibs (s, &s->path_info, &previous_info, &s->current_info);
dyld_update_shlibs (&s->path_info, &s->current_info);
dyld_objfile_info_free (&previous_info);
s->state = dyld_initialized;
if (maint_use_timers)
do_cleanups (timer_cleanup);
}
enum gdb_osabi
macosx_get_osabi_from_dyld_entry (bfd *abfd)
{
if (abfd == NULL)
return GDB_OSABI_UNKNOWN;
const char *bfd_name = bfd_get_filename (abfd);
if (bfd_name == NULL)
return GDB_OSABI_UNKNOWN;
struct macosx_dyld_thread_status *status = &macosx_dyld_status;
const struct dyld_path_info *d = &status->path_info;
struct dyld_objfile_entry *e;
int i;
enum gdb_osabi bfd_osabi = GDB_OSABI_UNKNOWN;
const char *entry_name = NULL;
for (i = num_macosx_solib_add_dyld_objfile_entries - 1; i >= 0; i--)
{
e = &macosx_solib_add_dyld_objfile_entries[i];
entry_name = dyld_entry_filename (e, d, DYLD_ENTRY_FILENAME_LOADED);
if (entry_name != NULL && strcmp (entry_name, bfd_name) == 0)
{
bfd_osabi = dyld_objfile_entry_osabi (e);
break;
}
}
if (bfd_osabi <= GDB_OSABI_UNKNOWN)
{
DYLD_ALL_OBJFILE_INFO_ENTRIES (&status->current_info, e, i)
{
entry_name = dyld_entry_filename (e, d, DYLD_ENTRY_FILENAME_LOADED);
if (entry_name != NULL)
{
const char *alt_entry_name = dyld_fix_path (entry_name);
if (strcmp (entry_name, bfd_name) == 0
|| strcmp (alt_entry_name, bfd_name) == 0)
{
bfd_osabi = dyld_objfile_entry_osabi (e);
xfree (alt_entry_name);
break;
}
xfree (alt_entry_name);
}
}
}
if (bfd_osabi >= GDB_OSABI_UNKNOWN)
dyld_debug ("macosx_get_osabi_from_dyld_entry(%s) returned osabi = %s\n",
bfd_name, gdbarch_osabi_name (bfd_osabi));
return bfd_osabi;
}
void
macosx_init_dyld_symfile (struct objfile *o, bfd *abfd)
{
macosx_init_dyld (&macosx_dyld_status, o, abfd);
}
static void
dyld_cache_purge_command (char *exp, int from_tty)
{
dyld_purge_cached_libraries (&macosx_dyld_status.current_info);
}
struct section_offsets *
get_sectoffs_for_shared_cache_dylib (struct dyld_objfile_entry *entry,
CORE_ADDR header_addr)
{
int cur_section;
struct cleanup *cleanup;
bfd *this_bfd = entry->abfd;
struct section_offsets *sect_offsets;
struct bfd_section *this_sect;
int i;
struct section_addr_info *sect_addrs;
sect_addrs = get_section_addresses_for_macho_in_memory (header_addr);
if (sect_addrs == NULL)
return NULL;
cleanup = make_cleanup_free_section_addr_info (sect_addrs);
CORE_ADDR slide_within_shared_cache = 0;
for (i = 0; i < sect_addrs->num_sections; i++)
{
if (strcmp ("LC_SEGMENT.__TEXT", sect_addrs->other[i].name) == 0)
{
slide_within_shared_cache = header_addr - sect_addrs->other[i].addr;
break;
}
}
for (i = 0; i < sect_addrs->num_sections; i++)
sect_addrs->other[i].addr += slide_within_shared_cache;
sect_offsets = (struct section_offsets *)
xmalloc (SIZEOF_N_SECTION_OFFSETS (this_bfd->section_count));
memset (sect_offsets, 0,
SIZEOF_N_SECTION_OFFSETS (this_bfd->section_count));
for (i = 0; i < sect_addrs->num_sections; i++)
{
if (sect_addrs->other[i].name == NULL
|| sect_addrs->other[i].name[0] == '\0'
|| sect_addrs->other[i].addr == 0)
continue;
for (this_sect = this_bfd->sections, cur_section = 0;
this_sect != NULL;
this_sect = this_sect->next, ++cur_section)
{
if (this_sect->name == NULL || this_sect->name[0] == '\0')
continue;
if (strcmp (sect_addrs->other[i].name, this_sect->name) == 0)
{
sect_offsets->offsets[cur_section] =
sect_addrs->other[i].addr - this_sect->vma;
}
}
}
do_cleanups (cleanup);
return sect_offsets;
}
static int
dyld_info_process_raw (struct macosx_dyld_thread_status *s,
struct dyld_objfile_entry *entry,
CORE_ADDR name, uint64_t modtime, CORE_ADDR header_addr)
{
char *namebuf = NULL;
int errno, i;
CORE_ADDR curpos;
CORE_ADDR intended_loadaddr;
struct load_command cmd;
struct dylib_command dcmd;
bfd *this_bfd = NULL;
struct cleanup *override_trust_readonly;
int old_trust_readonly;
old_trust_readonly = set_trust_readonly (0);
override_trust_readonly = make_cleanup (set_trust_readonly_cleanup,
(void *) old_trust_readonly);
target_read_mach_header (header_addr, &entry->mem_header);
switch (entry->mem_header.filetype)
{
case 0:
return 0;
case MH_EXECUTE:
case MH_DYLIB:
case MH_DYLINKER:
case MH_BUNDLE:
case MH_KEXT_BUNDLE:
break;
case MH_FVMLIB:
case MH_PRELOAD:
return 0;
default:
warning
("Ignored unknown object module at 0x%s with type 0x%x\n",
paddr_nz (header_addr), entry->mem_header.filetype);
do_cleanups (override_trust_readonly);
return 0;
}
target_read_string (name, &namebuf, 1024, &errno);
if (errno != 0)
{
xfree (namebuf);
namebuf = NULL;
}
if (namebuf == NULL)
{
namebuf = xmalloc (PATH_MAX);
curpos = header_addr + target_get_mach_header_size (&entry->mem_header);
for (i = 0; i < entry->mem_header.ncmds; i++)
{
if (target_read_load_command (curpos, &cmd) != 0)
break;
if (cmd.cmd == LC_ID_DYLIB)
{
if (target_read_dylib_command (curpos, &dcmd) == 0)
target_read_memory (curpos + dcmd.dylib.name.offset,
(gdb_byte *) namebuf,
PATH_MAX);
break;
}
curpos += cmd.cmdsize;
}
}
if (namebuf != NULL)
{
char buf[PATH_MAX];
char *resolved = NULL;
resolved = dyld_fix_path (namebuf);
xfree (namebuf);
namebuf = resolved;
resolved = realpath (namebuf, buf);
if (resolved == NULL)
resolved = namebuf;
entry->dyld_name = xstrdup (resolved);
entry->dyld_name_valid = 1;
}
dyld_debug ("dyld_info_process_raw () called for '%s'\n", entry->dyld_name);
entry->dyld_addr = header_addr;
if (core_bfd)
{
entry->dyld_valid = 1;
entry->loaded_addr = header_addr;
entry->loaded_addrisoffset = 0;
}
intended_loadaddr = INVALID_ADDRESS;
if (entry->dyld_name)
entry->dyld_valid = 1;
if (dyld_objfile_entry_in_shared_cache (entry))
{
if (entry->dyld_name != NULL)
{
struct bfd_section *this_sect = NULL;
struct section_offsets *sect_offsets = NULL;
#ifdef ALWAYS_READ_FROM_MEMORY
int old_always_read = dyld_always_read_from_memory_flag;
dyld_always_read_from_memory_flag = 1;
entry->dyld_valid = 1;
entry->loaded_addr = header_addr;
entry->loaded_addrisoffset = 0;
#endif
dyld_load_library (&(s->path_info), entry);
#ifdef ALWAYS_READ_FROM_MEMORY
dyld_always_read_from_memory_flag = old_always_read;
#endif
this_bfd = entry->abfd;
if (this_bfd == NULL)
{
entry->dyld_valid = 1;
entry->loaded_addr = header_addr;
entry->loaded_addrisoffset = 0;
dyld_load_library_from_memory (&(s->path_info), entry, 1);
this_bfd = entry->abfd;
if (this_bfd == NULL)
error ("Could not read in on disk or the memory version of library \"%s\".", entry->dyld_name);
}
if (macosx_bfd_is_in_memory (this_bfd))
{
int cur_section;
sect_offsets = (struct section_offsets *)
xmalloc (SIZEOF_N_SECTION_OFFSETS (this_bfd->section_count));
memset (sect_offsets, 0,
SIZEOF_N_SECTION_OFFSETS (this_bfd->section_count));
CORE_ADDR process_shared_cache_slide = 0;
intended_loadaddr = header_addr;
for (this_sect = this_bfd->sections;
this_sect != NULL;
this_sect = this_sect->next)
{
if (this_sect->name && strcmp (this_sect->name, "LC_SEGMENT.__TEXT") == 0)
{
process_shared_cache_slide = header_addr - this_sect->vma;
intended_loadaddr = this_sect->vma;
break;
}
}
cur_section = 0;
for (this_sect = this_bfd->sections; this_sect != NULL;
this_sect = this_sect->next)
{
if (!objfile_keeps_section (this_bfd, this_sect))
continue;
sect_offsets->offsets[cur_section++] = process_shared_cache_slide;
}
entry->dyld_section_offsets = sect_offsets;
}
else
{
entry->dyld_section_offsets =
get_sectoffs_for_shared_cache_dylib (entry, header_addr);
}
if (this_bfd != NULL)
{
asection *text_sect;
text_sect = bfd_get_section_by_name (this_bfd,
"LC_SEGMENT.__TEXT");
if (text_sect != NULL)
intended_loadaddr = bfd_section_vma (this_bfd, text_sect);
else
warning ("Couldn't find __TEXT segment in disk version of "
" library \"%s\" for library in shared cache at %s",
entry->dyld_name, paddr_nz (header_addr));
}
else
{
error ("Couldn't find the on disk version of library \"%s\" "
"for library in shared cache at %s", entry->dyld_name,
paddr_nz (header_addr));
}
}
else
{
warning ("Can't read symbols for shared cache image at address %s",
paddr_nz (header_addr));
}
}
else
{
struct bfd_section *this_sect;
struct section_offsets *sect_offsets;
int cur_section;
entry->dyld_slide = INVALID_ADDRESS;
dyld_load_library (&(s->path_info), entry);
if (!entry->loaded_error && entry->abfd)
{
CORE_ADDR rigid_slide;
this_bfd = entry->abfd;
sect_offsets = (struct section_offsets *)
xmalloc (SIZEOF_N_SECTION_OFFSETS (this_bfd->section_count));
memset (sect_offsets, 0,
SIZEOF_N_SECTION_OFFSETS (this_bfd->section_count));
for (this_sect = this_bfd->sections;
this_sect != NULL;
this_sect = this_sect->next)
{
if (!objfile_keeps_section (this_bfd, this_sect))
continue;
if (strcmp (this_sect->name, TEXT_SEGMENT_NAME) == 0)
{
intended_loadaddr = this_sect->vma;
break;
}
}
rigid_slide = header_addr - intended_loadaddr;
cur_section = 0;
for (this_sect = this_bfd->sections;
this_sect != NULL;
this_sect = this_sect->next)
{
if (!objfile_keeps_section (this_bfd, this_sect))
continue;
sect_offsets->offsets[cur_section++] = rigid_slide;
}
entry->dyld_section_offsets = sect_offsets;
}
}
if (intended_loadaddr == INVALID_ADDRESS)
entry->dyld_slide = 0;
else
entry->dyld_slide = header_addr - intended_loadaddr;
entry->dyld_valid = 1;
switch (entry->mem_header.filetype)
{
case MH_EXECUTE:
{
entry->reason = dyld_reason_executable;
if (symfile_objfile != NULL)
{
entry->objfile = symfile_objfile;
if (core_bfd == NULL)
{
entry->loaded_from_memory = 0;
entry->loaded_addr = 0;
entry->loaded_addrisoffset = 1;
}
entry->loaded_name = symfile_objfile->name;
}
break;
}
case MH_DYLIB:
entry->reason = dyld_reason_dyld;
break;
case MH_DYLINKER:
case MH_BUNDLE:
case MH_KEXT_BUNDLE:
entry->reason = dyld_reason_dyld;
break;
default:
internal_error (__FILE__, __LINE__,
"Unknown object module at 0x%s (offset 0x%s) with type 0x%x\n",
paddr_nz (header_addr), paddr_nz (entry->dyld_slide),
entry->mem_header.filetype);
}
do_cleanups (override_trust_readonly);
return 1;
}
struct dyld_all_image_infos_offsets
{
int version;
int infoArrayCount;
int infoArray;
int notification;
int processDetachedFromSharedRegion;
int libSystemInitialized;
int dyldImageLoadAddress;
int jitInfo;
int dyldVersion;
int errorMessage;
int terminationFlags;
int coreSymbolicationShmPage;
int systemOrderFlag;
int uuidArrayCount;
int uuidArray;
int dyldAllImageInfosAddress;
int initialImageCount;
int errorKind;
int errorClientOfDylibPath;
int errorTargetDylibPath;
int errorSymbol;
int sharedCacheSlide;
};
static void
dyld_read_raw_infos (CORE_ADDR addr, struct dyld_raw_infos *info)
{
gdb_assert (addr != INVALID_ADDRESS);
int wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
int p = wordsize;
int b = 1;
int i = 4;
struct dyld_all_image_infos_offsets offsets =
{ .version = 0,
.infoArrayCount = i,
.infoArray = i + i,
.notification = i + i + p,
.processDetachedFromSharedRegion = i + i + p + p,
.libSystemInitialized = i + i + p + p + b,
.dyldImageLoadAddress = i + i + p + p + b + b + (p - 2 * b),
.jitInfo = i + i + p + p + b + b + (p - 2 * b) + p,
.dyldVersion = i + i + p + p + b + b + (p - 2 * b) + p + p,
.errorMessage = i + i + p + p + b + b + (p - 2 * b) + p + p + p,
.terminationFlags = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p,
.coreSymbolicationShmPage = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p,
.systemOrderFlag = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p,
.uuidArrayCount = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p,
.uuidArray = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p,
.dyldAllImageInfosAddress = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p,
.initialImageCount = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p + p,
.errorKind = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p + p + p,
.errorClientOfDylibPath = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p + p + p + p,
.errorTargetDylibPath = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p + p + p + p + p,
.errorSymbol = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p + p + p + p + p + p,
.sharedCacheSlide = i + i + p + p + b + b + (p - 2 * b) + p + p + p + p + p + p + p + p + p + p + p + p + p + p + p,
};
uint8_t version_buf[4];
int version;
int image_infos_size;
target_read_memory (addr, version_buf, 4);
version = extract_unsigned_integer (version_buf, 4);
if (version >= 9)
image_infos_size = offsets.dyldAllImageInfosAddress + p;
else if (version >= 2)
image_infos_size = offsets.jitInfo;
else
image_infos_size = offsets.libSystemInitialized;
gdb_byte *buf = (gdb_byte *) alloca (image_infos_size);
target_read_memory (addr, buf, image_infos_size);
info->version = extract_unsigned_integer (buf, 4);
info->num_info = extract_unsigned_integer (buf + offsets.infoArrayCount, 4);
info->info_array = extract_unsigned_integer (buf + offsets.infoArray, wordsize);
info->dyld_notify = extract_unsigned_integer (buf + offsets.notification, wordsize);
#if defined (TARGET_ARM)
info->dyld_notify = info->dyld_notify & 0xfffffffffffffffeull;
#endif
info->process_detached_from_shared_region = extract_unsigned_integer
(buf + offsets.processDetachedFromSharedRegion, 1);
info->libsystem_initialized = extract_unsigned_integer
(buf + offsets.libSystemInitialized, 1);
info->dyld_actual_load_address = extract_unsigned_integer
(buf + offsets.dyldImageLoadAddress, wordsize);
CORE_ADDR adjustment = INVALID_ADDRESS;
if (info->version >= 9)
{
CORE_ADDR dyld_image_infos_addr;
dyld_image_infos_addr = extract_unsigned_integer
(buf + offsets.dyldAllImageInfosAddress, wordsize);
if (dyld_image_infos_addr != addr)
{
adjustment = addr - dyld_image_infos_addr;
}
}
if (adjustment != INVALID_ADDRESS
&& dyld_starts_here_p (info->dyld_actual_load_address + adjustment))
{
if (info->info_array != 0 && info->info_array != INVALID_ADDRESS)
info->info_array += adjustment;
if (info->dyld_notify != 0 && info->dyld_notify != INVALID_ADDRESS)
info->dyld_notify += adjustment;
if (info->dyld_actual_load_address != 0 && info->dyld_actual_load_address != INVALID_ADDRESS)
info->dyld_actual_load_address += adjustment;
}
if (dyld_starts_here_p (info->dyld_actual_load_address))
{
info->dyld_intended_load_address = find_text_segment_load_address
(info->dyld_actual_load_address);
}
else
{
info->dyld_intended_load_address = INVALID_ADDRESS;
}
}
static void
dyld_info_read_raw_data (CORE_ADDR addr, int num, struct dyld_raw_info *rinfo)
{
gdb_byte *buf;
int i;
int size_of_dyld_raw_info_in_inferior;
int wordsize = gdbarch_tdep (current_gdbarch)->wordsize;
size_of_dyld_raw_info_in_inferior = wordsize * 3;
if (num == 0)
return;
buf = xmalloc (sizeof (struct dyld_raw_info) * num);
target_read_memory (addr, buf, num * size_of_dyld_raw_info_in_inferior);
for (i = 0; i < num; i++)
{
gdb_byte *ebuf = buf + (i * size_of_dyld_raw_info_in_inferior);
rinfo[i].addr = extract_unsigned_integer (ebuf, wordsize);
ebuf += wordsize;
rinfo[i].name = extract_unsigned_integer (ebuf, wordsize);
ebuf += wordsize;
rinfo[i].modtime = extract_unsigned_integer (ebuf, wordsize);
}
xfree (buf);
}
static void
dyld_info_read_raw (struct macosx_dyld_thread_status *status,
struct dyld_raw_info **rinfo, int *rninfo)
{
struct dyld_raw_infos info;
struct dyld_raw_info *ninfo;
dyld_read_raw_infos (status->dyld_image_infos, &info);
if (info.version >= 2)
{
status->libsystem_initialized = info.libsystem_initialized;
macosx_set_malloc_inited (status->libsystem_initialized);
}
ninfo = xmalloc (info.num_info * sizeof (struct dyld_raw_info));
dyld_info_read_raw_data (info.info_array, info.num_info, ninfo);
*rinfo = ninfo;
*rninfo = info.num_info;
}
static void
dyld_info_read (struct macosx_dyld_thread_status *status,
struct dyld_objfile_info *info, int dyldonly)
{
struct dyld_raw_info *rinfo = NULL;
int reserved = -1;
int nrinfo = 0;
int i = 0;
if (!dyldonly)
{
struct dyld_objfile_entry *entry = dyld_objfile_entry_alloc (info);
reserved = entry - info->entries;
}
if (status->dyld_addr != INVALID_ADDRESS)
{
const char *dyld_name = NULL;
struct dyld_objfile_entry *entry = NULL;
char buf[PATH_MAX];
entry = dyld_objfile_entry_alloc (info);
dyld_name =
(status->dyld_name != NULL) ? status->dyld_name : "/usr/lib/dyld";
if (realpath (dyld_name, buf) != NULL)
dyld_name = buf;
char *new_dyld_name = dyld_fix_path (dyld_name);
if (file_exists_p (new_dyld_name))
{
entry->dyld_name = new_dyld_name;
}
else
{
xfree (new_dyld_name);
entry->dyld_name = xstrdup (dyld_name);
}
entry->dyld_name_valid = 1;
entry->prefix = dyld_symbols_prefix;
entry->dyld_addr = status->dyld_addr;
if (status->dyld_slide != INVALID_ADDRESS)
entry->dyld_slide = status->dyld_slide;
else
entry->dyld_slide = 0;
entry->dyld_valid = 1;
entry->reason = dyld_reason_dyld;
}
if (dyldonly)
return;
if (status->dyld_image_infos != INVALID_ADDRESS)
dyld_info_read_raw (status, &rinfo, &nrinfo);
else
{
rinfo = NULL;
nrinfo = 0;
}
for (i = 0; i < nrinfo; i++)
{
struct dyld_objfile_entry tentry;
struct dyld_objfile_entry *pentry = NULL;
dyld_objfile_entry_clear (&tentry);
tentry.allocated = 1;
tentry.reason = dyld_reason_dyld;
if (dyld_info_process_raw
(status, &tentry, rinfo[i].name, rinfo[i].modtime, rinfo[i].addr) == 1)
{
if ((tentry.reason & dyld_reason_executable_mask) && reserved >= 0)
{
pentry = &info->entries[reserved];
reserved = -1;
}
else
{
pentry = dyld_objfile_entry_alloc (info);
}
*pentry = tentry;
}
}
xfree (rinfo);
if (reserved >= 0)
dyld_objfile_entry_clear (&info->entries[reserved]);
}
int
macosx_dyld_update (int dyldonly)
{
#if WITH_CFM
int ret;
#endif
int libraries_changed;
struct dyld_objfile_info previous_info, saved_info, *current_info;
struct macosx_dyld_thread_status *status;
static int timer_id = -1;
struct cleanup *timer_cleanup = NULL;
if (maint_use_timers)
timer_cleanup = start_timer (&timer_id, "macosx_dyld_update", "");
status = &macosx_dyld_status;
current_info = &status->current_info;
dyld_objfile_info_init (&previous_info);
dyld_objfile_info_init (&saved_info);
dyld_objfile_info_copy (&previous_info, current_info);
dyld_objfile_info_copy (&saved_info, &previous_info);
dyld_objfile_info_free (current_info);
dyld_objfile_info_init (current_info);
dyld_info_read (status, current_info, dyldonly);
#if WITH_CFM
CHECK_FATAL (macosx_status != NULL);
if (inferior_auto_start_cfm_flag)
ret = cfm_update (macosx_status->task, current_info);
#endif
dyld_merge_shlibs (status, &status->path_info, &previous_info, current_info);
dyld_update_shlibs (&status->path_info, current_info);
if (dyld_filter_events_flag)
{
libraries_changed = dyld_objfile_info_compare (&saved_info, current_info);
}
else
{
libraries_changed = 1;
}
dyld_objfile_info_free (&saved_info);
dyld_objfile_info_free (&previous_info);
if (ui_out_is_mi_like_p (uiout) && libraries_changed)
{
struct cleanup *notify_cleanup;
notify_cleanup =
make_cleanup_ui_out_notify_begin_end (uiout, "shlibs-updated");
do_cleanups (notify_cleanup);
}
#if WITH_CFM
macosx_cfm_init (&macosx_status->cfm_status);
#endif
objc_init_trampoline_observer ();
objc_init_runtime_version ();
if (maint_use_timers)
do_cleanups (timer_cleanup);
return libraries_changed;
}
void
macosx_dyld_mourn_inferior (void)
{
struct dyld_objfile_entry *e;
int i;
struct macosx_dyld_thread_status *status = &macosx_dyld_status;
DYLD_ALL_OBJFILE_INFO_ENTRIES (&status->current_info, e, i)
{
e->dyld_addr = 0;
e->dyld_slide = 0;
e->dyld_length = 0;
e->dyld_valid = 0;
e->pre_run_slide_addr_valid = 0;
#if WITH_CFM
e->cfm_container = 0;
#endif
if (e->reason == dyld_reason_dyld)
e->reason = dyld_reason_init;
if (e->text_name == NULL && e->dyld_name != NULL)
e->text_name = e->dyld_name;
e->dyld_name = NULL;
}
int removed_memory_objfiles = 0;
DYLD_ALL_OBJFILE_INFO_ENTRIES (&status->current_info, e, i)
{
if (e->objfile && e->objfile->obfd
&& bfd_mach_o_in_shared_cached_memory (e->objfile->obfd))
{
continue;
}
if (e->objfile && macosx_bfd_is_in_memory (e->objfile->obfd))
{
dyld_remove_objfile (e);
dyld_objfile_entry_clear (e);
removed_memory_objfiles = 1;
}
}
if (removed_memory_objfiles)
dyld_objfile_info_pack (&status->current_info);
free_pre_run_memory_map (status->pre_run_memory_map);
status->pre_run_memory_map = NULL;
}
static void
macosx_dyld_update_command (char *args, int from_tty)
{
macosx_dyld_update (0);
macosx_init_dyld (&macosx_dyld_status, symfile_objfile, exec_bfd);
}
static void
map_shlib_numbers (char *args,
void (*function) (struct dyld_path_info *,
struct dyld_objfile_entry *,
struct objfile *,
int index,
const char *param),
struct dyld_path_info *d, struct dyld_objfile_info *info)
{
char *p, *p1, *val;
char **argv;
int num, match;
struct cleanup *cleanups;
if (args == 0)
error_no_arg ("one or more shlib numbers");
p = args;
while (isspace (*p) && (*p != '\0'))
p++;
if (strncmp (p, "all ", 4) == 0)
p += 4;
else
{
for (;;)
{
while (isspace (*p) && (*p != '\0'))
p++;
if (!isdigit (*p))
break;
while ((!isspace (*p)) && (*p != '\0'))
p++;
}
}
val = p;
argv = buildargv (val);
if (argv == NULL)
error ("no argument provided");
cleanups = make_cleanup_freeargv (argv);
if (argv[0] == NULL || argv[1] != NULL)
error ("exactly one argument must be provided");
gdb_assert (strlen (argv[0]) <= strlen (val));
strcpy (val, argv[0]);
if (*p != '\0' && p > args)
{
p[-1] = '\0';
}
p = args;
if (strcmp (p, "all") == 0)
{
struct dyld_objfile_entry *e;
unsigned int n;
DYLD_ALL_OBJFILE_INFO_ENTRIES (info, e, n)
(*function) (d, e, e->objfile, n + 1, val);
do_cleanups (cleanups);
return;
}
while (*p)
{
struct dyld_objfile_entry *e;
struct objfile *o;
int ret;
match = 0;
p1 = p;
num = get_number_or_range (&p);
if (num == 0)
{
warning ("bad shlib number at or near '%s'", p1);
do_cleanups (cleanups);
return;
}
ret = dyld_resolve_shlib_num (info, num, &e, &o);
if (ret < 0)
{
warning ("no shlib %d", num);
do_cleanups (cleanups);
return;
}
(*function) (d, e, o, num, val);
}
do_cleanups (cleanups);
}
static void
dyld_generic_command_with_helper (char *args,
int from_tty,
void (*function) (struct dyld_path_info *,
struct dyld_objfile_entry *,
struct objfile *,
int,
const char *param))
{
struct dyld_objfile_info original_info, modified_info;
static int timer_id = -1;
struct cleanup *timer_cleanup = NULL;
if (maint_use_timers)
timer_cleanup = start_timer (&timer_id, "dyld_generic_command_with_helper", "");
dyld_objfile_info_init (&original_info);
dyld_objfile_info_init (&modified_info);
dyld_objfile_info_copy (&original_info,
&macosx_dyld_status.current_info);
dyld_objfile_info_copy (&modified_info,
&macosx_dyld_status.current_info);
dyld_objfile_info_clear_objfiles (&modified_info);
map_shlib_numbers (args, function, &macosx_dyld_status.path_info,
&modified_info);
dyld_merge_shlibs (&macosx_dyld_status,
&macosx_dyld_status.path_info, &original_info,
&modified_info);
dyld_update_shlibs (&macosx_dyld_status.path_info, &modified_info);
dyld_objfile_info_copy (&macosx_dyld_status.current_info,
&modified_info);
dyld_objfile_info_free (&original_info);
dyld_objfile_info_free (&modified_info);
if (maint_use_timers)
do_cleanups (timer_cleanup);
}
static void
add_helper (struct dyld_path_info *d,
struct dyld_objfile_entry *e, struct objfile *o, int index, const char *arg)
{
if (e != NULL)
e->load_flag = OBJF_SYM_ALL;
}
static void
dyld_add_symbol_file_command (char *args, int from_tty)
{
dyld_generic_command_with_helper (args, from_tty, add_helper);
}
static void
remove_helper (struct dyld_path_info *d,
struct dyld_objfile_entry *e,
struct objfile *o, int index,
const char *arg)
{
if (e != NULL)
e->load_flag = OBJF_SYM_NONE | dyld_minimal_load_flag (d, e);
}
static void
dyld_remove_symbol_file_command (char *args, int from_tty)
{
dyld_generic_command_with_helper (args, from_tty, remove_helper);
}
int
dyld_objfile_set_load_state (struct objfile *o, int load_state)
{
struct dyld_objfile_entry *e;
int i, found_it = -1;
DYLD_ALL_OBJFILE_INFO_ENTRIES (&macosx_dyld_status.current_info, e, i)
if (e->objfile == o)
{
found_it = e->load_flag;
set_load_state_1 (e, &macosx_dyld_status.path_info, i + 1, load_state);
break;
}
return found_it;
}
static void
apply_load_rules_helper (struct dyld_path_info *d,
struct dyld_objfile_entry *e,
struct objfile *o,
int index,
const char *arg)
{
int load_state;
if (e == NULL)
return;
load_state =
dyld_default_load_flag (d, e) | dyld_minimal_load_flag (d, e);
set_load_state_1 (e, d, index, load_state);
}
static void
dyld_apply_load_rules_command (char *args, int from_tty)
{
map_shlib_numbers (args, apply_load_rules_helper,
&macosx_dyld_status.path_info,
&macosx_dyld_status.current_info);
re_enable_breakpoints_in_shlibs (0);
}
static void
set_load_state_1 (struct dyld_objfile_entry *e,
const struct dyld_path_info *d,
int index,
int load_state)
{
struct bfd *tmp_bfd;
enum dyld_reload_result state_change;
int old_pre_run_slide_addr_valid;
CORE_ADDR old_pre_run_slide_addr;
int old_image_addr_valid;
CORE_ADDR old_image_addr;
e->load_flag = load_state;
if (e->objfile == NULL)
{
dyld_load_library (d, e);
if (e->abfd)
dyld_load_symfile (e);
return;
}
state_change = dyld_should_reload_objfile_for_flags (e);
if (state_change == DYLD_NO_CHANGE)
return;
tmp_bfd = e->objfile->obfd;
e->objfile->obfd = NULL;
if (bfd_get_flavour (tmp_bfd) == bfd_target_mach_o_flavour)
{
int ret;
struct bfd_mach_o_load_command *gsymtab;
ret = bfd_mach_o_lookup_command (tmp_bfd, BFD_MACH_O_LC_SYMTAB, &gsymtab);
if (ret != 1)
{
warning
("Error fetching LC_SYMTAB load command from object file \"%s\"",
tmp_bfd->filename);
}
else if (gsymtab->command.symtab.strtab == DBX_STRINGTAB (e->objfile))
gsymtab->command.symtab.strtab = NULL;
}
tell_breakpoints_objfile_changed (e->objfile);
tell_objc_msgsend_cacher_objfile_changed (e->objfile);
if (e->reason == dyld_reason_init)
{
old_pre_run_slide_addr_valid = e->pre_run_slide_addr_valid;
old_pre_run_slide_addr = e->pre_run_slide_addr;
old_image_addr = e->image_addr;
old_image_addr_valid = e->image_addr_valid;
}
dyld_clear_objfile (e);
e->abfd = tmp_bfd;
if (e->reason == dyld_reason_init)
{
e->pre_run_slide_addr_valid = old_pre_run_slide_addr_valid;
e->pre_run_slide_addr = old_pre_run_slide_addr;
asection *text_sect =
bfd_get_section_by_name (e->abfd, TEXT_SEGMENT_NAME);
if (text_sect != NULL)
{
e->image_addr = bfd_section_vma (e->abfd, text_sect);
e->image_addr_valid = 1;
}
}
dyld_load_symfile_preserving_objfile (e);
if (e->reason == dyld_reason_init)
{
e->image_addr = old_image_addr;
e->image_addr_valid = old_image_addr_valid;
}
if (ui_out_is_mi_like_p (uiout))
{
struct cleanup *notify_cleanup;
notify_cleanup =
make_cleanup_ui_out_notify_begin_end (uiout,
"shlib-state-modified");
dyld_print_entry_info (e, index, 0);
do_cleanups (notify_cleanup);
}
}
static void
set_load_state_helper (struct dyld_path_info *d, struct dyld_objfile_entry *e,
struct objfile *o, int index, const char *arg)
{
int load_state;
if (e == NULL)
return;
load_state = dyld_parse_load_level (arg);
load_state |= dyld_minimal_load_flag (d, e);
set_load_state_1 (e, d, index, load_state);
}
static void
dyld_set_load_state_command (char *args, int from_tty)
{
map_shlib_numbers (args, set_load_state_helper,
&macosx_dyld_status.path_info,
&macosx_dyld_status.current_info);
re_enable_breakpoints_in_shlibs (0);
}
static void
section_info_helper (struct dyld_path_info *d, struct dyld_objfile_entry *e,
struct objfile *o, int index, const char *arg)
{
if (o != NULL)
{
print_section_info_objfile (o);
}
else
{
ui_out_begin (uiout, ui_out_type_list, "section-info");
ui_out_end (uiout, ui_out_type_list);
}
if (e != NULL)
{
#if WITH_CFM
if (inferior_auto_start_cfm_flag && e->cfm_container != 0)
{
NCFragContainerInfo container;
struct cfm_parser *parser;
unsigned long section_index;
int ret;
parser = &macosx_status->cfm_status.parser;
ret =
cfm_fetch_container_info (parser, e->cfm_container, &container);
if (ret != 0)
return;
ui_out_begin (uiout, ui_out_type_list, "cfm-section-info");
for (section_index = 0; section_index < container.sectionCount;
section_index++)
{
NCFragSectionInfo section;
NCFragInstanceInfo instance;
instance.address = 0;
ret =
cfm_fetch_container_section_info (parser, e->cfm_container,
section_index, §ion);
if (ret != 0)
break;
ui_out_begin (uiout, ui_out_type_list, "section");
ui_out_text (uiout, "\t");
ui_out_field_core_addr (uiout, "addr", instance.address);
ui_out_text (uiout, " - ");
ui_out_field_core_addr (uiout, "endaddr",
instance.address + section.length);
if (info_verbose)
{
ui_out_text (uiout, " @ ");
ui_out_field_core_addr (uiout, "filepos", 0);
}
ui_out_text (uiout, " is ");
ui_out_field_string (uiout, "name", "unknown");
#if 0
if (p->objfile->obfd != abfd)
{
ui_out_text (uiout, " in ");
ui_out_field_string (uiout, "filename",
bfd_get_filename (p->bfd));
}
#endif
ui_out_text (uiout, "\n");
ui_out_end (uiout, ui_out_type_list);
}
ui_out_end (uiout, ui_out_type_list);
}
#endif
}
}
static void
dyld_section_info_command (char *args, int from_tty)
{
map_shlib_numbers (args, section_info_helper,
&macosx_dyld_status.path_info,
&macosx_dyld_status.current_info);
}
static void
info_sharedlibrary_command (char *args, int from_tty)
{
char **argv;
struct cleanup *wipe;
wipe = make_cleanup (null_cleanup, NULL);
if (args != NULL)
if ((argv = buildargv (args)) != NULL)
make_cleanup_freeargv (argv);
if (args == NULL || argv == NULL || argv[0] == NULL
|| !strcmp (argv[0], ""))
{
dyld_print_status_info (&macosx_dyld_status,
dyld_reason_all_mask | dyld_reason_user, args);
}
else
{
CORE_ADDR address;
address = parse_and_eval_address (argv[0]);
info_sharedlibrary_address (address);
}
do_cleanups (wipe);
}
static void
info_sharedlibrary_address (CORE_ADDR address)
{
struct dyld_objfile_info *s = &macosx_dyld_status.current_info;
int shlibnum = 1;
int found_dylib = 0;
int baselen;
int i;
struct obj_section *osection;
baselen = dyld_shlib_info_basename_length (s, dyld_reason_all_mask);
if (baselen < 12)
baselen = 12;
osection = find_pc_sect_section (address, NULL);
if (osection != NULL)
{
for (i = 0; i < s->nents; i++)
{
if (osection->objfile == s->entries[i].objfile)
{
found_dylib = 1;
break;
}
shlibnum++;
}
}
if (found_dylib)
dyld_print_entry_info (&s->entries[i], shlibnum, baselen);
else
error ("[unknown]");
}
static void
info_sharedlibrary_all_command (char *args, int from_tty)
{
dyld_print_shlib_info (&macosx_dyld_status.current_info,
dyld_reason_all_mask | dyld_reason_user, 1, args);
}
static void
info_sharedlibrary_dyld_command (char *args, int from_tty)
{
dyld_print_shlib_info (&macosx_dyld_status.current_info,
dyld_reason_dyld, 1, args);
}
#if WITH_CFM
static void
info_sharedlibrary_cfm_command (char *args, int from_tty)
{
dyld_print_shlib_info (&macosx_dyld_status.current_info,
dyld_reason_cfm, 1, args);
}
static void
info_sharedlibrary_raw_cfm_command (char *args, int from_tty)
{
task_t task = macosx_status->task;
struct dyld_objfile_info info;
dyld_objfile_info_init (&info);
cfm_update (task, &info);
dyld_print_shlib_info (&info, dyld_reason_cfm, 1, args);
}
#endif
static void
info_sharedlibrary_raw_dyld_command (char *args, int from_tty)
{
struct dyld_objfile_info info;
dyld_objfile_info_init (&info);
dyld_info_read (&macosx_dyld_status, &info, 0);
dyld_print_shlib_info (&info, dyld_reason_dyld, 1, args);
}
int
dyld_lookup_and_bind_function (char *name)
{
if (!target_has_execution)
return 0;
return 1;
}
static void
dyld_cache_symfiles_command (char *args, int from_tty)
{
error ("Cached symfiles are not supported on this configuration of GDB.");
}
static void
dyld_cache_symfile_command (char *args, int from_tty)
{
error ("Cached symfiles are not supported on this configuration of GDB.");
}
void
update_section_tables ()
{
update_section_tables_dyld (&macosx_dyld_status.current_info);
}
void
update_section_tables_dyld (struct dyld_objfile_info *s)
{
struct target_ops *target;
struct objfile *o;
struct obj_section *osection;
int nsections, csection, osections;
int i;
struct dyld_objfile_entry *j;
target = &exec_ops;
nsections = 0;
ALL_OBJFILES (o)
ALL_OBJFILE_OSECTIONS (o, osection)
nsections++;
osections = target->to_sections_end - target->to_sections;
target_resize_to_sections (target, nsections - osections);
gdb_assert ((target->to_sections + nsections) == target->to_sections_end);
#define ADD_SECTION(osection) \
{ \
gdb_assert (osection != NULL); \
gdb_assert (osection->objfile != NULL); \
target->to_sections[csection].addr = osection->addr; \
target->to_sections[csection].endaddr = osection->endaddr; \
target->to_sections[csection].the_bfd_section = osection->the_bfd_section; \
target->to_sections[csection].bfd = osection->objfile->obfd; \
csection++; \
}
csection = 0;
DYLD_ALL_OBJFILE_INFO_ENTRIES (s, j, i)
{
if (j->objfile != NULL)
ALL_OBJFILE_OSECTIONS (j->objfile, osection)
ADD_SECTION (osection);
if (j->commpage_objfile != NULL)
ALL_OBJFILE_OSECTIONS (j->commpage_objfile, osection)
ADD_SECTION (osection);
}
ALL_OBJFILES (o)
{
int found = 0;
DYLD_ALL_OBJFILE_INFO_ENTRIES (s, j, i)
{
if (j->objfile == o || j->commpage_objfile == o)
found = 1;
}
if (!found)
ALL_OBJFILE_OSECTIONS (o, osection)
ADD_SECTION (osection);
}
#undef ADD_SECTION
gdb_assert (csection == nsections);
}
const char *
macosx_pc_solib (CORE_ADDR addr)
{
return NULL;
}
char *
dyld_fix_path (const char *path)
{
int i;
if (shlib_path_substitutions)
{
for (i = 0; shlib_path_substitutions[i] != NULL; i += 2)
{
const char *prefix = shlib_path_substitutions[i];
const char *new_prefix = shlib_path_substitutions[i + 1];
if (strncmp (path, new_prefix, strlen (new_prefix)) == 0)
{
return xstrdup (path);
}
}
for (i = 0; shlib_path_substitutions[i] != NULL; i += 2)
{
const char *prefix = shlib_path_substitutions[i];
const char *new_prefix = shlib_path_substitutions[i + 1];
if (strncmp (path, prefix, strlen (prefix)) == 0)
{
int old_prefix_length = strlen (prefix);
int new_path_length = strlen (new_prefix) +
strlen (path) - old_prefix_length + 1;
char *new_path = (char *) xmalloc (new_path_length);
if (new_path)
{
strcpy (new_path, new_prefix);
strcat (new_path, path + old_prefix_length);
return new_path;
}
else
{
}
}
}
}
return xstrdup (path);
}
static int malloc_inited_p;
void
macosx_set_malloc_inited (int new_val)
{
malloc_inited_p = new_val;
}
int
macosx_get_malloc_inited (void)
{
if (malloc_inited_p == 0)
macosx_init_addresses (&macosx_dyld_status);
return malloc_inited_p;
}
struct cmd_list_element *dyldlist = NULL;
struct cmd_list_element *setshliblist = NULL;
struct cmd_list_element *showshliblist = NULL;
struct cmd_list_element *infoshliblist = NULL;
struct cmd_list_element *shliblist = NULL;
struct cmd_list_element *maintenanceshliblist = NULL;
static void
maintenance_sharedlibrary_command (char *arg, int from_tty)
{
printf_unfiltered
("\"maintenance sharedlibrary\" must be followed by the name of a sharedlibrary command.\n");
help_list (maintenanceshliblist, "maintenance sharedlibrary ", -1,
gdb_stdout);
}
static void
sharedlibrary_command (char *arg, int from_tty)
{
printf_unfiltered
("\"sharedlibrary\" must be followed by the name of a sharedlibrary command.\n");
help_list (shliblist, "sharedlibrary ", -1, gdb_stdout);
}
static void
macosx_set_auto_start_dyld (char *args, int from_tty,
struct cmd_list_element *c)
{
if (target_executing)
return;
#if defined (NM_NEXTSTEP)
if (macosx_status == NULL)
return;
#endif
if (!inferior_auto_start_dyld_flag)
{
macosx_clear_start_breakpoint ();
return;
}
if (ptid_equal (inferior_ptid, null_ptid))
return;
macosx_solib_add (NULL, 0, NULL, 0);
}
static void
set_shlib_path_substitutions_cmd (char *args, int from_tty,
struct cmd_list_element * c)
{
int success = 0;
if (shlib_path_substitutions != NULL)
{
freeargv (shlib_path_substitutions);
shlib_path_substitutions = NULL;
}
if (shlib_path_subst_cmd_args && shlib_path_subst_cmd_args[0])
{
shlib_path_substitutions = buildargv (shlib_path_subst_cmd_args);
if (shlib_path_substitutions && shlib_path_substitutions[0] != NULL)
{
int i;
success = 1;
for (i = 0; success && shlib_path_substitutions[i] != NULL; i += 2)
{
success = shlib_path_substitutions[i+1] != NULL;
}
}
if (!success)
{
warning ("An even number of paths must be given, surround paths "
"constaining spaces with single or double quotes.");
freeargv (shlib_path_substitutions);
shlib_path_substitutions = NULL;
}
}
}
static void
show_shlib_path_substitutions_cmd (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
char *from;
char *to;
int i = 0;
if (shlib_path_substitutions)
{
fprintf_filtered (file, _("Current shared library path substitions:\n"));
for (i = 0; shlib_path_substitutions[i] != NULL; i += 2)
{
from = shlib_path_substitutions[i];
to = shlib_path_substitutions[i+1];
fprintf_filtered (file, _(" [%i] '%s' -> '%s'\n"), i/2 + 1, from, to);
}
}
else
fprintf_filtered (file, _("No shared library path substitions are currently set.\n"));
if (shlib_path_subst_cmd_args)
fprintf_filtered (file, _("\nLast shared library pathname substition command was:\n"
"set shlib-path-substitutions%s%s\n"),
shlib_path_subst_cmd_args[0] ? " " : "",
shlib_path_subst_cmd_args);
}
void
_initialize_macosx_nat_dyld ()
{
macosx_dyld_thread_init (&macosx_dyld_status);
dyld_stderr = fdopen (fileno (stderr), "w");
add_prefix_cmd ("sharedlibrary", class_run, sharedlibrary_command,
"Commands for shared library manipulation.",
&shliblist, "sharedlibrary ", 0, &cmdlist);
add_prefix_cmd ("sharedlibrary", class_maintenance,
maintenance_sharedlibrary_command,
"Commands for internal sharedlibrary manipulation.",
&maintenanceshliblist, "maintenance sharedlibrary ", 0,
&maintenancelist);
add_cmd ("apply-load-rules", class_run, dyld_apply_load_rules_command,
"Apply the current load-rules to the existing shared library state.",
&shliblist);
add_cmd ("add-symbol-file", class_run, dyld_add_symbol_file_command,
"Add a symbol file.", &shliblist);
add_cmd ("remove-symbol-file", class_run, dyld_remove_symbol_file_command,
"Remove a symbol file.", &shliblist);
add_cmd ("set-load-state", class_run, dyld_set_load_state_command,
"Set the load level of a library (given by the index from \"info sharedlibrary\").",
&shliblist);
add_cmd ("section-info", class_run, dyld_section_info_command,
"Get the section info for a library (given by the index from \"info sharedlibrary\").",
&shliblist);
add_cmd ("cache-purge", class_obscure, dyld_cache_purge_command,
"Purge all symbols for DYLD images cached by GDB.",
&maintenanceshliblist);
add_cmd ("update", class_run, macosx_dyld_update_command,
"Process all pending DYLD events.", &shliblist);
add_prefix_cmd ("sharedlibrary", no_class, info_sharedlibrary_command,
"Generic command for shlib information.\n`info sharedlibrary ADDRESS' will show the dylib containing ADDRESS.",
&infoshliblist, "info sharedlibrary ", 1, &infolist);
add_cmd ("all", no_class, info_sharedlibrary_all_command,
"Show current DYLD state.", &infoshliblist);
add_cmd ("dyld", no_class, info_sharedlibrary_dyld_command,
"Show current DYLD state.", &infoshliblist);
#if WITH_CFM
add_cmd ("cfm", no_class, info_sharedlibrary_cfm_command,
"Show current CFM state.", &infoshliblist);
add_cmd ("raw-cfm", no_class, info_sharedlibrary_raw_cfm_command,
"Show current CFM state.", &infoshliblist);
#endif
add_cmd ("raw-dyld", no_class, info_sharedlibrary_raw_dyld_command,
"Show current CFM state.", &infoshliblist);
add_prefix_cmd ("sharedlibrary", no_class, not_just_help_class_command,
"Generic command for setting shlib settings.",
&setshliblist, "set sharedlibrary ", 0, &setlist);
add_prefix_cmd ("sharedlibrary", no_class, not_just_help_class_command,
"Generic command for showing shlib settings.",
&showshliblist, "show sharedlibrary ", 0, &showlist);
add_setshow_boolean_cmd ("filter-events", class_obscure,
&dyld_filter_events_flag, _("\
Set if GDB should filter shared library events to a minimal set."), _("\
Show if GDB should filter shared library events to a minimal set."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_boolean_cmd ("preload-libraries", class_obscure,
&dyld_preload_libraries_flag, _("\
Set if GDB should pre-load symbols for DYLD libraries."), _("\
Show if GDB should pre-load symbols for DYLD libraries."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_boolean_cmd ("load-dyld-symbols", class_obscure,
&dyld_load_dyld_symbols_flag, _("\
Set if GDB should load symbol information for the dynamic linker."), _("\
Show if GDB should load symbol information for the dynamic linker."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_boolean_cmd ("load-dyld-shlib-symbols", class_obscure,
&dyld_load_dyld_shlib_symbols_flag, _("\
Set if GDB should load symbol information for DYLD-based shared libraries."), _("\
Show if GDB should load symbol information for DYLD-based shared libraries."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_boolean_cmd ("load-cfm-shlib-symbols", class_obscure,
&dyld_load_cfm_shlib_symbols_flag, _("\
Set if GDB should load symbol information for CFM-based shared libraries."), _("\
Show if GDB should load symbol information for CFM-based shared libraries."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_string_cmd ("dyld-symbols-prefix", class_obscure,
&dyld_symbols_prefix, _("\
Set the prefix that GDB should prepend to all symbols for the dynamic linker."), _("\
Show the prefix that GDB should prepend to all symbols for the dynamic linker."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
dyld_symbols_prefix = xstrdup (dyld_symbols_prefix);
add_setshow_boolean_cmd ("always-read-from-memory", class_obscure,
&dyld_always_read_from_memory_flag, _("\
Set if GDB should always read loaded images from the inferior's memory."), _("\
Show if GDB should always read loaded images from the inferior's memory."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_boolean_cmd ("print-basenames", class_obscure,
&dyld_print_basenames_flag, _("\
Set if GDB should print the basenames of loaded files when printing progress messages."), _("\
Show if GDB should print the basenames of loaded files when printing progress messages."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_string_cmd ("load-rules", class_support,
&dyld_load_rules, _("\
Set the rules governing the level of symbol loading for shared libraries.\n\
* Each load rule is a triple.\n\
* The command takes a flattened list of triples.\n\
* The first two elements of the triple specify the library, by giving \n\
- \"who loaded it\" (i.e. dyld, cfm or all) in the first element, \n\
- and a regexp to match the library name in the second. \n\
* The last element specifies the level of loading for that library\n\
- The options are: all, extern, container or none.\n\
\n\
Example: To load only external symbols from all dyld-based system libraries, use: \n\
set sharedlibrary load-rules dyld ^/System/Library.* extern\n"),
"XYZ",
NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_string_cmd ("minimal-load-rules", class_support,
&dyld_minimal_load_rules, _("\
Set the minimal DYLD load rules. These prime the main list.\n\
gdb relies on some of these for proper functioning, so don't remove elements from it\n\
unless you know what you are doing."),
"xyz",
NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_zinteger_cmd ("dyld", class_obscure,
&dyld_debug_flag, _("\
Set if printing dyld communication debugging statements."), _("\
Show if printing dyld communication debugging statements."), NULL,
NULL, NULL,
&setdebuglist, &showdebuglist);
dyld_minimal_load_rules =
xstrdup
("\"dyld\" \"CarbonCore$\\\\|CarbonCore_[^/]*$\" all \".*\" \"dyld$\" extern \".*\" \".*\" none");
dyld_load_rules = xstrdup ("\".*\" \".*\" all");
add_setshow_zinteger_cmd ("stop-on-shlibs-added", class_support,
&dyld_stop_on_shlibs_added, _("\
Set if a shlib event should be reported on a shlibs-added event."), _("\
Show if a shlib event should be reported on a shlibs-added event."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_zinteger_cmd ("stop-on-shlibs-updated", class_support,
&dyld_stop_on_shlibs_updated, _("\
Set if a shlib event should be reported on a shlibs-updated event."), _("\
Show if a shlib event should be reported on a shlibs-updated event."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_zinteger_cmd ("combine-shlibs-added", class_support,
&dyld_combine_shlibs_added, _("\
Set if GDB should combine shlibs-added events from the same image into a single event."), _("\
Show if GDB should combine shlibs-added events from the same image into a single event."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_zinteger_cmd ("reload-on-downgrade", class_support,
&dyld_reload_on_downgrade_flag, _("\
Set if GDB should re-read symbol files in order to remove symbol information."), _("\
Show if GDB should re-read symbol files in order to remove symbol information."), NULL,
NULL, NULL,
&setshliblist, &showshliblist);
add_setshow_boolean_cmd ("inferior-auto-start-dyld", class_obscure,
&inferior_auto_start_dyld_flag, _("\
Set if GDB should enable debugging of dyld shared libraries."), _("\
Show if GDB should enable debugging of dyld shared libraries."), NULL,
macosx_set_auto_start_dyld, NULL,
&setlist, &showlist);
add_setshow_boolean_cmd ("inferior-auto-start-cfm", class_obscure,
&inferior_auto_start_cfm_flag, _("\
Set if GDB should enable debugging of CFM shared libraries."), _("\
Show if GDB should enable debugging of CFM shared libraries."), NULL,
NULL, NULL,
&setlist, &showlist);
add_cmd ("cache-symfiles", class_run, dyld_cache_symfiles_command,
"Generate persistent caches of symbol files for the current executable state.",
&shliblist);
add_cmd ("cache-symfile", class_run, dyld_cache_symfile_command,
"Generate persistent caches of symbol files for a specified executable.\n"
"usage: cache-symfile <source> <target> [prefix]", &shliblist);
add_setshow_string_cmd ("shlib-path-substitutions", class_support,
&shlib_path_subst_cmd_args, _("\
Set path substitutions to be used when loading shared libraries."), _("\
Show path substitutions to be used when loading shared libraries."), _("\
Commonly used for remote debugging a target that was built with shared\n\
libraries that do not match those currently installed on the host machine.\n\
Any needed shared libraries can be copied from the remote machine to a local\n\
directory, or the root of the remote machine could be mounted over a network.\n\
\n\
The string substitutions are space separated pairs of paths where each\n\
string can be surrounded by double quotes if a path contains spaces.\n\
\n\
For example, if you are running gdb on a 10.4 machine, and you are remote\n\
debugging to a machine with 10.3 installed, you could copy the files to a\n\
local directory (/tmp/remote) and use the following command:\n\
\n\
shlib-path-substitutions /usr /tmp/remote/usr /System /tmp/remote/System"),
set_shlib_path_substitutions_cmd,
show_shlib_path_substitutions_cmd,
&setlist, &showlist);
add_setshow_boolean_cmd ("pre-slide-libraries", class_obscure,
&pre_slide_libraries_flag, _("\
Set if GDB should pre-slide libraries to unique addresses before running."), _("\
Show if GDB should pre-slide libraries to unique addresses before running."),
_("\
When multiple libraries have a load address of 0x0, they will overlap before\n\
execution has started. When execution starts, dyld will slide them all to\n\
unique locations. Before execution, when you try to disassemble or examine\n\
the contents of these libraries, you may have unexpected results from gdb as\n\
it gets the different overlapping libraries confused. At this time, the \n\
pre-sliding feature still has some rough edges and is not recommended for\n\
use by default."),
NULL, NULL,
&setshliblist, &showshliblist);
}