From cdaa5616cb95596ecf0c09c08a2bf55f39c82019 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 21 Feb 2012 09:13:02 +0000 Subject: [PATCH] 2012-02-21 Tristan Gingold * 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 | 29 +++++++ gas/config/obj-macho.c | 228 +++++++++++++++++++++++++++++++++++++++---------- gas/config/obj-macho.h | 53 +++++++++--- gas/config/tc-i386.h | 14 +++ gas/frags.h | 3 + gas/symbols.c | 4 + gas/write.c | 4 + 7 files changed, 276 insertions(+), 59 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 2f9d09a..7a8fcb5 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,32 @@ +2012-02-21 Tristan Gingold + + * 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 * config/obj-macho.c (obj_mach_o_is_frame_section): New. diff --git a/gas/config/obj-macho.c b/gas/config/obj-macho.c index 4623384..376e620 100644 --- a/gas/config/obj-macho.c +++ b/gas/config/obj-macho.c @@ -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; +} diff --git a/gas/config/obj-macho.h b/gas/config/obj-macho.h index e081ba0..0ac8df4 100644 --- a/gas/config/obj-macho.h +++ b/gas/config/obj-macho.h @@ -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 */ diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index 688c69a..cc86c9d 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -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 */ diff --git a/gas/frags.h b/gas/frags.h index dd247f9..a1fabfb 100644 --- a/gas/frags.h +++ b/gas/frags.h @@ -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]; diff --git a/gas/symbols.c b/gas/symbols.c index 12b2f8f..679534d 100644 --- a/gas/symbols.c +++ b/gas/symbols.c @@ -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); diff --git a/gas/write.c b/gas/write.c index 5d4e073..f640c61 100644 --- a/gas/write.c +++ b/gas/write.c @@ -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. */ -- 2.7.4