[Patch macho/bfd/gas] .indirect_symbol, take 2.

Iain Sandoe developer@sandoe-acoustics.co.uk
Mon Jan 9 13:00:00 GMT 2012


Here is a different implementation of the .indirect_symbol patch.

In this we keep indirect_symbols in a linked list in the section to  
which they belong.
As of now, I can't see a reason to keep them in GAS as well.

If this is OK, then a TODO would be to populate the list when a mach-o  
file is read in -
- this is nicely symmetrical -
- and means that sections can be reordered/removed without having to  
cross-check the dysymtab.

The only thing that is less satisfactory, is that there is no way  
(AFAICS) to mark a symbol as 'referenced by an indirect' which means  
if one deletes (or wishes to delete) symbols - then one should cross- 
check the usage from the indirect tables.

tests follow as separate patch (they've all be posted before anyway).

OK?
Iain

bfd:

	* mach-o.c (bfd_mach_o_count_indirect_symbols): New.
	(bfd_mach_o_build_dysymtab_command): Populate indirect table.
	* mach-o.h (bfd_mach_o_section): Add fields for indirect symbol
	lists.

gas:

	* config/obj-macho.c (obj_mach_o_set_symbol_qualifier): Switch off
	lazy for extern/private extern.
	(obj_mach_o_indirect_symbol): New.
	(obj_mach_o_placeholder): Remove.
	(mach_o_pseudo_table): Use obj_mach_o_indirect_symbol.
	(obj_macho_frob_label): Take care not to force local symbols into
	the regular table.
	(obj_macho_frob_symbol): Likewise.  Ensure undefined and comm syms
	have their fields set.
	(obj_mach_o_frob_section): New.
	* config/obj-macho.h (obj_frob_section): Define.
	(obj_mach_o_frob_section): Declare.

  bfd/mach-o.c           |   63 +++++++++++++-
  bfd/mach-o.h           |   16 ++++
  gas/config/obj-macho.c |  214 +++++++++++++++++++++++++++++++++++++++ 
++-------
  gas/config/obj-macho.h |    3 +
  4 files changed, 262 insertions(+), 34 deletions(-)

diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index a1f6596..493116a 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -2067,6 +2067,33 @@ bfd_mach_o_build_seg_command (const char  
*segment,
    return TRUE;
  }

+/* Count the number of indirect symbols in the image.
+   Requires that the sections are in their final order.  */
+
+static unsigned int
+bfd_mach_o_count_indirect_symbols (bfd *abfd, bfd_mach_o_data_struct  
*mdata)
+{
+  unsigned int i;
+  unsigned int nisyms = 0;
+
+  for (i = 0; i < mdata->nsects; ++i)
+    {
+      bfd_mach_o_section *sec = mdata->sections[i];
+
+      switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
+	{
+	  case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
+	  case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
+	  case BFD_MACH_O_S_SYMBOL_STUBS:
+	    nisyms += bfd_mach_o_section_get_nbr_indirect (abfd, sec);
+	    break;
+	  default:
+	    break;
+	}
+    }
+  return nisyms;
+}
+
  static bfd_boolean
  bfd_mach_o_build_dysymtab_command (bfd *abfd,
  				   bfd_mach_o_data_struct *mdata,
@@ -2123,9 +2150,11 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd,
        dsym->nundefsym = 0;
      }

+  dsym->nindirectsyms = bfd_mach_o_count_indirect_symbols (abfd,  
mdata);
    if (dsym->nindirectsyms > 0)
      {
        unsigned i;
+      unsigned n;

        mdata->filelen = FILE_ALIGN (mdata->filelen, 2);
        dsym->indirectsymoff = mdata->filelen;
@@ -2134,11 +2163,37 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd,
        dsym->indirect_syms = bfd_zalloc (abfd, dsym->nindirectsyms *  
4);
        if (dsym->indirect_syms == NULL)
          return FALSE;
-
-      /* So fill in the indices.  */
-      for (i = 0; i < dsym->nindirectsyms; ++i)
+		
+      n = 0;
+      for (i = 0; i < mdata->nsects; ++i)
  	{
-	  /* TODO: fill in the table.  */
+	  bfd_mach_o_section *sec = mdata->sections[i];
+
+	  switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
+	    {
+	      case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
+	      case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
+	      case BFD_MACH_O_S_SYMBOL_STUBS:
+		{
+		  bfd_mach_o_indirect_sym *isym = sec->indirectsyms;
+		  if (isym == NULL)
+		    break;
+		  /* Record the starting index in the reserved1 field.  */
+		  sec->reserved1 = n;
+		  do
+		    {
+		      dsym->indirect_syms[n] = isym->sym->symbol.udata.i;
+		      n++;
+		      /* Final safety net.  */
+		      if (n > dsym->nindirectsyms)
+		        abort ();
+		    }
+		  while ((isym = isym->next) != NULL);
+		}
+		break;
+	      default:
+		break;
+	    }
  	}
      }

diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index ca810a0..31a4095 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -63,6 +63,12 @@ typedef struct bfd_mach_o_section

    /* Corresponding bfd section.  */
    asection *bfdsection;
+
+  /* Linked list of indirect symbols for this section (only applies to
+     stub and reference sections).  */
+  struct bfd_mach_o_indirect_sym *indirectsyms;
+  /* Pointer to the last indirect, to save reversing the list.  */
+  struct bfd_mach_o_indirect_sym *lastindirectsym;

    /* Simply linked list.  */
    struct bfd_mach_o_section *next;
@@ -117,6 +123,16 @@ typedef struct bfd_mach_o_asymbol
  }
  bfd_mach_o_asymbol;

