aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog20
-rw-r--r--bfd/mach-o.c266
-rw-r--r--bfd/mach-o.h18
-rw-r--r--gas/ChangeLog17
-rw-r--r--gas/config/obj-macho.c371
-rw-r--r--gas/config/obj-macho.h10
-rw-r--r--gas/testsuite/ChangeLog12
-rw-r--r--gas/testsuite/gas/mach-o/err-syms-1.s12
-rw-r--r--gas/testsuite/gas/mach-o/err-syms-2.s15
-rw-r--r--gas/testsuite/gas/mach-o/err-syms-3.s10
-rw-r--r--gas/testsuite/gas/mach-o/symbols-2.d7
-rw-r--r--gas/testsuite/gas/mach-o/symbols-2.s9
-rw-r--r--gas/testsuite/gas/mach-o/symbols-3.s111
-rw-r--r--gas/testsuite/gas/mach-o/symbols-4.s65
-rw-r--r--gas/testsuite/gas/mach-o/symbols-5.d11
-rw-r--r--gas/testsuite/gas/mach-o/symbols-5.s17
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