Commit 7230378d authored by Alan Modra's avatar Alan Modra

* write.c (resolve_reloc_expr_symbols): Convert local symbols

	on relocs to section+offset.
	(get_frag_for_reloc): New function.
	(write_relocs): Merge sort fixup relocs with those from .reloc
	directives.
parent 9d4b6009
2011-08-18 Alan Modra <amodra@gmail.com>
* write.c (resolve_reloc_expr_symbols): Convert local symbols
on relocs to section+offset.
(get_frag_for_reloc): New function.
(write_relocs): Merge sort fixup relocs with those from .reloc
directives.
2011-08-10 Maciej W. Rozycki <macro@codesourcery.com>
* config/tc-mips.c (can_swap_branch_p): Update the comment on
......
/* write.c - emit .o file
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010 Free Software Foundation, Inc.
2010, 2011 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
......@@ -708,7 +708,20 @@ resolve_reloc_expr_symbols (void)
sec = NULL;
}
else if (sym != NULL)
symbol_mark_used_in_reloc (sym);
{
if (S_IS_LOCAL (sym) && !symbol_section_p (sym))
{
asection *symsec = S_GET_SEGMENT (sym);
if (!(((symsec->flags & SEC_MERGE) != 0
&& addend != 0)
|| (symsec->flags & SEC_THREAD_LOCAL) != 0))
{
addend += S_GET_VALUE (sym);
sym = section_symbol (symsec);
}
}
symbol_mark_used_in_reloc (sym);
}
}
if (sym == NULL)
{
......@@ -1146,15 +1159,37 @@ install_reloc (asection *sec, arelent *reloc, fragS *fragp,
}
}
static fragS *
get_frag_for_reloc (fragS *last_frag,
const segment_info_type *seginfo,
const struct reloc_list *r)
{
fragS *f;
for (f = last_frag; f != NULL; f = f->fr_next)
if (f->fr_address <= r->u.b.r.address
&& r->u.b.r.address < f->fr_address + f->fr_fix)
return f;
for (f = seginfo->frchainP->frch_root; f != NULL; f = f->fr_next)
if (f->fr_address <= r->u.b.r.address
&& r->u.b.r.address < f->fr_address + f->fr_fix)
return f;
as_bad_where (r->file, r->line,
_("reloc not within (fixed part of) section"));
return NULL;
}
static void
write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
{
segment_info_type *seginfo = seg_info (sec);
unsigned int i;
unsigned int n;
struct reloc_list *my_reloc_list, **rp, *r;
arelent **relocs;
fixS *fixp;
fragS *last_frag;
/* If seginfo is NULL, we did not create this section; don't do
anything with it. */
......@@ -1188,12 +1223,19 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
relocs = (arelent **) xcalloc (n, sizeof (arelent *));
i = 0;
n = 0;
r = my_reloc_list;
last_frag = NULL;
for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
{
int j;
int fx_size, slack;
offsetT loc;
arelent **reloc;
#ifndef RELOC_EXPANSION_POSSIBLE
arelent *rel;
reloc = &rel;
#endif
if (fixp->fx_done)
continue;
......@@ -1208,28 +1250,46 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
_("internal error: fixup not contained within frag"));
#ifndef RELOC_EXPANSION_POSSIBLE
{
arelent *reloc = tc_gen_reloc (sec, fixp);
if (!reloc)
continue;
relocs[i++] = reloc;
j = 1;
}
*reloc = tc_gen_reloc (sec, fixp);
#else
{
arelent **reloc = tc_gen_reloc (sec, fixp);
reloc = tc_gen_reloc (sec, fixp);
#endif
for (j = 0; reloc[j]; j++)
relocs[i++] = reloc[j];
}
while (*reloc)
{
while (r != NULL && r->u.b.r.address < (*reloc)->address)
{
fragS *f = get_frag_for_reloc (last_frag, seginfo, r);
if (f != NULL)
{
last_frag = f;
relocs[n++] = &r->u.b.r;
install_reloc (sec, &r->u.b.r, f, r->file, r->line);
}
r = r->next;
}
relocs[n++] = *reloc;
install_reloc (sec, *reloc, fixp->fx_frag,
fixp->fx_file, fixp->fx_line);
#ifndef RELOC_EXPANSION_POSSIBLE
break;
#else
reloc++;
#endif
}
}
for ( ; j != 0; --j)
install_reloc (sec, relocs[i - j], fixp->fx_frag,
fixp->fx_file, fixp->fx_line);
while (r != NULL)
{
fragS *f = get_frag_for_reloc (last_frag, seginfo, r);
if (f != NULL)
{
last_frag = f;
relocs[n++] = &r->u.b.r;
install_reloc (sec, &r->u.b.r, f, r->file, r->line);
}
r = r->next;
}
n = i;
#ifdef DEBUG4
{
......@@ -1249,23 +1309,6 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
}
#endif
for (r = my_reloc_list; r != NULL; r = r->next)
{
fragS *f;
for (f = seginfo->frchainP->frch_root; f; f = f->fr_next)
if (f->fr_address <= r->u.b.r.address
&& r->u.b.r.address < f->fr_address + f->fr_fix)
break;
if (f == NULL)
as_bad_where (r->file, r->line,
_("reloc not within (fixed part of) section"));
else
{
relocs[n++] = &r->u.b.r;
install_reloc (sec, &r->u.b.r, f, r->file, r->line);
}
}
if (n)
{
flagword flags = bfd_get_section_flags (abfd, sec);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment