From 32090b8e4f645bb5c80e8ad9c38cdd21d5b7b7e0 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Mon, 19 Jul 1993 19:12:59 +0000 Subject: [PATCH] * elf.c, elfcode.h, libelf.h: Serious reorganization. Deleted `thunk' structure, merged into tdata, duplicate data eliminated. Rearranged functions, grouping by function. Broke up many functions in elfcode.h, re-ordered many parts of file writing to handle unpredictable state of section relocation table as provided by various applications. Still needs cleanup: Merge functions back together, split out data structure with only data that is used only when writing out object file. * elf.c (bfd_elf_generic_reloc): New function, taken from coff-mips.c. * elf32-sparc.c (elf_sparc_howto_table): Use it, to work around bfd_perform_relocation lossage. --- bfd/ChangeLog | 22 + bfd/elf.c | 242 +++ bfd/elf32-sparc.c | 151 ++ bfd/elf32-target.h | 1 + bfd/elf64-sparc.c | 76 +- bfd/elfcode.h | 4754 ++++++++++++++++++++++---------------------- bfd/libelf.h | 154 +- 7 files changed, 2960 insertions(+), 2440 deletions(-) create mode 100644 bfd/elf.c create mode 100644 bfd/elf32-sparc.c diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 102ffb279d1..38328702b4c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,25 @@ +Mon Jul 19 14:53:30 1993 Ken Raeburn (raeburn@rtl.cygnus.com) + + * elf.c, elfcode.h, libelf.h: Serious reorganization. + Deleted `thunk' structure, merged into tdata, duplicate data + eliminated. + Rearranged functions, grouping by function. + Broke up many functions in elfcode.h, re-ordered many parts of + file writing to handle unpredictable state of section relocation + table as provided by various applications. + Still needs cleanup: Merge functions back together, split out + data structure with only data that is used only when writing out + object file. + + * elf.c (bfd_elf_generic_reloc): New function, taken from + coff-mips.c. + * elf32-sparc.c (elf_sparc_howto_table): Use it, to work around + bfd_perform_relocation lossage. + + * Makefile.in (BFD_LIBS): Include coff-mips.o and coff-msym.o, so + that gdb will link. + (ofiles): Don't use sort or uniq; do it with sh constructs. + Sun Jul 18 19:42:14 1993 Jim Kingdon (kingdon@rtl.cygnus.com) * coffcode.h: Recognize I386PTXMAGIC. diff --git a/bfd/elf.c b/bfd/elf.c new file mode 100644 index 00000000000..224eaacc470 --- /dev/null +++ b/bfd/elf.c @@ -0,0 +1,242 @@ +/* ELF executable support for BFD. + Copyright 1993 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#define ARCH_SIZE 0 +#include "libelf.h" + +#ifndef INLINE +#if __GNUC__ >= 2 +#define INLINE __inline__ +#else +#define INLINE +#endif +#endif + +/* Standard ELF hash function. Do not change this function; you will + cause invalid hash tables to be generated. (Well, you would if this + were being used yet.) */ +unsigned long +DEFUN (bfd_elf_hash, (name), + CONST unsigned char *name) +{ + unsigned long h = 0; + unsigned long g; + int ch; + + while ((ch = *name++) != '\0') + { + h = (h << 4) + ch; + if ((g = (h & 0xf0000000)) != 0) + { + h ^= g >> 24; + h &= ~g; + } + } + return h; +} + +/* Read a specified number of bytes at a specified offset in an ELF + file, into a newly allocated buffer, and return a pointer to the + buffer. */ + +static char * +DEFUN (elf_read, (abfd, offset, size), + bfd * abfd AND + long offset AND + int size) +{ + char *buf; + + if ((buf = bfd_alloc (abfd, size)) == NULL) + { + bfd_error = no_memory; + return NULL; + } + if (bfd_seek (abfd, offset, SEEK_SET) == -1) + { + bfd_error = system_call_error; + return NULL; + } + if (bfd_read ((PTR) buf, size, 1, abfd) != size) + { + bfd_error = system_call_error; + return NULL; + } + return buf; +} + +boolean +DEFUN (elf_mkobject, (abfd), bfd * abfd) +{ + /* this just does initialization */ + /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */ + elf_tdata (abfd) = (struct elf_obj_tdata *) + bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); + if (elf_tdata (abfd) == 0) + { + bfd_error = no_memory; + return false; + } + /* since everything is done at close time, do we need any + initialization? */ + + return true; +} + +char * +DEFUN (elf_get_str_section, (abfd, shindex), + bfd * abfd AND + unsigned int shindex) +{ + Elf_Internal_Shdr **i_shdrp; + char *shstrtab = NULL; + unsigned int offset; + unsigned int shstrtabsize; + + i_shdrp = elf_elfsections (abfd); + if (i_shdrp == 0 || i_shdrp[shindex] == 0) + return 0; + + shstrtab = i_shdrp[shindex]->rawdata; + if (shstrtab == NULL) + { + /* No cached one, attempt to read, and cache what we read. */ + offset = i_shdrp[shindex]->sh_offset; + shstrtabsize = i_shdrp[shindex]->sh_size; + shstrtab = elf_read (abfd, offset, shstrtabsize); + i_shdrp[shindex]->rawdata = (void *) shstrtab; + } + return shstrtab; +} + +char * +DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex), + bfd * abfd AND + unsigned int shindex AND + unsigned int strindex) +{ + Elf_Internal_Shdr *hdr; + + if (strindex == 0) + return ""; + + hdr = elf_elfsections (abfd)[shindex]; + + if (!hdr->rawdata + && elf_get_str_section (abfd, shindex) == NULL) + return NULL; + + return ((char *) hdr->rawdata) + strindex; +} + +/* +INTERNAL_FUNCTION + bfd_elf_find_section + +SYNOPSIS + struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name); + +DESCRIPTION + Helper functions for GDB to locate the string tables. + Since BFD hides string tables from callers, GDB needs to use an + internal hook to find them. Sun's .stabstr, in particular, + isn't even pointed to by the .stab section, so ordinary + mechanisms wouldn't work to find it, even if we had some. +*/ + +struct elf_internal_shdr * +DEFUN (bfd_elf_find_section, (abfd, name), + bfd * abfd AND + char *name) +{ + Elf_Internal_Shdr **i_shdrp; + char *shstrtab; + unsigned int max; + unsigned int i; + + i_shdrp = elf_elfsections (abfd); + if (i_shdrp != NULL) + { + shstrtab = elf_get_str_section (abfd, elf_elfheader (abfd)->e_shstrndx); + if (shstrtab != NULL) + { + max = elf_elfheader (abfd)->e_shnum; + for (i = 1; i < max; i++) + if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name)) + return i_shdrp[i]; + } + } + return 0; +} + +const struct bfd_elf_arch_map bfd_elf_arch_map[] = { + { bfd_arch_sparc, EM_SPARC }, + { bfd_arch_i386, EM_386 }, + { bfd_arch_m68k, EM_68K }, + { bfd_arch_m88k, EM_88K }, + { bfd_arch_i860, EM_860 }, + { bfd_arch_mips, EM_MIPS }, + { bfd_arch_hppa, EM_HPPA }, +}; + +const int bfd_elf_arch_map_size = sizeof (bfd_elf_arch_map) / sizeof (bfd_elf_arch_map[0]); + +const char *const bfd_elf_section_type_names[] = { + "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB", + "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE", + "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM", +}; + +/* ELF relocs are against symbols. If we are producing relocateable + output, and the reloc is against an external symbol, and nothing + has given us any additional addend, the resulting reloc will also + be against the same symbol. In such a case, we don't want to + change anything about the way the reloc is handled, since it will + all be done at final link time. Rather than put special case code + into bfd_perform_relocation, all the reloc types use this howto + function. It just short circuits the reloc if producing + relocateable output against an external symbol. */ + +bfd_reloc_status_type +bfd_elf_generic_reloc (abfd, + reloc_entry, + symbol, + data, + input_section, + output_bfd) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; +{ + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && reloc_entry->addend == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + return bfd_reloc_continue; +} diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c new file mode 100644 index 00000000000..78c7eaa9900 --- /dev/null +++ b/bfd/elf32-sparc.c @@ -0,0 +1,151 @@ +/* SPARC-specific support for 32-bit ELF + Copyright 1993 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "libelf.h" + +enum reloc_type + { + R_SPARC_NONE = 0, + R_SPARC_8, R_SPARC_16, R_SPARC_32, + R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, + R_SPARC_WDISP30, R_SPARC_WDISP22, + R_SPARC_HI22, R_SPARC_22, + R_SPARC_13, R_SPARC_LO10, + R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, + R_SPARC_PC10, R_SPARC_PC22, + R_SPARC_WPLT30, + R_SPARC_COPY, + R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, + R_SPARC_RELATIVE, + R_SPARC_UA32, + R_SPARC_max + }; + +#if 0 +static CONST char *CONST reloc_type_names[] = +{ + "R_SPARC_NONE", + "R_SPARC_8", "R_SPARC_16", "R_SPARC_32", + "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32", + "R_SPARC_WDISP30", "R_SPARC_WDISP22", + "R_SPARC_HI22", "R_SPARC_22", + "R_SPARC_13", "R_SPARC_LO10", + "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", + "R_SPARC_PC10", "R_SPARC_PC22", + "R_SPARC_WPLT30", + "R_SPARC_COPY", + "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", + "R_SPARC_RELATIVE", + "R_SPARC_UA32", +}; +#endif + +static reloc_howto_type elf_sparc_howto_table[] = +{ + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,false,false, &bfd_elf_generic_reloc,"R_SPARC_NONE", false,0,0x00000000,false), + HOWTO(R_SPARC_8, 0,0, 8,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_8", false,0,0x000000ff,false), + HOWTO(R_SPARC_16, 0,1,16,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_16", false,0,0x0000ffff,false), + HOWTO(R_SPARC_32, 0,2,32,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_32", false,0,0xffffffff,false), + HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_DISP8", false,0,0x000000ff,false), + HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_DISP16", false,0,0x0000ffff,false), + HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_DISP32", false,0,0x00ffffff,false), + HOWTO(R_SPARC_WDISP30,2,2,30,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_WDISP30",false,0,0x3fffffff,false), + HOWTO(R_SPARC_WDISP22,2,2,22,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_WDISP22",false,0,0x003fffff,false), + HOWTO(R_SPARC_HI22, 10,2,22,false,0,true, false, &bfd_elf_generic_reloc,"R_SPARC_HI22", false,0,0x003fffff,false), + HOWTO(R_SPARC_22, 0,2,22,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_22", false,0,0x003fffff,false), + HOWTO(R_SPARC_13, 0,1,13,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_13", false,0,0x00001fff,false), + HOWTO(R_SPARC_LO10, 0,1,10,false,0,true, false, &bfd_elf_generic_reloc,"R_SPARC_LO10", false,0,0x000003ff,false), + HOWTO(R_SPARC_GOT10, 0,1,10,false,0,false, true, &bfd_elf_generic_reloc,"R_SPARC_GOT10", false,0,0x000003ff,false), + HOWTO(R_SPARC_GOT13, 0,1,13,false,0,false, true, &bfd_elf_generic_reloc,"R_SPARC_GOT13", false,0,0x00001fff,false), + HOWTO(R_SPARC_GOT22, 10,2,22,false,0,false, true, &bfd_elf_generic_reloc,"R_SPARC_GOT22", false,0,0x003fffff,false), + HOWTO(R_SPARC_PC10, 0,1,10,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_PC10", false,0,0x000003ff,false), + HOWTO(R_SPARC_PC22, 0,2,22,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_PC22", false,0,0x003fffff,false), + HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,false,false, &bfd_elf_generic_reloc,"R_SPARC_WPLT30", false,0,0x00000000,false), + HOWTO(R_SPARC_COPY, 0,0,00,false,0,false,false, &bfd_elf_generic_reloc,"R_SPARC_COPY", false,0,0x00000000,false), + HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,false), + HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,false), + HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_RELATIVE",false,0,0x00000000,false), + HOWTO(R_SPARC_UA32, 0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_UA32", false,0,0x00000000,false), +}; + +struct elf_reloc_map { + unsigned char bfd_reloc_val; + unsigned char elf_reloc_val; +}; + +static CONST struct elf_reloc_map sparc_reloc_map[] = +{ + { BFD_RELOC_NONE, R_SPARC_NONE, }, + { BFD_RELOC_16, R_SPARC_16, }, + { BFD_RELOC_8, R_SPARC_8 }, + { BFD_RELOC_8_PCREL, R_SPARC_DISP8 }, + { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */ + { BFD_RELOC_32, R_SPARC_32 }, + { BFD_RELOC_32_PCREL, R_SPARC_DISP32 }, + { BFD_RELOC_HI22, R_SPARC_HI22 }, + { BFD_RELOC_LO10, R_SPARC_LO10, }, + { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 }, + { BFD_RELOC_SPARC22, R_SPARC_22 }, + { BFD_RELOC_SPARC13, R_SPARC_13 }, + { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 }, + { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 }, + { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 }, + { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 }, + { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 }, + { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 }, + { BFD_RELOC_SPARC_COPY, R_SPARC_COPY }, + { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT }, + { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT }, + { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE }, + { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 }, + /* { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */ +}; + +static CONST struct reloc_howto_struct * +DEFUN (bfd_elf32_bfd_reloc_type_lookup, (abfd, code), + bfd *abfd AND + bfd_reloc_code_real_type code) +{ + int i; + for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) + { + if (sparc_reloc_map[i].bfd_reloc_val == code) + return &elf_sparc_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; + } + return 0; +} + +static void +DEFUN (elf_info_to_howto, (abfd, cache_ptr, dst), + bfd *abfd AND + arelent *cache_ptr AND + Elf32_Internal_Rela *dst) +{ + BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max); + cache_ptr->howto = &elf_sparc_howto_table[ELF32_R_TYPE(dst->r_info)]; +} + +#define TARGET_BIG_SYM bfd_elf32_sparc_vec +#define TARGET_BIG_NAME "elf32-sparc" +#define ELF_ARCH bfd_arch_sparc + +#include "elf32-target.h" diff --git a/bfd/elf32-target.h b/bfd/elf32-target.h index 59d22bc6f73..f74696aa93b 100644 --- a/bfd/elf32-target.h +++ b/bfd/elf32-target.h @@ -66,6 +66,7 @@ static CONST struct elf_backend_data elf32_bed = #else 0, /* elf_info_to_howto_rel */ #endif + bfd_elf32__write_relocs, /* write_relocs */ }; #ifdef TARGET_BIG_SYM diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index ab44feab436..882a5aa3daa 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -78,44 +78,44 @@ extern void abort (); static reloc_howto_type elf_sparc_howto_table[] = { - HOWTO(R_SPARC_NONE, 0,0, 0,false,0,false,false, 0,"R_SPARC_NONE", false,0,0x00000000,false), - HOWTO(R_SPARC_8, 0,0, 8,false,0,true, true, 0,"R_SPARC_8", false,0,0x000000ff,false), - HOWTO(R_SPARC_16, 0,1,16,false,0,true, true, 0,"R_SPARC_16", false,0,0x0000ffff,false), - HOWTO(R_SPARC_32, 0,2,32,false,0,true, true, 0,"R_SPARC_32", false,0,0xffffffff,false), - HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,false, true, 0,"R_SPARC_DISP8", false,0,0x000000ff,false), - HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,false, true, 0,"R_SPARC_DISP16", false,0,0x0000ffff,false), - HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,false, true, 0,"R_SPARC_DISP32", false,0,0x00ffffff,false), - HOWTO(R_SPARC_WDISP30,2,2,30,true, 0,false, true, 0,"R_SPARC_WDISP30",false,0,0x3fffffff,false), - HOWTO(R_SPARC_WDISP22,2,2,22,true, 0,false, true, 0,"R_SPARC_WDISP22",false,0,0x003fffff,false), - HOWTO(R_SPARC_HI22, 10,2,22,false,0,true, false, 0,"R_SPARC_HI22", false,0,0x003fffff,false), - HOWTO(R_SPARC_22, 0,2,22,false,0,true, true, 0,"R_SPARC_22", false,0,0x003fffff,false), - HOWTO(R_SPARC_13, 0,1,13,false,0,true, true, 0,"R_SPARC_13", false,0,0x00001fff,false), - HOWTO(R_SPARC_LO10, 0,1,10,false,0,true, false, 0,"R_SPARC_LO10", false,0,0x000003ff,false), - HOWTO(R_SPARC_GOT10, 0,1,10,false,0,false, true, 0,"R_SPARC_GOT10", false,0,0x000003ff,false), - HOWTO(R_SPARC_GOT13, 0,1,13,false,0,false, true, 0,"R_SPARC_GOT13", false,0,0x00001fff,false), - HOWTO(R_SPARC_GOT22, 10,2,22,false,0,false, true, 0,"R_SPARC_GOT22", false,0,0x003fffff,false), - HOWTO(R_SPARC_PC10, 0,1,10,false,0,true, true, 0,"R_SPARC_PC10", false,0,0x000003ff,false), - HOWTO(R_SPARC_PC22, 0,2,22,false,0,true, true, 0,"R_SPARC_PC22", false,0,0x003fffff,false), - HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,false,false, 0,"R_SPARC_WPLT30", false,0,0x00000000,false), - HOWTO(R_SPARC_COPY, 0,0,00,false,0,false,false, 0,"R_SPARC_COPY", false,0,0x00000000,false), - HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,false,false,0,"R_SPARC_GLOB_DAT",false,0,0x00000000,false), - HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,false,false,0,"R_SPARC_JMP_SLOT",false,0,0x00000000,false), - HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,false,false,0,"R_SPARC_RELATIVE",false,0,0x00000000,false), - HOWTO(R_SPARC_UA32, 0,0,00,false,0,false,false,0,"R_SPARC_UA32", false,0,0x00000000,false), - HOWTO(R_SPARC_10, 0,1,10,false,0,true, true, 0, "R_SPARC_10", false,0,0x000003ff,false), - HOWTO(R_SPARC_11, 0,1,11,false,0,true, true, 0,"R_SPARC_11", false,0,0x000007ff,false), - HOWTO(R_SPARC_64, 0,4,00,false,0,true, true, 0,"R_SPARC_64", false,0,(((bfd_vma)0xffffffff)<<32)+0xffffffff,false), - HOWTO(R_SPARC_OLO10, 0,1,10,false,0,true,false, DIE,"R_SPARC_OLO10",false,0,0x000003ff,false), - HOWTO(R_SPARC_HH22, 42,2,22,false,0,true, false, 0,"R_SPARC_HH22", false,0,0x003fffff,false), - HOWTO(R_SPARC_HM10, 32,1,10,false,0,true,false, 0,"R_SPARC_HM10", false,0,0x000003ff,false), - HOWTO(R_SPARC_LM22, 10,2,22,false,0,true,false, 0,"R_SPARC_LM22", false,0,0x003fffff,false), - HOWTO(R_SPARC_PC_HH22,42,2,22, true,0,true, false, 0,"R_SPARC_HH22", false,0,0x003fffff,false), - HOWTO(R_SPARC_PC_HM10,32,1,10, true,0,true,false, 0,"R_SPARC_HM10", false,0,0x000003ff,false), - HOWTO(R_SPARC_PC_LM22,10,2,22,true, 0,true,false, 0,"R_SPARC_LM22", false,0,0x003fffff,false), - HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,false, true,DIE,"R_SPARC_WDISP16",false,0,0,false), - HOWTO(R_SPARC_WDISP19, 2,2,22,true, 0,false, true, 0, "R_SPARC_WDISP19",false,0,0x0007ffff,false), - HOWTO(R_SPARC_GLOB_JMP,0,0,00,false,0,false,false,0,"R_SPARC_GLOB_DAT",false,0,0x00000000,false), - HOWTO(R_SPARC_LO7, 0,1, 7,false,0,false,false,0,"R_SPARC_LO7", false,0,0x0000007f,false), + HOWTO(R_SPARC_NONE, 0,0, 0,false,0,false,false, &bfd_elf_generic_reloc,"R_SPARC_NONE", false,0,0x00000000,false), + HOWTO(R_SPARC_8, 0,0, 8,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_8", false,0,0x000000ff,false), + HOWTO(R_SPARC_16, 0,1,16,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_16", false,0,0x0000ffff,false), + HOWTO(R_SPARC_32, 0,2,32,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_32", false,0,0xffffffff,false), + HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_DISP8", false,0,0x000000ff,false), + HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_DISP16", false,0,0x0000ffff,false), + HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_DISP32", false,0,0x00ffffff,false), + HOWTO(R_SPARC_WDISP30,2,2,30,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_WDISP30",false,0,0x3fffffff,true), + HOWTO(R_SPARC_WDISP22,2,2,22,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_WDISP22",false,0,0x003fffff,false), + HOWTO(R_SPARC_HI22, 10,2,22,false,0,true, false, &bfd_elf_generic_reloc,"R_SPARC_HI22", false,0,0x003fffff,false), + HOWTO(R_SPARC_22, 0,2,22,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_22", false,0,0x003fffff,false), + HOWTO(R_SPARC_13, 0,1,13,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_13", false,0,0x00001fff,false), + HOWTO(R_SPARC_LO10, 0,1,10,false,0,true, false, &bfd_elf_generic_reloc,"R_SPARC_LO10", false,0,0x000003ff,false), + HOWTO(R_SPARC_GOT10, 0,1,10,false,0,false, true, &bfd_elf_generic_reloc,"R_SPARC_GOT10", false,0,0x000003ff,false), + HOWTO(R_SPARC_GOT13, 0,1,13,false,0,false, true, &bfd_elf_generic_reloc,"R_SPARC_GOT13", false,0,0x00001fff,false), + HOWTO(R_SPARC_GOT22, 10,2,22,false,0,false, true, &bfd_elf_generic_reloc,"R_SPARC_GOT22", false,0,0x003fffff,false), + HOWTO(R_SPARC_PC10, 0,1,10,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_PC10", false,0,0x000003ff,false), + HOWTO(R_SPARC_PC22, 0,2,22,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_PC22", false,0,0x003fffff,false), + HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,false,false, &bfd_elf_generic_reloc,"R_SPARC_WPLT30", false,0,0x00000000,false), + HOWTO(R_SPARC_COPY, 0,0,00,false,0,false,false, &bfd_elf_generic_reloc,"R_SPARC_COPY", false,0,0x00000000,false), + HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,false), + HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,false), + HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_RELATIVE",false,0,0x00000000,false), + HOWTO(R_SPARC_UA32, 0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_UA32", false,0,0x00000000,false), + HOWTO(R_SPARC_10, 0,1,10,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_10", false,0,0x000003ff,false), + HOWTO(R_SPARC_11, 0,1,11,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_11", false,0,0x000007ff,false), + HOWTO(R_SPARC_64, 0,4,00,false,0,true, true, &bfd_elf_generic_reloc,"R_SPARC_64", false,0,(((bfd_vma)0xffffffff)<<32)+0xffffffff,false), + HOWTO(R_SPARC_OLO10, 0,1,10,false,0,true,false, &bfd_elf_generic_reloc,"R_SPARC_OLO10",false,0,0x000003ff,false), + HOWTO(R_SPARC_HH22, 42,2,22,false,0,true, false, &bfd_elf_generic_reloc,"R_SPARC_HH22", false,0,0x003fffff,false), + HOWTO(R_SPARC_HM10, 32,1,10,false,0,true,false, &bfd_elf_generic_reloc,"R_SPARC_HM10", false,0,0x000003ff,false), + HOWTO(R_SPARC_LM22, 10,2,22,false,0,true,false, &bfd_elf_generic_reloc,"R_SPARC_LM22", false,0,0x003fffff,false), + HOWTO(R_SPARC_PC_HH22,42,2,22, true,0,true, false, &bfd_elf_generic_reloc,"R_SPARC_HH22", false,0,0x003fffff,false), + HOWTO(R_SPARC_PC_HM10,32,1,10, true,0,true,false, &bfd_elf_generic_reloc,"R_SPARC_HM10", false,0,0x000003ff,false), + HOWTO(R_SPARC_PC_LM22,10,2,22,true, 0,true,false, &bfd_elf_generic_reloc,"R_SPARC_LM22", false,0,0x003fffff,false), + HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,false, true,&bfd_elf_generic_reloc,"R_SPARC_WDISP16",false,0,0,false), + HOWTO(R_SPARC_WDISP19, 2,2,22,true, 0,false, true, &bfd_elf_generic_reloc,"R_SPARC_WDISP19",false,0,0x0007ffff,false), + HOWTO(R_SPARC_GLOB_JMP,0,0,00,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,false), + HOWTO(R_SPARC_LO7, 0,1, 7,false,0,false,false,&bfd_elf_generic_reloc,"R_SPARC_LO7", false,0,0x0000007f,false), }; struct elf_reloc_map { diff --git a/bfd/elfcode.h b/bfd/elfcode.h index a3119d14e15..908e010c8df 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -56,12 +56,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ */ +#include #include /* For strrchr and friends */ #include "bfd.h" #include "sysdep.h" #include "libbfd.h" #include "libelf.h" +/* Renaming structures, typedefs, macros and functions to be size-specific. */ #define Elf_External_Ehdr NAME(Elf,External_Ehdr) #define Elf_External_Sym NAME(Elf,External_Sym) #define Elf_External_Shdr NAME(Elf,External_Shdr) @@ -76,7 +78,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define elf_core_file_matches_executable_p NAME(bfd_elf,core_file_matches_executable_p) #define elf_object_p NAME(bfd_elf,object_p) #define elf_core_file_p NAME(bfd_elf,core_file_p) -#define elf_write_object_contents NAME(bfd_elf,write_object_contents) #define elf_get_symtab_upper_bound NAME(bfd_elf,get_symtab_upper_bound) #define elf_get_reloc_upper_bound NAME(bfd_elf,get_reloc_upper_bound) #define elf_canonicalize_reloc NAME(bfd_elf,canonicalize_reloc) @@ -91,25 +92,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define elf_set_section_contents NAME(bfd_elf,set_section_contents) #define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto) #define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel) -#define elf_get_sect_thunk NAME(bfd_elf,get_sect_thunk) #define elf_hash NAME(bfd_elf,hash) #define elf_new_section_hook NAME(bfd_elf,new_section_hook) +#define write_relocs NAME(bfd_elf,_write_relocs) #if ARCH_SIZE == 64 #define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y) #define ELF_R_SYM(X) ELF64_R_SYM(X) +#define ELFCLASS ELFCLASS64 #endif #if ARCH_SIZE == 32 #define ELF_R_INFO(X,Y) ELF32_R_INFO(X,Y) #define ELF_R_SYM(X) ELF32_R_SYM(X) -#endif - -#ifdef HAVE_PROCFS /* Some core file support requires host /proc files */ -#include -#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 */ +#define ELFCLASS ELFCLASS32 #endif #ifndef INLINE @@ -120,6 +115,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif #endif +static int shstrtab_length_fixed; + +struct elf_sect_data { + int reloc_sec; + /* more? */ +}; + /* Forward declarations of static functions */ static struct sec * section_from_elf_index PARAMS ((bfd *, int)); @@ -132,12 +134,19 @@ static int elf_symbol_from_bfd_symbol PARAMS ((bfd *, struct symbol_cache_entry **)); static void elf_map_symbols PARAMS ((bfd *)); +static void swap_out_syms PARAMS ((bfd *)); #ifdef DEBUG static void elf_debug_section PARAMS ((char *, int, Elf_Internal_Shdr *)); static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *)); #endif +#define elf_string_from_elf_strtab(abfd,strindex) \ + elf_string_from_elf_section(abfd,elf_elfheader(abfd)->e_shstrndx,strindex) + + +/* Structure swapping routines */ + /* Should perhaps use put_offset, put_word, etc. For now, the two versions can be handled by explicitly specifying 32 bits or "the long type". */ #if ARCH_SIZE == 64 @@ -301,8 +310,6 @@ DEFUN (elf_swap_phdr_in, (abfd, src, dst), dst->p_align = get_word (abfd, (bfd_byte *) src->p_align); } -/* ... */ - static void DEFUN (elf_swap_phdr_out, (abfd, src, dst), bfd * abfd AND @@ -321,7 +328,7 @@ DEFUN (elf_swap_phdr_out, (abfd, src, dst), } /* Translate an ELF reloc from external format to internal format. */ -static void +static INLINE void DEFUN (elf_swap_reloc_in, (abfd, src, dst), bfd * abfd AND Elf_External_Rel * src AND @@ -331,7 +338,7 @@ DEFUN (elf_swap_reloc_in, (abfd, src, dst), dst->r_info = get_word (abfd, (bfd_byte *) src->r_info); } -static void +static INLINE void DEFUN (elf_swap_reloca_in, (abfd, src, dst), bfd * abfd AND Elf_External_Rela * src AND @@ -343,7 +350,7 @@ DEFUN (elf_swap_reloca_in, (abfd, src, dst), } /* Translate an ELF reloc from internal format to external format. */ -static void +static INLINE void DEFUN (elf_swap_reloc_out, (abfd, src, dst), bfd * abfd AND Elf_Internal_Rel * src AND @@ -353,7 +360,7 @@ DEFUN (elf_swap_reloc_out, (abfd, src, dst), put_word (abfd, src->r_info, dst->r_info); } -static void +static INLINE void DEFUN (elf_swap_reloca_out, (abfd, src, dst), bfd * abfd AND Elf_Internal_Rela * src AND @@ -364,24 +371,85 @@ DEFUN (elf_swap_reloca_out, (abfd, src, dst), put_word (abfd, src->r_addend, dst->r_addend); } -/* Create a new bfd section from an ELF section header. */ + + +/* String table creation/manipulation routines */ + +static struct strtab * +DEFUN (bfd_new_strtab, (abfd), + bfd * abfd) +{ + struct strtab *ss; + + ss = (struct strtab *) bfd_xmalloc (sizeof (struct strtab)); + ss->tab = bfd_xmalloc (1); + BFD_ASSERT (ss->tab != 0); + *ss->tab = 0; + ss->nentries = 0; + ss->length = 1; -static INLINE char * -DEFUN (elf_string_from_elf_strtab, (abfd, strindex), - bfd *abfd AND - int strindex) + return ss; +} + +static int +DEFUN (bfd_add_to_strtab, (abfd, ss, str), + bfd * abfd AND + struct strtab *ss AND + CONST char *str) +{ + /* should search first, but for now: */ + /* include the trailing NUL */ + int ln = strlen (str) + 1; + + /* should this be using obstacks? */ + ss->tab = realloc (ss->tab, ss->length + ln); + + BFD_ASSERT (ss->tab != 0); + strcpy (ss->tab + ss->length, str); + ss->nentries++; + ss->length += ln; + + return ss->length - ln; +} + +static int +DEFUN (bfd_add_2_to_strtab, (abfd, ss, str, str2), + bfd * abfd AND + struct strtab *ss AND + char *str AND + CONST char *str2) { - return elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, - strindex); + /* should search first, but for now: */ + /* include the trailing NUL */ + int ln = strlen (str) + strlen (str2) + 1; + + /* should this be using obstacks? */ + if (ss->length) + ss->tab = realloc (ss->tab, ss->length + ln); + else + ss->tab = bfd_xmalloc (ln); + + BFD_ASSERT (ss->tab != 0); + strcpy (ss->tab + ss->length, str); + strcpy (ss->tab + ss->length + strlen (str), str2); + ss->nentries++; + ss->length += ln; + + return ss->length - ln; } + +/* ELF .o/exec file reading */ + +/* Create a new bfd section from an ELF section header. */ + static boolean DEFUN (bfd_section_from_shdr, (abfd, shindex), bfd * abfd AND unsigned int shindex) { - Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); - Elf_Internal_Shdr *hdr = i_shdrp + shindex; + Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex]; + Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd); asection *newsect; char *name; @@ -401,10 +469,10 @@ DEFUN (bfd_section_from_shdr, (abfd, shindex), newsect = bfd_make_section (abfd, name); if (newsect != NULL) { + newsect->filepos = hdr->sh_offset; /* so we can read back the bits */ + newsect->flags |= SEC_HAS_CONTENTS; newsect->vma = hdr->sh_addr; newsect->_raw_size = hdr->sh_size; - newsect->filepos = hdr->sh_offset; /* so we can read back the bits */ - newsect->flags |= SEC_HAS_CONTENTS; newsect->alignment_power = bfd_log2 (hdr->sh_addralign); if (hdr->sh_flags & SHF_ALLOC) @@ -417,7 +485,7 @@ DEFUN (bfd_section_from_shdr, (abfd, shindex), newsect->flags |= SEC_READONLY; if (hdr->sh_flags & SHF_EXECINSTR) - newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */ + newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */ else newsect->flags |= SEC_DATA; @@ -456,36 +524,91 @@ DEFUN (bfd_section_from_shdr, (abfd, shindex), return true; case SHT_SYMTAB: /* A symbol table */ + if (elf_onesymtab (abfd) == shindex) + return true; + BFD_ASSERT (hdr->sh_entsize == sizeof (Elf_External_Sym)); + BFD_ASSERT (elf_onesymtab (abfd) == 0); elf_onesymtab (abfd) = shindex; + elf_tdata(abfd)->symtab_hdr = *hdr; + elf_elfsections(abfd)[shindex] = &elf_tdata(abfd)->symtab_hdr; abfd->flags |= HAS_SYMS; return true; case SHT_STRTAB: /* A string table */ - if (!strcmp (name, ".strtab") || !strcmp (name, ".shstrtab")) + if (hdr->rawdata) return true; + if (ehdr->e_shstrndx == shindex) + { + elf_tdata(abfd)->shstrtab_hdr = *hdr; + elf_elfsections(abfd)[shindex] = &elf_tdata(abfd)->shstrtab_hdr; + hdr->rawdata = (PTR) &elf_tdata(abfd)->shstrtab_hdr; + return true; + } + { + int i; - if (!hdr->rawdata) + for (i = 1; i < ehdr->e_shnum; i++) + { + Elf_Internal_Shdr *hdr2 = elf_elfsections(abfd)[i]; + if (hdr2->sh_link == shindex) + { + bfd_section_from_shdr (abfd, i); + if (elf_onesymtab (abfd) == i) + { + elf_tdata(abfd)->strtab_hdr = *hdr; + elf_elfsections(abfd)[shindex] = &elf_tdata(abfd)->strtab_hdr; + return true; + } +#if 0 /* Not handling other string tables specially right now. */ + hdr2 = elf_elfsections(abfd)[i]; /* in case it moved */ + /* We have a strtab for some random other section. */ + newsect = (asection *) hdr2->rawdata; + if (!newsect) + break; + hdr->rawdata = (PTR) newsect; + hdr2 = &elf_section_data (newsect)->str_hdr; + *hdr2 = *hdr; + elf_elfsections(abfd)[shindex] = hdr2; +#endif + } + } + } + + newsect = bfd_make_section (abfd, name); + if (newsect) { - newsect = bfd_make_section (abfd, name); - if (newsect) - newsect->flags = SEC_HAS_CONTENTS; + newsect->flags = SEC_HAS_CONTENTS; + hdr->rawdata = (PTR) newsect; + newsect->_raw_size = hdr->sh_size; + newsect->alignment_power = 0; + newsect->vma = 0; + + if (hdr->sh_flags & SHF_ALLOC) + newsect->flags |= SEC_ALLOC|SEC_LOAD; + if (!(hdr->sh_flags & SHF_WRITE)) + newsect->flags |= SEC_READONLY; + if (hdr->sh_flags & SHF_EXECINSTR) + newsect->flags |= SEC_CODE; + else + newsect->flags |= SEC_DATA; } return true; case SHT_REL: case SHT_RELA: - /* *these* do a lot of work -- but build no sections! */ - /* the spec says there can be multiple strtabs, but only one symtab */ - /* but there can be lots of REL* sections. */ + /* *These* do a lot of work -- but build no sections! + The spec says there can be multiple strtabs, but only one symtab, + but there can be lots of REL* sections. */ /* FIXME: The above statement is wrong! There are typically at least - two symbol tables in a dynamically linked executable, ".dynsym" - which is the dynamic linkage symbol table and ".symtab", which is - the "traditional" symbol table. -fnf */ + two symbol tables in a dynamically linked executable, ".dynsym" + which is the dynamic linkage symbol table and ".symtab", which is + the "traditional" symbol table. -fnf */ { asection *target_sect; + Elf_Internal_Shdr *hdr2; int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; /* Don't allow REL relocations on a machine that uses RELA and @@ -503,24 +626,20 @@ DEFUN (bfd_section_from_shdr, (abfd, shindex), ? sizeof (Elf_External_Rela) : sizeof (Elf_External_Rel))); - bfd_section_from_shdr (abfd, hdr->sh_link); /* symbol table */ bfd_section_from_shdr (abfd, hdr->sh_info); /* target */ + bfd_section_from_shdr (abfd, hdr->sh_link); /* symbol table */ target_sect = section_from_elf_index (abfd, hdr->sh_info); if (target_sect == NULL) return false; -#if 0 - /* FIXME: We are only prepared to read one symbol table, so - do NOT read the dynamic symbol table since it is only a - subset of the full symbol table. Also see comment above. -fnf */ - if (!elf_slurp_symbol_table (abfd, i_shdrp + hdr->sh_link)) - return false; -#endif - + hdr2 = &elf_section_data (target_sect)->rel_hdr; + *hdr2 = *hdr; + elf_elfsections(abfd)[shindex] = hdr2; target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize; target_sect->flags |= SEC_RELOC; target_sect->relocation = 0; target_sect->rel_filepos = hdr->sh_offset; + abfd->flags |= HAS_RELOC; return true; } break; @@ -559,131 +678,11 @@ DEFUN (elf_new_section_hook, (abfd, sec), bfd *abfd AND asection *sec) { -/* sec->symbol->name = "";*/ - return true; -} - -static struct strtab * -DEFUN (bfd_new_strtab, (abfd), - bfd * abfd) -{ - struct strtab *ss; - - ss = (struct strtab *) bfd_xmalloc (sizeof (struct strtab)); - ss->tab = bfd_xmalloc (1); - BFD_ASSERT (ss->tab != 0); - *ss->tab = 0; - ss->nentries = 0; - ss->length = 1; - - return ss; -} - -static int -DEFUN (bfd_add_to_strtab, (abfd, ss, str), - bfd * abfd AND - struct strtab *ss AND - CONST char *str) -{ - /* should search first, but for now: */ - /* include the trailing NUL */ - int ln = strlen (str) + 1; - - /* should this be using obstacks? */ - ss->tab = realloc (ss->tab, ss->length + ln); - - BFD_ASSERT (ss->tab != 0); - strcpy (ss->tab + ss->length, str); - ss->nentries++; - ss->length += ln; - - return ss->length - ln; -} - -static int -DEFUN (bfd_add_2_to_strtab, (abfd, ss, str, str2), - bfd * abfd AND - struct strtab *ss AND - char *str AND - CONST char *str2) -{ - /* should search first, but for now: */ - /* include the trailing NUL */ - int ln = strlen (str) + strlen (str2) + 1; - - /* should this be using obstacks? */ - if (ss->length) - ss->tab = realloc (ss->tab, ss->length + ln); - else - ss->tab = bfd_xmalloc (ln); - - BFD_ASSERT (ss->tab != 0); - strcpy (ss->tab + ss->length, str); - strcpy (ss->tab + ss->length + strlen (str), str2); - ss->nentries++; - ss->length += ln; - - return ss->length - ln; -} - -/* Create a new ELF section from a bfd section. */ - -#if 0 /* not used */ -static boolean -DEFUN (bfd_shdr_from_section, (abfd, hdr, shstrtab, indx), - bfd * abfd AND - Elf_Internal_Shdr * hdr AND - struct strtab *shstrtab AND - int indx) -{ - asection *sect; - int ndx; - - sect = abfd->sections; - for (ndx = indx; --ndx;) - { - sect = sect->next; - } - hdr[indx].sh_name = bfd_add_to_strtab (abfd, shstrtab, - bfd_section_name (abfd, sect)); - hdr[indx].sh_addr = sect->vma; - hdr[indx].sh_size = sect->_raw_size; - hdr[indx].sh_addralign = 1 << sect->alignment_power; - hdr[indx].sh_flags = 0; - /* these need to be preserved on */ - hdr[indx].sh_link = 0; - hdr[indx].sh_info = 0; - hdr[indx].sh_entsize = 0; - - hdr[indx].sh_type = 0; - if (sect->flags & SEC_RELOC) - { - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - hdr[indx].sh_type = use_rela_p ? SHT_RELA : SHT_REL; - } - - if (sect->flags & SEC_HAS_CONTENTS) - { - hdr[indx].sh_offset = sect->filepos; - hdr[indx].sh_size = sect->_raw_size; - } - if (sect->flags & SEC_ALLOC) - { - hdr[indx].sh_flags |= SHF_ALLOC; - if (sect->flags & SEC_LOAD) - { - /* do something with sh_type ? */ - } - } - if (!(sect->flags & SEC_READONLY)) - hdr[indx].sh_flags |= SHF_WRITE; - - if (sect->flags & SEC_CODE) - hdr[indx].sh_flags |= SHF_EXECINSTR; - + struct bfd_elf_section_data *sdata; + sec->used_by_bfd = sdata = bfd_alloc (abfd, sizeof (*sdata)); + memset (sdata, 0, sizeof (*sdata)); return true; } -#endif /* Create a new bfd section from an ELF program header. @@ -766,2622 +765,2705 @@ DEFUN (bfd_section_from_phdr, (abfd, hdr, index), return true; } -#ifdef HAVE_PROCFS +/* Begin processing a given object. -static void -DEFUN (bfd_prstatus, (abfd, descdata, descsz, filepos), - bfd * abfd AND - char *descdata AND - int descsz AND - long filepos) + First we validate the file by reading in the ELF header and checking + the magic number. */ + +static INLINE boolean +DEFUN (elf_file_p, (x_ehdrp), Elf_External_Ehdr * x_ehdrp) { - asection *newsect; - prstatus_t *status = (prstatus_t *) 0; + return ((x_ehdrp->e_ident[EI_MAG0] == ELFMAG0) + && (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1) + && (x_ehdrp->e_ident[EI_MAG2] == ELFMAG2) + && (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3)); +} - if (descsz == sizeof (prstatus_t)) - { - newsect = bfd_make_section (abfd, ".reg"); - newsect->_raw_size = sizeof (status->pr_reg); - newsect->filepos = filepos + (long) &status->pr_reg; - newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS; - newsect->alignment_power = 2; - if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL) - { - memcpy (core_prstatus (abfd), descdata, descsz); - } - } -} - -/* Stash a copy of the prpsinfo structure away for future use. */ - -static void -DEFUN (bfd_prpsinfo, (abfd, descdata, descsz, filepos), - bfd * abfd AND - char *descdata AND - int descsz AND - long filepos) +bfd_target * +DEFUN (elf_object_p, (abfd), bfd * abfd) { - asection *newsect; + Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + Elf_External_Shdr x_shdr; /* Section header table entry, external form */ + Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ + int shindex; + char *shstrtab; /* Internal copy of section header stringtab */ + struct elf_backend_data *ebd; /* Use to get ELF_ARCH stored in xvec */ - if (descsz == sizeof (prpsinfo_t)) + /* Read in the ELF header in external format. */ + + if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) { - if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) != NULL) - { - memcpy (core_prpsinfo (abfd), descdata, descsz); - } + bfd_error = system_call_error; + return NULL; } -} -static void -DEFUN (bfd_fpregset, (abfd, descdata, descsz, filepos), - bfd * abfd AND - char *descdata AND - int descsz AND - long filepos) -{ - asection *newsect; + /* 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 + section header table (FIXME: See comments re sections at top of this + file). */ - newsect = bfd_make_section (abfd, ".reg2"); - newsect->_raw_size = descsz; - newsect->filepos = filepos; - newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS; - newsect->alignment_power = 2; -} + if (elf_file_p (&x_ehdr) == false) + { + wrong: + bfd_error = wrong_format; + return NULL; + } -#endif /* HAVE_PROCFS */ + if (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) + goto wrong; -/* 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. */ + if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS) + goto wrong; -char * -DEFUN (elf_core_file_failing_command, (abfd), - bfd * abfd) -{ -#ifdef HAVE_PROCFS - if (core_prpsinfo (abfd)) + /* Switch xvec to match the specified byte order. */ + switch (x_ehdr.e_ident[EI_DATA]) { - 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; + case ELFDATA2MSB: /* Big-endian */ + if (!abfd->xvec->header_byteorder_big_p) + goto wrong; + break; + case ELFDATA2LSB: /* Little-endian */ + if (abfd->xvec->header_byteorder_big_p) + goto wrong; + break; + case ELFDATANONE: /* No data encoding specified */ + default: /* Unknown data encoding specified */ + goto wrong; } -#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. - */ + /* Allocate an instance of the elf_obj_tdata structure and hook it up to + the tdata pointer in the bfd. */ -int -DEFUN (elf_core_file_failing_signal, (abfd), - bfd * abfd) -{ -#ifdef HAVE_PROCFS - if (core_prstatus (abfd)) + if (NULL == (elf_tdata (abfd) = (struct elf_obj_tdata *) + bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)))) { - return ((prstatus_t *) (core_prstatus (abfd)))->pr_cursig; + bfd_error = no_memory; + return NULL; } -#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. - */ + /* FIXME: Any `wrong' exits below here will leak memory (tdata). */ -boolean -DEFUN (elf_core_file_matches_executable_p, (core_bfd, exec_bfd), - bfd * core_bfd AND - bfd * exec_bfd) -{ -#ifdef HAVE_PROCFS - char *corename; - char *execname; + /* 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 - /* First, xvecs must match since both are ELF files for the same target. */ + /* If there is no section header table, we're hosed. */ + if (i_ehdrp->e_shoff == 0) + goto wrong; - if (core_bfd->xvec != exec_bfd->xvec) - { - bfd_error = system_call_error; - return false; - } + if (i_ehdrp->e_type == ET_EXEC || i_ehdrp->e_type == ET_DYN) + abfd->flags |= EXEC_P; -#ifdef HAVE_PROCFS + /* Retrieve the architecture information from the xvec and verify + that it matches the machine info stored in the ELF header. + This allows us to resolve ambiguous formats that might not + otherwise be distinguishable. */ - /* If no prpsinfo, just return true. Otherwise, grab the last component - of the exec'd pathname from the prpsinfo. */ + ebd = get_elf_backend_data (abfd); - if (core_prpsinfo (core_bfd)) + /* Perhaps the elf architecture value should be another field in the + elf backend data? If you change this to work that way, make sure + that you still get bfd_arch_unknown for unknown architecture types, + and that it still gets accepted by the `generic' elf target. */ + { + int i; + enum bfd_architecture arch = bfd_arch_unknown; + + for (i = 0; i < bfd_elf_arch_map_size; i++) + { + if (bfd_elf_arch_map[i].elf_arch == i_ehdrp->e_machine) + { + arch = bfd_elf_arch_map[i].bfd_arch; + break; + } + } + /* start-sanitize-v9 */ + if (i_ehdrp->e_machine == EM_SPARC64) + arch = bfd_arch_sparc; + /* end-sanitize-v9 */ + if (ebd->arch != arch) + goto wrong; + bfd_default_set_arch_mach (abfd, arch, 0); + } + + /* Allocate space for a copy of the section header table in + internal form, seek to the section 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 section + header table entry actually matches the size recorded in the file. */ + + if (i_ehdrp->e_shentsize != sizeof (x_shdr)) + goto wrong; + i_shdrp = (Elf_Internal_Shdr *) + bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum); + elf_elfsections (abfd) = bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum); + if (!i_shdrp || !elf_elfsections(abfd)) { - corename = (((struct prpsinfo *) core_prpsinfo (core_bfd))->pr_fname); + bfd_error = no_memory; + return NULL; } - else + if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) == -1) { - return true; + bfd_error = system_call_error; + return NULL; } - - /* Find the last component of the executable pathname. */ - - if ((execname = strrchr (exec_bfd->filename, '/')) != NULL) + for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++) { - execname++; + if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) + != sizeof (x_shdr)) + { + bfd_error = system_call_error; + return NULL; + } + elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); + elf_elfsections(abfd)[shindex] = i_shdrp + shindex; } - else + if (i_ehdrp->e_shstrndx) { - execname = (char *) exec_bfd->filename; + bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx); } - /* See if they match */ +#if 0 + for (shindex = i_ehdrp->e_shnum - 1; shindex >= 0; shindex--) + { + if (!strcmp (elf_string_from_elf_strtab (abfd, + i_shdrp[shindex].sh_name), + ".strtab")) + { + elf_tdata(abfd)->strtab_hdr = i_shdrp[shindex]; + elf_elfsections(abfd)[shindex] = &elf_tdata(abfd)->strtab_hdr; + } + else if (!strcmp (elf_string_from_elf_strtab (abfd, + i_shdrp[shindex].sh_name), + ".symtab")) + { + elf_tdata(abfd)->symtab_hdr = i_shdrp[shindex]; + elf_elfsections(abfd)[shindex] = &elf_tdata(abfd)->symtab_hdr; + elf_onesymtab (abfd) = shindex; + } + } +#endif - return strcmp (execname, corename) ? false : true; + /* Read in the string table containing the names of the sections. We + will need the base pointer to this table later. */ + /* We read this inline now, so that we don't have to go through + bfd_section_from_shdr with it (since this particular strtab is + used to find all of the ELF section names.) */ -#else + shstrtab = elf_get_str_section (abfd, i_ehdrp->e_shstrndx); + if (!shstrtab) + return NULL; - return true; + /* Once all of the section headers have been read and converted, we + can start processing them. Note that the first section header is + a dummy placeholder entry, so we ignore it. -#endif /* HAVE_PROCFS */ -} + We also watch for the symbol table section and remember the file + offset and section size for both the symbol table section and the + associated string table section. */ -/* 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. + for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++) + { + bfd_section_from_shdr (abfd, shindex); + } - 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. + /* Remember the entry point specified in the ELF file header. */ - 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. + bfd_get_start_address (abfd) = i_ehdrp->e_entry; - */ + return abfd->xvec; +} + +/* ELF .o/exec file writing */ + +/* Create a new ELF section from a bfd section. */ + +#if 0 /* not used */ static boolean -DEFUN (elf_corefile_note, (abfd, hdr), +DEFUN (bfd_shdr_from_section, (abfd, hdr, shstrtab, indx), bfd * abfd AND - Elf_Internal_Phdr * hdr) + Elf_Internal_Shdr * hdr AND + struct strtab *shstrtab AND + int indx) { - 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; + asection *sect; + int ndx; - if (hdr->p_filesz > 0 - && (buf = (char *) bfd_xmalloc (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) + sect = abfd->sections; + for (ndx = indx; --ndx;) { - 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 */ - bfd_prstatus (abfd, descdata, i_note.descsz, filepos); - sectname = ".prstatus"; - break; - case NT_FPREGSET: - /* process descdata as fpregset info */ - bfd_fpregset (abfd, descdata, i_note.descsz, filepos); - sectname = ".fpregset"; - break; - case NT_PRPSINFO: - /* process descdata as prpsinfo */ - bfd_prpsinfo (abfd, descdata, i_note.descsz, filepos); - sectname = ".prpsinfo"; - break; - default: - /* Unknown descriptor, just ignore it. */ - sectname = NULL; - break; - } - if (sectname != NULL) - { - newsect = bfd_make_section (abfd, sectname); - 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)); - } + sect = sect->next; } - if (buf != NULL) + hdr[indx].sh_name = bfd_add_to_strtab (abfd, shstrtab, + bfd_section_name (abfd, sect)); + hdr[indx].sh_addr = sect->vma; + hdr[indx].sh_size = sect->_raw_size; + hdr[indx].sh_addralign = 1 << sect->alignment_power; + hdr[indx].sh_flags = 0; + /* these need to be preserved on */ + hdr[indx].sh_link = 0; + hdr[indx].sh_info = 0; + hdr[indx].sh_entsize = 0; + + hdr[indx].sh_type = 0; + if (sect->flags & SEC_RELOC) { - free (buf); + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; + hdr[indx].sh_type = use_rela_p ? SHT_RELA : SHT_REL; } - return true; - -} + if (sect->flags & SEC_HAS_CONTENTS) + { + hdr[indx].sh_offset = sect->filepos; + hdr[indx].sh_size = sect->_raw_size; + } + if (sect->flags & SEC_ALLOC) + { + hdr[indx].sh_flags |= SHF_ALLOC; + if (sect->flags & SEC_LOAD) + { + /* do something with sh_type ? */ + } + } + if (!(sect->flags & SEC_READONLY)) + hdr[indx].sh_flags |= SHF_WRITE; -/* Begin processing a given object. + if (sect->flags & SEC_CODE) + hdr[indx].sh_flags |= SHF_EXECINSTR; - First we validate the file by reading in the ELF header and checking - the magic number. */ + return true; +} +#endif -static INLINE boolean -DEFUN (elf_file_p, (x_ehdrp), Elf_External_Ehdr * x_ehdrp) +/* + Takes a bfd and a symbol, returns a pointer to the elf specific area + of the symbol if there is one. + */ +static INLINE elf_symbol_type * +DEFUN (elf_symbol_from, (ignore_abfd, symbol), + bfd * ignore_abfd AND + asymbol * symbol) { - return ((x_ehdrp->e_ident[EI_MAG0] == ELFMAG0) - && (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1) - && (x_ehdrp->e_ident[EI_MAG2] == ELFMAG2) - && (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3)); + if (symbol->the_bfd->xvec->flavour != bfd_target_elf_flavour) + return 0; + + if (symbol->the_bfd->tdata.elf_obj_data == (struct elf_obj_tdata *) NULL) + return 0; + + return (elf_symbol_type *) symbol; } -bfd_target * -DEFUN (elf_object_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_Shdr x_shdr; /* Section header table entry, external form */ - Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ - int shindex; - char *shstrtab; /* Internal copy of section header stringtab */ - struct elf_backend_data *ebd; /* Use to get ELF_ARCH stored in xvec */ +/* + Create ELF output from BFD sections. - /* Read in the ELF header in external format. */ + Essentially, just create the section header and forget about the program + header for now. - if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) - { - bfd_error = system_call_error; - 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 - section header table (FIXME: See comments re sections at top of this - file). */ +static void +DEFUN (elf_make_sections, (abfd, asect, obj), + bfd * abfd AND + asection * asect AND + PTR obj) +{ + /* most of what is in bfd_shdr_from_section goes in here... */ + /* and all of these sections generate at *least* one ELF section. */ + int idx; - if (elf_file_p (&x_ehdr) == false) - { - wrong: - bfd_error = wrong_format; - return NULL; - } + Elf_Internal_Shdr *this_hdr; + this_hdr = &elf_section_data (asect)->this_hdr; - if (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) - goto wrong; + this_hdr->sh_addr = asect->vma; + this_hdr->sh_size = asect->_raw_size; + /* contents already set by elf_set_section_contents */ - { -#if ARCH_SIZE == 64 - unsigned int class = ELFCLASS64; -#endif -#if ARCH_SIZE == 32 - unsigned int class = ELFCLASS32; + if ((asect->flags & SEC_RELOC) +#if 0 + /* The flags are sometimes inconsistent. */ + && asect->reloc_count > 0 #endif - if (x_ehdr.e_ident[EI_CLASS] != class) - goto wrong; - } - - /* Switch xvec to match the specified byte order. */ - switch (x_ehdr.e_ident[EI_DATA]) + ) { - case ELFDATA2MSB: /* Big-endian */ - if (!abfd->xvec->header_byteorder_big_p) - goto wrong; - break; - case ELFDATA2LSB: /* Little-endian */ - if (abfd->xvec->header_byteorder_big_p) - goto wrong; - break; - case ELFDATANONE: /* No data encoding specified */ - default: /* Unknown data encoding specified */ - goto wrong; - } + /* emit a reloc section, and thus strtab and symtab... */ + Elf_Internal_Shdr *rela_hdr; + Elf_External_Rela *outbound_relocas; + Elf_External_Rel *outbound_relocs; + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - /* Allocate an instance of the elf_obj_tdata structure and hook it up to - the tdata pointer in the bfd. */ + rela_hdr = &elf_section_data (asect)->rel_hdr; - if (NULL == (elf_tdata (abfd) = (struct elf_obj_tdata *) - bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)))) + /* orelocation has the data, reloc_count has the count... */ + if (use_rela_p) + { + rela_hdr->sh_type = SHT_RELA; + rela_hdr->sh_entsize = sizeof (Elf_External_Rela); + } + else + /* REL relocations */ + { + rela_hdr->sh_type = SHT_REL; + rela_hdr->sh_entsize = sizeof (Elf_External_Rel); + } + rela_hdr->sh_flags = 0; + rela_hdr->sh_addr = 0; + rela_hdr->sh_offset = 0; + rela_hdr->sh_addralign = 0; + rela_hdr->size = 0; + } + if (asect->flags & SEC_ALLOC) { - bfd_error = no_memory; - return NULL; + this_hdr->sh_flags |= SHF_ALLOC; + if (asect->flags & SEC_LOAD) + { + /* @@ Do something with sh_type? */ + } } + if (!(asect->flags & SEC_READONLY)) + this_hdr->sh_flags |= SHF_WRITE; - /* FIXME: Any `wrong' exits below here will leak memory (tdata). */ + if (asect->flags & SEC_CODE) + this_hdr->sh_flags |= SHF_EXECINSTR; +} - /* 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 +void +write_relocs (abfd, sec, xxx) + bfd *abfd; + asection *sec; + PTR xxx; +{ + Elf_Internal_Shdr *rela_hdr; + Elf_External_Rela *outbound_relocas; + Elf_External_Rel *outbound_relocs; + int idx; + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - /* If there is no section header table, we're hosed. */ - if (i_ehdrp->e_shoff == 0) - goto wrong; +malloc(0); + if ((sec->flags & SEC_RELOC) == 0) + return; + /* Flags are sometimes inconsistent. */ + if (sec->reloc_count == 0) + return; - if (i_ehdrp->e_type == ET_EXEC || i_ehdrp->e_type == ET_DYN) - abfd->flags |= EXEC_P; + rela_hdr = &elf_section_data (sec)->rel_hdr; - /* Retrieve the architecture information from the xvec and verify - that it matches the machine info stored in the ELF header. - This allows us to resolve ambiguous formats that might not - otherwise be distinguishable. */ + rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; + rela_hdr->contents = (void *) bfd_alloc (abfd, rela_hdr->sh_size); - ebd = get_elf_backend_data (abfd); - switch (i_ehdrp->e_machine) - { - default: - case EM_NONE: - case EM_M32: - /* Arguably EM_M32 should be bfd_arch_obscure, but then we would - need both an elf32-obscure target and an elf32-unknown target. - The distinction is probably not worth worrying about. */ - if (ebd->arch != bfd_arch_unknown) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_unknown, 0); - break; - case EM_SPARC: - if (ebd->arch != bfd_arch_sparc) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_sparc, 0); - break; + /* orelocation has the data, reloc_count has the count... */ + if (use_rela_p) + { + outbound_relocas = (Elf_External_Rela *) rela_hdr->contents; - /* start-sanitize-v9 */ - case EM_SPARC64: /* v9 */ - if (ebd->arch != bfd_arch_sparc) /* v9 */ - goto wrong; /* v9 */ - bfd_default_set_arch_mach (abfd, bfd_arch_sparc, 0); /* v9 */ - break; /* v9 */ - /* end-sanitize-v9 */ + for (idx = 0; idx < sec->reloc_count; idx++) + { + Elf_Internal_Rela dst_rela; + Elf_External_Rela *src_rela; + arelent *ptr; + asymbol *sym; - case EM_386: - if (ebd->arch != bfd_arch_i386) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_i386, 0); - break; - case EM_68K: - if (ebd->arch != bfd_arch_m68k) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); - break; - case EM_88K: - if (ebd->arch != bfd_arch_m88k) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0); - break; - case EM_860: - if (ebd->arch != bfd_arch_i860) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_i860, 0); - break; - case EM_MIPS: - if (ebd->arch != bfd_arch_mips) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_mips, 0); - break; - case EM_HPPA: - if (ebd->arch != bfd_arch_hppa) - goto wrong; - bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 0); - break; - } + ptr = sec->orelocation[idx]; + src_rela = outbound_relocas + idx; + if (!(abfd->flags & EXEC_P)) + dst_rela.r_offset = ptr->address - sec->vma; + else + dst_rela.r_offset = ptr->address; - /* Allocate space for a copy of the section header table in - internal form, seek to the section 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 section - header table entry actually matches the size recorded in the file. */ + sym = *ptr->sym_ptr_ptr; +#if 0 + /* I think this bit is wrong. But doing it right here means + fixing bfd_perform_relocation, and verifying that it doesn't + break other targets. Sigh. + + Problem I'm trying to solve here: `ld -r' tends to get + offset of target symbol in output-file section put into + addend, but retains the original symbol, so the net + result is doubling of that offset. */ + if (!bfd_is_com_section (sym->section) + && sym->section != &bfd_und_section) + { + /* Could adjust either the offset or the symbol here. + I'm pretty indifferent. */ + sym = sym->section->symbol; + } +#endif + dst_rela.r_info + = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, &sym), + ptr->howto->type); - if (i_ehdrp->e_shentsize != sizeof (x_shdr)) - goto wrong; - i_shdrp = (Elf_Internal_Shdr *) - bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum); - if (!i_shdrp) - { - bfd_error = no_memory; - return NULL; - } - if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) == -1) - { - bfd_error = system_call_error; - return NULL; - } - for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++) - { - if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) - != sizeof (x_shdr)) - { - bfd_error = system_call_error; - return NULL; + dst_rela.r_addend = ptr->addend; + elf_swap_reloca_out (abfd, &dst_rela, src_rela); +malloc(0); + } } - elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); - } - - elf_elfsections (abfd) = i_shdrp; + else + /* REL relocations */ + { + outbound_relocs = (Elf_External_Rel *) rela_hdr->contents; - /* Read in the string table containing the names of the sections. We - will need the base pointer to this table later. */ - /* We read this inline now, so that we don't have to go through - bfd_section_from_shdr with it (since this particular strtab is - used to find all of the ELF section names.) */ + for (idx = 0; idx < sec->reloc_count; idx++) + { + Elf_Internal_Rel dst_rel; + Elf_External_Rel *src_rel; + arelent *ptr; - shstrtab = elf_get_str_section (abfd, i_ehdrp->e_shstrndx); - if (!shstrtab) - return NULL; + ptr = sec->orelocation[idx]; + src_rel = outbound_relocs + idx; + if (!(abfd->flags & EXEC_P)) + dst_rel.r_offset = ptr->address - sec->vma; + else + dst_rel.r_offset = ptr->address; + + dst_rel.r_info + = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, ptr->sym_ptr_ptr), + ptr->howto->type); + + elf_swap_reloc_out (abfd, &dst_rel, src_rel); + + /* Update the addend -- FIXME add 64 bit support. */ + bfd_put_32 (abfd, ptr->addend, + (unsigned char *) (elf_section_data (sec)->this_hdr.contents) + + dst_rel.r_offset); + } + } +} - /* Once all of the section headers have been read and converted, we - can start processing them. Note that the first section header is - a dummy placeholder entry, so we ignore it. +static void +fix_up_strtabs (abfd, asect, obj) + bfd *abfd; + asection *asect; + PTR obj; +{ + Elf_Internal_Shdr *this_hdr = &elf_section_data (asect)->this_hdr; + int this_idx = elf_section_data(asect)->this_idx; - We also watch for the symbol table section and remember the file - offset and section size for both the symbol table section and the - associated string table section. */ + /* @@ Check flags! */ + if (!strncmp (asect->name, ".stab", 5) + && !strcmp ("str", asect->name + strlen (asect->name) - 3)) + { + size_t len = strlen (asect->name) + 1; + char *s = alloca (len); + strcpy (s, asect->name); + s[len - 4] = 0; + asect = bfd_get_section_by_name (abfd, s); + if (!asect) + abort (); + elf_section_data(asect)->this_hdr.sh_link = this_idx; - for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++) - { - bfd_section_from_shdr (abfd, shindex); + /* @@ Assuming 32 bits! */ + this_hdr->sh_entsize = 0xc; } +} - /* Remember the entry point specified in the ELF file header. */ +static void +DEFUN (elf_fake_sections, (abfd, asect, obj), + bfd * abfd AND + asection * asect AND + PTR obj) +{ + /* most of what is in bfd_shdr_from_section goes in here... */ + /* and all of these sections generate at *least* one ELF section. */ - bfd_get_start_address (abfd) = i_ehdrp->e_entry; + Elf_Internal_Shdr *this_hdr; + this_hdr = &elf_section_data (asect)->this_hdr; + this_hdr->sh_name = + bfd_add_to_strtab (abfd, elf_shstrtab (abfd), asect->name); + /* We need to log the type *now* so that elf_section_from_bfd_section + can find us... have to set rawdata too. */ + this_hdr->rawdata = (void *) asect; + this_hdr->sh_addralign = 1 << asect->alignment_power; + if ((asect->flags & SEC_ALLOC) && (asect->flags & SEC_LOAD)) + this_hdr->sh_type = SHT_PROGBITS; + /* @@ Select conditions correctly! */ + else if (!strcmp (asect->name, ".bss")) + this_hdr->sh_type = SHT_NOBITS; + else + /* what *do* we put here? */ + this_hdr->sh_type = SHT_PROGBITS; + + this_hdr->sh_flags = 0; + this_hdr->sh_addr = 0; + this_hdr->sh_size = 0; + this_hdr->sh_entsize = 0; + this_hdr->sh_info = 0; + this_hdr->sh_link = 0; + this_hdr->sh_offset = 0; + this_hdr->size = 0; - return abfd->xvec; -} + { + /* Emit a strtab and symtab, and possibly a reloc section. */ + Elf_Internal_Shdr *rela_hdr; + Elf_Internal_Shdr *symstrtab_hdr; -/* - Takes a bfd and a symbol, returns a pointer to the elf specific area - of the symbol if there is one. - */ -static INLINE elf_symbol_type * -DEFUN (elf_symbol_from, (ignore_abfd, symbol), - bfd * ignore_abfd AND - asymbol * symbol) -{ - if (symbol->the_bfd->xvec->flavour != bfd_target_elf_flavour) - return 0; + /* Note that only one symtab is used, so just remember it + for now. */ - if (symbol->the_bfd->tdata.elf_obj_data == (struct elf_obj_tdata *) NULL) - return 0; + if ((asect->flags & SEC_RELOC) + /* inconsistent flags... */ + && asect->reloc_count > 0) + { + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - return (elf_symbol_type *) symbol; + rela_hdr = &elf_section_data (asect)->rel_hdr; + rela_hdr->sh_name = + bfd_add_2_to_strtab (abfd, elf_shstrtab (abfd), + use_rela_p ? ".rela" : ".rel", + asect->name); + 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_flags = 0; + rela_hdr->sh_addr = 0; + rela_hdr->sh_size = 0; + rela_hdr->sh_offset = 0; + rela_hdr->sh_addralign = 0; + rela_hdr->size = 0; + } + } + if (asect->flags & SEC_ALLOC) + { + this_hdr->sh_flags |= SHF_ALLOC; + if (asect->flags & SEC_LOAD) + { + /* @@ Do something with sh_type? */ + } + } + if (!(asect->flags & SEC_READONLY)) + this_hdr->sh_flags |= SHF_WRITE; + if (asect->flags & SEC_CODE) + this_hdr->sh_flags |= SHF_EXECINSTR; } -/* 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). +/* +xxxINTERNAL_FUNCTION + bfd_elf_locate_sh - */ +xxxSYNOPSIS + struct elf_internal_shdr *bfd_elf_locate_sh (bfd *abfd, + struct strtab *strtab, + struct elf_internal_shdr *shdrp, + CONST char *name); -bfd_target * -DEFUN (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; +xxxDESCRIPTION + Helper function to locate an ELF section header given the + name of a BFD section. +*/ - /* Read in the ELF header in external format. */ +static struct elfNAME (internal_shdr) * +DEFUN (elf_locate_sh, (abfd, strtab, shdrp, name), + bfd * abfd AND + struct strtab *strtab AND + struct elfNAME (internal_shdr) *shdrp AND + CONST char *name) +{ + Elf_Internal_Shdr *gotit = NULL; + int max, i; - if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) + if (shdrp != NULL && strtab != NULL) { - bfd_error = system_call_error; - return NULL; + max = elf_elfheader (abfd)->e_shnum; + for (i = 1; i < max; i++) + { + if (!strcmp (strtab->tab + shdrp[i].sh_name, name)) + { + gotit = &shdrp[i]; + } + } } + return gotit; +} - /* 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). */ +/* Map symbol from it's internal number to the external number, moving + all local symbols to be at the head of the list. */ - if (elf_file_p (&x_ehdr) == false) +static INLINE int +sym_is_global (sym) + asymbol *sym; +{ + if (sym->flags & BSF_GLOBAL) { - wrong: - bfd_error = wrong_format; - return NULL; + if (sym->flags & BSF_LOCAL) + abort (); + return 1; } + if (sym->section == &bfd_und_section) + return 1; + if (bfd_is_com_section (sym->section)) + return 1; + if (sym->flags & (BSF_LOCAL | BSF_SECTION_SYM | BSF_FILE)) + return 0; + return 0; +} - /* 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 +static void +DEFUN (elf_map_symbols, (abfd), bfd * abfd) +{ + int symcount = bfd_get_symcount (abfd); + asymbol **syms = bfd_get_outsymbols (abfd); + int num_locals = 0; + int num_globals = 0; + int num_locals2 = 0; + int num_globals2 = 0; + int num_sections = 0; + int *symtab_map; + int idx; + asection *asect; - if (x_ehdr.e_ident[EI_CLASS] != desired_address_size) - goto wrong; - } +#ifdef DEBUG + fprintf (stderr, "elf_map_symbols\n"); + fflush (stderr); +#endif - /* Switch xvec to match the specified byte order. */ - switch (x_ehdr.e_ident[EI_DATA]) + /* Add local symbols for each allocated section + FIXME -- we should only put out symbols for sections that + are actually relocated against. */ + for (asect = abfd->sections; asect; asect = asect->next) { - 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; + if (/*asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE)*/1) + num_sections++; } - /* 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) + if (num_sections) { - bfd_error = no_memory; - return NULL; - } - - /* FIXME, `wrong' returns from this point onward, leak memory. */ + if (syms) + syms = (asymbol **) bfd_realloc (abfd, syms, + ((symcount + num_sections + 1) + * sizeof (asymbol *))); + else + syms = (asymbol **) bfd_alloc (abfd, + (num_sections + 1) * sizeof (asymbol *)); - /* 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 + for (asect = abfd->sections; asect; asect = asect->next) + { + if (/* asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE) */ 1) + { + asymbol *sym = syms[symcount++] = bfd_make_empty_symbol (abfd); + sym->the_bfd = abfd; + sym->name = asect->name; + sym->value = asect->vma; + sym->flags = BSF_SECTION_SYM; + sym->section = asect; + } + } - /* If 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; + syms[symcount] = (asymbol *) 0; + bfd_set_symtab (abfd, syms, symcount); + } - /* 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. */ + elf_symtab_map (abfd) = symtab_map + = (int *) bfd_alloc (abfd, symcount * sizeof (int *)); - 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_error = no_memory; - return NULL; - } - if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1) + /* Identify and classify all of the symbols. */ + for (idx = 0; idx < symcount; idx++) { - bfd_error = system_call_error; - return NULL; + if (!sym_is_global (syms[idx])) + num_locals++; + else + num_globals++; } - for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++) + + /* Now provide mapping information. Add +1 for skipping over the + dummy symbol. */ + for (idx = 0; idx < symcount; idx++) { - if (bfd_read ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd) - != sizeof (x_phdr)) - { - bfd_error = system_call_error; - return NULL; - } - elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex); + if (!sym_is_global (syms[idx])) + symtab_map[idx] = 1 + num_locals2++; + else + symtab_map[idx] = 1 + num_locals + num_globals2++; } - /* Once all of the program headers have been read and converted, we - can start processing them. */ + elf_num_locals (abfd) = num_locals; + elf_num_globals (abfd) = num_globals; +} - 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) - { - elf_corefile_note (abfd, i_phdrp + phindex); - } - } +static void assign_section_numbers (); +static void assign_file_positions_except_relocs (); - /* Remember the entry point specified in the ELF file header. */ +static boolean +DEFUN (elf_compute_section_file_positions, (abfd), bfd * abfd) +{ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ + struct strtab *shstrtab; + int count, maxsections; - bfd_get_start_address (abfd) = i_ehdrp->e_entry; + bfd_map_over_sections (abfd, elf_fake_sections, 0); - return abfd->xvec; -} + assign_section_numbers (abfd); -/* - Create ELF output from BFD sections. + bfd_map_over_sections (abfd, elf_make_sections, 0); - Essentially, just create the section header and forget about the program - header for now. + bfd_map_over_sections (abfd, fix_up_strtabs, 0); /* .stab/.stabstr &c */ -*/ + swap_out_syms (abfd); -#if 0 /* not used */ -static int -elf_idx_of_sym (abfd, sym) - bfd *abfd; - asymbol *sym; + assign_file_positions_except_relocs (abfd); + + return true; +} + +static boolean +DEFUN (elf_write_phdrs, (abfd, i_ehdrp, i_phdrp, phdr_cnt), + bfd * abfd AND + Elf_Internal_Ehdr * i_ehdrp AND + Elf_Internal_Phdr * i_phdrp AND + Elf32_Half phdr_cnt) { + /* first program header entry goes after the file header */ + int outbase = i_ehdrp->e_ehsize; int i; - for (i = 0; i < abfd->symcount; i++) + Elf_External_Phdr x_phdr; + + for (i = 0; i < phdr_cnt; i++) { - if (sym == (asymbol *) abfd->outsymbols[i]) - { - /* sanity check */ - BFD_ASSERT ((strcmp (sym->name, abfd->outsymbols[i]->name) == 0) - || (strlen (sym->name) == 0)); - return i + 1; - } + elf_swap_phdr_out (abfd, i_phdrp + i, &x_phdr); + bfd_seek (abfd, outbase, SEEK_SET); + bfd_write ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd); + outbase += sizeof (x_phdr); } - return STN_UNDEF; + + return true; } -#endif -static void -DEFUN (elf_make_sections, (abfd, asect, obj), +static Elf_Internal_Phdr * +DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt), bfd * abfd AND - asection * asect AND - PTR obj) + Elf_Internal_Ehdr * i_ehdrp AND + Elf_Internal_Shdr * i_shdrp AND + Elf32_Half * phdr_cnt) { - elf_sect_thunk *thunk = (elf_sect_thunk *) obj; - /* most of what is in bfd_shdr_from_section goes in here... */ - /* and all of these sections generate at *least* one ELF section. */ - int this_section; + Elf_Internal_Phdr *phdr_buf; int idx; + /* NOTES: + 1. The program header table is *not* loaded as part + of the memory image of the program. If this + changes later, the PT_PHDR entry must come first. + 2. there is currently no support for program header + entries of type PT_PHDR, PT_DYNAMIC, PT_INTERP, + or PT_SHLIB. */ - Elf_Internal_Shdr *this_hdr; - this_section = elf_section_from_bfd_section (abfd, asect); - this_hdr = &thunk->i_shdrp[this_section]; + /* A. Figure out how many program header table entries are needed + 1. PT_LOAD for the text segment + 2. PT_LOAD for the data segment + Then, reserve space for one more pointer. This will be NULL + to indicate the end of the program header table. */ - this_hdr->sh_addr = asect->vma; - this_hdr->sh_size = asect->_raw_size; - /* contents already set by elf_set_section_contents */ +#ifdef PHDRS_INCLUDED + *phdr_cnt = 4; +#else + /* XXX right now, execve() expects exactly 3 PT entries on HPPA-OSF. */ + *phdr_cnt = 3; +#endif - if (asect->flags & SEC_RELOC) - { - /* emit a reloc section, and thus strtab and symtab... */ - Elf_Internal_Shdr *rela_hdr; - Elf_Internal_Shdr *symtab_hdr; - Elf_External_Rela *outbound_relocas; - Elf_External_Rel *outbound_relocs; - int rela_section; - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; + phdr_buf = (Elf_Internal_Phdr *) bfd_xmalloc (((*phdr_cnt) + 1) + * + sizeof (Elf_Internal_Phdr)); - symtab_hdr = &thunk->i_shdrp[thunk->symtab_section]; + idx = 0; +#ifdef PHDRS_INCLUDED + /* B. Fill in the PT_PHDR entry. */ - if (thunk->symtab_section == this_section + 1) - rela_section = thunk->symtab_section + 2; /* symtab + symstrtab */ - else - rela_section = this_section + 1; - rela_hdr = &thunk->i_shdrp[rela_section]; - rela_hdr->sh_link = thunk->symtab_section; - rela_hdr->sh_info = this_section; + idx++; +#endif - /* orelocation has the data, reloc_count has the count... */ - if (use_rela_p) - { - rela_hdr->sh_type = SHT_RELA; - rela_hdr->sh_entsize = sizeof (Elf_External_Rela); - rela_hdr->sh_size = rela_hdr->sh_entsize * asect->reloc_count; - outbound_relocas = (Elf_External_Rela *) bfd_alloc (abfd, rela_hdr->sh_size); - - for (idx = 0; idx < asect->reloc_count; idx++) - { - Elf_Internal_Rela dst_rela; - Elf_External_Rela *src_rela; - arelent *ptr; - - ptr = asect->orelocation[idx]; - src_rela = outbound_relocas + idx; - if (!(abfd->flags & EXEC_P)) - dst_rela.r_offset = ptr->address - asect->vma; - else - dst_rela.r_offset = ptr->address; - - dst_rela.r_info - = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, ptr->sym_ptr_ptr), - ptr->howto->type); - - dst_rela.r_addend = ptr->addend; - elf_swap_reloca_out (abfd, &dst_rela, src_rela); - } + /* C. Fill in the PT_LOAD entry for the text segment. */ - rela_hdr->contents = (void *) outbound_relocas; + phdr_buf[idx].p_type = PT_LOAD; - rela_hdr->sh_flags = 0; - rela_hdr->sh_addr = 0; - rela_hdr->sh_offset = 0; - rela_hdr->sh_addralign = 0; - rela_hdr->size = 0; - } - else - /* REL relocations */ - { - rela_hdr->sh_type = SHT_REL; - rela_hdr->sh_entsize = sizeof (Elf_External_Rel); - rela_hdr->sh_size = rela_hdr->sh_entsize * asect->reloc_count; - outbound_relocs = (Elf_External_Rel *) - bfd_alloc (abfd, rela_hdr->sh_size); - - for (idx = 0; idx < asect->reloc_count; idx++) - { - Elf_Internal_Rel dst_rel; - Elf_External_Rel *src_rel; - arelent *ptr; - - ptr = asect->orelocation[idx]; - src_rel = outbound_relocs + idx; - if (!(abfd->flags & EXEC_P)) - dst_rel.r_offset = ptr->address - asect->vma; - else - dst_rel.r_offset = ptr->address; - - dst_rel.r_info - = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, ptr->sym_ptr_ptr), - ptr->howto->type); - - elf_swap_reloc_out (abfd, &dst_rel, src_rel); - - /* Update the addend -- FIXME add 64 bit support. */ -#ifdef DEBUG - fprintf (stderr, "Updating addend: 0x%.8lx = %d, this_section = %d\n", - (long) ((unsigned char *) (elf_elfsections (abfd)[this_section].contents) - + dst_rel.r_offset), ptr->addend, this_section); -#endif - - bfd_put_32 (abfd, ptr->addend, - (unsigned char *) (elf_elfsections (abfd)[this_section].contents) - + dst_rel.r_offset); - } - rela_hdr->contents = (void *) outbound_relocs; + /* get virtual/physical address from .text section */ + phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".text")->vma; + phdr_buf[idx].p_paddr = 0; /* XXX */ - rela_hdr->sh_flags = 0; - rela_hdr->sh_addr = 0; - rela_hdr->sh_offset = 0; - rela_hdr->sh_addralign = 0; - rela_hdr->size = 0; - } - } - if (asect->flags & SEC_ALLOC) - { - this_hdr->sh_flags |= SHF_ALLOC; - if (asect->flags & SEC_LOAD) - { - /* @@ Do something with sh_type? */ - } - } - if (!(asect->flags & SEC_READONLY)) - this_hdr->sh_flags |= SHF_WRITE; + /* Ultimately, we would like the size of the .text load + segment to be the sum of the following sections: + the program header table itself + .interp + .hash + .dynsym + .dynstr + .rela.bss + .rela.plt + .init + .text + .fini + .rodata + But, right now, it will be the sum of the following sections: + .text + .rodata */ - if (asect->flags & SEC_CODE) - this_hdr->sh_flags |= SHF_EXECINSTR; + { + static char *CONST ld_sect_names[] = + {".text", ".rodata", NULL}; + int i; + int ld_size = 0; + + for (i = 0; ld_sect_names[i]; i++) + { + asection *asect = bfd_get_section_by_name (abfd, + ld_sect_names[i]); + + if (asect) + ld_size += bfd_section_size (abfd, asect); + } + phdr_buf[idx].p_filesz = ld_size; + /* XXX: need to fix this */ + phdr_buf[idx].p_memsz = ld_size; + } + phdr_buf[idx].p_flags = PF_R + PF_X; + phdr_buf[idx].p_align = + bfd_get_section_by_name (abfd, ".text")->alignment_power; + + idx++; + + /* D. Fill in the PT_LOAD entry for the data segment. */ + + phdr_buf[idx].p_type = PT_LOAD; + + /* get virtual/physical address from .data section */ + phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".data")->vma; + phdr_buf[idx].p_paddr = 0; /* XXX */ + + /* Ultimately, we would like the size of the data load segment + to be the sum of the following sections: + the PT_DYNAMIC program header table entry + .plt + .data + .data1 + .got + .dynamic + But, right now, it will be the sum of the following sections: + .data */ + + { + static char *CONST ld_sect_names[] = + {".data", NULL}; + int i; + int ld_size = 0; + + for (i = 0; ld_sect_names[i]; i++) + { + asection *asect = bfd_get_section_by_name (abfd, + ld_sect_names[i]); + + if (asect) + ld_size += bfd_section_size (abfd, asect); + } + phdr_buf[idx].p_filesz = ld_size; + /* XXX: need to fix this */ + phdr_buf[idx].p_memsz = ld_size; + } + phdr_buf[idx].p_flags = PF_R + PF_W + PF_X; + phdr_buf[idx].p_align + = bfd_get_section_by_name (abfd, ".data")->alignment_power; + + idx++; + + /* E. Fill in the PT_LOAD entry for the bss segment. */ + + phdr_buf[idx].p_type = PT_LOAD; + + /* get virtual/physical address from .data section */ + phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".bss")->vma; + phdr_buf[idx].p_paddr = 0; /* XXX */ + + { + static char *CONST ld_sect_names[] = + {".bss", NULL}; + int i; + int ld_size = 0; + + for (i = 0; ld_sect_names[i]; i++) + { + asection *asect = bfd_get_section_by_name (abfd, + ld_sect_names[i]); + + if (asect) + ld_size += bfd_section_size (abfd, asect); + } + phdr_buf[idx].p_filesz = 0; + /* XXX: need to fix this */ + phdr_buf[idx].p_memsz = ld_size; + } + phdr_buf[idx].p_flags = PF_R + PF_W + PF_X; + phdr_buf[idx].p_align + = bfd_get_section_by_name (abfd, ".bss")->alignment_power; + + idx++; + + /* F. Set up the "end of program header table" sentinel. */ + + memset ((char *) (phdr_buf + idx), 0, sizeof (Elf_Internal_Phdr)); + idx++; + + BFD_ASSERT (idx - 1 == *phdr_cnt); + + return phdr_buf; } +static const Elf_Internal_Shdr null_shdr; + +/* 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. (Link pointers for .stab sections are + not filled in here.) */ static void -fix_up_strtabs (abfd, asect, obj) +assign_section_numbers (abfd) bfd *abfd; - asection *asect; - PTR obj; { - int this_section = elf_section_from_bfd_section (abfd, asect); - elf_sect_thunk *thunk = (elf_sect_thunk *) obj; - Elf_Internal_Shdr *this_hdr = &thunk->i_shdrp[this_section]; - - /* @@ Check flags! */ - if (!strncmp (asect->name, ".stab", 5) - && strcmp ("str", asect->name + strlen (asect->name) - 3)) - { - asection *s; - char strtab[100]; /* @@ fixed size buffer -- eliminate */ - int stridx; + struct elf_obj_tdata *t = elf_tdata (abfd); + asection *sec; + int section_number = 1; + int i; + Elf_Internal_Shdr **i_shdrp; - strcpy (strtab, asect->name); - strcat (strtab, "str"); + t->shstrtab_hdr.sh_size = elf_shstrtab(abfd)->length; + t->shstrtab_hdr.contents = (void *) elf_shstrtab(abfd)->tab; + shstrtab_length_fixed = 1; - s = bfd_get_section_by_name (abfd, strtab); -#if 0 - fprintf (stderr, "`%s' -> 0x%x\n", strtab, s); -#endif - if (s) + t->shstrtab_section = section_number++; + elf_elfheader(abfd)->e_shstrndx = t->shstrtab_section; + if (abfd->symcount) + { + t->symtab_section = section_number++; + t->strtab_section = section_number++; + 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); + d->this_idx = section_number++; + if (sec->reloc_count != 0) { - Elf_Internal_Shdr *s2 = thunk->i_shdrp; - - for (stridx = 0; /* ?? */; s2++, stridx++) - { - if (!strcmp (strtab, s2->sh_name + elf_shstrtab (abfd)->tab)) - break; - } + d->rel_idx = section_number++; + d->rel_hdr.sh_link = t->symtab_section; + d->rel_hdr.sh_info = d->this_idx; } else - { - stridx = 0; -#if 0 - { - asection *s2 = abfd->sections; - fprintf (stderr, " not in:"); - while (s2) - { - fprintf (stderr, " %s", s2->name); - s2 = s2->next; - } - fprintf (stderr, "\n"); - } -#endif - } - this_hdr->sh_link = stridx; - /* @@ Assuming 32 bits! */ - this_hdr->sh_entsize = 0xc; + d->rel_idx = 0; + /* No handling for per-section string tables currently. */ + } + elf_elfheader(abfd)->e_shnum = section_number; + + /* Set up the list of section header pointers, in agreement with the + indices. */ + i_shdrp = bfd_alloc (abfd, + section_number * sizeof (Elf_Internal_Shdr *)); + elf_elfsections(abfd) = i_shdrp; + for (i = 0; i < section_number; i++) + i_shdrp[i] = 0; + + i_shdrp[0] = (Elf_Internal_Shdr *) &null_shdr; + i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr; + if (abfd->symcount) + { + i_shdrp[t->symtab_section] = &t->symtab_hdr; + i_shdrp[t->strtab_section] = &t->strtab_hdr; } + for (sec = abfd->sections; sec; sec = sec->next) + { + struct bfd_elf_section_data *d = elf_section_data (sec); + i_shdrp[d->this_idx] = &d->this_hdr; + if (d->rel_idx) + i_shdrp[d->rel_idx] = &d->rel_hdr; + } + /* Make sure we got everything.... */ + for (i = 0; i < section_number; i++) + if (i_shdrp[i] == 0) + abort (); +} + +static INLINE file_ptr +assign_file_position_for_section (i_shdrp, offset) + Elf_Internal_Shdr *i_shdrp; + file_ptr offset; +{ + i_shdrp->sh_offset = offset; + offset += i_shdrp->sh_size; + return offset; } static void -DEFUN (elf_fake_sections, (abfd, asect, obj), - bfd * abfd AND - asection * asect AND - PTR obj) +assign_file_positions_except_relocs (abfd) + bfd *abfd; { - elf_sect_thunk *thunk = (elf_sect_thunk *) obj; - /* most of what is in bfd_shdr_from_section goes in here... */ - /* and all of these sections generate at *least* one ELF section. */ - int this_section; - - /* check if we're making a PROGBITS section... */ - /* if ((asect->flags & SEC_ALLOC) && (asect->flags & SEC_LOAD)) */ - /* this was too strict... what *do* we want to check here? */ - if (1) - { - Elf_Internal_Shdr *this_hdr; - this_section = thunk->i_ehdr->e_shnum++; - this_hdr = &thunk->i_shdrp[this_section]; - this_hdr->sh_name = - bfd_add_to_strtab (abfd, thunk->shstrtab, asect->name); - /* we need to log the type *now* so that elf_section_from_bfd_section - can find us... have to set rawdata too. */ - this_hdr->rawdata = (void *) asect; - this_hdr->sh_addralign = 1 << asect->alignment_power; - if ((asect->flags & SEC_ALLOC) && (asect->flags & SEC_LOAD)) - this_hdr->sh_type = SHT_PROGBITS; - /* @@ Select conditions correctly! */ - else if (!strcmp (asect->name, ".bss")) - this_hdr->sh_type = SHT_NOBITS; - else - /* what *do* we put here? */ - this_hdr->sh_type = SHT_PROGBITS; - - this_hdr->sh_flags = 0; - this_hdr->sh_addr = 0; - this_hdr->sh_size = 0; - this_hdr->sh_entsize = 0; - this_hdr->sh_info = 0; - this_hdr->sh_link = 0; - this_hdr->sh_offset = 0; - this_hdr->size = 0; + /* For now, we ignore the possibility of having program segments, which + may require some alignment in the file. That'll require padding, and + some interesting calculations to optimize file space usage. - { - /* Emit a strtab and symtab, and possibly a reloc section. */ - Elf_Internal_Shdr *rela_hdr; - Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Shdr *symstrtab_hdr; - int rela_section; - int symstrtab_section; - - /* Note that only one symtab is used, so just remember it - for now. */ - if (!thunk->symtab_section) - { - thunk->symtab_section = thunk->i_ehdr->e_shnum++; - symtab_hdr = &thunk->i_shdrp[thunk->symtab_section]; - symtab_hdr->sh_name = - bfd_add_to_strtab (abfd, thunk->shstrtab, ".symtab"); - symtab_hdr->sh_type = SHT_SYMTAB; - symtab_hdr->sh_entsize = sizeof (Elf_External_Sym); - - symstrtab_section = thunk->i_ehdr->e_shnum++; - BFD_ASSERT (symstrtab_section == thunk->symtab_section + 1); - symstrtab_hdr = &thunk->i_shdrp[symstrtab_section]; - symtab_hdr->sh_link = symstrtab_section; - symstrtab_hdr->sh_name = - bfd_add_to_strtab (abfd, thunk->shstrtab, ".strtab"); - symstrtab_hdr->sh_type = SHT_STRTAB; - - symtab_hdr->contents = 0; - symtab_hdr->sh_flags = 0; - symtab_hdr->sh_addr = 0; - symtab_hdr->sh_offset = 0; - symtab_hdr->sh_addralign = 0; - symtab_hdr->size = 0; - symstrtab_hdr->contents = 0; - symstrtab_hdr->sh_size = 0; - 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_offset = 0; - symstrtab_hdr->sh_addralign = 0; - symstrtab_hdr->size = 0; - } - else - symtab_hdr = &thunk->i_shdrp[thunk->symtab_section]; + Also, since the application may change the list of relocations for + a given section, we don't figure them in here. We'll put them at the + end of the file, at positions computed during bfd_close. - if (asect->flags & SEC_RELOC) - { - int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - - rela_section = thunk->i_ehdr->e_shnum++; - rela_hdr = &thunk->i_shdrp[rela_section]; - rela_hdr->sh_name = - bfd_add_2_to_strtab (abfd, thunk->shstrtab, - use_rela_p ? ".rela" : ".rel", - asect->name); - rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; - rela_hdr->sh_link = thunk->symtab_section; - rela_hdr->sh_info = this_section; - rela_hdr->sh_entsize = sizeof (Elf_External_Rela); - - rela_hdr->sh_flags = 0; - rela_hdr->sh_addr = 0; - rela_hdr->sh_size = 0; - rela_hdr->sh_offset = 0; - rela_hdr->sh_addralign = 0; - rela_hdr->size = 0; - } - } - if (asect->flags & SEC_ALLOC) + The order, for now: ... ... */ + + file_ptr off; + int i; + Elf_Internal_Shdr **i_shdrpp = elf_elfsections (abfd); + Elf_Internal_Shdr *i_shdrp; + Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); + + off = i_ehdrp->e_ehsize; + i_ehdrp->e_shoff = off; + off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize; + off = assign_file_position_for_section (&elf_tdata(abfd)->shstrtab_hdr, off); + off = assign_file_position_for_section (&elf_tdata(abfd)->symtab_hdr, off); + off = assign_file_position_for_section (&elf_tdata(abfd)->strtab_hdr, off); + for (i = 0; i < i_ehdrp->e_shnum; i++) + { + i_shdrp = i_shdrpp[i]; + if (i_shdrp->sh_type == SHT_REL || i_shdrp->sh_type == SHT_RELA) { - this_hdr->sh_flags |= SHF_ALLOC; - if (asect->flags & SEC_LOAD) - { - /* @@ Do something with sh_type? */ - } + i_shdrp->sh_offset = -1; + continue; } - if (!(asect->flags & SEC_READONLY)) - this_hdr->sh_flags |= SHF_WRITE; - if (asect->flags & SEC_CODE) - this_hdr->sh_flags |= SHF_EXECINSTR; + off = assign_file_position_for_section (i_shdrp, off); } + elf_tdata (abfd)->next_file_pos = off; } +static boolean +prep_headers (abfd) + bfd *abfd; +{ + Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */ + Elf_External_Shdr *x_shdrp; /* Section header table, external form */ + Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ -/* -xxxINTERNAL_FUNCTION - bfd_elf_locate_sh + int count; + int scnt; + struct strtab *shstrtab; -xxxSYNOPSIS - struct elf_internal_shdr *bfd_elf_locate_sh (bfd *abfd, - struct strtab *strtab, - struct elf_internal_shdr *shdrp, - CONST char *name); + i_ehdrp = elf_elfheader (abfd); + i_shdrp = elf_elfsections (abfd); -xxxDESCRIPTION - Helper function to locate an ELF section header given the - name of a BFD section. -*/ + shstrtab = bfd_new_strtab (abfd); + elf_shstrtab (abfd) = shstrtab; -static struct elfNAME (internal_shdr) * -DEFUN (elf_locate_sh, (abfd, strtab, shdrp, name), - bfd * abfd AND - struct strtab *strtab AND - struct elfNAME (internal_shdr) *shdrp AND - CONST char *name) -{ - Elf_Internal_Shdr *gotit = NULL; - int max, i; + 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; - if (shdrp != NULL && strtab != NULL) - { - max = elf_elfheader (abfd)->e_shnum; - for (i = 1; i < max; i++) - { - if (!strcmp (strtab->tab + shdrp[i].sh_name, name)) - { - gotit = &shdrp[i]; - } - } - } - return gotit; -} + 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; -/* Map symbol from it's internal number to the external number, moving - all local symbols to be at the head of the list. */ + for (count = EI_PAD; count < EI_NIDENT; count++) + i_ehdrp->e_ident[count] = 0; -static INLINE int -sym_is_global (sym) - asymbol *sym; -{ - if (sym->flags & BSF_GLOBAL) + i_ehdrp->e_type = (abfd->flags & EXEC_P) ? ET_EXEC : ET_REL; + switch (bfd_get_arch (abfd)) { - if (sym->flags & BSF_LOCAL) - abort (); - return 1; + 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; + /* also note that EM_M32, AT&T WE32100 is unknown to bfd */ + default: + i_ehdrp->e_machine = EM_NONE; } - if (sym->section == &bfd_und_section) - return 1; - if (bfd_is_com_section (sym->section)) - return 1; - if (sym->flags & (BSF_LOCAL | BSF_SECTION_SYM | BSF_FILE)) - return 0; - return 0; -} - -static void -DEFUN (elf_map_symbols, (abfd), bfd * abfd) -{ - int symcount = bfd_get_symcount (abfd); - asymbol **syms = bfd_get_outsymbols (abfd); - int num_locals = 0; - int num_globals = 0; - int num_locals2 = 0; - int num_globals2 = 0; - int num_sections = 0; - int *symtab_map; - int idx; - asection *asect; + i_ehdrp->e_version = EV_CURRENT; + i_ehdrp->e_ehsize = sizeof (Elf_External_Ehdr); -#ifdef DEBUG - fprintf (stderr, "elf_map_symbols\n"); - fflush (stderr); -#endif + /* no program header, for now. */ + i_ehdrp->e_phoff = 0; + i_ehdrp->e_phentsize = 0; + i_ehdrp->e_phnum = 0; - /* Add local symbols for each allocated section - FIXME -- we should only put out symbols for sections that - are actually relocated against. */ - for (asect = abfd->sections; asect; asect = asect->next) - { - if (/*asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE)*/1) - num_sections++; - } + /* 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 (num_sections) + /* if we're building an executable, we'll need a program header table */ + if (abfd->flags & EXEC_P) { - if (syms) - syms = (asymbol **) bfd_realloc (abfd, syms, - ((symcount + num_sections + 1) - * sizeof (asymbol *))); - else - syms = (asymbol **) bfd_alloc (abfd, - (num_sections + 1) * sizeof (asymbol *)); + abort (); - for (asect = abfd->sections; asect; asect = asect->next) - { - if (/* asect->flags & (SEC_LOAD | SEC_DATA | SEC_CODE) */ 1) - { - asymbol *sym = syms[symcount++] = bfd_make_empty_symbol (abfd); - sym->the_bfd = abfd; - sym->name = asect->name; - sym->value = asect->vma; - sym->flags = BSF_SECTION_SYM; - sym->section = asect; - } - } +#if 0 + i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr); - syms[symcount] = (asymbol *) 0; - bfd_set_symtab (abfd, syms, symcount); + /* 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 } - - elf_symtab_map (abfd) = symtab_map - = (int *) bfd_alloc (abfd, symcount * sizeof (int *)); - - /* Identify and classify all of the symbols. */ - for (idx = 0; idx < symcount; idx++) + else { - if (!sym_is_global (syms[idx])) - num_locals++; - else - num_globals++; + i_ehdrp->e_phentsize = 0; + i_phdrp = 0; + i_ehdrp->e_phoff = 0; } - /* Now provide mapping information. Add +1 for skipping over the - dummy symbol. */ - for (idx = 0; idx < symcount; idx++) - { - if (!sym_is_global (syms[idx])) - symtab_map[idx] = 1 + num_locals2++; - else - symtab_map[idx] = 1 + num_locals + num_globals2++; - } + 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"); - elf_num_locals (abfd) = num_locals; - elf_num_globals (abfd) = num_globals; } - -static boolean -DEFUN (elf_compute_section_file_positions, (abfd), bfd * abfd) +static void +swap_out_syms (abfd) + bfd *abfd; { - Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ - Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ - struct strtab *shstrtab; - int count, maxsections; - elf_sect_thunk est; - - if (!elf_shstrtab (abfd)) - { - i_ehdrp = elf_elfheader (abfd); /* build new header in tdata memory */ - shstrtab = bfd_new_strtab (abfd); - - 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; - -#if ARCH_SIZE == 32 - i_ehdrp->e_ident[EI_CLASS] = ELFCLASS32; -#endif -#if ARCH_SIZE == 64 - i_ehdrp->e_ident[EI_CLASS] = ELFCLASS64; -#endif - 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 /* v9 */ - i_ehdrp->e_machine = EM_SPARC64; /* v9 */ -#endif /* v9 */ - /* 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; - /* 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; + struct strtab *shstrtab = elf_shstrtab (abfd); - /* each bfd section is section header entry */ - i_ehdrp->e_entry = bfd_get_start_address (abfd); - i_ehdrp->e_shentsize = sizeof (Elf_External_Shdr); - - /* figure at most each section can have a rel, strtab, symtab */ - maxsections = 4 * bfd_count_sections (abfd) + 2; - - i_ehdrp->e_shoff = i_ehdrp->e_ehsize; - - /* and we'll just have to fix up the offsets later. */ - /* outbase += i_ehdr.e_shentsize * i_ehdr.e_shnum; */ - - i_shdrp = (Elf_Internal_Shdr *) - bfd_alloc (abfd, sizeof (*i_shdrp) * maxsections); - if (!i_shdrp) - { - bfd_error = no_memory; - return false; - } - for (count = 0; count < maxsections; count++) - { - i_shdrp[count].rawdata = 0; - i_shdrp[count].contents = 0; - } + elf_map_symbols (abfd); + /* 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; - i_shdrp[0].sh_name = 0; - i_shdrp[0].sh_type = SHT_NULL; - i_shdrp[0].sh_flags = 0; - i_shdrp[0].sh_addr = 0; - i_shdrp[0].sh_offset = 0; - i_shdrp[0].sh_size = 0; - i_shdrp[0].sh_link = SHN_UNDEF; - i_shdrp[0].sh_info = 0; - i_shdrp[0].sh_addralign = 0; - i_shdrp[0].sh_entsize = 0; + 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; - i_ehdrp->e_shnum = 1; + /* see assert in elf_fake_sections that supports this: */ + symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; + symstrtab_hdr->sh_type = SHT_STRTAB; - elf_elfsections (abfd) = i_shdrp; - elf_shstrtab (abfd) = shstrtab; + outbound_syms = (Elf_External_Sym *) + bfd_alloc (abfd, (1 + symcount) * sizeof (Elf_External_Sym)); + /* 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); } - est.i_ehdr = elf_elfheader (abfd); - est.i_shdrp = elf_elfsections (abfd); - est.shstrtab = elf_shstrtab (abfd); - est.symtab_section = 0; /* elf_fake_sections fills it in */ + for (idx = 0; idx < symcount; idx++) + { + Elf_Internal_Sym sym; + bfd_vma value = syms[idx]->value; - elf_map_symbols (abfd); - bfd_map_over_sections (abfd, elf_fake_sections, &est); - { - asection *secp; - asection *psecp = (asection *) 0; - int idx; - Elf_Internal_Shdr *shp; + 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); - for (idx = 0, secp = abfd->sections; secp; idx++, secp = secp->next) - { - if (psecp == (asection *) 0) + if (bfd_is_com_section (syms[idx]->section)) { - secp->filepos = est.i_ehdr->e_shoff + (est.i_ehdr->e_shnum + 1) * sizeof (Elf_External_Shdr); + /* 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 = SHN_COMMON; } else { - secp->filepos = psecp->filepos + psecp->_cooked_size; - } - shp = elf_locate_sh (abfd, est.shstrtab, est.i_shdrp, secp->name); - if (shp) - shp->sh_offset = secp->filepos; - psecp = secp; - } - } - elf_onesymtab (abfd) = est.symtab_section; - return true; -} + asection *sec = syms[idx]->section; + int shndx; -static boolean -DEFUN (elf_write_phdrs, (abfd, i_ehdrp, i_phdrp, phdr_cnt), - bfd * abfd AND - Elf_Internal_Ehdr * i_ehdrp AND - Elf_Internal_Phdr * i_phdrp AND - Elf32_Half phdr_cnt) -{ - /* first program header entry goes after the file header */ - int outbase = i_ehdrp->e_ehsize; - int i; - Elf_External_Phdr x_phdr; + if (sec->output_section) + { + value += sec->output_offset; + sec = sec->output_section; + } + value += sec->vma; + sym.st_value = value; + sym.st_size = (elf_symbol_from (abfd, syms[idx]))->internal_elf_sym.st_size; + 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); + assert (sec2 != 0); + sym.st_shndx = shndx = elf_section_from_bfd_section (abfd, sec2); + assert (shndx != -1); + } + } - for (i = 0; i < phdr_cnt; i++) - { - elf_swap_phdr_out (abfd, i_phdrp + i, &x_phdr); - bfd_seek (abfd, outbase, SEEK_SET); - bfd_write ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd); - outbase += sizeof (x_phdr); - } + if (bfd_is_com_section (syms[idx]->section)) + sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE); + else if (syms[idx]->section == &bfd_und_section) + sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE); + else if (syms[idx]->flags & BSF_WEAK) + sym.st_info = ELF_ST_INFO (STB_WEAK, STT_OBJECT); + else if (syms[idx]->flags & BSF_SECTION_SYM) + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); + else if (syms[idx]->flags & BSF_FILE) + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); + else if (syms[idx]->flags & (BSF_GLOBAL | BSF_EXPORT)) + { + if (syms[idx]->flags & BSF_FUNCTION) + sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); + else + sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT); + } + else if (syms[idx]->flags & BSF_LOCAL) + { + if (syms[idx]->flags & BSF_FUNCTION) + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC); + else + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT); + } + else + /* Default to local if flag isn't set at all. */ + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT); - return true; + sym.st_other = 0; + elf_swap_symbol_out (abfd, &sym, + outbound_syms + elf_symtab_map (abfd)[idx]); + } + + 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 = 0; + 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 = 0; + this_hdr->size = 0; + } } -static Elf_Internal_Phdr * -DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt), - bfd * abfd AND - Elf_Internal_Ehdr * i_ehdrp AND - Elf_Internal_Shdr * i_shdrp AND - Elf32_Half * phdr_cnt) +static boolean +write_shdrs_and_ehdr (abfd) + bfd *abfd; { - Elf_Internal_Phdr *phdr_buf; - int idx; - /* NOTES: - 1. The program header table is *not* loaded as part - of the memory image of the program. If this - changes later, the PT_PHDR entry must come first. - 2. there is currently no support for program header - entries of type PT_PHDR, PT_DYNAMIC, PT_INTERP, - or PT_SHLIB. */ + Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */ + Elf_External_Shdr *x_shdrp; /* Section header table, external form */ + Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ - /* A. Figure out how many program header table entries are needed - 1. PT_LOAD for the text segment - 2. PT_LOAD for the data segment - Then, reserve space for one more pointer. This will be NULL - to indicate the end of the program header table. */ + int count; + int scnt; + struct strtab *shstrtab; -#ifdef PHDRS_INCLUDED - *phdr_cnt = 4; -#else - /* XXX right now, execve() expects exactly 3 PT entries on HPPA-OSF. */ - *phdr_cnt = 3; + 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); + bfd_seek (abfd, (file_ptr) 0, SEEK_SET); + bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd); - phdr_buf = (Elf_Internal_Phdr *) bfd_xmalloc (((*phdr_cnt) + 1) - * - sizeof (Elf_Internal_Phdr)); + /* If we're building an executable, fixup the program header table + offsets. - idx = 0; -#ifdef PHDRS_INCLUDED - /* B. Fill in the PT_PHDR entry. */ + @@ For now, assume that the entries are in a fixed order: text, + data, bss. FIXME */ - idx++; + if (abfd->flags & EXEC_P) + { + static char *CONST section_name[] = + {".text", ".data", ".bss"}; + + for (count = 0; count < 3; count++) + { + asection *asect = bfd_get_section_by_name (abfd, + section_name[count]); + int sh_idx = elf_section_from_bfd_section (abfd, asect); + + i_phdrp[count].p_offset = i_shdrp[sh_idx]->sh_offset; + } + + /* write out the program header table entries */ + elf_write_phdrs (abfd, i_ehdrp, i_phdrp, i_ehdrp->e_phnum); + } + + /* 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_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); + } + bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET); + bfd_write ((PTR) x_shdrp, sizeof (*x_shdrp), i_ehdrp->e_shnum, abfd); + /* need to dump the string table too... */ - /* C. Fill in the PT_LOAD entry for the text segment. */ + return true; +} - phdr_buf[idx].p_type = PT_LOAD; +static void +assign_file_positions_for_relocs (abfd) + bfd *abfd; +{ + file_ptr off = elf_tdata(abfd)->next_file_pos; + int i; + Elf_Internal_Shdr **shdrpp = elf_elfsections (abfd); + Elf_Internal_Shdr *shdrp; + for (i = 0; i < elf_elfheader(abfd)->e_shnum; i++) + { + shdrp = shdrpp[i]; + if (shdrp->sh_type != SHT_REL && shdrp->sh_type != SHT_RELA) + continue; + off = assign_file_position_for_section (shdrp, off); + } + elf_tdata(abfd)->next_file_pos = off; +} - /* get virtual/physical address from .text section */ - phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".text")->vma; - phdr_buf[idx].p_paddr = 0; /* XXX */ +boolean +DEFUN (NAME(bfd_elf,write_object_contents), (abfd), bfd * abfd) +{ + Elf_Internal_Ehdr *i_ehdrp; + Elf_Internal_Shdr **i_shdrp; + int count; - /* Ultimately, we would like the size of the .text load - segment to be the sum of the following sections: - the program header table itself - .interp - .hash - .dynsym - .dynstr - .rela.bss - .rela.plt - .init - .text - .fini - .rodata - But, right now, it will be the sum of the following sections: - .text - .rodata */ + if (abfd->output_has_begun == false) + { + malloc (0); + prep_headers (abfd); +malloc(0); + elf_compute_section_file_positions (abfd); +malloc(0); + abfd->output_has_begun = true; + } - { - static char *CONST ld_sect_names[] = - {".text", ".rodata", NULL}; - int i; - int ld_size = 0; + i_shdrp = elf_elfsections (abfd); + i_ehdrp = elf_elfheader (abfd); - for (i = 0; ld_sect_names[i]; i++) - { - asection *asect = bfd_get_section_by_name (abfd, - ld_sect_names[i]); + bfd_map_over_sections (abfd, write_relocs, (PTR) 0); +malloc(0); + assign_file_positions_for_relocs (abfd); - if (asect) - ld_size += bfd_section_size (abfd, asect); + /* After writing the headers, we need to write the sections too... */ + for (count = 0; count < i_ehdrp->e_shnum; count++) + if (i_shdrp[count]->contents) + { + bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET); + bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size, 1, abfd); } - phdr_buf[idx].p_filesz = ld_size; - /* XXX: need to fix this */ - phdr_buf[idx].p_memsz = ld_size; - } - phdr_buf[idx].p_flags = PF_R + PF_X; - phdr_buf[idx].p_align = - bfd_get_section_by_name (abfd, ".text")->alignment_power; + return write_shdrs_and_ehdr (abfd); +} - idx++; +/* 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. */ - /* D. Fill in the PT_LOAD entry for the data segment. */ +/* 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... */ - phdr_buf[idx].p_type = PT_LOAD; +static struct sec * +DEFUN (section_from_elf_index, (abfd, index), + bfd * abfd AND + int index) +{ + /* @@ Is bfd_com_section really correct in all the places it could + be returned from this routine? */ - /* get virtual/physical address from .data section */ - phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".data")->vma; - phdr_buf[idx].p_paddr = 0; /* XXX */ + if (index == SHN_ABS) + return &bfd_com_section; /* not abs? */ + if (index == SHN_COMMON) + return &bfd_com_section; - /* Ultimately, we would like the size of the data load segment - to be the sum of the following sections: - the PT_DYNAMIC program header table entry - .plt - .data - .data1 - .got - .dynamic - But, right now, it will be the sum of the following sections: - .data */ + if (index > elf_elfheader (abfd)->e_shnum) + return 0; { - static char *CONST ld_sect_names[] = - {".data", NULL}; - int i; - int ld_size = 0; + Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[index]; - for (i = 0; ld_sect_names[i]; i++) + switch (hdr->sh_type) { - asection *asect = bfd_get_section_by_name (abfd, - ld_sect_names[i]); + /* 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; - if (asect) - ld_size += bfd_section_size (abfd, asect); + default: + return (struct sec *) &bfd_abs_section; } - phdr_buf[idx].p_filesz = ld_size; - /* XXX: need to fix this */ - phdr_buf[idx].p_memsz = ld_size; } - phdr_buf[idx].p_flags = PF_R + PF_W + PF_X; - phdr_buf[idx].p_align - = bfd_get_section_by_name (abfd, ".data")->alignment_power; +} - idx++; +/* given a section, search the header to find them... */ +static int +DEFUN (elf_section_from_bfd_section, (abfd, asect), + bfd * abfd AND + struct sec *asect) +{ + Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd); + int index; + Elf_Internal_Shdr *hdr; + int maxindex = elf_elfheader (abfd)->e_shnum; - /* E. Fill in the PT_LOAD entry for the bss segment. */ + if (asect == &bfd_abs_section) + return SHN_ABS; + if (asect == &bfd_com_section) + return SHN_COMMON; + if (asect == &bfd_und_section) + return SHN_UNDEF; - phdr_buf[idx].p_type = PT_LOAD; + 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: + if (hdr->rawdata) + { + if (((struct sec *) (hdr->rawdata)) == asect) + return index; + } + break; + default: + break; + } + } + return -1; +} - /* get virtual/physical address from .data section */ - phdr_buf[idx].p_vaddr = bfd_get_section_by_name (abfd, ".bss")->vma; - phdr_buf[idx].p_paddr = 0; /* XXX */ +/* given a symbol, return the bfd index for that symbol. */ +static int +DEFUN (elf_symbol_from_bfd_symbol, (abfd, asym_ptr_ptr), + bfd * abfd AND + struct symbol_cache_entry **asym_ptr_ptr) +{ + struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr; + CONST char *name = asym_ptr->name; + int idx; + int symcount = bfd_get_symcount (abfd); + asymbol **syms = bfd_get_outsymbols (abfd); + + /* FIXME -- there has to be a better way than linear search. */ + for (idx = 0; idx < symcount; idx++) + { + if (syms[idx] == asym_ptr + || (name == syms[idx]->name && name) + || ((asym_ptr->flags & BSF_SECTION_SYM) + && (syms[idx]->flags & BSF_SECTION_SYM) + && asym_ptr->section == syms[idx]->section)) + break; + } + + if (idx >= symcount) + { + /* badness... */ + fprintf (stderr, "bfd app err: can't find sym `%s' in symtab\n", + name); + abort (); + } + idx = elf_symtab_map (abfd)[idx]; +#if DEBUG & 4 { - static char *CONST ld_sect_names[] = - {".bss", NULL}; - int i; - int ld_size = 0; + flagword flags = asym_ptr->flags; - for (i = 0; ld_sect_names[i]; i++) - { - asection *asect = bfd_get_section_by_name (abfd, - ld_sect_names[i]); + fprintf (stderr, + "elfsym<-bfdsym %.8lx `%s' sec=%s symnum=%d {", + (long) asym_ptr, asym_ptr->name, asym_ptr->section->name, idx); - if (asect) - ld_size += bfd_section_size (abfd, asect); - } - phdr_buf[idx].p_filesz = 0; - /* XXX: need to fix this */ - phdr_buf[idx].p_memsz = ld_size; - } - phdr_buf[idx].p_flags = PF_R + PF_W + PF_X; - phdr_buf[idx].p_align - = bfd_get_section_by_name (abfd, ".bss")->alignment_power; + if (flags == BSF_NO_FLAGS) + fprintf (stderr, " none"); - idx++; + if (flags & BSF_LOCAL) + fprintf (stderr, " local"); - /* F. Set up the "end of program header table" sentinel. */ + if (flags & BSF_GLOBAL) + fprintf (stderr, " global"); - memset ((char *) (phdr_buf + idx), 0, sizeof (Elf_Internal_Phdr)); - idx++; + if (flags & BSF_EXPORT) + fprintf (stderr, " export"); - BFD_ASSERT (idx - 1 == *phdr_cnt); + if (flags & BSF_DEBUGGING) + fprintf (stderr, " debugging"); - return phdr_buf; -} + if (flags & BSF_KEEP) + fprintf (stderr, " keep"); -boolean -DEFUN (elf_write_object_contents, (abfd), bfd * abfd) -{ - Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ - Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ - Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */ - Elf_External_Shdr *x_shdrp; /* Section header table, external form */ - Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ - asection *nsect; - elf_sect_thunk est; + if (flags & BSF_KEEP_G) + fprintf (stderr, " keep_g"); - int outbase = 0; - int count; - int scnt; - struct strtab *shstrtab; + if (flags & BSF_WEAK) + fprintf (stderr, " weak"); - if (abfd->output_has_begun == false) - { - elf_compute_section_file_positions (abfd); - abfd->output_has_begun = true; - } + if (flags & BSF_SECTION_SYM) + fprintf (stderr, " section_sym"); - i_ehdrp = elf_elfheader (abfd); - i_shdrp = elf_elfsections (abfd); - shstrtab = elf_shstrtab (abfd); + if (flags & BSF_OLD_COMMON) + fprintf (stderr, " old_common"); - est.i_ehdr = i_ehdrp; - est.i_shdrp = i_shdrp; - est.shstrtab = shstrtab; - est.symtab_section = elf_onesymtab (abfd); /* filled in by elf_fake */ + if (flags & BSF_NOT_AT_END) + fprintf (stderr, " not_at_end"); - bfd_map_over_sections (abfd, elf_make_sections, &est); - bfd_map_over_sections (abfd, fix_up_strtabs, &est); + if (flags & BSF_CONSTRUCTOR) + fprintf (stderr, " constructor"); - /* 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; - int symstrtab_section; - Elf_External_Sym *outbound_syms; - int idx; + if (flags & BSF_WARNING) + fprintf (stderr, " warning"); - symtab_hdr = &i_shdrp[est.symtab_section]; - 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; + if (flags & BSF_INDIRECT) + fprintf (stderr, " indirect"); - /* see assert in elf_fake_sections that supports this: */ - symstrtab_section = est.symtab_section + 1; - symstrtab_hdr = &i_shdrp[symstrtab_section]; - symtab_hdr->sh_link = symstrtab_section; - symstrtab_hdr->sh_type = SHT_STRTAB; + if (flags & BSF_FILE) + fprintf (stderr, " file"); - outbound_syms = (Elf_External_Sym *) - bfd_alloc (abfd, (1 + symcount) * sizeof (Elf_External_Sym)); - /* now generate the data (for "contents") */ + if (flags & BSF_FUNCTION) + fprintf (stderr, " function"); + + fputs (" }\n", stderr); + fflush (stderr); + } +#endif + + return idx; +} + +static boolean +DEFUN (elf_slurp_symbol_table, (abfd, symptrs), + bfd * abfd AND + asymbol ** symptrs) /* Buffer for generated bfd symbols */ +{ + Elf_Internal_Shdr *hdr = &elf_tdata(abfd)->symtab_hdr; + int symcount; /* Number of external ELF symbols */ + int i; + 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; + + /* 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 */ + if (bfd_get_outsymbols (abfd) != NULL) { - /* 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); + return true; } - 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); + /* 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. - 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; - } - else - { - value += syms[idx]->section->output_section->vma - + syms[idx]->section->output_offset; - sym.st_value = value; + 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. */ - sym.st_size = (elf_symbol_from (abfd, syms[idx]))->internal_elf_sym.st_size; - } + if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) + { + bfd_error = system_call_error; + return false; + } - if (bfd_is_com_section (syms[idx]->section)) - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE); - else if (syms[idx]->section == &bfd_und_section) - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_NOTYPE); - else if (syms[idx]->flags & BSF_WEAK) - sym.st_info = ELF_ST_INFO (STB_WEAK, STT_OBJECT); - else if (syms[idx]->flags & BSF_SECTION_SYM) - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION); - else if (syms[idx]->flags & BSF_FILE) - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE); - else if (syms[idx]->flags & (BSF_GLOBAL | BSF_EXPORT)) - { - if (syms[idx]->flags & BSF_FUNCTION) - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); - else - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT); - } - else if (syms[idx]->flags & BSF_LOCAL) - { - if (syms[idx]->flags & BSF_FUNCTION) - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC); - else - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT); - } - else - /* Default to local if flag isn't set at all. */ - sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_OBJECT); - - sym.st_other = 0; - if (syms[idx]->section) - sym.st_shndx = - elf_section_from_bfd_section (abfd, - syms[idx]->section->output_section); - else - sym.st_shndx = SHN_UNDEF; - - elf_swap_symbol_out (abfd, &sym, - outbound_syms + elf_symtab_map (abfd)[idx]); - } - - symtab_hdr->contents = (void *) outbound_syms; - symstrtab_hdr->contents = (void *) 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_offset = 0; - symstrtab_hdr->sh_addralign = 0; - symstrtab_hdr->size = 0; - } - - /* put the strtab out too... */ - { - Elf_Internal_Shdr *this_hdr; - int this_section; - - this_section = i_ehdrp->e_shnum++; - i_ehdrp->e_shstrndx = this_section; - this_hdr = &i_shdrp[this_section]; - this_hdr->sh_name = bfd_add_to_strtab (abfd, shstrtab, ".shstrtab"); - this_hdr->sh_type = SHT_STRTAB; - this_hdr->sh_size = shstrtab->length; - this_hdr->contents = (void *) shstrtab->tab; - - this_hdr->sh_flags = 0; - this_hdr->sh_addr = 0; - this_hdr->sh_entsize = 0; - this_hdr->sh_link = 0; - this_hdr->sh_info = 0; - this_hdr->sh_offset = 0; - this_hdr->sh_addralign = 0; - this_hdr->size = 0; - } + symcount = hdr->sh_size / sizeof (Elf_External_Sym); + symbase = (elf_symbol_type *) bfd_zalloc (abfd, symcount * sizeof (elf_symbol_type)); + sym = symbase; - outbase = i_ehdrp->e_ehsize; + /* Temporarily allocate room for the raw ELF symbols. */ + x_symp = (Elf_External_Sym *) bfd_xmalloc (symcount * sizeof (Elf_External_Sym)); - /* if we're building an executable, we'll need a program header table */ - if (abfd->flags & EXEC_P) + if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd) + != symcount * sizeof (Elf_External_Sym)) { - 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 = i_ehdrp->e_ehsize; - i_ehdrp->e_shoff = i_ehdrp->e_phoff + (i_ehdrp->e_phentsize - * i_ehdrp->e_phnum); + free ((PTR) x_symp); + bfd_error = system_call_error; + return false; } - - /* 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); - bfd_seek (abfd, (file_ptr) 0, SEEK_SET); - bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd); - -#if 0 - outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum; - outbase += i_ehdrp->e_shentsize * i_ehdrp->e_shnum; -#endif - /* find the next available location in the file - (just beyond the sections that have already been written). */ - outbase = 0; - for (count = 1; count < i_ehdrp->e_shnum; count++) + /* Skip first symbol, which is a null dummy. */ + for (i = 1; i < symcount; i++) { - if (i_shdrp[count].sh_offset && outbase < i_shdrp[count].sh_offset) - outbase = i_shdrp[count].sh_offset + i_shdrp[count].sh_size; - } + elf_swap_symbol_in (abfd, x_symp + i, &i_sym); + memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym)); + memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym)); + sym->symbol.the_bfd = abfd; - /* now we fix up the offsets... */ - for (count = 1; count < i_ehdrp->e_shnum; count++) - { - if (i_shdrp[count].sh_offset == 0) - i_shdrp[count].sh_offset = outbase; - outbase += i_shdrp[count].sh_size; - } + sym->symbol.name = elf_string_from_elf_section (abfd, hdr->sh_link, + i_sym.st_name); - /* If we're building an executable, fixup the program header table - offsets. + sym->symbol.value = i_sym.st_value; - @@ For now, assume that the entries are in a fixed order: text, - data, bss. FIXME */ + 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; - if (abfd->flags & EXEC_P) - { - static char *CONST section_name[] = - {".text", ".data", ".bss"}; + sym->symbol.value -= sym->symbol.section->vma; - for (count = 0; count < 3; count++) + switch (ELF_ST_BIND (i_sym.st_info)) { - asection *asect = bfd_get_section_by_name (abfd, section_name[count]); - int sh_idx = elf_section_from_bfd_section (abfd, asect); + case STB_LOCAL: + sym->symbol.flags |= BSF_LOCAL; + break; + case STB_GLOBAL: + sym->symbol.flags |= (BSF_GLOBAL | BSF_EXPORT); + break; + case STB_WEAK: + sym->symbol.flags |= BSF_WEAK; + break; + } - i_phdrp[count].p_offset = i_shdrp[sh_idx].sh_offset; + 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; } + /* Is this a definition of $global$? If so, keep it because it will be + needd if any relocations are performed. */ + if (!strcmp (sym->symbol.name, "$global$") + && sym->symbol.section != &bfd_und_section) + { + /* @@ Why is this referring to backend data and not a field of + abfd? FIXME */ + struct elf_backend_data *be_data = (struct elf_backend_data *) abfd->xvec->backend_data; - /* write out the program header table entries */ - elf_write_phdrs (abfd, i_ehdrp, i_phdrp, i_ehdrp->e_phnum); + be_data->global_sym = (PTR) sym; + } + sym++; } - /* 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_error = no_memory; - return false; - } + /* We rely on the zalloc to clear out the final symbol entry. */ - for (count = 0, scnt = 0; count < i_ehdrp->e_shnum; count++) - { -#if DEBUG & 2 - elf_debug_section (shstrtab->tab + i_shdrp[scnt].sh_name, count, i_shdrp + scnt); -#endif - elf_swap_shdr_out (abfd, i_shdrp + count, x_shdrp + scnt); - scnt++; - } - bfd_write ((PTR) x_shdrp, sizeof (*x_shdrp), i_ehdrp->e_shnum, abfd); - /* need to dump the string table too... */ + /* obj_raw_syms macro uses a cast... */ + elf_tdata (abfd)->raw_syms = (PTR) x_symp; - /* after writing the headers, we need to write the sections too... */ - nsect = abfd->sections; - for (count = 0; count < i_ehdrp->e_shnum; count++) + bfd_get_symcount (abfd) = symcount = sym - symbase; + + /* Fill in the user's symbol pointer vector if needed. */ + if (symptrs) { - if (i_shdrp[count].contents) + sym = symbase; + while (symcount-- > 0) { - bfd_seek (abfd, i_shdrp[count].sh_offset, SEEK_SET); - bfd_write (i_shdrp[count].contents, i_shdrp[count].sh_size, 1, abfd); + *symptrs++ = &sym->symbol; + sym++; } + *symptrs = 0; /* Final null pointer */ } return true; } -/* 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. */ +/* Return the number of bytes required to hold the symtab vector. -/* 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... */ + 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. */ -static struct sec * -DEFUN (section_from_elf_index, (abfd, index), - bfd * abfd AND - int index) +unsigned int +DEFUN (elf_get_symtab_upper_bound, (abfd), bfd * abfd) { - /* @@ Is bfd_com_section really correct in all the places it could - be returned from this routine? */ + unsigned int symcount; + unsigned int symtab_size = 0; - if (index == SHN_ABS) - return &bfd_com_section; /* not abs? */ - if (index == SHN_COMMON) - return &bfd_com_section; + Elf_Internal_Shdr *hdr = &elf_tdata(abfd)->symtab_hdr; + symcount = hdr->sh_size / sizeof (Elf_External_Sym); + symtab_size = (symcount - 1 + 1) * (sizeof (asymbol)); - { - Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); - Elf_Internal_Shdr *hdr = i_shdrp + index; + return symtab_size; +} - 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; +/* + This function return the number of bytes required to store the + relocation information associated with section <> + attached to bfd <> - default: - return (struct sec *) &bfd_abs_section; - } - } +*/ +unsigned int +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; } -/* given a section, search the header to find them... */ -static int -DEFUN (elf_section_from_bfd_section, (abfd, asect), +static boolean +DEFUN (elf_slurp_reloca_table, (abfd, asect, symbols), bfd * abfd AND - struct sec *asect) + sec_ptr asect AND + asymbol ** symbols) { - 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; + Elf_External_Rela *native_relocs; + arelent *reloc_cache; + arelent *cache_ptr; - 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: - if (hdr->rawdata) - { - if (((struct sec *) (hdr->rawdata)) == asect) - return index; - } - break; - default: - break; - } - } - return 0; -} + unsigned int idx; -/* given a symbol, return the bfd index for that symbol. */ -static int -DEFUN (elf_symbol_from_bfd_symbol, (abfd, asym_ptr_ptr), - bfd * abfd AND - struct symbol_cache_entry **asym_ptr_ptr) -{ - struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr; - CONST char *name = asym_ptr->name; - int idx; - int symcount = bfd_get_symcount (abfd); - asymbol **syms = bfd_get_outsymbols (abfd); + if (asect->relocation) + return true; + if (asect->reloc_count == 0) + return true; + if (asect->flags & SEC_CONSTRUCTOR) + return true; - /* FIXME -- there has to be a better way than linear search. */ - for (idx = 0; idx < symcount; idx++) - { - if (syms[idx] == asym_ptr - || (name == syms[idx]->name && name) - || ((asym_ptr->flags & BSF_SECTION_SYM) - && (syms[idx]->flags & BSF_SECTION_SYM) - && asym_ptr->section == syms[idx]->section)) - break; - } + bfd_seek (abfd, asect->rel_filepos, SEEK_SET); + native_relocs = (Elf_External_Rela *) + bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rela)); + bfd_read ((PTR) native_relocs, + sizeof (Elf_External_Rela), asect->reloc_count, abfd); - if (idx >= symcount) + reloc_cache = (arelent *) + bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent))); + + if (!reloc_cache) { - /* badness... */ - fprintf (stderr, "bfd app err: can't find sym `%s' in symtab\n", - name); - abort (); + bfd_error = no_memory; + return false; } - idx = elf_symtab_map (abfd)[idx]; - -#if DEBUG & 4 - { - flagword flags = asym_ptr->flags; - - fprintf (stderr, - "elfsym<-bfdsym %.8lx `%s' sec=%s symnum=%d {", - (long) asym_ptr, asym_ptr->name, asym_ptr->section->name, idx); - - if (flags == BSF_NO_FLAGS) - fprintf (stderr, " none"); - - if (flags & BSF_LOCAL) - fprintf (stderr, " local"); - - if (flags & BSF_GLOBAL) - fprintf (stderr, " global"); - - if (flags & BSF_EXPORT) - fprintf (stderr, " export"); - - if (flags & BSF_DEBUGGING) - fprintf (stderr, " debugging"); - - if (flags & BSF_KEEP) - fprintf (stderr, " keep"); - if (flags & BSF_KEEP_G) - fprintf (stderr, " keep_g"); - - if (flags & BSF_WEAK) - fprintf (stderr, " weak"); - - if (flags & BSF_SECTION_SYM) - fprintf (stderr, " section_sym"); + for (idx = 0; idx < asect->reloc_count; idx++) + { +#ifdef RELOC_PROCESSING + Elf_Internal_Rela dst; + Elf_External_Rela *src; - if (flags & BSF_OLD_COMMON) - fprintf (stderr, " old_common"); + cache_ptr = reloc_cache + idx; + src = native_relocs + idx; + elf_swap_reloca_in (abfd, src, &dst); - if (flags & BSF_NOT_AT_END) - fprintf (stderr, " not_at_end"); + RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect); +#else + Elf_Internal_Rela dst; + Elf_External_Rela *src; - if (flags & BSF_CONSTRUCTOR) - fprintf (stderr, " constructor"); + cache_ptr = reloc_cache + idx; + src = native_relocs + idx; - if (flags & BSF_WARNING) - fprintf (stderr, " warning"); + elf_swap_reloca_in (abfd, src, &dst); - if (flags & BSF_INDIRECT) - fprintf (stderr, " indirect"); + 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; subtract 1 + because the first entry is NULL. */ + cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1; + { + /* Is it an ELF section symbol? If so, translate it into a + BFD section symbol. */ + asymbol *s = *(cache_ptr->sym_ptr_ptr); + if (s->flags & BSF_SECTION_SYM) + cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr; + } + cache_ptr->addend = dst.r_addend; - if (flags & BSF_FILE) - fprintf (stderr, " file"); + /* 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 + } - if (flags & BSF_FUNCTION) - fprintf (stderr, " function"); + asect->relocation = reloc_cache; + return true; +} - fputs (" }\n", stderr); - fflush (stderr); - } -#endif +#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); +} - return idx; +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 -DEFUN (elf_slurp_symbol_table, (abfd, symptrs), +DEFUN (elf_slurp_reloc_table, (abfd, asect, symbols), bfd * abfd AND - asymbol ** symptrs) /* Buffer for generated bfd symbols */ + sec_ptr asect AND + asymbol ** symbols) { - Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); - Elf_Internal_Shdr *hdr = i_shdrp + elf_onesymtab (abfd); - int symcount; /* Number of external ELF symbols */ - int i; - 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; + Elf_External_Rel *native_relocs; + arelent *reloc_cache; + arelent *cache_ptr; + Elf_Internal_Shdr *data_hdr; + ElfNAME (Off) data_off; + ElfNAME (Word) data_max; + char buf[4]; /* FIXME -- might be elf64 */ - /* 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 */ - if (bfd_get_outsymbols (abfd) != NULL) - { - return true; - } + unsigned int idx; - /* 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. + if (asect->relocation) + return true; + if (asect->reloc_count == 0) + return true; + if (asect->flags & SEC_CONSTRUCTOR) + return true; - 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. */ + bfd_seek (abfd, asect->rel_filepos, SEEK_SET); + native_relocs = (Elf_External_Rel *) + bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rel)); + bfd_read ((PTR) native_relocs, + sizeof (Elf_External_Rel), asect->reloc_count, abfd); - if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) + reloc_cache = (arelent *) + bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent))); + + if (!reloc_cache) { - bfd_error = system_call_error; + bfd_error = no_memory; return false; } - symcount = hdr->sh_size / sizeof (Elf_External_Sym); - symbase = (elf_symbol_type *) bfd_zalloc (abfd, symcount * sizeof (elf_symbol_type)); - sym = symbase; + /* 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; - /* Temporarily allocate room for the raw ELF symbols. */ - x_symp = (Elf_External_Sym *) bfd_xmalloc (symcount * sizeof (Elf_External_Sym)); +#if DEBUG & 2 + elf_debug_section ("data section", -1, data_hdr); +#endif - if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd) - != symcount * sizeof (Elf_External_Sym)) - { - free ((PTR) x_symp); - bfd_error = system_call_error; - return false; - } - /* Skip first symbol, which is a null dummy. */ - for (i = 1; i < symcount; i++) + for (idx = 0; idx < asect->reloc_count; idx++) { - elf_swap_symbol_in (abfd, x_symp + i, &i_sym); - memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym)); - memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym)); - sym->symbol.the_bfd = abfd; +#ifdef RELOC_PROCESSING + Elf_Internal_Rel dst; + Elf_External_Rel *src; - sym->symbol.name = elf_string_from_elf_section (abfd, hdr->sh_link, - i_sym.st_name); + cache_ptr = reloc_cache + idx; + src = native_relocs + idx; + elf_swap_reloc_in (abfd, src, &dst); - sym->symbol.value = i_sym.st_value; + RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect); +#else + Elf_Internal_Rel dst; + Elf_External_Rel *src; - 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) + cache_ptr = reloc_cache + idx; + src = native_relocs + idx; + + elf_swap_reloc_in (abfd, src, &dst); + + if (asect->flags & SEC_RELOC) { - sym->symbol.section = &bfd_abs_section; + /* relocatable, so the offset is off of the section */ + cache_ptr->address = dst.r_offset + asect->vma; } - else if (i_sym.st_shndx == SHN_COMMON) + else { - 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; + /* non-relocatable, so the offset a virtual address */ + cache_ptr->address = dst.r_offset; } - else if (i_sym.st_shndx == SHN_UNDEF) + /* ELF_R_SYM(dst.r_info) is the symbol table offset... + -1 is to skip the dummy symbol table entry */ + cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1; + BFD_ASSERT (dst.r_offset <= data_max); + if (bfd_seek (abfd, data_off + dst.r_offset, SEEK_SET) != 0 + || bfd_read ((PTR) buf, sizeof (buf), 1, abfd) != sizeof (buf)) { - sym->symbol.section = &bfd_und_section; + bfd_error = system_call_error; + return false; } - else - sym->symbol.section = &bfd_abs_section; - sym->symbol.value -= sym->symbol.section->vma; + cache_ptr->addend = (*abfd->xvec->bfd_getx_signed_32) ((bfd_byte *) buf); - 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 | BSF_EXPORT); - break; - case STB_WEAK: - sym->symbol.flags |= BSF_WEAK; - break; - } + /* 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 + } - 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; - } - /* Is this a definition of $global$? If so, keep it because it will be - needd if any relocations are performed. */ - if (!strcmp (sym->symbol.name, "$global$") - && sym->symbol.section != &bfd_und_section) - { - /* @@ Why is this referring to backend data and not a field of - abfd? FIXME */ - struct elf_backend_data *be_data = (struct elf_backend_data *) abfd->xvec->backend_data; + asect->relocation = reloc_cache; + return true; +} - be_data->global_sym = (PTR) sym; - } - sym++; +unsigned int +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) + elf_slurp_reloca_table (abfd, section, symbols); + else + elf_slurp_reloc_table (abfd, section, symbols); + + tblptr = section->relocation; + if (!tblptr) + return 0; + + for (; count++ < section->reloc_count;) + *relptr++ = tblptr++; + + *relptr = 0; + return section->reloc_count; +} + +unsigned int +DEFUN (elf_get_symtab, (abfd, alocation), + bfd * abfd AND + asymbol ** alocation) +{ + + if (!elf_slurp_symbol_table (abfd, alocation)) + return 0; + else + return bfd_get_symcount (abfd); +} + +asymbol * +DEFUN (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_error = no_memory; + return NULL; + } + else + { + newsym->symbol.the_bfd = abfd; + return &newsym->symbol; } +} - /* We rely on the zalloc to clear out the final symbol entry. */ +void +DEFUN (elf_get_symbol_info, (ignore_abfd, symbol, ret), + bfd * ignore_abfd AND + asymbol * symbol AND + symbol_info * ret) +{ + bfd_symbol_info (symbol, ret); +} - /* obj_raw_syms macro uses a cast... */ - elf_tdata (abfd)->raw_syms = (PTR) x_symp; +void +DEFUN (elf_print_symbol, (ignore_abfd, filep, symbol, how), + bfd * ignore_abfd AND + PTR filep AND + asymbol * symbol AND + 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; + } - bfd_get_symcount (abfd) = symcount = sym - symbase; +} - /* Fill in the user's symbol pointer vector if needed. */ - if (symptrs) +alent * +DEFUN (elf_get_lineno, (ignore_abfd, symbol), + bfd * ignore_abfd AND + asymbol * symbol) +{ + fprintf (stderr, "elf_get_lineno unimplemented\n"); + fflush (stderr); + BFD_FAIL (); + return NULL; +} + +boolean +DEFUN (elf_set_arch_mach, (abfd, arch, machine), + bfd * abfd AND + enum bfd_architecture arch AND + unsigned long machine) +{ + /* Allow any architecture to be supported by the elf backend */ + switch (arch) { - sym = symbase; - while (symcount-- > 0) - { - *symptrs++ = &sym->symbol; - sym++; - } - *symptrs = 0; /* Final null pointer */ + 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) */ + return bfd_default_set_arch_mach (abfd, arch, machine); + default: + return false; } +} - return true; +boolean +DEFUN (elf_find_nearest_line, (abfd, + section, + symbols, + offset, + filename_ptr, + functionname_ptr, + line_ptr), + bfd * abfd AND + asection * section AND + asymbol ** symbols AND + bfd_vma offset AND + CONST char **filename_ptr AND + CONST char **functionname_ptr AND + unsigned int *line_ptr) +{ + return false; } -/* 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. */ +int +DEFUN (elf_sizeof_headers, (abfd, reloc), + bfd * abfd AND + boolean reloc) +{ + fprintf (stderr, "elf_sizeof_headers unimplemented\n"); + fflush (stderr); + BFD_FAIL (); + return 0; +} -unsigned int -DEFUN (elf_get_symtab_upper_bound, (abfd), bfd * abfd) +boolean +DEFUN (elf_set_section_contents, (abfd, section, location, offset, count), + bfd * abfd AND + sec_ptr section AND + PTR location AND + file_ptr offset AND + bfd_size_type count) { - unsigned int symcount; - unsigned int symtab_size = 0; - Elf_Internal_Shdr *i_shdrp; Elf_Internal_Shdr *hdr; - i_shdrp = elf_elfsections (abfd); - if (i_shdrp != NULL) + if (abfd->output_has_begun == false) /* set by bfd.c handler? */ { - hdr = i_shdrp + elf_onesymtab (abfd); - symcount = hdr->sh_size / sizeof (Elf_External_Sym); - symtab_size = (symcount - 1 + 1) * (sizeof (asymbol)); + /* do setup calculations (FIXME) */ + prep_headers (abfd); + elf_compute_section_file_positions (abfd); + abfd->output_has_begun = true; } - return symtab_size; -} -/* - This function return the number of bytes required to store the - relocation information associated with section <> - attached to bfd <> + hdr = &elf_section_data(section)->this_hdr; -*/ -unsigned int -elf_get_reloc_upper_bound (abfd, asect) - bfd *abfd; - sec_ptr asect; + 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 +DEFUN (elf_no_info_to_howto, (abfd, cache_ptr, dst), + bfd * abfd AND + arelent * cache_ptr AND + Elf_Internal_Rela * dst) { - if (asect->flags & SEC_RELOC) - { - /* either rel or rela */ - return asect->_raw_size; - } - else - return 0; + fprintf (stderr, "elf RELA relocation support for target machine unimplemented\n"); + fflush (stderr); + BFD_FAIL (); } -static boolean -DEFUN (elf_slurp_reloca_table, (abfd, asect, symbols), +void +DEFUN (elf_no_info_to_howto_rel, (abfd, cache_ptr, dst), bfd * abfd AND - sec_ptr asect AND - asymbol ** symbols) + arelent * cache_ptr AND + Elf_Internal_Rel * dst) { - Elf_External_Rela *native_relocs; - arelent *reloc_cache; - arelent *cache_ptr; + fprintf (stderr, "elf REL relocation support for target machine unimplemented\n"); + fflush (stderr); + BFD_FAIL (); +} - unsigned int idx; + +/* Core file support */ - if (asect->relocation) - return true; - if (asect->reloc_count == 0) - return true; - if (asect->flags & SEC_CONSTRUCTOR) - return true; +#ifdef HAVE_PROCFS /* Some core file support requires host /proc files */ +#include +#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 - bfd_seek (abfd, asect->rel_filepos, SEEK_SET); - native_relocs = (Elf_External_Rela *) - bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rela)); - bfd_read ((PTR) native_relocs, - sizeof (Elf_External_Rela), asect->reloc_count, abfd); +#ifdef HAVE_PROCFS - reloc_cache = (arelent *) - bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent))); +static void +DEFUN (bfd_prstatus, (abfd, descdata, descsz, filepos), + bfd * abfd AND + char *descdata AND + int descsz AND + long filepos) +{ + asection *newsect; + prstatus_t *status = (prstatus_t *) 0; - if (!reloc_cache) + if (descsz == sizeof (prstatus_t)) { - bfd_error = no_memory; - return false; + newsect = bfd_make_section (abfd, ".reg"); + newsect->_raw_size = sizeof (status->pr_reg); + newsect->filepos = filepos + (long) &status->pr_reg; + newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS; + newsect->alignment_power = 2; + if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL) + { + memcpy (core_prstatus (abfd), descdata, descsz); + } } +} - for (idx = 0; idx < asect->reloc_count; idx++) - { -#ifdef RELOC_PROCESSING - Elf_Internal_Rela dst; - Elf_External_Rela *src; - - cache_ptr = reloc_cache + idx; - src = native_relocs + idx; - elf_swap_reloca_in (abfd, src, &dst); - - RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect); -#else - Elf_Internal_Rela dst; - Elf_External_Rela *src; - - cache_ptr = reloc_cache + idx; - src = native_relocs + idx; +/* Stash a copy of the prpsinfo structure away for future use. */ - elf_swap_reloca_in (abfd, src, &dst); +static void +DEFUN (bfd_prpsinfo, (abfd, descdata, descsz, filepos), + bfd * abfd AND + char *descdata AND + int descsz AND + long filepos) +{ + asection *newsect; - if (asect->flags & SEC_RELOC) - { - /* relocatable, so the offset is off of the section */ - cache_ptr->address = dst.r_offset + asect->vma; - } - else + if (descsz == sizeof (prpsinfo_t)) + { + if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) != NULL) { - /* non-relocatable, so the offset a virtual address */ - cache_ptr->address = dst.r_offset; + memcpy (core_prpsinfo (abfd), descdata, descsz); } - /* ELF_R_SYM(dst.r_info) is the symbol table offset; subtract 1 - because the first entry is NULL. */ - cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1; - { - /* Is it an ELF section symbol? If so, translate it into a - BFD section symbol. */ - asymbol *s = *(cache_ptr->sym_ptr_ptr); - if (s->flags & BSF_SECTION_SYM) - cache_ptr->sym_ptr_ptr = s->section->symbol_ptr_ptr; - } - 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; +DEFUN (bfd_fpregset, (abfd, descdata, descsz, filepos), + bfd * abfd AND + char *descdata AND + int descsz AND + long filepos) { - fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num, str, (long) hdr); - fprintf (stderr, "sh_name = %ld\n", (long) hdr->sh_name); - fprintf (stderr, "sh_type = %ld\n", (long) hdr->sh_type); - fprintf (stderr, "sh_flags = %ld\n", (long) hdr->sh_flags); - fprintf (stderr, "sh_addr = %ld\n", (long) hdr->sh_addr); - fprintf (stderr, "sh_offset = %ld\n", (long) hdr->sh_offset); - fprintf (stderr, "sh_size = %ld\n", (long) hdr->sh_size); - fprintf (stderr, "sh_link = %ld\n", (long) hdr->sh_link); - fprintf (stderr, "sh_info = %ld\n", (long) hdr->sh_info); - fprintf (stderr, "sh_addralign = %ld\n", (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); -} + asection *newsect; -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); + newsect = bfd_make_section (abfd, ".reg2"); + newsect->_raw_size = descsz; + newsect->filepos = filepos; + newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS; + newsect->alignment_power = 2; } -#endif -static boolean -DEFUN (elf_slurp_reloc_table, (abfd, asect, symbols), - bfd * abfd AND - sec_ptr asect AND - asymbol ** symbols) +#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 * +DEFUN (elf_core_file_failing_command, (abfd), + bfd * abfd) { - Elf_External_Rel *native_relocs; - arelent *reloc_cache; - arelent *cache_ptr; - Elf_Internal_Shdr *i_shdrp; - Elf_Internal_Shdr *data_hdr; - ElfNAME (Off) data_off; - ElfNAME (Word) data_max; - char buf[4]; /* FIXME -- might be elf64 */ +#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; +} - unsigned int idx; +/* 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. + */ - if (asect->relocation) - return true; - if (asect->reloc_count == 0) - return true; - if (asect->flags & SEC_CONSTRUCTOR) - return true; +int +DEFUN (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; +} - bfd_seek (abfd, asect->rel_filepos, SEEK_SET); - native_relocs = (Elf_External_Rel *) - bfd_alloc (abfd, asect->reloc_count * sizeof (Elf_External_Rel)); - bfd_read ((PTR) native_relocs, - sizeof (Elf_External_Rel), asect->reloc_count, abfd); +/* 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. + */ - reloc_cache = (arelent *) - bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent))); +boolean +DEFUN (elf_core_file_matches_executable_p, (core_bfd, exec_bfd), + bfd * core_bfd AND + bfd * exec_bfd) +{ +#ifdef HAVE_PROCFS + char *corename; + char *execname; +#endif - if (!reloc_cache) + /* First, xvecs must match since both are ELF files for the same target. */ + + if (core_bfd->xvec != exec_bfd->xvec) { - bfd_error = no_memory; + bfd_error = system_call_error; return false; } - /* Get the offset of the start of the segment we are relocating to read in - the implicit addend. */ - i_shdrp = elf_elfsections (abfd); - data_hdr = i_shdrp + elf_section_from_bfd_section (abfd, asect); - data_off = data_hdr->sh_offset; - data_max = data_hdr->sh_size - sizeof (buf) + 1; +#ifdef HAVE_PROCFS -#if DEBUG & 2 - elf_debug_section ("data section", data_hdr - i_shdrp, data_hdr); -#endif + /* If no prpsinfo, just return true. Otherwise, grab the last component + of the exec'd pathname from the prpsinfo. */ - for (idx = 0; idx < asect->reloc_count; idx++) + if (core_prpsinfo (core_bfd)) { -#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; + corename = (((struct prpsinfo *) core_prpsinfo (core_bfd))->pr_fname); + } + else + { + return true; + } - cache_ptr = reloc_cache + idx; - src = native_relocs + idx; + /* Find the last component of the executable pathname. */ - elf_swap_reloc_in (abfd, src, &dst); + if ((execname = strrchr (exec_bfd->filename, '/')) != NULL) + { + execname++; + } + else + { + execname = (char *) exec_bfd->filename; + } - 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... - -1 is to skip the dummy symbol table entry */ - cache_ptr->sym_ptr_ptr = symbols + ELF_R_SYM (dst.r_info) - 1; - BFD_ASSERT (dst.r_offset <= data_max); - if (bfd_seek (abfd, data_off + dst.r_offset, SEEK_SET) != 0 - || bfd_read ((PTR) buf, sizeof (buf), 1, abfd) != sizeof (buf)) - { - bfd_error = system_call_error; - return false; - } + /* See if they match */ - cache_ptr->addend = (*abfd->xvec->bfd_getx_signed_32) ((bfd_byte *) buf); + return strcmp (execname, corename) ? false : true; - /* 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 - } +#else - asect->relocation = reloc_cache; return true; -} -unsigned int -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; +#endif /* HAVE_PROCFS */ +} - /* snarfed from coffcode.h */ - if (use_rela_p) - elf_slurp_reloca_table (abfd, section, symbols); - else - elf_slurp_reloc_table (abfd, section, symbols); +/* 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. - tblptr = section->relocation; - if (!tblptr) - return 0; + 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. - for (; count++ < section->reloc_count;) - *relptr++ = tblptr++; + 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. - *relptr = 0; - return section->reloc_count; -} + */ -unsigned int -DEFUN (elf_get_symtab, (abfd, alocation), +static boolean +DEFUN (elf_corefile_note, (abfd, hdr), bfd * abfd AND - asymbol ** alocation) + 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 *) bfd_xmalloc (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 */ + bfd_prstatus (abfd, descdata, i_note.descsz, filepos); + sectname = ".prstatus"; + break; + case NT_FPREGSET: + /* process descdata as fpregset info */ + bfd_fpregset (abfd, descdata, i_note.descsz, filepos); + sectname = ".fpregset"; + break; + case NT_PRPSINFO: + /* process descdata as prpsinfo */ + bfd_prpsinfo (abfd, descdata, i_note.descsz, filepos); + sectname = ".prpsinfo"; + break; + default: + /* Unknown descriptor, just ignore it. */ + sectname = NULL; + break; + } + if (sectname != NULL) + { + newsect = bfd_make_section (abfd, sectname); + 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); + } + return true; - if (!elf_slurp_symbol_table (abfd, alocation)) - return 0; - else - return bfd_get_symcount (abfd); } -asymbol * -DEFUN (elf_make_empty_symbol, (abfd), - bfd * abfd) +/* 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). + + */ + +bfd_target * +DEFUN (elf_core_file_p, (abfd), bfd * abfd) { - elf_symbol_type *newsym; + 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; - newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (elf_symbol_type)); - if (!newsym) + /* Read in the ELF header in external format. */ + + if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) { - bfd_error = no_memory; + bfd_error = system_call_error; return NULL; } - else + + /* 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) { - newsym->symbol.the_bfd = abfd; - return &newsym->symbol; + wrong: + bfd_error = wrong_format; + return NULL; } -} -void -DEFUN (elf_get_symbol_info, (ignore_abfd, symbol, ret), - bfd * ignore_abfd AND - asymbol * symbol AND - symbol_info * ret) -{ - bfd_symbol_info (symbol, ret); -} + /* FIXME, Check EI_VERSION here ! */ -void -DEFUN (elf_print_symbol, (ignore_abfd, filep, symbol, how), - bfd * ignore_abfd AND - PTR filep AND - asymbol * symbol AND - bfd_print_symbol_type how) -{ - FILE *file = (FILE *) filep; - switch (how) + { +#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 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); + case ELFDATA2MSB: /* Big-endian */ + if (abfd->xvec->byteorder_big_p == false) + goto wrong; 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); - } + 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; } -} - -alent * -DEFUN (elf_get_lineno, (ignore_abfd, symbol), - bfd * ignore_abfd AND - asymbol * symbol) -{ - fprintf (stderr, "elf_get_lineno unimplemented\n"); - fflush (stderr); - BFD_FAIL (); - return NULL; -} + /* Allocate an instance of the elf_obj_tdata structure and hook it up to + the tdata pointer in the bfd. */ -boolean -DEFUN (elf_set_arch_mach, (abfd, arch, machine), - bfd * abfd AND - enum bfd_architecture arch AND - unsigned long machine) -{ - /* Allow any architecture to be supported by the elf backend */ - switch (arch) + elf_tdata (abfd) = + (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); + if (elf_tdata (abfd) == NULL) { - 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) */ - return bfd_default_set_arch_mach (abfd, arch, machine); - default: - return false; + bfd_error = no_memory; + return NULL; } -} -boolean -DEFUN (elf_find_nearest_line, (abfd, - section, - symbols, - offset, - filename_ptr, - functionname_ptr, - line_ptr), - bfd * abfd AND - asection * section AND - asymbol ** symbols AND - bfd_vma offset AND - CONST char **filename_ptr AND - CONST char **functionname_ptr AND - unsigned int *line_ptr) -{ - return false; -} + /* FIXME, `wrong' returns from this point onward, leak memory. */ -int -DEFUN (elf_sizeof_headers, (abfd, reloc), - bfd * abfd AND - boolean reloc) -{ - fprintf (stderr, "elf_sizeof_headers unimplemented\n"); - fflush (stderr); - BFD_FAIL (); - return 0; -} + /* 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 -boolean -DEFUN (elf_set_section_contents, (abfd, section, location, offset, count), - bfd * abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) -{ - int dest_sect; + /* 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; - if (abfd->output_has_begun == false) /* set by bfd.c handler? */ + /* 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) { - /* do setup calculations (FIXME) */ - elf_compute_section_file_positions (abfd); - abfd->output_has_begun = true; + bfd_error = no_memory; + return NULL; + } + if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1) + { + bfd_error = system_call_error; + 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)) + { + bfd_error = system_call_error; + return NULL; + } + elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex); } - dest_sect = elf_section_from_bfd_section (abfd, section); - if (!dest_sect) - return false; - - if (bfd_seek (abfd, elf_elfsections (abfd)[dest_sect].sh_offset + offset, SEEK_SET) == -1) - return false; - if (bfd_write (location, 1, count, abfd) != count) - return false; - return true; -} - -void -DEFUN (elf_no_info_to_howto, (abfd, cache_ptr, dst), - bfd * abfd AND - arelent * cache_ptr AND - Elf_Internal_Rela * dst) -{ - fprintf (stderr, "elf RELA relocation support for target machine unimplemented\n"); - fflush (stderr); - BFD_FAIL (); -} + /* Once all of the program headers have been read and converted, we + can start processing them. */ -void -DEFUN (elf_no_info_to_howto_rel, (abfd, cache_ptr, dst), - bfd * abfd AND - arelent * cache_ptr AND - Elf_Internal_Rel * dst) -{ - fprintf (stderr, "elf REL relocation support for target machine unimplemented\n"); - fflush (stderr); - BFD_FAIL (); -} + 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) + { + elf_corefile_note (abfd, i_phdrp + phindex); + } + } -boolean -DEFUN (elf_get_sect_thunk, (abfd, est), - bfd * abfd AND - elf_sect_thunk * est) -{ - if (est == (elf_sect_thunk *) NULL) - return false; + /* Remember the entry point specified in the ELF file header. */ - est->i_ehdr = elf_elfheader (abfd); - est->i_shdrp = elf_elfsections (abfd); - est->shstrtab = elf_shstrtab (abfd); - est->symtab_section = elf_onesymtab (abfd); /* filled in by elf_fake */ + bfd_get_start_address (abfd) = i_ehdrp->e_entry; - return true; + return abfd->xvec; } diff --git a/bfd/libelf.h b/bfd/libelf.h index 532513a91cd..9936c23fb65 100644 --- a/bfd/libelf.h +++ b/bfd/libelf.h @@ -88,17 +88,6 @@ typedef struct Elf64_External_Sym native_elf_sym; } elf64_symbol_type; -/* Lacking nested functions and nested types, set up for mapping over - BFD sections to produce ELF sections. */ -typedef struct -{ - Elf_Internal_Ehdr * i_ehdr; - Elf_Internal_Shdr * i_shdrp; - struct strtab *shstrtab; - int symtab_section; -} -elf_sect_thunk; - struct elf_backend_data { int use_rela_p; @@ -108,6 +97,7 @@ struct elf_backend_data Elf_Internal_Rela *)); void (*elf_info_to_howto_rel) PARAMS ((bfd *, arelent *, Elf_Internal_Rel *)); + void (*write_relocs) PARAMS ((bfd *, asection *, PTR)); /* @@ I really don't think this should be here. I don't know what global_sym is supposed to be used for, but I doubt it's something @@ -119,13 +109,95 @@ struct elf_backend_data PTR global_sym; }; -extern boolean elf_get_sect_thunk PARAMS ((bfd *, elf_sect_thunk *)); +struct bfd_elf_arch_map { + enum bfd_architecture bfd_arch; + int elf_arch; +}; + +extern const struct bfd_elf_arch_map bfd_elf_arch_map[]; +extern const int bfd_elf_arch_map_size; + +struct bfd_elf_section_data { + Elf_Internal_Shdr this_hdr; + Elf_Internal_Shdr rel_hdr; + int this_idx, rel_idx; +#if 0 + Elf_Internal_Shdr str_hdr; + int str_idx; +#endif +}; +#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd) +#define shdr_name(abfd,shdr) (elf_shstrtab (abfd)->tab + (shdr)->sh_name) + +#define get_elf_backend_data(abfd) \ + ((struct elf_backend_data *) (abfd)->xvec->backend_data) + +struct strtab +{ + char *tab; + int nentries; + int length; +}; + +/* Some private data is stashed away for future use using the tdata pointer + in the bfd structure. */ + +struct elf_obj_tdata +{ + Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */ + Elf_Internal_Shdr **elf_sect_ptr; + struct strtab *strtab_ptr; + int num_locals; + int num_globals; + int *symtab_map; + PTR raw_syms; /* Elf_External_Sym* */ + Elf_Internal_Sym *internal_syms; + PTR symbols; /* elf_symbol_type */ +/* struct strtab *shstrtab;*/ + Elf_Internal_Shdr symtab_hdr; + Elf_Internal_Shdr shstrtab_hdr; + Elf_Internal_Shdr strtab_hdr; + int symtab_section, shstrtab_section, strtab_section; + file_ptr next_file_pos; + void *prstatus; /* The raw /proc prstatus structure */ + void *prpsinfo; /* The raw /proc prpsinfo structure */ +}; + +#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) +#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header) +#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) +#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr) +#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) +#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals) +#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals) +#define elf_symtab_map(bfd) (elf_tdata(bfd) -> symtab_map) +#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo) +#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus) +#define obj_symbols(bfd) ((elf_symbol_type*)(elf_tdata(bfd) -> symbols)) +#define obj_raw_syms(bfd) ((Elf_External_Sym*)(elf_tdata(bfd) -> raw_syms)) +#define obj_internal_syms(bfd) (elf_tdata(bfd) -> internal_syms) + +extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned)); +extern char * elf_get_str_section PARAMS ((bfd *, unsigned)); + +#define bfd_elf32_mkobject bfd_elf_mkobject +#define bfd_elf64_mkobject bfd_elf_mkobject +#define elf_mkobject bfd_elf_mkobject + extern unsigned long elf_hash PARAMS ((CONST unsigned char *)); -extern bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); -extern bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *)); +extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *, + arelent *, + asymbol *, + PTR, + asection *, + bfd *)); extern boolean bfd_elf_mkobject PARAMS ((bfd *)); extern boolean bfd_elf32_write_object_contents PARAMS ((bfd *)); +extern boolean bfd_elf64_write_object_contents PARAMS ((bfd *)); + +extern bfd_target *bfd_elf32_object_p PARAMS ((bfd *)); +extern bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *)); extern char *bfd_elf32_core_file_failing_command PARAMS ((bfd *)); extern int bfd_elf32_core_file_failing_signal PARAMS ((bfd *)); extern boolean bfd_elf32_core_file_matches_executable_p PARAMS ((bfd *, @@ -154,6 +226,7 @@ extern boolean bfd_elf32_find_nearest_line PARAMS ((bfd *, asection *, CONST char **, unsigned int *)); extern int bfd_elf32_sizeof_headers PARAMS ((bfd *, boolean)); +extern void bfd_elf32__write_relocs PARAMS ((bfd *, asection *, PTR)); extern boolean bfd_elf32_new_section_hook PARAMS ((bfd *, asection *)); /* If the target doesn't have reloc handling written yet: */ @@ -162,7 +235,6 @@ extern void bfd_elf32_no_info_to_howto PARAMS ((bfd *, arelent *, extern bfd_target *bfd_elf64_object_p PARAMS ((bfd *)); extern bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *)); -extern boolean bfd_elf64_write_object_contents PARAMS ((bfd *)); extern char *bfd_elf64_core_file_failing_command PARAMS ((bfd *)); extern int bfd_elf64_core_file_failing_signal PARAMS ((bfd *)); extern boolean bfd_elf64_core_file_matches_executable_p PARAMS ((bfd *, @@ -191,61 +263,11 @@ extern boolean bfd_elf64_find_nearest_line PARAMS ((bfd *, asection *, CONST char **, unsigned int *)); extern int bfd_elf64_sizeof_headers PARAMS ((bfd *, boolean)); +extern void bfd_elf64__write_relocs PARAMS ((bfd *, asection *, PTR)); extern boolean bfd_elf64_new_section_hook PARAMS ((bfd *, asection *)); /* If the target doesn't have reloc handling written yet: */ extern void bfd_elf64_no_info_to_howto PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *)); -#define get_elf_backend_data(abfd) \ - ((struct elf_backend_data *) (abfd)->xvec->backend_data) - -struct strtab -{ - char *tab; - int nentries; - int length; -}; - -/* Some private data is stashed away for future use using the tdata pointer - in the bfd structure. */ - -struct elf_obj_tdata -{ - Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */ - Elf_Internal_Shdr *elf_sect_ptr; - struct strtab *strtab_ptr; - int symtab_section; - int num_locals; - int num_globals; - int *symtab_map; - void *prstatus; /* The raw /proc prstatus structure */ - void *prpsinfo; /* The raw /proc prpsinfo structure */ - PTR raw_syms; /* Elf_External_Sym* */ - Elf_Internal_Sym *internal_syms; - PTR symbols; /* elf_symbol_type */ - elf_sect_thunk thunk; -}; - -#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) -#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header) -#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) -#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr) -#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) -#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals) -#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals) -#define elf_symtab_map(bfd) (elf_tdata(bfd) -> symtab_map) -#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo) -#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus) -#define obj_symbols(bfd) ((elf_symbol_type*)(elf_tdata(bfd) -> symbols)) -#define obj_raw_syms(bfd) ((Elf_External_Sym*)(elf_tdata(bfd) -> raw_syms)) -#define obj_internal_syms(bfd) (elf_tdata(bfd) -> internal_syms) - -extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned)); -extern char * elf_get_str_section PARAMS ((bfd *, unsigned)); - -#define bfd_elf32_mkobject bfd_elf_mkobject -#define bfd_elf64_mkobject bfd_elf_mkobject -#define elf_mkobject bfd_elf_mkobject - #endif /* _LIBELF_H_ */ -- 2.30.2