* internal.h (elf_internal_sym): Add st_target_internal.
	* arm.h (arm_st_branch_type): New enum.
	(ARM_SYM_BRANCH_TYPE): New macro.
bfd/
	* elf-bfd.h (elf_link_hash_entry): Add target_internal.
	* elf.c (swap_out_syms): Set st_target_internal for each
	Elf_Internal_Sym.
	* elfcode.h (elf_swap_symbol_in): Likewise.
	* elf32-i370.c (i370_elf_finish_dynamic_sections): Likewise.
	* elf32-sh-symbian.c (sh_symbian_relocate_section): Likewise.
	* elf64-sparc.c (elf64_sparc_output_arch_syms): Likewise.
	* elfxx-sparc.c (_bfd_sparc_elf_size_dynamic_sections): Likewise.
	* elflink.c (elf_link_output_extsym): Likewise.
	(bfd_elf_final_link): Likewise.
	(elf_link_add_object_symbols): Copy st_target_internal
	to the hash table if we see a definition.
	(_bfd_elf_copy_link_hash_symbol_type): Copy target_internal.
	* elf32-arm.c (elf32_arm_stub_hash_entry): Replace st_type with
	a branch_type field.
	(a8_erratum_fix, a8_erratum_reloc): Likewise.
	(arm_type_of_stub): Replace actual_st_type with an
	actual_branch_type parameter.
	(arm_build_one_stub): Use branch types rather than st_types to
	determine the type of branch.
	(cortex_a8_erratum_scan): Likewise.
	(elf32_arm_size_stubs): Likewise.
	(bfd_elf32_arm_process_before_allocation): Likewise.
	(allocate_dynrelocs_for_symbol): Likewise.
	(elf32_arm_finish_dynamic_sections): Likewise.
	(elf32_arm_final_link_relocate): Replace sym_flags parameter with
	a branch_type parameter.
	(elf32_arm_relocate_section): Update call accordingly.
	(elf32_arm_adjust_dynamic_symbol): Don't check STT_ARM_TFUNC.
	(elf32_arm_output_map_sym): Initialize st_target_internal.
	(elf32_arm_output_stub_sym): Likewise.
	(elf32_arm_symbol_processing): Delete.
	(elf32_arm_swap_symbol_in): Convert STT_ARM_TFUNCs into STT_FUNCs.
	Use st_target_internal to record the branch type.
	(elf32_arm_swap_symbol_out): Use st_target_internal to test for
	Thumb functions.
	(elf32_arm_is_function_type): Delete.
	(elf_backend_symbol_processing): Likewise.
	(elf_backend_is_function_type): Likewise.
gas/
	* config/tc-arm.c (arm_adjust_symtab): Set the branch type
	for Thumb symbols.
ld/
	* emultempl/armelf.em (gld${EMULATION_NAME}_finish): Check
	eh->target_internal.
opcodes/
	* arm-dis.c (get_sym_code_type): Don't check for STT_ARM_TFUNC.
	Use branch types instead.
	(print_insn): Likewise.
		
	
		
			
				
	
	
		
			361 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			361 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* ELF support for BFD.
 | |
|    Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002,
 | |
|    2003, 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
 | |
| 
 | |
|    Written by Fred Fish @ Cygnus Support, from information published
 | |
|    in "UNIX System V Release 4, Programmers Guide: ANSI C and
 | |
|    Programming Support Tools".
 | |
| 
 | |
|    This file is part of BFD, the Binary File Descriptor library.
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or modify
 | |
|    it under the terms of the GNU General Public License as published by
 | |
|    the Free Software Foundation; either version 3 of the License, or
 | |
|    (at your option) any later version.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
 | |
|    MA 02110-1301, USA.  */
 | |
| 
 | |
| /* This file is part of ELF support for BFD, and contains the portions
 | |
|    that describe how ELF is represented internally in the BFD library.
 | |
|    I.E. it describes the in-memory representation of ELF.  It requires
 | |
|    the elf-common.h file which contains the portions that are common to
 | |
|    both the internal and external representations.  */
 | |
