FreeBSD/libexec/rtld-elf/powerpc64/reloc.c
/*
 * Relocate a non-PLT object with addend.
 */
Relocate a non-PLT object with addend.
Relocate a non - PLT object with addend .
static int
reloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
    SymCache *cache, int flags, RtldLockState *lockstate)
{
	Elf_Addr        *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
	const Elf_Sym   *def;
	const Obj_Entry *defobj;
	Elf_Addr         tmp;
	switch (ELF_R_TYPE(rela->r_info)) {
	case R_PPC_NONE:
		break;
        case R_PPC64_UADDR64:    
        case R_PPC64_ADDR64:
        case R_PPC_GLOB_DAT:
		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
		    flags, cache, lockstate);
		if (def == NULL) {
			return (-1);
		}
                tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
                    rela->r_addend);
                if (*where != tmp) {
                        *where = tmp;
		}
                break;
        case R_PPC_RELATIVE:  
		tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
		if (*where != tmp) {
			*where = tmp;
		}
		break;
	case R_PPC_COPY:
		if (!obj->mainprog) {
			_rtld_error("%s: Unexpected R_COPY "
				    " relocation in shared library",
				    obj->path);
			return (-1);
		}
		break;
	case R_PPC_JMP_SLOT:
		break;
	case R_PPC64_DTPMOD64:
		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
		    flags, cache, lockstate);
		if (def == NULL)
			return (-1);
		*where = (Elf_Addr) defobj->tlsindex;
		break;
	case R_PPC64_TPREL64:
		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
		    flags, cache, lockstate);
		if (def == NULL)
			return (-1);
		if (!defobj->tls_done) {
			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
				_rtld_error("%s: No space available for static "
				    "Thread Local Storage", obj->path);
				return (-1);
			}
		}
		*(Elf_Addr **)where = *where * sizeof(Elf_Addr)
		    + (Elf_Addr *)(def->st_value + rela->r_addend
		    + defobj->tlsoffset - TLS_TP_OFFSET);
		break;
	case R_PPC64_DTPREL64:
		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
		    flags, cache, lockstate);
		if (def == NULL)
			return (-1);
		*where += (Elf_Addr)(def->st_value + rela->r_addend
		    - TLS_DTV_OFFSET);
		break;
	default:
		_rtld_error("%s: Unsupported relocation type %ld"
			    " in non-PLT relocations\n", obj->path,
			    ELF_R_TYPE(rela->r_info));
		return (-1);
        }
	return (0);
}
static int reloc_nonplt_object ( Obj_Entry * obj_rtld , Obj_Entry * obj , const Elf_Rela * rela , SymCache * cache , int flags , RtldLockState * lockstate ) { Elf_Addr * where = ( Elf_Addr * ) ( obj -> relocbase + rela -> r_offset ) ; const Elf_Sym * def ; const Obj_Entry * defobj ; Elf_Addr tmp ; switch ( ELF_R_TYPE ( rela -> r_info ) ) { case R_PPC_NONE : break ; case R_PPC64_UADDR64 : case R_PPC64_ADDR64 : case R_PPC_GLOB_DAT : def = find_symdef ( ELF_R_SYM ( rela -> r_info ) , obj , & defobj , flags , cache , lockstate ) ; if ( def == NULL ) { return ( -1 ) ; } tmp = ( Elf_Addr ) ( defobj -> relocbase + def -> st_value + rela -> r_addend ) ; if ( * where != tmp ) { * where = tmp ; } break ; case R_PPC_RELATIVE : tmp = ( Elf_Addr ) ( obj -> relocbase + rela -> r_addend ) ; if ( * where != tmp ) { * where = tmp ; } break ; case R_PPC_COPY : if ( ! obj -> mainprog ) { _rtld_error ( " " " " , obj -> path ) ; return ( -1 ) ; } break ; case R_PPC_JMP_SLOT : break ; case R_PPC64_DTPMOD64 : def = find_symdef ( ELF_R_SYM ( rela -> r_info ) , obj , & defobj , flags , cache , lockstate ) ; if ( def == NULL ) return ( -1 ) ; * where = ( Elf_Addr ) defobj -> tlsindex ; break ; case R_PPC64_TPREL64 : def = find_symdef ( ELF_R_SYM ( rela -> r_info ) , obj , & defobj , flags , cache , lockstate ) ; if ( def == NULL ) return ( -1 ) ; if ( ! defobj -> tls_done ) { if ( ! allocate_tls_offset ( ( Obj_Entry * ) defobj ) ) { _rtld_error ( " " " " , obj -> path ) ; return ( -1 ) ; } } * ( Elf_Addr * * ) where = * where * sizeof ( Elf_Addr ) + ( Elf_Addr * ) ( def -> st_value + rela -> r_addend + defobj -> tlsoffset - TLS_TP_OFFSET ) ; break ; case R_PPC64_DTPREL64 : def = find_symdef ( ELF_R_SYM ( rela -> r_info ) , obj , & defobj , flags , cache , lockstate ) ; if ( def == NULL ) return ( -1 ) ; * where += ( Elf_Addr ) ( def -> st_value + rela -> r_addend - TLS_DTV_OFFSET ) ; break ; default : _rtld_error ( " " " \n " , obj -> path , ELF_R_TYPE ( rela -> r_info ) ) ; return ( -1 ) ; } return ( 0 ) ; }
Relocate a non-PLT object with addend.
Relocate a non - PLT object with addend .
/* doubleword64 S + A */ /* Don't issue write if unnecessary; avoid COW page fault */ /* doubleword64 B + A */ /* As above, don't issue write unnecessarily */ /*
		 * These are deferred until all other relocations
		 * have been done.  All we do here is make sure
		 * that the COPY relocation is not in a shared
		 * library.  They are allowed only in executable
		 * files.
		 */ /*
		 * These will be handled by the plt/jmpslot routines
		 */ /*
		 * We lazily allocate offsets for static TLS as we
		 * see the first relocation that references the
		 * TLS block. This allows us to support (small
		 * amounts of) static TLS in dynamically loaded
		 * modules. If we run out of space, we generate an
		 * error.
		 */