From fa15568ac1035f9835938d24a4053c2250378775 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 5 Jun 1994 20:00:42 +0000 Subject: [PATCH] Changes to support ELF strip and objcopy on dynamically linked files. * elfcode.h (elf_fake_sections): Add prototype. (bfd_section_from_shdr): Make a BFD section from an SHT_HASH section, and from an SHT_DYNSYM section, and from the dynamic string table section. (elf_object_p): Set D_PAGED if there is a program header. (elf_make_sections): Remove. (fix_up_strtabs): Remove. (elf_fake_sections): Rewrite. Now sets sh_entsize. (assign_section_numbers): Rewrite. Now sets sh_link and sh_info for all sections. (elf_compute_section_file_positions): Don't call obsolete functions elf_make_sections or fix_up_strtabs. (swap_out_syms): Set sh_addralign to FILE_ALIGN rather than 4. (NAME(bfd_elf,write_object_contents)): Permit writing DYNAMIC objects. (elf_section_from_bfd_section): Treat SHT_DYNSYM like other normal sections. If an SHT_REL or SHT_RELA section is allocated or uses an unusual symbol table, permit a BFD section to map to it. Permit most SHT_STRTAB sections to have a BFD section mapped to them. (elf_bfd_final_link): Don't set sh_link, sh_info or sh_entsize fields of dynamic sections here; do it in assign_section_numbers. * elf32-target.h, elf64-target.h: Add D_PAGED to permitted object flags. --- bfd/ChangeLog | 27 ++ bfd/elf32-target.h | 4 +- bfd/elf64-target.h | 4 +- bfd/elfcode.h | 627 ++++++++++++++++++++------------------------- 4 files changed, 313 insertions(+), 349 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index eae173b81f3..5102ba6ce53 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,32 @@ Sun Jun 5 15:02:30 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + Changes to support ELF strip and objcopy on dynamically linked + files. + * elfcode.h (elf_fake_sections): Add prototype. + (bfd_section_from_shdr): Make a BFD section from an SHT_HASH + section, and from an SHT_DYNSYM section, and from the dynamic + string table section. + (elf_object_p): Set D_PAGED if there is a program header. + (elf_make_sections): Remove. + (fix_up_strtabs): Remove. + (elf_fake_sections): Rewrite. Now sets sh_entsize. + (assign_section_numbers): Rewrite. Now sets sh_link and sh_info + for all sections. + (elf_compute_section_file_positions): Don't call obsolete + functions elf_make_sections or fix_up_strtabs. + (swap_out_syms): Set sh_addralign to FILE_ALIGN rather than 4. + (NAME(bfd_elf,write_object_contents)): Permit writing DYNAMIC + objects. + (elf_section_from_bfd_section): Treat SHT_DYNSYM like other normal + sections. If an SHT_REL or SHT_RELA section is allocated or uses + an unusual symbol table, permit a BFD section to map to it. + Permit most SHT_STRTAB sections to have a BFD section mapped to + them. + (elf_bfd_final_link): Don't set sh_link, sh_info or sh_entsize + fields of dynamic sections here; do it in assign_section_numbers. + * elf32-target.h, elf64-target.h: Add D_PAGED to permitted object + flags. + * elf.c (_bfd_elf_make_section_from_shdr): Only set SEC_DATA if SEC_LOAD is set, rather than checking SEC_ALLOC. diff --git a/bfd/elf32-target.h b/bfd/elf32-target.h index ae318767b7e..6192ad53a2d 100644 --- a/bfd/elf32-target.h +++ b/bfd/elf32-target.h @@ -194,7 +194,7 @@ bfd_target TARGET_BIG_SYM = /* object_flags: mask of all file flags */ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | - DYNAMIC | WP_TEXT), + DYNAMIC | WP_TEXT | D_PAGED), /* section_flags: mask of all section flags */ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | @@ -282,7 +282,7 @@ bfd_target TARGET_LITTLE_SYM = /* object_flags: mask of all file flags */ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | - DYNAMIC | WP_TEXT), + DYNAMIC | WP_TEXT | D_PAGED), /* section_flags: mask of all section flags */ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | diff --git a/bfd/elf64-target.h b/bfd/elf64-target.h index 4730386968d..dbab77d7a9f 100644 --- a/bfd/elf64-target.h +++ b/bfd/elf64-target.h @@ -197,7 +197,7 @@ bfd_target TARGET_BIG_SYM = /* object_flags: mask of all file flags */ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | - DYNAMIC | WP_TEXT), + DYNAMIC | WP_TEXT | D_PAGED), /* section_flags: mask of all section flags */ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | @@ -285,7 +285,7 @@ bfd_target TARGET_LITTLE_SYM = /* object_flags: mask of all file flags */ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | - DYNAMIC | WP_TEXT), + DYNAMIC | WP_TEXT | D_PAGED), /* section_flags: mask of all section flags */ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 21deffdf167..28befbdf205 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -145,6 +145,7 @@ static int elf_symbol_from_bfd_symbol PARAMS ((bfd *, static boolean elf_compute_section_file_positions PARAMS ((bfd *, struct bfd_link_info *)); static boolean prep_headers PARAMS ((bfd *)); +static void elf_fake_sections PARAMS ((bfd *, asection *, PTR)); static boolean assign_section_numbers PARAMS ((bfd *)); static file_ptr align_file_position PARAMS ((file_ptr)); static file_ptr assign_file_position_for_section @@ -520,6 +521,7 @@ bfd_section_from_shdr (abfd, shindex) case SHT_PROGBITS: /* Normal section with contents. */ case SHT_DYNAMIC: /* Dynamic linking information. */ case SHT_NOBITS: /* .bss section. */ + case SHT_HASH: /* .hash section. */ return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_SYMTAB: /* A symbol table */ @@ -544,7 +546,10 @@ bfd_section_from_shdr (abfd, shindex) elf_tdata (abfd)->dynsymtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->dynsymtab_hdr; abfd->flags |= HAS_SYMS; - return true; + + /* Besides being a symbol table, we also treat this as a regular + section, so that objcopy can handle it. */ + return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_STRTAB: /* A string table */ if (hdr->rawdata != NULL) @@ -569,14 +574,18 @@ bfd_section_from_shdr (abfd, shindex) if (elf_onesymtab (abfd) == i) { elf_tdata (abfd)->strtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr; + elf_elfsections (abfd)[shindex] = + &elf_tdata (abfd)->strtab_hdr; return true; } if (elf_dynsymtab (abfd) == i) { elf_tdata (abfd)->dynstrtab_hdr = *hdr; - elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->dynstrtab_hdr; - return true; + elf_elfsections (abfd)[shindex] = + &elf_tdata (abfd)->dynstrtab_hdr; + /* We also treat this as a regular section, so + that objcopy can handle it. */ + break; } #if 0 /* Not handling other string tables specially right now. */ hdr2 = elf_elfsections (abfd)[i]; /* in case it moved */ @@ -649,13 +658,6 @@ bfd_section_from_shdr (abfd, shindex) } break; - case SHT_HASH: -#if 0 - fprintf (stderr, "Dynamic Linking sections not yet supported.\n"); - BFD_FAIL (); -#endif - break; - case SHT_NOTE: #if 0 fprintf (stderr, "Note Sections not yet supported.\n"); @@ -926,13 +928,14 @@ elf_object_p (abfd) } } - /* Set the flags and architecture before calling the backend so that - it can override them. */ if (i_ehdrp->e_type == ET_EXEC) abfd->flags |= EXEC_P; else if (i_ehdrp->e_type == ET_DYN) abfd->flags |= DYNAMIC; + if (i_ehdrp->e_phnum > 0) + abfd->flags |= D_PAGED; + if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0)) goto got_no_match; @@ -1036,78 +1039,6 @@ elf_symbol_from (ignore_abfd, symbol) return (elf_symbol_type *) symbol; } -/* Create ELF output from BFD sections. - - Essentially, just create the section header and forget about the program - header for now. */ - -static void -elf_make_sections (abfd, asect, obj) - bfd *abfd; - asection *asect; - PTR obj; -{ - /* most of what is in bfd_shdr_from_section goes in here... */ - /* and all of these sections generate at *least* one ELF section. */ - Elf_Internal_Shdr *this_hdr; - this_hdr = &elf_section_data (asect)->this_hdr; - - this_hdr->sh_addr = asect->vma; - this_hdr->sh_size = asect->_raw_size; - /* contents already set by elf_set_section_contents */ - - if (asect->flags & SEC_RELOC) - { - /* emit a reloc section, and thus strtab and symtab... */ - Elf_Internal_Shdr *rela_hdr; - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - - rela_hdr = &elf_section_data (asect)->rel_hdr; - - /* orelocation has the data, reloc_count has the count... */ - if (use_rela_p) - { - rela_hdr->sh_type = SHT_RELA; - rela_hdr->sh_entsize = sizeof (Elf_External_Rela); - } - else - /* REL relocations */ - { - rela_hdr->sh_type = SHT_REL; - rela_hdr->sh_entsize = sizeof (Elf_External_Rel); - } - rela_hdr->sh_flags = 0; - rela_hdr->sh_addr = 0; - rela_hdr->sh_offset = 0; - - /* FIXME: Systems I've checked use an alignment of 4, but it is - possible that some systems use a different alignment. */ - rela_hdr->sh_addralign = 4; - - rela_hdr->size = 0; - } - if (asect->flags & SEC_ALLOC) - { - this_hdr->sh_flags |= SHF_ALLOC; - if (asect->flags & SEC_LOAD) - { - /* @@ Do something with sh_type? */ - } - } - else - { - /* If this section is not part of the program image during - execution, leave the address fields at 0. */ - this_hdr->sh_addr = 0; - asect->vma = 0; - } - if (!(asect->flags & SEC_READONLY)) - this_hdr->sh_flags |= SHF_WRITE; - - if (asect->flags & SEC_CODE) - this_hdr->sh_flags |= SHF_EXECINSTR; -} - void write_relocs (abfd, sec, xxx) bfd *abfd; @@ -1211,96 +1142,97 @@ write_relocs (abfd, sec, xxx) } } -static void -fix_up_strtabs (abfd, asect, obj) - bfd *abfd; - asection *asect; - PTR obj; -{ - Elf_Internal_Shdr *this_hdr = &elf_section_data (asect)->this_hdr; - int this_idx = elf_section_data (asect)->this_idx; - - /* @@ Check flags! */ - if (!strncmp (asect->name, ".stab", 5) - && !strcmp ("str", asect->name + strlen (asect->name) - 3)) - { - size_t len = strlen (asect->name) + 1; - char *s = (char *) malloc (len); - if (s == NULL) - /* FIXME: Should deal more gracefully with errors. */ - abort (); - strcpy (s, asect->name); - s[len - 4] = 0; - asect = bfd_get_section_by_name (abfd, s); - free (s); - if (!asect) - abort (); - elf_section_data (asect)->this_hdr.sh_link = this_idx; - /* @@ Assuming 32 bits! */ - elf_section_data (asect)->this_hdr.sh_entsize = 0xc; - - this_hdr->sh_type = SHT_STRTAB; - } -} +/* Set up an ELF internal section header for a section. */ +/*ARGSUSED*/ static void -elf_fake_sections (abfd, asect, obj) +elf_fake_sections (abfd, asect, ignore) bfd *abfd; asection *asect; - PTR obj; + PTR ignore; { - /* most of what is in bfd_shdr_from_section goes in here... */ - /* and all of these sections generate at *least* one ELF section. */ - Elf_Internal_Shdr *this_hdr; + this_hdr = &elf_section_data (asect)->this_hdr; - this_hdr->sh_name = - bfd_add_to_strtab (abfd, elf_shstrtab (abfd), asect->name); + + this_hdr->sh_name = bfd_add_to_strtab (abfd, elf_shstrtab (abfd), + asect->name); if (this_hdr->sh_name == (unsigned long) -1) abort (); /* FIXME */ - /* We need to log the type *now* so that elf_section_from_bfd_section - can find us... have to set rawdata too. */ - this_hdr->rawdata = (void *) asect; + + this_hdr->sh_flags = 0; + if ((asect->flags & SEC_ALLOC) != 0) + this_hdr->sh_addr = asect->vma; + else + this_hdr->sh_addr = 0; + this_hdr->sh_offset = 0; + this_hdr->sh_size = asect->_raw_size; + this_hdr->sh_link = 0; + this_hdr->sh_info = 0; this_hdr->sh_addralign = 1 << asect->alignment_power; + this_hdr->sh_entsize = 0; + + this_hdr->rawdata = (PTR) asect; + this_hdr->contents = NULL; + this_hdr->size = 0; /* FIXME: This should not be based on section names. */ if (strcmp (asect->name, ".dynstr") == 0) this_hdr->sh_type = SHT_STRTAB; else if (strcmp (asect->name, ".hash") == 0) - this_hdr->sh_type = SHT_HASH; + { + this_hdr->sh_type = SHT_HASH; + this_hdr->sh_entsize = ARCH_SIZE / 8; + } else if (strcmp (asect->name, ".dynsym") == 0) - this_hdr->sh_type = SHT_DYNSYM; + { + this_hdr->sh_type = SHT_DYNSYM; + this_hdr->sh_entsize = sizeof (Elf_External_Sym); + } else if (strcmp (asect->name, ".dynamic") == 0) - this_hdr->sh_type = SHT_DYNAMIC; + { + this_hdr->sh_type = SHT_DYNAMIC; + this_hdr->sh_entsize = sizeof (Elf_External_Dyn); + } else if (strncmp (asect->name, ".rel.", 5) == 0) - this_hdr->sh_type = SHT_REL; + { + this_hdr->sh_type = SHT_REL; + this_hdr->sh_entsize = sizeof (Elf_External_Rel); + } else if (strncmp (asect->name, ".rela.", 6) == 0) - this_hdr->sh_type = SHT_RELA; - else if ((asect->flags & SEC_ALLOC) && (asect->flags & SEC_LOAD)) + { + this_hdr->sh_type = SHT_RELA; + this_hdr->sh_entsize = sizeof (Elf_External_Rela); + } + else if (strcmp (asect->name, ".note") == 0) + this_hdr->sh_type = SHT_NOTE; + else if (strncmp (asect->name, ".stab", 5) == 0 + && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0) + this_hdr->sh_type = SHT_STRTAB; + else if ((asect->flags & SEC_ALLOC) != 0 + && (asect->flags & SEC_LOAD) != 0) this_hdr->sh_type = SHT_PROGBITS; - else if ((asect->flags & SEC_ALLOC) && ((asect->flags & SEC_LOAD) == 0)) + else if ((asect->flags & SEC_ALLOC) != 0 + && ((asect->flags & SEC_LOAD) == 0)) { BFD_ASSERT (strcmp (asect->name, ".bss") == 0 || strcmp (asect->name, ".sbss") == 0); this_hdr->sh_type = SHT_NOBITS; } - /* FIXME I am not sure how to detect a .note section from the flags - word of an `asection'. */ - else if (!strcmp (asect->name, ".note")) - this_hdr->sh_type = SHT_NOTE; else - this_hdr->sh_type = SHT_PROGBITS; + { + /* Who knows? */ + this_hdr->sh_type = SHT_PROGBITS; + } - this_hdr->sh_flags = 0; - this_hdr->sh_addr = 0; - this_hdr->sh_size = 0; - this_hdr->sh_entsize = 0; - this_hdr->sh_info = 0; - this_hdr->sh_link = 0; - this_hdr->sh_offset = 0; - this_hdr->size = 0; + if ((asect->flags & SEC_ALLOC) != 0) + this_hdr->sh_flags |= SHF_ALLOC; + if ((asect->flags & SEC_READONLY) == 0) + this_hdr->sh_flags |= SHF_WRITE; + if ((asect->flags & SEC_CODE) != 0) + this_hdr->sh_flags |= SHF_EXECINSTR; - /* Now, check for processor-specific section types. */ + /* Check for processor-specific section types. */ { struct elf_backend_data *bed = get_elf_backend_data (abfd); @@ -1308,51 +1240,199 @@ elf_fake_sections (abfd, asect, obj) (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect); } - { - /* Emit a strtab and symtab, and possibly a reloc section. */ - Elf_Internal_Shdr *rela_hdr; + /* If the section has relocs, set up a section header for the + SHT_REL[A] section. */ + if ((asect->flags & SEC_RELOC) != 0) + { + Elf_Internal_Shdr *rela_hdr; + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - /* Note that only one symtab is used, so just remember it - for now. */ + rela_hdr = &elf_section_data (asect)->rel_hdr; + rela_hdr->sh_name = + bfd_add_2_to_strtab (abfd, elf_shstrtab (abfd), + use_rela_p ? ".rela" : ".rel", + asect->name); + rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; + rela_hdr->sh_entsize = (use_rela_p + ? sizeof (Elf_External_Rela) + : sizeof (Elf_External_Rel)); + rela_hdr->sh_addralign = FILE_ALIGN; + rela_hdr->sh_flags = 0; + rela_hdr->sh_addr = 0; + rela_hdr->sh_size = 0; + rela_hdr->sh_offset = 0; + rela_hdr->size = 0; + } +} - if (asect->flags & SEC_RELOC) - { - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; +/* Assign all ELF section numbers. The dummy first section is handled here + too. The link/info pointers for the standard section types are filled + in here too, while we're at it. (Link pointers for .stab sections are + not filled in here.) */ - rela_hdr = &elf_section_data (asect)->rel_hdr; - rela_hdr->sh_name = - bfd_add_2_to_strtab (abfd, elf_shstrtab (abfd), - use_rela_p ? ".rela" : ".rel", - asect->name); - rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; - rela_hdr->sh_entsize = (use_rela_p - ? sizeof (Elf_External_Rela) - : sizeof (Elf_External_Rel)); - - rela_hdr->sh_flags = 0; - rela_hdr->sh_addr = 0; - rela_hdr->sh_size = 0; - rela_hdr->sh_offset = 0; - - /* FIXME: Systems I've checked use an alignment of 4, but some - systems may use a different alignment. */ - rela_hdr->sh_addralign = 4; - - rela_hdr->size = 0; - } - } - if (asect->flags & SEC_ALLOC) +static boolean +assign_section_numbers (abfd) + bfd *abfd; +{ + struct elf_obj_tdata *t = elf_tdata (abfd); + asection *sec; + unsigned int section_number; + Elf_Internal_Shdr **i_shdrp; + + section_number = 1; + + t->shstrtab_section = section_number++; + elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; + t->shstrtab_hdr.sh_size = elf_shstrtab (abfd)->length; + t->shstrtab_hdr.contents = (PTR) elf_shstrtab (abfd)->tab; + + if (abfd->symcount > 0) + { + t->symtab_section = section_number++; + t->strtab_section = section_number++; + } + + for (sec = abfd->sections; sec; sec = sec->next) + { + struct bfd_elf_section_data *d = elf_section_data (sec); + + d->this_idx = section_number++; + if ((sec->flags & SEC_RELOC) == 0) + d->rel_idx = 0; + else + d->rel_idx = section_number++; + } + + elf_elfheader (abfd)->e_shnum = section_number; + + /* Set up the list of section header pointers, in agreement with the + indices. */ + i_shdrp = ((Elf_Internal_Shdr **) + bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *))); + if (i_shdrp == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + + i_shdrp[0] = ((Elf_Internal_Shdr *) + bfd_alloc (abfd, sizeof (Elf_Internal_Shdr))); + if (i_shdrp[0] == NULL) + { + bfd_release (abfd, i_shdrp); + bfd_set_error (bfd_error_no_memory); + return false; + } + memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr)); + + elf_elfsections (abfd) = i_shdrp; + + i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr; + if (abfd->symcount > 0) + { + i_shdrp[t->symtab_section] = &t->symtab_hdr; + i_shdrp[t->strtab_section] = &t->strtab_hdr; + t->symtab_hdr.sh_link = t->strtab_section; + } + for (sec = abfd->sections; sec; sec = sec->next) { - this_hdr->sh_flags |= SHF_ALLOC; - if (asect->flags & SEC_LOAD) + struct bfd_elf_section_data *d = elf_section_data (sec); + asection *s; + const char *name; + + i_shdrp[d->this_idx] = &d->this_hdr; + if (d->rel_idx != 0) + i_shdrp[d->rel_idx] = &d->rel_hdr; + + /* Fill in the sh_link and sh_info fields while we're at it. */ + + /* sh_link of a reloc section is the section index of the symbol + table. sh_info is the section index of the section to which + the relocation entries apply. */ + if (d->rel_idx != 0) + { + d->rel_hdr.sh_link = t->symtab_section; + d->rel_hdr.sh_info = d->this_idx; + } + + switch (d->this_hdr.sh_type) { - /* @@ Do something with sh_type? */ + case SHT_REL: + case SHT_RELA: + /* A reloc section which we are treating as a normal BFD + section. sh_link is the section index of the symbol + table. sh_info is the section index of the section to + which the relocation entries apply. We assume that an + allocated reloc section uses the dynamic symbol table. + FIXME: How can we be sure? */ + s = bfd_get_section_by_name (abfd, ".dynsym"); + if (s != NULL) + d->this_hdr.sh_link = elf_section_data (s)->this_idx; + + /* We look up the section the relocs apply to by name. */ + name = sec->name; + if (d->this_hdr.sh_type == SHT_REL) + name += 4; + else + name += 5; + s = bfd_get_section_by_name (abfd, name); + if (s != NULL) + d->this_hdr.sh_info = elf_section_data (s)->this_idx; + break; + + case SHT_STRTAB: + /* We assume that a section named .stab*str is a stabs + string section. We look for a section with the same name + but without the trailing ``str'', and set its sh_link + field to point to this section. */ + if (strncmp (sec->name, ".stab", sizeof ".stab" - 1) == 0 + && strcmp (sec->name + strlen (sec->name) - 3, "str") == 0) + { + size_t len; + char *alc; + + len = strlen (sec->name); + alc = (char *) malloc (len - 2); + if (alc == NULL) + { + bfd_set_error (bfd_error_no_memory); + return false; + } + strncpy (alc, sec->name, len - 3); + alc[len - 3] = '\0'; + s = bfd_get_section_by_name (abfd, alc); + free (alc); + if (s != NULL) + { + elf_section_data (s)->this_hdr.sh_link = d->this_idx; + + /* This is a .stab section. */ + elf_section_data (s)->this_hdr.sh_entsize = + 4 + 2 * (ARCH_SIZE / 8); + } + } + break; + + case SHT_DYNAMIC: + case SHT_DYNSYM: + /* sh_link is the section header index of the string table + used for the dynamic entries or symbol table. */ + s = bfd_get_section_by_name (abfd, ".dynstr"); + if (s != NULL) + d->this_hdr.sh_link = elf_section_data (s)->this_idx; + break; + + case SHT_HASH: + /* sh_link is the section header index of the symbol table + this hash table is for. */ + s = bfd_get_section_by_name (abfd, ".dynsym"); + if (s != NULL) + d->this_hdr.sh_link = elf_section_data (s)->this_idx; + break; } } - if (!(asect->flags & SEC_READONLY)) - this_hdr->sh_flags |= SHF_WRITE; - if (asect->flags & SEC_CODE) - this_hdr->sh_flags |= SHF_EXECINSTR; + + return true; } /* Map symbol from it's internal number to the external number, moving @@ -1540,10 +1620,6 @@ elf_compute_section_file_positions (abfd, link_info) if (!assign_section_numbers (abfd)) return false; - bfd_map_over_sections (abfd, elf_make_sections, 0); - - bfd_map_over_sections (abfd, fix_up_strtabs, 0); /* .stab/.stabstr &c */ - /* The backend linker builds symbol table information itself. */ if (link_info == NULL) { @@ -1574,89 +1650,6 @@ elf_compute_section_file_positions (abfd, link_info) } -/* Assign all ELF section numbers. The dummy first section is handled here - too. The link/info pointers for the standard section types are filled - in here too, while we're at it. (Link pointers for .stab sections are - not filled in here.) */ -static boolean -assign_section_numbers (abfd) - bfd *abfd; -{ - struct elf_obj_tdata *t = elf_tdata (abfd); - asection *sec; - int section_number = 1; - int i; - Elf_Internal_Shdr **i_shdrp; - - t->shstrtab_hdr.sh_size = elf_shstrtab (abfd)->length; - t->shstrtab_hdr.contents = (void *) elf_shstrtab (abfd)->tab; - - t->shstrtab_section = section_number++; - elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; - if (abfd->symcount) - { - t->symtab_section = section_number++; - t->strtab_section = section_number++; - t->symtab_hdr.sh_link = t->strtab_section; - } - for (sec = abfd->sections; sec; sec = sec->next) - { - struct bfd_elf_section_data *d = elf_section_data (sec); - d->this_idx = section_number++; - if (sec->flags & SEC_RELOC) - { - d->rel_idx = section_number++; - d->rel_hdr.sh_link = t->symtab_section; - d->rel_hdr.sh_info = d->this_idx; - } - else - d->rel_idx = 0; - /* No handling for per-section string tables currently. */ - } - elf_elfheader (abfd)->e_shnum = section_number; - - /* Set up the list of section header pointers, in agreement with the - indices. */ - i_shdrp = ((Elf_Internal_Shdr **) - bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *))); - if (i_shdrp == NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - i_shdrp[0] = ((Elf_Internal_Shdr *) - bfd_alloc (abfd, sizeof (Elf_Internal_Shdr))); - if (i_shdrp[0] == NULL) - { - bfd_release (abfd, i_shdrp); - bfd_set_error (bfd_error_no_memory); - return false; - } - elf_elfsections (abfd) = i_shdrp; - for (i = 1; i < section_number; i++) - i_shdrp[i] = NULL; - memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr)); - - i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr; - if (abfd->symcount) - { - i_shdrp[t->symtab_section] = &t->symtab_hdr; - i_shdrp[t->strtab_section] = &t->strtab_hdr; - } - for (sec = abfd->sections; sec; sec = sec->next) - { - struct bfd_elf_section_data *d = elf_section_data (sec); - i_shdrp[d->this_idx] = &d->this_hdr; - if (d->rel_idx) - i_shdrp[d->rel_idx] = &d->rel_hdr; - } - /* Make sure we got everything.... */ - for (i = 0; i < section_number; i++) - if (i_shdrp[i] == NULL) - abort (); - return true; -} - /* Align to the maximum file alignment that could be required for any ELF data structure. */ @@ -2246,13 +2239,8 @@ swap_out_syms (abfd) symtab_hdr->sh_entsize = sizeof (Elf_External_Sym); symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1); symtab_hdr->sh_info = elf_num_locals (abfd) + 1; + symtab_hdr->sh_addralign = FILE_ALIGN; - /* FIXME: Systems I've checked use 4 byte alignment for .symtab, - but it is possible that there are systems which use a different - alignment. */ - symtab_hdr->sh_addralign = 4; - - /* see assert in elf_fake_sections that supports this: */ symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; symstrtab_hdr->sh_type = SHT_STRTAB; @@ -2473,15 +2461,6 @@ NAME(bfd_elf,write_object_contents) (abfd) Elf_Internal_Shdr **i_shdrp; unsigned int count; - /* We don't know how to write dynamic objects. Specifically, we - don't know how to construct the program header. */ - if ((abfd->flags & DYNAMIC) != 0) - { - fprintf (stderr, "Writing ELF dynamic objects is not supported\n"); - bfd_set_error (bfd_error_wrong_format); - return false; - } - if (! abfd->output_has_begun && ! elf_compute_section_file_positions (abfd, (struct bfd_link_info *) NULL)) @@ -2591,6 +2570,7 @@ elf_section_from_bfd_section (abfd, asect) case SHT_NOTE: case SHT_HASH: case SHT_DYNAMIC: + case SHT_DYNSYM: if (hdr->rawdata) { if (((struct sec *) (hdr->rawdata)) == asect) @@ -2598,19 +2578,22 @@ elf_section_from_bfd_section (abfd, asect) } break; + case SHT_REL: + case SHT_RELA: + /* We sometimes map a reloc section to a BFD section. */ + if (((hdr->sh_flags & SHF_ALLOC) != 0 + || hdr->sh_link != elf_onesymtab (abfd)) + && (asection *) hdr->rawdata == asect) + return index; + break; + case SHT_STRTAB: - /* fix_up_strtabs will generate STRTAB sections with names - of .stab*str. */ - if (!strncmp (asect->name, ".stab", 5) - && !strcmp ("str", asect->name + strlen (asect->name) - 3)) - { - if (hdr->rawdata) - { - if (((struct sec *) (hdr->rawdata)) == asect) - return index; - } - break; - } + /* We map most string tables to BFD sections. */ + if (index != elf_elfheader (abfd)->e_shstrndx + && index != elf_onesymtab (abfd) + && (asection *) hdr->rawdata == asect) + return index; + /* FALL THROUGH */ default: { @@ -5524,10 +5507,6 @@ elf_bfd_final_link (abfd, info) for (o = dynobj->sections; o != NULL; o = o->next) { - Elf_Internal_Shdr *hdr; - asection *s; - const char *name; - if ((o->flags & SEC_HAS_CONTENTS) == 0) continue; BFD_ASSERT ((o->flags & SEC_IN_MEMORY) != 0); @@ -5535,48 +5514,6 @@ elf_bfd_final_link (abfd, info) o->contents, o->output_offset, o->_raw_size)) goto error_return; - - hdr = &elf_section_data (o->output_section)->this_hdr; - switch (hdr->sh_type) - { - case SHT_DYNAMIC: - s = bfd_get_section_by_name (abfd, ".dynstr"); - hdr->sh_link = elf_section_data (s)->this_idx; - hdr->sh_entsize = sizeof (Elf_External_Dyn); - break; - - case SHT_HASH: - s = finfo.dynsym_sec->output_section; - hdr->sh_link = elf_section_data (s)->this_idx; - hdr->sh_entsize = ARCH_SIZE / 8; - break; - - case SHT_DYNSYM: - s = bfd_get_section_by_name (abfd, ".dynstr"); - hdr->sh_link = elf_section_data (s)->this_idx; - hdr->sh_entsize = sizeof (Elf_External_Sym); - break; - - case SHT_REL: - case SHT_RELA: - name = bfd_get_section_name (abfd, o->output_section); - s = finfo.dynsym_sec->output_section; - hdr->sh_link = elf_section_data (s)->this_idx; - if (hdr->sh_type == SHT_REL) - { - name += 4; - hdr->sh_entsize = sizeof (Elf_External_Rel); - } - else - { - name += 5; - hdr->sh_entsize = sizeof (Elf_External_Rela); - } - s = bfd_get_section_by_name (abfd, name); - if (s != NULL) - hdr->sh_info = elf_section_data (s)->this_idx; - break; - } } } -- 2.30.2