2012-02-21 Tristan Gingold <gingold@adacore.com>
authorIain Sandoe <iain@codesourcery.com>
Tue, 21 Feb 2012 09:13:02 +0000 (09:13 +0000)
committerIain Sandoe <iain@codesourcery.com>
Tue, 21 Feb 2012 09:13:02 +0000 (09:13 +0000)
* config/tc-i386.h (OBJ_MACH_O): New section.
(TC_FORCE_RELOCATION): Use obj_mach_o_force_reloc.
(TC_FORCE_RELOCATION_SUB_SAME): New
(TC_FORCE_RELOCATION_SUB_LOCAL): New.
(TC_VALIDATE_FIX_SUB): New.
* frags.h (struct frag): OBJ_FRAG_TYPE, new field.
* symbols.c (colon): obj_frob_colon: New hook.
* write.c (write_object_file): md_pre_relax_hook, new
hook.
* config/obj-macho.c (obj_mach_o_frob_colon): New.
(obj_mach_o_frob_label): Record sub-section labels.
(obj_mach_o_frob_symbol): Rename from obj_macho_frob_symbol.
(obj_mach_o_set_subsections): New.
(obj_mach_o_pre_relax_hook): New.
(obj_mach_o_in_different_subsection): New.
(obj_mach_o_force_reloc_sub_same): New.
(obj_mach_o_force_reloc_sub_local): New.
(obj_mach_o_force_reloc): New.
* config/obj-macho.h (OBJ_SYMFIELD_TYPE): New.
(obj_frob_colon): New Define.
(obj_mach_o_frob_label): Renamed.
(obj_mach_o_frob_symbol): Renamed.
(OBJ_FRAG_TYPE): New.
(obj_mach_o_in_different_subsection, obj_mach_o_force_reloc,
 obj_mach_o_force_reloc_sub_same,
 obj_mach_o_force_reloc_sub_local): New declarations.

gas/ChangeLog
gas/config/obj-macho.c
gas/config/obj-macho.h
gas/config/tc-i386.h
gas/frags.h
gas/symbols.c
gas/write.c

index 2f9d09a2e3101edf4d5c35dbcc9747891b86eeb9..7a8fcb59f7b88b6baa86753fffec275186453624 100644 (file)
@@ -1,3 +1,32 @@
+2012-02-21  Tristan Gingold  <gingold@adacore.com>
+
+       * config/tc-i386.h (OBJ_MACH_O): New section.
+       (TC_FORCE_RELOCATION): Use obj_mach_o_force_reloc.
+       (TC_FORCE_RELOCATION_SUB_SAME): New
+       (TC_FORCE_RELOCATION_SUB_LOCAL): New.
+       (TC_VALIDATE_FIX_SUB): New.
+       * frags.h (struct frag): OBJ_FRAG_TYPE, new field.
+       * symbols.c (colon): obj_frob_colon: New hook.
+       * write.c (write_object_file): md_pre_relax_hook, new
+       hook.
+       * config/obj-macho.c (obj_mach_o_frob_colon): New.
+       (obj_mach_o_frob_label): Record sub-section labels.
+       (obj_mach_o_frob_symbol): Rename from obj_macho_frob_symbol.
+       (obj_mach_o_set_subsections): New.
+       (obj_mach_o_pre_relax_hook): New.
+       (obj_mach_o_in_different_subsection): New.
+       (obj_mach_o_force_reloc_sub_same): New.
+       (obj_mach_o_force_reloc_sub_local): New.
+       (obj_mach_o_force_reloc): New.
+       * config/obj-macho.h (OBJ_SYMFIELD_TYPE): New.
+       (obj_frob_colon): New Define.
+       (obj_mach_o_frob_label): Renamed.
+       (obj_mach_o_frob_symbol): Renamed.
+       (OBJ_FRAG_TYPE): New.
+       (obj_mach_o_in_different_subsection, obj_mach_o_force_reloc,
+        obj_mach_o_force_reloc_sub_same,
+        obj_mach_o_force_reloc_sub_local): New declarations.
+
 2012-02-20  Iain Sandoe  <idsandoe@googlemail.com>
 
        * config/obj-macho.c (obj_mach_o_is_frame_section): New.
