tracing/kprobes: Get ready for -mfentry
Subsystems (4)
Steven Rostedt
maintainercover tracing/kprobes: Get ready for -mfentry
As I want to add the -mfentry to allow for function tracing without frame pointers (as some distros are now disabling function tracing :-(
I have to handle the case that a kprobe is placed on a ftrace nop. As ftrace nops with -mfentry will be the first instruction of a function, it being the location of a kprobe is a likely occurrence.
Ideally, kprobes would just use the function tracing infrastructure to make an automatic optimized jump. But that is for another day as it requires a bit of work in the function tracer to handle regs and such.
So the quick fix for now is to simply move the probe to the next instruction after the ftrace nop. As the nop shouldn't be doing anything anyway (and tracing should return to the function in the same state) moving the location of the probe should not cause any harm.
The first 5 patches are non controversial, and could probably just be pushed for 3.5 inclusion. The last patch makes the change to move the probe to the next instruction after the ftrace nop.
Anyone see any problem with this?
-- Steve
Steven Rostedt (6):
ftrace: Sort all function addresses, not just per page
ftrace: Remove extra helper functions
ftrace: Speed up search by skipping pages by address
ftrace: Consolidate ftrace_location() and ftrace_text_reserved()
ftrace: Return record ip addr for ftrace_location()
kprobes: Allow probe on ftrace reserved text (but move it)
----
include/asm-generic/vmlinux.lds.h | 2 +- include/linux/ftrace.h | 2 +- kernel/kprobes.c | 11 ++- kernel/trace/ftrace.c | 173 ++++++++++++++++++++----------------- 4 files changed, 104 insertions(+), 84 deletions(-)
Steven Rostedt
maintainerRFC PATCH 1/6 ftrace: Sort all function addresses, not just per page
From: Steven Rostedt <[email protected]>
Instead of just sorting the ip's of the functions per ftrace page, sort the entire list before adding them to the ftrace pages.
This will allow the bsearch algorithm to be sped up as it can also sort by pages, not just records within a page.
--- include/asm-generic/vmlinux.lds.h | 2 +- kernel/trace/ftrace.c | 34 ++++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 13 deletions(-)
include/asm-generic/vmlinux.lds.h +1 -1
@@ -486,8 +486,8 @@ CPU_DISCARD(init.data) \ MEM_DISCARD(init.data) \ KERNEL_CTORS() \ - *(.init.rodata) \MCOUNT_REC () \ + *(.init.rodata) \ FTRACE_EVENTS() \ TRACE_SYSCALLS() \DEV_DISCARD (init.rodata) \
kernel/trace/ftrace.c +22 -12
@@ -3688,15 +3688,27 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)return 0 ; } -static void ftrace_swap_recs (void *a,void *b,int size) +static int ftrace_cmp_ips (const void *a,const void *b) { -struct dyn_ftrace *reca = a; -struct dyn_ftrace *recb = b; -struct dyn_ftrace t; +const unsigned long *ipa = a; +const unsigned long *ipb = b; - t = *reca; - *reca = *recb; - *recb = t; +if (*ipa > *ipb) +return 1 ; +if (*ipa < *ipb) +return -1 ; +return 0 ; +} + +static void ftrace_swap_ips (void *a,void *b,int size) +{ +unsigned long *ipa = a; +unsigned long *ipb = b; +unsigned long t; + + t = *ipa; + *ipa = *ipb; + *ipb = t; } static int ftrace_process_locs(struct module *mod,
@@ -3715,6 +3727,9 @@ static int ftrace_process_locs(struct module *mod,if (!count)return 0 ; +sort (start, count,sizeof (*start), + ftrace_cmp_ips, ftrace_swap_ips); + pg =ftrace_allocate_pages (count);if (!pg)return -ENOMEM ;
@@ -3762,11 +3777,6 @@ static int ftrace_process_locs(struct module *mod,/* These new locations need to be initialized */ ftrace_new_pgs = pg; -/* Make each individual set of pages sorted by ips */ -for (; pg; pg = pg->next) -sort (pg->records, pg->index,sizeof (struct dyn_ftrace ), - ftrace_cmp_recs, ftrace_swap_recs); -/* * We only need to disable interrupts on start up * because we are modifying code that an interrupt
Signature · 1 line
1.7.9.5
Steven Rostedt
maintainerRFC PATCH 2/6 ftrace: Remove extra helper functions
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
The ftrace_record_ip() and ftrace_alloc_dyn_node() were from the time of the ftrace daemon. Although they were still used, they still make things a bit more complex than necessary.
Move the code into the one function that uses it, and remove the helper functions.
--- kernel/trace/ftrace.c | 61 +++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 37 deletions(-)
kernel/trace/ftrace.c +24 -37
@@ -1520,35 +1520,6 @@ static void ftrace_hash_rec_enable(struct ftrace_ops *ops,__ftrace_hash_rec_update (ops, filter_hash,1 ); } -static struct dyn_ftrace *ftrace_alloc_dyn_node (unsigned long ip) -{ -if (ftrace_pages->index == ftrace_pages->size) { -/* We should have allocated enough */ -if (WARN_ON (!ftrace_pages->next)) -return NULL ; - ftrace_pages = ftrace_pages->next; - } - -return &ftrace_pages->records[ftrace_pages->index++]; -} - -static struct dyn_ftrace * -ftrace_record_ip (unsigned long ip) -{ -struct dyn_ftrace *rec; - -if (ftrace_disabled) -return NULL ; - - rec =ftrace_alloc_dyn_node (ip); -if (!rec) -return NULL ; - - rec->ip = ip; - -return rec; -} -static void print_ip_ins (const char *fmt,unsigned char *p) {int i;
@@ -3715,7 +3686,9 @@ static int ftrace_process_locs(struct module *mod,unsigned long *start, unsigned long *end) { + struct ftrace_page *start_pg;struct ftrace_page *pg; +struct dyn_ftrace *rec;unsigned long count;unsigned long *p;unsigned long addr;
@@ -3730,8 +3703,8 @@ static int ftrace_process_locs(struct module *mod,sort (start, count,sizeof (*start), ftrace_cmp_ips, ftrace_swap_ips); - pg =ftrace_allocate_pages (count); -if (!pg) + start_pg =ftrace_allocate_pages (count); +if (!start_pg)return -ENOMEM ;mutex_lock (&ftrace_lock);
@@ -3744,7 +3717,7 @@ static int ftrace_process_locs(struct module *mod,if (!mod) {WARN_ON (ftrace_pages || ftrace_pages_start);/* First initialization */ - ftrace_pages = ftrace_pages_start = pg; + ftrace_pages = ftrace_pages_start = start_pg; }else {if (!ftrace_pages) goto out;
@@ -3755,11 +3728,11 @@ static int ftrace_process_locs(struct module *mod, ftrace_pages = ftrace_pages->next; } - ftrace_pages->next = pg; - ftrace_pages = pg; + ftrace_pages->next = start_pg; } p = start; + pg = start_pg;while (p < end) { addr =ftrace_call_adjust (*p++);/*
@@ -3770,12 +3743,26 @@ static int ftrace_process_locs(struct module *mod,*/ if (!addr)continue ; -if (!ftrace_record_ip (addr)) -break ; + +if (pg->index == pg->size) { +/* We should have allocated enough */ +if (WARN_ON (!pg->next)) +break ; + pg = pg->next; + } + + rec = &pg->records[pg->index++]; + rec->ip = addr; } +/* We should have used all pages */ +WARN_ON (pg->next); + +/* Assign the last page to ftrace_pages */ + ftrace_pages = pg; +/* These new locations need to be initialized */ - ftrace_new_pgs = pg; + ftrace_new_pgs = start_pg;/* * We only need to disable interrupts on start up
Signature · 1 line
1.7.9.5
Steven Rostedt
maintainerRFC PATCH 3/6 ftrace: Speed up search by skipping pages by address
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
As all records in a page of the ftrace table are sorted, we can speed up the search algorithm by checking if the address to look for falls in between the first and last record ip on the page.
This speeds up both the ftrace_location() and ftrace_text_reserved() algorithms, as it can skip full pages when the search address is not in them.
--- kernel/trace/ftrace.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
kernel/trace/ftrace.c +16 -6
@@ -1411,6 +1411,8 @@ int ftrace_location(unsigned long ip) key.ip = ip;for (pg = ftrace_pages_start; pg; pg = pg->next) { +if (ip < pg->records[0 ].ip || ip > pg->records[pg->index -1 ].ip) +continue ; rec =bsearch (&key, pg->records, pg->index,sizeof (struct dyn_ftrace ), ftrace_cmp_recs);
@@ -1571,16 +1573,24 @@ void ftrace_bug(int failed, unsigned long ip)/* Return 1 if the address range is reserved for ftrace */ -int ftrace_text_reserved (void *start,void *end) +int ftrace_text_reserved (void *s,void *e) {struct dyn_ftrace *rec;struct ftrace_page *pg; +unsigned long start = (unsigned long )s; +unsigned long end = (unsigned long )e; +int i; -do_for_each_ftrace_rec (pg, rec) { -if (rec->ip <= (unsigned long )end && - rec->ip +MCOUNT_INSN_SIZE > (unsigned long )start) -return 1 ; - }while_for_each_ftrace_rec (); +for (pg = ftrace_pages_start; pg; pg = pg->next) { +if (end < pg->records[0 ].ip || + start >= (pg->records[pg->index -1 ].ip +MCOUNT_INSN_SIZE )) +continue ; +for (i =0 ; i < pg->index; i++) { + rec = &pg->records[i]; +if (rec->ip <= end && rec->ip +MCOUNT_INSN_SIZE > start) +return 1 ; + } + }return 0 ; }
Signature · 1 line
1.7.9.5
Steven Rostedt
maintainerRFC PATCH 4/6 ftrace: Consolidate ftrace_location() and ftrace_text_reserved()
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Both ftrace_location() and ftrace_text_reserved() do basically the same thing. They search to see if an address is in the ftace table (contains an address that may change from nop to call ftrace_caller). The difference is that ftrace_location() searches a single address, but ftrace_text_reserved() searches a range.
This laso makes the ftrace_text_reserved() faster as it now uses a bsearch() instead of linearly searching all the addresses within a page.
--- kernel/trace/ftrace.c | 80 ++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 40 deletions(-)
kernel/trace/ftrace.c +40 -40
@@ -1383,35 +1383,28 @@ ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)static int ftrace_cmp_recs (const void *a,const void *b) { -const struct dyn_ftrace *reca = a; -const struct dyn_ftrace *recb = b; +const struct dyn_ftrace *key = a; +const struct dyn_ftrace *rec = b; -if (reca->ip > recb->ip) -return 1 ; -if (reca->ip < recb->ip) +if (key->flags < rec->ip)return -1 ; +if (key->ip >= rec->ip +MCOUNT_INSN_SIZE ) +return 1 ;return 0 ; } -/** -* ftrace_location - return true if the ip giving is a traced location -* @ip: the instruction pointer to check -* -* Returns 1 if @ip given is a pointer to a ftrace location. -* That is, the instruction that is either a NOP or call to -* the function tracer. It checks the ftrace internal tables to -* determine if the address belongs or not. -*/ -int ftrace_location (unsigned long ip) +static int ftrace_location_range (unsigned long start,unsigned long end) {struct ftrace_page *pg;struct dyn_ftrace *rec;struct dyn_ftrace key; - key.ip = ip; + key.ip = start; + key.flags = end;/* overload flags, as it is unsigned long */ for (pg = ftrace_pages_start; pg; pg = pg->next) { -if (ip < pg->records[0 ].ip || ip > pg->records[pg->index -1 ].ip) +if (end < pg->records[0 ].ip || + start >= (pg->records[pg->index -1 ].ip +MCOUNT_INSN_SIZE ))continue ; rec = bsearch(&key, pg->records, pg->index, sizeof(struct dyn_ftrace),
@@ -1423,6 +1416,36 @@ int ftrace_location(unsigned long ip)return 0 ; } +/** +* ftrace_location - return true if the ip giving is a traced location +* @ip: the instruction pointer to check +* +* Returns 1 if @ip given is a pointer to a ftrace location. +* That is, the instruction that is either a NOP or call to +* the function tracer. It checks the ftrace internal tables to +* determine if the address belongs or not. +*/ +int ftrace_location (unsigned long ip) +{ +return ftrace_location_range (ip, ip); +} + +/** +* ftrace_text_reserved - return true if range contains an ftrace location +* @start: start of range to search +* @end: end of range to search (inclusive). @end points to the last byte to check. +* +* Returns 1 if @start and @end contains a ftrace location. +* That is, the instruction that is either a NOP or call to +* the function tracer. It checks the ftrace internal tables to +* determine if the address belongs or not. +*/ +int ftrace_text_reserved (void *start,void *end) +{ +return ftrace_location_range ((unsigned long )start, + (unsigned long )end); +} +static void __ftrace_hash_rec_update (struct ftrace_ops *ops,int filter_hash,bool inc)
@@ -1571,29 +1594,6 @@ void ftrace_bug(int failed, unsigned long ip) } } - -/* Return 1 if the address range is reserved for ftrace */ -int ftrace_text_reserved (void *s,void *e) -{ -struct dyn_ftrace *rec; -struct ftrace_page *pg; -unsigned long start = (unsigned long )s; -unsigned long end = (unsigned long )e; -int i; - -for (pg = ftrace_pages_start; pg; pg = pg->next) { -if (end < pg->records[0 ].ip || - start >= (pg->records[pg->index -1 ].ip +MCOUNT_INSN_SIZE )) -continue ; -for (i =0 ; i < pg->index; i++) { - rec = &pg->records[i]; -if (rec->ip <= end && rec->ip +MCOUNT_INSN_SIZE > start) -return 1 ; - } - } -return 0 ; -} -static int ftrace_check_record (struct dyn_ftrace *rec,int enable,int update) {unsigned long flag =0UL ;
Signature · 1 line
1.7.9.5
Steven Rostedt
maintainerRFC PATCH 5/6 ftrace: Return record ip addr for ftrace_location()
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
ftrace_location() is passed an addr, and returns 1 if the addr is on a ftrace nop (or caller to ftrace_caller), and 0 otherwise.
To let kprobes know if it should move a breakpoint or not, it must return the actual addr that is the start of the ftrace nop. This way a kprobe placed on the location of a ftrace nop, can instead be placed on the instruction after the nop. Even if the probe addr is on the second or later byte of the nop, it can simply be moved forward.
--- include/linux/ftrace.h | 2 +- kernel/trace/ftrace.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-)
include/linux/ftrace.h +1 -1
@@ -295,7 +295,7 @@ struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter);int ftrace_update_record (struct dyn_ftrace *rec,int enable);int ftrace_test_record (struct dyn_ftrace *rec,int enable);void ftrace_run_stop_machine (int command); -int ftrace_location (unsigned long ip); +unsigned long ftrace_location (unsigned long ip);extern ftrace_func_t ftrace_trace_function;
kernel/trace/ftrace.c +10 -6
@@ -1393,7 +1393,7 @@ static int ftrace_cmp_recs(const void *a, const void *b)return 0 ; } -static int ftrace_location_range (unsigned long start,unsigned long end) +static unsigned long ftrace_location_range (unsigned long start,unsigned long end) {struct ftrace_page *pg;struct dyn_ftrace *rec;
@@ -1410,7 +1410,7 @@ static int ftrace_location_range(unsigned long start, unsigned long end)sizeof (struct dyn_ftrace ), ftrace_cmp_recs);if (rec) -return 1 ; +return rec->ip; }return 0 ;
@@ -1420,12 +1420,12 @@ static int ftrace_location_range(unsigned long start, unsigned long end)* ftrace_location - return true if the ip giving is a traced location * @ip: the instruction pointer to check * -* Returns 1 if @ip given is a pointer to a ftrace location. +* Returns rec->ip if @ip given is a pointer to a ftrace location. * That is, the instruction that is either a NOP or call to * the function tracer. It checks the ftrace internal tables to * determine if the address belongs or not. */ -int ftrace_location (unsigned long ip) +unsigned long ftrace_location (unsigned long ip) {return ftrace_location_range (ip, ip); }
@@ -1442,8 +1442,12 @@ int ftrace_location(unsigned long ip)*/ int ftrace_text_reserved (void *start,void *end) { -return ftrace_location_range ((unsigned long )start, - (unsigned long )end); +unsigned long ret; + + ret =ftrace_location_range ((unsigned long )start, + (unsigned long )end); + +return (int )!!ret; } static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
Signature · 1 line
1.7.9.5
Steven Rostedt
maintainerRFC PATCH 6/6 kprobes: Allow probe on ftrace reserved text (but move it)
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
If a probe is placed on a ftrace nop (or ftrace_caller), simply move the probe to the next instruction instead of rejecting it. This will allow kprobes not to be affected by ftrace using the -mfentry gcc option which will put the ftrace nop at the beginning of the function. As a very common case for kprobes is to add a probe to the very beginning of a function we need a way to handle the case when ftrace takes the first instruction.
--- kernel/kprobes.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
kernel/kprobes.c +10 -1
@@ -1319,10 +1319,20 @@ int __kprobes register_kprobe(struct kprobe *p)struct kprobe *old_p;struct module *probed_mod;kprobe_opcode_t *addr; +unsigned long ftrace_addr; addr =kprobe_addr (p);if (IS_ERR (addr))return PTR_ERR (addr); + +/* +* If the address is located on a ftrace nop, set the +* breakpoint to the following instruction. +*/ + ftrace_addr =ftrace_location ((unsigned long )addr); +if (unlikely (ftrace_addr)) + addr = (kprobe_opcode_t *)(ftrace_addr +MCOUNT_INSN_SIZE ); + p->addr = addr; ret =check_kprobe_rereg (p);
@@ -1333,7 +1343,6 @@ int __kprobes register_kprobe(struct kprobe *p)preempt_disable ();if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) || -ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) { ret = -EINVAL ; goto cannot_probe;
Signature · 1 line
1.7.9.5
Re: [PATCH 6/6][RFC] kprobes: Allow probe on ftrace reserved text (but move it)
Quoted 8 lines · Steven Rostedt
From: Steven Rostedt <[email protected]>
If a probe is placed on a ftrace nop (or
ftrace_caller), simply move the probe to the next instruction instead of rejecting it. This will allow kprobes not to be affected by ftrace using the -mfentry gcc option which will put the ftrace nop at the beginning of the function. As a very common case for kprobes is to add a probe to the very beginning of a function we need a way to handle the case when ftrace takes the first instruction.
Hmm, I think you'd better introduce a flag(KPROBE_FLAG_MOVED) for adjustment of probed IP address. Caller or handler can fixup its IP or kprobes itself can do it.
Quoted 18 lines
Cc Masami Hiramatsu <[email protected]>Signed-off-by Steven Rostedt <[email protected]>--- kernel/kprobes.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)kernel/kprobes.c +1
-0@@ -1319,10 +1319,20 @@ int __kprobes register_kprobe(struct kprobe *p)struct kprobe *old_p;struct module *probed_mod;kprobe_opcode_t *addr; +unsigned long ftrace_addr; addr =kprobe_addr (p);
kernel/kprobes.c int __kprobes register_kprobe(struct kprobe *p) · line 1334
Quoted 10 lines
kernel/kprobes.c +8
-0if (IS_ERR (addr))return PTR_ERR (addr); + +/* +* If the address is located on a ftrace nop, set the +* breakpoint to the following instruction. +*/ + ftrace_addr =ftrace_location ((unsigned long )addr); +if (unlikely (ftrace_addr)) + addr = (kprobe_opcode_t *)(ftrace_addr +MCOUNT_INSN_SIZE );
And also, you may need to use ftrace_text_reserved() here, or need a void ftrace_location() function for CONFIG_DYNAMIC_FTRACE=n.
kernel/kprobes.c int __kprobes register_kprobe(struct kprobe *p) · line 1348
Quoted 12 lines
kernel/kprobes.c +1
-1+ p->addr = addr; ret =check_kprobe_rereg (p);@@ -1333,7 +1343,6 @@ int __kprobes register_kprobe(struct kprobe *p)preempt_disable ();if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) || -ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) { ret = -EINVAL ; goto cannot_probe;
Thanks,
Signature · 4 lines
Masami HIRAMATSU Software Platform Research Dept. Linux Technology Center Hitachi, Ltd., Yokohama Research Laboratory E-mail: [email protected]
Steven Rostedt
maintainerRe: [PATCH 6/6][RFC] kprobes: Allow probe on ftrace reserved text (but move it)
Quoted 7 lines · Masami Hiramatsu
Hmm, I think you'd better introduce a
flag(KPROBE_FLAG_MOVED)for adjustment of probed IP address. Caller or handler can fixup its IP or kprobes itself can do it.And also, you may need to use
ftrace_text_reserved()here, or need a voidftrace_location()function forCONFIG_DYNAMIC_FTRACE=n.
Hi Masami,
What do you think of this patch?
-- Steve
commit 648bb05a49dcf95b9dddd07e361023124357ea36
Author: Steven Rostedt <[email protected]> Date: Wed Apr 25 14:28:22 2012 -0400
kprobes: Allow probe on ftrace reserved text (but move it)
If a probe is placed on a ftrace nop (or ftrace_caller), simply move the probe to the next instruction instead of rejecting it. This will allow kprobes not to be affected by ftrace using the -mfentry gcc option which will put the ftrace nop at the beginning of the function. As a very common case for kprobes is to add a probe to the very beginning of a function we need a way to handle the case when ftrace takes the first instruction.
Added KPROBE_FLAG_MOVED (as suggested by Masami) that is set when the address is moved to get around an ftrace nop.
include/linux/ftrace.h +2 -0
@@ -414,6 +414,8 @@ static inline int ftrace_text_reserved(void *start, void *end)#define ftrace_set_notrace (ops, buf, len, reset) ({ -ENODEV; })#define ftrace_free_filter (ops) do { } while (0) +static inline unsigned long ftrace_location (unsigned long ip) {return 0 ; } +static inline ssize_t ftrace_filter_write (struct file *file,const char __user *ubuf,size_t cnt,loff_t *ppos) {return -ENODEV ; } static inline ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
include/linux/kprobes.h +1 -0
@@ -128,6 +128,7 @@ struct kprobe {* NOTE: * this flag is only for optimized_kprobe. */ +#define KPROBE_FLAG_MOVED 8/* probe was moved passed ftrace nop */ /* Has this kprobe gone ? */ static inline int kprobe_gone (struct kprobe *p)
kernel/kprobes.c +12 -1
@@ -1319,10 +1319,22 @@ int __kprobes register_kprobe(struct kprobe *p)struct kprobe *old_p;struct module *probed_mod;kprobe_opcode_t *addr; +unsigned long ftrace_addr; addr =kprobe_addr (p);if (IS_ERR (addr))return PTR_ERR (addr); + +/* +* If the address is located on a ftrace nop, set the +* breakpoint to the following instruction. +*/ + ftrace_addr =ftrace_location ((unsigned long )addr); +if (unlikely (ftrace_addr)) { + addr = (kprobe_opcode_t *)(ftrace_addr +MCOUNT_INSN_SIZE ); + p->flags |=KPROBE_FLAG_MOVED ; + } + p->addr = addr; ret =check_kprobe_rereg (p);
@@ -1333,7 +1345,6 @@ int __kprobes register_kprobe(struct kprobe *p)preempt_disable ();if (!kernel_text_address ((unsigned long ) p->addr) ||in_kprobes_functions ((unsigned long ) p->addr) || -ftrace_text_reserved (p->addr, p->addr) ||jump_label_text_reserved (p->addr, p->addr)) { ret = -EINVAL ; goto cannot_probe;
Re: [PATCH 6/6][RFC] kprobes: Allow probe on ftrace reserved text (but move it)
kernel/kprobes.c int __kprobes register_kprobe(struct kprobe *p) · line 1336
Quoted 13 lines · Steven Rostedt
[...]
What do you think of this patch?
[...]kernel/kprobes.c +9
-0+/* +* If the address is located on a ftrace nop, set the +* breakpoint to the following instruction. +*/ + ftrace_addr =ftrace_location ((unsigned long )addr); +if (unlikely (ftrace_addr)) { + addr = (kprobe_opcode_t *)(ftrace_addr +MCOUNT_INSN_SIZE ); + p->flags |=KPROBE_FLAG_MOVED ; + }
I suspect Masami intended that this flag is later used during int3 processing to subtract MCOUNT_INSN_SIZE back out from the pt_regs->ip during kprobe_handler() if this flag was set.
- FChE