-static boolean
-swap_out_syms (abfd)
- bfd *abfd;
-{
- if (!elf_map_symbols (abfd))
- return false;
-
- /* Dump out the symtabs. */
- {
- int symcount = bfd_get_symcount (abfd);
- asymbol **syms = bfd_get_outsymbols (abfd);
- struct strtab *stt = bfd_new_strtab (abfd);
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
- Elf_External_Sym *outbound_syms;
- int idx;
-
- if (!stt)
- return false;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- symtab_hdr->sh_type = SHT_SYMTAB;
- symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
- symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
- symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
-
- /* FIXME: Systems I've checked use 4 byte alignment for .symtab,
- but it is possible that there are systems which use a different
- alignment. */
- symtab_hdr->sh_addralign = 4;
-
- /* see assert in elf_fake_sections that supports this: */
- symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
- symstrtab_hdr->sh_type = SHT_STRTAB;
-
- outbound_syms = (Elf_External_Sym *)
- bfd_alloc (abfd, (1 + symcount) * sizeof (Elf_External_Sym));
- if (!outbound_syms)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- /* now generate the data (for "contents") */
- {
- /* Fill in zeroth symbol and swap it out. */
- Elf_Internal_Sym sym;
- sym.st_name = 0;
- sym.st_value = 0;
- sym.st_size = 0;
- sym.st_info = 0;
- sym.st_other = 0;
- sym.st_shndx = SHN_UNDEF;
- elf_swap_symbol_out (abfd, &sym, outbound_syms);
- }
- for (idx = 0; idx < symcount; idx++)
- {
- Elf_Internal_Sym sym;
- bfd_vma value = syms[idx]->value;
-
- if (syms[idx]->flags & BSF_SECTION_SYM)
- /* Section symbols have no names. */
- sym.st_name = 0;
- else
- sym.st_name = bfd_add_to_strtab (abfd, stt, syms[idx]->name);
-
- if (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;
- /* Should retrieve this from somewhere... */
- sym.st_value = 16;
- sym.st_shndx = elf_section_from_bfd_section (abfd,
- syms[idx]->section);
- }
- else
- {
- asection *sec = syms[idx]->section;
- elf_symbol_type *type_ptr;
- int shndx;
-
- if (sec->output_section)
- {
- value += sec->output_offset;
- sec = sec->output_section;
- }
- value += sec->vma;
- sym.st_value = value;
- type_ptr = elf_symbol_from (abfd, syms[idx]);
- 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 (syms[idx]->section == &bfd_und_section)
- sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE);
- else if (syms[idx]->flags & BSF_SECTION_SYM)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
- else if (syms[idx]->flags & BSF_FILE)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
- else
- {
- int bind = STB_LOCAL;
- int type = STT_OBJECT;
- unsigned int flags = syms[idx]->flags;
-
- if (flags & BSF_LOCAL)
- bind = STB_LOCAL;
- else if (flags & BSF_WEAK)
- bind = STB_WEAK;
- else if (flags & BSF_GLOBAL)
- bind = STB_GLOBAL;
-
- if (flags & BSF_FUNCTION)
- type = STT_FUNC;
-
- sym.st_info = ELF_ST_INFO (bind, type);
- }
-
- sym.st_other = 0;
- elf_swap_symbol_out (abfd, &sym,
- (outbound_syms
- + elf_sym_extra (abfd)[idx].elf_sym_num));
- }
-
- symtab_hdr->contents = (PTR) outbound_syms;
- symstrtab_hdr->contents = (PTR) stt->tab;
- symstrtab_hdr->sh_size = stt->length;
- symstrtab_hdr->sh_type = SHT_STRTAB;
-
- symstrtab_hdr->sh_flags = 0;
- symstrtab_hdr->sh_addr = 0;
- symstrtab_hdr->sh_entsize = 0;
- symstrtab_hdr->sh_link = 0;
- symstrtab_hdr->sh_info = 0;
- symstrtab_hdr->sh_addralign = 1;
- symstrtab_hdr->size = 0;
- }
-
- /* put the strtab out too... */
- {
- Elf_Internal_Shdr *this_hdr;
-
- this_hdr = &elf_tdata (abfd)->shstrtab_hdr;
- this_hdr->contents = (PTR) elf_shstrtab (abfd)->tab;
- this_hdr->sh_size = elf_shstrtab (abfd)->length;
- this_hdr->sh_type = SHT_STRTAB;
- this_hdr->sh_flags = 0;
- this_hdr->sh_addr = 0;
- this_hdr->sh_entsize = 0;
- this_hdr->sh_addralign = 1;
- this_hdr->size = 0;
- }
- return true;
-}
-
-static boolean
-write_shdrs_and_ehdr (abfd)
- bfd *abfd;
-{
- Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
- Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_External_Shdr *x_shdrp; /* Section header table, external form */
- Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
- unsigned int count;
- struct strtab *shstrtab;
-
- i_ehdrp = elf_elfheader (abfd);
- i_shdrp = elf_elfsections (abfd);
- shstrtab = elf_shstrtab (abfd);
-
- /* swap the header before spitting it out... */
-
-#if DEBUG & 1
- elf_debug_file (i_ehdrp);
-#endif
- elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr);
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
- || (bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd)
- != sizeof (x_ehdr)))
- return false;
-
- /* at this point we've concocted all the ELF sections... */
- x_shdrp = (Elf_External_Shdr *)
- bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum));
- if (!x_shdrp)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- for (count = 0; count < i_ehdrp->e_shnum; count++)
- {
-#if DEBUG & 2
- elf_debug_section (shstrtab->tab + i_shdrp[count]->sh_name, count,
- i_shdrp[count]);
-#endif
- elf_swap_shdr_out (abfd, i_shdrp[count], x_shdrp + count);
- }
- if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
- || (bfd_write ((PTR) x_shdrp, sizeof (*x_shdrp), i_ehdrp->e_shnum, abfd)
- != sizeof (*x_shdrp)))
- return false;
-
- /* need to dump the string table too... */
-
- return true;
-}
-
-static void
-assign_file_positions_for_relocs (abfd)
- bfd *abfd;
-{
- file_ptr off = elf_tdata (abfd)->next_file_pos;
- unsigned int i;
- Elf_Internal_Shdr **shdrpp = elf_elfsections (abfd);
- Elf_Internal_Shdr *shdrp;
- for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
- {
- shdrp = shdrpp[i];
- if (shdrp->sh_type != SHT_REL && shdrp->sh_type != SHT_RELA)
- continue;
- off = align_file_position (off);
- off = assign_file_position_for_section (shdrp, off);
- }
- elf_tdata (abfd)->next_file_pos = off;
-}
-
-boolean
-NAME(bfd_elf,write_object_contents) (abfd)
- bfd *abfd;
-{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- Elf_Internal_Ehdr *i_ehdrp;
- Elf_Internal_Shdr **i_shdrp;
- unsigned int count;
-
- /* We don't know how to write dynamic objects. Specifically, we
- don't know how to construct the program header. */
- if ((abfd->flags & DYNAMIC) != 0)
- {
- fprintf (stderr, "Writing ELF dynamic objects is not supported\n");
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
-
- if (abfd->output_has_begun == false)
- {
- if (prep_headers (abfd) == false)
- return false;
- if (elf_compute_section_file_positions (abfd) == false)
- return false;
- abfd->output_has_begun = true;
- }
-
- i_shdrp = elf_elfsections (abfd);
- i_ehdrp = elf_elfheader (abfd);
-
- bfd_map_over_sections (abfd, write_relocs, (PTR) 0);
- assign_file_positions_for_relocs (abfd);
-
- /* After writing the headers, we need to write the sections too... */
- for (count = 1; count < i_ehdrp->e_shnum; count++)
- {
- if (bed->elf_backend_section_processing)
- (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
- if (i_shdrp[count]->contents)
- {
- if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
- || (bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size,
- 1, abfd)
- != i_shdrp[count]->sh_size))
- return false;
- }
- }
-
- if (bed->elf_backend_final_write_processing)
- (*bed->elf_backend_final_write_processing) (abfd);
-
- return write_shdrs_and_ehdr (abfd);
-}
-
-/* Given an index of a section, retrieve a pointer to it. Note
- that for our purposes, sections are indexed by {1, 2, ...} with
- 0 being an illegal index. */
-
-/* In the original, each ELF section went into exactly one BFD
- section. This doesn't really make sense, so we need a real mapping.
- The mapping has to hide in the Elf_Internal_Shdr since asection
- doesn't have anything like a tdata field... */
-
-static struct sec *
-section_from_elf_index (abfd, index)
- bfd *abfd;
- unsigned int index;
-{
- /* @@ Is bfd_com_section really correct in all the places it could
- be returned from this routine? */
-
- if (index == SHN_ABS)
- return &bfd_com_section; /* not abs? */
- if (index == SHN_COMMON)
- return &bfd_com_section;
-
- if (index > elf_elfheader (abfd)->e_shnum)
- return 0;
-
- {
- Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[index];
-
- switch (hdr->sh_type)
- {
- /* ELF sections that map to BFD sections */
- case SHT_PROGBITS:
- case SHT_NOBITS:
- if (!hdr->rawdata)
- bfd_section_from_shdr (abfd, index);
- return (struct sec *) hdr->rawdata;
-
- default:
- return (struct sec *) &bfd_abs_section;
- }
- }
-}
-
-/* given a section, search the header to find them... */
-static int
-elf_section_from_bfd_section (abfd, asect)
- bfd *abfd;
- struct sec *asect;
-{
- Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
- int index;
- Elf_Internal_Shdr *hdr;
- int maxindex = elf_elfheader (abfd)->e_shnum;
-
- if (asect == &bfd_abs_section)
- return SHN_ABS;
- if (asect == &bfd_com_section)
- return SHN_COMMON;
- if (asect == &bfd_und_section)
- return SHN_UNDEF;
-
- for (index = 0; index < maxindex; index++)
- {
- hdr = i_shdrp[index];
- switch (hdr->sh_type)
- {
- /* ELF sections that map to BFD sections */
- case SHT_PROGBITS:
- case SHT_NOBITS:
- case SHT_NOTE:
- if (hdr->rawdata)
- {
- if (((struct sec *) (hdr->rawdata)) == asect)
- return index;
- }
- break;
-
- case SHT_STRTAB:
- /* fix_up_strtabs will generate STRTAB sections with names
- of .stab*str. */
- if (!strncmp (asect->name, ".stab", 5)
- && !strcmp ("str", asect->name + strlen (asect->name) - 3))
- {
- if (hdr->rawdata)
- {
- if (((struct sec *) (hdr->rawdata)) == asect)
- return index;
- }
- break;
- }
- /* FALL THROUGH */
- default:
- {
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- if (bed->elf_backend_section_from_bfd_section)
- {
- int retval;
-
- retval = index;
- if ((*bed->elf_backend_section_from_bfd_section)
- (abfd, hdr, asect, &retval))
- return retval;
- }
- }
- break;
- }
- }
- return -1;
-}
-
-/* given a symbol, return the bfd index for that symbol. */
-static int
-elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
- bfd *abfd;
- struct symbol_cache_entry **asym_ptr_ptr;
-{
- struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr;
- int idx;
- flagword flags = asym_ptr->flags;
-
- /* When gas creates relocations against local labels, it creates its
- own symbol for the section, but does put the symbol into the
- symbol chain, so udata is 0. When the linker is generating
- relocatable output, this section symbol may be for one of the
- input sections rather than the output section. */
- if (asym_ptr->udata == (PTR) 0
- && (flags & BSF_SECTION_SYM)
- && asym_ptr->section)
- {
- int indx;
-
- if (asym_ptr->section->output_section != NULL)
- indx = asym_ptr->section->output_section->index;
- else
- indx = asym_ptr->section->index;
- if (elf_section_syms (abfd)[indx])
- asym_ptr->udata = elf_section_syms (abfd)[indx]->udata;
- }
-
- if (asym_ptr->udata)
- idx = ((Elf_Sym_Extra *) asym_ptr->udata)->elf_sym_num;
- else
- {
- abort ();
- }
-
-#if DEBUG & 4
- {
-
- fprintf (stderr,
- "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx %s\n",
- (long) asym_ptr, asym_ptr->name, idx, flags, elf_symbol_flags (flags));
- fflush (stderr);
- }
-#endif
-
- return idx;
-}
-
-static boolean
-elf_slurp_symbol_table (abfd, symptrs)
- bfd *abfd;
- asymbol **symptrs; /* Buffer for generated bfd symbols */
-{
- Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_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;
-
- /* this is only valid because there is only one symtab... */
- /* FIXME: This is incorrect, there may also be a dynamic symbol
- table which is a subset of the full symbol table. We either need
- to be prepared to read both (and merge them) or ensure that we
- only read the full symbol table. Currently we only get called to
- read the full symbol table. -fnf */
-
- /* 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 (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
- return false;
-
- 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 false;
-
- 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 false;
- }
- 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_LORESERV)