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]

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


On Jan 3, 2012, at 9:14 PM, Iain Sandoe wrote:

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

I think we should really moving .indirect_symbols out of the symtab for the following reasons:
1) there is no natural flags for them (BSF_INDIRECT | BSF_SYNTHETIC is not fully correct)
2) they are anonymous (so it doesn't make sense to create a symbol for them)
3) they aren't physically in the symtab
4) they're values are well defined.
5) there is a symmetry violation: when we read a mach-o file, we don't create symbol for .indirect_symbol, but we will need symbols to create .indirect_symbol.  This will lead to trouble for objcopy and co.

If you don't agree, please argue!

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

I am almost ok for this as a proof-of-principle, but I think reworking will be less work than first committing and then modifying.
Except for a few nits (see below), I am OK with the patch if you removing the .indirect_symbol parts in gas.

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

I am fine with that.

Thanks,
Tristan.

> ====
> 
> 
> 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;
> }
> 

ok.

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

Indeed!

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

Please, define a constant for this -1, that will make the code clearer.

>         {
> -          /* 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;

A constant for -2 would be welcome too.

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

Space after 'if'.

> +    {
> +      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;

Remove that.

> +  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;
> +    }

And that.

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

And the test,

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

and this comment,
> +
> +     FIME: change if/when we use a different way to communicate this.  */
> +  if (! S_IS_MACHO_INDIRECT (sp))

and this test,

> +    {
> +      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;
> +}

Replace the body by a 'not implemented' error message.
I think it should be renamed to .._make_indirect_symbol_for, as we make an indirect symbol for S.

> +
> +/* 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;

Note that handling indirect symbols in obj_mach_o_set_symbol_qualifier is a little abuse.
Also, there can be only one symbol for the .indirect_symbol directive.  Maybe it will be clearer to handle it separately.

> +
> +      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;

Do we need to break in case of error ?

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

Usually we don't keep #if 0/#endif code.

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


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