This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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)




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]