diff options
author | Ian Lance Taylor <ian@airs.com> | 1995-02-06 20:01:08 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1995-02-06 20:01:08 +0000 |
commit | 6c97aedf2686633d3e837802ce51ebe630f64056 (patch) | |
tree | bb409db186375bad6ede2a558c8a29d9dd1cb950 /bfd/elfcode.h | |
parent | ebc4ca90f97420f225f48141c631405357b58c16 (diff) | |
download | gdb-6c97aedf2686633d3e837802ce51ebe630f64056.zip gdb-6c97aedf2686633d3e837802ce51ebe630f64056.tar.gz gdb-6c97aedf2686633d3e837802ce51ebe630f64056.tar.bz2 |
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.
Diffstat (limited to 'bfd/elfcode.h')
-rw-r--r-- | bfd/elfcode.h | 185 |
1 files changed, 153 insertions, 32 deletions
diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 2edd5a8..0e61bb3 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -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) |