Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49e0b465 authored by Naveen N. Rao's avatar Naveen N. Rao Committed by Michael Ellerman
Browse files

kprobes: Convert kprobe_lookup_name() to a function



The macro is now pretty long and ugly on powerpc. In the light of further
changes needed here, convert it to a __weak variant to be over-ridden with a
nicer looking function.

Suggested-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Acked-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: default avatarNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent a460246c
Loading
Loading
Loading
Loading
+0 −53
Original line number Diff line number Diff line
@@ -61,59 +61,6 @@ extern kprobe_opcode_t optprobe_template_end[];
#define MAX_OPTINSN_SIZE	(optprobe_template_end - optprobe_template_entry)
#define RELATIVEJUMP_SIZE	sizeof(kprobe_opcode_t)	/* 4 bytes */

#ifdef PPC64_ELF_ABI_v2
/* PPC64 ABIv2 needs local entry point */
#define kprobe_lookup_name(name, addr)					\
{									\
	addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);		\
	if (addr)							\
		addr = (kprobe_opcode_t *)ppc_function_entry(addr);	\
}
#elif defined(PPC64_ELF_ABI_v1)
/*
 * 64bit powerpc ABIv1 uses function descriptors:
 * - Check for the dot variant of the symbol first.
 * - If that fails, try looking up the symbol provided.
 *
 * This ensures we always get to the actual symbol and not the descriptor.
 * Also handle <module:symbol> format.
 */
#define kprobe_lookup_name(name, addr)					\
{									\
	char dot_name[MODULE_NAME_LEN + 1 + KSYM_NAME_LEN];		\
	const char *modsym;							\
	bool dot_appended = false;					\
	if ((modsym = strchr(name, ':')) != NULL) {			\
		modsym++;						\
		if (*modsym != '\0' && *modsym != '.') {		\
			/* Convert to <module:.symbol> */		\
			strncpy(dot_name, name, modsym - name);		\
			dot_name[modsym - name] = '.';			\
			dot_name[modsym - name + 1] = '\0';		\
			strncat(dot_name, modsym,			\
				sizeof(dot_name) - (modsym - name) - 2);\
			dot_appended = true;				\
		} else {						\
			dot_name[0] = '\0';				\
			strncat(dot_name, name, sizeof(dot_name) - 1);	\
		}							\
	} else if (name[0] != '.') {					\
		dot_name[0] = '.';					\
		dot_name[1] = '\0';					\
		strncat(dot_name, name, KSYM_NAME_LEN - 2);		\
		dot_appended = true;					\
	} else {							\
		dot_name[0] = '\0';					\
		strncat(dot_name, name, KSYM_NAME_LEN - 1);		\
	}								\
	addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name);	\
	if (!addr && dot_appended) {					\
		/* Let's try the original non-dot symbol lookup	*/	\
		addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);	\
	}								\
}
#endif

#define flush_insn_slot(p)	do { } while (0)
#define kretprobe_blacklist_size 0

+58 −0
Original line number Diff line number Diff line
@@ -42,6 +42,64 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);

struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};

kprobe_opcode_t *kprobe_lookup_name(const char *name)
{
	kprobe_opcode_t *addr;

#ifdef PPC64_ELF_ABI_v2
	/* PPC64 ABIv2 needs local entry point */
	addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);
	if (addr)
		addr = (kprobe_opcode_t *)ppc_function_entry(addr);
