diff options
-rw-r--r-- | bfd/ChangeLog | 20 | ||||
-rw-r--r-- | bfd/mach-o.c | 266 | ||||
-rw-r--r-- | bfd/mach-o.h | 18 | ||||
-rw-r--r-- | gas/ChangeLog | 17 | ||||
-rw-r--r-- | gas/config/obj-macho.c | 371 | ||||
-rw-r--r-- | gas/config/obj-macho.h | 10 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 12 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/err-syms-1.s | 12 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/err-syms-2.s | 15 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/err-syms-3.s | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/symbols-2.d | 7 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/symbols-2.s | 9 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/symbols-3.s | 111 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/symbols-4.s | 65 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/symbols-5.d | 11 | ||||
-rw-r--r-- | gas/testsuite/gas/mach-o/symbols-5.s | 17 |
16 files changed, 750 insertions, 221 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c5b2a1b..d820ad2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,23 @@ +2012-01-09 Iain Sandoe <idsandoe@googlemail.com> + + * mach-o.c (bfd_mach_o_bfd_copy_private_symbol_data): Implement. + (bfd_mach_o_write_symtab): Remove handling for indirect syms. + (bfd_mach_o_primary_symbol_sort_key): Likewise. + (bfd_mach_o_cf_symbols): Likewise. + (bfd_mach_o_sort_symbol_table): Remove. + (bfd_mach_o_mangle_symbols): Adjust arguments, remove handling + for indirect and dysymtab counts. Do the symbol sorting here. + (bfd_mach_o_build_dysymtab_command): Count the symbol types here. + Make the indirect symbols a TODO. + (bfd_mach_o_build_commands): Adjust call to bfd_mach_o_mangle_symbols. + (bfd_mach_o_make_empty_symbol): Specifically flag unset symbols with + a non-zero value. + (bfd_mach_o_read_symtab_symbol): Record the symbol index. + (bfd_mach_o_read_symtab_symbol): Adjust recording of global status. + * mach-o.h (mach_o_data_struct): Remove indirect and dysymtab entries. + (IS_MACHO_INDIRECT): Remove. + (SYM_MACHO_FIELDS_UNSET, SYM_MACHO_FIELDS_NOT_VALIDATED): New. + 2012-01-06 Nick Clifton <nickc@redhat.com> PR binutils/13121 diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 86012d5..07ca65a 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -533,10 +533,17 @@ bfd_mach_o_section_get_nbr_indirect (bfd *abfd, bfd_mach_o_section *sec) bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED, - asymbol *isymbol ATTRIBUTE_UNUSED, + asymbol *isymbol, bfd *obfd ATTRIBUTE_UNUSED, - asymbol *osymbol ATTRIBUTE_UNUSED) + asymbol *osymbol) { + bfd_mach_o_asymbol *os, *is; + os = (bfd_mach_o_asymbol *)osymbol; + is = (bfd_mach_o_asymbol *)isymbol; + os->n_type = is->n_type; + os->n_sect = is->n_sect; + os->n_desc = is->n_desc; + os->symbol.udata.i = is->symbol.udata.i; return TRUE; } @@ -1400,22 +1407,6 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command) { bfd_size_type str_index; bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; - - /* For a bare indirect symbol, the system tools expect that the symbol - value will be the string table offset for its referenced counterpart. - - Normally, indirect syms will not be written this way, but rather as - part of the dysymtab command. - - In either case, correct operation depends on the symbol table being - sorted such that the indirect symbols are at the end (since the - string table index is filled in below). */ - - if (IS_MACHO_INDIRECT (s->n_type)) - /* A pointer to the referenced symbol will be stored in the udata - field. Use that to find the string index. */ - s->symbol.value = - ((bfd_mach_o_asymbol *)s->symbol.udata.p)->symbol.udata.i; if (s->symbol.name == 0 || s->symbol.name[0] == '\0') /* An index of 0 always means the empty string. */ @@ -1423,11 +1414,6 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command) else { str_index = _bfd_stringtab_add (strtab, s->symbol.name, TRUE, FALSE); - /* Record the string index. This can be looked up by an indirect sym - which retains a pointer to its referenced counterpart, until it is - actually output. */ - if (IS_MACHO_INDIRECT (s->n_type)) - s->symbol.udata.i = str_index; if (str_index == (bfd_size_type) -1) goto err; @@ -1673,28 +1659,24 @@ bfd_mach_o_write_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) } static unsigned -bfd_mach_o_primary_symbol_sort_key (unsigned type) +bfd_mach_o_primary_symbol_sort_key (bfd_mach_o_asymbol *s) { - unsigned mtyp = type & BFD_MACH_O_N_TYPE; + unsigned mtyp = s->n_type & BFD_MACH_O_N_TYPE; /* Just leave debug symbols where they are (pretend they are local, and then they will just be sorted on position). */ - if (type & BFD_MACH_O_N_STAB) + if (s->n_type & BFD_MACH_O_N_STAB) return 0; - /* Sort indirects to last. */ - if (mtyp == BFD_MACH_O_N_INDR) - return 3; - /* Local (we should never see an undefined local AFAICT). */ - if (! (type & (BFD_MACH_O_N_EXT | BFD_MACH_O_N_PEXT))) + if (! (s->n_type & (BFD_MACH_O_N_EXT | BFD_MACH_O_N_PEXT))) return 0; /* Common symbols look like undefined externs. */ if (mtyp == BFD_MACH_O_N_UNDF) return 2; - /* A defined symbol that's not indirect or extern. */ + /* A defined non-local, non-debug symbol. */ return 1; } @@ -1705,8 +1687,8 @@ bfd_mach_o_cf_symbols (const void *a, const void *b) bfd_mach_o_asymbol *sb = *(bfd_mach_o_asymbol **) b; unsigned int soa, sob; - soa = bfd_mach_o_primary_symbol_sort_key (sa->n_type); - sob = bfd_mach_o_primary_symbol_sort_key (sb->n_type); + soa = bfd_mach_o_primary_symbol_sort_key (sa); + sob = bfd_mach_o_primary_symbol_sort_key (sb); if (soa < sob) return -1; @@ -1720,55 +1702,13 @@ bfd_mach_o_cf_symbols (const void *a, const void *b) return -1; if (sa->symbol.udata.i > sb->symbol.udata.i) return 1; + + /* This is probably an error. */ return 0; } - /* Unless it's an indirect the second sort key is name. */ - if (soa < 3) - return strcmp (sa->symbol.name, sb->symbol.name); - - /* Here be indirect symbols, which have different sort rules. */ - - /* Next sort key for indirect, is the section index. */ - if (sa->n_sect < sb->n_sect) - return -1; - - if (sa->n_sect > sb->n_sect) - return 1; - - /* Last sort key is the order of definition - which should be in line with - the value, since a stub size of 0 is meaninglesss. */ - - if (sa->symbol.value < sb->symbol.value) - return -1; - - if (sa->symbol.value > sb->symbol.value) - return 1; - - /* In the final analysis, this is probably an error ... but leave it alone - for now. */ - return 0; -} - -/* When this is finished, return the number of non-indirect symbols. */ - -static unsigned int -bfd_mach_o_sort_symbol_table (asymbol **symbols, unsigned int nin) -{ - qsort (symbols, (size_t) nin, sizeof (void *), bfd_mach_o_cf_symbols); - - /* Find the last non-indirect symbol. - There must be at least one non-indirect symbol otherwise there's - nothing for the indirect(s) to refer to. */ - do - { - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[nin - 1]; - if (IS_MACHO_INDIRECT (s->n_type)) - nin--; - else - break; - } while (nin - 1 > 0); - return nin; + /* The second sort key is name. */ + return strcmp (sa->symbol.name, sb->symbol.name); } /* Process the symbols. @@ -1784,18 +1724,14 @@ bfd_mach_o_sort_symbol_table (asymbol **symbols, unsigned int nin) (unsorted) ( ii) external defined (by name) - (iii) external undefined + (iii) external undefined/common (by name) ( iv) common (by name) - ( v) indirect - (by section) - (by position within section). - - (c) Indirect symbols are moved to the end of the list. */ +*/ static bfd_boolean -bfd_mach_o_mangle_symbols (bfd *abfd, bfd_mach_o_data_struct *mdata) +bfd_mach_o_mangle_symbols (bfd *abfd) { unsigned long i; asymbol **symbols = bfd_get_outsymbols (abfd); @@ -1807,11 +1743,15 @@ bfd_mach_o_mangle_symbols (bfd *abfd, bfd_mach_o_data_struct *mdata) { bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; - if (s->n_type == BFD_MACH_O_N_UNDF && !(s->symbol.flags & BSF_DEBUGGING)) + /* We use this value, which is out-of-range as a symbol index, to signal + that the mach-o-specific data are not filled in and need to be created + from the bfd values. It is much preferable for the application to do + this, since more meaningful diagnostics can be made that way. */ + + if (s->symbol.udata.i == SYM_MACHO_FIELDS_UNSET) { - /* As genuine Mach-O symbols type shouldn't be N_UNDF (undefined - symbols should be N_UNDEF | N_EXT), we suppose the back-end - values haven't been set. */ + /* No symbol information has been set - therefore determine + it from the bfd symbol flags/info. */ if (s->symbol.section == bfd_abs_section_ptr) s->n_type = BFD_MACH_O_N_ABS; else if (s->symbol.section == bfd_und_section_ptr) @@ -1821,9 +1761,13 @@ bfd_mach_o_mangle_symbols (bfd *abfd, bfd_mach_o_data_struct *mdata) s->n_desc |= BFD_MACH_O_N_WEAK_REF; /* mach-o automatically makes undefined symbols extern. */ s->n_type |= BFD_MACH_O_N_EXT; + s->symbol.flags |= BSF_GLOBAL; } else if (s->symbol.section == bfd_com_section_ptr) - s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT; + { + s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT; + s->symbol.flags |= BSF_GLOBAL; + } else s->n_type = BFD_MACH_O_N_SECT; @@ -1839,54 +1783,18 @@ bfd_mach_o_mangle_symbols (bfd *abfd, bfd_mach_o_data_struct *mdata) && s->symbol.name == NULL)) s->n_sect = s->symbol.section->target_index; - /* Unless we're looking at an indirect sym, note the input ordering. - We use this to keep local symbols ordered as per the input. */ - if (! IS_MACHO_INDIRECT (s->n_type)) - s->symbol.udata.i = i; + /* Number to preserve order for local and debug syms. */ + s->symbol.udata.i = i; } - /* Sort the symbols and determine how many will remain in the main symbol - table, and how many will be emitted as indirect (assuming that we will - be emitting a dysymtab). Renumber the sorted symbols so that the right - index will be found during indirection. */ - i = bfd_mach_o_sort_symbol_table (symbols, bfd_get_symcount (abfd)); - if (bfd_mach_o_should_emit_dysymtab ()) - { - /* Point at the first indirect symbol. */ - if (i < bfd_get_symcount (abfd)) - { - mdata->indirect_syms = &symbols[i]; - mdata->nindirect = bfd_get_symcount (abfd) - i; - /* This is, essentially, local to the output section of mach-o, - and therefore should be safe. */ - abfd->symcount = i; - } + /* Sort the symbols. */ + qsort ((void *) symbols, (size_t) bfd_get_symcount (abfd), + sizeof (asymbol *), bfd_mach_o_cf_symbols); - /* Now setup the counts for each type of symbol. */ - for (i = 0; i < bfd_get_symcount (abfd); ++i) - { - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; - s->symbol.udata.i = i; /* renumber. */ - if (s->n_type & (BFD_MACH_O_N_EXT | BFD_MACH_O_N_PEXT)) - break; - } - mdata->nlocal = i; - for (; i < bfd_get_symcount (abfd); ++i) - { - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; - s->symbol.udata.i = i; /* renumber. */ - if ((s->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_UNDF) - break; - } - mdata->ndefext = i - mdata->nlocal; - mdata->nundefext = bfd_get_symcount (abfd) - - mdata->ndefext - - mdata->nlocal; - for (; i < bfd_get_symcount (abfd); ++i) - { - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; - s->symbol.udata.i = i; /* renumber. */ - } + for (i = 0; i < bfd_get_symcount (abfd); ++i) + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; + s->symbol.udata.i = i; /* renumber. */ } return TRUE; @@ -2179,43 +2087,58 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd, } dsym->ilocalsym = 0; - dsym->nlocalsym = mdata->nlocal; - dsym->iextdefsym = dsym->nlocalsym; - dsym->nextdefsym = mdata->ndefext; - dsym->iundefsym = dsym->nextdefsym + dsym->iextdefsym; - dsym->nundefsym = mdata->nundefext; - if (mdata->nindirect > 0) + if (bfd_get_symcount (abfd) > 0) + { + asymbol **symbols = bfd_get_outsymbols (abfd); + unsigned long i; + + /* Count the number of each kind of symbol. */ + for (i = 0; i < bfd_get_symcount (abfd); ++i) + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; + if (s->n_type & (BFD_MACH_O_N_EXT | BFD_MACH_O_N_PEXT)) + break; + } + dsym->nlocalsym = i; + dsym->iextdefsym = i; + for (; i < bfd_get_symcount (abfd); ++i) + { + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; + if ((s->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_UNDF) + break; + } + dsym->nextdefsym = i - dsym->nlocalsym; + dsym->iundefsym = dsym->nextdefsym + dsym->iextdefsym; + dsym->nundefsym = bfd_get_symcount (abfd) + - dsym->nlocalsym + - dsym->nextdefsym; + } + else + { + dsym->nlocalsym = 0; + dsym->iextdefsym = 0; + dsym->nextdefsym = 0; + dsym->iundefsym = 0; + dsym->nundefsym = 0; + } + + if (dsym->nindirectsyms > 0) { - unsigned i, sect; + unsigned i; mdata->filelen = FILE_ALIGN (mdata->filelen, 2); dsym->indirectsymoff = mdata->filelen; - mdata->filelen += mdata->nindirect * 4; + mdata->filelen += dsym->nindirectsyms * 4; - dsym->indirect_syms = bfd_zalloc (abfd, mdata->nindirect * 4); + dsym->indirect_syms = bfd_zalloc (abfd, dsym->nindirectsyms * 4); if (dsym->indirect_syms == NULL) return FALSE; - dsym->nindirectsyms = mdata->nindirect; - /* So fill in the indices, and point the section reserved1 fields - at the right one. */ - sect = (unsigned) -1; - for (i = 0; i < mdata->nindirect; ++i) + /* So fill in the indices. */ + for (i = 0; i < dsym->nindirectsyms; ++i) { - bfd_mach_o_asymbol *s = - (bfd_mach_o_asymbol *) mdata->indirect_syms[i]; - /* Lookup the index of the referenced symbol. */ - dsym->indirect_syms[i] = - ((bfd_mach_o_asymbol *) s->symbol.udata.p)->symbol.udata.i; - if (s->n_sect != sect) - { - /* Mach-o sections are 1-based, but the section table - is 0-based. */ - bfd_mach_o_section *sc = mdata->sections[s->n_sect-1]; - sc->reserved1 = i; - sect = s->n_sect; - } + /* TODO: fill in the table. */ } } @@ -2261,7 +2184,7 @@ bfd_mach_o_build_commands (bfd *abfd) /* Order the symbol table, fill-in/check mach-o specific fields and partition out any indirect symbols. */ - if (!bfd_mach_o_mangle_symbols (abfd, mdata)) + if (!bfd_mach_o_mangle_symbols (abfd)) return FALSE; /* It's valid to have a file with only absolute symbols... */ @@ -2423,7 +2346,7 @@ bfd_mach_o_make_empty_symbol (bfd *abfd) if (new_symbol == NULL) return new_symbol; new_symbol->the_bfd = abfd; - new_symbol->udata.i = 0; + new_symbol->udata.i = SYM_MACHO_FIELDS_UNSET; return new_symbol; } @@ -2751,7 +2674,7 @@ bfd_mach_o_read_symtab_symbol (bfd *abfd, s->symbol.name = sym->strtab + stroff; s->symbol.value = value; s->symbol.flags = 0x0; - s->symbol.udata.i = 0; + s->symbol.udata.i = i; s->n_type = type; s->n_sect = section; s->n_desc = desc; @@ -2782,13 +2705,9 @@ bfd_mach_o_read_symtab_symbol (bfd *abfd, } else { - if (type & BFD_MACH_O_N_PEXT) + if (type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)) s->symbol.flags |= BSF_GLOBAL; - - if (type & BFD_MACH_O_N_EXT) - s->symbol.flags |= BSF_GLOBAL; - - if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT))) + else s->symbol.flags |= BSF_LOCAL; switch (symtype) @@ -3989,6 +3908,7 @@ bfd_mach_o_header_p (bfd *abfd, if (header.cputype != cputype) goto wrong; } + if (filetype) { if (header.filetype != filetype) diff --git a/bfd/mach-o.h b/bfd/mach-o.h index 123edda..ca810a0 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -549,18 +549,6 @@ typedef struct mach_o_data_struct bfd_mach_o_symtab_command *symtab; bfd_mach_o_dysymtab_command *dysymtab; - /* Base values used for building the dysymtab for a single-module object. */ - unsigned long nlocal; - unsigned long ndefext; - unsigned long nundefext; - - /* If this is non-zero, then the pointer below is populated. */ - unsigned long nindirect; - /* A set of synthetic symbols representing the 'indirect' ones in the file. - These should be sorted (a) by the section they represent and (b) by the - order that they appear within each section. */ - asymbol **indirect_syms; - /* A place to stash dwarf2 info for this bfd. */ void *dwarf2_find_line_info; @@ -691,8 +679,10 @@ typedef struct bfd_mach_o_backend_data } bfd_mach_o_backend_data; -/* Symbol type tests. */ +/* Values used in symbol.udata.i, to signal that the mach-o-specific data in the + symbol are not yet set, or need validation (where this is possible). */ -#define IS_MACHO_INDIRECT(x) (((x) & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_INDR) +#define SYM_MACHO_FIELDS_UNSET ((bfd_vma) -1) +#define SYM_MACHO_FIELDS_NOT_VALIDATED ((bfd_vma) -2) #endif /* _BFD_MACH_O_H_ */ diff --git a/gas/ChangeLog b/gas/ChangeLog index c905439..1d72c39 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2012-01-09 Iain Sandoe <idsandoe@googlemail.com> + + * config/obj-macho.c (obj_mach_o_weak): Remove. + (obj_mach_o_common_parse): Set symbol qualifiers. + (LAZY, REFE): New macros. + (obj_mach_o_symbol_type): New enum. + (obj_mach_o_set_symbol_qualifier): New. + (obj_mach_o_sym_qual): New. + (mach_o_pseudo_table): Add symbol qualifiers, set indirect_symbol to + a dummy function. + (obj_mach_o_type_for_symbol): New. + (obj_macho_frob_label): New. + (obj_macho_frob_symbol): New. + * config/obj-macho.h (S_SET_ALIGN): Amend temorary var name. + (obj_frob_label, obj_macho_frob_label): Declare. + (obj_frob_symbol, obj_macho_frob_symbol): Declare. + 2012-01-08 Richard Sandiford <rdsandiford@googlemail.com> * config/tc-mips.c (s_tls_rel_directive): Call mips_clear_insn_labels. diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c index b523767..43f4fba 100644 --- a/gas/config/obj-macho.c +++ b/gas/config/obj-macho.c @@ -82,33 +82,8 @@ mach_o_begin (void) /* Remember the subsections_by_symbols state in case we need to reset the file flags. */ -static int obj_mach_o_subsections_by_symbols; -static void -obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED) -{ - char *name; - int c; - symbolS *symbolP; - - do - { - /* Get symbol name. */ - name = input_line_pointer; - c = get_symbol_end (); - symbolP = symbol_find_or_make (name); - S_SET_WEAK (symbolP); - *input_line_pointer = c; - SKIP_WHITESPACE (); - - if (c != ',') - break; - input_line_pointer++; - SKIP_WHITESPACE (); - } - while (*input_line_pointer != '\n'); - demand_empty_rest_of_line (); -} +static int obj_mach_o_subsections_by_symbols; /* This will put at most 16 characters (terminated by a ',' or newline) from the input stream into dest. If there are more than 16 chars before the @@ -901,6 +876,7 @@ obj_mach_o_common_parse (int is_local, symbolS *symbolP, addressT size) { addressT align = 0; + bfd_mach_o_asymbol *s; SKIP_WHITESPACE (); @@ -920,6 +896,7 @@ obj_mach_o_common_parse (int is_local, symbolS *symbolP, } } + s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (symbolP); if (is_local) { /* Create the BSS section on demand. */ @@ -929,6 +906,7 @@ obj_mach_o_common_parse (int is_local, symbolS *symbolP, seg_info (bss_section)->bss = 1; } bss_alloc (symbolP, size, align); + s->n_type = BFD_MACH_O_N_SECT; S_CLEAR_EXTERNAL (symbolP); } else @@ -937,9 +915,14 @@ obj_mach_o_common_parse (int is_local, symbolS *symbolP, S_SET_ALIGN (symbolP, align); S_SET_EXTERNAL (symbolP); S_SET_SEGMENT (symbolP, bfd_com_section_ptr); + s->n_type = BFD_MACH_O_N_UNDF | BFD_MACH_O_N_EXT; } - symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT; + /* This is a data object (whatever we choose that to mean). */ + s->symbol.flags |= BSF_OBJECT; + + /* We've set symbol qualifiers, so validate if you can. */ + s->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED; return symbolP; } @@ -979,6 +962,175 @@ obj_mach_o_fileprop (int prop) } } +/* Temporary markers for symbol reference data. + Lazy will remain in place. */ +#define LAZY 0x01 +#define REFE 0x02 + +/* We have a bunch of qualifiers that may be applied to symbols. + .globl is handled here so that we might make sure that conflicting qualifiers + are caught where possible. */ + +typedef enum obj_mach_o_symbol_type { + OBJ_MACH_O_SYM_UNK = 0, + OBJ_MACH_O_SYM_LOCAL = 1, + OBJ_MACH_O_SYM_GLOBL = 2, + OBJ_MACH_O_SYM_REFERENCE = 3, + OBJ_MACH_O_SYM_WEAK_REF = 4, + OBJ_MACH_O_SYM_LAZY_REF = 5, + OBJ_MACH_O_SYM_WEAK_DEF = 6, + OBJ_MACH_O_SYM_PRIV_EXT = 7, + OBJ_MACH_O_SYM_NO_DEAD_STRIP = 8, + OBJ_MACH_O_SYM_WEAK = 9 +} obj_mach_o_symbol_type; + +/* Set Mach-O-specific symbol qualifiers. */ + +static int +obj_mach_o_set_symbol_qualifier (symbolS *sym, int type) +{ + int is_defined; + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sym); + bfd_mach_o_section *sec; + int sectype = -1; + int err = 0; + + /* If the symbol is defined, then we can do more rigorous checking on + the validity of the qualifiers. Otherwise, we are stuck with waiting + until it's defined - or until write the file. + + In certain cases (e.g. when a symbol qualifier is intended to introduce + an undefined symbol in a stubs section) we should check that the current + section is appropriate to the qualifier. */ + + is_defined = s->symbol.section != bfd_und_section_ptr; + if (is_defined) + sec = bfd_mach_o_get_mach_o_section (s->symbol.section) ; + else + sec = bfd_mach_o_get_mach_o_section (now_seg) ; + + if (sec != NULL) + sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK; + + switch ((obj_mach_o_symbol_type) type) + { + case OBJ_MACH_O_SYM_LOCAL: + /* This is an extension over the system tools. */ + if (s->n_type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)) + { + as_bad (_("'%s' previously declared as '%s'."), s->symbol.name, + (s->n_type & BFD_MACH_O_N_PEXT) ? "private extern" + : "global" ); + err = 1; + } + else + { + s->n_type &= ~BFD_MACH_O_N_EXT; + S_CLEAR_EXTERNAL (sym); + } + break; + + case OBJ_MACH_O_SYM_PRIV_EXT: + s->n_type |= BFD_MACH_O_N_PEXT ; + /* We follow the system tools in marking PEXT as also global. */ + /* Fall through. */ + + case OBJ_MACH_O_SYM_GLOBL: + /* It's not an error to define a symbol and then make it global. */ + s->n_type |= BFD_MACH_O_N_EXT; + S_SET_EXTERNAL (sym); + break; + + case OBJ_MACH_O_SYM_REFERENCE: + if (is_defined) + s->n_desc |= BFD_MACH_O_N_NO_DEAD_STRIP; + else + s->n_desc |= (REFE | BFD_MACH_O_N_NO_DEAD_STRIP); + break; + + case OBJ_MACH_O_SYM_LAZY_REF: + if (is_defined) + s->n_desc |= BFD_MACH_O_N_NO_DEAD_STRIP; + else + s->n_desc |= (REFE | LAZY | BFD_MACH_O_N_NO_DEAD_STRIP); + break; + + /* Force ld to retain the symbol - even if it appears unused. */ + case OBJ_MACH_O_SYM_NO_DEAD_STRIP: + s->n_desc |= BFD_MACH_O_N_NO_DEAD_STRIP ; + break; + + /* Mach-O's idea of weak ... */ + case OBJ_MACH_O_SYM_WEAK_REF: + s->n_desc |= BFD_MACH_O_N_WEAK_REF ; + break; + + case OBJ_MACH_O_SYM_WEAK_DEF: + if (is_defined && sectype != BFD_MACH_O_S_COALESCED) + { + as_bad (_("'%s' can't be a weak_definition (currently only" + " supported in sections of type coalesced)"), + s->symbol.name); + err = 1; + } + else + s->n_desc |= BFD_MACH_O_N_WEAK_DEF; + break; + + case OBJ_MACH_O_SYM_WEAK: + /* A generic 'weak' - we try to figure out what it means at + symbol frob time. */ + S_SET_WEAK (sym); + break; + + default: + break; + } + + /* We've seen some kind of qualifier - check validity if or when the entity + is defined. */ + s->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED; + return err; +} + +/* Respond to symbol qualifiers. + All of the form: + .<qualifier> symbol [, symbol]* + a list of symbols is an extension over the Darwin system as. */ + +static void +obj_mach_o_sym_qual (int ntype) +{ + char *name; + char c; + symbolS *symbolP; + +#ifdef md_flush_pending_output + md_flush_pending_output (); +#endif + + do + { + name = input_line_pointer; + c = get_symbol_end (); + symbolP = symbol_find_or_make (name); + obj_mach_o_set_symbol_qualifier (symbolP, ntype); + *input_line_pointer = c; + SKIP_WHITESPACE (); + c = *input_line_pointer; + if (c == ',') + { + input_line_pointer++; + SKIP_WHITESPACE (); + if (is_end_of_line[(unsigned char) *input_line_pointer]) + c = '\n'; + } + } + while (c == ','); + + demand_empty_rest_of_line (); +} + /* Dummy function to allow test-code to work while we are working on things. */ @@ -1068,11 +1220,18 @@ const pseudo_typeS mach_o_pseudo_table[] = { "section", obj_mach_o_section, 0}, { "zerofill", obj_mach_o_zerofill, 0}, - /* Symbol-related. */ - { "indirect_symbol", obj_mach_o_placeholder, 0}, - { "weak_definition", obj_mach_o_placeholder, 0}, - { "private_extern", obj_mach_o_placeholder, 0}, - { "weak", obj_mach_o_weak, 0}, /* extension */ + /* Symbol qualifiers. */ + {"local", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_LOCAL}, + {"globl", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_GLOBL}, + {"reference", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_REFERENCE}, + {"weak_reference", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_WEAK_REF}, + {"lazy_reference", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_LAZY_REF}, + {"weak_definition", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_WEAK_DEF}, + {"private_extern", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_PRIV_EXT}, + {"no_dead_strip", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_NO_DEAD_STRIP}, + {"weak", obj_mach_o_sym_qual, OBJ_MACH_O_SYM_WEAK}, /* ext */ + + {"indirect_symbol", obj_mach_o_placeholder, 0}, /* File flags. */ { "subsections_via_symbols", obj_mach_o_fileprop, @@ -1081,6 +1240,154 @@ const pseudo_typeS mach_o_pseudo_table[] = {NULL, NULL, 0} }; +/* Determine the default n_type value for a symbol from its section. */ + +static unsigned +obj_mach_o_type_for_symbol (bfd_mach_o_asymbol *s) +{ + if (s->symbol.section == bfd_abs_section_ptr) + return BFD_MACH_O_N_ABS; + else if (s->symbol.section == bfd_com_section_ptr + || s->symbol.section == bfd_und_section_ptr) + return BFD_MACH_O_N_UNDF; + else + return BFD_MACH_O_N_SECT; +} + +/* We need to check the correspondence between some kinds of symbols and their + sections. Common and BSS vars will seen via the obj_macho_comm() function. + + The earlier we can pick up a problem, the better the diagnostics will be. + + However, when symbol type information is attached, the symbol section will + quite possibly be unknown. So we are stuck with checking (most of the) + validity at the time the file is written (unfortunately, then one doesn't + get line number information in the diagnostic). */ + +/* Here we pick up the case where symbol qualifiers have been applied that + are possibly incompatible with the section etc. that the symbol is defined + in. */ + +void obj_macho_frob_label (struct symbol *sp) +{ + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp); + /* This is the base symbol type, that we mask in. */ + unsigned base_type = obj_mach_o_type_for_symbol (s); + bfd_mach_o_section *sec = bfd_mach_o_get_mach_o_section (s->symbol.section); + int sectype = -1; + + if ((s->n_type & BFD_MACH_O_N_STAB) != 0) + return; /* Leave alone. */ + + if (sec != NULL) + sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK; + + /* If there is a pre-existing qualifier, we can make some checks about + validity now. */ + + if(s->symbol.udata.i == SYM_MACHO_FIELDS_NOT_VALIDATED) + { + if ((s->n_desc & BFD_MACH_O_N_WEAK_DEF) + && sectype != BFD_MACH_O_S_COALESCED) + as_bad (_("'%s' can't be a weak_definition (currently only supported" + " in sections of type coalesced)"), s->symbol.name); + + /* Have we changed from an undefined to defined ref? */ + s->n_desc &= ~(REFE | LAZY); + } + + s->n_type &= ~BFD_MACH_O_N_TYPE; + s->n_type |= base_type; +} + +/* This is the fall-back, we come here when we get to the end of the file and + the symbol is not defined - or there are combinations of qualifiers required + (e.g. global + weak_def). */ + +int +obj_macho_frob_symbol (struct symbol *sp) +{ + bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp); + unsigned base_type = obj_mach_o_type_for_symbol (s); + bfd_mach_o_section *sec = bfd_mach_o_get_mach_o_section (s->symbol.section); + int sectype = -1; + + if (sec != NULL) + sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK; + + if ((s->n_type & BFD_MACH_O_N_STAB) != 0) + return 0; /* Leave alone. */ + else if (s->symbol.section == bfd_und_section_ptr) + { + /* ??? Do we really gain much from implementing this as well as the + mach-o specific ones? */ + if (s->symbol.flags & BSF_WEAK) + s->n_desc |= BFD_MACH_O_N_WEAK_REF; + + /* Undefined references, become extern. */ + if (s->n_desc & REFE) + { + s->n_desc &= ~REFE; + s->n_type |= BFD_MACH_O_N_EXT; + } + + /* So do undefined 'no_dead_strip's. */ + if (s->n_desc & BFD_MACH_O_N_NO_DEAD_STRIP) + s->n_type |= BFD_MACH_O_N_EXT; + + } + else + { + if ((s->symbol.flags & BSF_WEAK) + && (sectype == BFD_MACH_O_S_COALESCED) + && (s->n_type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT))) + s->n_desc |= BFD_MACH_O_N_WEAK_DEF; +/* ??? we should do this - but then that reveals that the semantics of weak + are different from what's supported in mach-o object files. + else + as_bad (_("'%s' can't be a weak_definition."), + s->symbol.name); */ + } + + if (s->symbol.udata.i == SYM_MACHO_FIELDS_UNSET) + { + /* Anything here that should be added that is non-standard. */ + s->n_desc &= ~BFD_MACH_O_REFERENCE_MASK; + } + else if (s->symbol.udata.i == SYM_MACHO_FIELDS_NOT_VALIDATED) + { + /* Try to validate any combinations. */ + if (s->n_desc & BFD_MACH_O_N_WEAK_DEF) + { + if (s->symbol.section == bfd_und_section_ptr) + as_bad (_("'%s' can't be a weak_definition (since it is" + " undefined)"), s->symbol.name); + else if (sectype != BFD_MACH_O_S_COALESCED) + as_bad (_("'%s' can't be a weak_definition (currently only supported" + " in sections of type coalesced)"), s->symbol.name); + else if (! (s->n_type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT))) + as_bad (_("Non-global symbol: '%s' can't be a weak_definition."), + s->symbol.name); + } + + } + else + as_bad (_("internal error: [%s] unexpected code [%lx] in frob symbol"), + s->symbol.name, (unsigned long)s->symbol.udata.i); + + s->n_type &= ~BFD_MACH_O_N_TYPE; + s->n_type |= base_type; + + if (s->symbol.flags & BSF_GLOBAL) + s->n_type |= BFD_MACH_O_N_EXT; + + /* This cuts both ways - we promote some things to external above. */ + if (s->n_type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT)) + S_SET_EXTERNAL (sp); + + return 0; +} + /* Support stabs for mach-o. */ void diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h index b2acd17..cbc3a4f 100644 --- a/gas/config/obj-macho.h +++ b/gas/config/obj-macho.h @@ -40,8 +40,8 @@ extern void mach_o_begin (void); /* Common symbols can carry alignment information. */ #ifndef S_SET_ALIGN #define S_SET_ALIGN(S,V) do {\ - bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (S);\ - s->n_desc = (s->n_desc & 0xf0ff) | (((V) & 0x0f) << 8);\ + bfd_mach_o_asymbol *___s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (S);\ + ___s->n_desc = (___s->n_desc & 0xf0ff) | (((V) & 0x0f) << 8);\ } while (0) #endif @@ -56,6 +56,12 @@ extern const pseudo_typeS mach_o_pseudo_table[]; #define obj_read_begin_hook() {;} #define obj_symbol_new_hook(s) {;} +#define obj_frob_label(s) obj_macho_frob_label(s) +extern void obj_macho_frob_label (struct symbol *); + +#define obj_frob_symbol(s, punt) punt = obj_macho_frob_symbol(s) +extern int obj_macho_frob_symbol (struct symbol *); + #define EMIT_SECTION_SYMBOLS 0 #define OBJ_PROCESS_STAB(SEG,W,S,T,O,D) obj_mach_o_process_stab(W,S,T,O,D) diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index c638cdc..3176c0c 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2012-01-09 Iain Sandoe <idsandoe@googlemail.com> + + * gas/mach-o/err-syms-1.s: New. + * gas/mach-o/err-syms-2.s: New. + * gas/mach-o/err-syms-3.s: New. + * gas/mach-o/symbols-2.d: New. + * gas/mach-o/symbols-2.s: New. + * gas/mach-o/symbols-3.s: New. + * gas/mach-o/symbols-4.s: New. + * gas/mach-o/symbols-5.d: New. + * gas/mach-o/symbols-5.s: New. + 2012-01-08 Richard Sandiford <rdsandiford@googlemail.com> * gas/mips/tls-relw.s, gas/mips/tls-relw.d: New test. diff --git a/gas/testsuite/gas/mach-o/err-syms-1.s b/gas/testsuite/gas/mach-o/err-syms-1.s new file mode 100644 index 0000000..84146c7 --- /dev/null +++ b/gas/testsuite/gas/mach-o/err-syms-1.s @@ -0,0 +1,12 @@ +# { dg-do assemble } + + .globl a +a: .space 1 + .local a + + .private_extern b +b: .space 1 + .local b + +# { dg-error ".a. previously declared as .global." "" { target *-*-darwin*} 5 } +# { dg-error ".b. previously declared as .private extern." "" { target *-*-darwin*} 9 } diff --git a/gas/testsuite/gas/mach-o/err-syms-2.s b/gas/testsuite/gas/mach-o/err-syms-2.s new file mode 100644 index 0000000..ad4a692 --- /dev/null +++ b/gas/testsuite/gas/mach-o/err-syms-2.s @@ -0,0 +1,15 @@ +# { dg-do assemble } + + .section __weak, __weak, coalesced + +a: .space 1 + .weak_definition a + + .weak_definition b +b: .space 1 + + .weak_definition c + +# { dg-error "Non-global symbol: .a. can.t be a weak_definition." "" { target *-*-darwin*} 0 } +# { dg-error "Non-global symbol: .b. can.t be a weak_definition." "" { target *-*-darwin*} 0 } +# { dg-error ".c. can.t be a weak_definition .since it is undefined." "" { target *-*-darwin*} 0 } diff --git a/gas/testsuite/gas/mach-o/err-syms-3.s b/gas/testsuite/gas/mach-o/err-syms-3.s new file mode 100644 index 0000000..8315d86 --- /dev/null +++ b/gas/testsuite/gas/mach-o/err-syms-3.s @@ -0,0 +1,10 @@ +# { dg-do assemble } + + .weak_definition a +a: .space 1 + +b: .space 1 + .weak_definition b + +# { dg-error ".a. can.t be a weak_definition .currently only supported in sections of type coalesced." "" { target *-*-darwin*} 4 } +# { dg-error ".b. can.t be a weak_definition .currently only supported in sections of type coalesced." "" { target *-*-darwin*} 7 } diff --git a/gas/testsuite/gas/mach-o/symbols-2.d b/gas/testsuite/gas/mach-o/symbols-2.d new file mode 100644 index 0000000..c4bfcbd --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-2.d @@ -0,0 +1,7 @@ +#objdump: -t +# weak_definitions. +.*: +file format mach-o.* +#... +SYMBOL TABLE: +(00000000)?00000000 g.*1f SECT.*02 0080 \[__weak.__weak\] a +(00000000)?00000001 g.*0f SECT.*02 0080 \[__weak.__weak\] b diff --git a/gas/testsuite/gas/mach-o/symbols-2.s b/gas/testsuite/gas/mach-o/symbols-2.s new file mode 100644 index 0000000..2ba36d1 --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-2.s @@ -0,0 +1,9 @@ + .section __weak, __weak, coalesced + + .private_extern a + .weak_definition a +a: .space 1 + + .globl b + .weak_definition b +b: .space 1 diff --git a/gas/testsuite/gas/mach-o/symbols-3.s b/gas/testsuite/gas/mach-o/symbols-3.s new file mode 100644 index 0000000..054fdf6 --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-3.s @@ -0,0 +1,111 @@ +# indirect references, stubs and {non,}_lazy_symbol_pointer sections. +# not applicable to x86_64 mach-o. + + .text + .globl c + .globl c1 + .globl c2 +c: nop +c1: nop +c2: nop + +e: nop +e1: nop +e2: nop + + .data +d: .space 8 +d1: .space 8 +d2: .space 8 + + .private_extern f + .private_extern f1 + .private_extern f2 +f: .space 8 +f1: .space 8 +f2: .space 8 + + .section __dummy, __dummy, symbol_stubs,strip_static_syms,8 + + .indirect_symbol a +La: .space 8 + + .indirect_symbol b +Lb: .space 8 + + .indirect_symbol c +Lc: .space 8 + + .indirect_symbol d +Ld: .space 8 + + .indirect_symbol e +Le: .space 8 + + .indirect_symbol f +Lf: .space 8 + + .private_extern g + .indirect_symbol g +Lg: .space 8 + + .lazy_symbol_pointer + + .indirect_symbol a1 +La1: .space 4 + + .indirect_symbol b1 +Lb1: .space 4 + + .indirect_symbol c1 +Lc1: .space 4 + + .indirect_symbol d1 +Ld1: .space 4 + + .indirect_symbol e1 +Le1: .space 4 + + .indirect_symbol f1 +Lf1: .space 4 + + .private_extern g1 + .indirect_symbol g1 +Lg1: .space 4 + + .non_lazy_symbol_pointer + + .indirect_symbol a2 +La2: .space 4 + + .indirect_symbol b2 +Lb2: .space 4 + + .indirect_symbol c2 +Lc2: .space 4 + + .indirect_symbol d2 +Ld2: .space 4 + + .indirect_symbol e2 +Le2: .space 4 + + .indirect_symbol f2 +Lf2: .space 4 + + .private_extern g2 + .indirect_symbol g2 +Lg2: .space 4 + + .indirect_symbol f1 +Lf11: .space 4 + + .private_extern g1 + .indirect_symbol g1 +Lg11: .space 4 + + .indirect_symbol a2 +La12: .space 4 + + .indirect_symbol b2 +Lb12: .space 4 diff --git a/gas/testsuite/gas/mach-o/symbols-4.s b/gas/testsuite/gas/mach-o/symbols-4.s new file mode 100644 index 0000000..8800806 --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-4.s @@ -0,0 +1,65 @@ +# Reference & dead strip permutations. + + .text + + .reference ua + .lazy_reference ub + + .reference ua1 + .private_extern ua1 + + .private_extern ub1 + .lazy_reference ub1 + +c: .space 1 + .reference c + +d: .space 1 + .lazy_reference d + + .reference c1 +c1: .space 1 + + .lazy_reference d1 +d1: .space 1 + + .private_extern e + .reference e + + .private_extern f + .lazy_reference f + +g: .space 1 + .private_extern g + .reference g + +h: .space 1 + .private_extern h + .lazy_reference h + + .private_extern g1 + .reference g1 +g1: .space 1 + + .private_extern h1 + .lazy_reference h1 +h1: .space 1 + + .no_dead_strip n + + .globl m + .no_dead_strip m + + .private_extern p + .no_dead_strip p + +n1: .space 1 + .no_dead_strip n1 + +m1: .space 1 + .globl m1 + .no_dead_strip m1 + +p1: .space 1 + .private_extern p1 + .no_dead_strip p1 diff --git a/gas/testsuite/gas/mach-o/symbols-5.d b/gas/testsuite/gas/mach-o/symbols-5.d new file mode 100644 index 0000000..7f87e74 --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-5.d @@ -0,0 +1,11 @@ +#objdump: -t +# globals and private_externs +.*: +file format mach-o.* +#... +SYMBOL TABLE: +(00000000)?00000000 g.*1f SECT.*01 0000 \[.text\] a +(00000000)?00000001 g.*0f SECT.*01 0000 \[.text\] b +(00000000)?00000002 g.*1f SECT.*01 0000 \[.text\] c +(00000000)?00000000 g.*11 UND.*00 0000 d +(00000000)?00000000 g.*01 UND.*00 0000 e +(00000000)?00000000 g.*11 UND.*00 0000 f diff --git a/gas/testsuite/gas/mach-o/symbols-5.s b/gas/testsuite/gas/mach-o/symbols-5.s new file mode 100644 index 0000000..a43266d --- /dev/null +++ b/gas/testsuite/gas/mach-o/symbols-5.s @@ -0,0 +1,17 @@ + + .private_extern a +a: .space 1 + + .globl b +b: .space 1 + + .private_extern c + .globl c +c: .space 1 + + .private_extern d + + .globl e + + .globl f + .private_extern f |