index 4623384017659ff27bab7833589cac11793861ad..376e620d428effc049a141cdb9e7861c6ac70b60 100644 (file)
@@ -56,6 +56,7 @@ static int obj_mach_o_is_static;
 
 /* TODO: Implement the "-n" command line option to suppress the initial
    switch to the text segment.  */
+
 static int obj_mach_o_start_with_text_section = 1;
 
 /* Allow for special re-ordering on output.  */
@@ -1343,6 +1344,18 @@ obj_mach_o_type_for_symbol (bfd_mach_o_asymbol *s)
     return BFD_MACH_O_N_SECT;
 }
 
+void
+obj_mach_o_frob_colon (const char *name)
+{
+  if (!bfd_is_local_label_name (stdoutput, name))
+    {
+      /* A non-local label will create a new subsection, so start a new
+         frag.  */
+      frag_wane (frag_now);
+      frag_new (0);
+    }
+}
+
 /* 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.
    
@@ -1357,13 +1370,21 @@ obj_mach_o_type_for_symbol (bfd_mach_o_asymbol *s)
    are possibly incompatible with the section etc. that the symbol is defined
    in.  */
 
-void obj_macho_frob_label (struct symbol *sp)
+void obj_mach_o_frob_label (struct symbol *sp)
 {
   bfd_mach_o_asymbol *s;
   unsigned base_type;
   bfd_mach_o_section *sec;
   int sectype = -1;
 
+  if (!bfd_is_local_label_name (stdoutput, S_GET_NAME (sp)))
+    {
+      /* If this is a non-local label, it should have started a new sub-
+        section.  */
+      gas_assert (frag_now->obj_frag_data.subsection == NULL);
+      frag_now->obj_frag_data.subsection = sp;
+    }
+
   /* Leave local symbols alone.  */
 
   if (S_IS_LOCAL (sp))
@@ -1404,7 +1425,7 @@ void obj_macho_frob_label (struct symbol *sp)
    (e.g. global + weak_def).  */
 
 int
-obj_macho_frob_symbol (struct symbol *sp)
+obj_mach_o_frob_symbol (struct symbol *sp)
 {
   bfd_mach_o_asymbol *s;
   unsigned base_type;
@@ -1495,17 +1516,93 @@ obj_macho_frob_symbol (struct symbol *sp)
   return 0;
 }
 
-/* Relocation rules are different in frame sections.  */
+/* Support stabs for mach-o.  */
 
-static int
-obj_mach_o_is_frame_section (segT sec)
+void
+obj_mach_o_process_stab (int what, const char *string,
+                        int type, int other, int desc)
 {
-  int l;
-  l = strlen (segment_name (sec));
-  if ((l == 9 && strncmp (".eh_frame", segment_name (sec), 9) == 0)
-       || (l == 12 && strncmp (".debug_frame", segment_name (sec), 12) == 0))
-    return 1;
-  return 0;
+  symbolS *symbolP;
+  bfd_mach_o_asymbol *s;
+
+  switch (what)
+    {
+      case 'd':
+       symbolP = symbol_new ("", now_seg, frag_now_fix (), frag_now);
+       /* Special stabd NULL name indicator.  */
+       S_SET_NAME (symbolP, NULL);
+       break;
+
+      case 'n':
+      case 's':
+       symbolP = symbol_new (string, undefined_section, (valueT) 0,
+                             &zero_address_frag);
+       pseudo_set (symbolP);
+       break;
+
+      default:
+       as_bad(_("unrecognized stab type '%c'"), (char)what);
+       abort ();
+       break;
+    }
+
+  s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (symbolP);
+  s->n_type = type;
+  s->n_desc = desc;
+  /* For stabd, this will eventually get overwritten by the section number.  */
+  s->n_sect = other;
+
+  /* It's a debug symbol.  */
+  s->symbol.flags |= BSF_DEBUGGING;
+}
+
+/* Here we count up frags in each subsection (where a sub-section is defined
+   as starting with a non-local symbol).
+   Note that, if there are no non-local symbols in a section, all the frags will
+   be attached as one anonymous subsection.  */
+
+static void
+obj_mach_o_set_subsections (bfd *abfd ATTRIBUTE_UNUSED,
+                            asection *sec,
+                            void *unused ATTRIBUTE_UNUSED)
+{
+  segment_info_type *seginfo = seg_info (sec);
+  symbolS *cur_subsection = NULL;
+  struct obj_mach_o_symbol_data *cur_subsection_data = NULL;
+  fragS *frag;
+  frchainS *chain;
+
+  /* Protect against sections not created by gas.  */
+  if (seginfo == NULL)
+    return;
+
+  /* Attach every frag to a subsection.  */
+  for (chain = seginfo->frchainP; chain != NULL; chain = chain->frch_next)
+    for (frag = chain->frch_root; frag != NULL; frag = frag->fr_next)
+      {
+        if (frag->obj_frag_data.subsection == NULL)
+          frag->obj_frag_data.subsection = cur_subsection;
+        else
+          {
+            cur_subsection = frag->obj_frag_data.subsection;
+            cur_subsection_data = symbol_get_obj (cur_subsection);
+            cur_subsection_data->subsection_size = 0;
+          }
+        if (cur_subsection_data != NULL)
+          {
+            /* Update subsection size.  */
+            cur_subsection_data->subsection_size += frag->fr_fix;
+          }
+      }
+}
+
+/* Handle mach-o subsections-via-symbols counting up frags belonging to each 
+   sub-section.  */
+
+void
+obj_mach_o_pre_relax_hook (void)
+{
+  bfd_map_over_sections (stdoutput, obj_mach_o_set_subsections, (char *) 0);
 }
 
 /* Zerofill and GB Zerofill sections must be sorted to follow all other
@@ -1731,44 +1828,17 @@ obj_mach_o_reorder_section_relocs (asection *sec, arelent **rels, unsigned int n
   bfd_set_reloc (stdoutput, sec, rels, n);
 }
 
-/* Support stabs for mach-o.  */
+/* Relocation rules are different in frame sections.  */
 
-void
-obj_mach_o_process_stab (int what, const char *string,
-                        int type, int other, int desc)
+static int
+obj_mach_o_is_frame_section (segT sec)
 {
-  symbolS *symbolP;
-  bfd_mach_o_asymbol *s;
-
-  switch (what)
-    {
-      case 'd':
-       symbolP = symbol_new ("", now_seg, frag_now_fix (), frag_now);
-       /* Special stabd NULL name indicator.  */
-       S_SET_NAME (symbolP, NULL);
-       break;
-
-      case 'n':
-      case 's':
-       symbolP = symbol_new (string, undefined_section, (valueT) 0,
-                             &zero_address_frag);
-       pseudo_set (symbolP);
-       break;
-
-      default:
-       as_bad(_("unrecognized stab type '%c'"), (char)what);
-       abort ();
-       break;
-    }
-
-  s = (bfd_mach_o_asymbol *) symbol_get_bfdsym (symbolP);
-  s->n_type = type;
-  s->n_desc = desc;
-  /* For stabd, this will eventually get overwritten by the section number.  */
-  s->n_sect = other;
-
-  /* It's a debug symbol.  */
-  s->symbol.flags |= BSF_DEBUGGING;
+  int l;
+  l = strlen (segment_name (sec));
+  if ((l == 9 && strncmp (".eh_frame", segment_name (sec), 9) == 0)
+       || (l == 12 && strncmp (".debug_frame", segment_name (sec), 12) == 0))
+    return 1;
+  return 0;
 }
 
 /* Unless we're in a frame section, we need to force relocs to be generated for
@@ -1788,3 +1858,67 @@ obj_mach_o_allow_local_subtract (expressionS * left ATTRIBUTE_UNUSED,
   /* Allow in frame sections, otherwise emit a reloc.  */
   return obj_mach_o_is_frame_section (seg);
 }