| 
 | |
| /* NOTE that these structures are not kept in the same order as they appear
 | |
|    in the object file.  In some cases they've been reordered for more optimal
 | |
|    packing under various circumstances.  */
 | |
| 
 | |
| #ifndef _ELF_INTERNAL_H
 | |
| #define _ELF_INTERNAL_H
 | |
| 
 | |
| /* Special section indices, which may show up in st_shndx fields, among
 | |
|    other places.  */
 | |
| 
 | |
| #undef SHN_UNDEF
 | |
| #undef SHN_LORESERVE
 | |
| #undef SHN_LOPROC
 | |
| #undef SHN_HIPROC
 | |
| #undef SHN_LOOS
 | |
| #undef SHN_HIOS
 | |
| #undef SHN_ABS
 | |
| #undef SHN_COMMON
 | |
| #undef SHN_XINDEX
 | |
| #undef SHN_HIRESERVE
 | |
| #define SHN_UNDEF	0		/* Undefined section reference */
 | |
| #define SHN_LORESERVE	(-0x100u)	/* Begin range of reserved indices */
 | |
| #define SHN_LOPROC	(-0x100u)	/* Begin range of appl-specific */
 | |
| #define SHN_HIPROC	(-0xE1u)	/* End range of appl-specific */
 | |
| #define SHN_LOOS	(-0xE0u)	/* OS specific semantics, lo */
 | |
| #define SHN_HIOS	(-0xC1u)	/* OS specific semantics, hi */
 | |
| #define SHN_ABS		(-0xFu)		/* Associated symbol is absolute */
 | |
| #define SHN_COMMON	(-0xEu)		/* Associated symbol is in common */
 | |
| #define SHN_XINDEX	(-0x1u)		/* Section index is held elsewhere */
 | |
| #define SHN_HIRESERVE	(-0x1u)		/* End range of reserved indices */
 | |
| #define SHN_BAD		(-0x101u)	/* Used internally by bfd */
 | |
| 
 | |
| /* ELF Header */
 | |
| 
 | |
| #define EI_NIDENT	16		/* Size of e_ident[] */
 | |
| 
 | |
| typedef struct elf_internal_ehdr {
 | |
|   unsigned char		e_ident[EI_NIDENT]; /* ELF "magic number" */
 | |
|   bfd_vma		e_entry;	/* Entry point virtual address */
 | |
|   bfd_size_type		e_phoff;	/* Program header table file offset */
 | |
|   bfd_size_type		e_shoff;	/* Section header table file offset */
 | |
|   unsigned long		e_version;	/* Identifies object file version */
 | |
|   unsigned long		e_flags;	/* Processor-specific flags */
 | |
|   unsigned short	e_type;		/* Identifies object file type */
 | |
|   unsigned short	e_machine;	/* Specifies required architecture */
 | |
|   unsigned int		e_ehsize;	/* ELF header size in bytes */
 | |
|   unsigned int		e_phentsize;	/* Program header table entry size */
 | |
|   unsigned int		e_phnum;	/* Program header table entry count */
 | |
|   unsigned int		e_shentsize;	/* Section header table entry size */
 | |
|   unsigned int		e_shnum;	/* Section header table entry count */
 | |
|   unsigned int		e_shstrndx;	/* Section header string table index */
 | |
| } Elf_Internal_Ehdr;
 | |
| 
 | |
| /* Program header */
 | |
| 
 | |
| struct elf_internal_phdr {
 | |
|   unsigned long	p_type;			/* Identifies program segment type */
 | |
|   unsigned long	p_flags;		/* Segment flags */
 | |
|   bfd_vma	p_offset;		/* Segment file offset */
 | |
|   bfd_vma	p_vaddr;		/* Segment virtual address */
 | |
|   bfd_vma	p_paddr;		/* Segment physical address */
 | |
|   bfd_vma	p_filesz;		/* Segment size in file */
 | |
|   bfd_vma	p_memsz;		/* Segment size in memory */
 | |
|   bfd_vma	p_align;		/* Segment alignment, file & memory */
 | |
| };
 | |
| 
 | |
| typedef struct elf_internal_phdr Elf_Internal_Phdr;
 | |
| 
 | |
| /* Section header */
 | |
| 
 | |
| typedef struct elf_internal_shdr {
 | |
|   unsigned int	sh_name;		/* Section name, index in string tbl */
 | |
|   unsigned int	sh_type;		/* Type of section */
 | |
|   bfd_vma	sh_flags;		/* Miscellaneous section attributes */
 | |
|   bfd_vma	sh_addr;		/* Section virtual addr at execution */
 | |
|   file_ptr	sh_offset;		/* Section file offset */
 | |
|   bfd_size_type	sh_size;		/* Size of section in bytes */
 | |
|   unsigned int	sh_link;		/* Index of another section */
 | |
|   unsigned int	sh_info;		/* Additional section information */
 | |
|   bfd_vma	sh_addralign;		/* Section alignment */
 | |
|   bfd_size_type	sh_entsize;		/* Entry size if section holds table */
 | |
| 
 | |
|   /* The internal rep also has some cached info associated with it. */
 | |
|   asection *	bfd_section;		/* Associated BFD section.  */
 | |
|   unsigned char *contents;		/* Section contents.  */
 | |
| } Elf_Internal_Shdr;
 | |
| 
 | |
| /* Symbol table entry */
 | |
| 
 | |
| struct elf_internal_sym {
 | |
|   bfd_vma	st_value;		/* Value of the symbol */
 | |
|   bfd_vma	st_size;		/* Associated symbol size */
 | |
|   unsigned long	st_name;		/* Symbol name, index in string tbl */
 | |
|   unsigned char	st_info;		/* Type and binding attributes */
 | |
|   unsigned char	st_other;		/* Visibilty, and target specific */
 | |
|   unsigned char st_target_internal;	/* Internal-only information */
 | |
|   unsigned int  st_shndx;		/* Associated section index */
 | |
| };
 | |
| 
 | |
| typedef struct elf_internal_sym Elf_Internal_Sym;
 | |
| 
 | |
| /* Note segments */
 | |
| 
 | |
| typedef struct elf_internal_note {
 | |
|   unsigned long	namesz;			/* Size of entry's owner string */
 | |
|   unsigned long	descsz;			/* Size of the note descriptor */
 | |
|   unsigned long	type;			/* Interpretation of the descriptor */
 | |
|   char *	namedata;		/* Start of the name+desc data */
 | |
|   char *	descdata;		/* Start of the desc data */
 | |
|   bfd_vma	descpos;		/* File offset of the descdata */
 | |
| } Elf_Internal_Note;
 | |
| 
 | |
| /* Relocation Entries */
 | |
| 
 | |
| typedef struct elf_internal_rela {
 | |
|   bfd_vma	r_offset;	/* Location at which to apply the action */
 | |
|   bfd_vma	r_info;		/* Index and Type of relocation */
 | |
|   bfd_vma	r_addend;	/* Constant addend used to compute value */
 | |
| } Elf_Internal_Rela;
 | |
| 
 | |
| /* dynamic section structure */
 | |
| 
 | |
| typedef struct elf_internal_dyn {
 | |
|   /* This needs to support 64-bit values in elf64.  */
 | |
|   bfd_vma d_tag;		/* entry tag value */
 | |
|   union {
 | |
|     /* This needs to support 64-bit values in elf64.  */
 | |
|     bfd_vma	d_val;
 | |
|     bfd_vma	d_ptr;
 | |
|   } d_un;
 | |
| } Elf_Internal_Dyn;
 | |
| 
 | |
| /* This structure appears in a SHT_GNU_verdef section.  */
 | |
| 
 | |
| typedef struct elf_internal_verdef {
 | |
|   unsigned short vd_version;	/* Version number of structure.  */
 | |
|   unsigned short vd_flags;	/* Flags (VER_FLG_*).  */
 | |
|   unsigned short vd_ndx;	/* Version index.  */
 | |
|   unsigned short vd_cnt;	/* Number of verdaux entries.  */
 | |
|   unsigned long	 vd_hash;	/* Hash of name.  */
 | |
|   unsigned long	 vd_aux;	/* Offset to verdaux entries.  */
 | |
|   unsigned long	 vd_next;	/* Offset to next verdef.  */
 | |
| 
 | |
|   /* These fields are set up when BFD reads in the structure.  FIXME:
 | |
|      It would be cleaner to store these in a different structure.  */
 | |
|   bfd			      *vd_bfd;		/* BFD.  */
 | |
|   const char		      *vd_nodename;	/* Version name.  */
 | |
|   struct elf_internal_verdef  *vd_nextdef;	/* vd_next as pointer.  */
 | |
|   struct elf_internal_verdaux *vd_auxptr;	/* vd_aux as pointer.  */
 | |
|   unsigned int		       vd_exp_refno;	/* Used by the linker.  */
 | |
| } Elf_Internal_Verdef;
 | |
| 
 | |
| /* This structure appears in a SHT_GNU_verdef section.  */
 | |
| 
 | |
| typedef struct elf_internal_verdaux {
 | |
|   unsigned long vda_name;	/* String table offset of name.  */
 | |
|   unsigned long vda_next;	/* Offset to next verdaux.  */
 | |
| 
 | |
|   /* These fields are set up when BFD reads in the structure.  FIXME:
 | |
|      It would be cleaner to store these in a different structure.  */
 | |
|   const char *vda_nodename;			/* vda_name as pointer.  */
 | |
|   struct elf_internal_verdaux *vda_nextptr;	/* vda_next as pointer.  */
 | |
| } Elf_Internal_Verdaux;
 | |
| 
 | |
| /* This structure appears in a SHT_GNU_verneed section.  */
 | |
| 
 | |
| typedef struct elf_internal_verneed {
 | |
|   unsigned short vn_version;	/* Version number of structure.  */
 | |
|   unsigned short vn_cnt;	/* Number of vernaux entries.  */
 | |
|   unsigned long	 vn_file;	/* String table offset of library name.  */
 | |
|   unsigned long	 vn_aux;	/* Offset to vernaux entries.  */
 | |
|   unsigned long	 vn_next;	/* Offset to next verneed.  */
 | |
| 
 | |
|   /* These fields are set up when BFD reads in the structure.  FIXME:
 | |
|      It would be cleaner to store these in a different structure.  */
 | |
|   bfd			      *vn_bfd;		/* BFD.  */
 | |
|   const char                  *vn_filename;	/* vn_file as pointer.  */
 | |
|   struct elf_internal_vernaux *vn_auxptr;	/* vn_aux as pointer.  */
 | |
|   struct elf_internal_verneed *vn_nextref;	/* vn_nextref as pointer.  */
 | |
| } Elf_Internal_Verneed;
 | |
| 
 | |
| /* This structure appears in a SHT_GNU_verneed section.  */
 | |
| 
 | |
| typedef struct elf_internal_vernaux {
 | |
|   unsigned long	 vna_hash;	/* Hash of dependency name.  */
 | |
|   unsigned short vna_flags;	/* Flags (VER_FLG_*).  */
 | |
|   unsigned short vna_other;	/* Unused.  */
 | |
|   unsigned long	 vna_name;	/* String table offset to version name.  */
 | |
|   unsigned long	 vna_next;	/* Offset to next vernaux.  */
 | |
| 
 | |
|   /* These fields are set up when BFD reads in the structure.  FIXME:
 | |
|      It would be cleaner to store these in a different structure.  */
 | |
|   const char                  *vna_nodename;	/* vna_name as pointer.  */
 | |
|   struct elf_internal_vernaux *vna_nextptr;	/* vna_next as pointer.  */
 | |
| } Elf_Internal_Vernaux;
 | |
| 
 | |
| /* This structure appears in a SHT_GNU_versym section.  This is not a
 | |
|    standard ELF structure; ELF just uses Elf32_Half.  */
 | |
| 
 | |
| typedef struct elf_internal_versym {
 | |
|   unsigned short vs_vers;
 | |
| } Elf_Internal_Versym;
 | |
