- /* If the backend has a special mapping, use it. */
- if (get_elf_backend_data (abfd)->elf_backend_sym_is_global)
- return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global)
- (abfd, sym));
-
- 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 (bfd_is_und_section (sym->section))
- return 1;
- if (bfd_is_com_section (sym->section))
- return 1;
- if (sym->flags & (BSF_LOCAL | BSF_SECTION_SYM | BSF_FILE))
- return 0;
- return 0;
-}
-
-static boolean
-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;
- Elf_Sym_Extra *sym_extra;
- int idx;
- asection *asect;
-
-#ifdef DEBUG
- fprintf (stderr, "elf_map_symbols\n");
- fflush (stderr);
-#endif
-
- /* Add local symbols for each section for which there are relocs.
- FIXME: How can we tell which sections have relocs at this point?
- Will reloc_count always be accurate? Actually, I think most ELF
- targets create section symbols for all sections anyhow. */
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- 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;
-
- if (sect_syms == 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- asymbol *sym = bfd_make_empty_symbol (abfd);
- if (!sym)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- 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)
- syms = (asymbol **) bfd_realloc (abfd, syms,
- ((symcount + num_sections + 1)
- * sizeof (asymbol *)));
- else
- syms = (asymbol **) bfd_alloc (abfd,
- (num_sections + 1) * sizeof (asymbol *));
- if (!syms)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- if (sect_syms[asect->index])
- syms[symcount++] = sect_syms[asect->index];
- }
-
- syms[symcount] = (asymbol *) 0;
- bfd_set_symtab (abfd, syms, symcount);
- }
-
- elf_sym_extra (abfd) = sym_extra
- = (Elf_Sym_Extra *) bfd_alloc (abfd, symcount * sizeof (Elf_Sym_Extra));
- if (!sym_extra)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* Identify and classify all of the symbols. */
- for (idx = 0; idx < symcount; idx++)
- {
- if (!sym_is_global (abfd, syms[idx]))
- num_locals++;
- else
- num_globals++;
- }
-
- /* Now provide mapping information. Add +1 for skipping over the
- dummy symbol. */
- for (idx = 0; idx < symcount; idx++)
- {
- syms[idx]->udata = (PTR) & sym_extra[idx];
- if (!sym_is_global (abfd, syms[idx]))
- sym_extra[idx].elf_sym_num = 1 + num_locals2++;
- else
- sym_extra[idx].elf_sym_num = 1 + num_locals + num_globals2++;
- }
-
- elf_num_locals (abfd) = num_locals;
- elf_num_globals (abfd) = num_globals;
- return true;
-}
-
-/* Compute the file positions we are going to put the sections at, and
- otherwise prepare to begin writing out the ELF file. If LINK_INFO
- is not NULL, this is being called by the ELF backend linker. */
-
-static boolean
-elf_compute_section_file_positions (abfd, link_info)
- bfd *abfd;
- struct bfd_link_info *link_info;
-{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- Elf_Internal_Shdr *shstrtab_hdr;
-
- if (abfd->output_has_begun)
- return true;
-
- /* Do any elf backend specific processing first. */
- if (bed->elf_backend_begin_write_processing)
- (*bed->elf_backend_begin_write_processing) (abfd, link_info);
-
- if (! prep_headers (abfd))
- return false;
-
- bfd_map_over_sections (abfd, elf_fake_sections, 0);
-
- if (!assign_section_numbers (abfd))
- return false;
-
- /* The backend linker builds symbol table information itself. */
- if (link_info == NULL)
- {
- if (! swap_out_syms (abfd))
- return false;
- }
-
- shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
- /* sh_name was set in prep_headers. */
- shstrtab_hdr->sh_type = SHT_STRTAB;
- shstrtab_hdr->sh_flags = 0;
- shstrtab_hdr->sh_addr = 0;
- shstrtab_hdr->sh_size = elf_shstrtab (abfd)->length;
- shstrtab_hdr->sh_entsize = 0;
- shstrtab_hdr->sh_link = 0;
- shstrtab_hdr->sh_info = 0;
- /* sh_offset is set in assign_file_positions_for_symtabs_and_strtabs. */
- shstrtab_hdr->sh_addralign = 1;
- shstrtab_hdr->contents = (PTR) elf_shstrtab (abfd)->tab;
-
- if (!assign_file_positions_except_relocs (abfd,
- link_info == NULL ? true : false))
- return false;
-
- abfd->output_has_begun = true;
-
- return true;
-}
-
-
-/* Align to the maximum file alignment that could be required for any
- ELF data structure. */
-
-static INLINE file_ptr
-align_file_position (off)
- file_ptr off;
-{
- return (off + FILE_ALIGN - 1) & ~(FILE_ALIGN - 1);
-}
-
-/* Assign a file position to a section, optionally aligning to the
- required section alignment. */
-
-static INLINE file_ptr
-assign_file_position_for_section (i_shdrp, offset, align)
- Elf_Internal_Shdr *i_shdrp;
- file_ptr offset;
- boolean align;
-{
- if (align)
- {
- unsigned int al;
-
- al = i_shdrp->sh_addralign;
- if (al > 1)
- offset = BFD_ALIGN (offset, al);
- }
- i_shdrp->sh_offset = offset;
- if (i_shdrp->rawdata != NULL)
- ((asection *) i_shdrp->rawdata)->filepos = offset;
- if (i_shdrp->sh_type != SHT_NOBITS)
- offset += i_shdrp->sh_size;
- 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. */
-
-static bfd_size_type
-get_program_header_size (abfd)
- bfd *abfd;
-{
- size_t segs;
- asection *s;
-
- /* 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)
- {
- /* If we have a loadable interpreter section, we need a
- PT_INTERP segment. In this case, assume we also need a
- PT_PHDR segment, although that may not be true for all
- targets. */
- segs += 2;
- }
-
- if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
- {
- /* We need a PT_DYNAMIC segment. */
- ++segs;
- }
-
- return segs * sizeof (Elf_External_Phdr);
-}
-
-/* Create the program header. OFF is the file offset where the
- program header should be written. FIRST is the first loadable ELF
- section. PHDR_SIZE is the size of the program header as returned
- by get_program_header_size. */
-
-static file_ptr
-map_program_segments (abfd, off, first, phdr_size)
- bfd *abfd;
- file_ptr off;
- Elf_Internal_Shdr *first;
- bfd_size_type phdr_size;
-{
- Elf_Internal_Phdr phdrs[10];
- unsigned int phdr_count;
- Elf_Internal_Phdr *phdr;
- int phdr_size_adjust;
- unsigned int i;
- Elf_Internal_Shdr **hdrpp;
- asection *sinterp, *sdyn;
- unsigned int last_type;
- Elf_Internal_Ehdr *i_ehdrp;
-
- BFD_ASSERT ((abfd->flags & (EXEC_P | DYNAMIC)) != 0);
- BFD_ASSERT (phdr_size / sizeof (Elf_Internal_Phdr)
- <= sizeof phdrs / sizeof (phdrs[0]));
-
- phdr_count = 0;
- phdr = phdrs;
-
- phdr_size_adjust = 0;
-
- /* If we have a loadable .interp section, we must create a PT_INTERP
- segment which must precede all PT_LOAD segments. We assume that
- we must also create a PT_PHDR segment, although that may not be
- true for all targets. */
- sinterp = bfd_get_section_by_name (abfd, ".interp");
- if (sinterp != NULL && (sinterp->flags & SEC_LOAD) != 0)
- {
- BFD_ASSERT (first != NULL);
-
- phdr->p_type = PT_PHDR;
-
- phdr->p_offset = off;
-
- /* Account for any adjustment made because of the alignment of
- the first loadable section. */
- phdr_size_adjust = (first->sh_offset - phdr_size) - off;
- BFD_ASSERT (phdr_size_adjust >= 0 && phdr_size_adjust < 128);
-
- /* The program header precedes all loadable sections. This lets
- us compute its loadable address. This depends on the linker
- script. */
- phdr->p_vaddr = first->sh_addr - (phdr_size + phdr_size_adjust);
-
- phdr->p_paddr = 0;
- phdr->p_filesz = phdr_size;
- phdr->p_memsz = phdr_size;
-
- /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
- phdr->p_flags = PF_R | PF_X;
-
- phdr->p_align = FILE_ALIGN;
- BFD_ASSERT ((phdr->p_vaddr - phdr->p_offset) % FILE_ALIGN == 0);
-
- /* Include the ELF header in the first loadable segment. */
- phdr_size_adjust += off;
-
- ++phdr_count;
- ++phdr;
-
- phdr->p_type = PT_INTERP;
- phdr->p_offset = sinterp->filepos;
- phdr->p_vaddr = sinterp->vma;
- phdr->p_paddr = 0;
- phdr->p_filesz = sinterp->_raw_size;
- phdr->p_memsz = sinterp->_raw_size;
- phdr->p_flags = PF_R;
- phdr->p_align = 1 << bfd_get_section_alignment (abfd, sinterp);
-
- ++phdr_count;
- ++phdr;
- }
-
- /* Look through the sections to see how they will be divided into
- program segments. The sections must be arranged in order by
- sh_addr for this to work correctly. */
- phdr->p_type = PT_NULL;
- last_type = SHT_PROGBITS;
- for (i = 1, hdrpp = elf_elfsections (abfd) + 1;
- i < elf_elfheader (abfd)->e_shnum;
- 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;
-
- /* If this section fits in the segment we are constructing, add
- it in. */
- if (phdr->p_type != PT_NULL
- && (hdr->sh_offset - (phdr->p_offset + phdr->p_memsz)
- == hdr->sh_addr - (phdr->p_vaddr + phdr->p_memsz))
- && (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS))
- {
- bfd_size_type adjust;
-
- adjust = hdr->sh_addr - (phdr->p_vaddr + phdr->p_memsz);
- phdr->p_memsz += hdr->sh_size + adjust;
- if (hdr->sh_type != SHT_NOBITS)
- phdr->p_filesz += hdr->sh_size + adjust;
- if ((hdr->sh_flags & SHF_WRITE) != 0)
- phdr->p_flags |= PF_W;
- if ((hdr->sh_flags & SHF_EXECINSTR) != 0)
- phdr->p_flags |= PF_X;
- last_type = hdr->sh_type;
- continue;
- }
-
- /* If we have a segment, move to the next one. */
- if (phdr->p_type != PT_NULL)
- {
- ++phdr;
- ++phdr_count;
- }
-
- /* Start a new segment. */
- phdr->p_type = PT_LOAD;
- phdr->p_offset = hdr->sh_offset;
- phdr->p_vaddr = hdr->sh_addr;
- phdr->p_paddr = 0;
- if (hdr->sh_type == SHT_NOBITS)
- phdr->p_filesz = 0;
- else
- phdr->p_filesz = hdr->sh_size;
- phdr->p_memsz = hdr->sh_size;
- phdr->p_flags = PF_R;
- if ((hdr->sh_flags & SHF_WRITE) != 0)
- phdr->p_flags |= PF_W;
- if ((hdr->sh_flags & SHF_EXECINSTR) != 0)
- phdr->p_flags |= PF_X;
- phdr->p_align = get_elf_backend_data (abfd)->maxpagesize;
-
- if (hdr == first
- && sinterp != NULL
- && (sinterp->flags & SEC_LOAD) != 0)
- {
- phdr->p_offset -= phdr_size + phdr_size_adjust;
- phdr->p_vaddr -= phdr_size + phdr_size_adjust;
- phdr->p_filesz += phdr_size + phdr_size_adjust;
- phdr->p_memsz += phdr_size + phdr_size_adjust;
- }
-
- last_type = hdr->sh_type;
- }
-
- if (phdr->p_type != PT_NULL)
- {
- ++phdr;
- ++phdr_count;
- }
-
- /* If we have a .dynamic section, create a PT_DYNAMIC segment. */
- sdyn = bfd_get_section_by_name (abfd, ".dynamic");
- if (sdyn != NULL && (sdyn->flags & SEC_LOAD) != 0)
- {
- phdr->p_type = PT_DYNAMIC;
- phdr->p_offset = sdyn->filepos;
- phdr->p_vaddr = sdyn->vma;
- phdr->p_paddr = 0;
- phdr->p_filesz = sdyn->_raw_size;
- phdr->p_memsz = sdyn->_raw_size;
- phdr->p_flags = PF_R;
- if ((sdyn->flags & SEC_READONLY) == 0)
- phdr->p_flags |= PF_W;
- if ((sdyn->flags & SEC_CODE) != 0)
- phdr->p_flags |= PF_X;
- phdr->p_align = 1 << bfd_get_section_alignment (abfd, sdyn);
-
- ++phdr;
- ++phdr_count;
- }
-
- /* Make sure the return value from get_program_header_size matches
- what we computed here. Actually, it's OK if we allocated too
- much space in the program header. */
- if (phdr_count > phdr_size / sizeof (Elf_External_Phdr))
- abort ();
-
- /* Set up program header information. */
- i_ehdrp = elf_elfheader (abfd);
- i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
- i_ehdrp->e_phoff = off;
- i_ehdrp->e_phnum = phdr_count;
-
- /* Save the program headers away. I don't think anybody uses this
- information right now. */
- elf_tdata (abfd)->phdr = ((Elf_Internal_Phdr *)
- bfd_alloc (abfd,
- (phdr_count
- * sizeof (Elf_Internal_Phdr))));
- if (elf_tdata (abfd)->phdr == NULL && phdr_count != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return (file_ptr) -1;
- }
- memcpy (elf_tdata (abfd)->phdr, phdrs,
- phdr_count * sizeof (Elf_Internal_Phdr));
-
- /* Write out the program headers. */
- if (bfd_seek (abfd, off, SEEK_SET) != 0)
- return (file_ptr) -1;
-
- for (i = 0, phdr = phdrs; i < phdr_count; i++, phdr++)
- {
- Elf_External_Phdr extphdr;
-
- elf_swap_phdr_out (abfd, phdr, &extphdr);
- if (bfd_write (&extphdr, sizeof (Elf_External_Phdr), 1, abfd)
- != sizeof (Elf_External_Phdr))
- return (file_ptr) -1;
- }
-
- return off + phdr_count * sizeof (Elf_External_Phdr);
-}
-
-/* Work out the file positions of all the sections. This is called by
- elf_compute_section_file_positions. All the section sizes and VMAs
- must be known before this is called.
-
- We do not consider reloc sections at this point, unless they form
- part of the loadable image. Reloc sections are assigned file
- positions in assign_file_positions_for_relocs, which is called by
- write_object_contents and final_link.
-
- If DOSYMS is false, we do not assign file positions for the symbol
- table or the string table. */
-
-static boolean
-assign_file_positions_except_relocs (abfd, dosyms)
- bfd *abfd;
- boolean dosyms;
-{
- struct elf_obj_tdata * const tdata = elf_tdata (abfd);
- Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd);
- Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
- file_ptr off;
-
- /* Start after the ELF header. */
- off = i_ehdrp->e_ehsize;
-
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- {
- Elf_Internal_Shdr **hdrpp;
- unsigned int i;
-
- /* We are not creating an executable, which means that we are
- not creating a program header, and that the actual order of
- the sections in the file is unimportant. */
- for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
- {
- Elf_Internal_Shdr *hdr;
-
- hdr = *hdrpp;
- 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);
- }
- }
- else
- {
- file_ptr phdr_off;
- bfd_size_type phdr_size;
- bfd_vma maxpagesize;
- Elf_Internal_Shdr **hdrpp;
- unsigned int i;
- 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;
-
- maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
- 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. */
-
- /* 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++)
- {
- Elf_Internal_Shdr *hdr;
-
- hdr = *hdrpp;
- if ((hdr->sh_flags & SHF_ALLOC) == 0)
- continue;
-
- 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;
-
- 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;
- BFD_ASSERT (phdr_map <= phdr_off + phdr_size);
- }
-
- /* Place the section headers. */
- off = align_file_position (off);
- i_ehdrp->e_shoff = off;
- off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
-
- elf_tdata (abfd)->next_file_pos = off;
-
- return true;
-}
-
-static boolean
-prep_headers (abfd)
- bfd *abfd;
-{
- Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
- Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
- int count;
- struct strtab *shstrtab;
-
- i_ehdrp = elf_elfheader (abfd);
- i_shdrp = elf_elfsections (abfd);
-
- shstrtab = bfd_new_strtab (abfd);
- if (!shstrtab)
- return false;
-
- elf_shstrtab (abfd) = shstrtab;
-
- i_ehdrp->e_ident[EI_MAG0] = ELFMAG0;
- i_ehdrp->e_ident[EI_MAG1] = ELFMAG1;
- i_ehdrp->e_ident[EI_MAG2] = ELFMAG2;
- i_ehdrp->e_ident[EI_MAG3] = ELFMAG3;
-
- i_ehdrp->e_ident[EI_CLASS] = ELFCLASS;
- i_ehdrp->e_ident[EI_DATA] =
- abfd->xvec->byteorder_big_p ? ELFDATA2MSB : ELFDATA2LSB;
- i_ehdrp->e_ident[EI_VERSION] = EV_CURRENT;
-
- for (count = EI_PAD; count < EI_NIDENT; count++)
- i_ehdrp->e_ident[count] = 0;
-
- if ((abfd->flags & DYNAMIC) != 0)
- i_ehdrp->e_type = ET_DYN;
- else if ((abfd->flags & EXEC_P) != 0)
- i_ehdrp->e_type = ET_EXEC;
- else
- i_ehdrp->e_type = ET_REL;
-
- switch (bfd_get_arch (abfd))
- {
- case bfd_arch_unknown:
- i_ehdrp->e_machine = EM_NONE;
- break;
- case bfd_arch_sparc:
-#if ARCH_SIZE == 64
- i_ehdrp->e_machine = EM_SPARC64;
-#else
- i_ehdrp->e_machine = EM_SPARC;
-#endif
- break;
- case bfd_arch_i386:
- i_ehdrp->e_machine = EM_386;
- break;
- case bfd_arch_m68k:
- i_ehdrp->e_machine = EM_68K;
- break;
- case bfd_arch_m88k:
- i_ehdrp->e_machine = EM_88K;
- break;
- case bfd_arch_i860:
- i_ehdrp->e_machine = EM_860;
- break;
- case bfd_arch_mips: /* MIPS Rxxxx */
- i_ehdrp->e_machine = EM_MIPS; /* only MIPS R3000 */
- break;
- case bfd_arch_hppa:
- i_ehdrp->e_machine = EM_PARISC;
- break;
- case bfd_arch_powerpc:
- i_ehdrp->e_machine = EM_CYGNUS_POWERPC;
- break;
- /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
- default:
- i_ehdrp->e_machine = EM_NONE;
- }
- i_ehdrp->e_version = EV_CURRENT;
- i_ehdrp->e_ehsize = sizeof (Elf_External_Ehdr);
-
- /* no program header, for now. */
- i_ehdrp->e_phoff = 0;
- i_ehdrp->e_phentsize = 0;
- i_ehdrp->e_phnum = 0;
-
- /* each bfd section is section header entry */
- i_ehdrp->e_entry = bfd_get_start_address (abfd);
- i_ehdrp->e_shentsize = sizeof (Elf_External_Shdr);
-
- /* if we're building an executable, we'll need a program header table */
- if (abfd->flags & EXEC_P)
- {
- /* it all happens later */
-#if 0
- i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
-
- /* elf_build_phdrs() returns a (NULL-terminated) array of
- Elf_Internal_Phdrs */
- i_phdrp = elf_build_phdrs (abfd, i_ehdrp, i_shdrp, &i_ehdrp->e_phnum);
- i_ehdrp->e_phoff = outbase;
- outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum;
-#endif
- }
- else
- {
- i_ehdrp->e_phentsize = 0;
- i_phdrp = 0;
- i_ehdrp->e_phoff = 0;
- }
-
- elf_tdata (abfd)->symtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
- ".symtab");
- elf_tdata (abfd)->strtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
- ".strtab");
- elf_tdata (abfd)->shstrtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
- ".shstrtab");
- if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
- || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
- || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
- return false;
-
- return true;
-}
-
-static boolean
-swap_out_syms (abfd)
- bfd *abfd;
-{
- if (!elf_map_symbols (abfd))
- return false;
-
- /* Dump out the symtabs. */
- {
- int symcount = bfd_get_symcount (abfd);
- asymbol **syms = bfd_get_outsymbols (abfd);
- struct strtab *stt = bfd_new_strtab (abfd);
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
- Elf_External_Sym *outbound_syms;
- int idx;
-
- if (!stt)
- return false;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- symtab_hdr->sh_type = SHT_SYMTAB;
- 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;
-
- symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
- symstrtab_hdr->sh_type = SHT_STRTAB;
-
- outbound_syms = (Elf_External_Sym *)
- bfd_alloc (abfd, (1 + symcount) * sizeof (Elf_External_Sym));
- if (!outbound_syms)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- /* now generate the data (for "contents") */
- {
- /* Fill in zeroth symbol and swap it out. */
- Elf_Internal_Sym sym;
- sym.st_name = 0;
- sym.st_value = 0;
- sym.st_size = 0;
- sym.st_info = 0;
- sym.st_other = 0;
- sym.st_shndx = SHN_UNDEF;
- elf_swap_symbol_out (abfd, &sym, outbound_syms);
- }
- for (idx = 0; idx < symcount; idx++)
- {
- Elf_Internal_Sym sym;
- bfd_vma value = syms[idx]->value;
- elf_symbol_type *type_ptr;
-
- if (syms[idx]->flags & BSF_SECTION_SYM)
- /* Section symbols have no names. */
- sym.st_name = 0;
- else
- {
- sym.st_name = bfd_add_to_strtab (abfd, stt, syms[idx]->name);
- if (sym.st_name == (unsigned long) -1)
- return false;
- }
-
- type_ptr = elf_symbol_from (abfd, syms[idx]);
-
- if (bfd_is_com_section (syms[idx]->section))
- {
- /* ELF common symbols put the alignment into the `value' field,
- and the size into the `size' field. This is backwards from
- how BFD handles it, so reverse it here. */
- sym.st_size = value;
- sym.st_value = type_ptr ? type_ptr->internal_elf_sym.st_value : 16;
- sym.st_shndx = elf_section_from_bfd_section (abfd,
- syms[idx]->section);
- }
- else
- {
- asection *sec = syms[idx]->section;
- int shndx;
-
- if (sec->output_section)
- {
- value += sec->output_offset;
- sec = sec->output_section;
- }
- value += sec->vma;
- sym.st_value = value;
- sym.st_size = type_ptr ? type_ptr->internal_elf_sym.st_size : 0;
- sym.st_shndx = shndx = elf_section_from_bfd_section (abfd, sec);
- if (shndx == -1)
- {
- asection *sec2;
- /* Writing this would be a hell of a lot easier if we had
- some decent documentation on bfd, and knew what to expect
- of the library, and what to demand of applications. For
- example, it appears that `objcopy' might not set the
- section of a symbol to be a section that is actually in
- the output file. */
- sec2 = bfd_get_section_by_name (abfd, sec->name);
- BFD_ASSERT (sec2 != 0);
- sym.st_shndx = shndx = elf_section_from_bfd_section (abfd, sec2);
- BFD_ASSERT (shndx != -1);
- }
- }
-
- if (bfd_is_com_section (syms[idx]->section))
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT);
- else if (bfd_is_und_section (syms[idx]->section))
- sym.st_info = ELF_ST_INFO (STB_GLOBAL,
- ((syms[idx]->flags & BSF_FUNCTION)
- ? STT_FUNC
- : STT_NOTYPE));
- 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
- {
- 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_sym_extra (abfd)[idx].elf_sym_num));
- }
-
- symtab_hdr->contents = (PTR) outbound_syms;
- symstrtab_hdr->contents = (PTR) stt->tab;
- symstrtab_hdr->sh_size = stt->length;
- symstrtab_hdr->sh_type = SHT_STRTAB;
-
- symstrtab_hdr->sh_flags = 0;
- symstrtab_hdr->sh_addr = 0;
- symstrtab_hdr->sh_entsize = 0;
- symstrtab_hdr->sh_link = 0;
- symstrtab_hdr->sh_info = 0;
- symstrtab_hdr->sh_addralign = 1;
- symstrtab_hdr->size = 0;
- }
-
- return true;
-}
-
-static boolean
-write_shdrs_and_ehdr (abfd)
- bfd *abfd;
-{
- Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
- Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_External_Shdr *x_shdrp; /* Section header table, external form */
- Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
- unsigned int count;
- struct strtab *shstrtab;
-
- i_ehdrp = elf_elfheader (abfd);
- i_shdrp = elf_elfsections (abfd);
- shstrtab = elf_shstrtab (abfd);
-
- /* swap the header before spitting it out... */
-
-#if DEBUG & 1
- elf_debug_file (i_ehdrp);
-#endif
- elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr);
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
- || (bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd)
- != sizeof (x_ehdr)))
- return false;
-
- /* at this point we've concocted all the ELF sections... */
- x_shdrp = (Elf_External_Shdr *)
- bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum));
- if (!x_shdrp)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- for (count = 0; count < i_ehdrp->e_shnum; count++)
- {
-#if DEBUG & 2
- elf_debug_section (shstrtab->tab + i_shdrp[count]->sh_name, count,
- i_shdrp[count]);
-#endif
- elf_swap_shdr_out (abfd, i_shdrp[count], x_shdrp + count);
- }
- if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
- || (bfd_write ((PTR) x_shdrp, sizeof (*x_shdrp), i_ehdrp->e_shnum, abfd)
- != sizeof (*x_shdrp) * i_ehdrp->e_shnum))
- return false;
-
- /* need to dump the string table too... */
-
- return true;
-}
-
-/* Assign file positions for all the reloc sections which are not part
- of the loadable file image. */
-
-static void
-assign_file_positions_for_relocs (abfd)
- bfd *abfd;
-{
- file_ptr off;
- unsigned int i;
- Elf_Internal_Shdr **shdrpp;
-
- off = elf_tdata (abfd)->next_file_pos;
-
- for (i = 1, shdrpp = elf_elfsections (abfd) + 1;
- i < elf_elfheader (abfd)->e_shnum;
- i++, shdrpp++)
- {
- Elf_Internal_Shdr *shdrp;
-
- shdrp = *shdrpp;
- if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
- && shdrp->sh_offset == -1)
- off = assign_file_position_for_section (shdrp, off, true);
- }
-
- elf_tdata (abfd)->next_file_pos = off;
-}
-
-boolean
-NAME(bfd_elf,write_object_contents) (abfd)
- bfd *abfd;
-{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- Elf_Internal_Ehdr *i_ehdrp;
- Elf_Internal_Shdr **i_shdrp;
- unsigned int count;
-
- if (! abfd->output_has_begun
- && ! elf_compute_section_file_positions (abfd,
- (struct bfd_link_info *) NULL))
- return false;
-
- i_shdrp = elf_elfsections (abfd);
- i_ehdrp = elf_elfheader (abfd);
-
- bfd_map_over_sections (abfd, write_relocs, (PTR) 0);
- assign_file_positions_for_relocs (abfd);
-
- /* After writing the headers, we need to write the sections too... */
- for (count = 1; count < i_ehdrp->e_shnum; count++)
- {
- if (bed->elf_backend_section_processing)
- (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
- if (i_shdrp[count]->contents)
- {
- if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
- || (bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size,
- 1, abfd)
- != i_shdrp[count]->sh_size))
- return false;
- }
- }
-
- if (bed->elf_backend_final_write_processing)
- (*bed->elf_backend_final_write_processing) (abfd,
- elf_tdata (abfd)->linker);
-
- return write_shdrs_and_ehdr (abfd);
-}
-
-/* Given an index of a section, retrieve a pointer to it. Note
- that for our purposes, sections are indexed by {1, 2, ...} with
- 0 being an illegal index. */
-
-/* In the original, each ELF section went into exactly one BFD
- section. This doesn't really make sense, so we need a real mapping.
- The mapping has to hide in the Elf_Internal_Shdr since asection
- doesn't have anything like a tdata field... */
-
-static asection *
-section_from_elf_index (abfd, index)
- bfd *abfd;
- unsigned int index;
-{
- /* @@ Is bfd_com_section_ptr really correct in all the places it could
- be returned from this routine? */
-
- if (index == SHN_ABS)
- return bfd_com_section_ptr; /* not abs? */
- if (index == SHN_COMMON)
- return bfd_com_section_ptr;
-
- if (index >= elf_elfheader (abfd)->e_shnum)
- return NULL;
-
- {
- Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[index];
-
- switch (hdr->sh_type)
- {
- /* ELF sections that map to BFD sections */
- case SHT_PROGBITS:
- case SHT_NOBITS:
- case SHT_HASH:
- case SHT_DYNAMIC:
- if (hdr->rawdata == NULL)
- {
- if (! bfd_section_from_shdr (abfd, index))
- return NULL;
- }
- return (struct sec *) hdr->rawdata;
-
- default:
- return bfd_abs_section_ptr;
- }
- }
-}
-
-/* given a section, search the header to find them... */
-static int
-elf_section_from_bfd_section (abfd, asect)
- bfd *abfd;
- struct sec *asect;
-{
- Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
- int index;
- Elf_Internal_Shdr *hdr;
- int maxindex = elf_elfheader (abfd)->e_shnum;
-
- if (asect->owner == NULL)
- {
- if (bfd_is_abs_section (asect))
- return SHN_ABS;
- if (bfd_is_com_section (asect))
- return SHN_COMMON;
- if (bfd_is_und_section (asect))
- return SHN_UNDEF;
- return -1;
- }
-
- BFD_ASSERT (asect->owner == abfd);
-
- for (index = 0; index < maxindex; index++)
- {
- hdr = i_shdrp[index];
- switch (hdr->sh_type)
- {
- /* ELF sections that map to BFD sections */
- case SHT_PROGBITS:
- case SHT_NOBITS:
- case SHT_NOTE:
- case SHT_HASH:
- case SHT_DYNAMIC:
- case SHT_DYNSYM:
- case SHT_SYMTAB:
- if (hdr->rawdata)
- {
- if (((struct sec *) (hdr->rawdata)) == asect)
- return index;
- }
- break;
-
- case SHT_REL:
- case SHT_RELA:
- /* We sometimes map a reloc section to a BFD section. */
- if (hdr->sh_link != elf_onesymtab (abfd)
- && (asection *) hdr->rawdata == asect)
- return index;
- break;
-
- case SHT_STRTAB:
- /* 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:
- {
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- if (bed->elf_backend_section_from_bfd_section)
- {
- int retval;
-
- retval = index;
- if ((*bed->elf_backend_section_from_bfd_section)
- (abfd, hdr, asect, &retval))
- return retval;
- }
- }
- break;
- }
- }
- return -1;
-}
-
-/* given a symbol, return the bfd index for that symbol. */
-static int
-elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
- bfd *abfd;
- struct symbol_cache_entry **asym_ptr_ptr;
-{
- struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr;
- int idx;
- flagword flags = asym_ptr->flags;
-
- /* 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. When the linker is generating
- relocatable output, this section symbol may be for one of the
- input sections rather than the output section. */
- if (asym_ptr->udata == (PTR) 0
- && (flags & BSF_SECTION_SYM)
- && asym_ptr->section)
- {
- int indx;
-
- if (asym_ptr->section->output_section != NULL)
- indx = asym_ptr->section->output_section->index;
- else
- indx = asym_ptr->section->index;
- if (elf_section_syms (abfd)[indx])
- asym_ptr->udata = elf_section_syms (abfd)[indx]->udata;
- }
-
- if (asym_ptr->udata)
- idx = ((Elf_Sym_Extra *) asym_ptr->udata)->elf_sym_num;
- else
- {
- abort ();
- }
-
-#if DEBUG & 4
- {
-
- fprintf (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
-
- return idx;
-}
-
-static long
-elf_slurp_symbol_table (abfd, symptrs, dynamic)
- bfd *abfd;
- asymbol **symptrs; /* Buffer for generated bfd symbols */
- boolean dynamic;
-{
- Elf_Internal_Shdr *hdr;
- long symcount; /* Number of external ELF symbols */
- elf_symbol_type *sym; /* Pointer to current bfd symbol */
- elf_symbol_type *symbase; /* Buffer for generated bfd symbols */
- Elf_Internal_Sym i_sym;
- Elf_External_Sym *x_symp = NULL;
-
- /* Read each raw ELF symbol, converting from external ELF form to
- internal ELF form, and then using the information to create a
- canonical bfd symbol table entry.
-
- Note that we allocate the initial bfd canonical symbol buffer
- based on a one-to-one mapping of the ELF symbols to canonical
- symbols. We actually use all the ELF symbols, so there will be no
- space left over at the end. When we have all the symbols, we
- build the caller's pointer vector. */
-
- if (dynamic)
- hdr = &elf_tdata (abfd)->dynsymtab_hdr;
- else
- hdr = &elf_tdata (abfd)->symtab_hdr;
- if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
- return -1;
-
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
-
- if (symcount == 0)
- sym = symbase = NULL;
- else
- {
- long i;
-
- if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
- return -1;
-
- symbase = ((elf_symbol_type *)
- bfd_zalloc (abfd, symcount * sizeof (elf_symbol_type)));
- if (symbase == (elf_symbol_type *) NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return -1;
- }
- sym = symbase;
-
- /* Temporarily allocate room for the raw ELF symbols. */
- x_symp = ((Elf_External_Sym *)
- malloc (symcount * sizeof (Elf_External_Sym)));
- if (x_symp == NULL && symcount != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
-
- if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
- != symcount * sizeof (Elf_External_Sym))
- goto error_return;
- /* Skip first symbol, which is a null dummy. */
- for (i = 1; i < symcount; i++)
- {
- elf_swap_symbol_in (abfd, x_symp + i, &i_sym);
- memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym));
-#ifdef ELF_KEEP_EXTSYM
- memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym));
-#endif
- sym->symbol.the_bfd = abfd;
-
- sym->symbol.name = elf_string_from_elf_section (abfd, hdr->sh_link,
- i_sym.st_name);
-
- sym->symbol.value = i_sym.st_value;
-
- if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERVE)
- {
- sym->symbol.section = section_from_elf_index (abfd,
- i_sym.st_shndx);
- if (sym->symbol.section == NULL)
- {
- /* This symbol is in a section for which we did not
- create a BFD section. Just use bfd_abs_section,
- although it is wrong. FIXME. */
- sym->symbol.section = bfd_abs_section_ptr;
- }
- }
- else if (i_sym.st_shndx == SHN_ABS)
- {
- sym->symbol.section = bfd_abs_section_ptr;
- }
- else if (i_sym.st_shndx == SHN_COMMON)
- {
- sym->symbol.section = bfd_com_section_ptr;
- /* Elf puts the alignment into the `value' field, and
- the size into the `size' field. BFD wants to see the
- size in the value field, and doesn't care (at the
- moment) about the alignment. */
- sym->symbol.value = i_sym.st_size;
- }
- else if (i_sym.st_shndx == SHN_UNDEF)
- {
- sym->symbol.section = bfd_und_section_ptr;
- }
- else
- sym->symbol.section = bfd_abs_section_ptr;
-
- sym->symbol.value -= sym->symbol.section->vma;
-
- switch (ELF_ST_BIND (i_sym.st_info))
- {
- case STB_LOCAL:
- sym->symbol.flags |= BSF_LOCAL;
- break;
- case STB_GLOBAL:
- sym->symbol.flags |= BSF_GLOBAL;
- break;
- case STB_WEAK:
- sym->symbol.flags |= BSF_WEAK;
- break;
- }
-
- switch (ELF_ST_TYPE (i_sym.st_info))
- {
- case STT_SECTION:
- sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
- break;
- case STT_FILE:
- sym->symbol.flags |= BSF_FILE | BSF_DEBUGGING;
- break;
- case STT_FUNC:
- sym->symbol.flags |= BSF_FUNCTION;
- break;
- }
-
- if (dynamic)
- sym->symbol.flags |= BSF_DYNAMIC;
-
- /* Do some backend-specific processing on this symbol. */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- if (ebd->elf_backend_symbol_processing)
- (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
- }
-
- sym++;
- }
- }
-
- /* Do some backend-specific processing on this symbol table. */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- if (ebd->elf_backend_symbol_table_processing)
- (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
- }
-
- /* We rely on the zalloc to clear out the final symbol entry. */
-
- symcount = sym - symbase;
-
- /* Fill in the user's symbol pointer vector if needed. */
- if (symptrs)
- {
- long l = symcount;
-
- sym = symbase;
- while (l-- > 0)
- {
- *symptrs++ = &sym->symbol;
- sym++;
- }
- *symptrs = 0; /* Final null pointer */
- }
-
- if (x_symp != NULL)
- free (x_symp);
- return symcount;
-error_return:
- if (x_symp != NULL)
- free (x_symp);
- return -1;
-}
-
-/* Return the number of bytes required to hold the symtab vector.
-
- Note that we base it on the count plus 1, since we will null terminate
- the vector allocated based on this size. However, the ELF symbol table
- always has a dummy entry as symbol #0, so it ends up even. */
-
-long
-elf_get_symtab_upper_bound (abfd)
- bfd *abfd;
-{
- long symcount;
- long symtab_size;
- Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
-
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
- symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
-
- return symtab_size;
-}
-
-long
-elf_get_dynamic_symtab_upper_bound (abfd)
- bfd *abfd;
-{
- long symcount;
- long symtab_size;
- Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
-
- if (elf_dynsymtab (abfd) == 0)
- {
- bfd_set_error (bfd_error_invalid_operation);
- return -1;
- }
-
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
- symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
-
- return symtab_size;
-}
-
-long
-elf_get_reloc_upper_bound (abfd, asect)
- bfd *abfd;
- sec_ptr asect;
-{
- return (asect->reloc_count + 1) * sizeof (arelent *);
-}
-
-/* Read in and swap the external relocs. */
-
-static boolean
-elf_slurp_reloc_table (abfd, asect, symbols)
- bfd *abfd;
- asection *asect;
- asymbol **symbols;
-{
- struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
- struct bfd_elf_section_data * const d = elf_section_data (asect);
- PTR allocated = NULL;
- bfd_byte *native_relocs;
- arelent *relents;
- arelent *relent;
- unsigned int i;
- int entsize;
-
- if (asect->relocation != NULL
- || (asect->flags & SEC_RELOC) == 0
- || asect->reloc_count == 0)
- return true;
-
- BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset
- && (asect->reloc_count
- == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
-
- allocated = (PTR) malloc (d->rel_hdr.sh_size);
- if (allocated == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
-
- if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
- || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
- != d->rel_hdr.sh_size))
- goto error_return;
-
- native_relocs = (bfd_byte *) allocated;
-
- relents = ((arelent *)
- bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
- if (relents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
-
- entsize = d->rel_hdr.sh_entsize;
- BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
- || entsize == sizeof (Elf_External_Rela));
-
- for (i = 0, relent = relents;
- i < asect->reloc_count;
- i++, relent++, native_relocs += entsize)
- {
- Elf_Internal_Rela rela;
- Elf_Internal_Rel rel;
-
- if (entsize == sizeof (Elf_External_Rela))
- elf_swap_reloca_in (abfd, (Elf_External_Rela *) native_relocs, &rela);
- else
- {
- elf_swap_reloc_in (abfd, (Elf_External_Rel *) native_relocs, &rel);
- rela.r_offset = rel.r_offset;
- rela.r_info = rel.r_info;
- rela.r_addend = 0;
- }
-
- /* The address of an ELF reloc is section relative for an object
- file, and absolute for an executable file or shared library.
- The address of a BFD reloc is always section relative. */
- if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
- relent->address = rela.r_offset;
- else
- relent->address = rela.r_offset - asect->vma;
-
- if (ELF_R_SYM (rela.r_info) == 0)
- relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
- else
- {
- asymbol **ps, *s;
-
- ps = symbols + ELF_R_SYM (rela.r_info) - 1;
- s = *ps;
-
- /* Canonicalize ELF section symbols. FIXME: Why? */
- if ((s->flags & BSF_SECTION_SYM) == 0)
- relent->sym_ptr_ptr = ps;
- else
- relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
- }
-
- relent->addend = rela.r_addend;
-
- if (entsize == sizeof (Elf_External_Rela))
- (*ebd->elf_info_to_howto) (abfd, relent, &rela);
- else
- (*ebd->elf_info_to_howto_rel) (abfd, relent, &rel);
- }
-
- asect->relocation = relents;
-
- if (allocated != NULL)
- free (allocated);
-
- return true;
-
- error_return:
- if (allocated != NULL)
- free (allocated);
- return false;
-}
-
-#ifdef DEBUG
-static void
-elf_debug_section (str, num, hdr)
- char *str;
- int num;
- Elf_Internal_Shdr *hdr;
-{
- fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num, str, (long) hdr);
- fprintf (stderr,
- "sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n",
- (long) hdr->sh_name,
- (long) hdr->sh_type,
- (long) hdr->sh_flags);
- fprintf (stderr,
- "sh_addr = %ld\tsh_offset = %ld\tsh_size = %ld\n",
- (long) hdr->sh_addr,
- (long) hdr->sh_offset,
- (long) hdr->sh_size);
- fprintf (stderr,
- "sh_link = %ld\tsh_info = %ld\tsh_addralign = %ld\n",
- (long) hdr->sh_link,
- (long) hdr->sh_info,
- (long) hdr->sh_addralign);
- fprintf (stderr, "sh_entsize = %ld\n",
- (long) hdr->sh_entsize);
- fprintf (stderr, "rawdata = 0x%.8lx\n", (long) hdr->rawdata);
- fprintf (stderr, "contents = 0x%.8lx\n", (long) hdr->contents);
- fprintf (stderr, "size = %ld\n", (long) hdr->size);
- fflush (stderr);
-}
-
-static void
-elf_debug_file (ehdrp)
- Elf_Internal_Ehdr *ehdrp;
-{
- fprintf (stderr, "e_entry = 0x%.8lx\n", (long) ehdrp->e_entry);
- fprintf (stderr, "e_phoff = %ld\n", (long) ehdrp->e_phoff);
- fprintf (stderr, "e_phnum = %ld\n", (long) ehdrp->e_phnum);
- fprintf (stderr, "e_phentsize = %ld\n", (long) ehdrp->e_phentsize);
- fprintf (stderr, "e_shoff = %ld\n", (long) ehdrp->e_shoff);
- fprintf (stderr, "e_shnum = %ld\n", (long) ehdrp->e_shnum);
- fprintf (stderr, "e_shentsize = %ld\n", (long) ehdrp->e_shentsize);
-}
-#endif
-
-/* Canonicalize the relocs. */
-
-long
-elf_canonicalize_reloc (abfd, section, relptr, symbols)
- bfd *abfd;
- sec_ptr section;
- arelent **relptr;
- asymbol **symbols;
-{
- arelent *tblptr;
- unsigned int i;
-
- if (! elf_slurp_reloc_table (abfd, section, symbols))
- return -1;
-
- tblptr = section->relocation;
- for (i = 0; i < section->reloc_count; i++)
- *relptr++ = tblptr++;
-
- *relptr = NULL;
-
- return section->reloc_count;
-}
-
-long
-elf_get_symtab (abfd, alocation)
- bfd *abfd;
- asymbol **alocation;
-{
- long symcount = elf_slurp_symbol_table (abfd, alocation, false);
-
- if (symcount >= 0)
- bfd_get_symcount (abfd) = symcount;
- return symcount;
-}
-
-long
-elf_canonicalize_dynamic_symtab (abfd, alocation)
- bfd *abfd;
- asymbol **alocation;
-{
- return elf_slurp_symbol_table (abfd, alocation, true);
-}
-
-asymbol *
-elf_make_empty_symbol (abfd)
- bfd *abfd;
-{
- elf_symbol_type *newsym;
-
- newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (elf_symbol_type));
- if (!newsym)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
- else
- {
- newsym->symbol.the_bfd = abfd;
- return &newsym->symbol;
- }
-}
-
-void
-elf_get_symbol_info (ignore_abfd, symbol, ret)
- bfd *ignore_abfd;
- asymbol *symbol;
- symbol_info *ret;
-{
- bfd_symbol_info (symbol, ret);
-}
-
-alent *
-elf_get_lineno (ignore_abfd, symbol)
- bfd *ignore_abfd;
- asymbol *symbol;
-{
- fprintf (stderr, "elf_get_lineno unimplemented\n");
- fflush (stderr);
- BFD_FAIL ();
- return NULL;
-}
-
-boolean
-elf_set_arch_mach (abfd, arch, machine)
- bfd *abfd;
- enum bfd_architecture arch;
- unsigned long machine;
-{
- /* If this isn't the right architecture for this backend, and this
- isn't the generic backend, fail. */
- if (arch != get_elf_backend_data (abfd)->arch
- && arch != bfd_arch_unknown
- && get_elf_backend_data (abfd)->arch != bfd_arch_unknown)
- return false;
-
- return bfd_default_set_arch_mach (abfd, arch, machine);
-}
-
-boolean
-elf_find_nearest_line (abfd,
- section,
- symbols,
- offset,
- filename_ptr,
- functionname_ptr,
- line_ptr)
- bfd *abfd;
- asection *section;
- asymbol **symbols;
- bfd_vma offset;
- CONST char **filename_ptr;
- CONST char **functionname_ptr;
- unsigned int *line_ptr;
-{
- return false;
-}
-
-int
-elf_sizeof_headers (abfd, reloc)
- bfd *abfd;
- boolean reloc;
-{
- int ret;
-
- ret = sizeof (Elf_External_Ehdr);
- if (! reloc)
- ret += get_program_header_size (abfd);
- return ret;
-}
-
-boolean
-elf_set_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- PTR location;
- file_ptr offset;
- bfd_size_type count;
-{
- Elf_Internal_Shdr *hdr;
-
- if (! abfd->output_has_begun
- && ! elf_compute_section_file_positions (abfd,
- (struct bfd_link_info *) NULL))
- return false;
-
- hdr = &elf_section_data (section)->this_hdr;
-
- if (bfd_seek (abfd, hdr->sh_offset + offset, SEEK_SET) == -1)
- return false;
- if (bfd_write (location, 1, count, abfd) != count)
- return false;
-
- return true;
-}
-
-void
-elf_no_info_to_howto (abfd, cache_ptr, dst)
- bfd *abfd;
- arelent *cache_ptr;
- Elf_Internal_Rela *dst;
-{
- fprintf (stderr, "elf RELA relocation support for target machine unimplemented\n");
- fflush (stderr);
- BFD_FAIL ();
-}
-
-void
-elf_no_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd *abfd;
- arelent *cache_ptr;
- Elf_Internal_Rel *dst;
-{
- fprintf (stderr, "elf REL relocation support for target machine unimplemented\n");
- fflush (stderr);
- BFD_FAIL ();
-}
-\f
-
-/* Core file support */
-
-#ifdef HAVE_PROCFS /* Some core file support requires host /proc files */
-#include <sys/procfs.h>
-#else
-#define bfd_prstatus(abfd, descdata, descsz, filepos) true
-#define bfd_fpregset(abfd, descdata, descsz, filepos) true
-#define bfd_prpsinfo(abfd, descdata, descsz, filepos) true
-#endif
-
-#ifdef HAVE_PROCFS
-
-static boolean
-bfd_prstatus (abfd, descdata, descsz, filepos)
- bfd *abfd;
- char *descdata;
- int descsz;
- long filepos;
-{
- asection *newsect;
- prstatus_t *status = (prstatus_t *) 0;
-
- if (descsz == sizeof (prstatus_t))
- {
- newsect = bfd_make_section (abfd, ".reg");
- if (newsect == NULL)
- return false;
- newsect->_raw_size = sizeof (status->pr_reg);
- newsect->filepos = filepos + (long) &status->pr_reg;
- newsect->flags = SEC_HAS_CONTENTS;
- newsect->alignment_power = 2;
- if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL)
- {
- memcpy (core_prstatus (abfd), descdata, descsz);
- }
- }
- return true;
-}
-
-/* Stash a copy of the prpsinfo structure away for future use. */
-
-static boolean
-bfd_prpsinfo (abfd, descdata, descsz, filepos)
- bfd *abfd;
- char *descdata;
- int descsz;
- long filepos;
-{
- if (descsz == sizeof (prpsinfo_t))
- {
- if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- memcpy (core_prpsinfo (abfd), descdata, descsz);
- }
- return true;
-}
-
-static boolean
-bfd_fpregset (abfd, descdata, descsz, filepos)
- bfd *abfd;
- char *descdata;
- int descsz;
- long filepos;
-{
- asection *newsect;
-
- newsect = bfd_make_section (abfd, ".reg2");
- if (newsect == NULL)
- return false;
- newsect->_raw_size = descsz;
- newsect->filepos = filepos;
- newsect->flags = SEC_HAS_CONTENTS;
- newsect->alignment_power = 2;
- return true;
-}
-
-#endif /* HAVE_PROCFS */
-
-/* Return a pointer to the args (including the command name) that were
- seen by the program that generated the core dump. Note that for
- some reason, a spurious space is tacked onto the end of the args
- in some (at least one anyway) implementations, so strip it off if
- it exists. */
-
-char *
-elf_core_file_failing_command (abfd)
- bfd *abfd;
-{
-#ifdef HAVE_PROCFS
- if (core_prpsinfo (abfd))
- {
- prpsinfo_t *p = core_prpsinfo (abfd);
- char *scan = p->pr_psargs;
- while (*scan++)
- {;
- }
- scan -= 2;
- if ((scan > p->pr_psargs) && (*scan == ' '))
- {
- *scan = '\000';
- }
- return p->pr_psargs;
- }
-#endif
- return NULL;
-}
-
-/* Return the number of the signal that caused the core dump. Presumably,
- since we have a core file, we got a signal of some kind, so don't bother
- checking the other process status fields, just return the signal number.
- */
-
-int
-elf_core_file_failing_signal (abfd)
- bfd *abfd;
-{
-#ifdef HAVE_PROCFS
- if (core_prstatus (abfd))
- {
- return ((prstatus_t *) (core_prstatus (abfd)))->pr_cursig;
- }
-#endif
- return -1;
-}
-
-/* Check to see if the core file could reasonably be expected to have
- come for the current executable file. Note that by default we return
- true unless we find something that indicates that there might be a
- problem.
- */
-
-boolean
-elf_core_file_matches_executable_p (core_bfd, exec_bfd)
- bfd *core_bfd;
- bfd *exec_bfd;
-{
-#ifdef HAVE_PROCFS
- char *corename;
- char *execname;
-#endif
-
- /* First, xvecs must match since both are ELF files for the same target. */
-
- if (core_bfd->xvec != exec_bfd->xvec)
- {
- bfd_set_error (bfd_error_system_call);
- return false;
- }
-
-#ifdef HAVE_PROCFS
-
- /* If no prpsinfo, just return true. Otherwise, grab the last component
- of the exec'd pathname from the prpsinfo. */
-
- if (core_prpsinfo (core_bfd))
- {
- corename = (((struct prpsinfo *) core_prpsinfo (core_bfd))->pr_fname);
- }
- else
- {
- return true;
- }
-
- /* Find the last component of the executable pathname. */
-
- if ((execname = strrchr (exec_bfd->filename, '/')) != NULL)
- {
- execname++;
- }
- else
- {
- execname = (char *) exec_bfd->filename;
- }
-
- /* See if they match */
-
- return strcmp (execname, corename) ? false : true;
-
-#else
-
- return true;
-
-#endif /* HAVE_PROCFS */
-}
-
-/* ELF core files contain a segment of type PT_NOTE, that holds much of
- the information that would normally be available from the /proc interface
- for the process, at the time the process dumped core. Currently this
- includes copies of the prstatus, prpsinfo, and fpregset structures.
-
- Since these structures are potentially machine dependent in size and
- ordering, bfd provides two levels of support for them. The first level,
- available on all machines since it does not require that the host
- have /proc support or the relevant include files, is to create a bfd
- section for each of the prstatus, prpsinfo, and fpregset structures,
- without any interpretation of their contents. With just this support,
- the bfd client will have to interpret the structures itself. Even with
- /proc support, it might want these full structures for it's own reasons.
-
- In the second level of support, where HAVE_PROCFS is defined, bfd will
- pick apart the structures to gather some additional information that
- clients may want, such as the general register set, the name of the
- exec'ed file and its arguments, the signal (if any) that caused the
- core dump, etc.
-
- */
-
-static boolean
-elf_corefile_note (abfd, hdr)
- bfd *abfd;
- Elf_Internal_Phdr *hdr;
-{
- Elf_External_Note *x_note_p; /* Elf note, external form */
- Elf_Internal_Note i_note; /* Elf note, internal form */
- char *buf = NULL; /* Entire note segment contents */
- char *namedata; /* Name portion of the note */
- char *descdata; /* Descriptor portion of the note */
- char *sectname; /* Name to use for new section */
- long filepos; /* File offset to descriptor data */
- asection *newsect;
-
- if (hdr->p_filesz > 0
- && (buf = (char *) malloc (hdr->p_filesz)) != NULL
- && bfd_seek (abfd, hdr->p_offset, SEEK_SET) != -1
- && bfd_read ((PTR) buf, hdr->p_filesz, 1, abfd) == hdr->p_filesz)
- {
- x_note_p = (Elf_External_Note *) buf;
- while ((char *) x_note_p < (buf + hdr->p_filesz))
- {
- i_note.namesz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->namesz);
- i_note.descsz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->descsz);
- i_note.type = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->type);
- namedata = x_note_p->name;
- descdata = namedata + BFD_ALIGN (i_note.namesz, 4);
- filepos = hdr->p_offset + (descdata - buf);
- switch (i_note.type)
- {
- case NT_PRSTATUS:
- /* process descdata as prstatus info */
- if (! bfd_prstatus (abfd, descdata, i_note.descsz, filepos))
- return false;
- sectname = ".prstatus";
- break;
- case NT_FPREGSET:
- /* process descdata as fpregset info */
- if (! bfd_fpregset (abfd, descdata, i_note.descsz, filepos))
- return false;
- sectname = ".fpregset";
- break;
- case NT_PRPSINFO:
- /* process descdata as prpsinfo */
- if (! bfd_prpsinfo (abfd, descdata, i_note.descsz, filepos))
- return false;
- sectname = ".prpsinfo";
- break;
- default:
- /* Unknown descriptor, just ignore it. */
- sectname = NULL;
- break;
- }
- if (sectname != NULL)
- {
- newsect = bfd_make_section (abfd, sectname);
- if (newsect == NULL)
- return false;
- newsect->_raw_size = i_note.descsz;
- newsect->filepos = filepos;
- newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
- newsect->alignment_power = 2;
- }
- x_note_p = (Elf_External_Note *)
- (descdata + BFD_ALIGN (i_note.descsz, 4));
- }
- }
- if (buf != NULL)
- {
- free (buf);
- }
- else if (hdr->p_filesz > 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- return true;
-
-}
-
-/* Core files are simply standard ELF formatted files that partition
- the file using the execution view of the file (program header table)
- rather than the linking view. In fact, there is no section header
- table in a core file.
-
- The process status information (including the contents of the general
- register set) and the floating point register set are stored in a
- segment of type PT_NOTE. We handcraft a couple of extra bfd sections
- that allow standard bfd access to the general registers (.reg) and the
- floating point registers (.reg2).
-
- */
-
-const bfd_target *
-elf_core_file_p (abfd)
- bfd *abfd;
-{
- Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
- Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_External_Phdr x_phdr; /* Program header table entry, external form */
- Elf_Internal_Phdr *i_phdrp; /* Program header table, internal form */
- unsigned int phindex;
- struct elf_backend_data *ebd;
-
- /* Read in the ELF header in external format. */
-
- if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr))
- {
- if (bfd_get_error () != bfd_error_system_call)
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
- }
-
- /* 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')
- and byte-swapping must match our XVEC entry, and it must have a
- program header table (FIXME: See comments re segments at top of this
- file). */
-
- if (elf_file_p (&x_ehdr) == false)
- {
- wrong:
- bfd_set_error (bfd_error_wrong_format);
- return NULL;
- }
-
- /* FIXME, Check EI_VERSION here ! */
-
- {
-#if ARCH_SIZE == 32
- int desired_address_size = ELFCLASS32;
-#endif
-#if ARCH_SIZE == 64
- int desired_address_size = ELFCLASS64;
-#endif
-
- if (x_ehdr.e_ident[EI_CLASS] != desired_address_size)
- goto wrong;
- }
-
- /* Switch xvec to match the specified byte order. */
- switch (x_ehdr.e_ident[EI_DATA])
- {
- case ELFDATA2MSB: /* Big-endian */
- if (abfd->xvec->byteorder_big_p == false)
- goto wrong;
- break;
- case ELFDATA2LSB: /* Little-endian */
- if (abfd->xvec->byteorder_big_p == true)
- goto wrong;
- break;
- case ELFDATANONE: /* No data encoding specified */
- default: /* Unknown data encoding specified */
- goto wrong;
- }
-
- /* Allocate an instance of the elf_obj_tdata structure and hook it up to
- the tdata pointer in the bfd. */
-
- elf_tdata (abfd) =
- (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
- if (elf_tdata (abfd) == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
-
- /* FIXME, `wrong' returns from this point onward, leak memory. */
-
- /* Now that we know the byte order, swap in the rest of the header */
- i_ehdrp = elf_elfheader (abfd);
- elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
-#if DEBUG & 1
- elf_debug_file (i_ehdrp);
-#endif
-
- ebd = get_elf_backend_data (abfd);
-
- /* Check that the ELF e_machine field matches what this particular
- BFD format expects. */
- if (ebd->elf_machine_code != i_ehdrp->e_machine)
- {
- const bfd_target * const *target_ptr;
-
- if (ebd->elf_machine_code != EM_NONE)
- goto wrong;
-
- /* This is the generic ELF target. Let it match any ELF target
- for which we do not have a specific backend. */
- for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
- {
- struct elf_backend_data *back;
-
- if ((*target_ptr)->flavour != bfd_target_elf_flavour)
- continue;
- back = (struct elf_backend_data *) (*target_ptr)->backend_data;
- if (back->elf_machine_code == i_ehdrp->e_machine)
- {
- /* target_ptr is an ELF backend which matches this
- object file, so reject the generic ELF target. */
- goto wrong;
- }
- }
- }
-
- /* If there is no program header, or the type is not a core file, then
- we are hosed. */
- if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
- goto wrong;
-
- /* Allocate space for a copy of the program header table in
- internal form, seek to the program header table in the file,
- read it in, and convert it to internal form. As a simple sanity
- check, verify that the what BFD thinks is the size of each program
- header table entry actually matches the size recorded in the file. */
-
- if (i_ehdrp->e_phentsize != sizeof (x_phdr))
- goto wrong;
- i_phdrp = (Elf_Internal_Phdr *)
- bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum);
- if (!i_phdrp)
- {
- bfd_set_error (bfd_error_no_memory);
- return NULL;
- }
- if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
- return NULL;
- for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
- {
- if (bfd_read ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd)
- != sizeof (x_phdr))
- return NULL;
- elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex);
- }
-
- /* Once all of the program headers have been read and converted, we
- can start processing them. */
-
- for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
- {
- bfd_section_from_phdr (abfd, i_phdrp + phindex, phindex);
- if ((i_phdrp + phindex)->p_type == PT_NOTE)
- {
- if (! elf_corefile_note (abfd, i_phdrp + phindex))
- return NULL;
- }
- }
-
- /* Remember the entry point specified in the ELF file header. */
-
- bfd_get_start_address (abfd) = i_ehdrp->e_entry;
-
- return abfd->xvec;
-}
-\f
-/* ELF linker code. */
-
-static boolean elf_link_add_object_symbols
- PARAMS ((bfd *, struct bfd_link_info *));
-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_adjust_dynamic_symbol
- PARAMS ((struct elf_link_hash_entry *, PTR));
-
-/* Given an ELF BFD, add symbols to the global hash table as
- appropriate. */
-
-boolean
-elf_bfd_link_add_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- switch (bfd_get_format (abfd))
- {
- case bfd_object:
- return elf_link_add_object_symbols (abfd, info);
- case bfd_archive:
- return elf_link_add_archive_symbols (abfd, info);
- default:
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
-}
-
-/* Add symbols from an ELF archive file to the linker hash table. We
- don't use _bfd_generic_link_add_archive_symbols because of a
- problem which arises on UnixWare. The UnixWare libc.so is an
- archive which includes an entry libc.so.1 which defines a bunch of
- symbols. The libc.so archive also includes a number of other
- object files, which also define symbols, some of which are the same
- as those defined in libc.so.1. Correct linking requires that we
- consider each object file in turn, and include it if it defines any
- symbols we need. _bfd_generic_link_add_archive_symbols does not do
- this; it looks through the list of undefined symbols, and includes
- any object file which defines them. When this algorithm is used on
- UnixWare, it winds up pulling in libc.so.1 early and defining a
- bunch of symbols. This means that some of the other objects in the
- archive are not included in the link, which is incorrect since they
- precede libc.so.1 in the archive.
-
- Fortunately, ELF archive handling is simpler than that done by
- _bfd_generic_link_add_archive_symbols, which has to allow for a.out
- oddities. In ELF, if we find a symbol in the archive map, and the
- symbol is currently undefined, we know that we must pull in that
- object file.
-
- Unfortunately, we do have to make multiple passes over the symbol
- table until nothing further is resolved. */
-
-static boolean
-elf_link_add_archive_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- symindex c;
- boolean *defined = NULL;
- boolean *included = NULL;
- carsym *symdefs;
- boolean loop;
-
- if (! bfd_has_map (abfd))
- {
- bfd_set_error (bfd_error_no_symbols);
- return false;
- }
-
- /* Keep track of all symbols we know to be already defined, and all
- files we know to be already included. This is to speed up the
- second and subsequent passes. */
- c = bfd_ardata (abfd)->symdef_count;
- if (c == 0)
- return true;
- defined = (boolean *) malloc (c * sizeof (boolean));
- included = (boolean *) malloc (c * sizeof (boolean));
- if (defined == (boolean *) NULL || included == (boolean *) NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
- memset (defined, 0, c * sizeof (boolean));
- memset (included, 0, c * sizeof (boolean));
-
- symdefs = bfd_ardata (abfd)->symdefs;
-
- do
- {
- file_ptr last;
- symindex i;
- carsym *symdef;
- carsym *symdefend;
-
- loop = false;
- last = -1;
-
- symdef = symdefs;
- symdefend = symdef + c;
- for (i = 0; symdef < symdefend; symdef++, i++)
- {
- struct elf_link_hash_entry *h;
- bfd *element;
- struct bfd_link_hash_entry *undefs_tail;
- symindex mark;
-
- if (defined[i] || included[i])
- continue;
- if (symdef->file_offset == last)
- {
- included[i] = true;
- continue;
- }
-
- h = elf_link_hash_lookup (elf_hash_table (info), symdef->name,
- false, false, false);
- if (h == (struct elf_link_hash_entry *) NULL)
- continue;
- if (h->root.type != bfd_link_hash_undefined)
- {
- defined[i] = true;
- continue;
- }
-
- /* We need to include this archive member. */
-
- element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
- if (element == (bfd *) NULL)
- goto error_return;
-
- if (! bfd_check_format (element, bfd_object))
- goto error_return;
-
- /* Doublecheck that we have not included this object
- already--it should be impossible, but there may be
- something wrong with the archive. */
- if (element->archive_pass != 0)
- {
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
- element->archive_pass = 1;
-
- undefs_tail = info->hash->undefs_tail;
-
- if (! (*info->callbacks->add_archive_element) (info, element,
- symdef->name))
- goto error_return;
- if (! elf_link_add_object_symbols (element, info))
- goto error_return;
-
- /* If there are any new undefined symbols, we need to make
- another pass through the archive in order to see whether
- they can be defined. FIXME: This isn't perfect, because
- common symbols wind up on undefs_tail and because an
- undefined symbol which is defined later on in this pass
- does not require another pass. This isn't a bug, but it
- does make the code less efficient than it could be. */
- if (undefs_tail != info->hash->undefs_tail)
- loop = true;
-
- /* Look backward to mark all symbols from this object file
- which we have already seen in this pass. */
- mark = i;
- do
- {
- included[mark] = true;
- if (mark == 0)
- break;
- --mark;
- }
- while (symdefs[mark].file_offset == symdef->file_offset);
-
- /* We mark subsequent symbols from this object file as we go
- on through the loop. */
- last = symdef->file_offset;
- }
- }
- while (loop);
-
- free (defined);
- free (included);
-
- return true;
-
- error_return:
- if (defined != (boolean *) NULL)
- free (defined);
- if (included != (boolean *) NULL)
- free (included);
- return false;
-}
-
-/* Record a new dynamic symbol. We record the dynamic symbols as we
- read the input files, since we need to have a list of all of them
- before we can determine the final sizes of the output sections. */
-
-INLINE boolean
-elf_link_record_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
-{
- if (h->dynindx == -1)
- {
- h->dynindx = elf_hash_table (info)->dynsymcount;
- ++elf_hash_table (info)->dynsymcount;
- h->dynstr_index = bfd_add_to_strtab (elf_hash_table (info)->dynobj,
- elf_hash_table (info)->dynstr,
- h->root.root.string);
- if (h->dynstr_index == (unsigned long) -1)
- return false;
- }
-
- return true;
-}
-
-/* Add symbols from an ELF object file to the linker hash table. */
-
-static boolean
-elf_link_add_object_symbols (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- boolean (*add_symbol_hook) PARAMS ((bfd *, struct bfd_link_info *,
- const Elf_Internal_Sym *,
- const char **, flagword *,
- asection **, bfd_vma *));
- boolean (*check_relocs) PARAMS ((bfd *, struct bfd_link_info *,
- asection *, const Elf_Internal_Rela *));
- boolean collect;
- Elf_Internal_Shdr *hdr;
- size_t symcount;
- size_t extsymcount;
- size_t extsymoff;
- Elf_External_Sym *buf = NULL;
- struct elf_link_hash_entry **sym_hash;
- boolean dynamic;
- Elf_External_Dyn *dynbuf = NULL;
- struct elf_link_hash_entry *weaks;
- Elf_External_Sym *esym;
- Elf_External_Sym *esymend;
-
- add_symbol_hook = get_elf_backend_data (abfd)->elf_add_symbol_hook;
- collect = get_elf_backend_data (abfd)->collect;
-
- /* A stripped shared library might only have a dynamic symbol table,
- not a regular symbol table. In that case we can still go ahead
- and link using the dynamic symbol table. */
- if (elf_onesymtab (abfd) == 0
- && elf_dynsymtab (abfd) != 0)
- {
- elf_onesymtab (abfd) = elf_dynsymtab (abfd);
- elf_tdata (abfd)->symtab_hdr = elf_tdata (abfd)->dynsymtab_hdr;
- }
-
- hdr = &elf_tdata (abfd)->symtab_hdr;
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
-
- /* The sh_info field of the symtab header tells us where the
- external symbols start. We don't care about the local symbols at
- this point. */
- if (elf_bad_symtab (abfd))
- {
- extsymcount = symcount;
- extsymoff = 0;
- }
- else
- {
- extsymcount = symcount - hdr->sh_info;
- extsymoff = hdr->sh_info;
- }
-
- buf = (Elf_External_Sym *) malloc (extsymcount * sizeof (Elf_External_Sym));
- if (buf == NULL && extsymcount != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
-
- /* We store a pointer to the hash table entry for each external
- symbol. */
- sym_hash = ((struct elf_link_hash_entry **)
- bfd_alloc (abfd,
- extsymcount * sizeof (struct elf_link_hash_entry *)));
- if (sym_hash == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
- elf_sym_hashes (abfd) = sym_hash;
-
- if (elf_elfheader (abfd)->e_type != ET_DYN)
- {
- dynamic = false;
-
- /* If we are creating a shared library, create all the dynamic
- sections immediately. We need to attach them to something,
- so we attach them to this BFD, provided it is the right
- format. FIXME: If there are no input BFD's of the same
- format as the output, we can't make a shared library. */
- if (info->shared
- && elf_hash_table (info)->dynobj == NULL
- && abfd->xvec == info->hash->creator)
- {
- if (! elf_link_create_dynamic_sections (abfd, info))
- goto error_return;
- elf_hash_table (info)->dynobj = abfd;
- }
- }
- else
- {
- asection *s;
- const char *name;
- unsigned long strindex;
-
- dynamic = true;
-
- /* You can't use -r against a dynamic object. Also, there's no
- hope of using a dynamic object which does not exactly match
- the format of the output file. */
- if (info->relocateable
- || info->hash->creator != abfd->xvec)
- {
- bfd_set_error (bfd_error_invalid_operation);
- goto error_return;
- }
-
- /* Find the name to use in a DT_NEEDED entry that refers to this
- object. If the object has a DT_SONAME entry, we use it.
- Otherwise, if the generic linker stuck something in
- elf_dt_needed_name, we use that. Otherwise, we just use the
- file name. */
- name = bfd_get_filename (abfd);
- if (elf_dt_needed_name (abfd) != NULL)
- name = elf_dt_needed_name (abfd);
- s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s != NULL)
- {
- Elf_External_Dyn *extdyn;
- Elf_External_Dyn *extdynend;
-
- dynbuf = (Elf_External_Dyn *) malloc (s->_raw_size);
- if (dynbuf == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
-
- if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf,
- (file_ptr) 0, s->_raw_size))
- goto error_return;
-
- extdyn = dynbuf;
- extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
- for (; extdyn < extdynend; extdyn++)
- {
- Elf_Internal_Dyn dyn;
-
- elf_swap_dyn_in (abfd, extdyn, &dyn);
- if (dyn.d_tag == DT_SONAME)
- {
- int elfsec;
- unsigned long link;
-
- elfsec = elf_section_from_bfd_section (abfd, s);
- if (elfsec == -1)
- goto error_return;
- link = elf_elfsections (abfd)[elfsec]->sh_link;
- name = elf_string_from_elf_section (abfd, link,
- dyn.d_un.d_val);
- if (name == NULL)
- goto error_return;
-
- break;
- }
- }
-
- free (dynbuf);
- dynbuf = NULL;
- }
-
- /* We do not want to include any of the sections in a dynamic
- object in the output file. We hack by simply clobbering the
- list of sections in the BFD. This could be handled more
- cleanly by, say, a new section flag; the existing
- SEC_NEVER_LOAD flag is not the one we want, because that one
- still implies that the section takes up space in the output
- file. */
- abfd->sections = NULL;
-
- /* If this is the first dynamic object found in the link, create
- the special sections required for dynamic linking. We need
- to put them somewhere, and attaching them to the first
- dynamic object is as good place as any. */
- if (elf_hash_table (info)->dynobj == NULL)
- {
- if (! elf_link_create_dynamic_sections (abfd, info))
- goto error_return;
- elf_hash_table (info)->dynobj = abfd;
- }
-
- /* Add a DT_NEEDED entry for this dynamic object. */
- strindex = bfd_add_to_strtab (abfd,
- elf_hash_table (info)->dynstr,
- name);
- if (strindex == (unsigned long) -1)
- goto error_return;
- if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
- goto error_return;
- }
-
- if (bfd_seek (abfd,
- hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
- SEEK_SET) != 0
- || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
- != extsymcount * sizeof (Elf_External_Sym)))
- goto error_return;
-
- weaks = NULL;
-
- esymend = buf + extsymcount;
- for (esym = buf; esym < esymend; esym++, sym_hash++)
- {
- Elf_Internal_Sym sym;
- int bind;
- bfd_vma value;
- asection *sec;
- flagword flags;
- const char *name;
- struct elf_link_hash_entry *h = NULL;
- boolean definition;
-
- elf_swap_symbol_in (abfd, esym, &sym);
-
- flags = BSF_NO_FLAGS;
- sec = NULL;
- value = sym.st_value;
- *sym_hash = NULL;
-
- bind = ELF_ST_BIND (sym.st_info);
- if (bind == STB_LOCAL)
- {
- /* This should be impossible, since ELF requires that all
- global symbols follow all local symbols, and that sh_info
- point to the first global symbol. Unfortunatealy, Irix 5
- screws this up. */
- continue;
- }
- else if (bind == STB_GLOBAL)
- flags = BSF_GLOBAL;
- else if (bind == STB_WEAK)
- flags = BSF_WEAK;
- else
- {
- /* Leave it up to the processor backend. */
- }
-
- if (sym.st_shndx == SHN_UNDEF)
- sec = bfd_und_section_ptr;
- else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)
- {
- sec = section_from_elf_index (abfd, sym.st_shndx);
- if (sec == NULL)
- goto error_return;
- value -= sec->vma;
- }
- else if (sym.st_shndx == SHN_ABS)
- sec = bfd_abs_section_ptr;
- else if (sym.st_shndx == SHN_COMMON)
- {
- sec = bfd_com_section_ptr;
- /* What ELF calls the size we call the value. What ELF
- calls the value we call the alignment. */
- value = sym.st_size;
- }
- else
- {
- /* Leave it up to the processor backend. */
- }
-
- name = elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
- if (name == (const char *) NULL)
- goto error_return;
-
- if (add_symbol_hook)
- {
- if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec,
- &value))
- goto error_return;
-
- /* The hook function sets the name to NULL if this symbol
- should be skipped for some reason. */
- if (name == (const char *) NULL)
- continue;
- }
-
- /* Sanity check that all possibilities were handled. */
- if (flags == BSF_NO_FLAGS || sec == (asection *) NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
-
- if (bfd_is_und_section (sec)
- || bfd_is_com_section (sec))
- definition = false;
- else
- definition = true;
-
- if (info->hash->creator->flavour == bfd_target_elf_flavour)
- {
- /* We need to look up the symbol now in order to get some of
- the dynamic object handling right. We pass the hash
- table entry in to _bfd_generic_link_add_one_symbol so
- that it does not have to look it up again. */
- h = elf_link_hash_lookup (elf_hash_table (info), name,
- true, false, false);
- if (h == NULL)
- goto error_return;
- *sym_hash = h;
-
- /* If we are looking at a dynamic object, and this is a
- definition, we need to see if it has already been defined
- by some other object. If it has, we want to use the
- existing definition, and we do not want to report a
- multiple symbol definition error; we do this by
- clobbering sec to be bfd_und_section_ptr. */
- if (dynamic && definition)
- {
- if (h->root.type == bfd_link_hash_defined)
- sec = bfd_und_section_ptr;
- }
-
- /* Similarly, if we are not looking at a dynamic object, and
- we have a definition, we want to override any definition
- we may have from a dynamic object. Symbols from regular
- files always take precedence over symbols from dynamic
- objects, even if they are defined after the dynamic
- object in the link. */
- if (! dynamic
- && definition
- && h->root.type == bfd_link_hash_defined
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
- && (bfd_get_flavour (h->root.u.def.section->owner)
- == bfd_target_elf_flavour)
- && (elf_elfheader (h->root.u.def.section->owner)->e_type
- == ET_DYN))
- {
- /* Change the hash table entry to undefined, and let
- _bfd_generic_link_add_one_symbol do the right thing
- with the new definition. */
- h->root.type = bfd_link_hash_undefined;
- h->root.u.undef.abfd = h->root.u.def.section->owner;
- h->elf_link_hash_flags &=~ ELF_LINK_HASH_DEFINED_WEAK;
- }
-
- /* If this is a weak definition which we are going to use,
- and the symbol is currently undefined, record that the
- definition is weak. */
- if (definition
- && (flags & BSF_WEAK) != 0
- && ! 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->elf_link_hash_flags |= ELF_LINK_HASH_DEFINED_WEAK;
- }
-
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, name, flags, sec, value, (const char *) NULL,
- false, collect, (struct bfd_link_hash_entry **) sym_hash)))
- goto error_return;
-
- if (dynamic
- && definition
- && (flags & BSF_WEAK) != 0
- && ELF_ST_TYPE (sym.st_info) != STT_FUNC
- && (*sym_hash)->weakdef == NULL)
- {
- /* Keep a list of all weak defined non function symbols from
- a dynamic object, using the weakdef field. Later in this
- function we will set the weakdef field to the correct
- value. We only put non-function symbols from dynamic
- objects on this list, because that happens to be the only
- time we need to know the normal symbol corresponding to a
- weak symbol, and the information is time consuming to
- figure out. If the weakdef field is not already NULL,
- then this symbol was already defined by some previous
- dynamic object, and we will be using that previous
- definition anyhow. */
-
- (*sym_hash)->weakdef = weaks;
- weaks = *sym_hash;
- }
-
- /* Get the alignment of a common symbol. */
- if (sym.st_shndx == SHN_COMMON
- && h->root.type == bfd_link_hash_common)
- h->root.u.c.alignment_power = bfd_log2 (sym.st_value);
-
- if (info->hash->creator->flavour == bfd_target_elf_flavour)
- {
- int old_flags;
- boolean dynsym;
- int new_flag;
-
- /* Remember the symbol size and type. */
- if (sym.st_size != 0)
- {
- /* FIXME: We should probably somehow give a warning if
- the symbol size changes. */
- h->size = sym.st_size;
- }
- if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE)
- {
- /* FIXME: We should probably somehow give a warning if
- the symbol type changes. */
- h->type = ELF_ST_TYPE (sym.st_info);
- }
-
- /* Set a flag in the hash table entry indicating the type of
- reference or definition we just found. Keep a count of
- the number of dynamic symbols we find. A dynamic symbol
- is one which is referenced or defined by both a regular
- object and a shared object, or one which is referenced or
- defined by more than one shared object. */
- old_flags = h->elf_link_hash_flags;
- dynsym = false;
- if (! dynamic)
- {
- if (! definition)
- new_flag = ELF_LINK_HASH_REF_REGULAR;
- else
- new_flag = ELF_LINK_HASH_DEF_REGULAR;
- if (info->shared
- || (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
- | ELF_LINK_HASH_REF_DYNAMIC)) != 0)
- dynsym = true;
- }
- else
- {
- if (! definition)
- new_flag = ELF_LINK_HASH_REF_DYNAMIC;
- else
- new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
- if ((old_flags & new_flag) != 0
- || (old_flags & (ELF_LINK_HASH_DEF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR)) != 0)
- dynsym = true;
- }
-
- h->elf_link_hash_flags |= new_flag;
- if (dynsym && h->dynindx == -1)
- {
- if (! elf_link_record_dynamic_symbol (info, h))
- goto error_return;
- }
- }
- }
-
- /* Now set the weakdefs field correctly for all the weak defined
- symbols we found. The only way to do this is to search all the
- symbols. Since we only need the information for non functions in
- dynamic objects, that's the only time we actually put anything on
- the list WEAKS. We need this information so that if a regular
- object refers to a symbol defined weakly in a dynamic object, the
- real symbol in the dynamic object is also put in the dynamic
- symbols; we also must arrange for both symbols to point to the
- same memory location. We could handle the general case of symbol
- aliasing, but a general symbol alias can only be generated in
- assembler code, handling it correctly would be very time
- consuming, and other ELF linkers don't handle general aliasing
- either. */
- while (weaks != NULL)
- {
- struct elf_link_hash_entry *hlook;
- asection *slook;
- bfd_vma vlook;
- struct elf_link_hash_entry **hpp;
- struct elf_link_hash_entry **hppend;
-
- hlook = weaks;
- weaks = hlook->weakdef;
- hlook->weakdef = NULL;
-
- BFD_ASSERT (hlook->root.type == bfd_link_hash_defined);
- slook = hlook->root.u.def.section;
- vlook = hlook->root.u.def.value;
-
- hpp = elf_sym_hashes (abfd);
- hppend = hpp + extsymcount;
- for (; hpp < hppend; hpp++)
- {
- struct elf_link_hash_entry *h;
-
- h = *hpp;
- if (h != hlook
- && h->root.type == bfd_link_hash_defined
- && h->root.u.def.section == slook
- && h->root.u.def.value == vlook)
- {
- hlook->weakdef = h;
-
- /* If the weak definition is in the list of dynamic
- symbols, make sure the real definition is put there
- as well. */
- if (hlook->dynindx != -1
- && h->dynindx == -1)
- {
- if (! elf_link_record_dynamic_symbol (info, h))
- goto error_return;
- }
-
- break;
- }
- }
- }
-
- if (buf != NULL)
- {
- free (buf);
- buf = NULL;
- }
-
- /* If this object is the same format as the output object, and it is
- not a shared library, then let the backend look through the
- relocs.
-
- This is required to build global offset table entries and to
- arrange for dynamic relocs. It is not required for the
- particular common case of linking non PIC code, even when linking
- against shared libraries, but unfortunately there is no way of
- knowing whether an object file has been compiled PIC or not.
- Looking through the relocs is not particularly time consuming.
- The problem is that we must either (1) keep the relocs in memory,
- which causes the linker to require additional runtime memory or
- (2) read the relocs twice from the input file, which wastes time.
- This would be a good case for using mmap.
-
- I have no idea how to handle linking PIC code into a file of a
- different format. It probably can't be done. */
- check_relocs = get_elf_backend_data (abfd)->check_relocs;
- if (! dynamic
- && abfd->xvec == info->hash->creator
- && check_relocs != NULL)
- {
- asection *o;
-
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- Elf_Internal_Rela *internal_relocs;
- boolean ok;
-
- if ((o->flags & SEC_RELOC) == 0
- || o->reloc_count == 0)
- continue;
-
- /* I believe we can ignore the relocs for any section which
- does not form part of the final process image, such as a
- debugging section. */
- if ((o->flags & SEC_ALLOC) == 0)
- continue;
-
- internal_relocs = elf_link_read_relocs (abfd, o, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->keep_memory);
- if (internal_relocs == NULL)
- goto error_return;
-
- ok = (*check_relocs) (abfd, info, o, internal_relocs);
-
- if (! info->keep_memory)
- free (internal_relocs);
-
- if (! ok)
- goto error_return;
- }
- }
-
- return true;
-
- error_return:
- if (buf != NULL)
- free (buf);
- if (dynbuf != NULL)
- free (dynbuf);
- return false;
-}
-
-/* Create some sections which will be filled in with dynamic linking
- information. The ABFD argument is an input file which is a dynamic
- object. The dynamic sections take up virtual memory space when the
- final executable is run, so we need to create them before addresses
- are assigned to the output sections. We work out the actual
- contents and size of these sections later. */
-
-boolean
-elf_link_create_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- flagword flags;
- register asection *s;
- struct elf_link_hash_entry *h;
- struct elf_backend_data *bed;
-
- /* Note that we set the SEC_IN_MEMORY flag for all of these
- sections. */
- flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
-
- /* A dynamically linked executable has a .interp section, but a
- shared library does not. */
- if (! info->shared)
- {
- s = bfd_make_section (abfd, ".interp");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
- return false;
- }
-
- s = bfd_make_section (abfd, ".dynsym");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
- return false;
-
- /* The first .dynsym symbol is a dummy. */
- elf_hash_table (info)->dynsymcount = 1;
-
- s = bfd_make_section (abfd, ".dynstr");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
- return false;
-
- /* Create a strtab to hold the dynamic symbol names. */
- elf_hash_table (info)->dynstr = bfd_new_strtab (abfd);
- if (elf_hash_table (info)->dynstr == NULL)
- return false;
-
- s = bfd_make_section (abfd, ".dynamic");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags)
- || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
- return false;
-
- /* The special symbol _DYNAMIC is always set to the start of the
- .dynamic section. This call occurs before we have processed the
- symbols for any dynamic object, so we don't have to worry about
- overriding a dynamic definition. We could set _DYNAMIC in a
- linker script, but we only want to define it if we are, in fact,
- creating a .dynamic section. We don't want to define it if there
- is no .dynamic section, since on some ELF platforms the start up
- code examines it to decide how to initialize the process. */
- h = NULL;
- if (! (_bfd_generic_link_add_one_symbol
- (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
- (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
- return false;
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (info->shared
- && ! elf_link_record_dynamic_symbol (info, h))
- return false;
-
- s = bfd_make_section (abfd, ".hash");
- if (s == NULL
- || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
- || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
- return false;
-
- /* Let the backend create the rest of the sections. This lets the
- backend set the right flags. The backend will normally create
- the .got and .plt sections. */
- bed = get_elf_backend_data (abfd);
- return (*bed->elf_backend_create_dynamic_sections) (abfd, info);
-}
-
-/* Add an entry to the .dynamic table. */
-
-boolean
-elf_add_dynamic_entry (info, tag, val)
- struct bfd_link_info *info;
- bfd_vma tag;
- bfd_vma val;
-{
- Elf_Internal_Dyn dyn;
- bfd *dynobj;
- asection *s;
- size_t newsize;
- bfd_byte *newcontents;
-
- dynobj = elf_hash_table (info)->dynobj;
-
- s = bfd_get_section_by_name (dynobj, ".dynamic");
- BFD_ASSERT (s != NULL);
-
- newsize = s->_raw_size + sizeof (Elf_External_Dyn);
- if (s->contents == NULL)
- newcontents = (bfd_byte *) malloc (newsize);
- else
- newcontents = (bfd_byte *) realloc (s->contents, newsize);
- if (newcontents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- dyn.d_tag = tag;
- dyn.d_un.d_val = val;
- elf_swap_dyn_out (dynobj, &dyn,
- (Elf_External_Dyn *) (newcontents + s->_raw_size));
-
- s->_raw_size = newsize;
- s->contents = newcontents;
-
- return true;
-}
-
-/* Read and swap the relocs for a section. They may have been cached.
- If the EXTERNAL_RELOCS and INTERNAL_RELOCS arguments are not NULL,
- they are used as buffers to read into. They are known to be large
- enough. If the INTERNAL_RELOCS relocs argument is NULL, the return
- value is allocated using either malloc or bfd_alloc, according to
- the KEEP_MEMORY argument. */
-
-static Elf_Internal_Rela *
-elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory)
- bfd *abfd;
- asection *o;
- PTR external_relocs;
- Elf_Internal_Rela *internal_relocs;
- boolean keep_memory;
-{
- Elf_Internal_Shdr *rel_hdr;
- PTR alloc1 = NULL;
- Elf_Internal_Rela *alloc2 = NULL;
-
- if (elf_section_data (o)->relocs != NULL)
- return elf_section_data (o)->relocs;
-
- if (o->reloc_count == 0)
- return NULL;
-
- rel_hdr = &elf_section_data (o)->rel_hdr;
-
- if (internal_relocs == NULL)
- {
- size_t size;
-
- size = o->reloc_count * sizeof (Elf_Internal_Rela);
- if (keep_memory)
- internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
- else
- internal_relocs = alloc2 = (Elf_Internal_Rela *) malloc (size);
- if (internal_relocs == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
- }
-
- if (external_relocs == NULL)
- {
- alloc1 = (PTR) malloc (rel_hdr->sh_size);
- if (alloc1 == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
- external_relocs = alloc1;
- }
-
- if ((bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0)
- || (bfd_read (external_relocs, 1, rel_hdr->sh_size, abfd)
- != rel_hdr->sh_size))
- goto error_return;
-
- /* Swap in the relocs. For convenience, we always produce an
- Elf_Internal_Rela array; if the relocs are Rel, we set the addend
- to 0. */
- if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
- {
- Elf_External_Rel *erel;
- Elf_External_Rel *erelend;
- Elf_Internal_Rela *irela;
-
- erel = (Elf_External_Rel *) external_relocs;
- erelend = erel + o->reloc_count;
- irela = internal_relocs;
- for (; erel < erelend; erel++, irela++)
- {
- Elf_Internal_Rel irel;
-
- elf_swap_reloc_in (abfd, erel, &irel);
- irela->r_offset = irel.r_offset;
- irela->r_info = irel.r_info;
- irela->r_addend = 0;
- }
- }
- else
- {
- Elf_External_Rela *erela;
- Elf_External_Rela *erelaend;
- Elf_Internal_Rela *irela;
-
- BFD_ASSERT (rel_hdr->sh_entsize == sizeof (Elf_External_Rela));
-
- erela = (Elf_External_Rela *) external_relocs;
- erelaend = erela + o->reloc_count;
- irela = internal_relocs;
- for (; erela < erelaend; erela++, irela++)
- elf_swap_reloca_in (abfd, erela, irela);
- }
-
- /* Cache the results for next time, if we can. */
- if (keep_memory)
- elf_section_data (o)->relocs = internal_relocs;
-
- if (alloc1 != NULL)
- free (alloc1);
-
- /* Don't free alloc2, since if it was allocated we are passing it
- back (under the name of internal_relocs). */
-
- return internal_relocs;
-
- error_return:
- if (alloc1 != NULL)
- free (alloc1);
- if (alloc2 != NULL)
- free (alloc2);
- return NULL;
-}
-
-/* Record an assignment to a symbol made by a linker script. We need
- this in case some dynamic object refers to this symbol. */
-
-/*ARGSUSED*/
-boolean
-NAME(bfd_elf,record_link_assignment) (output_bfd, info, name)
- bfd *output_bfd;
- struct bfd_link_info *info;
- const char *name;
-{
- struct elf_link_hash_entry *h;
-
- h = elf_link_hash_lookup (elf_hash_table (info), name, true, true, false);
- if (h == NULL)
- return false;
-
- h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
- h->type = STT_OBJECT;
-
- if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
- | ELF_LINK_HASH_REF_DYNAMIC)) != 0
- || info->shared)
- && h->dynindx == -1)
- {
- if (! elf_link_record_dynamic_symbol (info, h))
- return false;
-
- /* If this is a weak defined symbol, and we know a corresponding
- real symbol from the same dynamic object, make sure the real
- symbol is also made into a dynamic symbol. */
- if (h->weakdef != NULL
- && h->weakdef->dynindx == -1)
- {
- if (! elf_link_record_dynamic_symbol (info, h->weakdef))
- return false;
- }
- }
-
- return true;
-}
-
-/* Array used to determine the number of hash table buckets to use
- based on the number of symbols there are. If there are fewer than
- 3 symbols we use 1 bucket, fewer than 17 symbols we use 3 buckets,
- fewer than 37 we use 17 buckets, and so forth. We never use more
- than 521 buckets. */
-
-static const size_t elf_buckets[] =
-{
- 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 0
-};
-
-/* Set up the sizes and contents of the ELF dynamic sections. This is
- called by the ELF linker emulation before_allocation routine. We
- must set the sizes of the sections before the linker sets the
- addresses of the various sections. */
-
-boolean
-NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
- sinterpptr)
- bfd *output_bfd;
- const char *soname;
- const char *rpath;
- struct bfd_link_info *info;
- asection **sinterpptr;
-{
- bfd *dynobj;
- size_t dynsymcount;
- asection *s;
- Elf_Internal_Sym isym;
- size_t i;
- size_t bucketcount;
- struct elf_backend_data *bed;
-
- *sinterpptr = NULL;
-
- dynobj = elf_hash_table (info)->dynobj;
- dynsymcount = elf_hash_table (info)->dynsymcount;
-
- /* If there were no dynamic objects in the link, there is nothing to
- do here. */
- if (dynobj == NULL)
- return true;
-
- *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (*sinterpptr != NULL || info->shared);
-
- /* Set the size of the .dynsym and .hash sections. We counted the
- number of dynamic symbols in elf_link_add_object_symbols. We
- will build the contents of .dynsym and .hash when we build the
- final symbol table, because until then we do not know the correct
- value to give the symbols. We built the .dynstr section as we
- went along in elf_link_add_object_symbols. */
- s = bfd_get_section_by_name (dynobj, ".dynsym");
- BFD_ASSERT (s != NULL);
- s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* The first entry in .dynsym is a dummy symbol. */
- isym.st_value = 0;
- isym.st_size = 0;
- isym.st_name = 0;
- isym.st_info = 0;
- isym.st_other = 0;
- isym.st_shndx = 0;
- elf_swap_symbol_out (output_bfd, &isym,
- (Elf_External_Sym *) s->contents);
-
- for (i = 0; elf_buckets[i] != 0; i++)
- {
- bucketcount = elf_buckets[i];
- if (dynsymcount < elf_buckets[i + 1])
- break;
- }
-
- s = bfd_get_section_by_name (dynobj, ".hash");
- BFD_ASSERT (s != NULL);
- s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
- s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
- if (s->contents == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- memset (s->contents, 0, s->_raw_size);
-
- put_word (output_bfd, bucketcount, s->contents);
- put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
-
- elf_hash_table (info)->bucketcount = bucketcount;
-
- if (soname != NULL)
- {
- unsigned long indx;
-
- indx = bfd_add_to_strtab (dynobj, elf_hash_table (info)->dynstr, soname);
- if (indx == (unsigned long) -1
- || ! elf_add_dynamic_entry (info, DT_SONAME, indx))
- return false;
- }
-
- if (rpath != NULL)
- {
- unsigned long indx;
-
- indx = bfd_add_to_strtab (dynobj, elf_hash_table (info)->dynstr, rpath);
- if (indx == (unsigned long) -1
- || ! elf_add_dynamic_entry (info, DT_RPATH, indx))
- return false;
- }
-
- s = bfd_get_section_by_name (dynobj, ".dynstr");
- BFD_ASSERT (s != NULL);
- s->_raw_size = elf_hash_table (info)->dynstr->length;
- s->contents = (unsigned char *) elf_hash_table (info)->dynstr->tab;
-
- /* Find all symbols which were defined in a dynamic object and make
- the backend pick a reasonable value for them. */
- elf_link_hash_traverse (elf_hash_table (info),
- elf_adjust_dynamic_symbol,
- (PTR) info);
-
- /* Add some entries to the .dynamic section. We fill in some of the
- values later, in elf_bfd_final_link, but we must add the entries
- now so that we know the final size of the .dynamic section. */
- if (bfd_get_section_by_name (output_bfd, ".init") != NULL)
- {
- if (! elf_add_dynamic_entry (info, DT_INIT, 0))
- return false;
- }
- if (bfd_get_section_by_name (output_bfd, ".fini") != NULL)
- {
- if (! elf_add_dynamic_entry (info, DT_FINI, 0))
- return false;
- }
- if (! elf_add_dynamic_entry (info, DT_HASH, 0)
- || ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
- || ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
- || ! elf_add_dynamic_entry (info, DT_STRSZ,
- elf_hash_table (info)->dynstr->length)
- || ! elf_add_dynamic_entry (info, DT_SYMENT,
- sizeof (Elf_External_Sym)))
- return false;
-
- /* The backend must work out the sizes of all the other dynamic
- sections. */
- bed = get_elf_backend_data (output_bfd);
- if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
- return false;
-
- return elf_add_dynamic_entry (info, DT_NULL, 0);
-}
-
-/* Make the backend pick a good value for a dynamic symbol. This is
- called via elf_link_hash_traverse, and also calls itself
- recursively. */
-
-static boolean
-elf_adjust_dynamic_symbol (h, data)
- struct elf_link_hash_entry *h;
- PTR data;
-{
- struct bfd_link_info *info = (struct bfd_link_info *) data;
- bfd *dynobj;
- struct elf_backend_data *bed;
-
- /* If this symbol is not defined by a dynamic object, or is not
- referenced by a regular object, ignore it. FIXME: Do we need to
- worry about symbols which are defined by one dynamic object and
- referenced by another one? */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
- || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
- return true;
-
- /* If we've already adjusted this symbol, don't do it again. This
- can happen via a recursive call. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
- return true;
-
- /* Don't look at this symbol again. Note that we must set this
- after checking the above conditions, because we may look at a
- symbol once, decide not to do anything, and then get called
- recursively later after REF_REGULAR is set below. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_DYNAMIC_ADJUSTED;
-
- /* If this is a weak definition, and we know a real definition, and
- the real symbol is not itself defined by a regular object file,
- then get a good value for the real definition. We handle the
- real symbol first, for the convenience of the backend routine.
-
- Note that there is a confusing case here. If the real definition
- is defined by a regular object file, we don't get the real symbol
- from the dynamic object, but we do get the weak symbol. If the
- processor backend uses a COPY reloc, then if some routine in the
- dynamic object changes the real symbol, we will not see that
- change in the corresponding weak symbol. This is the way other
- ELF linkers work as well, and seems to be a result of the shared
- library model.
-
- I will clarify this issue. Most SVR4 shared libraries define the
- variable _timezone and define timezone as a weak synonym. The
- tzset call changes _timezone. If you write
- extern int timezone;
- int _timezone = 5;
- int main () { tzset (); printf ("%d %d\n", timezone, _timezone); }
- you might expect that, since timezone is a synonym for _timezone,
- the same number will print both times. However, if the processor
- backend uses a COPY reloc, then actually timezone will be copied
- into your process image, and, since you define _timezone
- yourself, _timezone will not. Thus timezone and _timezone will
- wind up at different memory locations. The tzset call will set
- _timezone, leaving timezone unchanged. */
-
- if (h->weakdef != NULL)
- {
- struct elf_link_hash_entry *weakdef;
-
- BFD_ASSERT (h->root.type == bfd_link_hash_defined);
- weakdef = h->weakdef;
- BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined);
- BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
- if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
- {
- /* This symbol is defined by a regular object file, so we
- will not do anything special. Clear weakdef for the
- convenience of the processor backend. */
- h->weakdef = NULL;
- }
- else
- {
- /* There is an implicit reference by a regular object file
- via the weak symbol. */
- weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
- if (! elf_adjust_dynamic_symbol (weakdef, (PTR) info))
- return false;
- }
- }
-
- dynobj = elf_hash_table (info)->dynobj;
- bed = get_elf_backend_data (dynobj);
- if (! (*bed->elf_backend_adjust_dynamic_symbol) (info, h))
- {
- /* FIXME: No way to return error. */
- abort ();
- }
-
- return true;
-}
-\f
-/* Final phase of ELF linker. */
-
-/* A structure we use to avoid passing large numbers of arguments. */
-
-struct elf_final_link_info
-{
- /* General link information. */
- struct bfd_link_info *info;
- /* Output BFD. */
- bfd *output_bfd;
- /* Symbol string table. */
- struct strtab *symstrtab;
- /* .dynsym section. */
- asection *dynsym_sec;
- /* .hash section. */
- asection *hash_sec;
- /* Buffer large enough to hold contents of any section. */
- bfd_byte *contents;
- /* Buffer large enough to hold external relocs of any section. */
- PTR external_relocs;
- /* Buffer large enough to hold internal relocs of any section. */
- Elf_Internal_Rela *internal_relocs;
- /* Buffer large enough to hold external local symbols of any input
- BFD. */
- Elf_External_Sym *external_syms;
- /* Buffer large enough to hold internal local symbols of any input
- BFD. */
- Elf_Internal_Sym *internal_syms;
- /* Array large enough to hold a symbol index for each local symbol
- of any input BFD. */
- long *indices;
- /* Array large enough to hold a section pointer for each local
- symbol of any input BFD. */
- asection **sections;
- /* Buffer to hold swapped out symbols. */
- Elf_External_Sym *symbuf;
- /* Number of swapped out symbols in buffer. */
- size_t symbuf_count;
- /* Number of symbols which fit in symbuf. */
- size_t symbuf_size;
-};
-
-static boolean elf_link_output_sym
- PARAMS ((struct elf_final_link_info *, const char *,
- Elf_Internal_Sym *, asection *));
-static boolean elf_link_flush_output_syms
- PARAMS ((struct elf_final_link_info *));
-static boolean elf_link_output_extsym
- PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean elf_link_input_bfd
- PARAMS ((struct elf_final_link_info *, bfd *));
-static boolean elf_reloc_link_order
- PARAMS ((bfd *, struct bfd_link_info *, asection *,
- struct bfd_link_order *));
-
-/* Do the final step of an ELF link. */
-
-boolean
-elf_bfd_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
-{
- bfd *dynobj;
- struct elf_final_link_info finfo;
- register asection *o;
- register struct bfd_link_order *p;
- register bfd *sub;
- size_t max_contents_size;
- size_t max_external_reloc_size;
- size_t max_internal_reloc_count;
- size_t max_sym_count;
- file_ptr off;
- Elf_Internal_Sym elfsym;
- unsigned int i;
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);