aboutsummaryrefslogtreecommitdiff
path: root/bfd/cofflink.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>1997-05-21 16:59:02 +0000
committerNick Clifton <nickc@redhat.com>1997-05-21 16:59:02 +0000
commite18683b73b325dcf6fe2c929d666542b30fec7e7 (patch)
treed2832cc175796a1a6f035c288ff2172a8043ae5b /bfd/cofflink.c
parent50a2a691824992f474b19bf40bbff016b2f67150 (diff)
downloadgdb-e18683b73b325dcf6fe2c929d666542b30fec7e7.zip
gdb-e18683b73b325dcf6fe2c929d666542b30fec7e7.tar.gz
gdb-e18683b73b325dcf6fe2c929d666542b30fec7e7.tar.bz2
Added code to cope with 'ld -X -r' stripiung symbols that will later be
used in relocations.
Diffstat (limited to 'bfd/cofflink.c')
-rw-r--r--bfd/cofflink.c135
1 files changed, 116 insertions, 19 deletions
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index cd76985..7d1d505 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -34,6 +34,10 @@ static boolean coff_link_check_archive_element
static boolean coff_link_check_ar_symbols
PARAMS ((bfd *, struct bfd_link_info *, boolean *));
static boolean coff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
+static char *dores_com PARAMS ((char *, bfd *, int));
+static char *get_name PARAMS ((char *, char **));
+static int process_embedded_commands
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *));
/* Create an entry in a COFF linker hash table. */
@@ -378,6 +382,13 @@ coff_link_add_symbols (abfd, info)
(struct bfd_link_hash_entry **) sym_hash)))
goto error_return;
+ if (section == bfd_com_section_ptr
+ && (*sym_hash)->root.type == bfd_link_hash_common
+ && ((*sym_hash)->root.u.c.p->alignment_power
+ > bfd_coff_default_section_alignment_power (abfd)))
+ (*sym_hash)->root.u.c.p->alignment_power
+ = bfd_coff_default_section_alignment_power (abfd);
+
if (info->hash->creator->flavour == bfd_get_flavour (abfd))
{
if (((*sym_hash)->class == C_NULL
@@ -533,7 +544,10 @@ _bfd_coff_final_link (abfd, info)
/* Compute the file positions for all the sections. */
if (! abfd->output_has_begun)
- bfd_coff_compute_section_file_positions (abfd);
+ {
+ if (! bfd_coff_compute_section_file_positions (abfd))
+ goto error_return;
+ }
/* Count the line numbers and relocation entries required for the
output file. Set the file positions for the relocs. */
@@ -1103,6 +1117,60 @@ process_embedded_commands (output_bfd, info, abfd)
return 1;
}
+/* Place a marker against all symbols which are used by relocations.
+ This marker can be picked up by the 'do we skip this symbol ?'
+ loop in _bfd_coff_link_input_bfd() and used to prevent skipping
+ that symbol.
+ */
+
+static void
+mark_relocs (finfo, input_bfd)
+ struct coff_final_link_info * finfo;
+ bfd * input_bfd;
+{
+ asection * a;
+
+ if ((bfd_get_file_flags (input_bfd) & HAS_SYMS) == 0)
+ return;
+
+ for (a = input_bfd->sections; a != (asection *) NULL; a = a->next)
+ {
+ struct internal_reloc * internal_relocs;
+ struct internal_reloc * irel;
+ struct internal_reloc * irelend;
+
+
+ if ((a->flags & SEC_RELOC) == 0 || a->reloc_count < 1)
+ continue;
+
+ /* Read in the relocs. */
+ internal_relocs = _bfd_coff_read_internal_relocs
+ (input_bfd, a, false,
+ finfo->external_relocs,
+ finfo->info->relocateable,
+ (finfo->info->relocateable
+ ? (finfo->section_info[ a->output_section->target_index ].relocs + a->output_section->reloc_count)
+ : finfo->internal_relocs)
+ );
+
+ if (internal_relocs == NULL)
+ continue;
+
+ irel = internal_relocs;
+ irelend = irel + a->reloc_count;
+
+ /* Place a mark in the sym_indices array (whose entries have
+ been initialised to 0) for all of the symbols that are used
+ in the relocation table. This will then be picked up in the
+ skip/don't pass */
+
+ for (; irel < irelend; irel++)
+ {
+ finfo->sym_indices[ irel->r_symndx ] = -1;
+ }
+ }
+}
+
/* Link an input file into the linker output file. This function
handles all the sections and relocations of the input file at once. */
@@ -1176,11 +1244,25 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
return false;
}
+ /* If we are going to perform relocations and also strip/discard some symbols
+ then we must make sure that we do not strip/discard those symbols that are
+ going to be involved in the relocations */
+ if (( finfo->info->strip != strip_none
+ || finfo->info->discard != discard_none)
+ && finfo->info->relocateable)
+ {
+ /* mark the symbol array as 'not-used' */
+ memset (indexp, 0, obj_raw_syment_count (input_bfd) * sizeof * indexp);
+
+ mark_relocs (finfo, input_bfd);
+ }
+
while (esym < esym_end)
{
struct internal_syment isym;
boolean skip;
boolean global;
+ boolean dont_skip_symbol;
int add;
bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
@@ -1201,6 +1283,14 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
*secpp = bfd_com_section_ptr;
}
+ /* Extract the flag indicating if this symbol is used by a relocation */
+ if (( finfo->info->strip != strip_none
+ || finfo->info->discard != discard_none)
+ && finfo->info->relocateable)
+ dont_skip_symbol = *indexp;
+ else
+ dont_skip_symbol = false;
+
*indexp = -1;
skip = false;
@@ -1208,7 +1298,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
add = 1 + isym.n_numaux;
/* If we are stripping all symbols, we want to skip this one. */
- if (finfo->info->strip == strip_all)
+ if (finfo->info->strip == strip_all && ! dont_skip_symbol)
skip = true;
if (! skip)
@@ -1228,7 +1318,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
{
/* This is a local symbol. Skip it if we are discarding
local symbols. */
- if (finfo->info->discard == discard_all)
+ if (finfo->info->discard == discard_all && ! dont_skip_symbol)
skip = true;
}
}
@@ -1237,6 +1327,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
symbol, then skip it. */
if (! skip
&& finfo->info->strip == strip_debugger
+ && ! dont_skip_symbol
&& isym.n_scnum == N_DEBUG)
skip = true;
@@ -1253,13 +1344,13 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
if (name == NULL)
return false;
- if ((finfo->info->strip == strip_some
- && (bfd_hash_lookup (finfo->info->keep_hash, name, false,
+ if (! dont_skip_symbol
+ && ((finfo->info->strip == strip_some
+ && (bfd_hash_lookup (finfo->info->keep_hash, name, false,
false) == NULL))
- || (! global
- && finfo->info->discard == discard_l
- && strncmp (name, finfo->info->lprefix,
- finfo->info->lprefix_len) == 0))
+ || (! global
+ && finfo->info->discard == discard_l
+ && bfd_is_local_label_name (input_bfd, name))))
skip = true;
}
@@ -2053,9 +2144,10 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
char buf[SYMNMLEN + 1];
/* This reloc is against a symbol we are
- stripping. It would be possible to
- handle this case, but I don't think it's
- worth it. */
+ stripping. This should have been handled
+ by the 'dont_skip_symbol' code in the while
+ loop at the top of this function. */
+
is = finfo->internal_syms + irel->r_symndx;
name = (_bfd_coff_internal_syment_name
@@ -2087,8 +2179,9 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
}
else
{
- if (! _bfd_write_section_stabs (output_bfd, o, &secdata->stab_info,
- contents))
+ if (! (_bfd_write_section_stabs
+ (output_bfd, &coff_hash_table (finfo->info)->stab_info,
+ o, &secdata->stab_info, contents)))
return false;
}
}
@@ -2425,11 +2518,15 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
/* If we are doing a relocateable link, then we can just ignore
a PC relative reloc that is pcrel_offset. It will already
- have the correct value. */
- if (info->relocateable
- && howto->pc_relative
- && howto->pcrel_offset)
- continue;
+ have the correct value. If this is not a relocateable link,
+ then we should ignore the symbol value. */
+ if (howto->pc_relative && howto->pcrel_offset)
+ {
+ if (info->relocateable)
+ continue;
+ if (sym != NULL && sym->n_scnum != 0)
+ addend += sym->n_value;
+ }
val = 0;