| 
 | |
| /* Structure for syminfo section.  */
 | |
| typedef struct
 | |
| {
 | |
|   unsigned short int 	si_boundto;
 | |
|   unsigned short int	si_flags;
 | |
| } Elf_Internal_Syminfo;
 | |
| 
 | |
| /* This structure appears on the stack and in NT_AUXV core file notes.  */
 | |
| typedef struct
 | |
| {
 | |
|   bfd_vma a_type;
 | |
|   bfd_vma a_val;
 | |
| } Elf_Internal_Auxv;
 | |
| 
 | |
| 
 | |
| /* This structure is used to describe how sections should be assigned
 | |
|    to program segments.  */
 | |
| 
 | |
| struct elf_segment_map
 | |
| {
 | |
|   /* Next program segment.  */
 | |
|   struct elf_segment_map *next;
 | |
|   /* Program segment type.  */
 | |
|   unsigned long p_type;
 | |
|   /* Program segment flags.  */
 | |
|   unsigned long p_flags;
 | |
|   /* Program segment physical address.  */
 | |
|   bfd_vma p_paddr;
 | |
|   /* Program segment virtual address offset from section vma.  */
 | |
|   bfd_vma p_vaddr_offset;
 | |
|   /* Program segment alignment.  */
 | |
|   bfd_vma p_align;
 | |
|   /* Segment size in file and memory */
 | |
|   bfd_vma p_size;
 | |
|   /* Required size of filehdr + phdrs, if non-zero */
 | |
|   bfd_vma header_size;
 | |
|   /* Whether the p_flags field is valid; if not, the flags are based
 | |
|      on the section flags.  */
 | |
|   unsigned int p_flags_valid : 1;
 | |
|   /* Whether the p_paddr field is valid; if not, the physical address
 | |
|      is based on the section lma values.  */
 | |
|   unsigned int p_paddr_valid : 1;
 | |
|   /* Whether the p_align field is valid; if not, PT_LOAD segment
 | |
|      alignment is based on the default maximum page size.  */
 | |
|   unsigned int p_align_valid : 1;
 | |
|   /* Whether the p_size field is valid; if not, the size are based
 | |
|      on the section sizes.  */
 | |
|   unsigned int p_size_valid : 1;
 | |
|   /* Whether this segment includes the file header.  */
 | |
|   unsigned int includes_filehdr : 1;
 | |
|   /* Whether this segment includes the program headers.  */
 | |
|   unsigned int includes_phdrs : 1;
 | |
|   /* Number of sections (may be 0).  */
 | |
|   unsigned int count;
 | |
|   /* Sections.  Actual number of elements is in count field.  */
 | |
|   asection *sections[1];
 | |
| };
 | |
| 
 | |
| /* .tbss is special.  It doesn't contribute memory space to normal
 | |
|    segments and it doesn't take file space in normal segments.  */
 | |
| #define ELF_TBSS_SPECIAL(sec_hdr, segment)			\
 | |
|   (((sec_hdr)->sh_flags & SHF_TLS) != 0				\
 | |
|    && (sec_hdr)->sh_type == SHT_NOBITS				\
 | |
|    && (segment)->p_type != PT_TLS)
 | |
| 
 | |
| #define ELF_SECTION_SIZE(sec_hdr, segment)			\
 | |
|   (ELF_TBSS_SPECIAL(sec_hdr, segment) ? 0 : (sec_hdr)->sh_size)
 | |
| 
 | |
| /* Decide if the section SEC_HDR is in SEGMENT.  If CHECK_VMA, then
 | |
|    VMAs are checked for alloc sections.  If STRICT, then a zero size
 | |
|    section won't match at the end of a segment, unless the segment
 | |
|    is also zero size.  Regardless of STRICT and CHECK_VMA, zero size
 | |
|    sections won't match at the start or end of PT_DYNAMIC, unless
 | |
|    PT_DYNAMIC is itself zero sized.  */
 | |