+
+int
+obj_mach_o_in_different_subsection (symbolS *a, symbolS *b)
+{
+  fragS *fa;
+  fragS *fb;
+
+  if (S_GET_SEGMENT (a) != S_GET_SEGMENT (b)
+      || !S_IS_DEFINED (a)
+      || !S_IS_DEFINED (b))
+    {
+      /* Not in the same segment, or undefined symbol.  */
+      return 1;
+    }
+
+  fa = symbol_get_frag (a);
+  fb = symbol_get_frag (b);
+  if (fa == NULL || fb == NULL)
+    {
+      /* One of the symbols is not in a subsection.  */
+      return 1;
+    }
+
+  return fa->obj_frag_data.subsection != fb->obj_frag_data.subsection;
+}
+
+int
+obj_mach_o_force_reloc_sub_same (fixS *fix, segT seg)
+{
+  if (! SEG_NORMAL (seg))
+    return 1;
+  return obj_mach_o_in_different_subsection (fix->fx_addsy, fix->fx_subsy);
+}
+
+int
+obj_mach_o_force_reloc_sub_local (fixS *fix, segT seg ATTRIBUTE_UNUSED)
+{
+  return obj_mach_o_in_different_subsection (fix->fx_addsy, fix->fx_subsy);
+}
+
+int
+obj_mach_o_force_reloc (fixS *fix)
+{
+  if (generic_force_reloc (fix))
+    return 1;
+
+  /* Force a reloc if the target is not in the same subsection.
+     FIXME: handle (a - b) where a and b belongs to the same subsection ?  */
+  if (fix->fx_addsy != NULL)
+    {
+      symbolS *subsec = fix->fx_frag->obj_frag_data.subsection;
+      symbolS *targ = fix->fx_addsy;
+
+      /* There might be no subsections at all.  */
+      if (subsec == NULL)
+        return 0;
+
+      if (S_GET_SEGMENT (targ) == absolute_section)
+        return 0;
+
+      return obj_mach_o_in_different_subsection (targ, subsec);
+    }
+  return 0;
+}
index e081ba0ec2d25471925113fd820c5b275caf1157..0ac8df4174a8e4d2083f64db8772c95b7951331f 100644 (file)
@@ -35,7 +35,7 @@
 extern void mach_o_begin (void);
 
 /* All our align expressions are power of two.  */
-#define USE_ALIGN_PTWO
+#define USE_ALIGN_PTWO 1
 
 /* Common symbols can carry alignment information.  */
 #ifndef S_SET_ALIGN
@@ -56,22 +56,50 @@ 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 EMIT_SECTION_SYMBOLS           0
+
+struct obj_mach_o_symbol_data
+{
+  /* If the symbol represents a subsection, this is the size of the subsection.
+     This is used to check whether a local symbol belongs to a subsection.  */
+  valueT subsection_size;
+};
+#define OBJ_SYMFIELD_TYPE struct obj_mach_o_symbol_data
+
+#define obj_frob_colon obj_mach_o_frob_colon
+extern void obj_mach_o_frob_colon (const char *);
+
+/* Called when a label is defined.  Mach-O uses this to create subsections.  */
+#define obj_frob_label obj_mach_o_frob_label
+extern void obj_mach_o_frob_label (symbolS *);
+
+#define obj_frob_symbol(s, punt) punt = obj_mach_o_frob_symbol(s)
+extern int obj_mach_o_frob_symbol (struct symbol *);
+
+#define OBJ_PROCESS_STAB(SEG,W,S,T,O,D)        obj_mach_o_process_stab(W,S,T,O,D)
+extern void obj_mach_o_process_stab (int, const char *,int, int, int);
+
+struct obj_mach_o_frag_data
+{
+  /* Symbol that corresponds to the subsection.  */
+  symbolS *subsection;
+};
+  
+#define OBJ_FRAG_TYPE struct obj_mach_o_frag_data
 
-#define obj_frob_symbol(s, punt) punt = obj_macho_frob_symbol(s)
-extern int obj_macho_frob_symbol (struct symbol *);
+#define md_pre_relax_hook obj_mach_o_pre_relax_hook()
+extern void obj_mach_o_pre_relax_hook (void);
 
 #define md_post_relax_hook obj_mach_o_post_relax_hook()
