diff options
-rw-r--r-- | bfd/elfcode.h | 324 |
1 files changed, 201 insertions, 123 deletions
diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 533ad3c..3aeffe4 100644 --- a/bfd/elfcode.h +++ b/bfd/elfcode.h @@ -99,6 +99,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #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) #ifdef HAVE_PROCFS /* Some core file support requires host /proc files */ @@ -571,6 +572,16 @@ DEFUN (bfd_section_from_shdr, (abfd, shindex), return true; case SHT_STRTAB: /* A string table */ + if (!strcmp (name, ".strtab") || !strcmp (name, ".shstrtab")) + return true; + + if (!hdr->rawdata) + { + newsect = bfd_make_section (abfd, name); + if (newsect) + newsect->flags = SEC_HAS_CONTENTS; + } + return true; case SHT_REL: @@ -653,6 +664,15 @@ DEFUN (bfd_section_from_shdr, (abfd, shindex), return true; } +boolean +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) @@ -669,7 +689,7 @@ DEFUN (bfd_new_strtab, (abfd), return ss; } -int +static int DEFUN (bfd_add_to_strtab, (abfd, ss, str), bfd * abfd AND struct strtab *ss AND @@ -728,8 +748,6 @@ DEFUN (bfd_shdr_from_section, (abfd, hdr, shstrtab, indx), asection *sect; int ndx; - /* figure out out to write the section name from the bfd section name. MWE */ - sect = abfd->sections; for (ndx = indx; --ndx;) { @@ -1588,125 +1606,170 @@ DEFUN (elf_make_sections, (abfd, asect, obj), int this_section; int idx; - /* 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 = elf_section_from_bfd_section (abfd, asect); - this_hdr = &thunk->i_shdrp[this_section]; + Elf_Internal_Shdr *this_hdr; + this_section = elf_section_from_bfd_section (abfd, asect); + this_hdr = &thunk->i_shdrp[this_section]; - this_hdr->sh_addr = asect->vma; - this_hdr->sh_size = asect->_raw_size; - /* contents already set by elf_set_section_contents */ + 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) - { - /* 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; + 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; - symtab_hdr = &thunk->i_shdrp[thunk->symtab_section]; + 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; + 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; - /* orelocation has the data, reloc_count has the count... */ - if (use_rela_p) + /* 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++) { - 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 - = ELF32_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); - } - - rela_hdr->contents = (void *) outbound_relocas; + 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 + = ELF32_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); } - else - /* REL relocations */ + + rela_hdr->contents = (void *) outbound_relocas; + } + 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++) { - 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); + 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 + = ELF32_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; + } + } + 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; - for (idx = 0; idx < asect->reloc_count; idx++) - { - Elf_Internal_Rel dst_rel; - Elf_External_Rel *src_rel; - arelent *ptr; + if (asect->flags & SEC_CODE) + this_hdr->sh_flags |= SHF_EXECINSTR; +} - 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; +static void +fix_up_strtabs (abfd, asect, obj) + 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]; - dst_rel.r_info - = ELF32_R_INFO (elf_symbol_from_bfd_symbol (abfd, ptr->sym_ptr_ptr), - ptr->howto->type); + /* @@ 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; - elf_swap_reloc_out (abfd, &dst_rel, src_rel); + strcpy (strtab, asect->name); + strcat (strtab, "str"); - /* 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 + s = bfd_get_section_by_name (abfd, strtab); + fprintf (stderr, "`%s' -> 0x%x\n", strtab, s); + if (s) + { + Elf_Internal_Shdr *s2 = thunk->i_shdrp; - bfd_put_32 (abfd, ptr->addend, - (unsigned char *) (elf_elfsections (abfd)[this_section].contents) - + dst_rel.r_offset); - } - rela_hdr->contents = (void *) outbound_relocs; + for (stridx = 0; /* ?? */; s2++, stridx++) + { + if (!strcmp (strtab, s2->sh_name + elf_shstrtab (abfd)->tab)) + break; } } - if (asect->flags & SEC_ALLOC) + else { - this_hdr->sh_flags |= SHF_ALLOC; - if (asect->flags & SEC_LOAD) + asection *s2 = abfd->sections; + stridx = 0; + fprintf (stderr, " not in:"); + while (s2) { - /* @@ Do something with sh_type? */ + fprintf (stderr, " %s", s2->name); + s2 = s2->next; } + fprintf (stderr, "\n"); } - if (!(asect->flags & SEC_READONLY)) - this_hdr->sh_flags |= SHF_WRITE; - - if (asect->flags & SEC_CODE) - this_hdr->sh_flags |= SHF_EXECINSTR; + this_hdr->sh_link = stridx; + /* @@ Assuming 32 bits! */ + this_hdr->sh_entsize = 0xc; } } @@ -1853,6 +1916,25 @@ DEFUN (bfd_elf_locate_sh, (abfd, strtab, shdrp, name), /* Map symbol from it's internal number to the external number, moving all local symbols to be at the head of the list. */ +static INLINE int +sym_is_global (sym) + asymbol *sym; +{ + if (sym->flags & BSF_GLOBAL) + { + 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; +} + static boolean DEFUN (elf_map_symbols, (abfd), bfd * abfd) { @@ -1915,8 +1997,7 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) /* Identify and classify all of the symbols. */ for (idx = 0; idx < symcount; idx++) { - flags = syms[idx]->flags; - if (flags & (BSF_LOCAL | BSF_SECTION_SYM | BSF_FILE)) + if (!sym_is_global (syms[idx])) num_locals++; else num_globals++; @@ -1926,8 +2007,7 @@ DEFUN (elf_map_symbols, (abfd), bfd * abfd) dummy symbol. */ for (idx = 0; idx < symcount; idx++) { - flags = syms[idx]->flags; - if (flags & (BSF_LOCAL | BSF_SECTION_SYM | BSF_FILE)) + if (!sym_is_global (syms[idx])) symtab_map[idx] = 1 + num_locals2++; else symtab_map[idx] = 1 + num_locals + num_globals2++; @@ -2309,6 +2389,7 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) est.symtab_section = elf_onesymtab (abfd); /* filled in by elf_fake */ bfd_map_over_sections (abfd, elf_make_sections, &est); + bfd_map_over_sections (abfd, fix_up_strtabs, &est); /* Dump out the symtabs. */ { @@ -2360,35 +2441,32 @@ DEFUN (elf_write_object_contents, (abfd), bfd * abfd) sym.st_size = (Elf32_Word) (elf_symbol_from (abfd, syms[idx]))->internal_elf_sym.st_size; - if (syms[idx]->flags & BSF_WEAK) + if (syms[idx]->section == &bfd_und_section + || bfd_is_com_section (syms[idx]->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_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 if (syms[idx]->flags & BSF_GLOBAL) + 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_EXPORT) + else if (syms[idx]->flags & BSF_LOCAL) { if (syms[idx]->flags & BSF_FUNCTION) - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_FUNC); + sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC); else - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT); + sym.st_info = ELF_ST_INFO (STB_LOCAL, 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 - sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_OBJECT); + /* 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) |