From 497c543457bbdabe61c03733d2a44167bf354dae Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 20 May 1994 16:04:59 +0000 Subject: [PATCH] * elf.c (_bfd_elf_make_section_from_shdr): New function, based on code repeated three times in bfd_section_from_shdr in elfcode.h. * libelf.h (_bfd_elf_make_section_from_shdr): Declare. * elfcode.h (bfd_section_from_shdr): Use new function _bfd_elf_make_section_from_shdr to create BFD sections. If a reloc section does not use the main symbol table, or it is part of the process image, treat it as a normal section, not relocs. * elf32-mips.c (mips_elf_section_from_shdr): Use new function _bfd_elf_make_section_from_shdr. --- bfd/ChangeLog | 12 ++++ bfd/elf.c | 62 ++++++++++++++++++++ bfd/elf32-mips.c | 93 +++++++++++------------------- bfd/elfcode.h | 144 ++++++++++------------------------------------- bfd/libelf.h | 3 +- 5 files changed, 137 insertions(+), 177 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a542d718337..aaecc9c520e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +Fri May 20 11:57:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) + + * elf.c (_bfd_elf_make_section_from_shdr): New function, based on + code repeated three times in bfd_section_from_shdr in elfcode.h. + * libelf.h (_bfd_elf_make_section_from_shdr): Declare. + * elfcode.h (bfd_section_from_shdr): Use new function + _bfd_elf_make_section_from_shdr to create BFD sections. If a + reloc section does not use the main symbol table, or it is part of + the process image, treat it as a normal section, not relocs. + * elf32-mips.c (mips_elf_section_from_shdr): Use new function + _bfd_elf_make_section_from_shdr. + Thu May 19 11:37:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * elf32-target.h, elf64-target.h: Change ar_max_namelen value from diff --git a/bfd/elf.c b/bfd/elf.c index a3ec15148fe..b5c23db365d 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -154,6 +154,68 @@ elf_string_from_elf_section (abfd, shindex, strindex) return ((char *) hdr->rawdata) + strindex; } +/* Make a BFD section from an ELF section. We store a pointer to the + BFD section in the rawdata field of the header. */ + +boolean +_bfd_elf_make_section_from_shdr (abfd, hdr, name) + bfd *abfd; + Elf_Internal_Shdr *hdr; + const char *name; +{ + asection *newsect; + flagword flags; + + if (hdr->rawdata != NULL) + { + BFD_ASSERT (strcmp (name, ((asection *) hdr->rawdata)->name) == 0); + return true; + } + + newsect = bfd_make_section_anyway (abfd, name); + if (newsect == NULL) + return false; + + newsect->filepos = hdr->sh_offset; + + if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr) + || ! bfd_set_section_size (abfd, newsect, hdr->sh_size) + || ! bfd_set_section_alignment (abfd, newsect, + bfd_log2 (hdr->sh_addralign))) + return false; + + flags = SEC_NO_FLAGS; + if (hdr->sh_type != SHT_NOBITS) + flags |= SEC_HAS_CONTENTS; + if ((hdr->sh_flags & SHF_ALLOC) != 0) + { + flags |= SEC_ALLOC; + if (hdr->sh_type != SHT_NOBITS) + flags |= SEC_LOAD; + } + if ((hdr->sh_flags & SHF_WRITE) == 0) + flags |= SEC_READONLY; + if ((hdr->sh_flags & SHF_EXECINSTR) != 0) + flags |= SEC_CODE; + else if ((flags & SEC_ALLOC) != 0) + flags |= SEC_DATA; + + /* The debugging sections appear to be recognized only by name, not + any sort of flag. */ + if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (name, ".line", sizeof ".line" - 1) == 0 + || strncmp (name, ".stab", sizeof ".stab" - 1) == 0) + flags |= SEC_DEBUGGING; + + if (! bfd_set_section_flags (abfd, newsect, flags)) + return false; + + hdr->rawdata = (PTR) newsect; + elf_section_data (newsect)->this_hdr = *hdr; + + return true; +} + /* INTERNAL_FUNCTION bfd_elf_find_section diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 7f4930da627..17942107764 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -795,6 +795,8 @@ mips_elf_section_from_shdr (abfd, hdr, name) Elf32_Internal_Shdr *hdr; char *name; { + asection *newsect; + /* There ought to be a place to keep ELF backend specific flags, but at the moment there isn't one. We just keep track of the sections by their name, instead. Fortunately, the ABI gives @@ -835,60 +837,33 @@ mips_elf_section_from_shdr (abfd, hdr, name) return false; } - if (hdr->rawdata == NULL) - { - asection *newsect; - - newsect = bfd_make_section (abfd, name); - if (newsect != NULL) - { - newsect->filepos = hdr->sh_offset; - newsect->flags |= SEC_HAS_CONTENTS; - newsect->vma = hdr->sh_addr; - newsect->_raw_size = hdr->sh_size; - newsect->alignment_power = bfd_log2 (hdr->sh_addralign); - - if (hdr->sh_flags & SHF_ALLOC) - { - newsect->flags |= SEC_ALLOC; - newsect->flags |= SEC_LOAD; - } - - if (!(hdr->sh_flags & SHF_WRITE)) - newsect->flags |= SEC_READONLY; - - if (hdr->sh_flags & SHF_EXECINSTR) - newsect->flags |= SEC_CODE; - else if (newsect->flags & SEC_ALLOC) - newsect->flags |= SEC_DATA; - - if (hdr->sh_type == SHT_MIPS_DEBUG) - newsect->flags |= SEC_DEBUGGING; + if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) + return false; + newsect = (asection *) hdr->rawdata; - hdr->rawdata = (void *) newsect; + if (hdr->sh_type == SHT_MIPS_DEBUG) + { + if (! bfd_set_section_flags (abfd, newsect, + (bfd_get_section_flags (abfd, newsect) + | SEC_DEBUGGING))) + return false; + } - /* FIXME: We should record the sh_info field for a .gptab - section. */ + /* FIXME: We should record sh_info for a .gptab section. */ - /* For a .reginfo section, set the gp value in the tdata - information from the contents of this section. We need - the gp value while processing relocs, so we just get it - now. */ - if (hdr->sh_type == SHT_MIPS_REGINFO) - { - Elf32_External_RegInfo ext; - Elf32_RegInfo s; + /* For a .reginfo section, set the gp value in the tdata information + from the contents of this section. We need the gp value while + processing relocs, so we just get it now. */ + if (hdr->sh_type == SHT_MIPS_REGINFO) + { + Elf32_External_RegInfo ext; + Elf32_RegInfo s; - if (bfd_get_section_contents (abfd, newsect, (PTR) &ext, - (file_ptr) 0, - sizeof ext) == false) - return false; - bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s); - elf_gp (abfd) = s.ri_gp_value; - } - } - else - hdr->rawdata = (void *) bfd_get_section_by_name (abfd, name); + if (! bfd_get_section_contents (abfd, newsect, (PTR) &ext, + (file_ptr) 0, sizeof ext)) + return false; + bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s); + elf_gp (abfd) = s.ri_gp_value; } return true; @@ -1201,20 +1176,15 @@ mips_elf_final_link (abfd, info) _bfd_generic_link_write_global_symbol, (PTR) &wginfo); - /* Remove empty sections. Also drop the .options section, since it - has special semantics which I haven't bothered to figure out. - Also drop the .gptab sections, which also require special - handling which is not currently done. Removing the .gptab - sections is required for Irix 5 compatibility; I don't know about - the other sections. */ + /* Drop the .options section, since it has special semantics which I + haven't bothered to figure out. Also drop the .gptab sections, + which also require special handling which is not currently done. + Removing the .gptab sections is required for Irix 5 + compatibility; I don't know about .options. */ secpp = &abfd->sections; while (*secpp != NULL) { - if (((*secpp)->_raw_size == 0 - && strcmp ((*secpp)->name, ".data") != 0 - && strcmp ((*secpp)->name, ".text") != 0 - && strcmp ((*secpp)->name, ".bss") != 0) - || strcmp ((*secpp)->name, ".options") == 0 + if (strcmp ((*secpp)->name, ".options") == 0 || strncmp ((*secpp)->name, ".gptab", 6) == 0) { *secpp = (*secpp)->next; @@ -1694,6 +1664,7 @@ static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = #define ELF_ARCH bfd_arch_mips #define ELF_MACHINE_CODE EM_MIPS #define ELF_MAXPAGESIZE 0x10000 +#define elf_backend_collect true #define elf_info_to_howto 0 #define elf_info_to_howto_rel mips_info_to_howto_rel #define elf_backend_sym_is_global mips_elf_sym_is_global diff --git a/bfd/elfcode.h b/bfd/elfcode.h index bdedb487e69..db0316aac18 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -496,7 +496,6 @@ bfd_add_2_to_strtab (abfd, ss, str, str2) return ss->length - ln; } - /* ELF .o/exec file reading */ /* Create a new bfd section from an ELF section header. */ @@ -508,84 +507,20 @@ bfd_section_from_shdr (abfd, shindex) { Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex]; Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd); - asection *newsect; char *name; name = elf_string_from_elf_strtab (abfd, hdr->sh_name); switch (hdr->sh_type) { - case SHT_NULL: - /* inactive section. Throw it away. */ + /* Inactive section. Throw it away. */ return true; - case SHT_PROGBITS: - case SHT_DYNAMIC: - /* Bits that get saved. This one is real. */ - if (hdr->rawdata == NULL) - { - newsect = bfd_make_section_anyway (abfd, name); - if (newsect == NULL) - return false; - - newsect->filepos = hdr->sh_offset; - newsect->flags |= SEC_HAS_CONTENTS; - newsect->vma = hdr->sh_addr; - newsect->_raw_size = hdr->sh_size; - newsect->alignment_power = bfd_log2 (hdr->sh_addralign); - - if (hdr->sh_flags & SHF_ALLOC) - { - newsect->flags |= SEC_ALLOC; - newsect->flags |= SEC_LOAD; - } - - if (!(hdr->sh_flags & SHF_WRITE)) - newsect->flags |= SEC_READONLY; - - if (hdr->sh_flags & SHF_EXECINSTR) - newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */ - else if (newsect->flags & SEC_ALLOC) - newsect->flags |= SEC_DATA; - - /* The debugging sections appear to recognized only by name, - not any sort of flag. */ - if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0 - || strncmp (name, ".line", sizeof ".line" - 1) == 0 - || strncmp (name, ".stab", sizeof ".stab" - 1) == 0) - newsect->flags |= SEC_DEBUGGING; - - hdr->rawdata = (PTR) newsect; - } - return true; - - case SHT_NOBITS: - /* Bits that get saved. This one is real. */ - if (hdr->rawdata == NULL) - { - newsect = bfd_make_section_anyway (abfd, name); - if (newsect == NULL) - return false; - - newsect->vma = hdr->sh_addr; - newsect->_raw_size = hdr->sh_size; - newsect->filepos = hdr->sh_offset; /* fake */ - newsect->alignment_power = bfd_log2 (hdr->sh_addralign); - if (hdr->sh_flags & SHF_ALLOC) - newsect->flags |= SEC_ALLOC; - - if (!(hdr->sh_flags & SHF_WRITE)) - newsect->flags |= SEC_READONLY; - - /* FIXME: This section is empty. Does it really make sense - to set SEC_CODE for it? */ - if (hdr->sh_flags & SHF_EXECINSTR) - newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */ - - hdr->rawdata = (PTR) newsect; - } - return true; + case SHT_PROGBITS: /* Normal section with contents. */ + case SHT_DYNAMIC: /* Dynamic linking information. */ + case SHT_NOBITS: /* .bss section. */ + return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_SYMTAB: /* A symbol table */ if (elf_onesymtab (abfd) == shindex) @@ -612,7 +547,7 @@ bfd_section_from_shdr (abfd, shindex) return true; case SHT_STRTAB: /* A string table */ - if (hdr->rawdata) + if (hdr->rawdata != NULL) return true; if (ehdr->e_shstrndx == shindex) { @@ -658,48 +593,29 @@ bfd_section_from_shdr (abfd, shindex) } } - newsect = bfd_make_section_anyway (abfd, name); - if (newsect == NULL) - return false; - - newsect->flags = SEC_HAS_CONTENTS; - hdr->rawdata = (PTR) newsect; - newsect->_raw_size = hdr->sh_size; - newsect->alignment_power = bfd_log2 (hdr->sh_addralign); - newsect->vma = hdr->sh_addr; - newsect->filepos = hdr->sh_offset; - - if (hdr->sh_flags & SHF_ALLOC) - newsect->flags |= SEC_ALLOC | SEC_LOAD; - if (!(hdr->sh_flags & SHF_WRITE)) - newsect->flags |= SEC_READONLY; - if (hdr->sh_flags & SHF_EXECINSTR) - newsect->flags |= SEC_CODE; - else if (newsect->flags & SEC_ALLOC) - newsect->flags |= SEC_DATA; - - /* Check for debugging string tables. */ - if (strncmp (name, ".debug", sizeof ".debug" - 1) == 0 - || strncmp (name, ".stab", sizeof ".stab" - 1) == 0) - newsect->flags |= SEC_DEBUGGING; - - return true; + return _bfd_elf_make_section_from_shdr (abfd, hdr, name); case SHT_REL: case SHT_RELA: - /* *These* do a lot of work -- but build no sections! - The spec says there can be multiple strtabs, but only one symtab, - but there can be lots of REL* sections. */ - /* FIXME: The above statement is wrong! There are typically at least - two symbol tables in a dynamically linked executable, ".dynsym" - which is the dynamic linkage symbol table and ".symtab", which is - the "traditional" symbol table. -fnf */ - + /* *These* do a lot of work -- but build no sections! */ { asection *target_sect; Elf_Internal_Shdr *hdr2; int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; + /* Get the symbol table. */ + if (! bfd_section_from_shdr (abfd, hdr->sh_link)) + return false; + + /* If this reloc section does not use the main symbol table, + or if it is in the process image, we don't treat it as a + reloc section. BFD can't adequately represent such a + section, so at least for now, we don't try. We just + present it as a normal section. */ + if ((hdr->sh_flags & SHF_ALLOC) != 0 + || hdr->sh_link != elf_onesymtab (abfd)) + return _bfd_elf_make_section_from_shdr (abfd, hdr, name); + /* Don't allow REL relocations on a machine that uses RELA and vice versa. */ /* @@ Actually, the generic ABI does suggest that both might be @@ -708,15 +624,13 @@ bfd_section_from_shdr (abfd, shindex) each of those architectures. It's conceivable that, e.g., a bunch of absolute 32-bit relocs might be more compact in REL form even on a RELA machine... */ - BFD_ASSERT (!(use_rela_p && (hdr->sh_type == SHT_REL))); - BFD_ASSERT (!(!use_rela_p && (hdr->sh_type == SHT_RELA))); - BFD_ASSERT (hdr->sh_entsize == - (use_rela_p - ? sizeof (Elf_External_Rela) - : sizeof (Elf_External_Rel))); - - if (! bfd_section_from_shdr (abfd, hdr->sh_info) /* target */ - || ! bfd_section_from_shdr (abfd, hdr->sh_link)) /* symbol table */ + BFD_ASSERT (use_rela_p + ? (hdr->sh_type == SHT_RELA + && hdr->sh_entsize == sizeof (Elf_External_Rela)) + : (hdr->sh_type == SHT_REL + && hdr->sh_entsize == sizeof (Elf_External_Rel))); + + if (! bfd_section_from_shdr (abfd, hdr->sh_info)) return false; target_sect = section_from_elf_index (abfd, hdr->sh_info); if (target_sect == NULL @@ -728,7 +642,7 @@ bfd_section_from_shdr (abfd, shindex) elf_elfsections (abfd)[shindex] = hdr2; target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize; target_sect->flags |= SEC_RELOC; - target_sect->relocation = 0; + target_sect->relocation = NULL; target_sect->rel_filepos = hdr->sh_offset; abfd->flags |= HAS_RELOC; return true; diff --git a/bfd/libelf.h b/bfd/libelf.h index 5d53f88e344..25d56b05cb8 100644 --- a/bfd/libelf.h +++ b/bfd/libelf.h @@ -453,7 +453,8 @@ extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *, char **)); extern boolean bfd_elf_mkobject PARAMS ((bfd *)); extern Elf_Internal_Shdr *bfd_elf_find_section PARAMS ((bfd *, char *)); - +extern boolean _bfd_elf_make_section_from_shdr + PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, const char *name)); extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create PARAMS ((bfd *)); -- 2.30.2