FreeBSD/contrib/binutils/binutils/readelf.c
/* Apply addends of RELA relocations.  */
Apply addends of RELA relocations.
Apply addends of RELA relocations .
static int
debug_apply_rela_addends (void *file,
			  Elf_Internal_Shdr *section,
			  unsigned char *start)
{
  Elf_Internal_Shdr *relsec;
  unsigned char *end = start + section->sh_size;
  if (!is_relocatable)
    return 1;
  if (elf_header.e_machine == EM_SH)
    return 0;
  for (relsec = section_headers;
       relsec < section_headers + elf_header.e_shnum;
       ++relsec)
    {
      unsigned long nrelas;
      Elf_Internal_Rela *rela, *rp;
      Elf_Internal_Shdr *symsec;
      Elf_Internal_Sym *symtab;
      Elf_Internal_Sym *sym;
      if (relsec->sh_type != SHT_RELA
	  || SECTION_HEADER_INDEX (relsec->sh_info) >= elf_header.e_shnum
	  || SECTION_HEADER (relsec->sh_info) != section
	  || relsec->sh_size == 0
	  || SECTION_HEADER_INDEX (relsec->sh_link) >= elf_header.e_shnum)
	continue;
      if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
			      &rela, &nrelas))
	return 0;
      symsec = SECTION_HEADER (relsec->sh_link);
      symtab = GET_ELF_SYMBOLS (file, symsec);
      for (rp = rela; rp < rela + nrelas; ++rp)
	{
	  unsigned char *loc;
	  unsigned int reloc_size;
	  reloc_size = get_reloc_size (rp);
	  if (reloc_size == 0)
	    {
	      warn (_("skipping relocation of unknown size against offset 0x%lx in section %s\n"),
		    (unsigned long) rp->r_offset,
		    SECTION_NAME (section));
	      continue;
	    }
	  loc = start + rp->r_offset;
	  if ((loc + reloc_size) > end)
	    {
	      warn (_("skipping invalid relocation offset 0x%lx in section %s\n"),
		    (unsigned long) rp->r_offset,
		    SECTION_NAME (section));
	      continue;
	    }
	  if (is_32bit_elf)
	    {
	      sym = symtab + ELF32_R_SYM (rp->r_info);
	      if (ELF32_R_SYM (rp->r_info) != 0
		  && ELF32_ST_TYPE (sym->st_info) != STT_SECTION
		  && ELF32_ST_TYPE (sym->st_info) != STT_NOTYPE
		  && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT)
		{
		  warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"),
			get_symbol_type (ELF32_ST_TYPE (sym->st_info)),
			SECTION_NAME (section));
		  continue;
		}
	    }
	  else
	    {
	      if (elf_header.e_machine == EM_MIPS
		  && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
		rp->r_info = (((rp->r_info & 0xffffffff) << 32)
			      | ((rp->r_info >> 56) & 0xff)
			      | ((rp->r_info >> 40) & 0xff00)
			      | ((rp->r_info >> 24) & 0xff0000)
			      | ((rp->r_info >> 8) & 0xff000000));
	      sym = symtab + ELF64_R_SYM (rp->r_info);
	      if (ELF64_R_SYM (rp->r_info) != 0
		  && ELF64_ST_TYPE (sym->st_info) != STT_SECTION
		  && ELF64_ST_TYPE (sym->st_info) != STT_NOTYPE
		  && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT)
		{
		  warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"),
			get_symbol_type (ELF64_ST_TYPE (sym->st_info)),
			SECTION_NAME (section));
		  continue;
		}
	    }
	  byte_put (loc, rp->r_addend, reloc_size);
	}
      free (symtab);
      free (rela);
      break;
    }
  return 1;
}
static int debug_apply_rela_addends ( void * file , Elf_Internal_Shdr * section , unsigned char * start ) { Elf_Internal_Shdr * relsec ; unsigned char * end = start + section -> sh_size ; if ( ! is_relocatable ) return 1 ; if ( elf_header . e_machine == EM_SH ) return 0 ; for ( relsec = section_headers ; relsec < section_headers + elf_header . e_shnum ; ++ relsec ) { unsigned long nrelas ; Elf_Internal_Rela * rela , * rp ; Elf_Internal_Shdr * symsec ; Elf_Internal_Sym * symtab ; Elf_Internal_Sym * sym ; if ( relsec -> sh_type != SHT_RELA || SECTION_HEADER_INDEX ( relsec -> sh_info ) >= elf_header . e_shnum || SECTION_HEADER ( relsec -> sh_info ) != section || relsec -> sh_size == 0 || SECTION_HEADER_INDEX ( relsec -> sh_link ) >= elf_header . e_shnum ) continue ; if ( ! slurp_rela_relocs ( file , relsec -> sh_offset , relsec -> sh_size , & rela , & nrelas ) ) return 0 ; symsec = SECTION_HEADER ( relsec -> sh_link ) ; symtab = GET_ELF_SYMBOLS ( file , symsec ) ; for ( rp = rela ; rp < rela + nrelas ; ++ rp ) { unsigned char * loc ; unsigned int reloc_size ; reloc_size = get_reloc_size ( rp ) ; if ( reloc_size == 0 ) { warn ( _ ( " \n " ) , ( unsigned long ) rp -> r_offset , SECTION_NAME ( section ) ) ; continue ; } loc = start + rp -> r_offset ; if ( ( loc + reloc_size ) > end ) { warn ( _ ( " \n " ) , ( unsigned long ) rp -> r_offset , SECTION_NAME ( section ) ) ; continue ; } if ( is_32bit_elf ) { sym = symtab + ELF32_R_SYM ( rp -> r_info ) ; if ( ELF32_R_SYM ( rp -> r_info ) != 0 && ELF32_ST_TYPE ( sym -> st_info ) != STT_SECTION && ELF32_ST_TYPE ( sym -> st_info ) != STT_NOTYPE && ELF32_ST_TYPE ( sym -> st_info ) != STT_OBJECT ) { warn ( _ ( " \n " ) , get_symbol_type ( ELF32_ST_TYPE ( sym -> st_info ) ) , SECTION_NAME ( section ) ) ; continue ; } } else { if ( elf_header . e_machine == EM_MIPS && elf_header . e_ident [ EI_DATA ] != ELFDATA2MSB ) rp -> r_info = ( ( ( rp -> r_info & 0xffffffff ) << 32 ) | ( ( rp -> r_info >> 56 ) & 0xff ) | ( ( rp -> r_info >> 40 ) & 0xff00 ) | ( ( rp -> r_info >> 24 ) & 0xff0000 ) | ( ( rp -> r_info >> 8 ) & 0xff000000 ) ) ; sym = symtab + ELF64_R_SYM ( rp -> r_info ) ; if ( ELF64_R_SYM ( rp -> r_info ) != 0 && ELF64_ST_TYPE ( sym -> st_info ) != STT_SECTION && ELF64_ST_TYPE ( sym -> st_info ) != STT_NOTYPE && ELF64_ST_TYPE ( sym -> st_info ) != STT_OBJECT ) { warn ( _ ( " \n " ) , get_symbol_type ( ELF64_ST_TYPE ( sym -> st_info ) ) , SECTION_NAME ( section ) ) ; continue ; } } byte_put ( loc , rp -> r_addend , reloc_size ) ; } free ( symtab ) ; free ( rela ) ; break ; } return 1 ; }
Apply addends of RELA relocations.
Apply addends of RELA relocations .
/* SH uses RELA but uses in place value instead of the addend field.  */ /* Relocations against symbols without type can happen.
		     Gcc -feliminate-dwarf2-dups may generate symbols
		     without type for debug info.  */ /* Relocations against object symbols can happen,
		     eg when referencing a global array.  For an
		     example of this see the _clz.o binary in libgcc.a.  */ /* In MIPS little-endian objects, r_info isn't really a
		 64-bit little-endian value: it has a 32-bit little-endian
		 symbol index followed by four individual byte fields.
		 Reorder INFO accordingly.  */