| #define ELF_SECTION_IN_SEGMENT_1(sec_hdr, segment, check_vma, strict)	\
 | |
|   ((/* Only PT_LOAD, PT_GNU_RELRO and PT_TLS segments can contain	\
 | |
|        SHF_TLS sections.  */						\
 | |
|     ((((sec_hdr)->sh_flags & SHF_TLS) != 0)				\
 | |
|      && ((segment)->p_type == PT_TLS					\
 | |
| 	 || (segment)->p_type == PT_GNU_RELRO				\
 | |
| 	 || (segment)->p_type == PT_LOAD))				\
 | |
|     /* PT_TLS segment contains only SHF_TLS sections, PT_PHDR no	\
 | |
|        sections at all.  */						\
 | |
|     || (((sec_hdr)->sh_flags & SHF_TLS) == 0				\
 | |
| 	&& (segment)->p_type != PT_TLS					\
 | |
| 	&& (segment)->p_type != PT_PHDR))				\
 | |
|    /* Any section besides one of type SHT_NOBITS must have file		\
 | |
|       offsets within the segment.  */					\
 | |
|    && ((sec_hdr)->sh_type == SHT_NOBITS					\
 | |
|        || ((bfd_vma) (sec_hdr)->sh_offset >= (segment)->p_offset	\
 | |
| 	   && (!(strict)						\
 | |
| 	       || ((sec_hdr)->sh_offset - (segment)->p_offset		\
 | |
| 		   <= (segment)->p_filesz - 1))				\
 | |
| 	   && (((sec_hdr)->sh_offset - (segment)->p_offset		\
 | |
| 		+ ELF_SECTION_SIZE(sec_hdr, segment))			\
 | |
| 	       <= (segment)->p_filesz)))				\
 | |
|    /* SHF_ALLOC sections must have VMAs within the segment.  */		\
 | |
|    && (!(check_vma)							\
 | |
|        || ((sec_hdr)->sh_flags & SHF_ALLOC) == 0			\
 | |
|        || ((sec_hdr)->sh_addr >= (segment)->p_vaddr			\
 | |
| 	   && (!(strict)						\
 | |
| 	       || ((sec_hdr)->sh_addr - (segment)->p_vaddr		\
 | |
| 		   <= (segment)->p_memsz - 1))				\
 | |
| 	   && (((sec_hdr)->sh_addr - (segment)->p_vaddr			\
 | |
| 		+ ELF_SECTION_SIZE(sec_hdr, segment))			\
 | |
| 	       <= (segment)->p_memsz)))					\
 | |
|    /* No zero size sections at start or end of PT_DYNAMIC.  */		\
 | |
|    && ((segment)->p_type != PT_DYNAMIC					\
 | |
|        || (sec_hdr)->sh_size != 0					\
 | |
|        || (segment)->p_memsz == 0					\
 | |
|        || (((sec_hdr)->sh_type == SHT_NOBITS				\
 | |
| 	    || ((bfd_vma) (sec_hdr)->sh_offset > (segment)->p_offset	\
 | |
| 	        && ((sec_hdr)->sh_offset - (segment)->p_offset		\
 | |
| 		    < (segment)->p_filesz)))				\
 | |
| 	   && (((sec_hdr)->sh_flags & SHF_ALLOC) == 0			\
 | |
| 	       || ((sec_hdr)->sh_addr > (segment)->p_vaddr		\
 | |
| 		   && ((sec_hdr)->sh_addr - (segment)->p_vaddr		\
 | |
| 		       < (segment)->p_memsz))))))
 | |
| 
 | |
| #define ELF_SECTION_IN_SEGMENT(sec_hdr, segment)			\
 | |
|   (ELF_SECTION_IN_SEGMENT_1 (sec_hdr, segment, 1, 0))
 | |
| 
 | |
| #define ELF_SECTION_IN_SEGMENT_STRICT(sec_hdr, segment)			\
 | |
|   (ELF_SECTION_IN_SEGMENT_1 (sec_hdr, segment, 1, 1))
 | |
| 
 | |
| #endif /* _ELF_INTERNAL_H */
 |