Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 074fc0e4 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Ingo Molnar
Browse files

perf: Use die() for error cases in perf-probe



Use die() for exiting perf-probe with errors. This replaces
perror_exit(), msg_exit() and fprintf()+exit() with die(), and
uses die() in semantic_error().

This also renames 'die' local variables to 'dw_die' for avoiding
name confliction.

Signed-off-by: default avatarMasami Hiramatsu <mhiramat@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20091017000801.16556.46866.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 4c20194c
Loading
Loading
Loading
Loading
+14 −33
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@ const char *default_search_path[NR_SEARCH_PATH] = {


#define MAX_PATH_LEN 256
#define MAX_PATH_LEN 256
#define MAX_PROBES 128
#define MAX_PROBES 128
#define MAX_PROBE_ARGS 128


/* Session management structure */
/* Session management structure */
static struct {
static struct {
@@ -60,19 +61,7 @@ static struct {
	char *events[MAX_PROBES];
	char *events[MAX_PROBES];
} session;
} session;


static void semantic_error(const char *msg)
#define semantic_error(msg ...) die("Semantic error :" msg)
{
	fprintf(stderr, "Semantic error: %s\n", msg);
	exit(1);
}

static void perror_exit(const char *msg)
{
	perror(msg);
	exit(1);
}

#define MAX_PROBE_ARGS 128


static int parse_probepoint(const struct option *opt __used,
static int parse_probepoint(const struct option *opt __used,
			    const char *str, int unset __used)
			    const char *str, int unset __used)
@@ -109,7 +98,7 @@ static int parse_probepoint(const struct option *opt __used,
			/* Duplicate the argument */
			/* Duplicate the argument */
			argv[argc] = strndup(s, str - s);
			argv[argc] = strndup(s, str - s);
			if (argv[argc] == NULL)
			if (argv[argc] == NULL)
				perror_exit("strndup");
				die("strndup");
			if (++argc == MAX_PROBE_ARGS)
			if (++argc == MAX_PROBE_ARGS)
				semantic_error("Too many arguments");
				semantic_error("Too many arguments");
			debug("argv[%d]=%s\n", argc, argv[argc - 1]);
			debug("argv[%d]=%s\n", argc, argv[argc - 1]);
@@ -171,7 +160,7 @@ static int parse_probepoint(const struct option *opt __used,
	if (pp->nr_args > 0) {
	if (pp->nr_args > 0) {
		pp->args = (char **)malloc(sizeof(char *) * pp->nr_args);
		pp->args = (char **)malloc(sizeof(char *) * pp->nr_args);
		if (!pp->args)
		if (!pp->args)
			perror_exit("malloc");
			die("malloc");
		memcpy(pp->args, &argv[2], sizeof(char *) * pp->nr_args);
		memcpy(pp->args, &argv[2], sizeof(char *) * pp->nr_args);
	}
	}


@@ -260,7 +249,7 @@ static int write_new_event(int fd, const char *buf)
	printf("Adding new event: %s\n", buf);
	printf("Adding new event: %s\n", buf);
	ret = write(fd, buf, strlen(buf));
	ret = write(fd, buf, strlen(buf));
	if (ret <= 0)
	if (ret <= 0)
		perror("Error: Failed to create event");
		die("failed to create event.");


	return ret;
	return ret;
}
}
@@ -273,7 +262,7 @@ static int synthesize_probepoint(struct probe_point *pp)
	int i, len, ret;
	int i, len, ret;
	pp->probes[0] = buf = (char *)calloc(MAX_CMDLEN, sizeof(char));
	pp->probes[0] = buf = (char *)calloc(MAX_CMDLEN, sizeof(char));
	if (!buf)
	if (!buf)
		perror_exit("calloc");
		die("calloc");
	ret = snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
	ret = snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset);
	if (ret <= 0 || ret >= MAX_CMDLEN)
	if (ret <= 0 || ret >= MAX_CMDLEN)
		goto error;
		goto error;
@@ -322,10 +311,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
		ret = synthesize_probepoint(&session.probes[j]);
		ret = synthesize_probepoint(&session.probes[j]);
		if (ret == -E2BIG)
		if (ret == -E2BIG)
			semantic_error("probe point is too long.");
			semantic_error("probe point is too long.");
		else if (ret < 0) {
		else if (ret < 0)
			perror("snprintf");
			die("snprintf");
			return -1;
		}
	}
	}


#ifndef NO_LIBDWARF
#ifndef NO_LIBDWARF
@@ -336,10 +323,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
		fd = open(session.vmlinux, O_RDONLY);
		fd = open(session.vmlinux, O_RDONLY);
	else
	else
		fd = open_default_vmlinux();
		fd = open_default_vmlinux();
	if (fd < 0) {
	if (fd < 0)
		perror("vmlinux/module file open");
		die("vmlinux/module file open");
		return -1;
	}


	/* Searching probe points */
	/* Searching probe points */
	for (j = 0; j < session.nr_probe; j++) {
	for (j = 0; j < session.nr_probe; j++) {
@@ -349,10 +334,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)


		lseek(fd, SEEK_SET, 0);
		lseek(fd, SEEK_SET, 0);
		ret = find_probepoint(fd, pp);
		ret = find_probepoint(fd, pp);
		if (ret <= 0) {
		if (ret <= 0)
			fprintf(stderr, "Error: No probe point found.\n");
			die("No probe point found.\n");
			return -1;
		}
		debug("probe event %s found\n", session.events[j]);
		debug("probe event %s found\n", session.events[j]);
	}
	}
	close(fd);
	close(fd);
