mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-18 07:09:36 +02:00
Revert "perf,x86: avoid missing caller address in stack traces captured in uprobe"
This reverts commitadf290fe43
which is commitcfa7f3d2c5
upstream. It breaks the Android kernel abi and can be brought back in the future in an abi-safe way if it is really needed. Bug: 161946584 Change-Id: I4912c7be5dce01570c374c4018de1da6ce5dab3b Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
ac723e338f
commit
ae4370b575
|
@ -41,8 +41,6 @@
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/ldt.h>
|
#include <asm/ldt.h>
|
||||||
#include <asm/unwind.h>
|
#include <asm/unwind.h>
|
||||||
#include <asm/uprobes.h>
|
|
||||||
#include <asm/ibt.h>
|
|
||||||
|
|
||||||
#include "perf_event.h"
|
#include "perf_event.h"
|
||||||
|
|
||||||
|
@ -2818,46 +2816,6 @@ static unsigned long get_segment_base(unsigned int segment)
|
||||||
return get_desc_base(desc);
|
return get_desc_base(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_UPROBES
|
|
||||||
/*
|
|
||||||
* Heuristic-based check if uprobe is installed at the function entry.
|
|
||||||
*
|
|
||||||
* Under assumption of user code being compiled with frame pointers,
|
|
||||||
* `push %rbp/%ebp` is a good indicator that we indeed are.
|
|
||||||
*
|
|
||||||
* Similarly, `endbr64` (assuming 64-bit mode) is also a common pattern.
|
|
||||||
* If we get this wrong, captured stack trace might have one extra bogus
|
|
||||||
* entry, but the rest of stack trace will still be meaningful.
|
|
||||||
*/
|
|
||||||
static bool is_uprobe_at_func_entry(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
struct arch_uprobe *auprobe;
|
|
||||||
|
|
||||||
if (!current->utask)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auprobe = current->utask->auprobe;
|
|
||||||
if (!auprobe)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* push %rbp/%ebp */
|
|
||||||
if (auprobe->insn[0] == 0x55)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/* endbr64 (64-bit only) */
|
|
||||||
if (user_64bit_mode(regs) && is_endbr(*(u32 *)auprobe->insn))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
static bool is_uprobe_at_func_entry(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_UPROBES */
|
|
||||||
|
|
||||||
#ifdef CONFIG_IA32_EMULATION
|
#ifdef CONFIG_IA32_EMULATION
|
||||||
|
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
@ -2869,7 +2827,6 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
|
||||||
unsigned long ss_base, cs_base;
|
unsigned long ss_base, cs_base;
|
||||||
struct stack_frame_ia32 frame;
|
struct stack_frame_ia32 frame;
|
||||||
const struct stack_frame_ia32 __user *fp;
|
const struct stack_frame_ia32 __user *fp;
|
||||||
u32 ret_addr;
|
|
||||||
|
|
||||||
if (user_64bit_mode(regs))
|
if (user_64bit_mode(regs))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2879,12 +2836,6 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
|
||||||
|
|
||||||
fp = compat_ptr(ss_base + regs->bp);
|
fp = compat_ptr(ss_base + regs->bp);
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
/* see perf_callchain_user() below for why we do this */
|
|
||||||
if (is_uprobe_at_func_entry(regs) &&
|
|
||||||
!get_user(ret_addr, (const u32 __user *)regs->sp))
|
|
||||||
perf_callchain_store(entry, ret_addr);
|
|
||||||
|
|
||||||
while (entry->nr < entry->max_stack) {
|
while (entry->nr < entry->max_stack) {
|
||||||
if (!valid_user_frame(fp, sizeof(frame)))
|
if (!valid_user_frame(fp, sizeof(frame)))
|
||||||
break;
|
break;
|
||||||
|
@ -2913,7 +2864,6 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
|
||||||
{
|
{
|
||||||
struct stack_frame frame;
|
struct stack_frame frame;
|
||||||
const struct stack_frame __user *fp;
|
const struct stack_frame __user *fp;
|
||||||
unsigned long ret_addr;
|
|
||||||
|
|
||||||
if (perf_guest_state()) {
|
if (perf_guest_state()) {
|
||||||
/* TODO: We don't support guest os callchain now */
|
/* TODO: We don't support guest os callchain now */
|
||||||
|
@ -2937,19 +2887,6 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are called from uprobe handler, and we are indeed at the very
|
|
||||||
* entry to user function (which is normally a `push %rbp` instruction,
|
|
||||||
* under assumption of application being compiled with frame pointers),
|
|
||||||
* we should read return address from *regs->sp before proceeding
|
|
||||||
* to follow frame pointers, otherwise we'll skip immediate caller
|
|
||||||
* as %rbp is not yet setup.
|
|
||||||
*/
|
|
||||||
if (is_uprobe_at_func_entry(regs) &&
|
|
||||||
!get_user(ret_addr, (const unsigned long __user *)regs->sp))
|
|
||||||
perf_callchain_store(entry, ret_addr);
|
|
||||||
|
|
||||||
while (entry->nr < entry->max_stack) {
|
while (entry->nr < entry->max_stack) {
|
||||||
if (!valid_user_frame(fp, sizeof(frame)))
|
if (!valid_user_frame(fp, sizeof(frame)))
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -76,8 +76,6 @@ struct uprobe_task {
|
||||||
struct uprobe *active_uprobe;
|
struct uprobe *active_uprobe;
|
||||||
unsigned long xol_vaddr;
|
unsigned long xol_vaddr;
|
||||||
|
|
||||||
struct arch_uprobe *auprobe;
|
|
||||||
|
|
||||||
struct return_instance *return_instances;
|
struct return_instance *return_instances;
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2075,7 +2075,6 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
|
||||||
bool need_prep = false; /* prepare return uprobe, when needed */
|
bool need_prep = false; /* prepare return uprobe, when needed */
|
||||||
|
|
||||||
down_read(&uprobe->register_rwsem);
|
down_read(&uprobe->register_rwsem);
|
||||||
current->utask->auprobe = &uprobe->arch;
|
|
||||||
for (uc = uprobe->consumers; uc; uc = uc->next) {
|
for (uc = uprobe->consumers; uc; uc = uc->next) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@ -2090,7 +2089,6 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
|
||||||
|
|
||||||
remove &= rc;
|
remove &= rc;
|
||||||
}
|
}
|
||||||
current->utask->auprobe = NULL;
|
|
||||||
|
|
||||||
if (need_prep && !remove)
|
if (need_prep && !remove)
|
||||||
prepare_uretprobe(uprobe, regs); /* put bp at return */
|
prepare_uretprobe(uprobe, regs); /* put bp at return */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user