diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0b818d9035..605141afca 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,8 +1,63 @@ Fri Aug 20 15:16:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) + * elfcode.h (elf_build_phdrs): Unused function deleted. + (bfd_shdr_from_section): Ditto. + (write_relocs): Don't change section contents for addend. + (elf_locate_sh): Return type is now always elf_internal_shdr, + since the other types were really aliases for this type anyways. + Don't compile this function, since it is static and doesn't appear + to be used in this file. + (sym_is_global): Return non-zero for weak symbols. Abort if + section pointer is null. + (swap_out_syms): Reorder tests so function symbols can be weak. + (elf_slurp_symbol_table): Don't use BSF_EXPORT. + (elf_slurp_reloca_table): Make RELOC_PROCESSING section smaller by + extracting out some common code. Abort if BFD section symbol has + null name. + (elf_slurp_reloc_table): Translate ELF section symbols into BFD + section symbols. Don't read section contents to fill in addend + field. + * elf32-i386.c (elf_howto_table): All partial_inplace fields should be "true". + * Merged from OSF: + + Tue Jun 15 14:38:32 1993 Michael Meissner (meissner@osf.org) + + * libelf.h (struct Elf_Sym_Extra): New structure to contain ELF + specific information for a symbol. Put in elf_sym_num, which + gives the external symbol number in the elf object file, since + local symbols must come before global symbols. + (elf_sym_extra): New macro. + (elf_symtab_map): Delete, in favor of using Elf_Sym_Extra. + * elfcode.h (elf_map_symbols): Use Elf_Sym_Extra to map internal + symbol number to external number. Store the address of the + Elf_Sym_Extra field for the symbol in the udata field. + (elf_write_object_contents): Use Elf_Sym_Extra to map out symbols. + + Sun Jun 20 16:30:11 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_obj_tdata): Add field to count the size of the + array of pointers to section symbols. + (elf_map_symbols): Bump the max index of the section symbols so + that we don't overwrite memory. Store the max index into the + elf_obj_tdata field. + + Sat Jun 19 10:12:27 1993 Michael Meissner (meissner@osf.org) + + * elfcode.h (elf_obj_tdata): Add pointer to an array of pointers + to the section symbols we created. Remove unused field + internal_syms. + (elf_map_symbols): Fill in array of pointers to section symbols. + Only create section symbols for sections that have SEC_ALLOC set, + and have non-zero size. + (elf_symbol_from_bfd_symbol): If udata is NULL, and this is a + section symbol, look up the section in the list of section + symbols, and set the udata pointer appropriately. Otherwise, if + udata is still NULL, fail an assertion, and use 0, instead of + dropping core. + Fri Aug 20 12:18:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * config.bfd (mips-*-elfl*, mips-*-elf*): New targets, using diff --git a/bfd/elfcode.h b/bfd/elfcode.h index fb00ae05e2..ee5c4540e1 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -54,7 +54,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ once in 64-bit mode. More of it should be made size-independent and moved into elf.c. -*/ + (3) ELF section symbols are handled rather sloppily now. This should + be cleaned up, and ELF section symbols reconciled with BFD section + symbols. + */ #include #include /* For strrchr and friends */ @@ -776,6 +779,20 @@ DEFUN (elf_file_p, (x_ehdrp), Elf_External_Ehdr * x_ehdrp) && (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3)); } +/* Check to see if the file associated with ABFD matches the target vector + that ABFD points to. + + Note that we may be called several times with the same ABFD, but different + target vectors, most of which will not match. We have to avoid leaving + any side effects in ABFD, or any data it points to (like tdata), if the + file does not match the target vector. + + FIXME: There is memory leak if we are called more than once with the same + ABFD, and that bfd already has tdata allocated, since we allocate more tdata + and the old tdata is orphaned. Since it's in the bfd obstack, there isn't + much we can do about this except possibly rewrite the code. There are + also other bfd_allocs that may be the source of memory leaks as well. */ + bfd_target * DEFUN (elf_object_p, (abfd), bfd * abfd) { @@ -786,14 +803,12 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) int shindex; char *shstrtab; /* Internal copy of section header stringtab */ struct elf_backend_data *ebd; /* Use to get ELF_ARCH stored in xvec */ + struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd); /* Read in the ELF header in external format. */ if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) - { - bfd_error = system_call_error; - return NULL; - } + goto got_system_call_error; /* Now check to see if we have a valid ELF file, and one that BFD can make use of. The magic number must match, the address size ('class') @@ -801,46 +816,34 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) section header table (FIXME: See comments re sections at top of this file). */ - if (elf_file_p (&x_ehdr) == false) - { - wrong: - bfd_error = wrong_format; - return NULL; - } + if ((elf_file_p (&x_ehdr) == false) || + (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) || + (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)) + goto got_wrong_format_error; - if (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) - goto wrong; - - if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS) - goto wrong; - - /* Switch xvec to match the specified byte order. */ + /* Check that file's byte order matches xvec's */ switch (x_ehdr.e_ident[EI_DATA]) { case ELFDATA2MSB: /* Big-endian */ if (!abfd->xvec->header_byteorder_big_p) - goto wrong; + goto got_wrong_format_error; break; case ELFDATA2LSB: /* Little-endian */ if (abfd->xvec->header_byteorder_big_p) - goto wrong; + goto got_wrong_format_error; break; case ELFDATANONE: /* No data encoding specified */ default: /* Unknown data encoding specified */ - goto wrong; + goto got_wrong_format_error; } /* Allocate an instance of the elf_obj_tdata structure and hook it up to - the tdata pointer in the bfd. */ + the tdata pointer in the bfd. FIXME: memory leak, see above. */ - if (NULL == (elf_tdata (abfd) = (struct elf_obj_tdata *) - bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)))) - { - bfd_error = no_memory; - return NULL; - } - - /* FIXME: Any `wrong' exits below here will leak memory (tdata). */ + elf_tdata (abfd) = + (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); + if (elf_tdata (abfd) == NULL) + goto got_no_memory_error; /* Now that we know the byte order, swap in the rest of the header */ i_ehdrp = elf_elfheader (abfd); @@ -851,7 +854,7 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) /* If there is no section header table, we're hosed. */ if (i_ehdrp->e_shoff == 0) - goto wrong; + goto got_wrong_format_error; if (i_ehdrp->e_type == ET_EXEC || i_ehdrp->e_type == ET_DYN) abfd->flags |= EXEC_P; @@ -884,7 +887,7 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) arch = bfd_arch_sparc; /* end-sanitize-v9 */ if (ebd->arch != arch) - goto wrong; + goto got_wrong_format_error; bfd_default_set_arch_mach (abfd, arch, 0); } @@ -895,29 +898,19 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) header table entry actually matches the size recorded in the file. */ if (i_ehdrp->e_shentsize != sizeof (x_shdr)) - goto wrong; + goto got_wrong_format_error; i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum); elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum); if (!i_shdrp || !elf_elfsections(abfd)) - { - bfd_error = no_memory; - return NULL; - } + goto got_no_memory_error; if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) == -1) - { - bfd_error = system_call_error; - return NULL; - } + goto got_system_call_error; for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++) { - if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) - != sizeof (x_shdr)) - { - bfd_error = system_call_error; - return NULL; - } + if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) != sizeof (x_shdr)) + goto got_system_call_error; elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); elf_elfsections(abfd)[shindex] = i_shdrp + shindex; } @@ -955,7 +948,7 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) shstrtab = elf_get_str_section (abfd, i_ehdrp->e_shstrndx); if (!shstrtab) - return NULL; + goto got_wrong_format_error; /* Once all of the section headers have been read and converted, we can start processing them. Note that the first section header is @@ -974,75 +967,30 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) bfd_get_start_address (abfd) = i_ehdrp->e_entry; - return abfd->xvec; + return (abfd->xvec); + + /* If we are going to use goto's to avoid duplicating error setting + and return(NULL) code, then this at least makes it more maintainable. */ + + got_system_call_error: + bfd_error = system_call_error; + goto got_no_match; + got_wrong_format_error: + bfd_error = wrong_format; + goto got_no_match; + got_no_memory_error: + bfd_error = no_memory; + goto got_no_match; + got_no_match: + elf_tdata (abfd) = preserved_tdata; + return (NULL); } /* ELF .o/exec file writing */ -/* Create a new ELF section from a bfd section. */ - -#if 0 /* not used */ -static boolean -DEFUN (bfd_shdr_from_section, (abfd, hdr, shstrtab, indx), - bfd * abfd AND - Elf_Internal_Shdr * hdr AND - struct strtab *shstrtab AND - int indx) -{ - asection *sect; - int ndx; - - sect = abfd->sections; - for (ndx = indx; --ndx;) - { - sect = sect->next; - } - hdr[indx].sh_name = bfd_add_to_strtab (abfd, shstrtab, - bfd_section_name (abfd, sect)); - hdr[indx].sh_addr = sect->vma; - hdr[indx].sh_size = sect->_raw_size; - hdr[indx].sh_addralign = 1 << sect->alignment_power; - hdr[indx].sh_flags = 0; - /* these need to be preserved on */ - hdr[indx].sh_link = 0; - hdr[indx].sh_info = 0; - hdr[indx].sh_entsize = 0; - - hdr[indx].sh_type = 0; - if (sect->flags & SEC_RELOC) - { - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - hdr[indx].sh_type = use_rela_p ? SHT_RELA : SHT_REL; - } - - if (sect->flags & SEC_HAS_CONTENTS) - { - hdr[indx].sh_offset = sect->filepos; - hdr[indx].sh_size = sect->_raw_size; - } - if (sect->flags & SEC_ALLOC) - { - hdr[indx].sh_flags |= SHF_ALLOC; - if (sect->flags & SEC_LOAD) - { - /* do something with sh_type ? */ - } - } - if (!(sect->flags & SEC_READONLY)) - hdr[indx].sh_flags |= SHF_WRITE; - - if (sect->flags & SEC_CODE) - hdr[indx].sh_flags |= SHF_EXECINSTR; - - return true; -} -#endif - -/* - Takes a bfd and a symbol, returns a pointer to the elf specific area - of the symbol if there is one. - */ +/* Takes a bfd and a symbol, returns a pointer to the elf specific area + of the symbol if there is one. */ static INLINE elf_symbol_type * DEFUN (elf_symbol_from, (ignore_abfd, symbol), bfd * ignore_abfd AND @@ -1057,13 +1005,10 @@ DEFUN (elf_symbol_from, (ignore_abfd, symbol), return (elf_symbol_type *) symbol; } -/* - Create ELF output from BFD sections. +/* Create ELF output from BFD sections. - Essentially, just create the section header and forget about the program - header for now. - -*/ + Essentially, just create the section header and forget about the program + header for now. */ static void DEFUN (elf_make_sections, (abfd, asect, obj), @@ -1215,11 +1160,6 @@ write_relocs (abfd, sec, xxx) dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type); elf_swap_reloc_out (abfd, &dst_rel, src_rel); - - /* Update the addend -- FIXME add 64 bit support. */ - bfd_put_32 (abfd, ptr->addend, - (unsigned char *) (elf_section_data (sec)->this_hdr.contents) - + dst_rel.r_offset); } } } @@ -1331,6 +1271,7 @@ DEFUN (elf_fake_sections, (abfd, asect, obj), } +#if 0 /* xxxINTERNAL_FUNCTION bfd_elf_locate_sh @@ -1346,11 +1287,11 @@ xxxDESCRIPTION name of a BFD section. */ -static struct elfNAME (internal_shdr) * +static struct elf_internal_shdr * DEFUN (elf_locate_sh, (abfd, strtab, shdrp, name), bfd * abfd AND struct strtab *strtab AND - struct elfNAME (internal_shdr) *shdrp AND + struct elf_internal_shdr *shdrp AND CONST char *name) { Elf_Internal_Shdr *gotit = NULL; @@ -1369,6 +1310,7 @@ DEFUN (elf_locate_sh, (abfd, strtab, shdrp, name), } return gotit; } +#endif /* Map symbol from it's internal number to the external number, moving all local symbols to be at the head of the list. */ @@ -1377,12 +1319,19 @@ static INLINE int sym_is_global (sym) asymbol *sym; { - if (sym->flags & BSF_GLOBAL) + if (sym->flags & (BSF_GLOBAL | BSF_WEAK)) { if (sym->flags & BSF_LOCAL) abort (); return 1; } + if (sym->section == 0) + { + /* Is this valid? */ + abort (); + + return 1; + } if (sym->section == &bfd_und_section) return 1; if (bfd_is_com_section (sym->section)) @@ -1397,12 +1346,14 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) { int symcount = bfd_get_symcount (abfd); asymbol **syms = bfd_get_outsymbols (abfd); + asymbol **sect_syms; int num_locals = 0; int num_globals = 0; int num_locals2 = 0; int num_globals2 = 0; + int max_index = 0; int num_sections = 0; - int *symtab_map; + Elf_Sym_Extra *sym_extra; int idx; asection *asect; @@ -1411,15 +1362,40 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) fflush (stderr); #endif - /* Add local symbols for each allocated section + /* Add local symbols for each allocated section. FIXME -- we should only put out symbols for sections that are actually relocated against. */ for (asect = abfd->sections; asect; asect = asect->next) { - if (/*asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE)*/1) - num_sections++; + if (max_index < asect->index) + max_index = asect->index; } + max_index++; + elf_num_section_syms (abfd) = max_index; + sect_syms = (asymbol **) bfd_zalloc (abfd, max_index * sizeof (asymbol *)); + elf_section_syms (abfd) = sect_syms; + + BFD_ASSERT (sect_syms != 0); + + for (asect = abfd->sections; asect; asect = asect->next) + if ((asect->flags & SEC_ALLOC) && asect->_raw_size > 0) + { + asymbol *sym = bfd_make_empty_symbol (abfd); + sym->the_bfd = abfd; + sym->name = asect->name; + sym->value = asect->vma; + sym->flags = BSF_SECTION_SYM; + sym->section = asect; + sect_syms[asect->index] = sym; + num_sections++; +#ifdef DEBUG + fprintf (stderr, + "creating section symbol, name = %s, value = 0x%.8lx, index = %d, section = 0x%.8lx\n", + asect->name, (long) asect->vma, asect->index, (long) asect); +#endif + } + if (num_sections) { if (syms) @@ -1432,23 +1408,16 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) for (asect = abfd->sections; asect; asect = asect->next) { - if (/* asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE) */ 1) - { - asymbol *sym = syms[symcount++] = bfd_make_empty_symbol (abfd); - sym->the_bfd = abfd; - sym->name = asect->name; - sym->value = asect->vma; - sym->flags = BSF_SECTION_SYM; - sym->section = asect; - } + if (sect_syms[asect->index]) + syms[symcount++] = sect_syms[asect->index]; } syms[symcount] = (asymbol *) 0; bfd_set_symtab (abfd, syms, symcount); } - elf_symtab_map (abfd) = symtab_map - = (int *) bfd_alloc (abfd, symcount * sizeof (int *)); + elf_sym_extra (abfd) = sym_extra + = (Elf_Sym_Extra *) bfd_alloc (abfd, symcount * sizeof (Elf_Sym_Extra)); /* Identify and classify all of the symbols. */ for (idx = 0; idx < symcount; idx++) @@ -1463,10 +1432,11 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) dummy symbol. */ for (idx = 0; idx < symcount; idx++) { + syms[idx]->udata = (PTR) &sym_extra[idx]; if (!sym_is_global (syms[idx])) - symtab_map[idx] = 1 + num_locals2++; + sym_extra[idx].elf_sym_num = 1 + num_locals2++; else - symtab_map[idx] = 1 + num_locals + num_globals2++; + sym_extra[idx].elf_sym_num = 1 + num_locals + num_globals2++; } elf_num_locals (abfd) = num_locals; @@ -1522,183 +1492,6 @@ DEFUN (elf_write_phdrs, (abfd, i_ehdrp, i_phdrp, phdr_cnt), return true; } -#if 0 -static Elf_Internal_Phdr * -DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt), - bfd * abfd AND - Elf_Internal_Ehdr * i_ehdrp AND - Elf_Internal_Shdr * i_shdrp AND - Elf32_Half * phdr_cnt) -{ - Elf_Internal_Phdr *phdr_buf; - int idx; - /* NOTES: - 1. The program header table is *not* loaded as part - of the memory image of the program. If this - changes later, the PT_PHDR entry must come first. - 2. there is currently no support for program header - entries of type PT_PHDR, PT_DYNAMIC, PT_INTERP, - or PT_SHLIB. */ - - /* A. Figure out how many program header table entries are needed - 1. PT_LOAD for the text segment - 2. PT_LOAD for the data segment - Then, reserve space for one more pointer. This will be NULL - to indicate the end of the program header table. */ - -#ifdef PHDRS_INCLUDED - *phdr_cnt = 4; -#else - /* XXX right now, execve() expects exactly 3 PT entries on HPPA-OSF. */ - *phdr_cnt = 3; -#endif - - phdr_buf = (Elf_Internal_Phdr *) bfd_xmalloc (((*phdr_cnt) + 1) - * - sizeof (Elf_Internal_Phdr)); - - idx = 0; -#ifdef PHDRS_INCLUDED - /* B. Fill in the PT_PHDR entry. */ - - idx++; -#endif - - /* C. Fill in the PT_LOAD entry for the text segment. */ - - phdr_buf[idx].p_type = PT_LOAD; - - /* get virtual/physical address from .text section */ - phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".text")->vma; - phdr_buf[idx].p_paddr = 0; /* XXX */ - - /* Ultimately, we would like the size of the .text load - segment to be the sum of the following sections: - the program header table itself - .interp - .hash - .dynsym - .dynstr - .rela.bss - .rela.plt - .init - .text - .fini - .rodata - But, right now, it will be the sum of the following sections: - .text - .rodata */ - - { - static char *CONST ld_sect_names[] = - {".text", ".rodata", NULL}; - int i; - int ld_size = 0; - - for (i = 0; ld_sect_names[i]; i++) - { - asection *asect = bfd_get_section_by_name (abfd, - ld_sect_names[i]); - - if (asect) - ld_size += bfd_section_size (abfd, asect); - } - phdr_buf[idx].p_filesz = ld_size; - /* XXX: need to fix this */ - phdr_buf[idx].p_memsz = ld_size; - } - phdr_buf[idx].p_flags = PF_R + PF_X; - phdr_buf[idx].p_align = - bfd_get_section_by_name (abfd, ".text")->alignment_power; - - idx++; - - /* D. Fill in the PT_LOAD entry for the data segment. */ - - phdr_buf[idx].p_type = PT_LOAD; - - /* get virtual/physical address from .data section */ - phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".data")->vma; - phdr_buf[idx].p_paddr = 0; /* XXX */ - - /* Ultimately, we would like the size of the data load segment - to be the sum of the following sections: - the PT_DYNAMIC program header table entry - .plt - .data - .data1 - .got - .dynamic - But, right now, it will be the sum of the following sections: - .data */ - - { - static char *CONST ld_sect_names[] = - {".data", NULL}; - int i; - int ld_size = 0; - - for (i = 0; ld_sect_names[i]; i++) - { - asection *asect = bfd_get_section_by_name (abfd, - ld_sect_names[i]); - - if (asect) - ld_size += bfd_section_size (abfd, asect); - } - phdr_buf[idx].p_filesz = ld_size; - /* XXX: need to fix this */ - phdr_buf[idx].p_memsz = ld_size; - } - phdr_buf[idx].p_flags = PF_R + PF_W + PF_X; - phdr_buf[idx].p_align - = bfd_get_section_by_name (abfd, ".data")->alignment_power; - - idx++; - - /* E. Fill in the PT_LOAD entry for the bss segment. */ - - phdr_buf[idx].p_type = PT_LOAD; - - /* get virtual/physical address from .data section */ - phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".bss")->vma; - phdr_buf[idx].p_paddr = 0; /* XXX */ - - { - static char *CONST ld_sect_names[] = - {".bss", NULL}; - int i; - int ld_size = 0; - - for (i = 0; ld_sect_names[i]; i++) - { - asection *asect = bfd_get_section_by_name (abfd, - ld_sect_names[i]); - - if (asect) - ld_size += bfd_section_size (abfd, asect); - } - phdr_buf[idx].p_filesz = 0; - /* XXX: need to fix this */ - phdr_buf[idx].p_memsz = ld_size; - } - phdr_buf[idx].p_flags = PF_R + PF_W + PF_X; - phdr_buf[idx].p_align - = bfd_get_section_by_name (abfd, ".bss")->alignment_power; - - idx++; - - /* F. Set up the "end of program header table" sentinel. */ - - memset ((char *) (phdr_buf + idx), 0, sizeof (Elf_Internal_Phdr)); - idx++; - - BFD_ASSERT (idx - 1 == *phdr_cnt); - - return phdr_buf; -} -#endif - static const Elf_Internal_Shdr null_shdr; /* Assign all ELF section numbers. The dummy first section is handled here @@ -2287,33 +2080,33 @@ swap_out_syms (abfd) sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE); else if (syms[idx]->section == &bfd_und_section) sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE); - else if (syms[idx]->flags & BSF_WEAK) - sym.st_info = ELF_ST_INFO (STB_WEAK, STT_OBJECT); else if (syms[idx]->flags & BSF_SECTION_SYM) sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); else if (syms[idx]->flags & BSF_FILE) sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); - else if (syms[idx]->flags & (BSF_GLOBAL | BSF_EXPORT)) - { - if (syms[idx]->flags & BSF_FUNCTION) - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); - else - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT); - } - else if (syms[idx]->flags & BSF_LOCAL) - { - if (syms[idx]->flags & BSF_FUNCTION) - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC); - else - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT); - } else - /* Default to local if flag isn't set at all. */ - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT); + { + int bind = STB_LOCAL; + int type = STT_OBJECT; + unsigned int flags = syms[idx]->flags; + + if (flags & BSF_LOCAL) + bind = STB_LOCAL; + else if (flags & BSF_WEAK) + bind = STB_WEAK; + else if (flags & BSF_GLOBAL) + bind = STB_GLOBAL; + + if (flags & BSF_FUNCTION) + type = STT_FUNC; + + sym.st_info = ELF_ST_INFO (bind, type); + } sym.st_other = 0; elf_swap_symbol_out (abfd, &sym, - outbound_syms + elf_symtab_map (abfd)[idx]); + (outbound_syms + + elf_sym_extra (abfd)[idx].elf_sym_num)); } symtab_hdr->contents = (PTR) outbound_syms; @@ -2537,85 +2330,31 @@ DEFUN (elf_symbol_from_bfd_symbol, (abfd, asym_ptr_ptr), CONST char *name = asym_ptr->name; int idx; int symcount = bfd_get_symcount (abfd); + flagword flags = asym_ptr->flags; asymbol **syms = bfd_get_outsymbols (abfd); - /* FIXME -- there has to be a better way than linear search. */ - for (idx = 0; idx < symcount; idx++) + /* When gas creates relocations against local labels, it creates its + own symbol for the section, but does put the symbol into the + symbol chain, so udata is 0. */ + if (asym_ptr->udata == (PTR) 0 + && (flags & BSF_SECTION_SYM) + && asym_ptr->section + && elf_section_syms (abfd)[asym_ptr->section->index]) + asym_ptr->udata = elf_section_syms (abfd)[asym_ptr->section->index]->udata; + + if (asym_ptr->udata) + idx = ((Elf_Sym_Extra *)asym_ptr->udata)->elf_sym_num; + else { - if (syms[idx] == asym_ptr - || (name == syms[idx]->name && name) - || ((asym_ptr->flags & BSF_SECTION_SYM) - && (syms[idx]->flags & BSF_SECTION_SYM) - && asym_ptr->section == syms[idx]->section)) - break; - } - - if (idx >= symcount) - { - /* badness... */ - fprintf (stderr, "bfd app err: can't find sym `%s' in symtab\n", - name); abort (); } - idx = elf_symtab_map (abfd)[idx]; #if DEBUG & 4 { - flagword flags = asym_ptr->flags; fprintf (stderr, - "elfsym<-bfdsym %.8lx `%s' sec=%s symnum=%d {", - (long) asym_ptr, asym_ptr->name, asym_ptr->section->name, idx); - - if (flags == BSF_NO_FLAGS) - fprintf (stderr, " none"); - - if (flags & BSF_LOCAL) - fprintf (stderr, " local"); - - if (flags & BSF_GLOBAL) - fprintf (stderr, " global"); - - if (flags & BSF_EXPORT) - fprintf (stderr, " export"); - - if (flags & BSF_DEBUGGING) - fprintf (stderr, " debugging"); - - if (flags & BSF_KEEP) - fprintf (stderr, " keep"); - - if (flags & BSF_KEEP_G) - fprintf (stderr, " keep_g"); - - if (flags & BSF_WEAK) - fprintf (stderr, " weak"); - - if (flags & BSF_SECTION_SYM) - fprintf (stderr, " section_sym"); - - if (flags & BSF_OLD_COMMON) - fprintf (stderr, " old_common"); - - if (flags & BSF_NOT_AT_END) - fprintf (stderr, " not_at_end"); - - if (flags & BSF_CONSTRUCTOR) - fprintf (stderr, " constructor"); - - if (flags & BSF_WARNING) - fprintf (stderr, " warning"); - - if (flags & BSF_INDIRECT) - fprintf (stderr, " indirect"); - - if (flags & BSF_FILE) - fprintf (stderr, " file"); - - if (flags & BSF_FUNCTION) - fprintf (stderr, " function"); - - fputs (" }\n", stderr); + "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx %s\n", + (long) asym_ptr, asym_ptr->name, idx, flags, elf_symbol_flags (flags)); fflush (stderr); } #endif @@ -2722,7 +2461,7 @@ DEFUN (elf_slurp_symbol_table, (abfd, symptrs), sym->symbol.flags |= BSF_LOCAL; break; case STB_GLOBAL: - sym->symbol.flags |= (BSF_GLOBAL | BSF_EXPORT); + sym->symbol.flags |= BSF_GLOBAL; break; case STB_WEAK: sym->symbol.flags |= BSF_WEAK; @@ -2743,7 +2482,7 @@ DEFUN (elf_slurp_symbol_table, (abfd, symptrs), } /* Is this a definition of $global$? If so, keep it because it will be - needd if any relocations are performed. */ + needed if any relocations are performed. */ if (!strcmp (sym->symbol.name, "$global$") && sym->symbol.section != &bfd_und_section) { @@ -2853,7 +2592,6 @@ DEFUN (elf_slurp_reloca_table, (abfd, asect, symbols), for (idx = 0; idx < asect->reloc_count; idx++) { -#ifdef RELOC_PROCESSING Elf_Internal_Rela dst; Elf_External_Rela *src; @@ -2861,16 +2599,9 @@ DEFUN (elf_slurp_reloca_table, (abfd, asect, symbols), src = native_relocs + idx; elf_swap_reloca_in (abfd, src, &dst); +#ifdef RELOC_PROCESSING RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect); #else - Elf_Internal_Rela dst; - Elf_External_Rela *src; - - cache_ptr = reloc_cache + idx; - src = native_relocs + idx; - - elf_swap_reloca_in (abfd, src, &dst); - if (asect->flags & SEC_RELOC) { /* relocatable, so the offset is off of the section */ @@ -2889,7 +2620,12 @@ DEFUN (elf_slurp_reloca_table, (abfd, asect, symbols), BFD section symbol. */ asymbol *s = *(cache_ptr->sym_ptr_ptr); if (s->flags & BSF_SECTION_SYM) - cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr; + { + cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr; + s = *cache_ptr->sym_ptr_ptr; + if (s->name == 0 || s->name[0] == 0) + abort (); + } } cache_ptr->addend = dst.r_addend; @@ -3029,17 +2765,22 @@ DEFUN (elf_slurp_reloc_table, (abfd, asect, symbols), cache_ptr->address = dst.r_offset; } /* ELF_R_SYM(dst.r_info) is the symbol table offset... - -1 is to skip the dummy symbol table entry */ + -1 is to skip the dummy symbol table entry */ cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1; + { + /* Is it an ELF section symbol? If so, translate it into a + BFD section symbol. */ + asymbol *s = *(cache_ptr->sym_ptr_ptr); + if (s->flags & BSF_SECTION_SYM) + { + cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr; + s = *cache_ptr->sym_ptr_ptr; + if (s->name == 0 || s->name[0] == 0) + abort (); + } + } BFD_ASSERT (dst.r_offset <= data_max); - if (bfd_seek (abfd, data_off + dst.r_offset, SEEK_SET) != 0 - || bfd_read ((PTR) buf, sizeof (buf), 1, abfd) != sizeof (buf)) - { - bfd_error = system_call_error; - return false; - } - - cache_ptr->addend = (*abfd->xvec->bfd_getx_signed_32) ((bfd_byte *) buf); + cache_ptr->addend = 0; /* Fill in the cache_ptr->howto field from dst.r_type */ { diff --git a/bfd/libelf.h b/bfd/libelf.h index 1f0f1a5078..f5bc2c88f4 100644 --- a/bfd/libelf.h +++ b/bfd/libelf.h @@ -98,6 +98,13 @@ struct elf_backend_data PTR global_sym; }; +struct elf_sym_extra +{ + int elf_sym_num; /* sym# after locals/globals are reordered */ +}; + +typedef struct elf_sym_extra Elf_Sym_Extra; + struct bfd_elf_arch_map { enum bfd_architecture bfd_arch; int elf_arch; @@ -139,11 +146,12 @@ struct elf_obj_tdata struct strtab *strtab_ptr; int num_locals; int num_globals; - int *symtab_map; PTR raw_syms; /* Elf_External_Sym* */ Elf_Internal_Sym *internal_syms; PTR symbols; /* elf_symbol_type */ -/* struct strtab *shstrtab;*/ + Elf_Sym_Extra *sym_extra; + asymbol **section_syms; /* STT_SECTION symbols for each section */ + int num_section_syms; /* number of section_syms allocated */ Elf_Internal_Shdr symtab_hdr; Elf_Internal_Shdr shstrtab_hdr; Elf_Internal_Shdr strtab_hdr; @@ -160,7 +168,9 @@ struct elf_obj_tdata #define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) #define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals) #define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals) -#define elf_symtab_map(bfd) (elf_tdata(bfd) -> symtab_map) +#define elf_sym_extra(bfd) (elf_tdata(bfd) -> sym_extra) +#define elf_section_syms(bfd) (elf_tdata(bfd) -> section_syms) +#define elf_num_section_syms(bfd) (elf_tdata(bfd) -> num_section_syms) #define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo) #define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus) #define obj_symbols(bfd) ((elf_symbol_type*)(elf_tdata(bfd) -> symbols))