* 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.
This commit is contained in:
Alan Modra 2011-08-18 14:10:35 +00:00
parent 9d4b600942
commit 7230378dfd
2 changed files with 91 additions and 40 deletions

View File

@ -1,3 +1,11 @@
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

View File

@ -1,7 +1,7 @@
/* 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);
for (j = 0; reloc[j]; j++)
relocs[i++] = reloc[j];
}
reloc = tc_gen_reloc (sec, fixp);
#endif
for ( ; j != 0; --j)
install_reloc (sec, relocs[i - j], fixp->fx_frag,
fixp->fx_file, fixp->fx_line);
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
}
}
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);