diff options
author | Ken Raeburn <raeburn@cygnus> | 1993-07-19 19:12:59 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@cygnus> | 1993-07-19 19:12:59 +0000 |
commit | 32090b8e4f645bb5c80e8ad9c38cdd21d5b7b7e0 (patch) | |
tree | 525fd70fd35bb281b1b49468ae28baa7a2b613d0 /bfd/elfcode.h | |
parent | da374d80433e0ed482abf11deb8e4c9fbd729b2c (diff) | |
download | gdb-32090b8e4f645bb5c80e8ad9c38cdd21d5b7b7e0.zip gdb-32090b8e4f645bb5c80e8ad9c38cdd21d5b7b7e0.tar.gz gdb-32090b8e4f645bb5c80e8ad9c38cdd21d5b7b7e0.tar.bz2 |
* 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.
Diffstat (limited to 'bfd/elfcode.h')
-rw-r--r-- | bfd/elfcode.h | 2414 |
1 files changed, 1248 insertions, 1166 deletions
diff --git a/bfd/elfcode.h b/bfd/elfcode.h index a3119d1..908e010 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -56,12 +56,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ */ +#include <assert.h> #include <string.h> /* 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 <sys/procfs.h> -#else -#define bfd_prstatus(abfd, descdata, descsz, filepos) /* Define away */ -#define bfd_fpregset(abfd, descdata, descsz, filepos) /* Define away */ -#define bfd_prpsinfo(abfd, descdata, descsz, filepos) /* Define away */ +#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. */ + -static INLINE char * -DEFUN (elf_string_from_elf_strtab, (abfd, strindex), - bfd *abfd AND - int strindex) +/* String table creation/manipulation routines */ + +static struct strtab * +DEFUN (bfd_new_strtab, (abfd), + bfd * abfd) { - return elf_string_from_elf_section (abfd, elf_elfheader (abfd)->e_shstrndx, - strindex); + 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; +} + + +/* 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,132 +678,12 @@ DEFUN (elf_new_section_hook, (abfd, sec), bfd *abfd AND asection *sec) { -/* sec->symbol->name = "";*/ + struct bfd_elf_section_data *sdata; + sec->used_by_bfd = sdata = bfd_alloc (abfd, sizeof (*sdata)); + memset (sdata, 0, sizeof (*sdata)); 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; - - return true; -} -#endif - /* Create a new bfd section from an ELF program header. Since program segments have no names, we generate a synthetic name @@ -766,270 +765,6 @@ DEFUN (bfd_section_from_phdr, (abfd, hdr, index), return true; } -#ifdef HAVE_PROCFS - -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 (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) -{ - asection *newsect; - - if (descsz == sizeof (prpsinfo_t)) - { - if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) != NULL) - { - memcpy (core_prpsinfo (abfd), descdata, descsz); - } - } -} - -static void -DEFUN (bfd_fpregset, (abfd, descdata, descsz, filepos), - bfd * abfd AND - char *descdata AND - int descsz AND - long filepos) -{ - asection *newsect; - - 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 /* 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) -{ -#ifdef HAVE_PROCFS - if (core_prpsinfo (abfd)) - { - prpsinfo_t *p = core_prpsinfo (abfd); - char *scan = p->pr_psargs; - while (*scan++) - {; - } - scan -= 2; - if ((scan > p->pr_psargs) && (*scan == ' ')) - { - *scan = '\000'; - } - return p->pr_psargs; - } -#endif - return NULL; -} - -/* Return the number of the signal that caused the core dump. Presumably, - since we have a core file, we got a signal of some kind, so don't bother - checking the other process status fields, just return the signal number. - */ - -int -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; -} - -/* Check to see if the core file could reasonably be expected to have - come for the current executable file. Note that by default we return - true unless we find something that indicates that there might be a - problem. - */ - -boolean -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 - - /* First, xvecs must match since both are ELF files for the same target. */ - - if (core_bfd->xvec != exec_bfd->xvec) - { - bfd_error = system_call_error; - return false; - } - -#ifdef HAVE_PROCFS - - /* If no prpsinfo, just return true. Otherwise, grab the last component - of the exec'd pathname from the prpsinfo. */ - - if (core_prpsinfo (core_bfd)) - { - corename = (((struct prpsinfo *) core_prpsinfo (core_bfd))->pr_fname); - } - else - { - return true; - } - - /* Find the last component of the executable pathname. */ - - if ((execname = strrchr (exec_bfd->filename, '/')) != NULL) - { - execname++; - } - else - { - execname = (char *) exec_bfd->filename; - } - - /* See if they match */ - - return strcmp (execname, corename) ? false : true; - -#else - - return true; - -#endif /* HAVE_PROCFS */ -} - -/* ELF core files contain a segment of type PT_NOTE, that holds much of - the information that would normally be available from the /proc interface - for the process, at the time the process dumped core. Currently this - includes copies of the prstatus, prpsinfo, and fpregset structures. - - Since these structures are potentially machine dependent in size and - ordering, bfd provides two levels of support for them. The first level, - available on all machines since it does not require that the host - have /proc support or the relevant include files, is to create a bfd - section for each of the prstatus, prpsinfo, and fpregset structures, - without any interpretation of their contents. With just this support, - the bfd client will have to interpret the structures itself. Even with - /proc support, it might want these full structures for it's own reasons. - - In the second level of support, where HAVE_PROCFS is defined, bfd will - pick apart the structures to gather some additional information that - clients may want, such as the general register set, the name of the - exec'ed file and its arguments, the signal (if any) that caused the - core dump, etc. - - */ - -static boolean -DEFUN (elf_corefile_note, (abfd, hdr), - bfd * abfd AND - 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; - -} - - /* Begin processing a given object. First we validate the file by reading in the ELF header and checking @@ -1079,16 +814,8 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) if (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) goto wrong; - { -#if ARCH_SIZE == 64 - unsigned int class = ELFCLASS64; -#endif -#if ARCH_SIZE == 32 - unsigned int class = ELFCLASS32; -#endif - if (x_ehdr.e_ident[EI_CLASS] != class) - goto wrong; - } + if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS) + goto wrong; /* Switch xvec to match the specified byte order. */ switch (x_ehdr.e_ident[EI_DATA]) @@ -1138,63 +865,31 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) otherwise be distinguishable. */ 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; - /* 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 */ + /* 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; - 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; - } + 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, @@ -1206,7 +901,8 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) goto wrong; i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum); - if (!i_shdrp) + elf_elfsections (abfd) = bfd_alloc (abfd, sizeof (i_shdrp) * i_ehdrp->e_shnum); + if (!i_shdrp || !elf_elfsections(abfd)) { bfd_error = no_memory; return NULL; @@ -1225,9 +921,33 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) return NULL; } elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); + elf_elfsections(abfd)[shindex] = i_shdrp + shindex; + } + if (i_ehdrp->e_shstrndx) + { + bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx); } - elf_elfsections (abfd) = i_shdrp; +#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 /* Read in the string table containing the names of the sections. We will need the base pointer to this table later. */ @@ -1259,170 +979,84 @@ DEFUN (elf_object_p, (abfd), bfd * abfd) return abfd->xvec; } -/* - 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; - - if (symbol->the_bfd->tdata.elf_obj_data == (struct elf_obj_tdata *) NULL) - return 0; - - return (elf_symbol_type *) symbol; -} - -/* 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). + +/* ELF .o/exec file writing */ - */ +/* Create a new ELF section from a bfd section. */ -bfd_target * -DEFUN (elf_core_file_p, (abfd), bfd * abfd) +#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) { - 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; - - /* Read in the ELF header in external format. */ - - 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 - program header table (FIXME: See comments re segments at top of this - file). */ - - if (elf_file_p (&x_ehdr) == false) - { - wrong: - bfd_error = wrong_format; - return NULL; - } - - /* FIXME, Check EI_VERSION here ! */ - - { -#if ARCH_SIZE == 32 - int desired_address_size = ELFCLASS32; -#endif -#if ARCH_SIZE == 64 - int desired_address_size = ELFCLASS64; -#endif - - if (x_ehdr.e_ident[EI_CLASS] != desired_address_size) - goto wrong; - } + asection *sect; + int ndx; - /* Switch xvec to match the specified byte order. */ - switch (x_ehdr.e_ident[EI_DATA]) + sect = abfd->sections; + for (ndx = indx; --ndx;) { - 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; + 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; - /* 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) + hdr[indx].sh_type = 0; + if (sect->flags & SEC_RELOC) { - bfd_error = no_memory; - return NULL; + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; + hdr[indx].sh_type = use_rela_p ? SHT_RELA : SHT_REL; } - /* FIXME, `wrong' returns from this point onward, leak memory. */ - - /* Now that we know the byte order, swap in the rest of the header */ - i_ehdrp = elf_elfheader (abfd); - elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp); -#if DEBUG & 1 - elf_debug_file (i_ehdrp); -#endif - - /* If there is no program header, or the type is not a core file, then - we are hosed. */ - if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE) - goto wrong; - - /* Allocate space for a copy of the program header table in - internal form, seek to the program header table in the file, - read it in, and convert it to internal form. As a simple sanity - check, verify that the what BFD thinks is the size of each program - header table entry actually matches the size recorded in the file. */ - - if (i_ehdrp->e_phentsize != sizeof (x_phdr)) - goto wrong; - i_phdrp = (Elf_Internal_Phdr *) - bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum); - if (!i_phdrp) - { - bfd_error = no_memory; - return NULL; - } - if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1) + if (sect->flags & SEC_HAS_CONTENTS) { - bfd_error = system_call_error; - return NULL; + hdr[indx].sh_offset = sect->filepos; + hdr[indx].sh_size = sect->_raw_size; } - for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++) + if (sect->flags & SEC_ALLOC) { - if (bfd_read ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd) - != sizeof (x_phdr)) + hdr[indx].sh_flags |= SHF_ALLOC; + if (sect->flags & SEC_LOAD) { - bfd_error = system_call_error; - return NULL; + /* do something with sh_type ? */ } - elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex); } + if (!(sect->flags & SEC_READONLY)) + hdr[indx].sh_flags |= SHF_WRITE; - /* Once all of the program headers have been read and converted, we - can start processing them. */ + if (sect->flags & SEC_CODE) + hdr[indx].sh_flags |= SHF_EXECINSTR; - 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); - } - } + return true; +} +#endif - /* Remember the entry point specified in the ELF file header. */ +/* + 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; - bfd_get_start_address (abfd) = i_ehdrp->e_entry; + if (symbol->the_bfd->tdata.elf_obj_data == (struct elf_obj_tdata *) NULL) + return 0; - return abfd->xvec; + return (elf_symbol_type *) symbol; } /* @@ -1433,123 +1067,156 @@ DEFUN (elf_core_file_p, (abfd), bfd * abfd) */ -#if 0 /* not used */ -static int -elf_idx_of_sym (abfd, sym) - bfd *abfd; - asymbol *sym; -{ - int i; - for (i = 0; i < abfd->symcount; 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; - } - } - return STN_UNDEF; -} -#endif - static void DEFUN (elf_make_sections, (abfd, asect, obj), bfd * abfd AND asection * asect AND PTR obj) { - 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; int idx; Elf_Internal_Shdr *this_hdr; - this_section = elf_section_from_bfd_section (abfd, asect); - this_hdr = &thunk->i_shdrp[this_section]; + this_hdr = &elf_section_data (asect)->this_hdr; this_hdr->sh_addr = asect->vma; this_hdr->sh_size = asect->_raw_size; /* contents already set by elf_set_section_contents */ - if (asect->flags & SEC_RELOC) + if ((asect->flags & SEC_RELOC) +#if 0 + /* The flags are sometimes inconsistent. */ + && asect->reloc_count > 0 +#endif + ) { /* 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; - symtab_hdr = &thunk->i_shdrp[thunk->symtab_section]; - - 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; + rela_hdr = &elf_section_data (asect)->rel_hdr; /* 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++) + } + 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) + { + 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; +} + +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; + +malloc(0); + if ((sec->flags & SEC_RELOC) == 0) + return; + /* Flags are sometimes inconsistent. */ + if (sec->reloc_count == 0) + return; + + rela_hdr = &elf_section_data (sec)->rel_hdr; + + rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count; + rela_hdr->contents = (void *) bfd_alloc (abfd, rela_hdr->sh_size); + + /* orelocation has the data, reloc_count has the count... */ + if (use_rela_p) + { + outbound_relocas = (Elf_External_Rela *) rela_hdr->contents; + + for (idx = 0; idx < sec->reloc_count; idx++) { Elf_Internal_Rela dst_rela; Elf_External_Rela *src_rela; arelent *ptr; - - ptr = asect->orelocation[idx]; + asymbol *sym; + + ptr = sec->orelocation[idx]; src_rela = outbound_relocas + idx; if (!(abfd->flags & EXEC_P)) - dst_rela.r_offset = ptr->address - asect->vma; + dst_rela.r_offset = ptr->address - sec->vma; else dst_rela.r_offset = ptr->address; - + + 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, ptr->sym_ptr_ptr), + = ELF_R_INFO (elf_symbol_from_bfd_symbol (abfd, &sym), ptr->howto->type); - + dst_rela.r_addend = ptr->addend; elf_swap_reloca_out (abfd, &dst_rela, src_rela); +malloc(0); } - - rela_hdr->contents = (void *) outbound_relocas; - - 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++) + outbound_relocs = (Elf_External_Rel *) rela_hdr->contents; + + for (idx = 0; idx < sec->reloc_count; idx++) { Elf_Internal_Rel dst_rel; Elf_External_Rel *src_rel; arelent *ptr; - - ptr = asect->orelocation[idx]; + + ptr = sec->orelocation[idx]; src_rel = outbound_relocs + idx; if (!(abfd->flags & EXEC_P)) - dst_rel.r_offset = ptr->address - asect->vma; + dst_rel.r_offset = ptr->address - sec->vma; else dst_rel.r_offset = ptr->address; @@ -1560,38 +1227,11 @@ DEFUN (elf_make_sections, (abfd, asect, obj), 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) + (unsigned char *) (elf_section_data (sec)->this_hdr.contents) + dst_rel.r_offset); } - rela_hdr->contents = (void *) outbound_relocs; - - 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; - - if (asect->flags & SEC_CODE) - this_hdr->sh_flags |= SHF_EXECINSTR; } static void @@ -1600,52 +1240,22 @@ fix_up_strtabs (abfd, asect, obj) 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]; + Elf_Internal_Shdr *this_hdr = &elf_section_data (asect)->this_hdr; + int this_idx = elf_section_data(asect)->this_idx; /* @@ 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; - - strcpy (strtab, asect->name); - strcat (strtab, "str"); - - s = bfd_get_section_by_name (abfd, strtab); -#if 0 - fprintf (stderr, "`%s' -> 0x%x\n", strtab, s); -#endif - if (s) - { - Elf_Internal_Shdr *s2 = thunk->i_shdrp; + && !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 (stridx = 0; /* ?? */; s2++, stridx++) - { - if (!strcmp (strtab, s2->sh_name + elf_shstrtab (abfd)->tab)) - break; - } - } - 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; } @@ -1657,126 +1267,79 @@ DEFUN (elf_fake_sections, (abfd, asect, obj), asection * asect AND PTR obj) { - 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; + 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; + + { + /* Emit a strtab and symtab, and possibly a reloc section. */ + Elf_Internal_Shdr *rela_hdr; + Elf_Internal_Shdr *symstrtab_hdr; + + /* Note that only one symtab is used, so just remember it + for now. */ + + if ((asect->flags & SEC_RELOC) + /* inconsistent flags... */ + && asect->reloc_count > 0) { - /* 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]; + int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; - 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; - } + 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) + } + if (asect->flags & SEC_ALLOC) + { + this_hdr->sh_flags |= SHF_ALLOC; + if (asect->flags & SEC_LOAD) { - this_hdr->sh_flags |= SHF_ALLOC; - if (asect->flags & SEC_LOAD) - { - /* @@ Do something with sh_type? */ - } + /* @@ 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; } + if (!(asect->flags & SEC_READONLY)) + this_hdr->sh_flags |= SHF_WRITE; + if (asect->flags & SEC_CODE) + this_hdr->sh_flags |= SHF_EXECINSTR; } @@ -1922,6 +1485,8 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) elf_num_globals (abfd) = num_globals; } +static void assign_section_numbers (); +static void assign_file_positions_except_relocs (); static boolean DEFUN (elf_compute_section_file_positions, (abfd), bfd * abfd) @@ -1930,147 +1495,19 @@ DEFUN (elf_compute_section_file_positions, (abfd), bfd * abfd) 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; + bfd_map_over_sections (abfd, elf_fake_sections, 0); -#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; + assign_section_numbers (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); + bfd_map_over_sections (abfd, elf_make_sections, 0); - /* figure at most each section can have a rel, strtab, symtab */ - maxsections = 4 * bfd_count_sections (abfd) + 2; + bfd_map_over_sections (abfd, fix_up_strtabs, 0); /* .stab/.stabstr &c */ - i_ehdrp->e_shoff = i_ehdrp->e_ehsize; + swap_out_syms (abfd); - /* and we'll just have to fix up the offsets later. */ - /* outbase += i_ehdr.e_shentsize * i_ehdr.e_shnum; */ + assign_file_positions_except_relocs (abfd); - 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; - } - - - 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; - - i_ehdrp->e_shnum = 1; - - elf_elfsections (abfd) = i_shdrp; - elf_shstrtab (abfd) = shstrtab; - } - 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 */ - - 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; - - for (idx = 0, secp = abfd->sections; secp; idx++, secp = secp->next) - { - if (psecp == (asection *) 0) - { - secp->filepos = est.i_ehdr->e_shoff + (est.i_ehdr->e_shnum + 1) * sizeof (Elf_External_Shdr); - } - 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; } @@ -2272,39 +1709,246 @@ DEFUN (elf_build_phdrs, (abfd, i_ehdrp, i_shdrp, phdr_cnt), return phdr_buf; } -boolean -DEFUN (elf_write_object_contents, (abfd), bfd * abfd) +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 +assign_section_numbers (abfd) + bfd *abfd; +{ + struct elf_obj_tdata *t = elf_tdata (abfd); + asection *sec; + int section_number = 1; + int i; + Elf_Internal_Shdr **i_shdrp; + + t->shstrtab_hdr.sh_size = elf_shstrtab(abfd)->length; + t->shstrtab_hdr.contents = (void *) elf_shstrtab(abfd)->tab; + shstrtab_length_fixed = 1; + + 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) + { + d->rel_idx = section_number++; + d->rel_hdr.sh_link = t->symtab_section; + d->rel_hdr.sh_info = d->this_idx; + } + else + 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 +assign_file_positions_except_relocs (abfd) + bfd *abfd; +{ + /* 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. + + 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. + + The order, for now: <ehdr> <shdr> <sec1> <sec2> <sec3> ... <rel1> ... */ + + 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) + { + i_shdrp->sh_offset = -1; + continue; + } + 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_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; + Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ - int outbase = 0; int count; int scnt; struct strtab *shstrtab; - if (abfd->output_has_begun == false) + i_ehdrp = elf_elfheader (abfd); + i_shdrp = elf_elfsections (abfd); + + shstrtab = bfd_new_strtab (abfd); + elf_shstrtab (abfd) = shstrtab; + + i_ehdrp->e_ident[EI_MAG0] = ELFMAG0; + i_ehdrp->e_ident[EI_MAG1] = ELFMAG1; + i_ehdrp->e_ident[EI_MAG2] = ELFMAG2; + i_ehdrp->e_ident[EI_MAG3] = ELFMAG3; + + i_ehdrp->e_ident[EI_CLASS] = ELFCLASS; + i_ehdrp->e_ident[EI_DATA] = + abfd->xvec->byteorder_big_p ? ELFDATA2MSB : ELFDATA2LSB; + i_ehdrp->e_ident[EI_VERSION] = EV_CURRENT; + + for (count = EI_PAD; count < EI_NIDENT; count++) + i_ehdrp->e_ident[count] = 0; + + i_ehdrp->e_type = (abfd->flags & EXEC_P) ? ET_EXEC : ET_REL; + switch (bfd_get_arch (abfd)) { - elf_compute_section_file_positions (abfd); - abfd->output_has_begun = true; + 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; } + i_ehdrp->e_version = EV_CURRENT; + i_ehdrp->e_ehsize = sizeof (Elf_External_Ehdr); - i_ehdrp = elf_elfheader (abfd); - i_shdrp = elf_elfsections (abfd); - shstrtab = elf_shstrtab (abfd); + /* no program header, for now. */ + i_ehdrp->e_phoff = 0; + i_ehdrp->e_phentsize = 0; + i_ehdrp->e_phnum = 0; + + /* each bfd section is section header entry */ + i_ehdrp->e_entry = bfd_get_start_address (abfd); + i_ehdrp->e_shentsize = sizeof (Elf_External_Shdr); - 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 we're building an executable, we'll need a program header table */ + if (abfd->flags & EXEC_P) + { + abort (); - bfd_map_over_sections (abfd, elf_make_sections, &est); - bfd_map_over_sections (abfd, fix_up_strtabs, &est); +#if 0 + i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr); + + /* elf_build_phdrs() returns a (NULL-terminated) array of + Elf_Internal_Phdrs */ + i_phdrp = elf_build_phdrs (abfd, i_ehdrp, i_shdrp, &i_ehdrp->e_phnum); + i_ehdrp->e_phoff = outbase; + outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum; +#endif + } + else + { + i_ehdrp->e_phentsize = 0; + i_phdrp = 0; + i_ehdrp->e_phoff = 0; + } + + elf_tdata (abfd)->symtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab, + ".symtab"); + elf_tdata (abfd)->strtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab, + ".strtab"); + elf_tdata (abfd)->shstrtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab, + ".shstrtab"); + +} + +static void +swap_out_syms (abfd) + bfd *abfd; +{ + struct strtab *shstrtab = elf_shstrtab (abfd); + + elf_map_symbols (abfd); /* Dump out the symtabs. */ { @@ -2313,20 +1957,17 @@ DEFUN (elf_write_object_contents, (abfd), bfd * 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; - symtab_hdr = &i_shdrp[est.symtab_section]; + 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; /* 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 = &elf_tdata (abfd)->strtab_hdr; symstrtab_hdr->sh_type = SHT_STRTAB; outbound_syms = (Elf_External_Sym *) @@ -2362,14 +2003,36 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) sym.st_size = value; /* Should retrieve this from somewhere... */ sym.st_value = 16; + sym.st_shndx = SHN_COMMON; } else { - value += syms[idx]->section->output_section->vma - + syms[idx]->section->output_offset; - sym.st_value = value; + asection *sec = syms[idx]->section; + int shndx; + if (sec->output_section) + { + value += sec->output_offset; + sec = sec->output_section; + } + value += sec->vma; + sym.st_value = value; sym.st_size = (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); + } } if (bfd_is_com_section (syms[idx]->section)) @@ -2401,19 +2064,12 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) 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; + symtab_hdr->contents = (PTR) outbound_syms; + symstrtab_hdr->contents = (PTR) stt->tab; symstrtab_hdr->sh_size = stt->length; symstrtab_hdr->sh_type = SHT_STRTAB; @@ -2422,7 +2078,6 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) 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; } @@ -2430,40 +2085,36 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) /* 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 = &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_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; } +} - outbase = i_ehdrp->e_ehsize; +static boolean +write_shdrs_and_ehdr (abfd) + bfd *abfd; +{ + Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + Elf_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 */ - /* if we're building an executable, we'll need a program header table */ - if (abfd->flags & EXEC_P) - { - i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr); + int count; + int scnt; + struct strtab *shstrtab; - /* 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); - } + i_ehdrp = elf_elfheader (abfd); + i_shdrp = elf_elfsections (abfd); + shstrtab = elf_shstrtab (abfd); /* swap the header before spitting it out... */ @@ -2474,27 +2125,6 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) 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++) - { - if (i_shdrp[count].sh_offset && outbase < i_shdrp[count].sh_offset) - outbase = i_shdrp[count].sh_offset + i_shdrp[count].sh_size; - } - - /* 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; - } - /* If we're building an executable, fixup the program header table offsets. @@ -2508,10 +2138,11 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) for (count = 0; count < 3; count++) { - asection *asect = bfd_get_section_by_name (abfd, section_name[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; + i_phdrp[count].p_offset = i_shdrp[sh_idx]->sh_offset; } /* write out the program header table entries */ @@ -2527,29 +2158,71 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) return false; } - for (count = 0, scnt = 0; count < i_ehdrp->e_shnum; count++) + for (count = 0; count < i_ehdrp->e_shnum; count++) { #if DEBUG & 2 - elf_debug_section (shstrtab->tab + i_shdrp[scnt].sh_name, count, i_shdrp + scnt); + 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 + scnt); - scnt++; + 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... */ - /* after writing the headers, we need to write the sections too... */ - nsect = abfd->sections; - for (count = 0; count < i_ehdrp->e_shnum; count++) + return true; +} + +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++) { - 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); - } + 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; +} - return true; +boolean +DEFUN (NAME(bfd_elf,write_object_contents), (abfd), bfd * abfd) +{ + Elf_Internal_Ehdr *i_ehdrp; + Elf_Internal_Shdr **i_shdrp; + int count; + + 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; + } + + i_shdrp = elf_elfsections (abfd); + i_ehdrp = elf_elfheader (abfd); + + bfd_map_over_sections (abfd, write_relocs, (PTR) 0); +malloc(0); + assign_file_positions_for_relocs (abfd); + + /* 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); + } + return write_shdrs_and_ehdr (abfd); } /* Given an index of a section, retrieve a pointer to it. Note @@ -2574,9 +2247,11 @@ DEFUN (section_from_elf_index, (abfd, index), if (index == SHN_COMMON) return &bfd_com_section; + if (index > elf_elfheader (abfd)->e_shnum) + return 0; + { - Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); - Elf_Internal_Shdr *hdr = i_shdrp + index; + Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[index]; switch (hdr->sh_type) { @@ -2599,7 +2274,7 @@ DEFUN (elf_section_from_bfd_section, (abfd, asect), bfd * abfd AND struct sec *asect) { - Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); + Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd); int index; Elf_Internal_Shdr *hdr; int maxindex = elf_elfheader (abfd)->e_shnum; @@ -2608,10 +2283,12 @@ DEFUN (elf_section_from_bfd_section, (abfd, asect), return SHN_ABS; if (asect == &bfd_com_section) return SHN_COMMON; + if (asect == &bfd_und_section) + return SHN_UNDEF; for (index = 0; index < maxindex; index++) { - hdr = &i_shdrp[index]; + hdr = i_shdrp[index]; switch (hdr->sh_type) { /* ELF sections that map to BFD sections */ @@ -2627,7 +2304,7 @@ DEFUN (elf_section_from_bfd_section, (abfd, asect), break; } } - return 0; + return -1; } /* given a symbol, return the bfd index for that symbol. */ @@ -2731,8 +2408,7 @@ DEFUN (elf_slurp_symbol_table, (abfd, symptrs), bfd * abfd AND asymbol ** symptrs) /* Buffer for generated bfd symbols */ { - Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); - Elf_Internal_Shdr *hdr = i_shdrp + elf_onesymtab (abfd); + 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 */ @@ -2892,16 +2568,11 @@ DEFUN (elf_get_symtab_upper_bound, (abfd), bfd * abfd) { 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) - { - hdr = i_shdrp + elf_onesymtab (abfd); - symcount = hdr->sh_size / sizeof (Elf_External_Sym); - symtab_size = (symcount - 1 + 1) * (sizeof (asymbol)); - } + Elf_Internal_Shdr *hdr = &elf_tdata(abfd)->symtab_hdr; + symcount = hdr->sh_size / sizeof (Elf_External_Sym); + symtab_size = (symcount - 1 + 1) * (sizeof (asymbol)); + return symtab_size; } @@ -2919,7 +2590,7 @@ elf_get_reloc_upper_bound (abfd, asect) if (asect->flags & SEC_RELOC) { /* either rel or rela */ - return asect->_raw_size; + return elf_section_data(asect)->rel_hdr.sh_size; } else return 0; @@ -3021,16 +2692,23 @@ elf_debug_section (str, num, hdr) Elf_Internal_Shdr *hdr; { 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, + "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); @@ -3060,7 +2738,6 @@ DEFUN (elf_slurp_reloc_table, (abfd, asect, symbols), 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; @@ -3092,13 +2769,12 @@ DEFUN (elf_slurp_reloc_table, (abfd, asect, symbols), /* 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_hdr = &elf_section_data(asect)->this_hdr; data_off = data_hdr->sh_offset; data_max = data_hdr->sh_size - sizeof (buf) + 1; #if DEBUG & 2 - elf_debug_section ("data section", data_hdr - i_shdrp, data_hdr); + elf_debug_section ("data section", -1, data_hdr); #endif for (idx = 0; idx < asect->reloc_count; idx++) @@ -3328,23 +3004,23 @@ DEFUN (elf_set_section_contents, (abfd, section, location, offset, count), file_ptr offset AND bfd_size_type count) { - int dest_sect; + Elf_Internal_Shdr *hdr; if (abfd->output_has_begun == false) /* set by bfd.c handler? */ { /* do setup calculations (FIXME) */ + prep_headers (abfd); elf_compute_section_file_positions (abfd); abfd->output_has_begun = true; } - dest_sect = elf_section_from_bfd_section (abfd, section); - if (!dest_sect) - return false; + hdr = &elf_section_data(section)->this_hdr; - if (bfd_seek (abfd, elf_elfsections (abfd)[dest_sect].sh_offset + offset, SEEK_SET) == -1) + 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; } @@ -3370,18 +3046,424 @@ DEFUN (elf_no_info_to_howto_rel, (abfd, cache_ptr, dst), BFD_FAIL (); } -boolean -DEFUN (elf_get_sect_thunk, (abfd, est), + +/* Core file support */ + +#ifdef HAVE_PROCFS /* Some core file support requires host /proc files */ +#include <sys/procfs.h> +#else +#define bfd_prstatus(abfd, descdata, descsz, filepos) /* Define away */ +#define bfd_fpregset(abfd, descdata, descsz, filepos) /* Define away */ +#define bfd_prpsinfo(abfd, descdata, descsz, filepos) /* Define away */ +#endif + +#ifdef HAVE_PROCFS + +static void +DEFUN (bfd_prstatus, (abfd, descdata, descsz, filepos), bfd * abfd AND - elf_sect_thunk * est) + char *descdata AND + int descsz AND + long filepos) { - if (est == (elf_sect_thunk *) NULL) - return false; + asection *newsect; + prstatus_t *status = (prstatus_t *) 0; - 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 */ + 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) +{ + asection *newsect; + + if (descsz == sizeof (prpsinfo_t)) + { + if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) != NULL) + { + memcpy (core_prpsinfo (abfd), descdata, descsz); + } + } +} + +static void +DEFUN (bfd_fpregset, (abfd, descdata, descsz, filepos), + bfd * abfd AND + char *descdata AND + int descsz AND + long filepos) +{ + asection *newsect; + + 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 /* 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) +{ +#ifdef HAVE_PROCFS + if (core_prpsinfo (abfd)) + { + prpsinfo_t *p = core_prpsinfo (abfd); + char *scan = p->pr_psargs; + while (*scan++) + {; + } + scan -= 2; + if ((scan > p->pr_psargs) && (*scan == ' ')) + { + *scan = '\000'; + } + return p->pr_psargs; + } +#endif + return NULL; +} + +/* Return the number of the signal that caused the core dump. Presumably, + since we have a core file, we got a signal of some kind, so don't bother + checking the other process status fields, just return the signal number. + */ + +int +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; +} + +/* Check to see if the core file could reasonably be expected to have + come for the current executable file. Note that by default we return + true unless we find something that indicates that there might be a + problem. + */ + +boolean +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 + + /* First, xvecs must match since both are ELF files for the same target. */ + + if (core_bfd->xvec != exec_bfd->xvec) + { + bfd_error = system_call_error; + return false; + } + +#ifdef HAVE_PROCFS + + /* If no prpsinfo, just return true. Otherwise, grab the last component + of the exec'd pathname from the prpsinfo. */ + + if (core_prpsinfo (core_bfd)) + { + corename = (((struct prpsinfo *) core_prpsinfo (core_bfd))->pr_fname); + } + else + { + return true; + } + + /* Find the last component of the executable pathname. */ + + if ((execname = strrchr (exec_bfd->filename, '/')) != NULL) + { + execname++; + } + else + { + execname = (char *) exec_bfd->filename; + } + + /* See if they match */ + + return strcmp (execname, corename) ? false : true; + +#else + + return true; + +#endif /* HAVE_PROCFS */ +} + +/* ELF core files contain a segment of type PT_NOTE, that holds much of + the information that would normally be available from the /proc interface + for the process, at the time the process dumped core. Currently this + includes copies of the prstatus, prpsinfo, and fpregset structures. + + Since these structures are potentially machine dependent in size and + ordering, bfd provides two levels of support for them. The first level, + available on all machines since it does not require that the host + have /proc support or the relevant include files, is to create a bfd + section for each of the prstatus, prpsinfo, and fpregset structures, + without any interpretation of their contents. With just this support, + the bfd client will have to interpret the structures itself. Even with + /proc support, it might want these full structures for it's own reasons. + + In the second level of support, where HAVE_PROCFS is defined, bfd will + pick apart the structures to gather some additional information that + clients may want, such as the general register set, the name of the + exec'ed file and its arguments, the signal (if any) that caused the + core dump, etc. + + */ + +static boolean +DEFUN (elf_corefile_note, (abfd, hdr), + bfd * abfd AND + 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; + +} + +/* 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_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; + + /* Read in the ELF header in external format. */ + + 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 + program header table (FIXME: See comments re segments at top of this + file). */ + + if (elf_file_p (&x_ehdr) == false) + { + wrong: + bfd_error = wrong_format; + return NULL; + } + + /* FIXME, Check EI_VERSION here ! */ + + { +#if ARCH_SIZE == 32 + int desired_address_size = ELFCLASS32; +#endif +#if ARCH_SIZE == 64 + int desired_address_size = ELFCLASS64; +#endif + + if (x_ehdr.e_ident[EI_CLASS] != desired_address_size) + goto wrong; + } + + /* Switch xvec to match the specified byte order. */ + switch (x_ehdr.e_ident[EI_DATA]) + { + case ELFDATA2MSB: /* Big-endian */ + if (abfd->xvec->byteorder_big_p == false) + goto wrong; + break; + case ELFDATA2LSB: /* Little-endian */ + if (abfd->xvec->byteorder_big_p == true) + goto wrong; + break; + case ELFDATANONE: /* No data encoding specified */ + default: /* Unknown data encoding specified */ + goto wrong; + } + + /* Allocate an instance of the elf_obj_tdata structure and hook it up to + the tdata pointer in the bfd. */ + + elf_tdata (abfd) = + (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)); + if (elf_tdata (abfd) == NULL) + { + bfd_error = no_memory; + return NULL; + } + + /* FIXME, `wrong' returns from this point onward, leak memory. */ + + /* Now that we know the byte order, swap in the rest of the header */ + i_ehdrp = elf_elfheader (abfd); + elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp); +#if DEBUG & 1 + elf_debug_file (i_ehdrp); +#endif + + /* If there is no program header, or the type is not a core file, then + we are hosed. */ + if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE) + goto wrong; + + /* Allocate space for a copy of the program header table in + internal form, seek to the program header table in the file, + read it in, and convert it to internal form. As a simple sanity + check, verify that the what BFD thinks is the size of each program + header table entry actually matches the size recorded in the file. */ + + if (i_ehdrp->e_phentsize != sizeof (x_phdr)) + goto wrong; + i_phdrp = (Elf_Internal_Phdr *) + bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum); + if (!i_phdrp) + { + bfd_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); + } + + /* Once all of the program headers have been read and converted, we + can start processing them. */ + + for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++) + { + bfd_section_from_phdr (abfd, i_phdrp + phindex, phindex); + if ((i_phdrp + phindex)->p_type == PT_NOTE) + { + elf_corefile_note (abfd, i_phdrp + phindex); + } + } + + /* Remember the entry point specified in the ELF file header. */ + + bfd_get_start_address (abfd) = i_ehdrp->e_entry; + + return abfd->xvec; } |