+/* An element in a list of indirect symbols the root of which
+   is "indirectsyms" in the section to which they apply.  */
+
+typedef struct bfd_mach_o_indirect_sym
+{
+  struct bfd_mach_o_indirect_sym *next;
+  struct bfd_mach_o_asymbol *sym;
+}
+bfd_mach_o_indirect_sym;
+
  /* The symbol table is sorted like this:
   (1) local.
  	(otherwise in order of generation)
diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c
index 43f4fba..5d82977 100644
--- a/gas/config/obj-macho.c
+++ b/gas/config/obj-macho.c
@@ -39,6 +39,7 @@

  #include "as.h"
  #include "subsegs.h"
+#include "struc-symbol.h" /* For local symbol stuff in frob_label/ 
symbol.  */
  #include "symbols.h"
  #include "write.h"
  #include "mach-o.h"
@@ -1032,6 +1033,7 @@ obj_mach_o_set_symbol_qualifier (symbolS *sym,  
int type)

        case OBJ_MACH_O_SYM_PRIV_EXT:
  	s->n_type |= BFD_MACH_O_N_PEXT ;
+	s->n_desc &= ~LAZY; /* The native tool swithes this off too.  */
  	/* We follow the system tools in marking PEXT as also global.  */
  	/* Fall through.  */

@@ -1131,13 +1133,74 @@ obj_mach_o_sym_qual (int ntype)
    demand_empty_rest_of_line ();
  }

-/* Dummy function to allow test-code to work while we are working
-   on things.  */
-
  static void
-obj_mach_o_placeholder (int arg ATTRIBUTE_UNUSED)
+obj_mach_o_indirect_symbol (int arg ATTRIBUTE_UNUSED)
  {
-  ignore_rest_of_line ();
+  bfd_mach_o_section *sec = bfd_mach_o_get_mach_o_section (now_seg);
+  unsigned lazy = 0;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
+    {
+      case BFD_MACH_O_S_SYMBOL_STUBS:
+      case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
+        lazy = LAZY;
+        /* Fall through.  */
+      case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
+        {
+          bfd_mach_o_indirect_sym *isym;
+	  char *name = input_line_pointer;
+	  char c = get_symbol_end ();
+	  symbolS *sym = symbol_find_or_make (name);
+	  unsigned int elsize =
+			bfd_mach_o_section_get_entry_size (stdoutput, sec);
+
+	  if (elsize == 0)
+	    {
+	      as_bad (_("attempt to add an indirect_symbol to a stub or"
+			" reference section with a zero-sized element at %s"),
+			name);
+	      *input_line_pointer = c;
+	      ignore_rest_of_line ();
+	      return;
+	  }
+
+	  *input_line_pointer = c;
+
+	  /* This should be allocated in bfd, since it is owned there.  */
+	  isym = (bfd_mach_o_indirect_sym *)
+			bfd_zalloc (stdoutput, sizeof (bfd_mach_o_indirect_sym));
+	  if (isym == NULL)
+	    abort ();
+
+	  isym->sym = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sym);
+	  if (sec->indirectsyms == NULL)
+	    sec->indirectsyms = isym;
+	  else
+	    sec->lastindirectsym->next = isym;
+	  sec->lastindirectsym = isym;
+	
+	  /* We put in the lazy flag, it will get reset if the symbols is  
later
+	     defined, or if the symbol becomes private_extern.  */
+	  if (isym->sym->symbol.section == bfd_und_section_ptr
+	      && ! (isym->sym->n_type & BFD_MACH_O_N_PEXT))
+	    {
+	      isym->sym->n_desc = lazy;
+	      isym->sym->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED;
+	    }
+	}
+        break;
+
+      default:
+	as_bad (_("an .indirect_symbol must be in a symbol pointer"
+		  " or stub section."));
+	ignore_rest_of_line ();
+	return;
+    }
+  demand_empty_rest_of_line ();
  }

  const pseudo_typeS mach_o_pseudo_table[] =
@@ -1231,7 +1294,7 @@ const pseudo_typeS mach_o_pseudo_table[] =
    {"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},
+  {"indirect_symbol",	obj_mach_o_indirect_symbol, 0},

    /* File flags.  */
    { "subsections_via_symbols", obj_mach_o_fileprop,
@@ -1270,15 +1333,33 @@ obj_mach_o_type_for_symbol (bfd_mach_o_asymbol  
*s)

  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);
+  bfd_mach_o_asymbol *s;
+  unsigned base_type;
+  bfd_mach_o_section *sec;
    int sectype = -1;

+  /* Leave local symbols alone (unless they've already been made into  
a real
+     one).  */
+
+  if (0  && sp->bsym == NULL)
+    {
+      if (((struct local_symbol *) sp)->lsy_section != reg_section)
+	return;
+      else
+	/* We have a local which has been added to the symbol table, so carry
+	   on with the checking.  */
+	sp = ((struct local_symbol *) sp)->u.lsy_sym;
+    }
+
+  s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp);
+  /* Leave debug symbols alone.  */
    if ((s->n_type & BFD_MACH_O_N_STAB) != 0)
-    return; /* Leave alone.  */
-
+    return;
+
+  /* This is the base symbol type, that we mask in.  */
+  base_type = obj_mach_o_type_for_symbol (s);
+
+  sec = bfd_mach_o_get_mach_o_section (s->symbol.section);
    if (sec != NULL)
      sectype = sec->flags & BFD_MACH_O_SECTION_TYPE_MASK;

@@ -1307,34 +1388,50 @@ void obj_macho_frob_label (struct symbol *sp)
  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);
+  bfd_mach_o_asymbol *s;
+  unsigned base_type;
+  bfd_mach_o_section *sec;
    int sectype = -1;
-
+
+  /* Leave local symbols alone (unless they've already been made into  
a real
+     one).  */
+
+  if (0 && sp->bsym == NULL)
+    {
+      if (((struct local_symbol *) sp)->lsy_section != reg_section)
+	return 0;
+      else
+	/* We have a local which has been added to the symbol table, so carry
+	   on with the checking.  */
+	sp = ((struct local_symbol *) sp)->u.lsy_sym;
+    }
+
+  s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (sp);
+  /* Leave debug symbols alone.  */
+  if ((s->n_type & BFD_MACH_O_N_STAB) != 0)
+    return 0;
+
+  base_type = obj_mach_o_type_for_symbol (s);
+  sec = bfd_mach_o_get_mach_o_section (s->symbol.section);
    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)
+  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;
-
+      /* Undefined syms, become extern.  */
+      s->n_type |= BFD_MACH_O_N_EXT;
+      S_SET_EXTERNAL (sp);
+    }
+  else if (s->symbol.section == bfd_com_section_ptr)
+    {
+      /* ... so to comm.  */
+      s->n_type |= BFD_MACH_O_N_EXT;
+      S_SET_EXTERNAL (sp);
      }
    else
      {
@@ -1353,6 +1450,7 @@ obj_macho_frob_symbol (struct symbol *sp)
      {
        /* Anything here that should be added that is non-standard.  */
        s->n_desc &= ~BFD_MACH_O_REFERENCE_MASK;
+      s->symbol.udata.i = SYM_MACHO_FIELDS_NOT_VALIDATED;
      }
    else if (s->symbol.udata.i == SYM_MACHO_FIELDS_NOT_VALIDATED)
      {
@@ -1388,6 +1486,62 @@ obj_macho_frob_symbol (struct symbol *sp)
    return 0;
  }

+void
+obj_mach_o_frob_section (asection *sec)
+{
+  bfd_vma sect_size = bfd_section_size (stdoutput, sec);
+  bfd_mach_o_section *ms = bfd_mach_o_get_mach_o_section (sec);
+
+  /* Process indirect symbols to determine if we have errors there.  */
+
+  switch (ms->flags & BFD_MACH_O_SECTION_TYPE_MASK)
+    {
+      case BFD_MACH_O_S_SYMBOL_STUBS:
+      case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
+      case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
+	{
+	  unsigned int nactual;
+	  unsigned int ncalc;
+	  bfd_mach_o_indirect_sym *isym = ms->indirectsyms;
+	  unsigned long eltsiz =
+			bfd_mach_o_section_get_entry_size (stdoutput, ms);
+
+	  /* If we somehow added indirect symbols to a section with a zero
+	     entry size, we're dead ... */
+	  if (eltsiz == 0 && isym != NULL)
+	    abort ();
+
+	  ncalc = (unsigned int) (sect_size / eltsiz);
+
+	  nactual = 0;
+	  if (isym != NULL)
+	    do
+	      {
+	        /* Count it. */
+		nactual++;
+		if (isym->sym->symbol.section == bfd_und_section_ptr)
+		  {
+		    /* If the referenced symbol is undefined, make
+		       it extern.  */
+		    isym->sym->n_type |= BFD_MACH_O_N_EXT;
+		    isym->sym->symbol.flags |= BSF_GLOBAL;
+		  }
+	      }
+	    while ((isym = isym->next) != NULL);
+
+	  if (nactual != ncalc)
+	    as_bad (_("there %s %d indirect_symbol%sin section %s but"
+		      " %d %s expected"), (nactual == 1)?"is":"are", nactual,
+		      (nactual == 1)?" ":"s ", sec->name, ncalc,
+		      (ncalc == 1)?"is":"are");
+	}
+	break;
+
+      default:
+	break;
+    }
+}
+
  /* Support stabs for mach-o.  */

  void
diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h
index cbc3a4f..ceb1097 100644
--- a/gas/config/obj-macho.h
+++ b/gas/config/obj-macho.h
@@ -62,6 +62,9 @@ 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 obj_frob_section(s) obj_mach_o_frob_section(s)
+void obj_mach_o_frob_section (asection *);
+
  #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