gdb/solib-darwin.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "symtab.h"
- #include "bfd.h"
- #include "symfile.h"
- #include "objfiles.h"
- #include "gdbcore.h"
- #include "target.h"
- #include "inferior.h"
- #include "regcache.h"
- #include "gdbthread.h"
- #include "gdb_bfd.h"
- #include "solist.h"
- #include "solib.h"
- #include "solib-svr4.h"
- #include "bfd-target.h"
- #include "elf-bfd.h"
- #include "exec.h"
- #include "auxv.h"
- #include "mach-o.h"
- #include "mach-o/external.h"
- struct gdb_dyld_image_info
- {
-
- CORE_ADDR mach_header;
-
- CORE_ADDR file_path;
-
- unsigned long mtime;
- };
- struct gdb_dyld_all_image_infos
- {
-
- unsigned int version;
-
- unsigned int count;
-
- CORE_ADDR info;
-
- CORE_ADDR notifier;
- };
- #define DYLD_VERSION_MIN 1
- #define DYLD_VERSION_MAX 14
- struct darwin_info
- {
-
- CORE_ADDR all_image_addr;
-
- struct gdb_dyld_all_image_infos all_image;
- };
- static const struct program_space_data *solib_darwin_pspace_data;
- static void
- darwin_pspace_data_cleanup (struct program_space *pspace, void *arg)
- {
- xfree (arg);
- }
- static struct darwin_info *
- get_darwin_info (void)
- {
- struct darwin_info *info;
- info = program_space_data (current_program_space, solib_darwin_pspace_data);
- if (info != NULL)
- return info;
- info = XCNEW (struct darwin_info);
- set_program_space_data (current_program_space,
- solib_darwin_pspace_data, info);
- return info;
- }
- static int
- darwin_dyld_version_ok (const struct darwin_info *info)
- {
- return info->all_image.version >= DYLD_VERSION_MIN
- && info->all_image.version <= DYLD_VERSION_MAX;
- }
- static void
- darwin_load_image_infos (struct darwin_info *info)
- {
- gdb_byte buf[24];
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- int len;
-
- if (info->all_image_addr == 0)
- return;
-
- len = 4 + 4 + 2 * ptr_type->length;
- gdb_assert (len <= sizeof (buf));
- memset (&info->all_image, 0, sizeof (info->all_image));
-
- if (target_read_memory (info->all_image_addr, buf, len))
- return;
-
- info->all_image.version = extract_unsigned_integer (buf, 4, byte_order);
- if (!darwin_dyld_version_ok (info))
- return;
- info->all_image.count = extract_unsigned_integer (buf + 4, 4, byte_order);
- info->all_image.info = extract_typed_address (buf + 8, ptr_type);
- info->all_image.notifier = extract_typed_address
- (buf + 8 + ptr_type->length, ptr_type);
- }
- struct lm_info
- {
-
- CORE_ADDR lm_addr;
- };
- struct darwin_so_list
- {
-
- struct so_list sl;
-
- struct lm_info li;
- };
- static CORE_ADDR
- lookup_symbol_from_bfd (bfd *abfd, char *symname)
- {
- long storage_needed;
- asymbol **symbol_table;
- unsigned int number_of_symbols;
- unsigned int i;
- CORE_ADDR symaddr = 0;
- storage_needed = bfd_get_symtab_upper_bound (abfd);
- if (storage_needed <= 0)
- return 0;
- symbol_table = (asymbol **) xmalloc (storage_needed);
- number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
- for (i = 0; i < number_of_symbols; i++)
- {
- asymbol *sym = symbol_table[i];
- if (strcmp (sym->name, symname) == 0
- && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
- {
-
- symaddr = sym->value + sym->section->vma;
- break;
- }
- }
- xfree (symbol_table);
- return symaddr;
- }
- static char *
- find_program_interpreter (void)
- {
- char *buf = NULL;
-
- if (exec_bfd)
- {
- bfd_mach_o_load_command *cmd;
- if (bfd_mach_o_lookup_command (exec_bfd,
- BFD_MACH_O_LC_LOAD_DYLINKER, &cmd) == 1)
- return cmd->command.dylinker.name_str;
- }
-
- FIXME
- return buf;
- }
- static int
- open_symbol_file_object (void *from_ttyp)
- {
- return 0;
- }
- static struct so_list *
- darwin_current_sos (void)
- {
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- int ptr_len = TYPE_LENGTH (ptr_type);
- unsigned int image_info_size;
- struct so_list *head = NULL;
- struct so_list *tail = NULL;
- int i;
- struct darwin_info *info = get_darwin_info ();
-
- darwin_load_image_infos (info);
- if (!darwin_dyld_version_ok (info))
- return NULL;
- image_info_size = ptr_len * 3;
-
- for (i = 0; i < info->all_image.count; i++)
- {
- CORE_ADDR iinfo = info->all_image.info + i * image_info_size;
- gdb_byte buf[image_info_size];
- CORE_ADDR load_addr;
- CORE_ADDR path_addr;
- struct mach_o_header_external hdr;
- unsigned long hdr_val;
- char *file_path;
- int errcode;
- struct darwin_so_list *dnew;
- struct so_list *new;
- struct cleanup *old_chain;
-
- if (target_read_memory (iinfo, buf, image_info_size))
- break;
- load_addr = extract_typed_address (buf, ptr_type);
- path_addr = extract_typed_address (buf + ptr_len, ptr_type);
-
- if (target_read_memory (load_addr, (gdb_byte *) &hdr, sizeof (hdr) - 4))
- break;
-
- hdr_val = extract_unsigned_integer
- (hdr.magic, sizeof (hdr.magic), byte_order);
- if (hdr_val != BFD_MACH_O_MH_MAGIC && hdr_val != BFD_MACH_O_MH_MAGIC_64)
- continue;
-
- hdr_val = extract_unsigned_integer
- (hdr.filetype, sizeof (hdr.filetype), byte_order);
- if (hdr_val == BFD_MACH_O_MH_EXECUTE)
- continue;
- target_read_string (path_addr, &file_path,
- SO_NAME_MAX_PATH_SIZE - 1, &errcode);
- if (errcode)
- break;
-
- dnew = XCNEW (struct darwin_so_list);
- new = &dnew->sl;
- old_chain = make_cleanup (xfree, dnew);
- new->lm_info = &dnew->li;
- strncpy (new->so_name, file_path, SO_NAME_MAX_PATH_SIZE - 1);
- new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
- strcpy (new->so_original_name, new->so_name);
- xfree (file_path);
- new->lm_info->lm_addr = load_addr;
- if (head == NULL)
- head = new;
- else
- tail->next = new;
- tail = new;
- discard_cleanups (old_chain);
- }
- return head;
- }
- static CORE_ADDR
- darwin_read_exec_load_addr (struct darwin_info *info)
- {
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- int ptr_len = TYPE_LENGTH (ptr_type);
- unsigned int image_info_size = ptr_len * 3;
- int i;
-
- for (i = 0; i < info->all_image.count; i++)
- {
- CORE_ADDR iinfo = info->all_image.info + i * image_info_size;
- gdb_byte buf[image_info_size];
- CORE_ADDR load_addr;
- struct mach_o_header_external hdr;
- unsigned long hdr_val;
-
- if (target_read_memory (iinfo, buf, image_info_size))
- break;
- load_addr = extract_typed_address (buf, ptr_type);
-
- if (target_read_memory (load_addr, (gdb_byte *) &hdr, sizeof (hdr) - 4))
- break;
-
- hdr_val = extract_unsigned_integer
- (hdr.magic, sizeof (hdr.magic), byte_order);
- if (hdr_val != BFD_MACH_O_MH_MAGIC && hdr_val != BFD_MACH_O_MH_MAGIC_64)
- continue;
-
- hdr_val = extract_unsigned_integer
- (hdr.filetype, sizeof (hdr.filetype), byte_order);
- if (hdr_val == BFD_MACH_O_MH_EXECUTE)
- return load_addr;
- }
- return 0;
- }
- static int
- darwin_in_dynsym_resolve_code (CORE_ADDR pc)
- {
- return 0;
- }
- static void
- darwin_special_symbol_handling (void)
- {
- }
- static bfd *
- gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format,
- const bfd_arch_info_type *arch)
- {
- bfd *result = bfd_mach_o_fat_extract (abfd, format, arch);
- if (result == NULL)
- return NULL;
- if (result == abfd)
- gdb_bfd_ref (result);
- else
- gdb_bfd_mark_parent (result, abfd);
- return result;
- }
- static void
- darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info)
- {
- char *interp_name;
- CORE_ADDR load_addr = 0;
- bfd *dyld_bfd = NULL;
- struct cleanup *cleanup;
-
- if (current_inferior ()->attach_flag)
- return;
-
- interp_name = find_program_interpreter ();
- if (!interp_name)
- return;
- cleanup = make_cleanup (null_cleanup, NULL);
-
- dyld_bfd = gdb_bfd_open (interp_name, gnutarget, -1);
- if (dyld_bfd)
- {
- bfd *sub;
- make_cleanup_bfd_unref (dyld_bfd);
- sub = gdb_bfd_mach_o_fat_extract (dyld_bfd, bfd_object,
- gdbarch_bfd_arch_info (target_gdbarch ()));
- if (sub)
- {
- dyld_bfd = sub;
- make_cleanup_bfd_unref (sub);
- }
- else
- dyld_bfd = NULL;
- }
- if (!dyld_bfd)
- {
- do_cleanups (cleanup);
- return;
- }
-
- load_addr = (regcache_read_pc (get_current_regcache ())
- - bfd_get_start_address (dyld_bfd));
-
- info->all_image_addr =
- lookup_symbol_from_bfd (dyld_bfd, "_dyld_all_image_infos");
- do_cleanups (cleanup);
- if (info->all_image_addr == 0)
- return;
- info->all_image_addr += load_addr;
- }
- static void
- darwin_solib_read_all_image_info_addr (struct darwin_info *info)
- {
- gdb_byte buf[8 + 8 + 4];
- LONGEST len;
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- len = target_read (¤t_target, TARGET_OBJECT_DARWIN_DYLD_INFO, NULL,
- buf, 0, sizeof (buf));
- if (len != sizeof (buf))
- return;
- info->all_image_addr = extract_unsigned_integer (buf, 8, byte_order);
- }
- static void
- darwin_solib_create_inferior_hook (int from_tty)
- {
- struct darwin_info *info = get_darwin_info ();
- CORE_ADDR load_addr;
- info->all_image_addr = 0;
- darwin_solib_read_all_image_info_addr (info);
- if (info->all_image_addr == 0)
- darwin_solib_get_all_image_info_addr_at_init (info);
- if (info->all_image_addr == 0)
- return;
- darwin_load_image_infos (info);
- if (!darwin_dyld_version_ok (info))
- {
- warning (_("unhandled dyld version (%d)"), info->all_image.version);
- return;
- }
- create_solib_event_breakpoint (target_gdbarch (), info->all_image.notifier);
-
- load_addr = darwin_read_exec_load_addr (info);
- if (load_addr != 0 && symfile_objfile != NULL)
- {
- CORE_ADDR vmaddr;
-
- vmaddr = bfd_mach_o_get_base_address (exec_bfd);
-
- if (vmaddr != load_addr)
- objfile_rebase (symfile_objfile, load_addr - vmaddr);
- }
- }
- static void
- darwin_clear_solib (void)
- {
- struct darwin_info *info = get_darwin_info ();
- info->all_image_addr = 0;
- info->all_image.version = 0;
- }
- static void
- darwin_free_so (struct so_list *so)
- {
- }
- static void
- darwin_relocate_section_addresses (struct so_list *so,
- struct target_section *sec)
- {
- sec->addr += so->lm_info->lm_addr;
- sec->endaddr += so->lm_info->lm_addr;
-
- if (so->addr_high == 0)
- {
- so->addr_low = sec->addr;
- so->addr_high = sec->endaddr;
- }
- if (sec->endaddr > so->addr_high)
- so->addr_high = sec->endaddr;
- if (sec->addr < so->addr_low)
- so->addr_low = sec->addr;
- }
- static struct symbol *
- darwin_lookup_lib_symbol (struct objfile *objfile,
- const char *name,
- const domain_enum domain)
- {
- return NULL;
- }
- static bfd *
- darwin_bfd_open (char *pathname)
- {
- char *found_pathname;
- int found_file;
- bfd *abfd;
- bfd *res;
-
- found_pathname = solib_find (pathname, &found_file);
- if (found_pathname == NULL)
- perror_with_name (pathname);
-
- abfd = solib_bfd_fopen (found_pathname, found_file);
- res = gdb_bfd_mach_o_fat_extract (abfd, bfd_object,
- gdbarch_bfd_arch_info (target_gdbarch ()));
- if (!res)
- {
- make_cleanup_bfd_unref (abfd);
- error (_("`%s': not a shared-library: %s"),
- bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
- }
-
- xfree (bfd_get_filename (res));
- res->filename = xstrdup (pathname);
- gdb_bfd_unref (abfd);
- return res;
- }
- struct target_so_ops darwin_so_ops;
- extern initialize_file_ftype _initialize_darwin_solib;
- void
- _initialize_darwin_solib (void)
- {
- solib_darwin_pspace_data
- = register_program_space_data_with_cleanup (NULL,
- darwin_pspace_data_cleanup);
- darwin_so_ops.relocate_section_addresses = darwin_relocate_section_addresses;
- darwin_so_ops.free_so = darwin_free_so;
- darwin_so_ops.clear_solib = darwin_clear_solib;
- darwin_so_ops.solib_create_inferior_hook = darwin_solib_create_inferior_hook;
- darwin_so_ops.special_symbol_handling = darwin_special_symbol_handling;
- darwin_so_ops.current_sos = darwin_current_sos;
- darwin_so_ops.open_symbol_file_object = open_symbol_file_object;
- darwin_so_ops.in_dynsym_resolve_code = darwin_in_dynsym_resolve_code;
- darwin_so_ops.lookup_lib_global_symbol = darwin_lookup_lib_symbol;
- darwin_so_ops.bfd_open = darwin_bfd_open;
- }