[Patch mach-o 1/3] section directives needed to support GCC

Tristan Gingold gingold@adacore.com
Tue Dec 13 09:44:00 GMT 2011


On Dec 13, 2011, at 3:23 AM, Iain Sandoe wrote:

> These patches build on the work done by Tristan (it happened that we were both working on sections at the same time).
> .. this is one step further towards support for GCC's output for mach-o...
> 
> The first patch implements all the short-hand section directives and other special combinations currently emitted by GCC.
> It is entirely local to mach-o

Iain,

just for the future: it would be nice if you could split such large patch into smaller, per-feature ones in order to help the review.

I suppose you will need to rebase it after my commit.

See enclosing comments,
thank you for submitting this work!

[…]
> 
> diff --git a/bfd/mach-o-i386.c b/bfd/mach-o-i386.c
> index 1191560..c5e3884 100644
> --- a/bfd/mach-o-i386.c
> +++ b/bfd/mach-o-i386.c
> @@ -280,10 +280,65 @@ bfd_mach_o_i386_print_thread (bfd *abfd, bfd_mach_o_thread_flavour *thread,
>   return FALSE;
> }
> 
> +static const mach_o_section_name_xlat text_section_names_xlat[] =
> +  {
> +    {	".symbol_stub",			"__symbol_stub",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_SYMBOL_STUBS,
> +	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,
> +					0},
> +    {	".picsymbol_stub",		"__picsymbol_stub",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_SYMBOL_STUBS,
> +	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,
> +					0},
> +    { NULL, NULL, 0, 0, 0, 0}
> +  };
> +
> +static const mach_o_section_name_xlat data_section_names_xlat[] =
> +  {
> +    /* The first two are recognized by i386, but not emitted for x86 by
> +       modern GCC.  */
> +    {	".non_lazy_symbol_pointer",	"__nl_symbol_ptr",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    {	".lazy_symbol_pointer",		"__la_symbol_ptr",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    {	".lazy_symbol_pointer2",	"__la_sym_ptr2",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    {	".lazy_symbol_pointer3",	"__la_sym_ptr3",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    { NULL, NULL, 0, 0, 0, 0}
> +  };
> +
> +static const mach_o_section_name_xlat import_section_names_xlat[] =
> +  {
> +    {	".picsymbol_stub3",		"__jump_table",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_SYMBOL_STUBS,
> +	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS
> +	| BFD_MACH_O_S_SELF_MODIFYING_CODE,
> +					6},
> +    {	".non_lazy_symbol_pointer_x86",	"__pointers",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    { NULL, NULL, 0, 0, 0, 0}
> +  };
> +
> +const mach_o_segment_name_xlat mach_o_i386_segsec_names_xlat[] =
> +  {
> +    { "__TEXT", text_section_names_xlat },
> +    { "__DATA", data_section_names_xlat },
> +    { "__IMPORT", import_section_names_xlat },
> +    { NULL, NULL }
> +  };
> +
> #define bfd_mach_o_swap_reloc_in bfd_mach_o_i386_swap_reloc_in
> #define bfd_mach_o_swap_reloc_out bfd_mach_o_i386_swap_reloc_out
> #define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread
> 
> +#define bfd_mach_o_tgt_seg_table mach_o_i386_segsec_names_xlat
> +
> #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_i386_bfd_reloc_type_lookup
> #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_i386_bfd_reloc_name_lookup

ok.

> 
> diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c
> index 29682c9..f22aa18 100644
> --- a/bfd/mach-o-target.c
> +++ b/bfd/mach-o-target.c
> @@ -96,7 +96,8 @@ static const bfd_mach_o_backend_data TARGET_NAME_BACKEND =
>   TARGET_ARCHITECTURE,
>   bfd_mach_o_swap_reloc_in,
>   bfd_mach_o_swap_reloc_out,
> -  bfd_mach_o_print_thread
> +  bfd_mach_o_print_thread,
> +  bfd_mach_o_tgt_seg_table
> };
> 
> const bfd_target TARGET_NAME =

ok.

> diff --git a/bfd/mach-o-x86-64.c b/bfd/mach-o-x86-64.c
> index 2248d97..1bc3bf8 100644
> --- a/bfd/mach-o-x86-64.c
> +++ b/bfd/mach-o-x86-64.c
> @@ -287,6 +287,7 @@ bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
> #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
> #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup
> #define bfd_mach_o_print_thread NULL
> +#define bfd_mach_o_tgt_seg_table NULL
> 
> #define TARGET_NAME 		mach_o_x86_64_vec
> #define TARGET_STRING 		"mach-o-x86-64"

ok.

> diff --git a/bfd/mach-o.c b/bfd/mach-o.c
> index a386604..2e45282 100644
> --- a/bfd/mach-o.c
> +++ b/bfd/mach-o.c
> @@ -89,118 +89,310 @@ bfd_mach_o_wide_p (bfd *abfd)
>    names.  Use of canonical names (such as .text or .debug_frame) is required
>    by gdb.  */
> 
> -struct mach_o_section_name_xlat
> -{
> -  const char *bfd_name;
> -  const char *mach_o_name;
> -  flagword flags;
> -};
> -
> -static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] =
> +/* __TEXT Segment.  */
> +static const mach_o_section_name_xlat text_section_names_xlat[] =
>   {
> -    { ".debug_frame",    "__debug_frame",    SEC_DEBUGGING },
> -    { ".debug_info",     "__debug_info",     SEC_DEBUGGING },
> -    { ".debug_abbrev",   "__debug_abbrev",   SEC_DEBUGGING },
> -    { ".debug_aranges",  "__debug_aranges",  SEC_DEBUGGING },
> -    { ".debug_macinfo",  "__debug_macinfo",  SEC_DEBUGGING },
> -    { ".debug_line",     "__debug_line",     SEC_DEBUGGING },
> -    { ".debug_loc",      "__debug_loc",      SEC_DEBUGGING },
> -    { ".debug_pubnames", "__debug_pubnames", SEC_DEBUGGING },
> -    { ".debug_pubtypes", "__debug_pubtypes", SEC_DEBUGGING },
> -    { ".debug_str",      "__debug_str",      SEC_DEBUGGING },
> -    { ".debug_ranges",   "__debug_ranges",   SEC_DEBUGGING },
> -    { NULL, NULL, 0}
> +    {	".text",				"__text",	
> +	SEC_CODE | SEC_LOAD,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,	0},
> +    {	".const",				"__const",
> +	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,			0},
> +    {	".static_const",			"__static_const",
> +	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,			0},
> +    {	".cstring",				"__cstring",
> +	SEC_READONLY | SEC_DATA | SEC_LOAD | SEC_MERGE | SEC_STRINGS,
> +						BFD_MACH_O_S_CSTRING_LITERALS,
> +	BFD_MACH_O_S_ATTR_NONE,			0},
> +    {	".literal4",				"__literal4",
> +	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_4BYTE_LITERALS,
> +	BFD_MACH_O_S_ATTR_NONE,			2},
> +    {	".literal8",				"__literal8",
> +	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_8BYTE_LITERALS,
> +	BFD_MACH_O_S_ATTR_NONE,			3},
> +    {	".literal16",				"__literal16",
> +	SEC_READONLY | SEC_DATA | SEC_LOAD,	BFD_MACH_O_S_16BYTE_LITERALS,
> +	BFD_MACH_O_S_ATTR_NONE,			4},
> +    {	".constructor",				"__constructor",
> +	SEC_CODE | SEC_LOAD,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,			0},
> +    {	".destructor",				"__destructor",
> +	SEC_CODE | SEC_LOAD,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,			0},
> +    {	".eh_frame",				"__eh_frame",
> +	SEC_READONLY | SEC_LOAD,		BFD_MACH_O_S_COALESCED,
> +	BFD_MACH_O_S_ATTR_LIVE_SUPPORT
> +	| BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS
> +	| BFD_MACH_O_S_ATTR_NO_TOC,		3},
> +    { NULL, NULL, 0, 0, 0, 0}
>   };
> 
> -static const struct mach_o_section_name_xlat text_section_names_xlat[] =
> +/* __DATA Segment.  */
> +static const mach_o_section_name_xlat data_section_names_xlat[] =
>   {
> -    { ".text",     "__text",      SEC_CODE | SEC_LOAD },
> -    { ".const",    "__const",     SEC_READONLY | SEC_DATA | SEC_LOAD },
> -    { ".cstring",  "__cstring",   SEC_READONLY | SEC_DATA | SEC_LOAD },
> -    { ".eh_frame", "__eh_frame",  SEC_READONLY | SEC_LOAD },
> -    { NULL, NULL, 0}
> +    {	".data",			"__data",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,		0},
> +    {	".bss",				"__bss",
> +	SEC_NO_FLAGS,			BFD_MACH_O_S_ZEROFILL,
> +	BFD_MACH_O_S_ATTR_NONE,		0},
> +    {	".const_data",			"__const",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,		0},
> +    {	".static_data",			"__static_data",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,		0},
> +    {	".mod_init_func",		"__mod_init_func",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_MOD_INIT_FUNC_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    {	".mod_term_func",		"__mod_term_func",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_MOD_FINI_FUNC_POINTERS,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    {	".dyld",			"__dyld",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,		0},
> +    {	".cfstring",			"__cfstring",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NONE,		2},
> +    { NULL, NULL, 0, 0, 0, 0}
>   };
> 
> -static const struct mach_o_section_name_xlat data_section_names_xlat[] =
> +/* __DWARF Segment.  */
> +static const mach_o_section_name_xlat dwarf_section_names_xlat[] =
>   {
> -    { ".data",                "__data",          SEC_DATA | SEC_LOAD },
> -    { ".const_data",          "__const",         SEC_DATA | SEC_LOAD },
> -    { ".dyld",                "__dyld",          SEC_DATA | SEC_LOAD },
> -    { ".lazy_symbol_ptr",     "__la_symbol_ptr", SEC_DATA | SEC_LOAD },
> -    { ".non_lazy_symbol_ptr", "__nl_symbol_ptr", SEC_DATA | SEC_LOAD },
> -    { ".bss",                 "__bss",           SEC_NO_FLAGS },
> -    { NULL, NULL, 0}
> +    {	".debug_frame",			"__debug_frame",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_info",			"__debug_info",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_abbrev",		"__debug_abbrev",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_aranges",		"__debug_aranges",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_macinfo",		"__debug_macinfo",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_line",			"__debug_line",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_loc",			"__debug_loc",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_pubnames",		"__debug_pubnames",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_pubtypes",		"__debug_pubtypes",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_str",			"__debug_str",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_ranges",		"__debug_ranges",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    {	".debug_macro",			"__debug_macro",
> +	SEC_DEBUGGING,			BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_DEBUG,	0},
> +    { NULL, NULL, 0, 0, 0, 0}
>   };
> 
> -struct mach_o_segment_name_xlat
> -{
> -  /* Segment name.  */
> -  const char *segname;
> -
> -  /* List of known sections for the segment.  */
> -  const struct mach_o_section_name_xlat *sections;
> -};
> -
> -/* List of known segment names.  */
> +/* __OBJC Segment.  */
> +static const mach_o_section_name_xlat objc_section_names_xlat[] =
> +  {
> +    {	".objc_class",			"__class",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_meta_class",		"__meta_class",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_cat_cls_meth",		"__cat_cls_meth",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_cat_inst_meth",		"__cat_inst_meth",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_protocol",		"__protocol",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_string_object",		"__string_object",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_cls_meth",		"__cls_meth",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_inst_meth",		"__inst_meth",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_cls_refs",		"__cls_refs",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LITERAL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_message_refs",		"__message_refs",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_LITERAL_POINTERS,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_symbols",		"__symbols",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_category",		"__category",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_class_vars",		"__class_vars",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_instance_vars",		"__instance_vars",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_module_info",		"__module_info",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_selector_strs",		"__selector_strs",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_CSTRING_LITERALS,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_image_info",		"__image_info",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc_selector_fixup",		"__sel_fixup",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    /* Objc V1 */
> +    {	".objc1_class_ext",		"__class_ext",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc1_property_list",		"__property",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    {	".objc1_protocol_ext",		"__protocol_ext",
> +	SEC_DATA | SEC_LOAD,		BFD_MACH_O_S_REGULAR,
> +	BFD_MACH_O_S_ATTR_NO_DEAD_STRIP, 0},
> +    { NULL, NULL, 0, 0, 0, 0}
> +  };
> 
> -static const struct mach_o_segment_name_xlat segsec_names_xlat[] =
> +static const mach_o_segment_name_xlat segsec_names_xlat[] =
>   {
>     { "__TEXT", text_section_names_xlat },
>     { "__DATA", data_section_names_xlat },
>     { "__DWARF", dwarf_section_names_xlat },
> +    { "__OBJC", objc_section_names_xlat },
>     { NULL, NULL }
>   };
> 
> -/* Mach-O to bfd names.  */
> +/* For both cases bfd-name => mach-o name and vice versa, the specific target
> +   is checked before the generic.  This allows a target (e.g. ppc for cstring)
> +   to override the generic definition with a more specific one.  */
> 
> -void
> -bfd_mach_o_normalize_section_name (const char *segname, const char *sectname,
> -                                   const char **name, flagword *flags)
> +/* Fetch the translation from a Mach-O section designation (segment, section)
> +   as a bfd short name, if one exists.  Otherwise return NULL.
> +
> +   Allow the segment and section names to be unterminated 16 byte arrays.  */
> +
> +const mach_o_section_name_xlat *
> +bfd_mach_o_section_data_for_mach_sect (bfd *abfd, const char *segname,
> +				       const char *sectname)
> {
>   const struct mach_o_segment_name_xlat *seg;
> +  const mach_o_section_name_xlat *sec;
> +  bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
> 
> -  *name = NULL;
> -  *flags = SEC_NO_FLAGS;
> +  /* First try any target-specific translations defined...  */
> +  if (bed->segsec_names_xlat)
> +    for (seg = bed->segsec_names_xlat; seg->segname; seg++)
> +      if (strncmp (seg->segname, segname, 16) == 0)

BFD_MACH_O_SEGNAME_SIZE instead of 16 ?

> +	for (sec = seg->sections; sec->mach_o_name; sec++)
> +	  if (strncmp (sec->mach_o_name, sectname, 16) == 0)

Ditto.

> +	    return sec;
> 
> +  /* ... and then the Mach-O generic ones.  */
>   for (seg = segsec_names_xlat; seg->segname; seg++)
> -    {
> -      if (strncmp (seg->segname, segname, BFD_MACH_O_SEGNAME_SIZE) == 0)
> -        {
> -          const struct mach_o_section_name_xlat *sec;
> +    if (strncmp (seg->segname, segname, 16) == 0)

Ditto.

> +      for (sec = seg->sections; sec->mach_o_name; sec++)
> +        if (strncmp (sec->mach_o_name, sectname, 16) == 0)

Ditto.

> +          return sec;
> 
> -          for (sec = seg->sections; sec->mach_o_name; sec++)
> -            {
> -              if (strncmp (sec->mach_o_name, sectname,
> -                           BFD_MACH_O_SECTNAME_SIZE) == 0)
> -                {
> -                  *name = sec->bfd_name;
> -                  *flags = sec->flags;
> -                  return;
> -                }
> -            }
> -          return;
> -        }
> -    }
> +  return NULL;
> }
> 
> -/* Convert Mach-O section name to BFD.  Try to use standard names, otherwise
> -   forge a new name.  SEGNAME and SECTNAME are 16 bytes strings.  */
> +/* If the bfd_name for this section is a 'canonical' form for which we
> +   know the Mach-O data, return the segment name and the data for the
> +   Mach-O equivalent.  Otherwise return NULL.  */
> 
> -static void
> -bfd_mach_o_convert_section_name_to_bfd
> -  (bfd *abfd, const char *segname, const char *sectname,
> -   const char **name, flagword *flags)
> +const mach_o_section_name_xlat *
> +bfd_mach_o_section_data_for_bfd_name (bfd *abfd, const char *bfd_name,
> +				      const char **segname)
> +{
> +  const struct mach_o_segment_name_xlat *seg;
> +  const mach_o_section_name_xlat *sec;
> +  bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
> +  *segname = NULL;
> +
> +  if (bfd_name[0] != '.')
> +    return NULL;
> +
> +  /* First try any target-specific translations defined...  */
> +  if (bed->segsec_names_xlat)
> +    for (seg = bed->segsec_names_xlat; seg->segname; seg++)
> +      for (sec = seg->sections; sec->bfd_name; sec++)
> +	if (strcmp (bfd_name, sec->bfd_name) == 0)
> +	  {
> +	    *segname = seg->segname;
> +	    return sec;
> +	  }
> +
> +  /* ... and then the Mach-O generic ones.  */
> +  for (seg = segsec_names_xlat; seg->segname; seg++)
> +    for (sec = seg->sections; sec->bfd_name; sec++)
> +      if (strcmp (bfd_name, sec->bfd_name) == 0)
> +	{
> +	  *segname = seg->segname;
> +	  return sec;
> +	}
> +
> +  return NULL;
> +}
> +
> +/* Convert Mach-O section name to BFD.
> +
> +   Try to use standard/canonical names, for which we have tables including
> +   default flag settings - which are returned.  Otherwise forge a new name
> +   in the form "<segmentname>.<sectionname>" this will be prefixed with
> +   LC_SEGMENT. if the segment name does not begin with an underscore.
> +
> +   SEGNAME and SECTNAME are 16 byte arrays (they do not need to be NUL-
> +   terminated if the name length is exactly 16 bytes - but must be if the name
> +   length is less than 16 characters).  */
> +
> +void
> +bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, const char *segname,
> +					const char *secname, const char **name,
> +					flagword *flags)
> {
> +  const mach_o_section_name_xlat *xlat;
>   char *res;
>   unsigned int len;
>   const char *pfx = "";
> 
> -  /* First search for a canonical name.  */
> -  bfd_mach_o_normalize_section_name (segname, sectname, name, flags);
> +  *name = NULL;
> +  *flags = SEC_NO_FLAGS;
> 
> -  /* Return now if found.  */
> -  if (*name)
> -    return;
> +  /* First search for a canonical name...
> +     xlat will be non-null if there is an entry for segname, secname.  */
> +  xlat = bfd_mach_o_section_data_for_mach_sect (abfd, segname, secname);
> +  if (xlat)
> +    {
> +      len = strlen (xlat->bfd_name);
> +      res = bfd_alloc (abfd, len+1);
> +      if (res == NULL)
> +	return;
> +      memcpy (res, xlat->bfd_name, len+1);
> +      *name = res;
> +      *flags = xlat->bfd_flags;
> +      return;
> +    }
> +
> +  /* ... else we make up a bfd name from the segment concatenated with the
> +     section.  */
> 
>   len = 16 + 1 + 16 + 1;
> 
> @@ -217,43 +409,46 @@ bfd_mach_o_convert_section_name_to_bfd
>   res = bfd_alloc (abfd, len);
>   if (res == NULL)
>     return;
> -  snprintf (res, len, "%s%.16s.%.16s", pfx, segname, sectname);
> +  snprintf (res, len, "%s%.16s.%.16s", pfx, segname, secname);
>   *name = res;
> -  *flags = SEC_NO_FLAGS;
> }
> 
> -/* Convert a bfd section name to a Mach-O segment + section name.  */
> +/* Convert a bfd section name to a Mach-O segment + section name.
> 
> -static void
> +   If the name is a canonical one for which we have a Darwin match
> +   return the translation table - which contains defaults for flags,
> +   type, attribute and default alignment data.
> +
> +   Otherwise, expand the bfd_name (assumed to be in the form
> +   "[LC_SEGMENT.]<segmentname>.<sectionname>") and return NULL.  */
> +
> +static const mach_o_section_name_xlat *
> bfd_mach_o_convert_section_name_to_mach_o (bfd *abfd ATTRIBUTE_UNUSED,
>                                            asection *sect,
>                                            bfd_mach_o_section *section)
> {
> -  const struct mach_o_segment_name_xlat *seg;
> +  const mach_o_section_name_xlat *xlat;
>   const char *name = bfd_get_section_name (abfd, sect);
> +  const char *segname;
>   const char *dot;
>   unsigned int len;
>   unsigned int seglen;
>   unsigned int seclen;
> 
> -  /* List of well known names.  They all start with a dot.  */
> -  if (name[0] == '.')
> -    for (seg = segsec_names_xlat; seg->segname; seg++)
> -      {
> -        const struct mach_o_section_name_xlat *sec;
> +  memset (section->segname, 0, 17);
> +  memset (section->sectname, 0, 17);

Ditto (+1) ?

> 
> -        for (sec = seg->sections; sec->mach_o_name; sec++)
> -          {
> -            if (strcmp (sec->bfd_name, name) == 0)
> -              {
> -                strcpy (section->segname, seg->segname);
> -                strcpy (section->sectname, sec->mach_o_name);
> -                return;
> -              }
> -          }
> -      }
> +  /* See if is a canonical name ... */
> +  xlat = bfd_mach_o_section_data_for_bfd_name (abfd, name, &segname);
> +  if (xlat)
> +    {
> +      strcpy (section->segname, segname);
> +      strcpy (section->sectname, xlat->mach_o_name);
> +      return xlat;
> +    }
> 
> -  /* Strip LC_SEGMENT. prefix.  */
> +  /* .. else we convert our constructed one back to Mach-O.
> +     Strip LC_SEGMENT. prefix, if present.  */
>   if (strncmp (name, "LC_SEGMENT.", 11) == 0)
>     name += 11;
> 
> @@ -273,16 +468,23 @@ bfd_mach_o_convert_section_name_to_mach_o (bfd *abfd ATTRIBUTE_UNUSED,
>           section->segname[seglen] = 0;
>           memcpy (section->sectname, dot + 1, seclen);
>           section->sectname[seclen] = 0;
> -          return;
> +          return NULL;
>         }
>     }
> 
> +  /* The segment and section names are both missing - don't make them
> +     into dots.  */
> +  if (dot && dot == name)
> +    return NULL;
> +
> +  /* Just duplicate the name into both segment and section.  */
>   if (len > 16)
>     len = 16;
>   memcpy (section->segname, name, len);
>   section->segname[len] = 0;
>   memcpy (section->sectname, name, len);
>   section->sectname[len] = 0;
> +  return NULL;
> }
> 
> /* Return the size of an entry for section SEC.
> @@ -339,10 +541,20 @@ bfd_mach_o_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
> 
> bfd_boolean
> bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
> -					  asection *isection ATTRIBUTE_UNUSED,
> +					  asection *isection,
> 					  bfd *obfd ATTRIBUTE_UNUSED,
> -					  asection *osection ATTRIBUTE_UNUSED)
> +					  asection *osection)
> {
> +  if (osection->used_by_bfd == NULL)
> +    osection->used_by_bfd = isection->used_by_bfd;
> +  else
> +    if (isection->used_by_bfd != NULL)
> +      memcpy (osection->used_by_bfd, isection->used_by_bfd,
> +	      sizeof (bfd_mach_o_section));
> +
> +  if (osection->used_by_bfd != NULL)
> +    ((bfd_mach_o_section *)osection->used_by_bfd)->bfdsection = osection;
> +
>   return TRUE;
> }
> 
> @@ -1101,6 +1313,11 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command)
>   if (strtab == NULL)
>     return FALSE;
> 
> +  /* Although we don't strictly need to do this, for compatibility with
> +     Darwin system tools, actually output an empty string for the index
> +     0 entry.  */
> +  _bfd_stringtab_add (strtab, "", TRUE, FALSE);
> +

Ah, yes.  BTW I think that the string is padded to 4 or 8 bytes too.

>   for (i = 0; i < sym->nsyms; i++)
>     {
>       bfd_size_type str_index;
> @@ -1417,22 +1634,22 @@ bfd_mach_o_build_commands (bfd *abfd)
>   seg->sect_head = NULL;
>   seg->sect_tail = NULL;
> 
> -  /* Create Mach-O sections.  */
> +  /* Create Mach-O sections.
> +     Section type, attribute and align should have been set when the
> +     section was created - either read in or specified.  */
>   target_index = 0;
>   for (sec = abfd->sections; sec; sec = sec->next)
>     {
> +      unsigned bfd_align = bfd_get_section_alignment (abfd, sec);
>       bfd_mach_o_section *msect = bfd_mach_o_get_mach_o_section (sec);
> 
>       bfd_mach_o_append_section_to_segment (seg, sec);
> 
> -      if (msect->flags == 0)
> -        {
> -          /* We suppose it hasn't been set.  Convert from BFD flags.  */
> -          bfd_mach_o_set_section_flags_from_bfd (abfd, sec);
> -        }
>       msect->addr = bfd_get_section_vma (abfd, sec);
>       msect->size = bfd_get_section_size (sec);
> -      msect->align = bfd_get_section_alignment (abfd, sec);
> +      /* Use the largest alignment set, in case it was bumped after the
> +	 section was created.  */
> +      msect->align = msect->align > bfd_align ? msect->align : bfd_align;
> 
>       if (msect->size != 0)
>         {
> @@ -1574,11 +1791,13 @@ bfd_boolean
> bfd_mach_o_new_section_hook (bfd *abfd, asection *sec)
> {
>   bfd_mach_o_section *s;
> +  unsigned bfdalign = bfd_get_section_alignment (abfd, sec);
> 
>   s = bfd_mach_o_get_mach_o_section (sec);
>   if (s == NULL)
>     {
>       flagword bfd_flags;
> +      static const mach_o_section_name_xlat * xlat;
> 
>       s = (bfd_mach_o_section *) bfd_zalloc (abfd, sizeof (*s));
>       if (s == NULL)
> @@ -1586,21 +1805,24 @@ bfd_mach_o_new_section_hook (bfd *abfd, asection *sec)
>       sec->used_by_bfd = s;
>       s->bfdsection = sec;
> 
> -      /* Create default name.  */
> -      bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, s);
> -
> -      /* Create default flags.  */
> -      bfd_flags = bfd_get_section_flags (abfd, sec);
> -      if ((bfd_flags & SEC_CODE) == SEC_CODE)
> -        s->flags = BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS
> -          | BFD_MACH_O_S_ATTR_SOME_INSTRUCTIONS
> -          | BFD_MACH_O_S_REGULAR;
> -      else if ((bfd_flags & (SEC_ALLOC | SEC_LOAD)) == SEC_ALLOC)
> -        s->flags = BFD_MACH_O_S_ZEROFILL;
> -      else if (bfd_flags & SEC_DEBUGGING)
> -        s->flags = BFD_MACH_O_S_REGULAR |  BFD_MACH_O_S_ATTR_DEBUG;
> +      /* Create the Darwin seg/sect name pair from the bfd name.
> +	 If this is a canonical name for which a specific paiting exists
> +	 there will also be defined flags, type, attribute and alignment
> +	 values.  */
> +      xlat = bfd_mach_o_convert_section_name_to_mach_o (abfd, sec, s);
> +      if (xlat != NULL)
> +	{
> +	  s->flags = xlat->macho_sectype | xlat->macho_secattr;
> +	  s->align = xlat->sectalign > bfdalign ? xlat->sectalign
> +						: bfdalign;
> +	  bfd_set_section_alignment (abfd, sec, s->align);
> +	  bfd_flags = bfd_get_section_flags (abfd, sec);
> +	  if (bfd_flags == SEC_NO_FLAGS)
> +	    bfd_set_section_flags (abfd, sec, xlat->bfd_flags);
> +	}
>       else
> -        s->flags = BFD_MACH_O_S_REGULAR;
> +	/* Create default flags.  */
> +	bfd_mach_o_set_section_flags_from_bfd (abfd, sec);
>     }
> 
>   return _bfd_generic_new_section_hook (abfd, sec);
> @@ -1616,6 +1838,9 @@ bfd_mach_o_init_section_from_mach_o (bfd *abfd, asection *sec,
>   flags = bfd_get_section_flags (abfd, sec);
>   section = bfd_mach_o_get_mach_o_section (sec);
> 
> +  /* TODO: see if we should use the xlat system for doing this by
> +     preference and fall back to this for unknown sections.  */
> +
>   if (flags == SEC_NO_FLAGS)
>     {
>       /* Try to guess flags.  */
> @@ -3444,6 +3669,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_section_type_name[] =
>   { "interposing", BFD_MACH_O_S_INTERPOSING},
>   { "16byte_literals", BFD_MACH_O_S_16BYTE_LITERALS},
>   { "dtrace_dof", BFD_MACH_O_S_DTRACE_DOF},
> +  { "symbol_stubs", BFD_MACH_O_S_SYMBOL_STUBS},
>   { "lazy_dylib_symbol_pointers", BFD_MACH_O_S_LAZY_DYLIB_SYMBOL_POINTERS},
>   { NULL, 0}
> };
> @@ -3460,6 +3686,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_section_attribute_name[] =
>   { "strip_static_syms", BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS },
>   { "no_toc", BFD_MACH_O_S_ATTR_NO_TOC },
>   { "pure_instructions", BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS },
> +  { "self_modifying_code", BFD_MACH_O_S_SELF_MODIFYING_CODE },
>   { NULL, 0}
> };
> 
> @@ -3507,7 +3734,7 @@ static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
>   { NULL, 0}
> };
> 
> -/* Get the section type from NAME.  Return -1 if NAME is unknown.  */
> +/* Get the section type from NAME.  Return 256 if NAME is unknown.  */
> 
> unsigned int
> bfd_mach_o_get_section_type_from_name (const char *name)
> @@ -3517,7 +3744,8 @@ bfd_mach_o_get_section_type_from_name (const char *name)
>   for (x = bfd_mach_o_section_type_name; x->name; x++)
>     if (strcmp (x->name, name) == 0)
>       return x->val;
> -  return (unsigned int)-1;
> +  /* Maximum section ID = 0xff.  */
> +  return 256;
> }
> 
> /* Get the section attribute from NAME.  Return -1 if NAME is unknown.  */
> @@ -4160,6 +4388,7 @@ bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
> #define bfd_mach_o_swap_reloc_in NULL
> #define bfd_mach_o_swap_reloc_out NULL
> #define bfd_mach_o_print_thread NULL
> +#define bfd_mach_o_tgt_seg_table NULL
> 
> #define TARGET_NAME 		mach_o_be_vec
> #define TARGET_STRING     	"mach-o-be"

Ok.

> diff --git a/bfd/mach-o.h b/bfd/mach-o.h
> index f199016..84ed9a1 100644
> --- a/bfd/mach-o.h
> +++ b/bfd/mach-o.h
> @@ -1,5 +1,5 @@
> /* Mach-O support for BFD.
> -   Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009
> +   Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2011
>    Free Software Foundation, Inc.
> 
>    This file is part of BFD, the Binary File Descriptor library.
> @@ -70,7 +70,7 @@ bfd_mach_o_section;
> 
> typedef struct bfd_mach_o_segment_command
> {
> -  char segname[16 + 1];
> +  char segname[BFD_MACH_O_SEGNAME_SIZE + 1];
>   bfd_vma vmaddr;
>   bfd_vma vmsize;
>   bfd_vma fileoff;
> @@ -520,15 +520,6 @@ typedef struct mach_o_data_struct
> bfd_mach_o_data_struct;
> 
> /* Target specific routines.  */
> -typedef struct bfd_mach_o_backend_data
> -{
> -  enum bfd_architecture arch;
> -  bfd_boolean (*_bfd_mach_o_swap_reloc_in)(arelent *, bfd_mach_o_reloc_info *);
> -  bfd_boolean (*_bfd_mach_o_swap_reloc_out)(arelent *, bfd_mach_o_reloc_info *);
> -  bfd_boolean (*_bfd_mach_o_print_thread)(bfd *, bfd_mach_o_thread_flavour *,
> -                                          void *, char *);
> -}
> -bfd_mach_o_backend_data;
> 
> #define bfd_mach_o_get_data(abfd) ((abfd)->tdata.mach_o_data)
> #define bfd_mach_o_get_backend_data(abfd) \
> @@ -582,9 +573,44 @@ unsigned int bfd_mach_o_version (bfd *);
> 
> unsigned int bfd_mach_o_get_section_type_from_name (const char *);
> unsigned int bfd_mach_o_get_section_attribute_from_name (const char *);
> -void bfd_mach_o_normalize_section_name (const char *, const char *,
> -                                        const char **, flagword *);
> +
> +void bfd_mach_o_convert_section_name_to_bfd (bfd *, const char *, const char *,
> +					     const char **, flagword *);
> 
> extern const bfd_target mach_o_fat_vec;
> 
> +/* Interfaces between BFD names and Mach-O names.  */
> +
> +typedef struct mach_o_section_name_xlat
> +{
> +  const char *bfd_name;
> +  const char *mach_o_name;
> +  flagword bfd_flags;
> +  unsigned int macho_sectype;
> +  unsigned int macho_secattr;
> +  unsigned int sectalign;
> +} mach_o_section_name_xlat;
> +
> +typedef struct mach_o_segment_name_xlat
> +{
> +  const char *segname;
> +  const mach_o_section_name_xlat *sections;
> +} mach_o_segment_name_xlat;

Sooner or later we will have to add comments to the fields :-)

> +
> +const mach_o_section_name_xlat *
> +bfd_mach_o_section_data_for_mach_sect (bfd *, const char *, const char *);
> +const mach_o_section_name_xlat *
> +bfd_mach_o_section_data_for_bfd_name (bfd *, const char *, const char **);
> +
> +typedef struct bfd_mach_o_backend_data
> +{
> +  enum bfd_architecture arch;
> +  bfd_boolean (*_bfd_mach_o_swap_reloc_in)(arelent *, bfd_mach_o_reloc_info *);
> +  bfd_boolean (*_bfd_mach_o_swap_reloc_out)(arelent *, bfd_mach_o_reloc_info *);
> +  bfd_boolean (*_bfd_mach_o_print_thread)(bfd *, bfd_mach_o_thread_flavour *,
> +                                          void *, char *);
> +  const mach_o_segment_name_xlat *segsec_names_xlat;
> +}
> +bfd_mach_o_backend_data;
> +
> #endif /* _BFD_MACH_O_H_ */

ok.

> diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c
> index 5f1255d..1aa24f7 100644
> --- a/gas/config/obj-macho.c
> +++ b/gas/config/obj-macho.c
> @@ -1,5 +1,5 @@
> /* Mach-O object file format
> -   Copyright 2009 Free Software Foundation, Inc.
> +   Copyright 2009, 2011 Free Software Foundation, Inc.
> 
>    This file is part of GAS, the GNU Assembler.
> 
> @@ -18,6 +18,23 @@
>    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
>    02110-1301, USA.  */
> 
> +/* Here we handle the mach-o directives that are common to all architectures.
> +
> +   Most significant are mach-o named sections and a variety of symbol type
> +   decorations.  */
> +
> +/* Mach-O supports multiple, named segments each of which may contain
> +   multiple named sections.  Thus the concept of subsectioning is
> +   handled by (say) having a __TEXT segment with appropriate flags from
> +   which subsections are generated like __text, __const etc.
> +
> +   The well-known as short-hand section switch directives like .text, .data
> +   etc. are mapped onto predefined segment/section pairs using facilites
> +   supplied by the mach-o port of bfd.
> +
> +   A number of additional mach-o short-hand section switch directives are
> +   also defined.  */
> +
> #define OBJ_HEADER "obj-macho.h"
> 
> #include "as.h"
> @@ -26,6 +43,13 @@
> #include "write.h"
> #include "mach-o.h"
> #include "mach-o/loader.h"
> +#include "obj-macho.h"
> +
> +/* TODO: Implement "-dynamic"/"-static" command line options.  */
> +int is_static;

'static int'.  Maybe even 'static int obj_mach_o_is_static;'

> +
> +/* Allow for special re-ordering on output.  */
> +int seen_objc_section;

Ditto.

> 
> static void
> obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED)
> @@ -53,104 +77,172 @@ obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED)
>   demand_empty_rest_of_line ();
> }
> 
> -/* Parse:
> -   .section segname,sectname[,type[,attribute[,sizeof_stub]]]
> -*/
> +/* 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
> +   delimiter, a warning is given and the string is truncated.  On completion of
> +   this function, input_line_pointer will point to the char after the ',' or
> +   to the newline.
> +
> +   It trims leading and trailing space.  */
> +
> +static int
> +collect_16char_name (char *dest, const char *msg, int require_comma)
> +{
> +  char c, *namstart;
> +
> +  SKIP_WHITESPACE ();
> +  namstart = input_line_pointer;
> +
> +  while ( (c = *input_line_pointer) != ','
> +	 && !is_end_of_line[(unsigned char) c])
> +    input_line_pointer++;
> +
> +  {
> +      int len = input_line_pointer - namstart; /* could be zero.  */
> +      /* lose any trailing space.  */
> +      while (len > 0 && namstart[len-1] == ' ')
> +        len--;
> +      if (len > 16)
> +        {
> +          *input_line_pointer = '\0'; /* make a temp string.  */
> +	  as_warn (_("the %s name '%s' exceeds 16 characters, truncated"),
> +		     msg, namstart);

Warning or error ?

> +	  *input_line_pointer = c; /* restore for printing.  */
> +	  len = 16;
> +	}
> +      if (len > 0)
> +        memcpy (dest, namstart, len);
> +  }
> +
> +  if (c != ',' && require_comma)
> +    {
> +      as_bad (_("expected a %s name followed by a `,'"), msg);
> +      return 1;
> +    }
> +
> +  return 0;
> +}
> +
> +/* .section
> +
> +   The '.section' specification syntax looks like:
> +   .section <segment> , <section> [, type [, attribs [, size]]]
> +
> +   White space is allowed everywhere between elements.
> +
> +   <segment> and <section> may be from 0 to 16 chars in length - they may
> +   contain spaces but leading and trailing space will be trimmed.  It is
> +   mandatory that they be present (or that zero-length names are indicated
> +   by ",,").
> +
> +   There is only a single section type for any entry.
> +
> +   There may be multiple attributes, they are delimited by `+'.
> +
> +   Not all section types and attributes are accepted by the Darwin system
> +   assemblers as user-specifiable - although, at present, we do here.  */
> 
> static void
> obj_mach_o_section (int ignore ATTRIBUTE_UNUSED)
> {
>   char *p;
> -  char *segname;
> -  char *sectname;
>   char c;
> -  int sectype = BFD_MACH_O_S_REGULAR;
> +  unsigned int sectype = BFD_MACH_O_S_REGULAR;
> +  unsigned int defsectype = BFD_MACH_O_S_REGULAR;
> +  unsigned int sectype_given = 0;
>   unsigned int secattr = 0;
> +  unsigned int defsecattr = 0;
> +  int secattr_given = 0;
> +  unsigned int secalign = 0;
>   offsetT sizeof_stub = 0;
> +  const mach_o_section_name_xlat * xlat;
>   const char *name;
>   flagword oldflags, flags;
>   asection *sec;
> +  bfd_mach_o_section *msect;
> +  char segname[17];
> +  char sectname[17];
> 
> +  /* Zero-length segment and section names are allowed.  */
>   /* Parse segment name.  */
> -  if (!is_name_beginner (*input_line_pointer))
> +  memset (segname, 0, sizeof(segname));
> +  if (collect_16char_name (segname, "segment", 1))
>     {
> -      as_bad (_("missing segment name"));
>       ignore_rest_of_line ();
>       return;
>     }
> -  p = input_line_pointer;
> -  c = get_symbol_end ();
> -  segname = alloca (input_line_pointer - p + 1);
> -  strcpy (segname, p);
> -  *input_line_pointer = c;
> -
> -  if (*input_line_pointer != ',')
> -    {
> -      as_bad (_("missing comma after segment name"));
> -      ignore_rest_of_line ();
> -      return;
> -    }
> -  input_line_pointer++;
> +  input_line_pointer++; /* Skip the terminating ',' */
> 
>   /* Parse section name.  */
> -  if (!is_name_beginner (*input_line_pointer))
> -    {
> -      as_bad (_("missing section name"));
> -      ignore_rest_of_line ();
> -      return;
> -    }
> -  p = input_line_pointer;
> -  c = get_symbol_end ();
> -  sectname = alloca (input_line_pointer - p + 1);
> -  strcpy (sectname, p);
> -  *input_line_pointer = c;
> +  memset (sectname, 0, sizeof(sectname));
> +  collect_16char_name (sectname, "section", 0);
> 
>   /* Parse type.  */
>   if (*input_line_pointer == ',')
>     {
> +      char tmpc;
> +      int len;
>       input_line_pointer++;
> -      if (!is_name_beginner (*input_line_pointer))
> -        {
> -          as_bad (_("missing section type name"));
> -          ignore_rest_of_line ();
> -          return;
> -        }
> +      SKIP_WHITESPACE ();
>       p = input_line_pointer;
> -      c = get_symbol_end ();
> -
> +      while ((c = *input_line_pointer) != ','
> +	      && !is_end_of_line[(unsigned char) c])
> +	input_line_pointer++;
> +
> +      len = input_line_pointer - p;
> +      /* strip trailing spaces.  */
> +      while (len > 0 && p[len-1] == ' ')
> +	len--;
> +      tmpc = p[len];
> +
> +      /* Temporarily make a string from the token.  */
> +      p[len] = 0;
>       sectype = bfd_mach_o_get_section_type_from_name (p);
> -      if (sectype == -1)
> +      if (sectype > 255) /* Max Section ID == 255.  */
>         {
>           as_bad (_("unknown or invalid section type '%s'"), p);
>           sectype = BFD_MACH_O_S_REGULAR;
>         }
> -      *input_line_pointer = c;
> -
> -      /* Parse attributes.  */
> -      if (*input_line_pointer == ',')
> +      else
> +	sectype_given = 1;
> +      /* Restore.  */
> +      tmpc = p[len];
> +
> +      /* Parse attributes.
> +	 TODO: check validity of attributes for section type.  */
> +      if (sectype_given && c == ',')
>         {
>           do
>             {
>               int attr;
> 
> +	      /* Skip initial `,' and subsequent `+'.  */
>               input_line_pointer++;
> -
> -              if (!is_name_beginner (*input_line_pointer))
> -                {
> -                  as_bad (_("missing section attribute identifier"));
> -                  ignore_rest_of_line ();
> -                  break;
> -                }
> -              p = input_line_pointer;
> -              c = get_symbol_end ();
> -
> +	      SKIP_WHITESPACE ();
> +	      p = input_line_pointer;
> +	      while ((c = *input_line_pointer) != '+'
> +		      && c != ','
> +		      && !is_end_of_line[(unsigned char) c])
> +		input_line_pointer++;
> +
> +	      len = input_line_pointer - p;
> +	      /* strip trailing spaces.  */
> +	      while (len > 0 && p[len-1] == ' ')
> +		len--;
> +	      tmpc = p[len];
> +
> +	      /* Temporarily make a string from the token.  */
> +	      p[len] ='\0';
>               attr = bfd_mach_o_get_section_attribute_from_name (p);
> -              if (attr == -1)
> +	      if (attr == -1)
>                 as_bad (_("unknown or invalid section attribute '%s'"), p);
>               else
> -                secattr |= attr;
> -
> -              *input_line_pointer = c;
> +		{
> +		  secattr_given = 1;
> +                  secattr |= attr;
> +		}
> +	      /* Restore.  */
> +	      p[len] = tmpc;
>             }
>           while (*input_line_pointer == '+');
> 
> @@ -160,6 +252,7 @@ obj_mach_o_section (int ignore ATTRIBUTE_UNUSED)
>               if (sectype != BFD_MACH_O_S_SYMBOL_STUBS)
>                 as_bad (_("unexpected sizeof_stub expression"));
> 
> +	      input_line_pointer++;
>               sizeof_stub = get_absolute_expression ();
>             }
>           else if (sectype == BFD_MACH_O_S_SYMBOL_STUBS)
> @@ -168,8 +261,19 @@ obj_mach_o_section (int ignore ATTRIBUTE_UNUSED)
>     }
>   demand_empty_rest_of_line ();
> 
> -  bfd_mach_o_normalize_section_name (segname, sectname, &name, &flags);
> -  if (name == NULL)
> +  flags = SEC_NO_FLAGS;
> +  /* This provides default bfd flags and default mach-o section type and
> +     attributes along with the canonical name.  */
> +  xlat = bfd_mach_o_section_data_for_mach_sect (stdoutput, segname, sectname);
> +  if (xlat != NULL)
> +    {
> +      name = xstrdup (xlat->bfd_name);
> +      flags = xlat->bfd_flags;
> +      defsectype = xlat->macho_sectype;
> +      defsecattr = xlat->macho_secattr;
> +      secalign = xlat->sectalign;
> +    }
> +  else
>     {
>       /* There is no normal BFD section name for this section.  Create one.
>          The name created doesn't really matter as it will never be written
> @@ -194,90 +298,360 @@ obj_mach_o_section (int ignore ATTRIBUTE_UNUSED)
>   sec = subseg_new (name, 0);
> 
>   oldflags = bfd_get_section_flags (stdoutput, sec);
> -  if (oldflags == SEC_NO_FLAGS)
> +  msect = bfd_mach_o_get_mach_o_section (sec);
> +   if (oldflags == SEC_NO_FLAGS)
>     {
> -      bfd_mach_o_section *msect;
> -
>       if (! bfd_set_section_flags (stdoutput, sec, flags))
> 	as_warn (_("error setting flags for \"%s\": %s"),
> 		 bfd_section_name (stdoutput, sec),
> 		 bfd_errmsg (bfd_get_error ()));
> -      msect = bfd_mach_o_get_mach_o_section (sec);
>       strncpy (msect->segname, segname, sizeof (msect->segname));
>       msect->segname[16] = 0;
>       strncpy (msect->sectname, sectname, sizeof (msect->sectname));
>       msect->sectname[16] = 0;
> -      msect->flags = secattr | sectype;
> +      msect->align = secalign;
> +      if (sectype_given)
> +	{
> +	  msect->flags = sectype;
> +	  if (secattr_given)
> +	    msect->flags |= secattr;
> +	  else
> +	    msect->flags |= defsecattr;
> +	}
> +      else
> +        msect->flags = defsectype | defsecattr;
>       msect->reserved2 = sizeof_stub;
>     }
>   else if (flags != SEC_NO_FLAGS)
>     {
> -      if (flags != oldflags)
> +      if (flags != oldflags
> +	  || msect->flags != (secattr | sectype))
> 	as_warn (_("Ignoring changed section attributes for %s"), name);
>     }
> }
> 
> -struct known_section
> +static segT
> +obj_mach_o_segT_from_bfd_name (const char *nam, int must_succeed)
> {
> -  const char *name;
> -  unsigned int flags;
> -};
> +  const mach_o_section_name_xlat *xlat;
> +  const char *segn;
> +  segT sec;
> 
> -static const struct known_section known_sections[] =
> -  {
> -    /* 0 */ { NULL, 0},
> -    /* 1 */ { ".cstring", BFD_MACH_O_S_CSTRING_LITERALS }
> -  };
> +  /* BFD has tables of flags and default attributes for all the sections that
> +     have a 'canonical' name.  */
> +  xlat = bfd_mach_o_section_data_for_bfd_name (stdoutput, nam, &segn);
> +  if (xlat == NULL)
> +    {
> +      if (must_succeed)
> +	as_fatal (_("BFD is out of sync with GAS, "
> +		     "unhandled well-known section type `%s'"), nam);
> +      return NULL;
> +    }
> +
> +  sec = bfd_get_section_by_name (stdoutput, nam);
> +  if (sec == NULL)
> +    {
> +      bfd_mach_o_section *msect;
> +
> +      sec = subseg_force_new (xlat->bfd_name, 0);
> +
> +      /* Set default type, attributes and alignment.  */
> +      msect = bfd_mach_o_get_mach_o_section (sec);
> +      msect->flags = xlat->macho_sectype | xlat->macho_secattr;
> +      msect->align = xlat->sectalign;
> +
> +      if ((msect->flags & BFD_MACH_O_SECTION_TYPE_MASK)
> +	  == BFD_MACH_O_S_ZEROFILL)
> +	seg_info (sec)->bss = 1;
> +    }
> 
> +  return sec;
> +}
> +
> +static const char *known_sections[] =

const char * const.

> +{
> +  /*  0 */ NULL,
> +  /* __TEXT */
> +  /*  1 */ ".const",
> +  /*  2 */ ".static_const",
> +  /*  3 */ ".cstring",
> +  /*  4 */ ".literal4",
> +  /*  5 */ ".literal8",
> +  /*  6 */ ".literal16",
> +  /*  7 */ ".constructor",
> +  /*  8 */ ".destructor",
> +  /*  9 */ ".eh_frame",
> +  /* __DATA */
> +  /* 10 */ ".const_data",
> +  /* 11 */ ".static_data",
> +  /* 12 */ ".mod_init_func",
> +  /* 13 */ ".mod_term_func",
> +  /* 14 */ ".dyld",
> +  /* 15 */ ".cfstring"
> +};
> +
> +/* Interface for a known non-optional section directive.  */
> static void
> obj_mach_o_known_section (int sect_index)
> {
> -  const struct known_section *sect = &known_sections[sect_index];
> -  asection *old_sec;
> -  segT sec;
> +  segT section;
> +
> +#ifdef md_flush_pending_output
> +  md_flush_pending_output ();
> +#endif
> +
> +  section = obj_mach_o_segT_from_bfd_name (known_sections[sect_index], 1);
> +  if (section != NULL)
> +    subseg_set (section, 0);
> +
> +  /* else, we leave the section as it was; there was a fatal error anyway.  */
> +}
> +
> +static const char *objc_sections[] =

Ditto.

> +{
> +  /*  0 */ NULL,
> +  /*  1 */ ".objc_class",
> +  /*  2 */ ".objc_meta_class",
> +  /*  3 */ ".objc_cat_cls_meth",
> +  /*  4 */ ".objc_cat_inst_meth",
> +  /*  5 */ ".objc_protocol",
> +  /*  6 */ ".objc_string_object",
> +  /*  7 */ ".objc_cls_meth",
> +  /*  8 */ ".objc_inst_meth",
> +  /*  9 */ ".objc_cls_refs",
> +  /* 10 */ ".objc_message_refs",
> +  /* 11 */ ".objc_symbols",
> +  /* 12 */ ".objc_category",
> +  /* 13 */ ".objc_class_vars",
> +  /* 14 */ ".objc_instance_vars",
> +  /* 15 */ ".objc_module_info",
> +  /* 16 */ ".cstring", /* objc_class_names Alias for .cstring */
> +  /* 17 */ ".cstring", /* Alias objc_meth_var_types for .cstring */
> +  /* 18 */ ".cstring", /* objc_meth_var_names Alias for .cstring */
> +  /* 19 */ ".objc_selector_strs",
> +  /* 20 */ ".objc_image_info", /* extension.  */
> +  /* 21 */ ".objc_selector_fixup", /* extension.  */
> +  /* 22 */ ".objc1_class_ext", /* ObjC-1 extension.  */
> +  /* 23 */ ".objc1_property_list", /* ObjC-1 extension.  */
> +  /* 24 */ ".objc1_protocol_ext" /* ObjC-1 extension.  */
> +};
> +
> +/* This currently does the same as known_sections, but kept separate for
> +   ease of maintenance.  */
> +static void
> +obj_mach_o_objc_section (int sect_index)
> +{
> +  segT section;
> +
> +#ifdef md_flush_pending_output
> +  md_flush_pending_output ();
> +#endif
> +
> +  section = obj_mach_o_segT_from_bfd_name (objc_sections[sect_index], 1);
> +  if (section != NULL)
> +    {
> +      seen_objc_section = 1; /* We need to ensure that certain sections are
> +				present and in the right order.  */
> +      subseg_set (section, 0);
> +    }
> +
> +  /* else, we leave the section as it was; there was a fatal error anyway.  */
> +}
> +
> +/* Debug section directives.  */
> +static const char *debug_sections[] =

Ditto.

> +{
> +  /*  0 */ NULL,
> +  /* __DWARF */
> +  /*  1 */ ".debug_frame",
> +  /*  2 */ ".debug_info",
> +  /*  3 */ ".debug_abbrev",
> +  /*  4 */ ".debug_aranges",
> +  /*  5 */ ".debug_macinfo",
> +  /*  6 */ ".debug_line",
> +  /*  7 */ ".debug_loc",
> +  /*  8 */ ".debug_pubnames",
> +  /*  9 */ ".debug_pubtypes",
> +  /* 10 */ ".debug_str",
> +  /* 11 */ ".debug_ranges",
> +  /* 12 */ ".debug_macro"
> +};
> +
> +/* ??? Maybe these should be conditional on gdwarf-*.
> +   It`s also likely that we will need to be able to set them from the cfi
> +   code.  */
> +static void
> +obj_mach_o_debug_section (int sect_index)
> +{
> +  segT section;
> +
> +#ifdef md_flush_pending_output
> +  md_flush_pending_output ();
> +#endif
> +
> +  section = obj_mach_o_segT_from_bfd_name (debug_sections[sect_index], 1);
> +  if (section != NULL)
> +    subseg_set (section, 0);
> +
> +  /* else, we leave the section as it was; there was a fatal error anyway.  */
> +}
> +
> +/* This could be moved to the tc-xx files, but there is so little dependency
> +   there, that the code might as well be shared.  */
> +struct opt_tgt_sect {

'{' on the next line.

> + const char *name;
> + unsigned x86_val;
> + unsigned ppc_val;
> +};
> +
> +/* The extensions here are for specific sections that are generated by GCC
> +   and Darwin system tools, but don't have directives in the `system as'.  */
> +static const struct opt_tgt_sect tgt_sections[] =
> +{
> +  /*  0 */ {NULL, 0, 0},
> +  /*  1 */ {".lazy_symbol_pointer", 0, 0},
> +  /*  2 */ {".lazy_symbol_pointer2", 0, 0}, /* X86 - extension */
> +  /*  3 */ {".lazy_symbol_pointer3", 0, 0}, /* X86 - extension */
> +  /*  4 */ {".non_lazy_symbol_pointer", 0, 0},
> +  /*  5 */ {".non_lazy_symbol_pointer_x86", 0, 0}, /* X86 - extension */
> +  /*  6 */ {".symbol_stub", 16, 20},
> +  /*  7 */ {".symbol_stub1", 0, 16}, /* PPC - extension */
> +  /*  8 */ {".picsymbol_stub", 26, 36},
> +  /*  9 */ {".picsymbol_stub1", 0, 32}, /* PPC - extension */
> +  /* 10 */ {".picsymbol_stub2", 25, 0}, /* X86 - extension */
> +  /* 11 */ {".picsymbol_stub3", 5, 0}, /* X86 - extension  */
> +};

A space after '{'.
Should we #if/#endif arch extensions ?

> +
> +/* Interface for an optional section directive.  */
> +static void
> +obj_mach_o_opt_tgt_section (int sect_index)
> +{
> +  const struct opt_tgt_sect *tgtsct = &tgt_sections[sect_index];
> +  segT section;
> 
> #ifdef md_flush_pending_output
>   md_flush_pending_output ();
> #endif
> 
> -  old_sec = bfd_get_section_by_name (stdoutput, sect->name);
> -  if (old_sec)
> +  section = obj_mach_o_segT_from_bfd_name (tgtsct->name, 0);
> +  if (section == NULL)
>     {
> -      /* Section already present.  */
> -      sec = old_sec;
> -      subseg_set (sec, 0);
> +      as_bad (_("%s is not used for the selected target"), tgtsct->name);
> +      /* Leave the section as it is.  */
>     }
>   else
>     {
> -      bfd_mach_o_section *msect;
> +      bfd_mach_o_section *mo_sec =
> +		OBJ_MACH_O_GET_BACKEND_SECT_DATA (stdoutput, section);
> +      subseg_set (section, 0);
> +#if defined (TC_I386)
> +      mo_sec->reserved2 = tgtsct->x86_val;
> +#elif defined (TC_PPC)
> +      mo_sec->reserved2 = tgtsct->ppc_val;
> +#else
> +      mo_sec->reserved2 = 0;
> +#endif
> +    }
> +}
> 
> -      sec = subseg_force_new (sect->name, 0);
> +/* We don't necessarily have the three 'base' sections on mach-o.
> +   Normally, we would start up with only the 'text' section defined.
> +   However, even that can be suppressed with (TODO) c/l option "-n".
> +   Thus, we have to be able to create all three sections on-demand.  */
> 
> -      /* Set default flags.  */
> -      msect = bfd_mach_o_get_mach_o_section (sec);
> -      msect->flags = sect->flags;
> +static void
> +obj_mach_o_base_section (int sect_index)
> +{
> +  segT section;
> +
> +#ifdef md_flush_pending_output
> +  md_flush_pending_output ();
> +#endif
> +
> +  /* We don't support numeric (or any other) qualifications on the
> +     well-known section shorthands.  */
> +  demand_empty_rest_of_line ();
> +
> +  switch (sect_index)
> +    {
> +      /* Handle the three sections that are globally known within GAS.
> +	 For Mach-O, these are created on demand rather than at startup.  */
> +      case 1:
> +	if (text_section == NULL)
> +	  text_section = obj_mach_o_segT_from_bfd_name (TEXT_SECTION_NAME, 1);
> +	if (is_static)
> +	  {
> +	    bfd_mach_o_section *mo_sec
> +		= OBJ_MACH_O_GET_BACKEND_SECT_DATA (stdoutput, text_section);
> +	    mo_sec->flags &= ~BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS;
> +	  }
> +	section = text_section;
> +	break;
> +      case 2:
> +	if (data_section == NULL)
> +	  data_section = obj_mach_o_segT_from_bfd_name (DATA_SECTION_NAME, 1);
> +	section = data_section;
> +	break;
> +      case 3:
> +        /* ??? maybe this achieves very little, as an addition.  */
> +	if (bss_section == NULL)
> +	  {
> +	    bss_section = obj_mach_o_segT_from_bfd_name (BSS_SECTION_NAME, 1);
> +	    seg_info (bss_section)->bss = 1;
> +	  }
> +	section = bss_section;
> +	break;
> +      default:
> +        as_fatal (_("internal error: base section index out of range"));
> +        return;
> +	break;
>     }
> +  subseg_set (section, 0);
> }
> 
> -/* Called from read.c:s_comm after we've parsed .comm symbol, size.
> -   Parse a possible alignment value.  */
> -
> +/* This finishes off parsing a .comm or .lcomm statement, which both can have
> +   an (optional) alignment field.  It also allows us to create the bss section
> +   on demand.  */
> static symbolS *

Usually we let a blank line between the comment and the definition.  There are many occurrences and I am not sure the existing code always follow this rule.

> -obj_mach_o_common_parse (int ignore ATTRIBUTE_UNUSED,
> -                         symbolS *symbolP, addressT size)
> +obj_mach_o_common_parse (int is_local, symbolS *symbolP,
> +			 addressT size)
> {
>   addressT align = 0;
> 
> +  /* Both comm and lcomm take an optional alignment, as a power
> +     of two between 1 and 15.  */
>   if (*input_line_pointer == ',')
>     {
> +      /* We expect a power of 2.  */
>       align = parse_align (0);
>       if (align == (addressT) -1)
> 	return NULL;
> +      if (align > 15)
> +	{
> +	  as_warn (_("Alignment (%lu) too large: 15 assumed."),
> +		  (unsigned long)align);
> +	  align = 15;
> +	}
>     }
> 
> -  S_SET_VALUE (symbolP, size);
> -  S_SET_EXTERNAL (symbolP);
> -  S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
> +  if (is_local)
> +    {
> +      /* Create the BSS section on demand.  */
> +      if (bss_section == NULL)
> +	{
> +	  bss_section = obj_mach_o_segT_from_bfd_name (BSS_SECTION_NAME, 1);
> +	  seg_info (bss_section)->bss = 1;	
> +	}
> +      bss_alloc (symbolP, size, align);
> +      S_CLEAR_EXTERNAL (symbolP);
> +    }
> +  else
> +    {
> +      S_SET_VALUE (symbolP, size);
> +      S_SET_ALIGN (symbolP, align);
> +      S_SET_EXTERNAL (symbolP);
> +      S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
> +    }
> 
>   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
> 
> @@ -285,9 +659,9 @@ obj_mach_o_common_parse (int ignore ATTRIBUTE_UNUSED,
> }
> 
> static void
> -obj_mach_o_comm (int ignore ATTRIBUTE_UNUSED)
> +obj_mach_o_comm (int is_local)
> {
> -  s_comm_internal (ignore, obj_mach_o_common_parse);
> +  s_comm_internal (is_local, obj_mach_o_common_parse);
> }
> 
> static void
> @@ -297,13 +671,100 @@ obj_mach_o_subsections_via_symbols (int arg ATTRIBUTE_UNUSED)
>   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)
> +{
> +  ignore_rest_of_line ();
> +}
> +
> const pseudo_typeS mach_o_pseudo_table[] =
> {
> -  { "weak", obj_mach_o_weak, 0},
> -  { "section", obj_mach_o_section, 0},
> -  { "cstring", obj_mach_o_known_section, 1},
> -  { "lcomm", s_lcomm, 1 },
> +  /* Section directives.  */
>   { "comm", obj_mach_o_comm, 0 },
> +  { "lcomm", obj_mach_o_comm, 1 },
> +
> +  { "text", obj_mach_o_base_section, 1},
> +  { "data", obj_mach_o_base_section, 2},
> +  { "bss", obj_mach_o_base_section, 3},   /* extension */
> +
> +  { "const", obj_mach_o_known_section, 1},
> +  { "static_const", obj_mach_o_known_section, 2},
> +  { "cstring", obj_mach_o_known_section, 3},
> +  { "literal4", obj_mach_o_known_section, 4},
> +  { "literal8", obj_mach_o_known_section, 5},
> +  { "literal16", obj_mach_o_known_section, 6},
> +  { "constructor", obj_mach_o_known_section, 7},
> +  { "destructor", obj_mach_o_known_section, 8},
> +  { "eh_frame", obj_mach_o_known_section, 9},
> +
> +  { "const_data", obj_mach_o_known_section, 10},
> +  { "static_data", obj_mach_o_known_section, 11},
> +  { "mod_init_func", obj_mach_o_known_section, 12},
> +  { "mod_term_func", obj_mach_o_known_section, 13},
> +  { "dyld", obj_mach_o_known_section, 14},
> +  { "cfstring", obj_mach_o_known_section, 15},
> +
> +  { "objc_class", obj_mach_o_objc_section, 1},
> +  { "objc_meta_class", obj_mach_o_objc_section, 2},
> +  { "objc_cat_cls_meth", obj_mach_o_objc_section, 3},
> +  { "objc_cat_inst_meth", obj_mach_o_objc_section, 4},
> +  { "objc_protocol", obj_mach_o_objc_section, 5},
> +  { "objc_string_object", obj_mach_o_objc_section, 6},
> +  { "objc_cls_meth", obj_mach_o_objc_section, 7},
> +  { "objc_inst_meth", obj_mach_o_objc_section, 8},
> +  { "objc_cls_refs", obj_mach_o_objc_section, 9},
> +  { "objc_message_refs", obj_mach_o_objc_section, 10},
> +  { "objc_symbols", obj_mach_o_objc_section, 11},
> +  { "objc_category", obj_mach_o_objc_section, 12},
> +  { "objc_class_vars", obj_mach_o_objc_section, 13},
> +  { "objc_instance_vars", obj_mach_o_objc_section, 14},
> +  { "objc_module_info", obj_mach_o_objc_section, 15},
> +  { "objc_class_names", obj_mach_o_objc_section, 16}, /* Alias for .cstring */
> +  { "objc_meth_var_types", obj_mach_o_objc_section, 17}, /* Alias for .cstring */
> +  { "objc_meth_var_names", obj_mach_o_objc_section, 18}, /* Alias for .cstring */
> +  { "objc_selector_strs", obj_mach_o_objc_section, 19},
> +  { "objc_image_info", obj_mach_o_objc_section, 20}, /* extension.  */
> +  { "objc_selector_fixup", obj_mach_o_objc_section, 21}, /* extension.  */
> +  { "objc1_class_ext", obj_mach_o_objc_section, 22}, /* ObjC-1 extension.  */
> +  { "objc1_property_list", obj_mach_o_objc_section, 23}, /* ObjC-1 extension.  */
> +  { "objc1_protocol_ext", obj_mach_o_objc_section, 24}, /* ObjC-1 extension.  */
> +
> +  { "debug_frame", obj_mach_o_debug_section, 1}, /* extension.  */
> +  { "debug_info", obj_mach_o_debug_section, 2}, /* extension.  */
> +  { "debug_abbrev", obj_mach_o_debug_section, 3}, /* extension.  */
> +  { "debug_aranges", obj_mach_o_debug_section, 4}, /* extension.  */
> +  { "debug_macinfo", obj_mach_o_debug_section, 5}, /* extension.  */
> +  { "debug_line", obj_mach_o_debug_section, 6}, /* extension.  */
> +  { "debug_loc", obj_mach_o_debug_section, 7}, /* extension.  */
> +  { "debug_pubnames", obj_mach_o_debug_section, 8}, /* extension.  */
> +  { "debug_pubtypes", obj_mach_o_debug_section, 9}, /* extension.  */
> +  { "debug_str", obj_mach_o_debug_section, 10}, /* extension.  */
> +  { "debug_ranges", obj_mach_o_debug_section, 11}, /* extension.  */
> +  { "debug_macro", obj_mach_o_debug_section, 12}, /* extension.  */
> +
> +  { "lazy_symbol_pointer", obj_mach_o_opt_tgt_section, 1},
> +  { "lazy_symbol_pointer2", obj_mach_o_opt_tgt_section, 2}, /* extension.  */
> +  { "lazy_symbol_pointer3", obj_mach_o_opt_tgt_section, 3}, /* extension.  */
> +  { "non_lazy_symbol_pointer", obj_mach_o_opt_tgt_section, 4},
> +  { "non_lazy_symbol_pointer_x86", obj_mach_o_opt_tgt_section, 5}, /* extension.  */
> +  { "symbol_stub", obj_mach_o_opt_tgt_section, 6},
> +  { "symbol_stub1", obj_mach_o_opt_tgt_section, 7}, /* extension.  */
> +  { "picsymbol_stub", obj_mach_o_opt_tgt_section, 8}, /* extension.  */
> +  { "picsymbol_stub1", obj_mach_o_opt_tgt_section, 9}, /* extension.  */
> +  { "picsymbol_stub2", obj_mach_o_opt_tgt_section, 4}, /* extension.  */
> +  { "picsymbol_stub3", obj_mach_o_opt_tgt_section, 4}, /* extension.  */

#if/#endif arch specific pseudo ?

> +
> +  { "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 */
> +
> +  /* File flags.  */
>   { "subsections_via_symbols", obj_mach_o_subsections_via_symbols, 0 },
> 
>   {NULL, NULL, 0}

> diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h
> index d7e9bda..1203cd8 100644
> --- a/gas/config/obj-macho.h
> +++ b/gas/config/obj-macho.h
> @@ -1,5 +1,5 @@
> /* Mach-O object file format for gas, the assembler.
> -   Copyright 2009 Free Software Foundation, Inc.
> +   Copyright 2009, 2011 Free Software Foundation, Inc.
> 
>    This file is part of GAS, the GNU Assembler.
> 
> @@ -18,13 +18,29 @@
>    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
>    02110-1301, USA.  */
> 
> +#ifndef _OBJ_MACH_O_H
> +#define _OBJ_MACH_O_H
> +
> /* Tag to validate Mach-O object file format processing */
> #define OBJ_MACH_O 1
> 
> +#include "bfd/mach-o.h"
> +
> #include "targ-cpu.h"
> 
> #define OUTPUT_FLAVOR bfd_target_mach_o_flavour
> 
> +/* All our align expressions are power of two.  */
> +#define USE_ALIGN_PTWO
> +
> +/* 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);\
> +} while (0)
> +#endif
> +
> extern const pseudo_typeS mach_o_pseudo_table[];
> 
> #ifndef obj_pop_insert
> @@ -37,3 +53,12 @@ extern const pseudo_typeS mach_o_pseudo_table[];
> #define obj_symbol_new_hook(s)	{;}
> 
> #define EMIT_SECTION_SYMBOLS		0
> +
> +/* Accessor macros for the Mach-O backend data, in case we need to change how
> +   this is done.  */
> +#define OBJ_MACH_O_SET_BACKEND_SECT_DATA(ABFD, BFDSEC, MACHOSEC) \
> +  (BFDSEC)->used_by_bfd = (MACHOSEC)
> +
> +#define OBJ_MACH_O_GET_BACKEND_SECT_DATA(ABFD, BFDSEC) (BFDSEC)->used_by_bfd

Doesn't this duplicate mach-o.h: bfd_mach_o_get_mach_o_section ?

> +
> +#endif /* _OBJ_MACH_O_H */
> diff --git a/include/mach-o/loader.h b/include/mach-o/loader.h
> index 357f65e..296782f 100644
> --- a/include/mach-o/loader.h
> +++ b/include/mach-o/loader.h
> @@ -246,6 +246,9 @@ bfd_mach_o_section_type;
> 
> typedef enum bfd_mach_o_section_attribute
> {
> +  /* Section has no specified attibutes.  */
> +  BFD_MACH_O_S_ATTR_NONE              = 0,
> +
>   /* Section has local relocation entries.  */
>   BFD_MACH_O_S_ATTR_LOC_RELOC         = 0x00000100,

ok.



More information about the Binutils mailing list