From 11bb5591d65ba1f968aa6deec02a31320ecff259 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 12 Nov 1994 20:55:33 +0000 Subject: [PATCH] * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add export_dynamic argument, and handle it. (elf_export_symbol): New function. * bfd-in.h (bfd_elf32_size_dynamic_sections): Update declaration. (bfd_elf64_size_dynamic_sections): Update declaration. * bfd-in2.h: Rebuild. --- bfd/ChangeLog | 9 ++++ bfd/elfcode.h | 147 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 115 insertions(+), 41 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 793fdf5fda..4f3f10ab50 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +Fri Nov 11 14:29:31 1994 Ian Lance Taylor + + * elfcode.h (NAME(bfd_elf,size_dynamic_sections)): Add + export_dynamic argument, and handle it. + (elf_export_symbol): New function. + * bfd-in.h (bfd_elf32_size_dynamic_sections): Update declaration. + (bfd_elf64_size_dynamic_sections): Update declaration. + * bfd-in2.h: Rebuild. + Fri Nov 11 10:35:33 1994 Jeff Law (law@snake.cs.utah.edu) * hpux-core.c (hpux_core_struct): Delete handles for the diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 0e4a252f7d..302005a840 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -161,6 +161,7 @@ static file_ptr align_file_position PARAMS ((file_ptr)); static file_ptr assign_file_position_for_section PARAMS ((Elf_Internal_Shdr *, file_ptr, boolean)); 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 file_ptr map_program_segments @@ -2028,6 +2029,8 @@ assign_file_positions_except_relocs (abfd, dosyms) file_ptr phdr_off; bfd_size_type phdr_size; bfd_vma maxpagesize; + size_t hdrppsize; + Elf_Internal_Shdr **sorted_hdrs; Elf_Internal_Shdr **hdrpp; unsigned int i; Elf_Internal_Shdr *first; @@ -2048,57 +2051,57 @@ assign_file_positions_except_relocs (abfd, dosyms) if (maxpagesize == 0) maxpagesize = 1; - /* FIXME: We might want to sort the sections on the sh_addr - field here. For now, we just assume that the linker will - create the sections in an appropriate order. */ + /* We must sort the sections. The GNU linker will always create + the sections in an appropriate order, but the Irix 5 linker + will not. We don't include the dummy first section in the + sort. We sort sections which are not SHF_ALLOC to the end. */ + hdrppsize = (i_ehdrp->e_shnum - 1) * sizeof (Elf_Internal_Shdr *); + sorted_hdrs = (Elf_Internal_Shdr **) malloc (hdrppsize); + if (sorted_hdrs == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + memcpy (sorted_hdrs, i_shdrpp + 1, hdrppsize); + qsort (sorted_hdrs, i_ehdrp->e_shnum - 1, sizeof (Elf_Internal_Shdr *), + elf_sort_hdrs); - /* Assign file positions in two passes. In the first pass, we - assign a file position to every section which forms part of - the executable image. */ first = NULL; - for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++) + for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++) { Elf_Internal_Shdr *hdr; hdr = *hdrpp; if ((hdr->sh_flags & SHF_ALLOC) == 0) - continue; + { + if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) + { + hdr->sh_offset = -1; + continue; + } + if (! dosyms + && (hdr == i_shdrpp[tdata->symtab_section] + || hdr == i_shdrpp[tdata->strtab_section])) + { + hdr->sh_offset = -1; + continue; + } + } + else + { + if (first == NULL) + first = hdr; - if (first == NULL) - first = hdr; - - /* The section VMA must equal the file position modulo the - page size. This is required by the program header. */ - off += (hdr->sh_addr - off) % maxpagesize; + /* The section VMA must equal the file position modulo + the page size. This is required by the program + header. */ + off += (hdr->sh_addr - off) % maxpagesize; + } off = assign_file_position_for_section (hdr, off, false); } - /* Assign file positions to all the sections which do not form - part of the loadable image, except for the relocs. */ - for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++) - { - Elf_Internal_Shdr *hdr; - - hdr = *hdrpp; - if ((hdr->sh_flags & SHF_ALLOC) != 0) - continue; - if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA) - { - hdr->sh_offset = -1; - continue; - } - if (! dosyms - && (i == tdata->symtab_section - || i == tdata->strtab_section)) - { - hdr->sh_offset = -1; - continue; - } - - off = assign_file_position_for_section (hdr, off, true); - } - phdr_map = map_program_segments (abfd, phdr_off, first, phdr_size); if (phdr_map == (file_ptr) -1) return false; @@ -2115,6 +2118,36 @@ assign_file_positions_except_relocs (abfd, dosyms) return true; } +/* Sort the ELF headers by VMA. We sort headers which are not + SHF_ALLOC to the end. */ + +static int +elf_sort_hdrs (arg1, arg2) + const PTR arg1; + const PTR arg2; +{ + const Elf_Internal_Shdr *hdr1 = *(const Elf_Internal_Shdr **) arg1; + const Elf_Internal_Shdr *hdr2 = *(const Elf_Internal_Shdr **) arg2; + + if ((hdr1->sh_flags & SHF_ALLOC) != 0) + { + if ((hdr2->sh_flags & SHF_ALLOC) == 0) + return -1; + if (hdr1->sh_addr < hdr2->sh_addr) + return -1; + else if (hdr1->sh_addr > hdr2->sh_addr) + return 1; + else + return 0; + } + else + { + if ((hdr1->sh_flags & SHF_ALLOC) != 0) + return 1; + return 0; + } +} + static boolean prep_headers (abfd) bfd *abfd; @@ -3677,6 +3710,8 @@ static boolean elf_link_add_archive_symbols PARAMS ((bfd *, struct bfd_link_info *)); static Elf_Internal_Rela *elf_link_read_relocs PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean)); +static boolean elf_export_symbol + PARAMS ((struct elf_link_hash_entry *, PTR)); static boolean elf_adjust_dynamic_symbol PARAMS ((struct elf_link_hash_entry *, PTR)); @@ -4796,11 +4831,12 @@ static const size_t elf_buckets[] = addresses of the various sections. */ boolean -NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info, - sinterpptr) +NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, + export_dynamic, info, sinterpptr) bfd *output_bfd; const char *soname; const char *rpath; + boolean export_dynamic; struct bfd_link_info *info; asection **sinterpptr; { @@ -4820,6 +4856,12 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info, if (dynobj == NULL) return true; + /* If we are supposed to export all symbols into the dynamic symbol + table (this is not the normal case), then do so. */ + if (export_dynamic) + elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol, + (PTR) info); + if (elf_hash_table (info)->dynamic_sections_created) { bfd_size_type strsize; @@ -4951,6 +4993,29 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info, return true; } +/* This routine is used to export all defined symbols into the dynamic + symbol table. It is called via elf_link_hash_traverse. */ + +static boolean +elf_export_symbol (h, data) + struct elf_link_hash_entry *h; + PTR data; +{ + struct bfd_link_info *info = (struct bfd_link_info *) data; + + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0) + { + if (! elf_link_record_dynamic_symbol (info, h)) + { + /* FIXME: No way to report error. */ + abort (); + } + } + + return true; +} + /* Make the backend pick a good value for a dynamic symbol. This is called via elf_link_hash_traverse, and also calls itself recursively. */