mirror of https://gitee.com/openkylin/linux.git
perf arm64: Add argument support for SDT
Now the two OP formats are used for SDT marker argument in Arm64 ELF, one format is general register xNUM (e.g. x1, x2, etc), another is for using stack pointer to access local variables (e.g. [sp], [sp, 8]). This patch adds support SDT marker argument for Arm64, it parses OP and converts to uprobe compatible format. Signed-off-by: Leo Yan <leo.yan@linaro.org> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Alexandre Truong <alexandre.truong@arm.com> Cc: Alexis Berlemont <alexis.berlemont@gmail.com> Cc: He Zhe <zhe.he@windriver.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: John Garry <john.garry@huawei.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Mathieu Poirier <mathieu.poirier@linaro.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Sumanth Korikkar <sumanthk@linux.ibm.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Will Deacon <will@kernel.org> Cc: linux-arm-kernel@lists.infradead.org Link: http://lore.kernel.org/lkml/20201225052751.24513-4-leo.yan@linaro.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
f19b5872d8
commit
feab999efe
|
@ -1,4 +1,12 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
#include <errno.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/zalloc.h>
|
||||||
|
|
||||||
|
#include "../../../util/debug.h"
|
||||||
|
#include "../../../util/event.h"
|
||||||
#include "../../../util/perf_regs.h"
|
#include "../../../util/perf_regs.h"
|
||||||
|
|
||||||
const struct sample_reg sample_reg_masks[] = {
|
const struct sample_reg sample_reg_masks[] = {
|
||||||
|
@ -37,3 +45,89 @@ const struct sample_reg sample_reg_masks[] = {
|
||||||
SMPL_REG(pc, PERF_REG_ARM64_PC),
|
SMPL_REG(pc, PERF_REG_ARM64_PC),
|
||||||
SMPL_REG_END
|
SMPL_REG_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* %xNUM */
|
||||||
|
#define SDT_OP_REGEX1 "^(x[1-2]?[0-9]|3[0-1])$"
|
||||||
|
|
||||||
|
/* [sp], [sp, NUM] */
|
||||||
|
#define SDT_OP_REGEX2 "^\\[sp(, )?([0-9]+)?\\]$"
|
||||||
|
|
||||||
|
static regex_t sdt_op_regex1, sdt_op_regex2;
|
||||||
|
|
||||||
|
static int sdt_init_op_regex(void)
|
||||||
|
{
|
||||||
|
static int initialized;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (initialized)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
|
||||||
|
if (ret)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
|
||||||
|
if (ret)
|
||||||
|
goto free_regex1;
|
||||||
|
|
||||||
|
initialized = 1;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free_regex1:
|
||||||
|
regfree(&sdt_op_regex1);
|
||||||
|
error:
|
||||||
|
pr_debug4("Regex compilation error.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SDT marker arguments on Arm64 uses %xREG or [sp, NUM], currently
|
||||||
|
* support these two formats.
|
||||||
|
*/
|
||||||
|
int arch_sdt_arg_parse_op(char *old_op, char **new_op)
|
||||||
|
{
|
||||||
|
int ret, new_len;
|
||||||
|
regmatch_t rm[5];
|
||||||
|
|
||||||
|
ret = sdt_init_op_regex();
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
|
||||||
|
/* Extract xNUM */
|
||||||
|
new_len = 2; /* % NULL */
|
||||||
|
new_len += (int)(rm[1].rm_eo - rm[1].rm_so);
|
||||||
|
|
||||||
|
*new_op = zalloc(new_len);
|
||||||
|
if (!*new_op)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
scnprintf(*new_op, new_len, "%%%.*s",
|
||||||
|
(int)(rm[1].rm_eo - rm[1].rm_so), old_op + rm[1].rm_so);
|
||||||
|
} else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
|
||||||
|
/* [sp], [sp, NUM] or [sp,NUM] */
|
||||||
|
new_len = 7; /* + ( % s p ) NULL */
|
||||||
|
|
||||||
|
/* If the arugment is [sp], need to fill offset '0' */
|
||||||
|
if (rm[2].rm_so == -1)
|
||||||
|
new_len += 1;
|
||||||
|
else
|
||||||
|
new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
|
||||||
|
|
||||||
|
*new_op = zalloc(new_len);
|
||||||
|
if (!*new_op)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (rm[2].rm_so == -1)
|
||||||
|
scnprintf(*new_op, new_len, "+0(%%sp)");
|
||||||
|
else
|
||||||
|
scnprintf(*new_op, new_len, "+%.*s(%%sp)",
|
||||||
|
(int)(rm[2].rm_eo - rm[2].rm_so),
|
||||||
|
old_op + rm[2].rm_so);
|
||||||
|
} else {
|
||||||
|
pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
|
||||||
|
return SDT_ARG_SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDT_ARG_VALID;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue