/* Check we can represent the target in the instruction format */ if (!is_offset_in_branch_range(offset)) return 1;
/* Mask out the flags and target, so they don't step on each other. */
*instr = ppc_inst(0x48000000 | (flags & 0x3) | (offset & 0x03FFFFFC));
return 0;
}
int create_cond_branch(ppc_inst_t *instr, const u32 *addr, unsignedlong target, int flags); int patch_branch(u32 *addr, unsignedlong target, int flags); int patch_instruction(u32 *addr, ppc_inst_t instr); int raw_patch_instruction(u32 *addr, ppc_inst_t instr); int patch_instructions(u32 *addr, u32 *code, size_t len, bool repeat_instr);
/* * The data patching functions patch_uint() and patch_ulong(), etc., must be * called on aligned addresses. * * The instruction patching functions patch_instruction() and similar must be * called on addresses satisfying instruction alignment requirements.
*/
#ifdef CONFIG_PPC64
int patch_uint(void *addr, unsignedint val); int patch_ulong(void *addr, unsignedlong val);
/* * A PPC64 ABIv2 function may have a local and a global entry * point. We need to use the local entry point when patching * functions, so identify and step over the global entry point * sequence. * * The global entry point sequence is always of the form: * * addis r2,r12,XXXX * addi r2,r2,XXXX * * A linker optimisation may convert the addis to lis: * * lis r2,XXXX * addi r2,r2,XXXX
*/ if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2)) return (unsignedlong)(insn + 2); else return (unsignedlong)func; #elifdefined(CONFIG_PPC64_ELF_ABI_V1) /* * On PPC64 ABIv1 the function pointer actually points to the * function's descriptor. The first entry in the descriptor is the * address of the function text.
*/ return ((struct func_desc *)func)->addr; #else return (unsignedlong)func; #endif
}
staticinlineunsignedlong ppc_global_function_entry(void *func)
{ #ifdef CONFIG_PPC64_ELF_ABI_V2 /* PPC64 ABIv2 the global entry point is at the address */ return (unsignedlong)func; #else /* All other cases there is no change vs ppc_function_entry() */ return ppc_function_entry(func); #endif
}
/* * Wrapper around kallsyms_lookup() to return function entry address: * - For ABIv1, we lookup the dot variant. * - For ABIv2, we return the local entry point.
*/ staticinlineunsignedlong ppc_kallsyms_lookup_name(constchar *name)
{ unsignedlong addr; #ifdef CONFIG_PPC64_ELF_ABI_V1 /* check for dot variant */ char dot_name[1 + KSYM_NAME_LEN]; bool dot_appended = false;
if (strnlen(name, KSYM_NAME_LEN) >= KSYM_NAME_LEN) return 0;
/* * Some instruction encodings commonly used in dynamic ftracing * and function live patching.
*/
/* This must match the definition of STK_GOT in <asm/ppc_asm.h> */ #ifdef CONFIG_PPC64_ELF_ABI_V2 #define R2_STACK_OFFSET 24 #else #define R2_STACK_OFFSET 40 #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.