FreeBSD/sys/i386/i386/elf_machdep.c
/* Process one elf relocation with addend. */
Process one elf relocation with addend.
Process one elf relocation with addend .
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
    int type, int local, elf_lookup_fn lookup)
{
	Elf_Addr *where;
	Elf_Addr addr;
	Elf_Addr addend;
	Elf_Word rtype, symidx;
	const Elf_Rel *rel;
	const Elf_Rela *rela;
	int error;
	switch (type) {
	case ELF_RELOC_REL:
		rel = (const Elf_Rel *)data;
		where = (Elf_Addr *) (relocbase + rel->r_offset);
		addend = *where;
		rtype = ELF_R_TYPE(rel->r_info);
		symidx = ELF_R_SYM(rel->r_info);
		break;
	case ELF_RELOC_RELA:
		rela = (const Elf_Rela *)data;
		where = (Elf_Addr *) (relocbase + rela->r_offset);
		addend = rela->r_addend;
		rtype = ELF_R_TYPE(rela->r_info);
		symidx = ELF_R_SYM(rela->r_info);
		break;
	default:
		panic("unknown reloc type %d\n", type);
	}
	if (local) {
		if (rtype == R_386_RELATIVE) {	
			addr = elf_relocaddr(lf, relocbase + addend);
			if (*where != addr)
				*where = addr;
		}
		return (0);
	}
	switch (rtype) {
		case R_386_NONE:	
			break;
		case R_386_32:		
			error = lookup(lf, symidx, 1, &addr);
			if (error != 0)
				return -1;
			addr += addend;
			if (*where != addr)
				*where = addr;
			break;
		case R_386_PC32:	
			error = lookup(lf, symidx, 1, &addr);
			if (error != 0)
				return -1;
			addr += addend - (Elf_Addr)where;
			if (*where != addr)
				*where = addr;
			break;
		case R_386_COPY:	
			printf("kldload: unexpected R_COPY relocation\n");
			return -1;
			break;
		case R_386_GLOB_DAT:	
			error = lookup(lf, symidx, 1, &addr);
			if (error != 0)
				return -1;
			if (*where != addr)
				*where = addr;
			break;
		case R_386_RELATIVE:
			break;
		default:
			printf("kldload: unexpected relocation type %d\n",
			       rtype);
			return -1;
	}
	return(0);
}
static int elf_reloc_internal ( linker_file_t lf , Elf_Addr relocbase , const void * data , int type , int local , elf_lookup_fn lookup ) { Elf_Addr * where ; Elf_Addr addr ; Elf_Addr addend ; Elf_Word rtype , symidx ; const Elf_Rel * rel ; const Elf_Rela * rela ; int error ; switch ( type ) { case ELF_RELOC_REL : rel = ( const Elf_Rel * ) data ; where = ( Elf_Addr * ) ( relocbase + rel -> r_offset ) ; addend = * where ; rtype = ELF_R_TYPE ( rel -> r_info ) ; symidx = ELF_R_SYM ( rel -> r_info ) ; break ; case ELF_RELOC_RELA : rela = ( const Elf_Rela * ) data ; where = ( Elf_Addr * ) ( relocbase + rela -> r_offset ) ; addend = rela -> r_addend ; rtype = ELF_R_TYPE ( rela -> r_info ) ; symidx = ELF_R_SYM ( rela -> r_info ) ; break ; default : panic ( " \n " , type ) ; } if ( local ) { if ( rtype == R_386_RELATIVE ) { addr = elf_relocaddr ( lf , relocbase + addend ) ; if ( * where != addr ) * where = addr ; } return ( 0 ) ; } switch ( rtype ) { case R_386_NONE : break ; case R_386_32 : error = lookup ( lf , symidx , 1 , & addr ) ; if ( error != 0 ) return -1 ; addr += addend ; if ( * where != addr ) * where = addr ; break ; case R_386_PC32 : error = lookup ( lf , symidx , 1 , & addr ) ; if ( error != 0 ) return -1 ; addr += addend - ( Elf_Addr ) where ; if ( * where != addr ) * where = addr ; break ; case R_386_COPY : printf ( " \n " ) ; return -1 ; break ; case R_386_GLOB_DAT : error = lookup ( lf , symidx , 1 , & addr ) ; if ( error != 0 ) return -1 ; if ( * where != addr ) * where = addr ; break ; case R_386_RELATIVE : break ; default : printf ( " \n " , rtype ) ; return -1 ; } return ( 0 ) ; }
Process one elf relocation with addend.
Process one elf relocation with addend .
/* A + B */ /* none */ /* S + A */ /* S + A - P */ /* none */ /*
			 * There shouldn't be copy relocations in kernel
			 * objects.
			 */ /* S */