- this_hdr->sh_flags = 0;
- if ((asect->flags & SEC_ALLOC) != 0)
- this_hdr->sh_addr = asect->vma;
- else
- this_hdr->sh_addr = 0;
- this_hdr->sh_offset = 0;
- this_hdr->sh_size = asect->_raw_size;
- this_hdr->sh_link = 0;
- this_hdr->sh_info = 0;
- this_hdr->sh_addralign = 1 << asect->alignment_power;
- this_hdr->sh_entsize = 0;
-
- this_hdr->bfd_section = asect;
- this_hdr->contents = NULL;
-
- /* FIXME: This should not be based on section names. */
- if (strcmp (asect->name, ".dynstr") == 0)
- this_hdr->sh_type = SHT_STRTAB;
- else if (strcmp (asect->name, ".hash") == 0)
- {
- this_hdr->sh_type = SHT_HASH;
- this_hdr->sh_entsize = ARCH_SIZE / 8;
- }
- else if (strcmp (asect->name, ".dynsym") == 0)
- {
- this_hdr->sh_type = SHT_DYNSYM;
- this_hdr->sh_entsize = sizeof (Elf_External_Sym);
- }
- else if (strcmp (asect->name, ".dynamic") == 0)
- {
- this_hdr->sh_type = SHT_DYNAMIC;
- this_hdr->sh_entsize = sizeof (Elf_External_Dyn);
- }
- else if (strncmp (asect->name, ".rela", 5) == 0
- && get_elf_backend_data (abfd)->use_rela_p)
- {
- this_hdr->sh_type = SHT_RELA;
- this_hdr->sh_entsize = sizeof (Elf_External_Rela);
- }
- else if (strncmp (asect->name, ".rel", 4) == 0
- && ! get_elf_backend_data (abfd)->use_rela_p)
- {
- this_hdr->sh_type = SHT_REL;
- this_hdr->sh_entsize = sizeof (Elf_External_Rel);
- }
- else if (strcmp (asect->name, ".note") == 0)
- this_hdr->sh_type = SHT_NOTE;
- else if (strncmp (asect->name, ".stab", 5) == 0
- && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
- this_hdr->sh_type = SHT_STRTAB;
- else if ((asect->flags & SEC_ALLOC) != 0
- && (asect->flags & SEC_LOAD) != 0)
- this_hdr->sh_type = SHT_PROGBITS;
- else if ((asect->flags & SEC_ALLOC) != 0
- && ((asect->flags & SEC_LOAD) == 0))
- {
- BFD_ASSERT (strcmp (asect->name, ".bss") == 0
- || strcmp (asect->name, ".sbss") == 0
- || strcmp (asect->name, ".scommon") == 0
- || strcmp (asect->name, "COMMON") == 0);
- this_hdr->sh_type = SHT_NOBITS;
- }
- else
- {
- /* Who knows? */
- this_hdr->sh_type = SHT_PROGBITS;
- }
-
- if ((asect->flags & SEC_ALLOC) != 0)
- this_hdr->sh_flags |= SHF_ALLOC;
- if ((asect->flags & SEC_READONLY) == 0)
- this_hdr->sh_flags |= SHF_WRITE;
- if ((asect->flags & SEC_CODE) != 0)
- this_hdr->sh_flags |= SHF_EXECINSTR;
-
- /* Check for processor-specific section types. */
- {
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- if (bed->elf_backend_fake_sections)
- (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
- }
-
- /* If the section has relocs, set up a section header for the
- SHT_REL[A] section. */
- if ((asect->flags & SEC_RELOC) != 0)
- {
- Elf_Internal_Shdr *rela_hdr;
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
- char *name;
-
- rela_hdr = &elf_section_data (asect)->rel_hdr;
- name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name));
- if (name == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- *failedptr = true;
- return;
- }
- sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
- rela_hdr->sh_name =
- (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name,
- true, false);
- if (rela_hdr->sh_name == (unsigned int) -1)
- {
- *failedptr = true;
- return;
- }
- rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
- rela_hdr->sh_entsize = (use_rela_p
- ? sizeof (Elf_External_Rela)
- : sizeof (Elf_External_Rel));
- rela_hdr->sh_addralign = FILE_ALIGN;
- rela_hdr->sh_flags = 0;
- rela_hdr->sh_addr = 0;
- rela_hdr->sh_size = 0;
- rela_hdr->sh_offset = 0;
- }
-}
-
-/* Assign all ELF section numbers. The dummy first section is handled here
- too. The link/info pointers for the standard section types are filled
- in here too, while we're at it. */
-
-static boolean
-assign_section_numbers (abfd)
- bfd *abfd;
-{
- struct elf_obj_tdata *t = elf_tdata (abfd);
- asection *sec;
- unsigned int section_number;
- Elf_Internal_Shdr **i_shdrp;
-
- section_number = 1;
-
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- struct bfd_elf_section_data *d = elf_section_data (sec);
-
- d->this_idx = section_number++;
- if ((sec->flags & SEC_RELOC) == 0)
- d->rel_idx = 0;
- else
- d->rel_idx = section_number++;
- }
-
- t->shstrtab_section = section_number++;
- elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
- t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
-
- if (abfd->symcount > 0)
- {
- t->symtab_section = section_number++;
- t->strtab_section = section_number++;
- }
-
- elf_elfheader (abfd)->e_shnum = section_number;
-
- /* Set up the list of section header pointers, in agreement with the
- indices. */
- i_shdrp = ((Elf_Internal_Shdr **)
- bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *)));
- if (i_shdrp == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- i_shdrp[0] = ((Elf_Internal_Shdr *)
- bfd_alloc (abfd, sizeof (Elf_Internal_Shdr)));
- if (i_shdrp[0] == NULL)
- {
- bfd_release (abfd, i_shdrp);
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
-
- elf_elfsections (abfd) = i_shdrp;
-
- i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
- if (abfd->symcount > 0)
- {
- i_shdrp[t->symtab_section] = &t->symtab_hdr;
- i_shdrp[t->strtab_section] = &t->strtab_hdr;
- t->symtab_hdr.sh_link = t->strtab_section;
- }
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- struct bfd_elf_section_data *d = elf_section_data (sec);
- asection *s;
- const char *name;
-
- i_shdrp[d->this_idx] = &d->this_hdr;
- if (d->rel_idx != 0)
- i_shdrp[d->rel_idx] = &d->rel_hdr;
-
- /* Fill in the sh_link and sh_info fields while we're at it. */
-
- /* sh_link of a reloc section is the section index of the symbol
- table. sh_info is the section index of the section to which
- the relocation entries apply. */
- if (d->rel_idx != 0)
- {
- d->rel_hdr.sh_link = t->symtab_section;
- d->rel_hdr.sh_info = d->this_idx;
- }
-
- switch (d->this_hdr.sh_type)
- {
- case SHT_REL:
- case SHT_RELA:
- /* A reloc section which we are treating as a normal BFD
- section. sh_link is the section index of the symbol
- table. sh_info is the section index of the section to
- which the relocation entries apply. We assume that an
- allocated reloc section uses the dynamic symbol table.
- FIXME: How can we be sure? */
- s = bfd_get_section_by_name (abfd, ".dynsym");
- if (s != NULL)
- d->this_hdr.sh_link = elf_section_data (s)->this_idx;
-
- /* We look up the section the relocs apply to by name. */
- name = sec->name;
- if (d->this_hdr.sh_type == SHT_REL)
- name += 4;
- else
- name += 5;
- s = bfd_get_section_by_name (abfd, name);
- if (s != NULL)
- d->this_hdr.sh_info = elf_section_data (s)->this_idx;
- break;
-
- case SHT_STRTAB:
- /* We assume that a section named .stab*str is a stabs
- string section. We look for a section with the same name
- but without the trailing ``str'', and set its sh_link
- field to point to this section. */
- if (strncmp (sec->name, ".stab", sizeof ".stab" - 1) == 0
- && strcmp (sec->name + strlen (sec->name) - 3, "str") == 0)
- {
- size_t len;
- char *alc;
-
- len = strlen (sec->name);
- alc = (char *) malloc (len - 2);
- if (alc == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- strncpy (alc, sec->name, len - 3);
- alc[len - 3] = '\0';
- s = bfd_get_section_by_name (abfd, alc);
- free (alc);
- if (s != NULL)
- {
- elf_section_data (s)->this_hdr.sh_link = d->this_idx;
-
- /* This is a .stab section. */
- elf_section_data (s)->this_hdr.sh_entsize =
- 4 + 2 * (ARCH_SIZE / 8);
- }
- }
- break;
-
- case SHT_DYNAMIC:
- case SHT_DYNSYM:
- /* sh_link is the section header index of the string table
- used for the dynamic entries or symbol table. */
- s = bfd_get_section_by_name (abfd, ".dynstr");
- if (s != NULL)
- d->this_hdr.sh_link = elf_section_data (s)->this_idx;
- break;
-
- case SHT_HASH:
- /* sh_link is the section header index of the symbol table
- this hash table is for. */
- s = bfd_get_section_by_name (abfd, ".dynsym");
- if (s != NULL)
- d->this_hdr.sh_link = elf_section_data (s)->this_idx;
- break;
- }
- }
-
- return true;
-}
-
-/* Map symbol from it's internal number to the external number, moving
- all local symbols to be at the head of the list. */
-
-static INLINE int
-sym_is_global (abfd, sym)
- bfd *abfd;
- asymbol *sym;
-{
- /* 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));
-
- return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
- || bfd_is_und_section (bfd_get_section (sym))
- || bfd_is_com_section (bfd_get_section (sym)));
-}
-
-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;
- int idx;
- asection *asect;
- asymbol **new_syms;
-
-#ifdef DEBUG
- fprintf (stderr, "elf_map_symbols\n");
- fflush (stderr);
-#endif
-
- /* Add a section symbol for each BFD section. FIXME: Is this really
- necessary? */
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- if (max_index < asect->index)
- max_index = asect->index;
- }
-
- max_index++;
- sect_syms = (asymbol **) bfd_zalloc (abfd, max_index * sizeof (asymbol *));
- if (sect_syms == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- elf_section_syms (abfd) = sect_syms;
-
- for (idx = 0; idx < symcount; idx++)
- {
- if ((syms[idx]->flags & BSF_SECTION_SYM) != 0
- && syms[idx]->value == 0)
- {
- asection *sec;
-
- sec = syms[idx]->section;
- if (sec->owner != NULL)
- {
- if (sec->owner != abfd)
- {
- if (sec->output_offset != 0)
- continue;
- sec = sec->output_section;
- BFD_ASSERT (sec->owner == abfd);
- }
- sect_syms[sec->index] = syms[idx];
- }
- }
- }
-
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- asymbol *sym;
-
- if (sect_syms[asect->index] != NULL)
- continue;
-
- sym = bfd_make_empty_symbol (abfd);
- if (sym == NULL)
- return false;
- sym->the_bfd = abfd;
- sym->name = asect->name;
- sym->value = 0;
- /* Set the flags to 0 to indicate that this one was newly added. */
- sym->flags = 0;
- 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
- }
-
- /* Classify all of the symbols. */
- for (idx = 0; idx < symcount; idx++)
- {
- if (!sym_is_global (abfd, syms[idx]))
- num_locals++;
- else
- num_globals++;
- }
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- if (sect_syms[asect->index] != NULL
- && sect_syms[asect->index]->flags == 0)
- {
- sect_syms[asect->index]->flags = BSF_SECTION_SYM;
- if (!sym_is_global (abfd, sect_syms[asect->index]))
- num_locals++;
- else
- num_globals++;
- sect_syms[asect->index]->flags = 0;
- }
- }
-
- /* Now sort the symbols so the local symbols are first. */
- new_syms = ((asymbol **)
- bfd_alloc (abfd,
- (num_locals + num_globals) * sizeof (asymbol *)));
- if (new_syms == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- for (idx = 0; idx < symcount; idx++)
- {
- asymbol *sym = syms[idx];
- int i;
-
- if (!sym_is_global (abfd, sym))
- i = num_locals2++;
- else
- i = num_locals + num_globals2++;
- new_syms[i] = sym;
- sym->udata.i = i + 1;
- }
- for (asect = abfd->sections; asect; asect = asect->next)
- {
- if (sect_syms[asect->index] != NULL
- && sect_syms[asect->index]->flags == 0)
- {
- asymbol *sym = sect_syms[asect->index];
- int i;
-
- sym->flags = BSF_SECTION_SYM;
- if (!sym_is_global (abfd, sym))
- i = num_locals2++;
- else
- i = num_locals + num_globals2++;
- new_syms[i] = sym;
- sym->udata.i = i + 1;
- }
- }
-
- bfd_set_symtab (abfd, new_syms, num_locals + num_globals);
-
- 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);
- boolean failed;
- struct bfd_strtab_hash *strtab;
- 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;
-
- failed = false;
- bfd_map_over_sections (abfd, elf_fake_sections, &failed);
- if (failed)
- return false;
-
- if (!assign_section_numbers (abfd))
- return false;
-
- /* The backend linker builds symbol table information itself. */
- if (link_info == NULL)
- {
- if (! swap_out_syms (abfd, &strtab))
- 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 = _bfd_stringtab_size (elf_shstrtab (abfd));
- 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;
-
- if (!assign_file_positions_except_relocs (abfd,
- link_info == NULL ? true : false))
- return false;
-
- if (link_info == NULL)
- {
- /* Now that we know where the .strtab section goes, write it
- out. */
- if ((bfd_seek (abfd, elf_tdata (abfd)->strtab_hdr.sh_offset, SEEK_SET)
- != 0)
- || ! _bfd_stringtab_emit (abfd, strtab))
- return false;
- _bfd_stringtab_free (strtab);
- }
-
- 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->bfd_section != NULL)
- i_shdrp->bfd_section->filepos = offset;
- if (i_shdrp->sh_type != SHT_NOBITS)
- offset += i_shdrp->sh_size;
- return offset;
-}
-
-/* Get the size of the program header.
-
- SORTED_HDRS, if non-NULL, is an array of COUNT pointers to headers sorted
- by VMA. Non-allocated sections (!SHF_ALLOC) must appear last. All
- section VMAs and sizes are known so we can compute the correct value.
- (??? This may not be perfectly true. What cases do we miss?)
-
- If SORTED_HDRS is NULL we assume there are two segments: text and data
- (exclusive of .interp and .dynamic).
-
- If this is called by the linker before any of the section VMA's are set, it
- can't calculate the correct value for a strange memory layout. This only
- happens when SIZEOF_HEADERS is used in a linker script. In this case,
- SORTED_HDRS is NULL and we assume the normal scenario of one text and one
- data segment (exclusive of .interp and .dynamic).
-
- ??? User written scripts must either not use SIZEOF_HEADERS, or assume there
- will be two segments. */
-
-static bfd_size_type
-get_program_header_size (abfd, sorted_hdrs, count, maxpagesize)
- bfd *abfd;
- Elf_Internal_Shdr **sorted_hdrs;
- unsigned int count;
- bfd_vma maxpagesize;
-{
- size_t segs;
- asection *s;
-
- /* We can't return a different result each time we're called. */
- if (elf_tdata (abfd)->program_header_size != 0)
- return elf_tdata (abfd)->program_header_size;
-
- if (sorted_hdrs != NULL)
- {
- unsigned int i;
- unsigned int last_type;
- Elf_Internal_Shdr **hdrpp;
- /* What we think the current segment's offset is. */
- bfd_vma p_offset;
- /* What we think the current segment's address is. */
- bfd_vma p_vaddr;
- /* How big we think the current segment is. */
- bfd_vma p_memsz;
- /* What we think the current file offset is. */
- bfd_vma file_offset;
- bfd_vma next_offset;
-
- /* Scan the headers and compute the number of segments required. This
- code is intentionally similar to the code in map_program_segments.
-
- The `sh_offset' field isn't valid at this point, so we keep our own
- running total in `file_offset'.
-
- This works because section VMAs are already known. */
-
- segs = 1;
- /* Make sure the first section goes in the first segment. */
- file_offset = p_offset = sorted_hdrs[0]->sh_addr % maxpagesize;
- p_vaddr = sorted_hdrs[0]->sh_addr;
- p_memsz = 0;
- last_type = SHT_PROGBITS;
-
- for (i = 0, hdrpp = sorted_hdrs; i < count; 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;
-
- /* Keep track of where this and the next sections go.
- The section VMA must equal the file position modulo
- the page size. */
- file_offset += (hdr->sh_addr - file_offset) % maxpagesize;
- next_offset = file_offset;
- if (hdr->sh_type != SHT_NOBITS)
- next_offset = file_offset + hdr->sh_size;
-
- /* If this section fits in the segment we are constructing, add
- it in. */
- if ((file_offset - (p_offset + p_memsz)
- == hdr->sh_addr - (p_vaddr + p_memsz))
- && (last_type != SHT_NOBITS || hdr->sh_type == SHT_NOBITS))
- {
- bfd_size_type adjust;
-
- adjust = hdr->sh_addr - (p_vaddr + p_memsz);
- p_memsz += hdr->sh_size + adjust;
- file_offset = next_offset;
- last_type = hdr->sh_type;
- continue;
- }
-
- /* The section won't fit, start a new segment. */
- ++segs;
-
- /* Initialize the segment. */
- p_vaddr = hdr->sh_addr;
- p_memsz = hdr->sh_size;
- p_offset = file_offset;
- file_offset = next_offset;
-
- last_type = hdr->sh_type;
- }
- }
- else
- {
- /* 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;
- }
-
- elf_tdata (abfd)->program_header_size = segs * sizeof (Elf_External_Phdr);
- return elf_tdata (abfd)->program_header_size;
-}
-
-/* Create the program header. OFF is the file offset where the
- program header should be written. FIRST is the first loadable ELF
- section. SORTED_HDRS is the ELF sections sorted by section
- address. 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, sorted_hdrs, phdr_size)
- bfd *abfd;
- file_ptr off;
- Elf_Internal_Shdr *first;
- Elf_Internal_Shdr **sorted_hdrs;
- 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 = sorted_hdrs;
- 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;
- }
-
- /* The section won't fit, start a new segment. If we're already in one,
- move to the next one. */
- if (phdr->p_type != PT_NULL)
- {
- ++phdr;
- ++phdr_count;
- }
-
- /* Initialize the 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))
- {
- ((*_bfd_error_handler)
- ("%s: Not enough room for program headers (allocated %lu, need %u)",
- bfd_get_filename (abfd),
- (unsigned long) (phdr_size / sizeof (Elf_External_Phdr)),
- phdr_count));
- bfd_set_error (bfd_error_bad_value);
- return (file_ptr) -1;
- }
-
- /* 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;
- size_t hdrppsize;
- Elf_Internal_Shdr **sorted_hdrs;
- Elf_Internal_Shdr **hdrpp;
- unsigned int i;
- Elf_Internal_Shdr *first;
- file_ptr phdr_map;
-
- /* We are creating an executable. */
-
- maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
- if (maxpagesize == 0)
- maxpagesize = 1;
-
- /* We must sort the sections. The GNU linker will always create
- the sections in an appropriate order, but the Irix 5 linker
- will not. We don't include the dummy first section in the
- sort. We sort sections which are not SHF_ALLOC to the end. */
- hdrppsize = (i_ehdrp->e_shnum - 1) * sizeof (Elf_Internal_Shdr *);
- sorted_hdrs = (Elf_Internal_Shdr **) malloc (hdrppsize);
- if (sorted_hdrs == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- memcpy (sorted_hdrs, i_shdrpp + 1, hdrppsize);
- qsort (sorted_hdrs, i_ehdrp->e_shnum - 1, sizeof (Elf_Internal_Shdr *),
- elf_sort_hdrs);
-
- /* We can't actually create the program header until we have set the
- file positions for the sections, and we can't do that until we know
- how big the header is going to be. */
- off = align_file_position (off);
- phdr_size = get_program_header_size (abfd,
- sorted_hdrs, i_ehdrp->e_shnum - 1,
- maxpagesize);
- if (phdr_size == (file_ptr) -1)
- return false;
-
- /* Compute the file offsets of each section. */
- phdr_off = off;
- off += phdr_size;
- first = NULL;
- for (i = 1, hdrpp = sorted_hdrs; i < i_ehdrp->e_shnum; i++, hdrpp++)
- {
- Elf_Internal_Shdr *hdr;
-
- hdr = *hdrpp;
- if ((hdr->sh_flags & SHF_ALLOC) == 0)
- {
- if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
- {
- hdr->sh_offset = -1;
- continue;
- }
- if (! dosyms
- && (hdr == i_shdrpp[tdata->symtab_section]
- || hdr == i_shdrpp[tdata->strtab_section]))
- {
- hdr->sh_offset = -1;
- continue;
- }
- }
- else
- {
- if (first == NULL)
- first = hdr;
-
- /* 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);
- }
-
- /* Create the program header. */
- phdr_map = map_program_segments (abfd, phdr_off, first, sorted_hdrs,
- phdr_size);
- if (phdr_map == (file_ptr) -1)
- return false;
- BFD_ASSERT ((bfd_size_type) phdr_map <= (bfd_size_type) phdr_off + phdr_size);
-
- free (sorted_hdrs);
- }
-
- /* 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;
-}
-
-/* Sort the ELF headers by VMA. We sort headers which are not
- SHF_ALLOC to the end. */
-
-
-static int
-elf_sort_hdrs (arg1, arg2)
- const PTR arg1;
- const PTR arg2;
-{
- int ret;
- const Elf_Internal_Shdr *hdr1 = *(const Elf_Internal_Shdr **) arg1;
- const Elf_Internal_Shdr *hdr2 = *(const Elf_Internal_Shdr **) arg2;
-
-#define TOEND(x) (((x)->sh_flags & SHF_ALLOC)==0)
-
- if (TOEND(hdr1))
- if (TOEND(hdr2))
- return 0;
- else
- return 1;
-
- if (TOEND(hdr2))
- return -1;
-
- if (hdr1->sh_addr < hdr2->sh_addr)
- return -1;
- else if (hdr1->sh_addr > hdr2->sh_addr)
- return 1;
- /* Put !SHT_NOBITS sections before SHT_NOBITS ones.
- The main loop in map_program_segments requires this. */
- ret = (hdr1->sh_type == SHT_NOBITS) - (hdr2->sh_type == SHT_NOBITS);
- if (ret != 0)
- return ret;
- if (hdr1->sh_size < hdr2->sh_size)
- return -1;
- if (hdr1->sh_size > hdr2->sh_size)
- return 1;
- return 0;
- }
-
-
-
-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 bfd_strtab_hash *shstrtab;
-
- i_ehdrp = elf_elfheader (abfd);
- i_shdrp = elf_elfsections (abfd);
-
- shstrtab = elf_stringtab_init ();
- if (shstrtab == NULL)
- 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_PPC;
- break;
-/* start-sanitize-arc */
- case bfd_arch_arc:
- i_ehdrp->e_machine = EM_CYGNUS_ARC;
- break;
-/* end-sanitize-arc */
- /* 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 =
- (unsigned int) _bfd_stringtab_add (shstrtab, ".symtab", true, false);
- elf_tdata (abfd)->strtab_hdr.sh_name =
- (unsigned int) _bfd_stringtab_add (shstrtab, ".strtab", true, false);
- elf_tdata (abfd)->shstrtab_hdr.sh_name =
- (unsigned int) _bfd_stringtab_add (shstrtab, ".shstrtab", true, false);
- 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, sttp)
- bfd *abfd;
- struct bfd_strtab_hash **sttp;
-{
- if (!elf_map_symbols (abfd))
- return false;
-
- /* Dump out the symtabs. */
- {
- int symcount = bfd_get_symcount (abfd);
- asymbol **syms = bfd_get_outsymbols (abfd);
- struct bfd_strtab_hash *stt;
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
- Elf_External_Sym *outbound_syms;
- int idx;
-
- stt = elf_stringtab_init ();
- if (stt == NULL)
- 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 == NULL)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- symtab_hdr->contents = (PTR) outbound_syms;
-
- /* 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);
- ++outbound_syms;
- }
- for (idx = 0; idx < symcount; idx++)
- {
- Elf_Internal_Sym sym;
- bfd_vma value = syms[idx]->value;
- elf_symbol_type *type_ptr;
- flagword flags = syms[idx]->flags;
-
- if (flags & BSF_SECTION_SYM)
- /* Section symbols have no names. */
- sym.st_name = 0;
- else
- {
- sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
- syms[idx]->name,
- true, false);
- 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;
- if (type_ptr == NULL
- || type_ptr->internal_elf_sym.st_value == 0)
- sym.st_value = value >= 16 ? 16 : (1 << bfd_log2 (value));
- else
- sym.st_value = type_ptr->internal_elf_sym.st_value;
- 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 (((flags & BSF_WEAK)
- ? STB_WEAK
- : STB_GLOBAL),
- ((flags & BSF_FUNCTION)
- ? STT_FUNC
- : STT_NOTYPE));
- else if (flags & BSF_SECTION_SYM)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- else if (flags & BSF_FILE)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
- else
- {
- int bind = STB_LOCAL;
- int type = STT_OBJECT;
-
- 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);
- ++outbound_syms;
- }
-
- *sttp = stt;
- symstrtab_hdr->sh_size = _bfd_stringtab_size (stt);
- 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;
- }
-
- 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;
-
- i_ehdrp = elf_elfheader (abfd);
- i_shdrp = elf_elfsections (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 (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;
- boolean failed;
- 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);
-
- failed = false;
- bfd_map_over_sections (abfd, write_relocs, &failed);
- if (failed)
- return false;
- 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;
- }
- }
-
- /* Write out the section header names. */
- if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
- || ! _bfd_stringtab_emit (abfd, elf_shstrtab (abfd)))
- 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 ELF section number, retrieve the corresponding BFD
- section. */
-
-static asection *
-section_from_elf_index (abfd, index)
- bfd *abfd;
- unsigned int index;
-{
- BFD_ASSERT (index > 0 && index < SHN_LORESERVE);
- if (index >= elf_elfheader (abfd)->e_shnum)
- return NULL;
- return elf_elfsections (abfd)[index]->bfd_section;
-}
-
-/* given a section, search the header to find them... */
-static int
-elf_section_from_bfd_section (abfd, asect)
- bfd *abfd;
- struct sec *asect;
-{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
- int index;
- Elf_Internal_Shdr *hdr;
- int maxindex = elf_elfheader (abfd)->e_shnum;
-
- for (index = 0; index < maxindex; index++)
- {
- hdr = i_shdrp[index];
- if (hdr->bfd_section == asect)
- return index;
- }
-
- if (bed->elf_backend_section_from_bfd_section)
- {
- for (index = 0; index < maxindex; index++)
- {
- int retval;
-
- hdr = i_shdrp[index];
- retval = index;
- if ((*bed->elf_backend_section_from_bfd_section)
- (abfd, hdr, asect, &retval))
- return retval;
- }
- }
-
- 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;
-}
-
-/* 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.i == 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.i = elf_section_syms (abfd)[indx]->udata.i;
- }
-
- idx = asym_ptr->udata.i;
- BFD_ASSERT (idx != 0);
-
-#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:
- if (i_sym.st_shndx != SHN_UNDEF
- && i_sym.st_shndx != SHN_COMMON)
- 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 (num, hdr)
- int num;
- Elf_Internal_Shdr *hdr;
-{
- fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num,
- hdr->bfd_section != NULL ? hdr->bfd_section->name : "",
- (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);
- 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);
-}
-
-static char *
-elf_symbol_flags (flags)
- flagword flags;
-{
- static char buffer[1024];
-
- buffer[0] = '\0';
- if (flags & BSF_LOCAL)
- strcat (buffer, " local");
-
- if (flags & BSF_GLOBAL)
- strcat (buffer, " global");
-
- if (flags & BSF_DEBUGGING)
- strcat (buffer, " debug");
-
- if (flags & BSF_FUNCTION)
- strcat (buffer, " function");
-
- if (flags & BSF_KEEP)
- strcat (buffer, " keep");
-
- if (flags & BSF_KEEP_G)
- strcat (buffer, " keep_g");
-
- if (flags & BSF_WEAK)
- strcat (buffer, " weak");
-
- if (flags & BSF_SECTION_SYM)
- strcat (buffer, " section-sym");
-
- if (flags & BSF_OLD_COMMON)
- strcat (buffer, " old-common");
-
- if (flags & BSF_NOT_AT_END)
- strcat (buffer, " not-at-end");
-
- if (flags & BSF_CONSTRUCTOR)
- strcat (buffer, " constructor");
-
- if (flags & BSF_WARNING)
- strcat (buffer, " warning");
-
- if (flags & BSF_INDIRECT)
- strcat (buffer, " indirect");
-
- if (flags & BSF_FILE)
- strcat (buffer, " file");
-
- if (flags & DYNAMIC)
- strcat (buffer, " dynamic");
-
- if (flags & ~(BSF_LOCAL
- | BSF_GLOBAL
- | BSF_DEBUGGING
- | BSF_FUNCTION
- | BSF_KEEP
- | BSF_KEEP_G
- | BSF_WEAK
- | BSF_SECTION_SYM
- | BSF_OLD_COMMON
- | BSF_NOT_AT_END
- | BSF_CONSTRUCTOR
- | BSF_WARNING
- | BSF_INDIRECT
- | BSF_FILE
- | BSF_DYNAMIC))
- strcat (buffer, " unknown-bits");
-
- return buffer;
-}
-#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, (Elf_Internal_Shdr **) NULL, 0,
- (bfd_vma) 0);
- 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 = (((prpsinfo_t *) 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
- && (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1)
- && (ebd->elf_machine_alt2 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt2))
- {
- 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_export_symbol
- PARAMS ((struct elf_link_hash_entry *, PTR));
-static boolean elf_adjust_dynamic_symbol
- PARAMS ((struct elf_link_hash_entry *, PTR));
-
-/* This struct is used to pass information to routines called via
- elf_link_hash_traverse which must return failure. */
-
-struct elf_info_failed
-{
- boolean failed;
- struct bfd_link_info *info;
-};
-
-/* 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;
-{
- bfd *first;
-
- switch (bfd_get_format (abfd))
- {
- case bfd_object:
- return elf_link_add_object_symbols (abfd, info);
- case bfd_archive:
- first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
- if (first == NULL)
- {
- /* It's OK to have an empty archive. */
- return true;
- }
- if (! bfd_check_format (first, bfd_object))
- return false;
- if (bfd_get_flavour (first) != bfd_target_elf_flavour)
- {
- /* On Linux, we may have an a.out archive which got
- recognized as an ELF archive. Therefore, we treat all
- archives as though they were actually of the flavour of
- their first element. */
- return (*first->xvec->_bfd_link_add_symbols) (abfd, info);
- }
- 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))
- {
- /* An empty archive is a special case. */
- if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
- return true;
- 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.
- Note that we may actually call this function even though we are not
- going to output any dynamic symbols; in some cases we know that a
- symbol should be in the dynamic symbol table, but only if there is
- one. */
-
-boolean
-elf_link_record_dynamic_symbol (info, h)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
-{
- if (h->dynindx == -1)
- {
- struct bfd_strtab_hash *dynstr;
-
- h->dynindx = elf_hash_table (info)->dynsymcount;
- ++elf_hash_table (info)->dynsymcount;
-
- dynstr = elf_hash_table (info)->dynstr;
- if (dynstr == NULL)
- {
- /* Create a strtab to hold the dynamic symbol names. */
- elf_hash_table (info)->dynstr = dynstr = elf_stringtab_init ();
- if (dynstr == NULL)
- return false;
- }
-
- h->dynstr_index = ((unsigned long)
- _bfd_stringtab_add (dynstr, h->root.root.string,
- true, false));
- 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)->dynamic_sections_created
- && abfd->xvec == info->hash->creator)
- {
- if (! elf_link_create_dynamic_sections (abfd, info))
- goto error_return;
- }
- }
- else
- {
- asection *s;
- const char *name;
- bfd_size_type oldsize;
- bfd_size_type 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;
- }
- if (dyn.d_tag == DT_NEEDED)
- elf_hash_table (info)->saw_needed = true;
- }
-
- 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. */
- if (! elf_hash_table (info)->dynamic_sections_created)
- {
- if (! elf_link_create_dynamic_sections (abfd, info))
- goto error_return;
- }
-
- /* Add a DT_NEEDED entry for this dynamic object. */
- oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
- strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
- true, false);
- if (strindex == (bfd_size_type) -1)
- goto error_return;
-
- if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
- {
- asection *sdyn;
- Elf_External_Dyn *dyncon, *dynconend;
-
- /* The hash table size did not change, which means that the
- dynamic object name was already entered. If we have
- already included this dynamic object in the link, just
- ignore it. There is no reason to include a particular
- dynamic object more than once. */
- sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
- ".dynamic");
- BFD_ASSERT (sdyn != NULL);
-
- dyncon = (Elf_External_Dyn *) sdyn->contents;
- dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
- for (; dyncon < dynconend; dyncon++)
- {
- Elf_Internal_Dyn dyn;
-
- elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon, &dyn);
- if (dyn.d_tag == DT_NEEDED
- && dyn.d_un.d_val == strindex)
- {
- if (buf != NULL)
- free (buf);
- return true;
- }
- }
- }
-
- 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)
- {
- if (sym.st_shndx != SHN_UNDEF
- && sym.st_shndx != SHN_COMMON)
- flags = BSF_GLOBAL;
- else
- flags = 0;
- }
- 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)
- value -= sec->vma;
- else
- sec = bfd_abs_section_ptr;
- }
- 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 (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
- || h->root.type == bfd_link_hash_defweak)
- 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->root.type == bfd_link_hash_defweak)
- && (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;
- }
- }
-
- 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
- && info->hash->creator->flavour == bfd_target_elf_flavour
- && (*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
- && (*sym_hash)->root.type == bfd_link_hash_common)
- (*sym_hash)->root.u.c.p->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
- || hlook->root.type == bfd_link_hash_defweak);
- 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 != NULL && h != hlook
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && 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. ABFD is an input file which requires dynamic sections
- to be created. 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;
-
- if (elf_hash_table (info)->dynamic_sections_created)
- return true;
-
- /* Make sure that all dynamic sections use the same input BFD. */
- if (elf_hash_table (info)->dynobj == NULL)
- elf_hash_table (info)->dynobj = abfd;
- else
- abfd = elf_hash_table (info)->dynobj;
-
- /* 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;
-
- 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. */
- if (elf_hash_table (info)->dynstr == NULL)
- {
- elf_hash_table (info)->dynstr = elf_stringtab_init ();
- 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);
- if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
- return false;
-
- elf_hash_table (info)->dynamic_sections_created = true;
-
- return true;
-}
-
-/* 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;
- }