[Patch mach-o, indirect symbols 1/2] support indirect symbols in mach-o.

Iain Sandoe developer@sandoe-acoustics.co.uk
Tue Jan 3 20:14:00 GMT 2012


Hi Tristan,

On 3 Jan 2012, at 16:44, Iain Sandoe wrote:
>
> Well, OK, the simplest solution is to keep the code mechanism as is  
> - but to use a new/different flag to signal .indirect_symbols .. the  
> sorting etc. doesn't really need to change (just the bits using  
> IS_MACHO_INDIRECT - which needs to utilize a different flag) .. any  
> suggestions about the Right Flag  (or a new one)?
>
> The GAS end will need amending to use a SET_MACHO_INDIRECT .. but  
> that's also not too too bad...

So, here's a revised patch -
  that uses (BSF_INDIRECT | BSF_SYNTHETIC) as the 'signal' from gas ->  
bfd that the symbol is a mach_o .indirect_symbol
  these symbols are also unnamed (could be used as a third key if  
there is a meaning - can't think of one tonight - to (BSF_INDIRECT |  
BSF_SYNTHETIC)).

- it's a proof-of-principle (but ISTM it's likely OK for the current  
usage).

the sorting and extraction (and other qualifiers) are unaltered.

As far as documentation of the sorting of external symbols -
- well, I think I read it somewhere (might have been in the code) I  
couldn't find it quickly in the Mach-o or assembler doc.

In reality, the determining factor is what the native tools do -  
because that's what the native linker will expect .. and the native  
'as' definitely sorts as per what we have here.  My usual test is a  
one-to-one between as and gas/as-new on the same source.

wdyt? OK?
Iain


====


diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 26fde7d..600aa39 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -531,10 +531,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;
  }

@@ -1352,22 +1359,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.  */
@@ -1375,11 +1366,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;
@@ -1625,21 +1611,21 @@ 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)
+  if (IS_MACHO_INDIRECT (s))
      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.  */
@@ -1657,8 +1643,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;

@@ -1715,7 +1701,7 @@ bfd_mach_o_sort_symbol_table (asymbol **symbols,  
unsigned int nin)
    do
      {
        bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[nin - 1];
-      if (IS_MACHO_INDIRECT (s->n_type))
+      if (IS_MACHO_INDIRECT (s))
  	nin--;
        else
  	break;
@@ -1759,11 +1745,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 == (bfd_vma) -1)
          {
-          /* 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)
@@ -1793,7 +1783,7 @@ bfd_mach_o_mangle_symbols (bfd *abfd,  
bfd_mach_o_data_struct *mdata)

        /* 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))
+      if (! IS_MACHO_INDIRECT (s))
  	s->symbol.udata.i = i;
      }

@@ -2315,7 +2305,8 @@ bfd_mach_o_build_commands (bfd *abfd)
    /* So, now we have sized the commands and the filelen set to that.
       Now we can build the segment command and set the section file  
offsets.  */
    if (mdata->nsects > 0
-      && ! bfd_mach_o_build_seg_command (NULL, mdata, seg))
+      && ! bfd_mach_o_build_seg_command (NULL, mdata,
+					 &mdata->commands[0].command.segment))
      return FALSE;

    /* If we're doing a dysymtab, cmd points to its load command.  */
@@ -2375,7 +2366,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 = (bfd_vma) -1; /* Flag unset values.  */
    return new_symbol;
  }

@@ -2703,7 +2694,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;
@@ -2734,13 +2725,9 @@ bfd_mach_o_read_symtab_symbol (bfd *abfd,
      }
    else
      {
-      if (type & BFD_MACH_O_N_PEXT)
-	s->symbol.flags |= BSF_GLOBAL;
-
-      if (type & BFD_MACH_O_N_EXT)
+      if (type & (BFD_MACH_O_N_PEXT | 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)
@@ -3892,6 +3879,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 24a1645..c67890b 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -668,7 +668,7 @@ typedef struct bfd_mach_o_backend_data
  bfd_mach_o_backend_data;

  /* Symbol type tests.  */
-
-#define IS_MACHO_INDIRECT(x) (((x) & BFD_MACH_O_N_TYPE) ==  
BFD_MACH_O_N_INDR)
+#define MO_INDIRECT (BSF_SYNTHETIC | BSF_INDIRECT)
+#define IS_MACHO_INDIRECT(x) (((x)->symbol.flags & MO_INDIRECT) ==  
MO_INDIRECT)

  #endif /* _BFD_MACH_O_H_ */
diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c
index 16ceb5e..b0a002e 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
@@ -674,6 +649,7 @@ obj_mach_o_common_parse (int is_local, symbolS  
*symbolP,
  			 addressT size)
  {
    addressT align = 0;
+  bfd_mach_o_asymbol *s;

    /* Both comm and lcomm take an optional alignment, as a power
       of two between 1 and 15.  */
@@ -691,6 +667,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.  */
@@ -700,6 +677,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
@@ -708,9 +686,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 = (bfd_vma) -2;

    return symbolP;
  }
@@ -750,6 +733,388 @@ obj_mach_o_fileprop (int prop)
      }
  }

+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;
+}
+
+/* Temporary markers for symbol reference data.
+   Lazy will remain in place.  */
+#define LAZY 0x01
+#define REFE 0x02
+
+/* 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 == (bfd_vma) -2)
+    {
+      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);
+    }
+
+  if (S_IS_MACHO_INDIRECT (sp))
+    s->n_desc &= ~LAZY;
+  else
+    {
+      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_IS_MACHO_INDIRECT (sp))
+    {
+      /* If the referenced symbol is undefined, then make it extern.   
*/
+      bfd_mach_o_asymbol *sr = (bfd_mach_o_asymbol *) s- 
 >symbol.udata.p;
