[10/21] Fix the csect handling of XTY_ER symbols
Richard Sandiford
richards@transitive.com
Tue Mar 10 14:25:00 GMT 2009
xcoff_mark goes through the section's relocations and marks both the
target symbol's link entry _and_ its csect:
h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
if (h != NULL
&& (h->flags & XCOFF_MARK) == 0)
{
if (! xcoff_mark_symbol (info, h))
return FALSE;
}
rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
if (rsec != NULL
&& (rsec->flags & SEC_MARK) == 0)
{
if (! xcoff_mark (info, rsec))
return FALSE;
}
This is wrong in some cases, and I'll fix it later in the series.
However, the current code does show up another problem: XTY_ER
(external reference) symbols are given the same csect as the previous
symbol, even though that csect is usually completely unrelated.
For example, suppose we have two functions .f1 and .f2 that both
call .bar. The symbol table might look like:
SD PR .f1
SD PR .f2
ER PR .bar
At the moment, we'll say that .bar's csect is .f2. This means that
if we mark .f1, and thus mark its relocation against .bar, we'll wrongly
think that we need to keep .f2 as well.
I think the most natural fix is to set the "csect" of an undefined
external reference to bfd_und_section_ptr and the "csect" of an
absolute external reference to bfd_abs_section_ptr.
We keep track of the first and last symbol index associated with
each csect. The change above means that we can't always be sure
that every symbol in that range has the same csect, so the mark
routines should check this explicitly. (I think that's good
practice anyway.)
The code that records the last symbol index is rather convoluted.
We are only interested in indices that have a linker hash entry
associated with them, and only one part of xcoff_link_add_symbols
establishes such a link.
The changes in this patch are covered by tests in later patches.
OK to install?
Richard
bfd/
* libcoff-in.h (xcoff_section_tdata): Update commentary.
* libcoff.h: Regenerate.
* xcofflink.c (xcoff_link_add_symbols): Set the csect of XTY_ER
symbols to bfd_und_section_ptr or bfd_abs_section_ptr, rather than
the previous symbol's csect. Treat last_symndx as an inclusive value
and simplify its handling.
(xcoff_mark): Treat last_symndx as an inclusive value. Only mark
symbols with the right csect. Don't mark rsec when processing
relocations against undefined or absolute sections.
(bfd_xcoff_size_dynamic_sections): Don't check the SEC_MARK flag
of bfd_und_section_ptr.
(xcoff_link_input_bfd): Likewise.
Index: bfd/libcoff-in.h
===================================================================
--- bfd/libcoff-in.h 2009-03-10 13:38:53.000000000 +0000
+++ bfd/libcoff-in.h 2009-03-10 13:46:38.000000000 +0000
@@ -215,8 +215,7 @@ struct xcoff_section_tdata
/* The lineno_count field for the enclosing section, because we are
going to clobber it there. */
unsigned int lineno_count;
- /* The first and one past the last symbol indices for symbols used
- by this csect. */
+ /* The first and last symbol indices for symbols used by this csect. */
unsigned long first_symndx;
unsigned long last_symndx;
};
Index: bfd/libcoff.h
===================================================================
--- bfd/libcoff.h 2009-03-10 13:38:53.000000000 +0000
+++ bfd/libcoff.h 2009-03-10 13:46:38.000000000 +0000
@@ -219,8 +219,7 @@ struct xcoff_section_tdata
/* The lineno_count field for the enclosing section, because we are
going to clobber it there. */
unsigned int lineno_count;
- /* The first and one past the last symbol indices for symbols used
- by this csect. */
+ /* The first and last symbol indices for symbols used by this csect. */
unsigned long first_symndx;
unsigned long last_symndx;
};
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c 2009-03-10 13:46:23.000000000 +0000
+++ bfd/xcofflink.c 2009-03-10 13:46:38.000000000 +0000
@@ -1092,17 +1092,9 @@ #define N_BTSHFT n_btshft
Normally csect is a .pr, .rw etc. created in the loop
If C_FILE or first time, handle special
- Advance esym, sym_hash, csect_hash ptr's
- Keep track of the last_symndx for the current file. */
- if (sym.n_sclass == C_FILE && csect != NULL)
- {
- xcoff_section_data (abfd, csect)->last_symndx =
- ((esym
- - (bfd_byte *) obj_coff_external_syms (abfd))
- / symesz);
- csect = NULL;
- }
-
+ Advance esym, sym_hash, csect_hash ptrs. */
+ if (sym.n_sclass == C_FILE)
+ csect = NULL;
if (csect != NULL)
*csect_cache = csect;
else if (first_csect == NULL || sym.n_sclass == C_FILE)
@@ -1253,13 +1245,6 @@ #define N_BTSHFT n_btshft
break;
case XTY_SD:
- /* This is a csect definition. */
- if (csect != NULL)
- {
- xcoff_section_data (abfd, csect)->last_symndx =
- ((esym - (bfd_byte *) obj_coff_external_syms (abfd)) / symesz);
- }
-
csect = NULL;
csect_index = -(unsigned) 1;
@@ -1541,14 +1526,6 @@ #define N_BTSHFT n_btshft
named .tocbss, and rely on the linker script to put that
in the TOC area. */
- if (csect != NULL)
- {
- xcoff_section_data (abfd, csect)->last_symndx =
- ((esym
- - (bfd_byte *) obj_coff_external_syms (abfd))
- / symesz);
- }
-
if (aux.x_csect.x_smclas == XMC_TD)
{
/* The linker script puts the .td section in the data
@@ -1805,7 +1782,15 @@ #define N_BTSHFT n_btshft
}
}
- *csect_cache = csect;
+ if (smtyp == XTY_ER)
+ *csect_cache = section;
+ else
+ {
+ *csect_cache = csect;
+ if (csect != NULL)
+ xcoff_section_data (abfd, csect)->last_symndx
+ = (esym - (bfd_byte *) obj_coff_external_syms (abfd)) / symesz;
+ }
esym += (sym.n_numaux + 1) * symesz;
sym_hash += sym.n_numaux + 1;
@@ -2472,26 +2457,24 @@ xcoff_mark (struct bfd_link_info *info,
&& coff_section_data (sec->owner, sec) != NULL
&& xcoff_section_data (sec->owner, sec) != NULL)
{
- struct xcoff_link_hash_entry **hp, **hpend;
+ struct xcoff_link_hash_entry **syms;
struct internal_reloc *rel, *relend;
+ asection **csects;
+ unsigned long i, first, last;
/* Mark all the symbols in this section. */
- hp = (obj_xcoff_sym_hashes (sec->owner)
- + xcoff_section_data (sec->owner, sec)->first_symndx);
- hpend = (obj_xcoff_sym_hashes (sec->owner)
- + xcoff_section_data (sec->owner, sec)->last_symndx);
- for (; hp < hpend; hp++)
- {
- struct xcoff_link_hash_entry *h;
-
- h = *hp;
- if (h != NULL
- && (h->flags & XCOFF_MARK) == 0)
- {
- if (! xcoff_mark_symbol (info, h))
- return FALSE;
- }
- }
+ syms = obj_xcoff_sym_hashes (sec->owner);
+ csects = xcoff_data (sec->owner)->csects;
+ first = xcoff_section_data (sec->owner, sec)->first_symndx;
+ last = xcoff_section_data (sec->owner, sec)->last_symndx;
+ for (i = first; i <= last; i++)
+ if (csects[i] == sec
+ && syms[i] != NULL
+ && (syms[i]->flags & XCOFF_MARK) == 0)
+ {
+ if (!xcoff_mark_symbol (info, syms[i]))
+ return FALSE;
+ }
/* Look through the section relocs. */
if ((sec->flags & SEC_RELOC) != 0
@@ -2521,6 +2504,8 @@ xcoff_mark (struct bfd_link_info *info,
rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
if (rsec != NULL
+ && !bfd_is_und_section (rsec)
+ && !bfd_is_abs_section (rsec)
&& (rsec->flags & SEC_MARK) == 0)
{
if (! xcoff_mark (info, rsec))
@@ -3358,8 +3343,9 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
if (sym._n._n_n._n_zeroes == 0
&& *csectpp != NULL
&& (! gc
- || ((*csectpp)->flags & SEC_MARK) != 0
- || *csectpp == bfd_abs_section_ptr)
+ || bfd_is_abs_section (*csectpp)
+ || bfd_is_und_section (*csectpp)
+ || ((*csectpp)->flags & SEC_MARK) != 0)
&& bfd_coff_symname_in_debug (sub, &sym))
{
char *name;
@@ -3648,8 +3634,9 @@ #define N_BTSHFT n_btshft
symbol. */
if (! skip
&& xcoff_hash_table (finfo->info)->gc
- && ((*csectpp)->flags & SEC_MARK) == 0
- && *csectpp != bfd_abs_section_ptr)
+ && !bfd_is_abs_section (*csectpp)
+ && !bfd_is_und_section (*csectpp)
+ && ((*csectpp)->flags & SEC_MARK) == 0)
skip = TRUE;
/* An XCOFF linker always skips C_STAT symbols. */
More information about the Binutils
mailing list