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.
This commit is contained in:
parent
d82ea6a8a9
commit
cdaa5616cb
7 changed files with 276 additions and 59 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
#define obj_frob_symbol(s, punt) punt = obj_macho_frob_symbol(s)
|
||||
extern int obj_macho_frob_symbol (struct symbol *);
|
||||
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 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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
Loading…
Reference in a new issue