FreeBSD/sys/sparc64/sparc64/elf_machdep.c
/* Process one elf relocation with addend. */
Process one elf relocation with addend.
Process one elf relocation with addend .
int
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
    elf_lookup_fn lookup)
{
	const Elf_Rela *rela;
	Elf_Word *where32;
	Elf_Addr *where;
	Elf_Size rtype, symidx;
	Elf_Addr value;
	Elf_Addr mask;
	Elf_Addr addr;
	int error;
	if (type != ELF_RELOC_RELA)
		return (-1);
	rela = (const Elf_Rela *)data;
	where = (Elf_Addr *)(relocbase + rela->r_offset);
	where32 = (Elf_Word *)where;
	rtype = ELF64_R_TYPE_ID(rela->r_info);
	symidx = ELF_R_SYM(rela->r_info);
	if (rtype == R_SPARC_NONE || rtype == R_SPARC_RELATIVE)
		return (0);
	if (rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY ||
	    rtype >= nitems(reloc_target_bitmask)) {
		printf("kldload: unexpected relocation type %ld\n", rtype);
		return (-1);
	}
	if (RELOC_UNALIGNED(rtype)) {
		printf("kldload: unaligned relocation type %ld\n", rtype);
		return (-1);
	}
	value = rela->r_addend;
	if (RELOC_RESOLVE_SYMBOL(rtype)) {
		error = lookup(lf, symidx, 1, &addr);
		if (error != 0)
			return (-1);
		value += addr;
		if (RELOC_BARE_SYMBOL(rtype))
			value = elf_relocaddr(lf, value);
	}
	if (rtype == R_SPARC_OLO10)
		value = (value & 0x3ff) + ELF64_R_TYPE_DATA(rela->r_info);
	if (rtype == R_SPARC_HIX22)
		value ^= 0xffffffffffffffff;
	if (RELOC_PC_RELATIVE(rtype))
		value -= (Elf_Addr)where;
	if (RELOC_BASE_RELATIVE(rtype))
		value = elf_relocaddr(lf, value + relocbase);
	mask = RELOC_VALUE_BITMASK(rtype);
	value >>= RELOC_VALUE_RIGHTSHIFT(rtype);
	value &= mask;
	if (rtype == R_SPARC_LOX10)
		value |= 0x1c00;
	if (RELOC_TARGET_SIZE(rtype) > 32) {
		*where &= ~mask;
		*where |= value;
	} else {
		*where32 &= ~mask;
		*where32 |= value;
	}
	return (0);
}
int elf_reloc ( linker_file_t lf , Elf_Addr relocbase , const void * data , int type , elf_lookup_fn lookup ) { const Elf_Rela * rela ; Elf_Word * where32 ; Elf_Addr * where ; Elf_Size rtype , symidx ; Elf_Addr value ; Elf_Addr mask ; Elf_Addr addr ; int error ; if ( type != ELF_RELOC_RELA ) return ( -1 ) ; rela = ( const Elf_Rela * ) data ; where = ( Elf_Addr * ) ( relocbase + rela -> r_offset ) ; where32 = ( Elf_Word * ) where ; rtype = ELF64_R_TYPE_ID ( rela -> r_info ) ; symidx = ELF_R_SYM ( rela -> r_info ) ; if ( rtype == R_SPARC_NONE || rtype == R_SPARC_RELATIVE ) return ( 0 ) ; if ( rtype == R_SPARC_JMP_SLOT || rtype == R_SPARC_COPY || rtype >= nitems ( reloc_target_bitmask ) ) { printf ( " \n " , rtype ) ; return ( -1 ) ; } if ( RELOC_UNALIGNED ( rtype ) ) { printf ( " \n " , rtype ) ; return ( -1 ) ; } value = rela -> r_addend ; if ( RELOC_RESOLVE_SYMBOL ( rtype ) ) { error = lookup ( lf , symidx , 1 , & addr ) ; if ( error != 0 ) return ( -1 ) ; value += addr ; if ( RELOC_BARE_SYMBOL ( rtype ) ) value = elf_relocaddr ( lf , value ) ; } if ( rtype == R_SPARC_OLO10 ) value = ( value & 0x3ff ) + ELF64_R_TYPE_DATA ( rela -> r_info ) ; if ( rtype == R_SPARC_HIX22 ) value ^= 0xffffffffffffffff ; if ( RELOC_PC_RELATIVE ( rtype ) ) value -= ( Elf_Addr ) where ; if ( RELOC_BASE_RELATIVE ( rtype ) ) value = elf_relocaddr ( lf , value + relocbase ) ; mask = RELOC_VALUE_BITMASK ( rtype ) ; value >>= RELOC_VALUE_RIGHTSHIFT ( rtype ) ; value &= mask ; if ( rtype == R_SPARC_LOX10 ) value |= 0x1c00 ; if ( RELOC_TARGET_SIZE ( rtype ) > 32 ) { * where &= ~ mask ; * where |= value ; } else { * where32 &= ~ mask ; * where32 |= value ; } return ( 0 ) ; }
Process one elf relocation with addend.
Process one elf relocation with addend .