This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[12/21] Trim XCOFF symbols earlier in the link process
- From: Richard Sandiford <richards at transitive dot com>
- To: binutils at sourceware dot org
- Date: Tue, 10 Mar 2009 14:33:34 +0000
- Subject: [12/21] Trim XCOFF symbols earlier in the link process
- References: <g4y6vd7a4x.fsf@richards-desktop.transitives.com>
As I mentioned in the last patch, xcoff_link_input_bfd decides on the
fly whether to keep an XCOFF symbol in the static symbol table.
This patch moves the decision to bfd_size_dynamic_sections instead.
The patch is needed by a later bug fix, but it also lifts the
restriction mentioned here:
/* If some symbols are stripped based on the name, work out the
name and decide whether to skip this symbol. We don't handle
this correctly for symbols whose names are in the .debug
section; to get it right we would need a new bfd_strtab_hash
function to return the string given the index. */
if (! skip
&& (finfo->info->strip == strip_some
|| finfo->info->discard == discard_l)
&& (debug_index == NULL || *debug_index == (unsigned long) -1))
That is, xcoff_link_input_bfd cannot easily look up debug names,
and it runs too late to remove stuff from .debug anyway. I'm not
sure this ever matters in practice, but the "fix" falls out in the wash.
The patch also makes the structure of xcoff_link_input_bfd a bit
clearer IMO. At the moment, the function makes two passes over
the symbol table and divides the work up as follows:
Pass 1:
(1) Create dynamic symbol table entries where appropriate.
(The decision is independent of whether we keep entries
in the static symbol table.)
(2) Decide whether to strip the symbol from the static table.
If not:
(3) Assign an index to it.
(4) Adjust the contents of the main symbol entry, and swap it out.
(5) If the symbol is associated with a linker hash table entry,
update the hash entry appropriately.
Pass 2:
(6) Fix up C_BSTAT symbols.
(7) Adjust the contents of auxillary entries, and swap them out.
As the comment above the current second pass says:
/* Fix up the aux entries and the C_BSTAT symbols. This must be
done in a separate pass, because we don't know the correct symbol
indices until we have already decided which symbols we are going
to keep. */
But although we _can_ do (4) in the first pass, I don't see any
reason why we need to. It seems more logical to leave all the
symbol creation to the second pass, and do everything in order.
There's then no need for (6) to fix up the partially-complete
result of (4).
The patch instead does (1), (2), (3) and (5) in the first pass
and (4), (6) and (7) in the second.
The patch uses a new debug_index value of -2 for symbols that we
decide to strip. This seemed better than adding a dedicated array,
with all the overhead that implies.
debug_index is effectively a signed value already, so the patch changes
its type accordingly. No new casts are needed but some can be removed.
The logic in xcoff_keep_symbol_p is taken directly from xcoff_link_input_bfd.
Later patches tweak some aspects of it, but I've deliberately kept such
changes separate. I certainly can't vouch for the accuracy of the rest;
I'm just taking it on faith.
OK to install?
Richard
bfd/
* libcoff-in.h (xcoff_tdata): Change debug_indices to a signed long.
* libcoff.h: Regenerate.
* xcofflink.c (xcoff_keep_symbol_p): New function, using the
"skip" logic from xcoff_link_input_bfd.
(bfd_xcoff_size_dynamic_sections): Explicitly skip dynamic
objects in a dynamic link, rather than checking whether csectpp
is null. Always allocate debug_index for other objects,
and always go through the loop. Update the type of debug_index
after the change above. Read the auxillary csect information
and use xcoff_keep_symbol_p to decide whether a symbol should
be kept. Set its debug_index to -2 if not.
(xcoff_link_input_bfd): Update the type of debug_index after
the change above and always expect it to be nonnull. Use it to
test whether a symbol should be stripped, rather than making the
decision here. Postpone all symbol creation to the second pass.
Index: bfd/libcoff-in.h
===================================================================
--- bfd/libcoff-in.h 2009-03-10 13:46:38.000000000 +0000
+++ bfd/libcoff-in.h 2009-03-10 13:47:43.000000000 +0000
@@ -165,7 +165,7 @@ struct xcoff_tdata
/* Used by the XCOFF backend linker. */
asection **csects;
- unsigned long *debug_indices;
+ long *debug_indices;
unsigned int import_file_id;
};
Index: bfd/libcoff.h
===================================================================
--- bfd/libcoff.h 2009-03-10 13:46:38.000000000 +0000
+++ bfd/libcoff.h 2009-03-10 13:47:43.000000000 +0000
@@ -169,7 +169,7 @@ struct xcoff_tdata
/* Used by the XCOFF backend linker. */
asection **csects;
- unsigned long *debug_indices;
+ long *debug_indices;
unsigned int import_file_id;
};
Index: bfd/xcofflink.c
===================================================================
--- bfd/xcofflink.c 2009-03-10 13:46:58.000000000 +0000
+++ bfd/xcofflink.c 2009-03-10 13:47:43.000000000 +0000
@@ -2981,6 +2981,104 @@ xcoff_build_ldsyms (struct xcoff_link_ha
return TRUE;
}
+
+/* INPUT_BFD includes XCOFF symbol ISYM, which is associated with linker
+ hash table entry H and csect CSECT. AUX contains ISYM's auxillary
+ csect information, if any. NAME is the function's name if the name
+ is stored in the .debug section, otherwise it is null.
+
+ Return 1 if we should include an appropriately-adjusted ISYM
+ in the output file, 0 if we should discard ISYM, or -1 if an
+ error occured. */
+
+static int
+xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
+ struct internal_syment *isym,
+ union internal_auxent *aux,
+ struct xcoff_link_hash_entry *h,
+ asection *csect, const char *name)
+{
+ int smtyp;
+
+ /* If we are skipping this csect, we want to strip the symbol too. */
+ if (csect == NULL)
+ return 0;
+
+ /* Likewise if we garbage-collected the csect. */
+ if (xcoff_hash_table (info)->gc
+ && !bfd_is_abs_section (csect)
+ && !bfd_is_und_section (csect)
+ && (csect->flags & SEC_MARK) == 0)
+ return 0;
+
+ /* An XCOFF linker always removes C_STAT symbols. */
+ if (isym->n_sclass == C_STAT)
+ return 0;
+
+ /* We generate the TOC anchor separately. */
+ if (isym->n_sclass == C_HIDEXT
+ && aux->x_csect.x_smclas == XMC_TC0)
+ return 0;
+
+ /* If we are stripping all symbols, we want to discard this one. */
+ if (info->strip == strip_all)
+ return 0;
+
+ /* We can ignore external references that were resolved by the link. */
+ smtyp = SMTYP_SMTYP (aux->x_csect.x_smtyp);
+ if (isym->n_sclass == C_EXT
+ && smtyp == XTY_ER
+ && h->root.type != bfd_link_hash_undefined)
+ return 0;
+
+ /* We can ignore common symbols if they got defined somewhere else. */
+ if (isym->n_sclass == C_EXT
+ && smtyp == XTY_CM
+ && (h->root.type != bfd_link_hash_common
+ || h->root.u.c.p->section != csect)
+ && (h->root.type != bfd_link_hash_defined
+ || h->root.u.def.section != csect))
+ return 0;
+
+ /* If we're discarding local symbols, check whether ISYM is local. */
+ if (info->discard == discard_all
+ && isym->n_sclass != C_EXT
+ && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD))
+ return 0;
+
+ /* If we're stripping debugging symbols, check whether ISYM is one. */
+ if (info->strip == strip_debugger
+ && isym->n_scnum == N_DEBUG)
+ return 0;
+
+ /* If we are stripping symbols based on name, check how ISYM's
+ name should be handled. */
+ if (info->strip == strip_some
+ || info->discard == discard_l)
+ {
+ char buf[SYMNMLEN + 1];
+
+ if (name == NULL)
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, isym, buf);
+ if (name == NULL)
+ return -1;
+ }
+
+ if (info->strip == strip_some
+ && bfd_hash_lookup (info->keep_hash, name, FALSE, FALSE) == NULL)
+ return 0;
+
+ if (info->discard == discard_l
+ && isym->n_sclass != C_EXT
+ && (isym->n_sclass != C_HIDEXT || smtyp != XTY_SD)
+ && bfd_is_local_label_name (input_bfd, name))
+ return 0;
+ }
+
+ return 1;
+}
+
/* Build the .loader section. This is called by the XCOFF linker
emulation before_allocation routine. We must set the size of the
.loader section before the linker lays out the output file.
@@ -3288,97 +3386,134 @@ bfd_xcoff_size_dynamic_sections (bfd *ou
goto error_return;
}
- /* Now that we've done garbage collection, figure out the contents
- of the .debug section. */
+ /* Now that we've done garbage collection, decide which symbols to keep,
+ and figure out the contents of the .debug section. */
debug_strtab = xcoff_hash_table (info)->debug_strtab;
for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
{
asection *subdeb;
bfd_size_type symcount;
- unsigned long *debug_index;
+ long *debug_index;
asection **csectpp;
+ struct xcoff_link_hash_entry **sym_hash;
bfd_byte *esym, *esymend;
bfd_size_type symesz;
if (sub->xvec != info->output_bfd->xvec)
continue;
- subdeb = bfd_get_section_by_name (sub, ".debug");
- if (subdeb == NULL || subdeb->size == 0)
- continue;
- if (info->strip == strip_all
- || info->strip == strip_debugger
- || info->discard == discard_all)
- {
- subdeb->size = 0;
- continue;
- }
+ if ((sub->flags & DYNAMIC) != 0
+ && !info->static_link)
+ continue;
if (! _bfd_coff_get_external_symbols (sub))
goto error_return;
symcount = obj_raw_syment_count (sub);
- debug_index = bfd_zalloc (sub, symcount * sizeof (unsigned long));
+ debug_index = bfd_zalloc (sub, symcount * sizeof (long));
if (debug_index == NULL)
goto error_return;
xcoff_data (sub)->debug_indices = debug_index;
- /* Grab the contents of the .debug section. We use malloc and
- copy the names into the debug stringtab, rather than
- bfd_alloc, because I expect that, when linking many files
- together, many of the strings will be the same. Storing the
- strings in the hash table should save space in this case. */
- if (! bfd_malloc_and_get_section (sub, subdeb, &debug_contents))
- goto error_return;
+ if (info->strip == strip_all
+ || info->strip == strip_debugger
+ || info->discard == discard_all)
+ /* We're stripping all debugging information, so there's no need
+ to read SUB's .debug section. */
+ subdeb = NULL;
+ else
+ {
+ /* Grab the contents of SUB's .debug section, if any. */
+ subdeb = bfd_get_section_by_name (sub, ".debug");
+ if (subdeb != NULL && subdeb->size > 0)
+ {
+ /* We use malloc and copy the names into the debug
+ stringtab, rather than bfd_alloc, because I expect
+ that, when linking many files together, many of the
+ strings will be the same. Storing the strings in the
+ hash table should save space in this case. */
+ if (!bfd_malloc_and_get_section (sub, subdeb, &debug_contents))
+ goto error_return;
+ }
+ }
csectpp = xcoff_data (sub)->csects;
+ sym_hash = obj_xcoff_sym_hashes (sub);
+ symesz = bfd_coff_symesz (sub);
+ esym = (bfd_byte *) obj_coff_external_syms (sub);
+ esymend = esym + symcount * symesz;
- /* Dynamic object do not have csectpp's. */
- if (NULL != csectpp)
+ while (esym < esymend)
{
- symesz = bfd_coff_symesz (sub);
- esym = (bfd_byte *) obj_coff_external_syms (sub);
- esymend = esym + symcount * symesz;
+ struct internal_syment sym;
+ union internal_auxent aux;
+ const char *name;
+ int keep_p;
- while (esym < esymend)
- {
- struct internal_syment sym;
+ bfd_coff_swap_sym_in (sub, esym, &sym);
- bfd_coff_swap_sym_in (sub, (void *) esym, (void *) &sym);
+ /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
+ information too. */
+ if (sym.n_sclass == C_EXT || sym.n_sclass == C_HIDEXT)
+ {
+ BFD_ASSERT (sym.n_numaux > 0);
+ bfd_coff_swap_aux_in (sub, esym + symesz * sym.n_numaux,
+ sym.n_type, sym.n_sclass,
+ sym.n_numaux - 1, sym.n_numaux, &aux);
+ }
+
+ /* If this symbol's name is stored in the debug section,
+ get a pointer to it. */
+ if (debug_contents != NULL
+ && sym._n._n_n._n_zeroes == 0
+ && bfd_coff_symname_in_debug (sub, &sym))
+ name = (const char *) debug_contents + sym._n._n_n._n_offset;
+ else
+ name = NULL;
- *debug_index = (unsigned long) -1;
+ /* Decide whether to copy this symbol to the output file. */
+ keep_p = xcoff_keep_symbol_p (info, sub, &sym, &aux,
+ *sym_hash, *csectpp, name);
+ if (keep_p < 0)
+ return FALSE;
- if (sym._n._n_n._n_zeroes == 0
- && *csectpp != NULL
- && (! gc
- || bfd_is_abs_section (*csectpp)
- || bfd_is_und_section (*csectpp)
- || ((*csectpp)->flags & SEC_MARK) != 0)
- && bfd_coff_symname_in_debug (sub, &sym))
+ if (!keep_p)
+ /* Use a debug_index of -2 to record that a symbol should
+ be stripped. */
+ *debug_index = -2;
+ else
+ {
+ /* See whether we should store the symbol name in the
+ output .debug section. */
+ if (name != NULL)
{
- char *name;
bfd_size_type indx;
- name = (char *) debug_contents + sym._n._n_n._n_offset;
indx = _bfd_stringtab_add (debug_strtab, name, TRUE, TRUE);
if (indx == (bfd_size_type) -1)
goto error_return;
*debug_index = indx;
}
-
- esym += (sym.n_numaux + 1) * symesz;
- csectpp += sym.n_numaux + 1;
- debug_index += sym.n_numaux + 1;
+ else
+ *debug_index = -1;
}
+
+ esym += (sym.n_numaux + 1) * symesz;
+ csectpp += sym.n_numaux + 1;
+ sym_hash += sym.n_numaux + 1;
+ debug_index += sym.n_numaux + 1;
}
- free (debug_contents);
- debug_contents = NULL;
+ if (debug_contents)
+ {
+ free (debug_contents);
+ debug_contents = NULL;
- /* Clear the size of subdeb, so that it is not included directly
- in the output file. */
- subdeb->size = 0;
+ /* Clear the size of subdeb, so that it is not included directly
+ in the output file. */
+ subdeb->size = 0;
+ }
if (! info->keep_memory)
{
@@ -3455,7 +3590,7 @@ xcoff_link_input_bfd (struct xcoff_final
struct xcoff_link_hash_entry **sym_hash;
struct internal_syment *isymp;
asection **csectpp;
- unsigned long *debug_index;
+ long *debug_index;
long *indexp;
unsigned long output_index;
bfd_byte *outsym;
@@ -3495,6 +3630,9 @@ #define N_BTSHFT n_btshft
if (! _bfd_coff_get_external_symbols (input_bfd))
return FALSE;
+ /* Make one pass over the symbols and assign indices to symbols that
+ we have decided to keep. Also use create .loader symbol information
+ and update information in hash table entries. */
esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
sym_hash = obj_xcoff_sym_hashes (input_bfd);
@@ -3503,16 +3641,10 @@ #define N_BTSHFT n_btshft
isymp = finfo->internal_syms;
indexp = finfo->sym_indices;
output_index = syment_base;
- outsym = finfo->outsyms;
- incls = 0;
- oline = NULL;
-
while (esym < esym_end)
{
- struct internal_syment isym;
union internal_auxent aux;
int smtyp = 0;
- bfd_boolean skip;
int add;
bfd_coff_swap_sym_in (input_bfd, (void *) esym, (void *) isymp);
@@ -3531,17 +3663,11 @@ #define N_BTSHFT n_btshft
smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
}
- /* Make a copy of *isymp so that the relocate_section function
- always sees the original values. This is more reliable than
- always recomputing the symbol value even if we are stripping
- the symbol. */
- isym = *isymp;
-
/* If this symbol is in the .loader section, swap out the
.loader symbol information. If this is an external symbol
reference to a defined symbol, though, then wait until we get
to the definition. */
- if (isym.n_sclass == C_EXT
+ if (isymp->n_sclass == C_EXT
&& *sym_hash != NULL
&& (*sym_hash)->ldsym != NULL
&& (smtyp != XTY_ER
@@ -3552,18 +3678,18 @@ #define N_BTSHFT n_btshft
h = *sym_hash;
ldsym = h->ldsym;
- if (isym.n_scnum > 0)
+ if (isymp->n_scnum > 0)
{
ldsym->l_scnum = (*csectpp)->output_section->target_index;
- ldsym->l_value = (isym.n_value
+ ldsym->l_value = (isymp->n_value
+ (*csectpp)->output_section->vma
+ (*csectpp)->output_offset
- (*csectpp)->vma);
}
else
{
- ldsym->l_scnum = isym.n_scnum;
- ldsym->l_value = isym.n_value;
+ ldsym->l_scnum = isymp->n_scnum;
+ ldsym->l_value = isymp->n_value;
}
ldsym->l_smtype = smtyp;
@@ -3628,114 +3754,80 @@ #define N_BTSHFT n_btshft
}
}
- *indexp = -1;
-
- skip = FALSE;
- add = 1 + isym.n_numaux;
+ add = 1 + isymp->n_numaux;
- /* If we are skipping this csect, we want to skip this symbol. */
- if (*csectpp == NULL)
- skip = TRUE;
-
- /* If we garbage collected this csect, we want to skip this
- symbol. */
- if (! skip
- && xcoff_hash_table (finfo->info)->gc
- && !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. */
- if (! skip
- && isymp->n_sclass == C_STAT)
- skip = TRUE;
-
- /* We generate the TOC anchor separately. */
- if (! skip
- && isymp->n_sclass == C_HIDEXT
- && aux.x_csect.x_smclas == XMC_TC0)
- skip = TRUE;
-
- /* If we are stripping all symbols, we want to skip this one. */
- if (! skip
- && finfo->info->strip == strip_all)
- skip = TRUE;
-
- /* We can skip resolved external references. */
- if (! skip
- && isym.n_sclass == C_EXT
- && smtyp == XTY_ER
- && (*sym_hash)->root.type != bfd_link_hash_undefined)
- skip = TRUE;
-
- /* We can skip common symbols if they got defined somewhere
- else. */
- if (! skip
- && isym.n_sclass == C_EXT
- && smtyp == XTY_CM
- && ((*sym_hash)->root.type != bfd_link_hash_common
- || (*sym_hash)->root.u.c.p->section != *csectpp)
- && ((*sym_hash)->root.type != bfd_link_hash_defined
- || (*sym_hash)->root.u.def.section != *csectpp))
- skip = TRUE;
-
- /* Skip local symbols if we are discarding them. */
- if (! skip
- && finfo->info->discard == discard_all
- && isym.n_sclass != C_EXT
- && (isym.n_sclass != C_HIDEXT
- || smtyp != XTY_SD))
- skip = TRUE;
-
- /* If we stripping debugging symbols, and this is a debugging
- symbol, then skip it. */
- if (! skip
- && finfo->info->strip == strip_debugger
- && isym.n_scnum == N_DEBUG)
- skip = TRUE;
-
- /* If some symbols are stripped based on the name, work out the
- name and decide whether to skip this symbol. We don't handle
- this correctly for symbols whose names are in the .debug
- section; to get it right we would need a new bfd_strtab_hash
- function to return the string given the index. */
- if (! skip
- && (finfo->info->strip == strip_some
- || finfo->info->discard == discard_l)
- && (debug_index == NULL || *debug_index == (unsigned long) -1))
+ if (*debug_index == -2)
+ /* We've decided to strip this symbol. */
+ *indexp = -1;
+ else
{
- const char *name;
- char buf[SYMNMLEN + 1];
+ /* Assign the next unused index to this symbol. */
+ *indexp = output_index;
- name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+ if (isymp->n_sclass == C_EXT)
+ {
+ BFD_ASSERT (*sym_hash != NULL);
+ (*sym_hash)->indx = output_index;
+ }
- if (name == NULL)
- return FALSE;
+ /* If this is a symbol in the TOC which we may have merged
+ (class XMC_TC), remember the symbol index of the TOC
+ symbol. */
+ if (isymp->n_sclass == C_HIDEXT
+ && aux.x_csect.x_smclas == XMC_TC
+ && *sym_hash != NULL)
+ {
+ BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
+ BFD_ASSERT ((*sym_hash)->toc_section != NULL);
+ (*sym_hash)->u.toc_indx = output_index;
+ }
- if ((finfo->info->strip == strip_some
- && (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE,
- FALSE) == NULL))
- || (finfo->info->discard == discard_l
- && (isym.n_sclass != C_EXT
- && (isym.n_sclass != C_HIDEXT
- || smtyp != XTY_SD))
- && bfd_is_local_label_name (input_bfd, name)))
- skip = TRUE;
+ output_index += add;
}
- /* We now know whether we are to skip this symbol or not. */
- if (! skip)
+ esym += add * isymesz;
+ isymp += add;
+ csectpp += add;
+ sym_hash += add;
+ debug_index += add;
+ ++indexp;
+ for (--add; add > 0; --add)
+ *indexp++ = -1;
+ }
+
+ /* Now write out the symbols that we decided to keep. */
+
+ esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
+ isymp = finfo->internal_syms;
+ indexp = finfo->sym_indices;
+ csectpp = xcoff_data (input_bfd)->csects;
+ debug_index = xcoff_data (input_bfd)->debug_indices;
+ outsym = finfo->outsyms;
+ incls = 0;
+ oline = NULL;
+ while (esym < esym_end)
+ {
+ int add;
+
+ add = 1 + isymp->n_numaux;
+
+ if (*indexp < 0)
+ esym += add * isymesz;
+ else
{
- /* Adjust the symbol in order to output it. */
+ struct internal_syment isym;
+ int i;
+ /* Adjust the symbol in order to output it. */
+ isym = *isymp;
if (isym._n._n_n._n_zeroes == 0
&& isym._n._n_n._n_offset != 0)
{
/* This symbol has a long name. Enter it in the string
table we are building. If *debug_index != -1, the
name has already been entered in the .debug section. */
- if (debug_index != NULL && *debug_index != (unsigned long) -1)
+ if (*debug_index >= 0)
isym._n._n_n._n_offset = *debug_index;
else
{
@@ -3753,17 +3845,6 @@ #define N_BTSHFT n_btshft
}
}
- if (isym.n_sclass != C_BSTAT
- && isym.n_sclass != C_ESTAT
- && isym.n_sclass != C_DECL
- && isym.n_scnum > 0)
- {
- isym.n_scnum = (*csectpp)->output_section->target_index;
- isym.n_value += ((*csectpp)->output_section->vma
- + (*csectpp)->output_offset
- - (*csectpp)->vma);
- }
-
/* The value of a C_FILE symbol is the symbol index of the
next C_FILE symbol. The value of the last C_FILE symbol
is -1. We try to get this right, below, just before we
@@ -3772,10 +3853,10 @@ #define N_BTSHFT n_btshft
if (isym.n_sclass == C_FILE)
{
if (finfo->last_file_index != -1
- && finfo->last_file.n_value != (bfd_vma) output_index)
+ && finfo->last_file.n_value != (bfd_vma) *indexp)
{
/* We must correct the value of the last C_FILE entry. */
- finfo->last_file.n_value = output_index;
+ finfo->last_file.n_value = *indexp;
if ((bfd_size_type) finfo->last_file_index >= syment_base)
{
/* The last C_FILE symbol is in this input file. */
@@ -3806,7 +3887,7 @@ #define N_BTSHFT n_btshft
}
}
- finfo->last_file_index = output_index;
+ finfo->last_file_index = *indexp;
finfo->last_file = isym;
}
@@ -3819,84 +3900,12 @@ #define N_BTSHFT n_btshft
isym.n_value = finfo->line_filepos;
++incls;
}
-
- /* Output the symbol. */
-
- bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
-
- *indexp = output_index;
-
- if (isym.n_sclass == C_EXT)
- {
- long indx;
- struct xcoff_link_hash_entry *h;
-
- indx = ((esym - (bfd_byte *) obj_coff_external_syms (input_bfd))
- / isymesz);
- h = obj_xcoff_sym_hashes (input_bfd)[indx];
- BFD_ASSERT (h != NULL);
- h->indx = output_index;
- }
-
- /* If this is a symbol in the TOC which we may have merged
- (class XMC_TC), remember the symbol index of the TOC
- symbol. */
- if (isym.n_sclass == C_HIDEXT
- && aux.x_csect.x_smclas == XMC_TC
- && *sym_hash != NULL)
+ /* The value of a C_BSTAT symbol is the symbol table
+ index of the containing csect. */
+ else if (isym.n_sclass == C_BSTAT)
{
- BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
- BFD_ASSERT ((*sym_hash)->toc_section != NULL);
- (*sym_hash)->u.toc_indx = output_index;
- }
-
- output_index += add;
- outsym += add * osymesz;
- }
-
- esym += add * isymesz;
- isymp += add;
- csectpp += add;
- sym_hash += add;
- if (debug_index != NULL)
- debug_index += add;
- ++indexp;
- for (--add; add > 0; --add)
- *indexp++ = -1;
- }
-
- /* Fix up the aux entries and the C_BSTAT symbols. This must be
- done in a separate pass, because we don't know the correct symbol
- indices until we have already decided which symbols we are going
- to keep. */
-
- esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
- esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
- isymp = finfo->internal_syms;
- indexp = finfo->sym_indices;
- csectpp = xcoff_data (input_bfd)->csects;
- outsym = finfo->outsyms;
- while (esym < esym_end)
- {
- int add;
-
- add = 1 + isymp->n_numaux;
-
- if (*indexp < 0)
- esym += add * isymesz;
- else
- {
- int i;
-
- if (isymp->n_sclass == C_BSTAT)
- {
- struct internal_syment isym;
-
bfd_vma indx;
- /* The value of a C_BSTAT symbol is the symbol table
- index of the containing csect. */
- bfd_coff_swap_sym_in (output_bfd, (void *) outsym, (void *) &isym);
indx = isym.n_value;
if (indx < obj_raw_syment_count (input_bfd))
{
@@ -3907,10 +3916,20 @@ #define N_BTSHFT n_btshft
isym.n_value = 0;
else
isym.n_value = symindx;
- bfd_coff_swap_sym_out (output_bfd, (void *) &isym,
- (void *) outsym);
}
}
+ else if (isym.n_sclass != C_ESTAT
+ && isym.n_sclass != C_DECL
+ && isym.n_scnum > 0)
+ {
+ isym.n_scnum = (*csectpp)->output_section->target_index;
+ isym.n_value += ((*csectpp)->output_section->vma
+ + (*csectpp)->output_offset
+ - (*csectpp)->vma);
+ }
+
+ /* Output the symbol. */
+ bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);
esym += isymesz;
outsym += osymesz;
@@ -4185,6 +4204,7 @@ #define N_BTSHFT n_btshft
indexp += add;
isymp += add;
csectpp += add;
+ debug_index += add;
}
/* If we swapped out a C_FILE symbol, guess that the next C_FILE