+      if (sr->symbol.section == bfd_und_section_ptr)
+	sr->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 == (bfd_vma) -1)
+    {
+      /* Anything here that should be added that is non-standard.  */
+      s->n_desc &= ~BFD_MACH_O_REFERENCE_MASK;
+    }
+  else if (s->symbol.udata.i == (bfd_vma) -2)
+    {
+      /* 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 if (! S_IS_MACHO_INDIRECT (sp))
+    as_bad (_("internal error: [%s] unexpected code [%lx] in frob  
symbol"),
+	    s->symbol.name, (unsigned long)s->symbol.udata.i);
+
+  /* Leave the indirect symbol marker in place - we will need to  
write the info
+     into the dynamic symbol table indirect entries.
+
+     FIME: change if/when we use a different way to communicate  
this.  */
+  if (! S_IS_MACHO_INDIRECT (sp))
+    {
+      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;
+}
+
+/* Build a symbol that we will use to carry the .indirect_symbol  
reference to
+   BFD.  This symbol will never be output, so its name is really  
irrelevant.
+
+   It is TBD how the 'indirect' status will be represented - as a  
proof-of-
+   principle we signal by (BSF_INDIRECT | BSF_SYNTHETIC).  */
+
+static symbolS *
+obj_mach_o_make_indirect_symbol (asymbol *s)
+{
+  symbolS *sym;
+  sym = symbol_new ("", now_seg, frag_now_fix (), frag_now);
+  if (sym)
+    {
+      S_SET_NAME (sym, NULL);
+      S_SET_MACHO_INDIRECT (sym);
+      ((asymbol *)symbol_get_bfdsym (sym))->udata.p = (void *)s;
+    }
+  return sym;
+}
+
+/* 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_INDIRECT = 3,
+  OBJ_MACH_O_SYM_REFERENCE = 4,
+  OBJ_MACH_O_SYM_WEAK_REF = 5,
+  OBJ_MACH_O_SYM_LAZY_REF = 6,
+  OBJ_MACH_O_SYM_WEAK_DEF = 7,
+  OBJ_MACH_O_SYM_PRIV_EXT = 8,
+  OBJ_MACH_O_SYM_NO_DEAD_STRIP = 9,
+  OBJ_MACH_O_SYM_WEAK = 10
+} 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;
+
+      /* Indirect symbols.  */
+      case OBJ_MACH_O_SYM_INDIRECT:
+	sec = bfd_mach_o_get_mach_o_section (now_seg) ;
+	sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK;
+	if (sectype == BFD_MACH_O_S_SYMBOL_STUBS
+	    || sectype == BFD_MACH_O_S_LAZY_SYMBOL_POINTERS)
+	  {
+	    if (! is_defined)
+	      s->n_desc |= LAZY;
+	    obj_mach_o_make_indirect_symbol (symbol_get_bfdsym (sym));
+	  }
+	else if (sectype == BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS)
+	  obj_mach_o_make_indirect_symbol (symbol_get_bfdsym (sym));
+	else
+	  {
+	    as_bad (_("an .indirect_symbol must be in a symbol pointer"
+		      " or stub section."));
+	    err = 1;
+	  }
+	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 ;
+	S_SET_WEAKREFR (sym);
+	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;
+	    S_SET_WEAKREFD (sym);
+	  }
+	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 = (bfd_vma) -2;
+  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;
+  int err = 0;
+
+#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);
+      err = obj_mach_o_set_symbol_qualifier (symbolP, ntype);
+      *input_line_pointer = c;
+      if (err)
+	break;
+      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 == ',');
+
+  if (err)
+    ignore_rest_of_line ();
+  else
+    demand_empty_rest_of_line ();
+}
+
+#if 0
  /* Dummy function to allow test-code to work while we are working
     on things.  */

@@ -758,6 +1123,7 @@ obj_mach_o_placeholder (int arg ATTRIBUTE_UNUSED)
  {
    ignore_rest_of_line ();
  }
+#endif

  const pseudo_typeS mach_o_pseudo_table[] =
  {
@@ -838,11 +1204,17 @@ const pseudo_typeS mach_o_pseudo_table[] =

    { "section", obj_mach_o_section, 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},
+  {"indirect_symbol",	obj_mach_o_sym_qual, OBJ_MACH_O_SYM_INDIRECT},
+  {"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 */

    /* File flags.  */
    { "subsections_via_symbols", obj_mach_o_fileprop,
diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h
index b2acd17..f3b1d76 100644
--- a/gas/config/obj-macho.h
+++ b/gas/config/obj-macho.h
@@ -40,11 +40,18 @@ 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

+#define S_SET_MACHO_INDIRECT(S) \
+  ((asymbol *) symbol_get_bfdsym (S))->flags |= BSF_INDIRECT |  
BSF_SYNTHETIC
+
+#define S_IS_MACHO_INDIRECT(S) \
+ ((((asymbol *) symbol_get_bfdsym (S))->flags & (BSF_INDIRECT |  
BSF_SYNTHETIC)) \
+  == (BSF_INDIRECT | BSF_SYNTHETIC))
+
  extern const pseudo_typeS mach_o_pseudo_table[];

  #ifndef obj_pop_insert
@@ -56,6 +63,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)



More information about the Binutils mailing list