- 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;
-
- i_ehdrp->e_type = (abfd->flags & EXEC_P) ? ET_EXEC : ET_REL;
- switch (bfd_get_arch (abfd))
- {
- case bfd_arch_unknown:
- i_ehdrp->e_machine = EM_NONE;
- break;
- case bfd_arch_sparc:
- i_ehdrp->e_machine = EM_SPARC;
- /* start-sanitize-v9 */
-#if ARCH_SIZE == 64
- i_ehdrp->e_machine = EM_SPARC64;
-#endif
- /* end-sanitize-v9 */
- 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_HPPA;
- break;
- case bfd_arch_powerpc:
- i_ehdrp->e_machine = EM_CYGNUS_POWERPC;
- break;
- /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
- default:
- i_ehdrp->e_machine = EM_NONE;
- }
- i_ehdrp->e_version = EV_CURRENT;
- i_ehdrp->e_ehsize = sizeof (Elf_External_Ehdr);
-
- /* no program header, for now. */
- i_ehdrp->e_phoff = 0;
- i_ehdrp->e_phentsize = 0;
- i_ehdrp->e_phnum = 0;
-
- /* each bfd section is section header entry */
- i_ehdrp->e_entry = bfd_get_start_address (abfd);
- i_ehdrp->e_shentsize = sizeof (Elf_External_Shdr);
-
- /* if we're building an executable, we'll need a program header table */
- if (abfd->flags & EXEC_P)
- {
- /* it all happens later */
-#if 0
- i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
-
- /* elf_build_phdrs() returns a (NULL-terminated) array of
- Elf_Internal_Phdrs */
- i_phdrp = elf_build_phdrs (abfd, i_ehdrp, i_shdrp, &i_ehdrp->e_phnum);
- i_ehdrp->e_phoff = outbase;
- outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum;
-#endif
- }
- else
- {
- i_ehdrp->e_phentsize = 0;
- i_phdrp = 0;
- i_ehdrp->e_phoff = 0;
- }
-
- elf_tdata (abfd)->symtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
- ".symtab");
- elf_tdata (abfd)->strtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
- ".strtab");
- elf_tdata (abfd)->shstrtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab,
- ".shstrtab");
- return true;
-}
-
-static boolean
-swap_out_syms (abfd)
- bfd *abfd;
-{
- if (!elf_map_symbols (abfd))
- return false;
-
- /* Dump out the symtabs. */
- {
- int symcount = bfd_get_symcount (abfd);
- asymbol **syms = bfd_get_outsymbols (abfd);
- struct strtab *stt = bfd_new_strtab (abfd);
- Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *symstrtab_hdr;
- Elf_External_Sym *outbound_syms;
- int idx;
-
- if (!stt)
- return false;
- symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- symtab_hdr->sh_type = SHT_SYMTAB;
- symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
- symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
- symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
-
- /* 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) * i_ehdrp->e_shnum))
- 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)
- {
- /* Do any elf backend specific processing first. */
- if (bed->elf_backend_begin_write_processing)
- (*bed->elf_backend_begin_write_processing) (abfd);
-
- 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 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_LORESERV)
- {
- sym->symbol.section = section_from_elf_index (abfd,
- i_sym.st_shndx);
- }
- else if (i_sym.st_shndx == SHN_ABS)
- {
- sym->symbol.section = &bfd_abs_section;
- }
- else if (i_sym.st_shndx == SHN_COMMON)
- {
- sym->symbol.section = &bfd_com_section;
- /* 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;
- }
- else
- sym->symbol.section = &bfd_abs_section;
-
- sym->symbol.value -= sym->symbol.section->vma;
-
- switch (ELF_ST_BIND (i_sym.st_info))
- {
- case STB_LOCAL:
- sym->symbol.flags |= BSF_LOCAL;
- break;
- case STB_GLOBAL:
- sym->symbol.flags |= BSF_GLOBAL;
- break;
- case STB_WEAK:
- sym->symbol.flags |= BSF_WEAK;
- break;
- }
-
- switch (ELF_ST_TYPE (i_sym.st_info))
- {
- case STT_SECTION:
- sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
- break;
- case STT_FILE:
- sym->symbol.flags |= BSF_FILE | BSF_DEBUGGING;
- break;
- case STT_FUNC:
- sym->symbol.flags |= BSF_FUNCTION;
- break;
- }
-
- if (dynamic)
- sym->symbol.flags |= BSF_DYNAMIC;
-
- /* Do some backend-specific processing on this symbol. */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- if (ebd->elf_backend_symbol_processing)
- (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
- }
-
- sym++;
- }
- }
-
- /* Do some backend-specific processing on this symbol table. */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- if (ebd->elf_backend_symbol_table_processing)
- (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
- }
-
- /* We rely on the zalloc to clear out the final symbol entry. */
-
- symcount = sym - symbase;
-
- /* Fill in the user's symbol pointer vector if needed. */
- if (symptrs)
- {
- long l = symcount;
-
- sym = symbase;
- while (l-- > 0)
- {
- *symptrs++ = &sym->symbol;
- sym++;
- }
- *symptrs = 0; /* Final null pointer */
- }
-
- if (x_symp != NULL)
- free (x_symp);
- return symcount;
-error_return:
- if (x_symp != NULL)
- free (x_symp);
- return -1;
-}
-
-/* Return the number of bytes required to hold the symtab vector.
-
- Note that we base it on the count plus 1, since we will null terminate
- the vector allocated based on this size. However, the ELF symbol table
- always has a dummy entry as symbol #0, so it ends up even. */
-
-long
-elf_get_symtab_upper_bound (abfd)
- bfd *abfd;
-{
- long symcount;
- long symtab_size;
- Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
-
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
- symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
-
- return symtab_size;
-}
-
-long
-elf_get_dynamic_symtab_upper_bound (abfd)
- bfd *abfd;
-{
- long symcount;
- long symtab_size;
- Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
-
- symcount = hdr->sh_size / sizeof (Elf_External_Sym);
- symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
-
- return symtab_size;
-}
-
-/*
- This function return the number of bytes required to store the
- relocation information associated with section <<sect>>
- attached to bfd <<abfd>>
-
-*/
-long
-elf_get_reloc_upper_bound (abfd, asect)
- bfd *abfd;
- sec_ptr asect;
-{
- if (asect->flags & SEC_RELOC)
- {
- /* either rel or rela */
- return elf_section_data (asect)->rel_hdr.sh_size;
- }
- else
- return 0;
-}
-
-static boolean
-elf_slurp_reloca_table (abfd, asect, symbols)
- bfd *abfd;
- sec_ptr asect;
- asymbol **symbols;
-{
- Elf_External_Rela *native_relocs;
- arelent *reloc_cache;
- arelent *cache_ptr;
-
- unsigned int idx;
-
- if (asect->relocation)
- return true;
- if (asect->reloc_count == 0)
- return true;
- if (asect->flags & SEC_CONSTRUCTOR)
- return true;
-
- if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
- return false;
- native_relocs = (Elf_External_Rela *)
- bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rela));
- if (!native_relocs)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- if (bfd_read ((PTR) native_relocs,
- sizeof (Elf_External_Rela), asect->reloc_count, abfd)
- != sizeof (Elf_External_Rela) * asect->reloc_count)
- return false;
-
- reloc_cache = (arelent *)
- bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
-
- if (!reloc_cache)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- for (idx = 0; idx < asect->reloc_count; idx++)
- {
- Elf_Internal_Rela dst;
- Elf_External_Rela *src;
-
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
- elf_swap_reloca_in (abfd, src, &dst);
-
-#ifdef RELOC_PROCESSING
- RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
-#else
- if (asect->flags & SEC_RELOC)
- {
- /* relocatable, so the offset is off of the section */
- cache_ptr->address = dst.r_offset + asect->vma;
- }
- else
- {
- /* non-relocatable, so the offset a virtual address */
- cache_ptr->address = dst.r_offset;
- }
-
- /* ELF_R_SYM(dst.r_info) is the symbol table offset. An offset
- of zero points to the dummy symbol, which was not read into
- the symbol table SYMBOLS. */
- if (ELF_R_SYM (dst.r_info) == 0)
- cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
- else
- {
- asymbol *s;
-
- cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
-
- /* Translate any ELF section symbol into a BFD section
- symbol. */
- s = *(cache_ptr->sym_ptr_ptr);
- if (s->flags & BSF_SECTION_SYM)
- {
- cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
- s = *cache_ptr->sym_ptr_ptr;
- if (s->name == 0 || s->name[0] == 0)
- abort ();
- }
- }
- cache_ptr->addend = dst.r_addend;
-
- /* Fill in the cache_ptr->howto field from dst.r_type */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- (*ebd->elf_info_to_howto) (abfd, cache_ptr, &dst);
- }
-#endif
- }
-
- asect->relocation = reloc_cache;
- return true;
-}
-
-#ifdef DEBUG
-static void
-elf_debug_section (str, num, hdr)
- char *str;
- int num;
- Elf_Internal_Shdr *hdr;
-{
- fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num, str, (long) hdr);
- fprintf (stderr,
- "sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n",
- (long) hdr->sh_name,
- (long) hdr->sh_type,
- (long) hdr->sh_flags);
- fprintf (stderr,
- "sh_addr = %ld\tsh_offset = %ld\tsh_size = %ld\n",
- (long) hdr->sh_addr,
- (long) hdr->sh_offset,
- (long) hdr->sh_size);
- fprintf (stderr,
- "sh_link = %ld\tsh_info = %ld\tsh_addralign = %ld\n",
- (long) hdr->sh_link,
- (long) hdr->sh_info,
- (long) hdr->sh_addralign);
- fprintf (stderr, "sh_entsize = %ld\n",
- (long) hdr->sh_entsize);
- fprintf (stderr, "rawdata = 0x%.8lx\n", (long) hdr->rawdata);
- fprintf (stderr, "contents = 0x%.8lx\n", (long) hdr->contents);
- fprintf (stderr, "size = %ld\n", (long) hdr->size);
- fflush (stderr);
-}
-
-static void
-elf_debug_file (ehdrp)
- Elf_Internal_Ehdr *ehdrp;
-{
- fprintf (stderr, "e_entry = 0x%.8lx\n", (long) ehdrp->e_entry);
- fprintf (stderr, "e_phoff = %ld\n", (long) ehdrp->e_phoff);
- fprintf (stderr, "e_phnum = %ld\n", (long) ehdrp->e_phnum);
- fprintf (stderr, "e_phentsize = %ld\n", (long) ehdrp->e_phentsize);
- fprintf (stderr, "e_shoff = %ld\n", (long) ehdrp->e_shoff);
- fprintf (stderr, "e_shnum = %ld\n", (long) ehdrp->e_shnum);
- fprintf (stderr, "e_shentsize = %ld\n", (long) ehdrp->e_shentsize);
-}
-#endif
-
-static boolean
-elf_slurp_reloc_table (abfd, asect, symbols)
- bfd *abfd;
- sec_ptr asect;
- asymbol **symbols;
-{
- Elf_External_Rel *native_relocs;
- arelent *reloc_cache;
- arelent *cache_ptr;
- Elf_Internal_Shdr *data_hdr;
- bfd_vma data_off;
- unsigned long data_max;
- char buf[4]; /* FIXME -- might be elf64 */
-
- unsigned int idx;
-
- if (asect->relocation)
- return true;
- if (asect->reloc_count == 0)
- return true;
- if (asect->flags & SEC_CONSTRUCTOR)
- return true;
-
- if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
- return false;
- native_relocs = (Elf_External_Rel *)
- bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rel));
- if (!native_relocs)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
- if (bfd_read ((PTR) native_relocs,
- sizeof (Elf_External_Rel), asect->reloc_count, abfd)
- != sizeof (Elf_External_Rel) * asect->reloc_count)
- return false;
-
- reloc_cache = (arelent *)
- bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
-
- if (!reloc_cache)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
-
- /* Get the offset of the start of the segment we are relocating to read in
- the implicit addend. */
- data_hdr = &elf_section_data (asect)->this_hdr;
- data_off = data_hdr->sh_offset;
- data_max = data_hdr->sh_size - sizeof (buf) + 1;
-
-#if DEBUG & 2
- elf_debug_section ("data section", -1, data_hdr);
-#endif
-
- for (idx = 0; idx < asect->reloc_count; idx++)
- {
-#ifdef RELOC_PROCESSING
- Elf_Internal_Rel dst;
- Elf_External_Rel *src;
-
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
- elf_swap_reloc_in (abfd, src, &dst);
-
- RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
-#else
- Elf_Internal_Rel dst;
- Elf_External_Rel *src;
-
- cache_ptr = reloc_cache + idx;
- src = native_relocs + idx;
-
- elf_swap_reloc_in (abfd, src, &dst);
-
- if (asect->flags & SEC_RELOC)
- {
- /* relocatable, so the offset is off of the section */
- cache_ptr->address = dst.r_offset + asect->vma;
- }
- else
- {
- /* non-relocatable, so the offset a virtual address */
- cache_ptr->address = dst.r_offset;
- }
-
- /* ELF_R_SYM(dst.r_info) is the symbol table offset. An offset
- of zero points to the dummy symbol, which was not read into
- the symbol table SYMBOLS. */
- if (ELF_R_SYM (dst.r_info) == 0)
- cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
- else
- {
- asymbol *s;
-
- cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1;
-
- /* Translate any ELF section symbol into a BFD section
- symbol. */
- s = *(cache_ptr->sym_ptr_ptr);
- if (s->flags & BSF_SECTION_SYM)
- {
- cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr;
- s = *cache_ptr->sym_ptr_ptr;
- if (s->name == 0 || s->name[0] == 0)
- abort ();
- }
- }
- BFD_ASSERT (dst.r_offset <= data_max);
- cache_ptr->addend = 0;
-
- /* Fill in the cache_ptr->howto field from dst.r_type */
- {
- struct elf_backend_data *ebd = get_elf_backend_data (abfd);
- (*ebd->elf_info_to_howto_rel) (abfd, cache_ptr, &dst);
- }
-#endif
- }
-
- asect->relocation = reloc_cache;
- return true;
-}
-
-long
-elf_canonicalize_reloc (abfd, section, relptr, symbols)
- bfd *abfd;
- sec_ptr section;
- arelent **relptr;
- asymbol **symbols;
-{
- arelent *tblptr = section->relocation;
- unsigned int count = 0;
- int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
-
- /* snarfed from coffcode.h */
- if (use_rela_p)
- {
- if (! elf_slurp_reloca_table (abfd, section, symbols))
- return -1;
- }
- else
- {
- if (! elf_slurp_reloc_table (abfd, section, symbols))
- return -1;
- }
-
- tblptr = section->relocation;
-
- for (; count++ < section->reloc_count;)
- *relptr++ = tblptr++;
-
- *relptr = 0;
- 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);
-}
-
-void
-elf_print_symbol (ignore_abfd, filep, symbol, how)
- bfd *ignore_abfd;
- PTR filep;
- asymbol *symbol;
- bfd_print_symbol_type how;
-{
- FILE *file = (FILE *) filep;
- switch (how)
- {
- case bfd_print_symbol_name:
- fprintf (file, "%s", symbol->name);
- break;
- case bfd_print_symbol_more:
- fprintf (file, "elf ");
- fprintf_vma (file, symbol->value);
- fprintf (file, " %lx", (long) symbol->flags);
- break;
- case bfd_print_symbol_all:
- {
- CONST char *section_name;
- section_name = symbol->section ? symbol->section->name : "(*none*)";
- bfd_print_symbol_vandf ((PTR) file, symbol);
- fprintf (file, " %s\t%s",
- section_name,
- symbol->name);
- }
- break;
- }
-
-}
-
-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;
-{
- /* Allow any architecture to be supported by the elf backend */
- switch (arch)
- {
- case bfd_arch_unknown: /* EM_NONE */
- case bfd_arch_sparc: /* EM_SPARC */
- case bfd_arch_i386: /* EM_386 */
- case bfd_arch_m68k: /* EM_68K */
- case bfd_arch_m88k: /* EM_88K */
- case bfd_arch_i860: /* EM_860 */
- case bfd_arch_mips: /* EM_MIPS (MIPS R3000) */
- case bfd_arch_hppa: /* EM_HPPA (HP PA_RISC) */
- case bfd_arch_powerpc: /* EM_CYGNUS_POWERPC */
- return bfd_default_set_arch_mach (abfd, arch, machine);
- default:
- return false;
- }
-}
-
-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;
-{
- fprintf (stderr, "elf_sizeof_headers unimplemented\n");
- fflush (stderr);
- BFD_FAIL ();
- return 0;
-}
-
-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 == false) /* set by bfd.c handler? */
- {
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- /* Do any elf backend specific processing first. */
- if (bed->elf_backend_begin_write_processing)
- (*bed->elf_backend_begin_write_processing) (abfd);
-
- /* do setup calculations (FIXME) */
- if (prep_headers (abfd) == false)
- return false;
- if (elf_compute_section_file_positions (abfd) == false)
- return false;
- abfd->output_has_begun = true;
- }
-
- 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) /* Define away */
-#define bfd_fpregset(abfd, descdata, descsz, filepos) /* Define away */
-#define bfd_prpsinfo(abfd, descdata, descsz, filepos) /* Define away */
-#endif