コード例 #1
0
ファイル: perf_regs.c プロジェクト: Lyude/linux
/*
 * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
 * Possible variants of OP are:
 *	Format		Example
 *	-------------------------
 *	NUM(REG)	48(18)
 *	-NUM(REG)	-48(18)
 *	NUM(%rREG)	48(%r18)
 *	-NUM(%rREG)	-48(%r18)
 *	REG		18
 *	%rREG		%r18
 *	iNUM		i0
 *	i-NUM		i-1
 *
 * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
 * and REG form with -mno-regnames. Here REG is general purpose register,
 * which is in 0 to 31 range.
 */
int arch_sdt_arg_parse_op(char *old_op, char **new_op)
{
	int ret, new_len;
	regmatch_t rm[5];
	char prefix;

	/* Constant argument. Uprobe does not support it */
	if (old_op[0] == 'i') {
		pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
		return SDT_ARG_SKIP;
	}

	ret = sdt_init_op_regex();
	if (ret < 0)
		return ret;

	if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
		/* REG or %rREG --> %gprREG */

		new_len = 5;	/* % g p r NULL */
		new_len += (int)(rm[2].rm_eo - rm[2].rm_so);

		*new_op = zalloc(new_len);
		if (!*new_op)
			return -ENOMEM;

		scnprintf(*new_op, new_len, "%%gpr%.*s",
			(int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so);
	} else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
		/*
		 * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
		 *	+/-NUM(%gprREG)
		 */
		prefix = (rm[1].rm_so == -1) ? '+' : '-';

		new_len = 8;	/* +/- ( % g p r ) NULL */
		new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
		new_len += (int)(rm[4].rm_eo - rm[4].rm_so);

		*new_op = zalloc(new_len);
		if (!*new_op)
			return -ENOMEM;

		scnprintf(*new_op, new_len, "%c%.*s(%%gpr%.*s)", prefix,
			(int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
			(int)(rm[4].rm_eo - rm[4].rm_so), old_op + rm[4].rm_so);
	} else {
		pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
		return SDT_ARG_SKIP;
	}

	return SDT_ARG_VALID;
}
コード例 #2
0
ファイル: perf_regs.c プロジェクト: Lyude/linux
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;
}
コード例 #3
0
ファイル: perf_regs.c プロジェクト: AlexShiLucky/linux
static int sdt_init_op_regex(void)
{
	static int initialized;
	int ret = 0;

	if (initialized)
		return 0;

	ret = regcomp(&sdt_op_regex, SDT_OP_REGEX, REG_EXTENDED);
	if (ret < 0) {
		pr_debug4("Regex compilation error.\n");
		return ret;
	}

	initialized = 1;
	return 0;
}
コード例 #4
0
ファイル: symbol.c プロジェクト: valentil/CS-411-Group-13
static struct symbol *symbol__new(u64 start, u64 len, const char *name)
{
	size_t namelen = strlen(name) + 1;
	struct symbol *self = zalloc(symbol_conf.priv_size +
				     sizeof(*self) + namelen);
	if (self == NULL)
		return NULL;

	if (symbol_conf.priv_size)
		self = ((void *)self) + symbol_conf.priv_size;

	self->start = start;
	self->end   = len ? start + len - 1 : start;

	pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end);

	memcpy(self->name, name, namelen);

	return self;
}
コード例 #5
0
struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
{
    size_t namelen = strlen(name) + 1;
    struct symbol *sym = calloc(1, (symbol_conf.priv_size +
                                    sizeof(*sym) + namelen));
    if (sym == NULL)
        return NULL;

    if (symbol_conf.priv_size)
        sym = ((void *)sym) + symbol_conf.priv_size;

    sym->start   = start;
    sym->end     = len ? start + len - 1 : start;
    sym->binding = binding;
    sym->namelen = namelen - 1;

    pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n",
              __func__, name, start, sym->end);
    memcpy(sym->name, name, namelen);

    return sym;
}
コード例 #6
0
ファイル: perf_regs.c プロジェクト: AlexShiLucky/linux
int arch_sdt_arg_parse_op(char *old_op, char **new_op)
{
	char new_reg[SDT_REG_NAME_SIZE] = {0};
	int new_len = 0, ret;
	/*
	 * rm[0]:  +/-NUM(REG)
	 * rm[1]:  +/-
	 * rm[2]:  NUM
	 * rm[3]:  (
	 * rm[4]:  REG
	 * rm[5]:  )
	 */
	regmatch_t rm[6];
	/*
	 * Max prefix length is 2 as it may contains sign(+/-)
	 * and displacement 0 (Both sign and displacement 0 are
	 * optional so it may be empty). Use one more character
	 * to hold last NULL so that strlen can be used to find
	 * prefix length, instead of maintaing one more variable.
	 */
	char prefix[3] = {0};

	ret = sdt_init_op_regex();
	if (ret < 0)
		return ret;

	/*
	 * If unsupported OR does not match with regex OR
	 * register name too long, skip it.
	 */
	if (strchr(old_op, ',') || strchr(old_op, '$') ||
	    regexec(&sdt_op_regex, old_op, 6, rm, 0)   ||
	    rm[4].rm_eo - rm[4].rm_so > SDT_REG_NAME_SIZE) {
		pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
		return SDT_ARG_SKIP;
	}

	/*
	 * Prepare prefix.
	 * If SDT OP has parenthesis but does not provide
	 * displacement, add 0 for displacement.
	 *     SDT         Uprobe     Prefix
	 *     -----------------------------
	 *     +24(%rdi)   +24(%di)   +
	 *     24(%rdi)    +24(%di)   +
	 *     %rdi        %di
	 *     (%rdi)      +0(%di)    +0
	 *     -80(%rbx)   -80(%bx)   -
	 */
	if (rm[3].rm_so != rm[3].rm_eo) {
		if (rm[1].rm_so != rm[1].rm_eo)
			prefix[0] = *(old_op + rm[1].rm_so);
		else if (rm[2].rm_so != rm[2].rm_eo)
			prefix[0] = '+';
		else
			scnprintf(prefix, sizeof(prefix), "+0");
	}

	/* Rename register */
	sdt_rename_register(old_op + rm[4].rm_so, rm[4].rm_eo - rm[4].rm_so,
			    new_reg);

	/* Prepare final OP which should be valid for uprobe_events */
	new_len = strlen(prefix)              +
		  (rm[2].rm_eo - rm[2].rm_so) +
		  (rm[3].rm_eo - rm[3].rm_so) +
		  strlen(new_reg)             +
		  (rm[5].rm_eo - rm[5].rm_so) +
		  1;					/* NULL */

	*new_op = zalloc(new_len);
	if (!*new_op)
		return -ENOMEM;

	scnprintf(*new_op, new_len, "%.*s%.*s%.*s%.*s%.*s",
		  strlen(prefix), prefix,
		  (int)(rm[2].rm_eo - rm[2].rm_so), old_op + rm[2].rm_so,
		  (int)(rm[3].rm_eo - rm[3].rm_so), old_op + rm[3].rm_so,
		  strlen(new_reg), new_reg,
		  (int)(rm[5].rm_eo - rm[5].rm_so), old_op + rm[5].rm_so);

	return SDT_ARG_VALID;
}