Line 1... |
Line 1... |
/* write.c - emit .o file
|
/* write.c - emit .o file
|
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
|
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
2010, 2011 Free Software Foundation, Inc.
|
2010, 2011, 2012 Free Software Foundation, Inc.
|
|
|
This file is part of GAS, the GNU Assembler.
|
This file is part of GAS, the GNU Assembler.
|
|
|
GAS is free software; you can redistribute it and/or modify
|
GAS is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
Line 149... |
Line 149... |
int size, /* 1, 2, or 4 usually. */
|
int size, /* 1, 2, or 4 usually. */
|
symbolS *add_symbol, /* X_add_symbol. */
|
symbolS *add_symbol, /* X_add_symbol. */
|
symbolS *sub_symbol, /* X_op_symbol. */
|
symbolS *sub_symbol, /* X_op_symbol. */
|
offsetT offset, /* X_add_number. */
|
offsetT offset, /* X_add_number. */
|
int pcrel, /* TRUE if PC-relative relocation. */
|
int pcrel, /* TRUE if PC-relative relocation. */
|
RELOC_ENUM r_type ATTRIBUTE_UNUSED /* Relocation type. */,
|
RELOC_ENUM r_type /* Relocation type. */,
|
int at_beginning) /* Add to the start of the list? */
|
int at_beginning) /* Add to the start of the list? */
|
{
|
{
|
fixS *fixP;
|
fixS *fixP;
|
|
|
n_fixups++;
|
n_fixups++;
|
Line 652... |
Line 652... |
and check for validity. Convert RELOC_LIST from using U.A fields
|
and check for validity. Convert RELOC_LIST from using U.A fields
|
to U.B fields. */
|
to U.B fields. */
|
static void
|
static void
|
resolve_reloc_expr_symbols (void)
|
resolve_reloc_expr_symbols (void)
|
{
|
{
|
|
bfd_vma addr_mask = 1;
|
struct reloc_list *r;
|
struct reloc_list *r;
|
|
|
|
/* Avoid a shift by the width of type. */
|
|
addr_mask <<= bfd_arch_bits_per_address (stdoutput) - 1;
|
|
addr_mask <<= 1;
|
|
addr_mask -= 1;
|
|
|
for (r = reloc_list; r; r = r->next)
|
for (r = reloc_list; r; r = r->next)
|
{
|
{
|
|
reloc_howto_type *howto = r->u.a.howto;
|
expressionS *symval;
|
expressionS *symval;
|
symbolS *sym;
|
symbolS *sym;
|
bfd_vma offset, addend;
|
bfd_vma offset, addend;
|
asection *sec;
|
asection *sec;
|
reloc_howto_type *howto;
|
|
|
|
resolve_symbol_value (r->u.a.offset_sym);
|
resolve_symbol_value (r->u.a.offset_sym);
|
symval = symbol_get_value_expression (r->u.a.offset_sym);
|
symval = symbol_get_value_expression (r->u.a.offset_sym);
|
|
|
offset = 0;
|
offset = 0;
|
Line 707... |
Line 713... |
as_bad_where (r->file, r->line, _("invalid reloc expression"));
|
as_bad_where (r->file, r->line, _("invalid reloc expression"));
|
sec = NULL;
|
sec = NULL;
|
}
|
}
|
else if (sym != NULL)
|
else if (sym != NULL)
|
{
|
{
|
if (S_IS_LOCAL (sym) && !symbol_section_p (sym))
|
/* Convert relocs against local symbols to refer to the
|
|
corresponding section symbol plus offset instead. Keep
|
|
PC-relative relocs of the REL variety intact though to
|
|
prevent the offset from overflowing the relocated field,
|
|
unless it has enough bits to cover the whole address
|
|
space. */
|
|
if (S_IS_LOCAL (sym) && !symbol_section_p (sym)
|
|
&& !(howto->partial_inplace
|
|
&& howto->pc_relative
|
|
&& howto->src_mask != addr_mask))
|
{
|
{
|
asection *symsec = S_GET_SEGMENT (sym);
|
asection *symsec = S_GET_SEGMENT (sym);
|
if (!(((symsec->flags & SEC_MERGE) != 0
|
if (!(((symsec->flags & SEC_MERGE) != 0
|
&& addend != 0)
|
&& addend != 0)
|
|| (symsec->flags & SEC_THREAD_LOCAL) != 0))
|
|| (symsec->flags & SEC_THREAD_LOCAL) != 0))
|
Line 728... |
Line 743... |
if (abs_section_sym == NULL)
|
if (abs_section_sym == NULL)
|
abs_section_sym = section_symbol (absolute_section);
|
abs_section_sym = section_symbol (absolute_section);
|
sym = abs_section_sym;
|
sym = abs_section_sym;
|
}
|
}
|
|
|
howto = r->u.a.howto;
|
|
|
|
r->u.b.sec = sec;
|
r->u.b.sec = sec;
|
r->u.b.s = symbol_get_bfdsym (sym);
|
r->u.b.s = symbol_get_bfdsym (sym);
|
r->u.b.r.sym_ptr_ptr = &r->u.b.s;
|
r->u.b.r.sym_ptr_ptr = &r->u.b.s;
|
r->u.b.r.address = offset;
|
r->u.b.r.address = offset;
|
r->u.b.r.addend = addend;
|
r->u.b.r.addend = addend;
|
Line 1752... |
Line 1765... |
struct relax_seg_info rsi;
|
struct relax_seg_info rsi;
|
#ifndef WORKING_DOT_WORD
|
#ifndef WORKING_DOT_WORD
|
fragS *fragP; /* Track along all frags. */
|
fragS *fragP; /* Track along all frags. */
|
#endif
|
#endif
|
|
|
|
#ifdef md_pre_output_hook
|
|
md_pre_output_hook;
|
|
#endif
|
|
|
/* Do we really want to write it? */
|
/* Do we really want to write it? */
|
{
|
{
|
int n_warns, n_errs;
|
int n_warns, n_errs;
|
n_warns = had_warnings ();
|
n_warns = had_warnings ();
|
n_errs = had_errors ();
|
n_errs = had_errors ();
|
Line 1775... |
Line 1792... |
n_errs, n_errs == 1 ? "" : "s",
|
n_errs, n_errs == 1 ? "" : "s",
|
n_warns, n_warns == 1 ? "" : "s");
|
n_warns, n_warns == 1 ? "" : "s");
|
}
|
}
|
}
|
}
|
|
|
|
#ifdef md_pre_relax_hook
|
|
md_pre_relax_hook;
|
|
#endif
|
|
|
/* From now on, we don't care about sub-segments. Build one frag chain
|
/* From now on, we don't care about sub-segments. Build one frag chain
|
for each segment. Linked thru fr_next. */
|
for each segment. Linked thru fr_next. */
|
|
|
/* Remove the sections created by gas for its own purposes. */
|
/* Remove the sections created by gas for its own purposes. */
|
{
|
{
|