2011-08-08 Tristan Gingold <gingold@adacore.com>
authorTristan Gingold <gingold@adacore.com>
Mon, 8 Aug 2011 12:20:01 +0000 (12:20 +0000)
committerTristan Gingold <gingold@adacore.com>
Mon, 8 Aug 2011 12:20:01 +0000 (12:20 +0000)
* 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.

gas/ChangeLog
gas/config/obj-macho.c

index 110c77e..e3d925f 100644 (file)
@@ -1,3 +1,14 @@
+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.
+
 2011-08-06  Richard Henderson  <rth@redhat.com>
 
        * dw2gencfi.c (all_fde_data): Export.
index ee19c4a..5f1255d 100644 (file)
 #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,9 +53,258 @@ obj_mach_o_weak (int ignore ATTRIBUTE_UNUSED)
   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)
+    {
+      /* 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
+         on disk.  */
+      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
+
+  /* Sub-segments don't exists as is on Mach-O.  */
+  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;
+}
+
+static void
+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},
+  { "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}
 };