Distinguish a weak defined symbol from a regular defined symbol.

* linker.c (enum link_action): Add DEFW.
	(link_action): Add bfd_link_hash_defweak column.
	(_bfd_generic_link_add_one_symbol): Add DEFW case.  Handle
	bfd_link_hash_defweak in a few other cases.
	* Many files (bfd_link_hash_undefweak): Renamed from
	bfd_link_hash_weak.
	* aoutx.h (aout_link_write_symbols): Handle bfd_link_hash_defweak.
	(aout_link_write_other_symbol): Likewise.
	(aout_link_input_section_std): Likewise.
	(aout_link_input_section_ext): Likewise.
	* bout.c (get_value): Likewise.
	* coff-a29k.c (coff_a29k_relocate_section): Likewise.
	* coff-alpha.c (alpha_convert_external_reloc): Likewise.
	(alpha_relocate_section): Likewise.
	* coff-mips.c (mips_relocate_section): Likewise.
	(mips_relax_section): Likewise.
	(bfd_mips_ecoff_create_embedded_relocs): Likewise.
	* cofflink.c (coff_write_global_sym): Likewise.
	(_bfd_coff_generic_relocate_section): Likewise.
	* ecoff.c (ecoff_link_add_externals): Likewise.
	(ecoff_link_write_external): LIkewise.
	* elf32-hppa.c (elf32_hppa_relocate_section): Likewise.
	(elf32_hppa_size_stubs): Likewise.
	* elf32-i386.c (elf_i386_adjust_dynamic_symbol): Likewise.
	(elf_i386_relocate_section): Likewise.
	(elf_i386_finish_dynamic_symbol): Likewise.
	* elf32-mips.c (mips_elf_output_extsym): Likewise.
	(mips_elf_relocate_section): Likewise.
	* elf32-sparc.c (elf32_sparc_adjust_dynamic_symbol): Likewise.
	(elf32_sparc_relocate_section): Likewise.
	* elfcode.h (elf_link_add_object_symbols): Likewise.
	(elf_adjust_dynamic_symbol): Likewise.
	(elf_bfd_final_link): Likewise.
	(elf_link_output_extsym): Likewise.
	* i386linux.c (linux_add_one_symbol): Likewise.
	(linux_tally_symbols): Likewise.
	(linux_finish_dynamic_link): Likewise.
	* linker.c (_bfd_generic_link_output_symbols): Likewise.
	(set_symbol_from_hash): Likewise.
	* reloc16.c (bfd_coff_reloc16_get_value): Likewise.
	(bfd_perform_slip): Likewise.
	* sunos.c (sunos_add_one_symbol): Likewise.
	(sunos_scan_std_relocs): Likewise.
	(sunos_scan_ext_relocs): Likewise.
	(sunos_scan_dynamic_symbol): Likewise.
	(sunos_write_dynamic_symbol): Likewise.
This commit is contained in:
Ian Lance Taylor
1995-02-06 20:01:08 +00:00
parent ebc4ca90f9
commit 6c97aedf26
9 changed files with 423 additions and 177 deletions

View File