#elif defined(PPC64_ELF_ABI_v1)
	/*
	 * 64bit powerpc ABIv1 uses function descriptors:
	 * - Check for the dot variant of the symbol first.
	 * - If that fails, try looking up the symbol provided.
	 *
	 * This ensures we always get to the actual symbol and not
	 * the descriptor.
	 *
	 * Also handle <module:symbol> format.
	 */
	char dot_name[MODULE_NAME_LEN + 1 + KSYM_NAME_LEN];
	const char *modsym;
	bool dot_appended = false;
	if ((modsym = strchr(name, ':')) != NULL) {
		modsym++;
		if (*modsym != '\0' && *modsym != '.') {
			/* Convert to <module:.symbol> */
			strncpy(dot_name, name, modsym - name);
			dot_name[modsym - name] = '.';
			dot_name[modsym - name + 1] = '\0';
			strncat(dot_name, modsym,
				sizeof(dot_name) - (modsym - name) - 2);
			dot_appended = true;
		} else {
			dot_name[0] = '\0';
			strncat(dot_name, name, sizeof(dot_name) - 1);
		}
	} else if (name[0] != '.') {
		dot_name[0] = '.';
		dot_name[1] = '\0';
		strncat(dot_name, name, KSYM_NAME_LEN - 2);
		dot_appended = true;
	} else {
		dot_name[0] = '\0';
		strncat(dot_name, name, KSYM_NAME_LEN - 1);
	}
	addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name);
	if (!addr && dot_appended) {
		/* Let's try the original non-dot symbol lookup	*/
		addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);
	}
#else
	addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);
#endif

	return addr;
}

int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
	int ret = 0;
+2 −2
Original line number Diff line number Diff line
@@ -243,8 +243,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
	/*
	 * 2. branch to optimized_callback() and emulate_step()
	 */
	kprobe_lookup_name("optimized_callback", op_callback_addr);
	kprobe_lookup_name("emulate_step", emulate_step_addr);
	op_callback_addr = kprobe_lookup_name("optimized_callback");
	emulate_step_addr = kprobe_lookup_name("emulate_step");
	if (!op_callback_addr || !emulate_step_addr) {
		WARN(1, "kprobe_lookup_name() failed\n");
		goto error;
+1 −0
Original line number Diff line number Diff line
@@ -379,6 +379,7 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
	return this_cpu_ptr(&kprobe_ctlblk);
}

kprobe_opcode_t *kprobe_lookup_name(const char *name);
int register_kprobe(struct kprobe *p);
void unregister_kprobe(struct kprobe *p);
int register_kprobes(struct kprobe **kps, int num);
+8 −12
Original line number Diff line number Diff line
@@ -58,15 +58,6 @@
#define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)


/*
 * Some oddball architectures like 64bit powerpc have function descriptors
 * so this must be overridable.
 */
#ifndef kprobe_lookup_name
#define kprobe_lookup_name(name, addr) \
	addr = ((kprobe_opcode_t *)(kallsyms_lookup_name(name)))
#endif

static int kprobes_initialized;
static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
@@ -81,6 +72,11 @@ static struct {
	raw_spinlock_t lock ____cacheline_aligned_in_smp;
} kretprobe_table_locks[KPROBE_TABLE_SIZE];

kprobe_opcode_t * __weak kprobe_lookup_name(const char *name)
{
	return ((kprobe_opcode_t *)(kallsyms_lookup_name(name)));
}

static raw_spinlock_t *kretprobe_table_lock_ptr(unsigned long hash)
{
	return &(kretprobe_table_locks[hash].lock);
@@ -1407,7 +1403,7 @@ static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
		goto invalid;

	if (p->symbol_name) {
		kprobe_lookup_name(p->symbol_name, addr);
		addr = kprobe_lookup_name(p->symbol_name);
		if (!addr)
			return ERR_PTR(-ENOENT);
	}
@@ -2199,8 +2195,8 @@ static int __init init_kprobes(void)
	if (kretprobe_blacklist_size) {
		/* lookup the function address from its name */
		for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
			kprobe_lookup_name(kretprobe_blacklist[i].name,
					   kretprobe_blacklist[i].addr);
			kretprobe_blacklist[i].addr =
				kprobe_lookup_name(kretprobe_blacklist[i].name);
			if (!kretprobe_blacklist[i].addr)
				printk("kretprobe: lookup failed: %s\n",
				       kretprobe_blacklist[i].name);