tracing: probeevent: Return consumed bytes of dynamic area
Cleanup string fetching routine so that returns the consumed bytes of dynamic area and store the string information as data_loc format instead of data_rloc. This simplifies the fetcharg loop. Link: http://lkml.kernel.org/r/152465874163.26224.12125143907501289031.stgit@devbox Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:

committed by
Steven Rostedt (VMware)

parent
f451bc89d8
commit
9178412ddf
@@ -111,43 +111,38 @@ probe_user_read(void *dest, void *src, size_t size)
|
||||
* Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max
|
||||
* length and relative data location.
|
||||
*/
|
||||
static nokprobe_inline void
|
||||
fetch_store_string(unsigned long addr, void *dest)
|
||||
static nokprobe_inline int
|
||||
fetch_store_string(unsigned long addr, void *dest, void *base)
|
||||
{
|
||||
long ret;
|
||||
u32 rloc = *(u32 *)dest;
|
||||
int maxlen = get_rloc_len(rloc);
|
||||
u8 *dst = get_rloc_data(dest);
|
||||
u32 loc = *(u32 *)dest;
|
||||
int maxlen = get_loc_len(loc);
|
||||
u8 *dst = get_loc_data(dest, base);
|
||||
void __user *src = (void __force __user *) addr;
|
||||
|
||||
if (!maxlen)
|
||||
return;
|
||||
if (unlikely(!maxlen))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = strncpy_from_user(dst, src, maxlen);
|
||||
if (ret == maxlen)
|
||||
dst[--ret] = '\0';
|
||||
|
||||
if (ret < 0) { /* Failed to fetch string */
|
||||
((u8 *)get_rloc_data(dest))[0] = '\0';
|
||||
*(u32 *)dest = make_data_rloc(0, get_rloc_offs(rloc));
|
||||
} else {
|
||||
*(u32 *)dest = make_data_rloc(ret, get_rloc_offs(rloc));
|
||||
if (ret >= 0) {
|
||||
if (ret == maxlen)
|
||||
dst[ret - 1] = '\0';
|
||||
*(u32 *)dest = make_data_loc(ret, (void *)dst - base);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the length of string -- including null terminal byte */
|
||||
static nokprobe_inline void
|
||||
fetch_store_strlen(unsigned long addr, void *dest)
|
||||
static nokprobe_inline int
|
||||
fetch_store_strlen(unsigned long addr)
|
||||
{
|
||||
int len;
|
||||
void __user *vaddr = (void __force __user *) addr;
|
||||
|
||||
len = strnlen_user(vaddr, MAX_STRING_SIZE);
|
||||
|
||||
if (len == 0 || len > MAX_STRING_SIZE) /* Failed to check length */
|
||||
*(u32 *)dest = 0;
|
||||
else
|
||||
*(u32 *)dest = len;
|
||||
return (len > MAX_STRING_SIZE) ? 0 : len;
|
||||
}
|
||||
|
||||
static unsigned long translate_user_vaddr(unsigned long file_offset)
|
||||
@@ -164,10 +159,10 @@ static unsigned long translate_user_vaddr(unsigned long file_offset)
|
||||
/* Note that we don't verify it, since the code does not come from user space */
|
||||
static int
|
||||
process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
|
||||
bool pre)
|
||||
void *base)
|
||||
{
|
||||
unsigned long val;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* 1st stage: get value from context */
|
||||
switch (code->op) {
|
||||
@@ -204,18 +199,22 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
|
||||
}
|
||||
|
||||
/* 3rd stage: store value to buffer */
|
||||
if (unlikely(!dest)) {
|
||||
if (code->op == FETCH_OP_ST_STRING)
|
||||
return fetch_store_strlen(val + code->offset);
|
||||
else
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
switch (code->op) {
|
||||
case FETCH_OP_ST_RAW:
|
||||
fetch_store_raw(val, code, dest);
|
||||
break;
|
||||
case FETCH_OP_ST_MEM:
|
||||
probe_user_read(dest, (void *)val + code->offset, code->size);
|
||||
probe_kernel_read(dest, (void *)val + code->offset, code->size);
|
||||
break;
|
||||
case FETCH_OP_ST_STRING:
|
||||
if (pre)
|
||||
fetch_store_strlen(val + code->offset, dest);
|
||||
else
|
||||
fetch_store_string(val + code->offset, dest);
|
||||
ret = fetch_store_string(val + code->offset, dest, base);
|
||||
break;
|
||||
default:
|
||||
return -EILSEQ;
|
||||
@@ -228,7 +227,7 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
|
||||
code++;
|
||||
}
|
||||
|
||||
return code->op == FETCH_OP_END ? 0 : -EILSEQ;
|
||||
return code->op == FETCH_OP_END ? ret : -EILSEQ;
|
||||
}
|
||||
NOKPROBE_SYMBOL(process_fetch_insn)
|
||||
|
||||
@@ -1300,7 +1299,7 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
|
||||
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
|
||||
|
||||
ucb = uprobe_buffer_get();
|
||||
store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
|
||||
store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
|
||||
|
||||
if (tu->tp.flags & TP_FLAG_TRACE)
|
||||
ret |= uprobe_trace_func(tu, regs, ucb, dsize);
|
||||
@@ -1335,7 +1334,7 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
|
||||
esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
|
||||
|
||||
ucb = uprobe_buffer_get();
|
||||
store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
|
||||
store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
|
||||
|
||||
if (tu->tp.flags & TP_FLAG_TRACE)
|
||||
uretprobe_trace_func(tu, func, regs, ucb, dsize);
|
||||
|
Reference in New Issue
Block a user