@ -163,7 +163,10 @@ static file_ptr assign_file_position_for_section
static boolean assign_file_positions_except_relocs PARAMS ((bfd *, boolean));
static int elf_sort_hdrs PARAMS ((const PTR, const PTR));
static void assign_file_positions_for_relocs PARAMS ((bfd *));
static bfd_size_type get_program_header_size PARAMS ((bfd *));
static bfd_size_type get_program_header_size PARAMS ((bfd *,
Elf_Internal_Shdr **,
unsigned int,
bfd_vma));
static file_ptr map_program_segments
PARAMS ((bfd *, file_ptr, Elf_Internal_Shdr *, Elf_Internal_Shdr **,
bfd_size_type));
@ -1719,20 +1722,121 @@ assign_file_position_for_section (i_shdrp, offset, align)
return offset;
}
/* Get the size of the program header. This is called by the linker
before any of the section VMA's are set, so it can't calculate the
correct value for a strange memory layout. */
/* Get the size of the program header.
SORTED_HDRS, if non-NULL, is an array of COUNT pointers to headers sorted
by VMA. Non-allocated sections (!SHF_ALLOC) must appear last. All
section VMAs and sizes are known so we can compute the correct value.
(??? This may not be perfectly true. What cases do we miss?)
If SORTED_HDRS is NULL we assume there are two segments: text and data
(exclusive of .interp and .dynamic).
If this is called by the linker before any of the section VMA's are set, it
can't calculate the correct value for a strange memory layout. This only
happens when SIZEOF_HEADERS is used in a linker script. In this case,
SORTED_HDRS is NULL and we assume the normal scenario of one text and one
data segment (exclusive of .interp and .dynamic).
??? User written scripts must either not use SIZEOF_HEADERS, or assume there
will be two segments. */
static bfd_size_type
get_program_header_size (abfd)
get_program_header_size (abfd, sorted_hdrs, count, maxpagesize)
bfd *abfd;
Elf_Internal_Shdr **sorted_hdrs;
unsigned int count;
bfd_vma maxpagesize;
{
size_t segs;
asection *s;
/* Assume we will need exactly two PT_LOAD segments: one for text
and one for data. */
segs = 2;
/* We can't return a different result each time we're called. */
if (elf_tdata (abfd)->program_header_size != 0)
return elf_tdata (abfd)->program_header_size;
if (sorted_hdrs != NULL)
{
unsigned int i;
unsigned int last_type;
Elf_Internal_Shdr **hdrpp;
/* What we think the current segment's offset is. */
bfd_vma p_offset;
/* What we think the current segment's address is. */
bfd_vma p_vaddr;
/* How big we think the current segment is. */
bfd_vma p_memsz;
/* What we think the current file offset is. */
bfd_vma file_offset;
bfd_vma next_offset;
/* Scan the headers and compute the number of segments required. This
code is intentionally similar to the code in map_program_segments.
The `sh_offset' field isn't valid at this point, so we keep our own
running total in `file_offset'.
This works because section VMAs are already known. */
segs = 1;
/* Make sure the first section goes in the first segment. */
file_offset = p_offset = sorted_hdrs[0]->sh_addr % maxpagesize;
p_vaddr = sorted_hdrs[0]->sh_addr;
p_memsz = 0;
last_type = SHT_PROGBITS;
for (i = 0, hdrpp = sorted_hdrs; i < count; i++, hdrpp++)
{
Elf_Internal_Shdr *hdr;
hdr = *hdrpp;
/* Ignore any section which will not be part of the process
image. */
if ((hdr->sh_flags & SHF_ALLOC) == 0)
continue;
/* Keep track of where this and the next sections go.
The section VMA must equal the file position modulo
the page size. */
file_offset += (hdr->sh_addr - file_offset) % maxpagesize;
next_offset = file_offset;
if (hdr->sh_type != SHT_NOBITS)
next_offset = file_offset + hdr->sh_size;
/* If this section fits in the segment we are constructing, add
it in. */
if ((file_offset - (p_offset + p_memsz)
== hdr->sh_addr - (p_vaddr + p_memsz))
&& (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS))
{
bfd_size_type adjust;
adjust = hdr->sh_addr - (p_vaddr + p_memsz);
p_memsz += hdr->sh_size + adjust;
file_offset = next_offset;
last_type = hdr->sh_type;
continue;
}
/* The section won't fit, start a new segment. */
++segs;
/* Initialize the segment. */
p_vaddr = hdr->sh_addr;
p_memsz = hdr->sh_size;
p_offset = file_offset;
file_offset = next_offset;
last_type = hdr->sh_type;
}
}
else
{
/* Assume we will need exactly two PT_LOAD segments: one for text
and one for data. */
segs = 2;
}
s = bfd_get_section_by_name (abfd, ".interp");
if (s != NULL && (s->flags & SEC_LOAD) != 0)
@ -1750,7 +1854,8 @@ get_program_header_size (abfd)
++segs;
}
return segs * sizeof (Elf_External_Phdr);
elf_tdata (abfd)->program_header_size = segs * sizeof (Elf_External_Phdr);
return elf_tdata (abfd)->program_header_size;
}
/* Create the program header. OFF is the file offset where the
@ -1877,14 +1982,15 @@ map_program_segments (abfd, off, first, sorted_hdrs, phdr_size)
continue;
}
/* If we have a segment, move to the next one. */
/* The section won't fit, start a new segment. If we're already in one,
move to the next one. */
if (phdr->p_type != PT_NULL)
{
++phdr;
++phdr_count;
}
/* Start a new segment. */
/* Initialize the segment. */
phdr->p_type = PT_LOAD;
phdr->p_offset = hdr->sh_offset;
phdr->p_vaddr = hdr->sh_addr;
@ -2050,16 +2156,7 @@ assign_file_positions_except_relocs (abfd, dosyms)
Elf_Internal_Shdr *first;
file_ptr phdr_map;
/* We are creating an executable. We must create a program
header. We can't actually create the program header until we
have set the file positions for the sections, but we can
figure out how big it is going to be. */
off = align_file_position (off);
phdr_size = get_program_header_size (abfd);
if (phdr_size == (file_ptr) -1)
return false;
phdr_off = off;
off += phdr_size;
/* We are creating an executable. */
maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
if (maxpagesize == 0)
@ -2081,6 +2178,19 @@ assign_file_positions_except_relocs (abfd, dosyms)
qsort (sorted_hdrs, i_ehdrp->e_shnum - 1, sizeof (Elf_Internal_Shdr *),
elf_sort_hdrs);
/* We can't actually create the program header until we have set the
file positions for the sections, and we can't do that until we know
how big the header is going to be. */
off = align_file_position (off);
phdr_size = get_program_header_size (abfd,
sorted_hdrs, i_ehdrp->e_shnum - 1,
maxpagesize);
if (phdr_size == (file_ptr) -1)
return false;
/* Compute the file offsets of each section. */
phdr_off = off;
off += phdr_size;
first = NULL;
for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++)
{
@ -2116,6 +2226,7 @@ assign_file_positions_except_relocs (abfd, dosyms)
off = assign_file_position_for_section (hdr, off, false);
}
/* Create the program header. */
phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs,
phdr_size);
if (phdr_map == (file_ptr) -1)
@ -3209,7 +3320,8 @@ elf_sizeof_headers (abfd, reloc)
ret = sizeof (Elf_External_Ehdr);
if (! reloc)
ret += get_program_header_size (abfd);
ret += get_program_header_size (abfd, (Elf_Internal_Shdr **) NULL, 0,
(bfd_vma) 0);
return ret;
}
@ -4297,7 +4409,8 @@ elf_link_add_object_symbols (abfd, info)
clobbering sec to be bfd_und_section_ptr. */
if (dynamic && definition)
{
if (h->root.type == bfd_link_hash_defined)
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
sec = bfd_und_section_ptr;
}
@ -4309,7 +4422,8 @@ elf_link_add_object_symbols (abfd, info)
object in the link. */
if (! dynamic
&& definition
&& h->root.type == bfd_link_hash_defined
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
&& (bfd_get_flavour (h->root.u.def.section->owner)
== bfd_target_elf_flavour)
@ -4332,7 +4446,7 @@ elf_link_add_object_symbols (abfd, info)
&& ! bfd_is_und_section (sec)
&& (h->root.type == bfd_link_hash_new
|| h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_weak))
|| h->root.type == bfd_link_hash_undefweak))
h->elf_link_hash_flags |= ELF_LINK_HASH_DEFINED_WEAK;
}
@ -4454,7 +4568,8 @@ elf_link_add_object_symbols (abfd, info)
weaks = hlook->weakdef;
hlook->weakdef = NULL;
BFD_ASSERT (hlook->root.type == bfd_link_hash_defined);
BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
|| hlook->root.type == bfd_link_hash_defweak);
slook = hlook->root.u.def.section;
vlook = hlook->root.u.def.value;
@ -4466,7 +4581,8 @@ elf_link_add_object_symbols (abfd, info)
h = *hpp;
if (h != hlook
&& h->root.type == bfd_link_hash_defined
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section == slook
&& h->root.u.def.value == vlook)
{
@ -5136,9 +5252,11 @@ elf_adjust_dynamic_symbol (h, data)
{
struct elf_link_hash_entry *weakdef;
BFD_ASSERT (h->root.type == bfd_link_hash_defined);
BFD_ASSERT (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak);
weakdef = h->weakdef;
BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined);
BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
|| weakdef->root.type == bfd_link_hash_defweak);
BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
{
@ -5703,7 +5821,8 @@ elf_bfd_final_link (abfd, info)
h = elf_link_hash_lookup (elf_hash_table (info), name,
false, false, true);
BFD_ASSERT (h != NULL);
if (h->root.type == bfd_link_hash_defined)
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
{
dyn.d_un.d_val = h->root.u.def.value;
o = h->root.u.def.section;
@ -5980,7 +6099,8 @@ elf_link_output_extsym (h, data)
sym.st_value = 0;
sym.st_size = h->size;
sym.st_other = 0;
if (h->root.type == bfd_link_hash_weak
if (h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_defweak
|| (h->elf_link_hash_flags & ELF_LINK_HASH_DEFINED_WEAK) != 0)
sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
else
@ -5998,12 +6118,13 @@ elf_link_output_extsym (h, data)
sym.st_shndx = SHN_UNDEF;
break;
case bfd_link_hash_weak:
case bfd_link_hash_undefweak:
input_sec = bfd_und_section_ptr;
sym.st_shndx = SHN_UNDEF;
break;
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
{
input_sec = h->root.u.def.section;
if (input_sec->output_section != NULL)