@@ -363,10 +346,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
	/* Settng up probe points */
	/* Settng up probe points */
	snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path);
	snprintf(buf, MAX_CMDLEN, "%s/../kprobe_events", debugfs_path);
	fd = open(buf, O_WRONLY, O_APPEND);
	fd = open(buf, O_WRONLY, O_APPEND);
	if (fd < 0) {
	if (fd < 0)
		perror("kprobe_events open");
		die("kprobe_events open");
		return -1;
	}
	for (j = 0; j < session.nr_probe; j++) {
	for (j = 0; j < session.nr_probe; j++) {
		pp = &session.probes[j];
		pp = &session.probes[j];
		if (pp->found == 1) {
		if (pp->found == 1) {
+20 −35
Original line number Original line Diff line number Diff line
@@ -31,6 +31,8 @@
#include <string.h>
#include <string.h>
#include <stdarg.h>
#include <stdarg.h>
#include <ctype.h>
#include <ctype.h>

#include "util.h"
#include "probe-finder.h"
#include "probe-finder.h"




@@ -43,20 +45,6 @@ struct die_link {
static Dwarf_Debug __dw_debug;
static Dwarf_Debug __dw_debug;
static Dwarf_Error __dw_error;
static Dwarf_Error __dw_error;


static void msg_exit(int ret, const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	fprintf(stderr, "Error:  ");
	vfprintf(stderr, fmt, ap);
	va_end(ap);

	fprintf(stderr, "\n");
	exit(ret);
}


/*
/*
 * Generic dwarf analysis helpers
 * Generic dwarf analysis helpers
 */
 */
@@ -151,11 +139,11 @@ static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname)
}
}


/* Compare diename and tname */
/* Compare diename and tname */
static int die_compare_name(Dwarf_Die die, const char *tname)
static int die_compare_name(Dwarf_Die dw_die, const char *tname)
{
{
	char *name;
	char *name;
	int ret;
	int ret;
	ret = dwarf_diename(die, &name, &__dw_error);
	ret = dwarf_diename(dw_die, &name, &__dw_error);
	ERR_IF(ret == DW_DLV_ERROR);
	ERR_IF(ret == DW_DLV_ERROR);
	if (ret == DW_DLV_OK) {
	if (ret == DW_DLV_OK) {
		ret = strcmp(tname, name);
		ret = strcmp(tname, name);
@@ -187,25 +175,25 @@ static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
}
}


/* Check the die is inlined function */
/* Check the die is inlined function */
static Dwarf_Bool die_inlined_subprogram(Dwarf_Die die)
static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
{
{
	/* TODO: check strictly */
	/* TODO: check strictly */
	Dwarf_Bool inl;
	Dwarf_Bool inl;
	int ret;
	int ret;


	ret = dwarf_hasattr(die, DW_AT_inline, &inl, &__dw_error);
	ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
	ERR_IF(ret == DW_DLV_ERROR);
	ERR_IF(ret == DW_DLV_ERROR);
	return inl;
	return inl;
}
}


/* Get the offset of abstruct_origin */
/* Get the offset of abstruct_origin */
static Dwarf_Off die_get_abstract_origin(Dwarf_Die die)
static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
{
{
	Dwarf_Attribute attr;
	Dwarf_Attribute attr;
	Dwarf_Off cu_offs;
	Dwarf_Off cu_offs;
	int ret;
	int ret;


	ret = dwarf_attr(die, DW_AT_abstract_origin, &attr, &__dw_error);
	ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
	ERR_IF(ret != DW_DLV_OK);
	ERR_IF(ret != DW_DLV_OK);
	ret = dwarf_formref(attr, &cu_offs, &__dw_error);
	ret = dwarf_formref(attr, &cu_offs, &__dw_error);
	ERR_IF(ret != DW_DLV_OK);
	ERR_IF(ret != DW_DLV_OK);
@@ -214,7 +202,7 @@ static Dwarf_Off die_get_abstract_origin(Dwarf_Die die)
}
}


/* Get entry pc(or low pc, 1st entry of ranges)  of the die */
/* Get entry pc(or low pc, 1st entry of ranges)  of the die */
static Dwarf_Addr die_get_entrypc(Dwarf_Die die)
static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
{
{
	Dwarf_Attribute attr;
	Dwarf_Attribute attr;
	Dwarf_Addr addr;
	Dwarf_Addr addr;
@@ -224,7 +212,7 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die die)
	int ret;
	int ret;


	/* Try to get entry pc */
	/* Try to get entry pc */
	ret = dwarf_attr(die, DW_AT_entry_pc, &attr, &__dw_error);
	ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
	ERR_IF(ret == DW_DLV_ERROR);
	ERR_IF(ret == DW_DLV_ERROR);
	if (ret == DW_DLV_OK) {
	if (ret == DW_DLV_OK) {
		ret = dwarf_formaddr(attr, &addr, &__dw_error);
		ret = dwarf_formaddr(attr, &addr, &__dw_error);
@@ -234,13 +222,13 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die die)
	}
	}


	/* Try to get low pc */
	/* Try to get low pc */
	ret = dwarf_lowpc(die, &addr, &__dw_error);
	ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
	ERR_IF(ret == DW_DLV_ERROR);
	ERR_IF(ret == DW_DLV_ERROR);
	if (ret == DW_DLV_OK)
	if (ret == DW_DLV_OK)
		return addr;
		return addr;


	/* Try to get ranges */
	/* Try to get ranges */
	ret = dwarf_attr(die, DW_AT_ranges, &attr, &__dw_error);
	ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
	ERR_IF(ret != DW_DLV_OK);
	ERR_IF(ret != DW_DLV_OK);
	ret = dwarf_formref(attr, &offs, &__dw_error);
	ret = dwarf_formref(attr, &offs, &__dw_error);
	ERR_IF(ret != DW_DLV_OK);
	ERR_IF(ret != DW_DLV_OK);
@@ -382,11 +370,11 @@ static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
	} else if (op == DW_OP_regx) {
	} else if (op == DW_OP_regx) {
		regn = loc->lr_number;
		regn = loc->lr_number;
	} else
	} else
		msg_exit(-EINVAL, "Dwarf_OP %d is not supported.\n", op);
		die("Dwarf_OP %d is not supported.\n", op);


	regs = get_arch_regstr(regn);
	regs = get_arch_regstr(regn);
	if (!regs)
	if (!regs)
		msg_exit(-EINVAL, "%lld exceeds max register number.\n", regn);
		die("%lld exceeds max register number.\n", regn);


	if (deref)
	if (deref)
		ret = snprintf(pf->buf, pf->len,
		ret = snprintf(pf->buf, pf->len,
@@ -417,8 +405,8 @@ static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
	dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
	return ;
	return ;
error:
error:
	msg_exit(-1, "Failed to find the location of %s at this address.\n"
	die("Failed to find the location of %s at this address.\n"
		 " Perhaps, it was optimized out.\n", pf->var);
	    " Perhaps, it has been optimized out.\n", pf->var);
}
}


static int variable_callback(struct die_link *dlink, void *data)
static int variable_callback(struct die_link *dlink, void *data)
@@ -456,8 +444,7 @@ static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
	/* Search child die for local variables and parameters. */
	/* Search child die for local variables and parameters. */
	ret = search_die_from_children(sp_die, variable_callback, pf);
	ret = search_die_from_children(sp_die, variable_callback, pf);
	if (!ret)
	if (!ret)
		msg_exit(-1, "Failed to find '%s' in this function.\n",
		die("Failed to find '%s' in this function.\n", pf->var);
			 pf->var);
}
}


/* Get a frame base on the address */
/* Get a frame base on the address */
@@ -568,8 +555,7 @@ static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf)
		/* Search a real subprogram including this line, */
		/* Search a real subprogram including this line, */
		ret = search_die_from_children(cu_die, probeaddr_callback, pf);
		ret = search_die_from_children(cu_die, probeaddr_callback, pf);
		if (ret == 0)
		if (ret == 0)
			msg_exit(-1,
			die("Probe point is not found in subprograms.\n");
				 "Probe point is not found in subprograms.\n");
		/* Continuing, because target line might be inlined. */
		/* Continuing, because target line might be inlined. */
	}
	}
	dwarf_srclines_dealloc(__dw_debug, lines, cnt);
	dwarf_srclines_dealloc(__dw_debug, lines, cnt);
@@ -621,7 +607,7 @@ static int probefunc_callback(struct die_link *dlink, void *data)
				    !die_inlined_subprogram(lk->die))
				    !die_inlined_subprogram(lk->die))
					goto found;
					goto found;
			}
			}
			msg_exit(-1, "Failed to find real subprogram.\n");
			die("Failed to find real subprogram.\n");
found:
found:
			/* Get offset from subprogram */
			/* Get offset from subprogram */
			ret = die_within_subprogram(lk->die, pf->addr, &offs);
			ret = die_within_subprogram(lk->die, pf->addr, &offs);
@@ -649,8 +635,7 @@ int find_probepoint(int fd, struct probe_point *pp)


	ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
	ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
	if (ret != DW_DLV_OK)
	if (ret != DW_DLV_OK)
		msg_exit(-1, "Failed to call dwarf_init(). "
		die("Failed to call dwarf_init(). Maybe, not a dwarf file.\n");
			 "Maybe, not a dwarf file?\n");


	pp->found = 0;
	pp->found = 0;
	while (++cu_number) {
	while (++cu_number) {