Commit 290e3070 authored by Naveen N. Rao's avatar Naveen N. Rao Committed by Michael Ellerman

powerpc/kprobes: Fix handling of function offsets on ABIv2

commit 239aeba7 ("perf powerpc: Fix kprobe and kretprobe handling with
kallsyms on ppc64le") changed how we use the offset field in struct kprobe on
ABIv2. perf now offsets from the global entry point if an offset is specified
and otherwise chooses the local entry point.

Fix the same in kernel for kprobe API users. We do this by extending
kprobe_lookup_name() to accept an additional parameter to indicate the offset
specified with the kprobe registration. If offset is 0, we return the local
function entry and return the global entry point otherwise.

With:
  # cd /sys/kernel/debug/tracing/
  # echo "p _do_fork" >> kprobe_events
  # echo "p _do_fork+0x10" >> kprobe_events

before this patch:
  # cat ../kprobes/list
  c0000000000d0748  k  _do_fork+0x8    [DISABLED]
  c0000000000d0758  k  _do_fork+0x18    [DISABLED]
  c0000000000412b0  k  kretprobe_trampoline+0x0    [OPTIMIZED]

and after:
  # cat ../kprobes/list
  c0000000000d04c8  k  _do_fork+0x8    [DISABLED]
  c0000000000d04d0  k  _do_fork+0x10    [DISABLED]
  c0000000000412b0  k  kretprobe_trampoline+0x0    [OPTIMIZED]
Acked-by: default avatarAnanth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
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 49e0b465
...@@ -42,14 +42,14 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); ...@@ -42,14 +42,14 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
kprobe_opcode_t *kprobe_lookup_name(const char *name) kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset)
{ {
kprobe_opcode_t *addr; kprobe_opcode_t *addr;
#ifdef PPC64_ELF_ABI_v2 #ifdef PPC64_ELF_ABI_v2
/* PPC64 ABIv2 needs local entry point */ /* PPC64 ABIv2 needs local entry point */
addr = (kprobe_opcode_t *)kallsyms_lookup_name(name); addr = (kprobe_opcode_t *)kallsyms_lookup_name(name);
if (addr) if (addr && !offset)
addr = (kprobe_opcode_t *)ppc_function_entry(addr); addr = (kprobe_opcode_t *)ppc_function_entry(addr);
#elif defined(PPC64_ELF_ABI_v1) #elif defined(PPC64_ELF_ABI_v1)
/* /*
......
...@@ -243,8 +243,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p) ...@@ -243,8 +243,8 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
/* /*
* 2. branch to optimized_callback() and emulate_step() * 2. branch to optimized_callback() and emulate_step()
*/ */
op_callback_addr = kprobe_lookup_name("optimized_callback"); op_callback_addr = kprobe_lookup_name("optimized_callback", 0);
emulate_step_addr = kprobe_lookup_name("emulate_step"); emulate_step_addr = kprobe_lookup_name("emulate_step", 0);
if (!op_callback_addr || !emulate_step_addr) { if (!op_callback_addr || !emulate_step_addr) {
WARN(1, "kprobe_lookup_name() failed\n"); WARN(1, "kprobe_lookup_name() failed\n");
goto error; goto error;
......
...@@ -379,7 +379,7 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) ...@@ -379,7 +379,7 @@ static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
return this_cpu_ptr(&kprobe_ctlblk); return this_cpu_ptr(&kprobe_ctlblk);
} }
kprobe_opcode_t *kprobe_lookup_name(const char *name); kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset);
int register_kprobe(struct kprobe *p); int register_kprobe(struct kprobe *p);
void unregister_kprobe(struct kprobe *p); void unregister_kprobe(struct kprobe *p);
int register_kprobes(struct kprobe **kps, int num); int register_kprobes(struct kprobe **kps, int num);
......
...@@ -72,7 +72,8 @@ static struct { ...@@ -72,7 +72,8 @@ static struct {
raw_spinlock_t lock ____cacheline_aligned_in_smp; raw_spinlock_t lock ____cacheline_aligned_in_smp;
} kretprobe_table_locks[KPROBE_TABLE_SIZE]; } kretprobe_table_locks[KPROBE_TABLE_SIZE];
kprobe_opcode_t * __weak kprobe_lookup_name(const char *name) kprobe_opcode_t * __weak kprobe_lookup_name(const char *name,
unsigned int __unused)
{ {
return ((kprobe_opcode_t *)(kallsyms_lookup_name(name))); return ((kprobe_opcode_t *)(kallsyms_lookup_name(name)));
} }
...@@ -1403,7 +1404,7 @@ static kprobe_opcode_t *kprobe_addr(struct kprobe *p) ...@@ -1403,7 +1404,7 @@ static kprobe_opcode_t *kprobe_addr(struct kprobe *p)
goto invalid; goto invalid;
if (p->symbol_name) { if (p->symbol_name) {
addr = kprobe_lookup_name(p->symbol_name); addr = kprobe_lookup_name(p->symbol_name, p->offset);
if (!addr) if (!addr)
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
} }
...@@ -2196,7 +2197,7 @@ static int __init init_kprobes(void) ...@@ -2196,7 +2197,7 @@ static int __init init_kprobes(void)
/* lookup the function address from its name */ /* lookup the function address from its name */
for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
kretprobe_blacklist[i].addr = kretprobe_blacklist[i].addr =
kprobe_lookup_name(kretprobe_blacklist[i].name); kprobe_lookup_name(kretprobe_blacklist[i].name, 0);
if (!kretprobe_blacklist[i].addr) if (!kretprobe_blacklist[i].addr)
printk("kretprobe: lookup failed: %s\n", printk("kretprobe: lookup failed: %s\n",
kretprobe_blacklist[i].name); kretprobe_blacklist[i].name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment