mirror of https://gitee.com/openkylin/linux.git
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: Masami 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: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
4c20194c2d
commit
074fc0e4b3
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue