X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fmachoread.c;h=0194ee521620a9e1b4eec4c881a374a46e751492;hb=7f7828f676d00c8ef2befefd7912fafa9cda1a1b;hp=d8d3bd2285c20b36df6ab9faddfde13cf0cae8ca;hpb=cf1061c036950e2c75d7520eb33d7a1618e3a4ef;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/machoread.c b/gdb/machoread.c index d8d3bd2285..0194ee5216 100644 --- a/gdb/machoread.c +++ b/gdb/machoread.c @@ -69,7 +69,9 @@ typedef struct oso_el int num_sections; /* Each seaction of the object file is represented by a symbol and its - offset. */ + offset. If the offset is 0, we assume that the symbol is at offset 0 + in the OSO object file and a symbol lookup in the main file is + required to get the offset. */ asymbol **symbols; bfd_vma *offsets; } @@ -80,6 +82,7 @@ DEF_VEC_O (oso_el); static VEC (oso_el) *oso_vector; /* Add a new OSO to the vector. */ + static void macho_add_oso (const asymbol *oso_sym, int nbr_sections, asymbol **symbols, bfd_vma *offsets) @@ -97,13 +100,13 @@ macho_add_oso (const asymbol *oso_sym, int nbr_sections, /* Build the minimal symbol table from SYMBOL_TABLE of length NUMBER_OF_SYMBOLS for OBJFILE. Read OSO files at the end. */ + static void macho_symtab_read (struct objfile *objfile, long number_of_symbols, asymbol **symbol_table) { struct gdbarch *gdbarch = get_objfile_arch (objfile); long storage_needed; - asymbol *sym; long i, j; CORE_ADDR offset; enum minimal_symbol_type ms_type; @@ -114,22 +117,26 @@ macho_symtab_read (struct objfile *objfile, for (i = 0; i < number_of_symbols; i++) { - sym = symbol_table[i]; + asymbol *sym = symbol_table[i]; + bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym; + offset = ANOFFSET (objfile->section_offsets, sym->section->index); if (sym->flags & BSF_DEBUGGING) { - unsigned char type = BFD_MACH_O_SYM_NTYPE(sym); bfd_vma addr; - switch (type) + /* Debugging symbols are used to collect OSO file names as well + as section offsets. */ + + switch (mach_o_sym->n_type) { case N_SO: - if ((sym->name == NULL || sym->name[0] == 0) - && oso_file != NULL) + /* An empty SO entry terminates a chunk for an OSO file. */ + if ((sym->name == NULL || sym->name[0] == 0) && oso_file != NULL) { macho_add_oso (oso_file, nbr_sections, - first_symbol, first_offset); + first_symbol, first_offset); first_symbol = NULL; first_offset = NULL; oso_file = NULL; @@ -147,6 +154,7 @@ macho_symtab_read (struct objfile *objfile, if (addr != 0 && first_symbol[sym->section->index] == NULL) { + /* These STAB entries can directly relocate a section. */ first_symbol[sym->section->index] = sym; first_offset[sym->section->index] = addr + offset; } @@ -154,9 +162,15 @@ macho_symtab_read (struct objfile *objfile, case N_GSYM: gdb_assert (oso_file != NULL); if (first_symbol[sym->section->index] == NULL) - first_symbol[sym->section->index] = sym; + { + /* This STAB entry needs a symbol look-up to relocate + the section. */ + first_symbol[sym->section->index] = sym; + first_offset[sym->section->index] = 0; + } break; case N_OSO: + /* New OSO file. */ gdb_assert (oso_file == NULL); first_symbol = (asymbol **)xmalloc (nbr_sections * sizeof (asymbol *)); @@ -231,6 +245,7 @@ macho_symtab_read (struct objfile *objfile, if (oso_file != NULL && first_symbol[sym->section->index] == NULL) { + /* Standard symbols can directly relocate sections. */ first_symbol[sym->section->index] = sym; first_offset[sym->section->index] = symaddr; } @@ -241,6 +256,7 @@ macho_symtab_read (struct objfile *objfile, } } + /* Just in case there is no trailing SO entry. */ if (oso_file != NULL) macho_add_oso (oso_file, nbr_sections, first_symbol, first_offset); } @@ -248,6 +264,7 @@ macho_symtab_read (struct objfile *objfile, /* If NAME describes an archive member (ie: ARCHIVE '(' MEMBER ')'), returns the length of the archive name. Returns -1 otherwise. */ + static int get_archive_prefix_len (const char *name) { @@ -263,82 +280,111 @@ get_archive_prefix_len (const char *name) return lparen - name; } +static int +oso_el_compare_name (const void *vl, const void *vr) +{ + const oso_el *l = (const oso_el *)vl; + const oso_el *r = (const oso_el *)vr; + + return strcmp (l->name, r->name); +} + +/* Add an oso file as a symbol file. */ + +static void +macho_add_oso_symfile (oso_el *oso, bfd *abfd, struct objfile *main_objfile) +{ + struct section_addr_info *addrs; + int len; + int i; + char leading_char; + + if (mach_o_debug_level > 0) + printf_unfiltered (_("Loading symbols from oso: %s\n"), oso->name); + + if (!bfd_check_format (abfd, bfd_object)) + { + warning (_("`%s': can't read symbols: %s."), oso->name, + bfd_errmsg (bfd_get_error ())); + bfd_close (abfd); + return; + } + + bfd_set_cacheable (abfd, 1); + + /* Compute addr length. */ + len = 0; + for (i = 0; i < oso->num_sections; i++) + if (oso->symbols[i] != NULL) + len++; + + addrs = alloc_section_addr_info (len); + + leading_char = bfd_get_symbol_leading_char (main_objfile->obfd); + + len = 0; + for (i = 0; i < oso->num_sections; i++) + if (oso->symbols[i] != NULL) + { + if (oso->offsets[i]) + addrs->other[len].addr = oso->offsets[i]; + else + { + struct minimal_symbol *msym; + const char *name = oso->symbols[i]->name; + + if (name[0] == leading_char) + ++name; + + if (mach_o_debug_level > 3) + printf_unfiltered (_("resolve sect %s with %s\n"), + oso->symbols[i]->section->name, + oso->symbols[i]->name); + msym = lookup_minimal_symbol (name, NULL, main_objfile); + if (msym == NULL) + { + warning (_("can't find symbol '%s' in minsymtab"), + oso->symbols[i]->name); + addrs->other[len].addr = 0; + } + else + addrs->other[len].addr = SYMBOL_VALUE_ADDRESS (msym); + } + addrs->other[len].name = (char *)oso->symbols[i]->section->name; + len++; + } + + if (mach_o_debug_level > 1) + { + int j; + for (j = 0; j < addrs->num_sections; j++) + printf_unfiltered (_(" %s: %s\n"), + core_addr_to_string (addrs->other[j].addr), + addrs->other[j].name); + } + + symbol_file_add_from_bfd (abfd, 0, addrs, 0); +} + /* Read symbols from the vector of oso files. */ + static void macho_oso_symfile (struct objfile *main_objfile) { int ix; VEC (oso_el) *vec; oso_el *oso; - char leading_char; - - /* TODO: Sort them, group library search. */ vec = oso_vector; oso_vector = NULL; - leading_char = bfd_get_symbol_leading_char (main_objfile->obfd); + /* Sort oso by name so that files from libraries are gathered. */ + qsort (VEC_address (oso_el, vec), VEC_length (oso_el, vec), + sizeof (oso_el), oso_el_compare_name); - for (ix = 0; VEC_iterate (oso_el, vec, ix, oso); ix++) + for (ix = 0; VEC_iterate (oso_el, vec, ix, oso);) { - struct section_addr_info *addrs; int pfx_len; - int len; - int i; - oso_el el; - - if (mach_o_debug_level > 0) - printf_unfiltered (_("Loading symbols from oso: %s\n"), oso->name); - - /* Compute addr length. */ - len = 0; - for (i = 0; i < oso->num_sections; i++) - if (oso->symbols[i] != NULL) - len++; - - addrs = alloc_section_addr_info (len); - - len = 0; - for (i = 0; i < oso->num_sections; i++) - if (oso->symbols[i] != NULL) - { - if (oso->offsets[i]) - addrs->other[len].addr = oso->offsets[i]; - else - { - struct minimal_symbol *msym; - const char *name = oso->symbols[i]->name; - - if (name[0] == leading_char) - ++name; - - if (mach_o_debug_level > 3) - printf_unfiltered (_("resolv sec %s with %s\n"), - oso->symbols[i]->section->name, - oso->symbols[i]->name); - msym = lookup_minimal_symbol (name, NULL, main_objfile); - if (msym == NULL) - { - warning (_("can't find symbol '%s' in minsymtab"), - oso->symbols[i]->name); - addrs->other[len].addr = 0; - } - else - addrs->other[len].addr = SYMBOL_VALUE_ADDRESS (msym); - } - addrs->other[len].name = (char *)oso->symbols[i]->section->name; - len++; - } - - if (mach_o_debug_level > 1) - { - int j; - for (j = 0; j < addrs->num_sections; j++) - printf_unfiltered - (_(" %s: %s\n"), - core_addr_to_string (addrs->other[j].addr), - addrs->other[j].name); - } /* Check if this is a library name. */ pfx_len = get_archive_prefix_len (oso->name); @@ -346,19 +392,29 @@ macho_oso_symfile (struct objfile *main_objfile) { bfd *archive_bfd; bfd *member_bfd; - char *archive_name = (char *) alloca (pfx_len + 1); - int member_len; + char *archive_name = XNEWVEC (char, pfx_len + 1); + int last_ix; + oso_el *oso2; + int ix2; - member_len = strlen (oso->name + pfx_len + 1) - 1; memcpy (archive_name, oso->name, pfx_len); archive_name[pfx_len] = '\0'; + /* Compute number of oso for this archive. */ + for (last_ix = ix; + VEC_iterate (oso_el, vec, last_ix, oso2); last_ix++) + { + if (strncmp (oso2->name, archive_name, pfx_len) != 0) + break; + } + /* Open the archive and check the format. */ archive_bfd = bfd_openr (archive_name, gnutarget); if (archive_bfd == NULL) { warning (_("Could not open OSO archive file \"%s\""), archive_name); + ix = last_ix; continue; } if (!bfd_check_format (archive_bfd, bfd_archive)) @@ -366,6 +422,7 @@ macho_oso_symfile (struct objfile *main_objfile) warning (_("OSO archive file \"%s\" not an archive."), archive_name); bfd_close (archive_bfd); + ix = last_ix; continue; } member_bfd = bfd_openr_next_archived_file (archive_bfd, NULL); @@ -375,62 +432,68 @@ macho_oso_symfile (struct objfile *main_objfile) warning (_("Could not read archive members out of " "OSO archive \"%s\""), archive_name); bfd_close (archive_bfd); + ix = last_ix; continue; } - + + /* Load all oso in this library. */ while (member_bfd != NULL) { - bfd *prev = member_bfd; + bfd *prev; const char *member_name = member_bfd->filename; - if (strlen (member_name) == member_len - && !memcmp (member_name, oso->name + pfx_len + 1, member_len)) - break; + int member_len = strlen (member_name); + + /* If this member is referenced, add it as a symfile. */ + for (ix2 = ix; ix2 < last_ix; ix2++) + { + oso2 = VEC_index (oso_el, vec, ix2); + + if (oso2->name + && strlen (oso2->name) == pfx_len + member_len + 2 + && !memcmp (member_name, oso2->name + pfx_len + 1, + member_len)) + { + macho_add_oso_symfile (oso2, member_bfd, main_objfile); + oso2->name = NULL; + break; + } + } + + prev = member_bfd; member_bfd = bfd_openr_next_archived_file (archive_bfd, member_bfd); - bfd_close (prev); - } - if (member_bfd == NULL) - { - warning (_("Could not find specified archive member " - "for OSO name \"%s\""), oso->name); - bfd_close (archive_bfd); - continue; - } - - bfd_set_cacheable (member_bfd, 1); - - if (!bfd_check_format (member_bfd, bfd_object)) - { - warning (_("`%s': can't read symbols: %s."), oso->name, - bfd_errmsg (bfd_get_error ())); - bfd_close (member_bfd); + + /* Free previous member if not referenced by an oso. */ + if (ix2 >= last_ix) + bfd_close (prev); } - else - symbol_file_add_from_bfd (member_bfd, 0, addrs, 0, 0); + for (ix2 = ix; ix2 < last_ix; ix2++) + { + oso_el *oso2 = VEC_index (oso_el, vec, ix2); + + if (oso2->name != NULL) + warning (_("Could not find specified archive member " + "for OSO name \"%s\""), oso->name); + } + ix = last_ix; } else { - bfd *abfd; + bfd *abfd; abfd = bfd_openr (oso->name, gnutarget); if (!abfd) - { - warning (_("`%s': can't open to read symbols: %s."), oso->name, - bfd_errmsg (bfd_get_error ())); - continue; - } - bfd_set_cacheable (abfd, 1); - - if (!bfd_check_format (abfd, bfd_object)) - { - bfd_close (abfd); - warning (_("`%s': can't read symbols: %s."), oso->name, - bfd_errmsg (bfd_get_error ())); - continue; - } - - symbol_file_add_from_bfd (abfd, 0, addrs, 0, 0); - } + warning (_("`%s': can't open to read symbols: %s."), oso->name, + bfd_errmsg (bfd_get_error ())); + else + macho_add_oso_symfile (oso, abfd, main_objfile); + + ix++; + } + } + + for (ix = 0; VEC_iterate (oso_el, vec, ix, oso); ix++) + { xfree (oso->symbols); xfree (oso->offsets); } @@ -446,6 +509,7 @@ macho_oso_symfile (struct objfile *main_objfile) /* Check if a dsym file exists for OBJFILE. If so, returns a bfd for it. Return NULL if no valid dsym file is found. */ + static bfd * macho_check_dsym (struct objfile *objfile) { @@ -455,9 +519,8 @@ macho_check_dsym (struct objfile *objfile) size_t base_len = strlen (base_name); char *dsym_filename = alloca (name_len + dsym_len + base_len + 1); bfd *dsym_bfd; - asection *sect; - bfd_byte main_uuid[16]; - bfd_byte dsym_uuid[16]; + bfd_mach_o_load_command *main_uuid; + bfd_mach_o_load_command *dsym_uuid; strcpy (dsym_filename, objfile->name); strcpy (dsym_filename + name_len, DSYM_SUFFIX); @@ -466,19 +529,12 @@ macho_check_dsym (struct objfile *objfile) if (access (dsym_filename, R_OK) != 0) return NULL; - sect = bfd_get_section_by_name (objfile->obfd, "LC_UUID"); - if (sect == NULL) + if (bfd_mach_o_lookup_command (objfile->obfd, + BFD_MACH_O_LC_UUID, &main_uuid) == 0) { warning (_("can't find UUID in %s"), objfile->name); return NULL; } - if (!bfd_get_section_contents (objfile->obfd, sect, main_uuid, - 0, sizeof (main_uuid))) - { - warning (_("can't read UUID in %s"), objfile->name); - return NULL; - } - dsym_filename = xstrdup (dsym_filename); dsym_bfd = bfd_openr (dsym_filename, gnutarget); if (dsym_bfd == NULL) @@ -496,23 +552,16 @@ macho_check_dsym (struct objfile *objfile) return NULL; } - sect = bfd_get_section_by_name (dsym_bfd, "LC_UUID"); - if (sect == NULL) + if (bfd_mach_o_lookup_command (dsym_bfd, + BFD_MACH_O_LC_UUID, &dsym_uuid) == 0) { warning (_("can't find UUID in %s"), dsym_filename); bfd_close (dsym_bfd); xfree (dsym_filename); return NULL; } - if (!bfd_get_section_contents (dsym_bfd, sect, dsym_uuid, - 0, sizeof (dsym_uuid))) - { - warning (_("can't read UUID in %s"), dsym_filename); - bfd_close (dsym_bfd); - xfree (dsym_filename); - return NULL; - } - if (memcmp (dsym_uuid, main_uuid, sizeof (main_uuid))) + if (memcmp (dsym_uuid->command.uuid.uuid, main_uuid->command.uuid.uuid, + sizeof (main_uuid->command.uuid.uuid))) { warning (_("dsym file UUID doesn't match the one in %s"), objfile->name); bfd_close (dsym_bfd); @@ -520,11 +569,10 @@ macho_check_dsym (struct objfile *objfile) return NULL; } return dsym_bfd; - } static void -macho_symfile_read (struct objfile *objfile, int mainline) +macho_symfile_read (struct objfile *objfile, int symfile_flags) { bfd *abfd = objfile->obfd; struct cleanup *back_to; @@ -591,18 +639,18 @@ macho_symfile_read (struct objfile *objfile, int mainline) VEC_free (oso_el, oso_vector); oso_vector = NULL; - /* Now recurse: read dwarf from dsym. */ - symbol_file_add_from_bfd (dsym_bfd, 0, NULL, 0, 0); + /* Add the dsym file as a separate file. */ + symbol_file_add_separate (dsym_bfd, symfile_flags, objfile); /* Don't try to read dwarf2 from main file or shared libraries. */ - return; + return; } } if (dwarf2_has_info (objfile)) { /* DWARF 2 sections */ - dwarf2_build_psymtabs (objfile, mainline); + dwarf2_build_psymtabs (objfile); } /* Do not try to read .eh_frame/.debug_frame as they are not relocated @@ -683,6 +731,8 @@ static struct sym_fns macho_sym_fns = { macho_symfile_read, /* sym_read: read a symbol file into symtab */ macho_symfile_finish, /* sym_finish: finished with file, cleanup */ macho_symfile_offsets, /* sym_offsets: xlate external to internal form */ + default_symfile_segments, /* sym_segments: Get segment information from + a file. */ NULL /* next: pointer to next struct sym_fns */ };