add symbol qualifiers for mach-o to bfd/gas

bfd:

	* 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.

gas:

	* 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.

gas/testsuite:

	* 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.
This commit is contained in:
Iain Sandoe 2012-01-09 10:47:50 +00:00
parent 9f2f828a17
commit b22161d698
16 changed files with 750 additions and 221 deletions

View file

@ -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

View file

@ -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)
{
unsigned i, sect;
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;
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)

View file

@ -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_ */

View file

@ -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.

View file

@ -82,34 +82,9 @@ 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 ();
}
/* 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
delimiter, a warning is given and the string is truncated. On completion of
@ -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

View file

@ -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)

View file

@ -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.

View file

@ -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 }

View file

@ -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 }

View file

@ -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 }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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