.reloc improvement
Alan Modra
amodra@gmail.com
Thu Aug 18 14:08:00 GMT 2011
More information about the Binutils mailing list
Thu Aug 18 14:08:00 GMT 2011
- Previous message (by thread): [committed] mach-o: fix uninitialized fields
- Next message (by thread): .reloc improvement
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
This patch makes some improvements to relocations emitted by the
.reloc directive:
1) A symbol on these relocs is converted to section symbol plus offset
if the symbol satisifes S_IS_LOCAL and some section related
conditions. For example, forward/backward labels like "1f", and
ELF locals like .L123 will be converted. This helps keep the
symbol table tidy.
2) These relocations are merge sorted with the normal fixup relocs,
instead of being emitted after the fixup relocs. A merge sort
ought to be sufficient; If someone generates .reloc with offsets
out of order then I'd say they obviously don't care about reloc
sorting!
3) Time taken to find .reloc frags should be considerably better
than it used to be.
* 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.
Index: gas/write.c
===================================================================
RCS file: /cvs/src/src/gas/write.c,v
retrieving revision 1.144
diff -u -p -r1.144 write.c
--- gas/write.c 4 Aug 2011 20:53:58 -0000 1.144
+++ gas/write.c 18 Aug 2011 13:25:23 -0000
@@ -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 *r
}
}
+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,
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,
_("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,
}
#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);
--
Alan Modra
Australia Development Lab, IBM
- Previous message (by thread): [committed] mach-o: fix uninitialized fields
- Next message (by thread): .reloc improvement
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list