-void obj_mach_o_post_relax_hook (void);
+extern void obj_mach_o_post_relax_hook (void);
 
 #define obj_frob_file_after_relocs obj_mach_o_frob_file_after_relocs
 extern void obj_mach_o_frob_file_after_relocs (void);
 
-void obj_mach_o_reorder_section_relocs (asection *, arelent **, unsigned int);
-
 #define SET_SECTION_RELOCS(sec, relocs, n) \
   obj_mach_o_reorder_section_relocs (sec, relocs, n)
+extern void obj_mach_o_reorder_section_relocs (asection *, arelent **,
+                                              unsigned int);
 
 /* Emit relocs for local subtracts, to cater for subsections-via-symbols.  */
 #define md_allow_local_subtract(LEFT, RIGHT, SECTION) \
@@ -79,9 +107,10 @@ void obj_mach_o_reorder_section_relocs (asection *, arelent **, unsigned int);
 extern int obj_mach_o_allow_local_subtract (expressionS *, expressionS *,
                                            segT);
 
-#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)
-extern void obj_mach_o_process_stab (int, const char *,int, int, int);
+struct fix;
+extern int obj_mach_o_in_different_subsection (symbolS *a, symbolS *b);
+extern int obj_mach_o_force_reloc (struct fix *fix);
+extern int obj_mach_o_force_reloc_sub_same (struct fix *fix, segT seg);
+extern int obj_mach_o_force_reloc_sub_local (struct fix *fix, segT seg);
 
 #endif /* _OBJ_MACH_O_H */
index 688c69a5470b56061dc0edcff2227418652c1054..cc86c9d2062a1483a26788fc1013e174c4b4d862 100644 (file)
@@ -316,4 +316,18 @@ void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int);
 /* X_add_symbol:X_op_symbol (Intel mode only) */
 #define O_full_ptr O_md2
 
+#ifdef OBJ_MACH_O
+
+#define TC_FORCE_RELOCATION(FIX) (obj_mach_o_force_reloc (FIX))
+
+#define TC_FORCE_RELOCATION_SUB_SAME(FIX,SEG) \
+         (obj_mach_o_force_reloc_sub_same (FIX, SEG))
+
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX,SEG) \
+       (obj_mach_o_force_reloc_sub_local (FIX, SEG))
+
+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
+
+#endif /* OBJ_MACH_O */
+
 #endif /* TC_I386 */
index dd247f9c535accacd61b55723080ea9ef0431ed6..a1fabfb97a567dbf334f601806374c338522fe04 100644 (file)
@@ -100,6 +100,9 @@ struct frag {
 #ifdef TC_FRAG_TYPE
   TC_FRAG_TYPE tc_frag_data;
 #endif
+#ifdef OBJ_FRAG_TYPE
+  OBJ_FRAG_TYPE obj_frag_data;
+#endif
 
   /* Data begins here.  */
   char fr_literal[1];
index 12b2f8fe27ae89913547b5df8c38db8c8ca79e71..679534d48a03232f279aa1b20a2fc9dbae71ba38 100644 (file)
@@ -317,6 +317,10 @@ colon (/* Just seen "x:" - rattle symbols & frags.  */
     }
 #endif /* WORKING_DOT_WORD */
 
+#ifdef obj_frob_colon
+  obj_frob_colon (sym_name);
+#endif
+
   if ((symbolP = symbol_find (sym_name)) != 0)
     {
       S_CLEAR_WEAKREFR (symbolP);
index 5d4e073c01609248f167cabafa8e944eacc647a1..f640c6103d13553c0565094a4b6f1ac15a64e000 100644 (file)
@@ -1790,6 +1790,10 @@ write_object_file (void)
       }
   }
 
+#ifdef md_pre_relax_hook
+  md_pre_relax_hook;
+#endif
+
   /* From now on, we don't care about sub-segments.  Build one frag chain
      for each segment. Linked thru fr_next.  */