This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[mach-o/committed]: Add a few pseudo-ops to gas
- From: Tristan Gingold <gingold at adacore dot com>
- To: binutils Development <binutils at sourceware dot org>
- Date: Mon, 8 Aug 2011 14:19:46 +0200
- Subject: [mach-o/committed]: Add a few pseudo-ops to gas
Hi,
this patch adds a few pseudo-ops to gas, mostly .section
Slightly tested.
Tristan.
gas/
2011-08-08 Tristan Gingold <gingold@adacore.com>
* config/obj-macho.c (obj_mach_o_section): New function.
(struct known_section): New type.
(known_sections): Declare.
(obj_mach_o_known_section): New function.
(obj_mach_o_common_parse): Ditto.
(obj_mach_o_comm): Ditto.
(obj_mach_o_subsections_via_symbols): Ditto.
(mach_o_pseudo_table): Add new pseudos.
Index: config/obj-macho.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-macho.c,v
retrieving revision 1.1
diff -c -r1.1 obj-macho.c
*** config/obj-macho.c 2 Jul 2009 08:09:35 -0000 1.1
--- config/obj-macho.c 8 Aug 2011 12:06:59 -0000
***************
*** 21,27 ****
--- 21,31 ----
#define OBJ_HEADER "obj-macho.h"
#include "as.h"
+ #include "subsegs.h"
+ #include "symbols.h"
+ #include "write.h"
#include "mach-o.h"
+ #include "mach-o/loader.h"
static void
obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED)
***************
*** 49,57 ****
demand_empty_rest_of_line ();
}
const pseudo_typeS mach_o_pseudo_table[] =
{
! {"weak", obj_mach_o_weak, 0},
{NULL, NULL, 0}
};
--- 53,306 ----
demand_empty_rest_of_line ();
}
+ /* Parse:
+ .section segname,sectname[,type[,attribute[,sizeof_stub]]]
+ */
+
+ 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 secattr = 0;
+ offsetT sizeof_stub = 0;
+ const char *name;
+ flagword oldflags, flags;
+ asection *sec;
+
+ /* Parse segment name. */
+ if (!is_name_beginner (*input_line_pointer))
+ {
+ 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++;
+
+ /* 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;
+
+ /* Parse type. */
+ if (*input_line_pointer == ',')
+ {
+ input_line_pointer++;
+ if (!is_name_beginner (*input_line_pointer))
+ {
+ as_bad (_("missing section type name"));
+ ignore_rest_of_line ();
+ return;
+ }
+ p = input_line_pointer;
+ c = get_symbol_end ();
+
+ sectype = bfd_mach_o_get_section_type_from_name (p);
+ if (sectype == -1)
+ {
+ 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 == ',')
+ {
+ do
+ {
+ int attr;
+
+ 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 ();
+
+ attr = bfd_mach_o_get_section_attribute_from_name (p);
+ if (attr == -1)
+ as_bad (_("unknown or invalid section attribute '%s'"), p);
+ else
+ secattr |= attr;
+
+ *input_line_pointer = c;
+ }
+ while (*input_line_pointer == '+');
+
+ /* Parse sizeof_stub. */
+ if (*input_line_pointer == ',')
+ {
+ if (sectype != BFD_MACH_O_S_SYMBOL_STUBS)
+ as_bad (_("unexpected sizeof_stub expression"));
+
+ sizeof_stub = get_absolute_expression ();
+ }
+ else if (sectype == BFD_MACH_O_S_SYMBOL_STUBS)
+ as_bad (_("missing sizeof_stub expression"));
+ }
+ }
+ demand_empty_rest_of_line ();
+
+ bfd_mach_o_normalize_section_name (segname, sectname, &name, &flags);
+ if (name == NULL)
+ {
+ size_t seglen = strlen (segname);
+ size_t sectlen = strlen (sectname);
+ char *n;
+
+ n = xmalloc (seglen + 1 + sectlen + 1);
+ memcpy (n, segname, seglen);
+ n[seglen] = '.';
+ memcpy (n + seglen + 1, sectname, sectlen);
+ n[seglen + 1 + sectlen] = 0;
+ name = n;
+ }
+
+ #ifdef md_flush_pending_output
+ md_flush_pending_output ();
+ #endif
+
+ /* No subseg. */
+ sec = subseg_new (name, 0);
+
+ oldflags = bfd_get_section_flags (stdoutput, 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->reserved2 = sizeof_stub;
+ }
+ else if (flags != SEC_NO_FLAGS)
+ {
+ if (flags != oldflags)
+ as_warn (_("Ignoring changed section attributes for %s"), name);
+ }
+ }
+
+ struct known_section {
+ const char *name;
+ unsigned int flags;
+ };
+
+ static const struct known_section known_sections[] =
+ {
+ /* 0 */ { NULL, 0},
+ /* 1 */ { ".cstring", BFD_MACH_O_S_CSTRING_LITERALS }
+ };
+
+ static void
+ obj_mach_o_known_section (int sect_index)
+ {
+ const struct known_section *sect = &known_sections[sect_index];
+ asection *old_sec;
+ segT sec;
+
+ #ifdef md_flush_pending_output
+ md_flush_pending_output ();
+ #endif
+
+ old_sec = bfd_get_section_by_name (stdoutput, sect->name);
+ if (old_sec)
+ {
+ /* Section already present. */
+ sec = old_sec;
+ subseg_set (sec, 0);
+ }
+ else
+ {
+ bfd_mach_o_section *msect;
+
+ sec = subseg_force_new (sect->name, 0);
+
+ /* Set default flags. */
+ msect = bfd_mach_o_get_mach_o_section (sec);
+ msect->flags = sect->flags;
+ }
+ }
+
+ /* Called from read.c:s_comm after we've parsed .comm symbol, size.
+ Parse a possible alignment value. */
+
+ static symbolS *
+ obj_mach_o_common_parse (int ignore ATTRIBUTE_UNUSED,
+ symbolS *symbolP, addressT size)
+ {
+ addressT align = 0;
+
+ if (*input_line_pointer == ',')
+ {
+ align = parse_align (0);
+ if (align == (addressT) -1)
+ return NULL;
+ }
+
+ S_SET_VALUE (symbolP, size);
+ S_SET_EXTERNAL (symbolP);
+ S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
+
+ symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
+
+ return symbolP;
+ }
+
+ obj_mach_o_comm (int ignore ATTRIBUTE_UNUSED)
+ {
+ s_comm_internal (ignore, obj_mach_o_common_parse);
+ }
+
+ static void
+ obj_mach_o_subsections_via_symbols (int arg ATTRIBUTE_UNUSED)
+ {
+ /* Currently ignore it. */
+ demand_empty_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 },
! { "comm", obj_mach_o_comm, 0 },
! { "subsections_via_symbols", obj_mach_o_subsections_via_symbols, 0 },
{NULL, NULL, 0}
};