X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng%2Fcommands%2Fenable_events.c;h=c15edf5fd3deaaeeba49fc86345180475588d288;hb=880e5397bf7966caba19ddb1dc0e0de2a982569c;hp=eaae4941baffbb84f14be0e56eff952ef553c66b;hpb=9c48cab3239afea25eba069a9869a59ecd310c03;p=lttng-tools.git diff --git a/src/bin/lttng/commands/enable_events.c b/src/bin/lttng/commands/enable_events.c index eaae4941b..c15edf5fd 100644 --- a/src/bin/lttng/commands/enable_events.c +++ b/src/bin/lttng/commands/enable_events.c @@ -16,6 +16,7 @@ */ #define _GNU_SOURCE +#include #include #include #include @@ -29,6 +30,10 @@ #include "../command.h" #include +#if (LTTNG_SYMBOL_NAME_LEN == 256) +#define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255" +#endif + static char *opt_event_list; static int opt_event_type; static const char *opt_loglevel; @@ -134,7 +139,8 @@ static void usage(FILE *ofp) fprintf(ofp, " --syscall System call event\n"); fprintf(ofp, "\n"); fprintf(ofp, " --loglevel name\n"); - fprintf(ofp, " Tracepoint loglevel range from 0 to loglevel\n"); + fprintf(ofp, " Tracepoint loglevel range from 0 to loglevel.\n"); + fprintf(ofp, " For JUL domain, see the table below for the range values.\n"); fprintf(ofp, " --loglevel-only name\n"); fprintf(ofp, " Tracepoint loglevel (only this loglevel)\n"); fprintf(ofp, "\n"); @@ -159,6 +165,19 @@ static void usage(FILE *ofp) fprintf(ofp, " TRACE_DEBUG_LINE = 13\n"); fprintf(ofp, " TRACE_DEBUG = 14\n"); fprintf(ofp, " (shortcuts such as \"system\" are allowed)\n"); + fprintf(ofp, "\n"); + fprintf(ofp, " Available JUL domain loglevels:\n"); + fprintf(ofp, " JUL_OFF = INT32_MAX\n"); + fprintf(ofp, " JUL_SEVERE = %d\n", LTTNG_LOGLEVEL_JUL_SEVERE); + fprintf(ofp, " JUL_WARNING = %d\n", LTTNG_LOGLEVEL_JUL_WARNING); + fprintf(ofp, " JUL_INFO = %d\n", LTTNG_LOGLEVEL_JUL_INFO); + fprintf(ofp, " JUL_CONFIG = %d\n", LTTNG_LOGLEVEL_JUL_CONFIG); + fprintf(ofp, " JUL_FINE = %d\n", LTTNG_LOGLEVEL_JUL_FINE); + fprintf(ofp, " JUL_FINER = %d\n", LTTNG_LOGLEVEL_JUL_FINER); + fprintf(ofp, " JUL_FINEST = %d\n", LTTNG_LOGLEVEL_JUL_FINEST); + fprintf(ofp, " JUL_ALL = INT32_MIN\n"); + fprintf(ofp, " (shortcuts such as \"severe\" are allowed)\n"); + fprintf(ofp, "\n"); fprintf(ofp, " -f, --filter \'expression\'\n"); fprintf(ofp, " Filter expression on event fields and context.\n"); fprintf(ofp, " Event recording depends on evaluation.\n"); @@ -209,24 +228,27 @@ static void usage(FILE *ofp) */ static int parse_probe_opts(struct lttng_event *ev, char *opt) { - int ret; + int ret = CMD_SUCCESS; + int match; char s_hex[19]; +#define S_HEX_LEN_SCANF_IS_A_BROKEN_API "18" /* 18 is (19 - 1) (\0 is extra) */ char name[LTTNG_SYMBOL_NAME_LEN]; if (opt == NULL) { - ret = -1; + ret = CMD_ERROR; goto end; } /* Check for symbol+offset */ - ret = sscanf(opt, "%[^'+']+%s", name, s_hex); - if (ret == 2) { + match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API + "[^'+']+%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", name, s_hex); + if (match == 2) { strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN); ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; DBG("probe symbol %s", ev->attr.probe.symbol_name); if (*s_hex == '\0') { ERR("Invalid probe offset %s", s_hex); - ret = -1; + ret = CMD_ERROR; goto end; } ev->attr.probe.offset = strtoul(s_hex, NULL, 0); @@ -237,8 +259,9 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) /* Check for symbol */ if (isalpha(name[0])) { - ret = sscanf(opt, "%s", name); - if (ret == 1) { + match = sscanf(opt, "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "s", + name); + if (match == 1) { strncpy(ev->attr.probe.symbol_name, name, LTTNG_SYMBOL_NAME_LEN); ev->attr.probe.symbol_name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; DBG("probe symbol %s", ev->attr.probe.symbol_name); @@ -250,11 +273,11 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) } /* Check for address */ - ret = sscanf(opt, "%s", s_hex); - if (ret > 0) { + match = sscanf(opt, "%" S_HEX_LEN_SCANF_IS_A_BROKEN_API "s", s_hex); + if (match > 0) { if (*s_hex == '\0') { ERR("Invalid probe address %s", s_hex); - ret = -1; + ret = CMD_ERROR; goto end; } ev->attr.probe.addr = strtoul(s_hex, NULL, 0); @@ -265,12 +288,53 @@ static int parse_probe_opts(struct lttng_event *ev, char *opt) } /* No match */ - ret = -1; + ret = CMD_ERROR; end: return ret; } +/* + * Maps JUL loglevel from string to value + */ +static int loglevel_jul_str_to_value(const char *inputstr) +{ + int i = 0; + char str[LTTNG_SYMBOL_NAME_LEN]; + + /* + * Loop up to LTTNG_SYMBOL_NAME_LEN minus one because the NULL bytes is + * added at the end of the loop so a the upper bound we avoid the overflow. + */ + while (i < (LTTNG_SYMBOL_NAME_LEN - 1) && inputstr[i] != '\0') { + str[i] = toupper(inputstr[i]); + i++; + } + str[i] = '\0'; + + if (!strcmp(str, "JUL_OFF") || !strcmp(str, "OFF")) { + return LTTNG_LOGLEVEL_JUL_OFF; + } else if (!strcmp(str, "JUL_SEVERE") || !strcmp(str, "SEVERE")) { + return LTTNG_LOGLEVEL_JUL_SEVERE; + } else if (!strcmp(str, "JUL_WARNING") || !strcmp(str, "WARNING")) { + return LTTNG_LOGLEVEL_JUL_WARNING; + } else if (!strcmp(str, "JUL_INFO") || !strcmp(str, "INFO")) { + return LTTNG_LOGLEVEL_JUL_INFO; + } else if (!strcmp(str, "JUL_CONFIG") || !strcmp(str, "CONFIG")) { + return LTTNG_LOGLEVEL_JUL_CONFIG; + } else if (!strcmp(str, "JUL_FINE") || !strcmp(str, "FINE")) { + return LTTNG_LOGLEVEL_JUL_FINE; + } else if (!strcmp(str, "JUL_FINER") || !strcmp(str, "FINER")) { + return LTTNG_LOGLEVEL_JUL_FINER; + } else if (!strcmp(str, "JUL_FINEST") || !strcmp(str, "FINEST")) { + return LTTNG_LOGLEVEL_JUL_FINEST; + } else if (!strcmp(str, "JUL_ALL") || !strcmp(str, "ALL")) { + return LTTNG_LOGLEVEL_JUL_ALL; + } else { + return -1; + } +} + /* * Maps loglevel from string to value */ @@ -358,7 +422,10 @@ char *print_exclusions(int count, char **names) /* add length of preamble + one for NUL - one for last (missing) comma */ length += strlen(preamble); - ret = malloc(length); + ret = zmalloc(length); + if (!ret) { + return NULL; + } strncpy(ret, preamble, length); for (i = 0; i < count; i++) { strcat(ret, names[i]); @@ -527,14 +594,24 @@ static int enable_events(char *session_name) strcpy(ev.name, "*"); ev.loglevel_type = opt_loglevel_type; if (opt_loglevel) { - ev.loglevel = loglevel_str_to_value(opt_loglevel); + assert(opt_userspace || opt_jul); + if (opt_userspace) { + ev.loglevel = loglevel_str_to_value(opt_loglevel); + } else if (opt_jul) { + ev.loglevel = loglevel_jul_str_to_value(opt_loglevel); + } if (ev.loglevel == -1) { ERR("Unknown loglevel %s", opt_loglevel); ret = -LTTNG_ERR_INVALID; goto error; } } else { - ev.loglevel = -1; + assert(opt_userspace || opt_jul); + if (opt_userspace) { + ev.loglevel = -1; + } else if (opt_jul) { + ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL; + } } } @@ -556,6 +633,16 @@ static int enable_events(char *session_name) WARN("Kernel events already enabled (channel %s, session %s)", print_channel_name(channel_name), session_name); break; + case LTTNG_ERR_TRACE_ALREADY_STARTED: + { + const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; + ERR("Events: %s (channel %s, session %s)", + msg, + print_channel_name(channel_name), + session_name); + ret = CMD_ERROR; + break; + } default: ERR("Events: %s (channel %s, session %s)", lttng_strerror(ret), @@ -629,6 +716,16 @@ static int enable_events(char *session_name) " (channel %s, session %s)", print_channel_name(channel_name), session_name); break; + case LTTNG_ERR_TRACE_ALREADY_STARTED: + { + const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; + ERR("All events: %s (channel %s, session %s, filter \'%s\')", + msg, + print_channel_name(channel_name), + session_name, opt_filter); + ret = CMD_ERROR; + break; + } default: ERR("All events: %s (channel %s, session %s, filter \'%s\')", lttng_strerror(ret), @@ -668,7 +765,7 @@ static int enable_events(char *session_name) break; case LTTNG_EVENT_PROBE: ret = parse_probe_opts(&ev, opt_probe); - if (ret < 0) { + if (ret) { ERR("Unable to parse probe options"); ret = 0; goto error; @@ -676,7 +773,7 @@ static int enable_events(char *session_name) break; case LTTNG_EVENT_FUNCTION: ret = parse_probe_opts(&ev, opt_function); - if (ret < 0) { + if (ret) { ERR("Unable to parse function probe options"); ret = 0; goto error; @@ -768,6 +865,18 @@ static int enable_events(char *session_name) ret = CMD_UNSUPPORTED; goto error; } + + ev.loglevel_type = opt_loglevel_type; + if (opt_loglevel) { + ev.loglevel = loglevel_jul_str_to_value(opt_loglevel); + if (ev.loglevel == -1) { + ERR("Unknown loglevel %s", opt_loglevel); + ret = -LTTNG_ERR_INVALID; + goto error; + } + } else { + ev.loglevel = LTTNG_LOGLEVEL_JUL_ALL; + } ev.type = LTTNG_EVENT_TRACEPOINT; strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN); ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; @@ -792,7 +901,19 @@ static int enable_events(char *session_name) event_name, exclusion_string, print_channel_name(channel_name), session_name); + warn = 1; + break; + case LTTNG_ERR_TRACE_ALREADY_STARTED: + { + const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; + ERR("Event %s%s: %s (channel %s, session %s)", event_name, + exclusion_string, + msg, + print_channel_name(channel_name), + session_name); + ret = CMD_ERROR; break; + } default: ERR("Event %s%s: %s (channel %s, session %s)", event_name, exclusion_string, @@ -801,9 +922,9 @@ static int enable_events(char *session_name) ? print_raw_channel_name(channel_name) : print_channel_name(channel_name), session_name); + warn = 1; break; } - warn = 1; } else { MSG("%s event %s%s created in channel %s", get_domain_str(dom.type), event_name, @@ -829,6 +950,17 @@ static int enable_events(char *session_name) exclusion_string, print_channel_name(channel_name), session_name); break; + case LTTNG_ERR_TRACE_ALREADY_STARTED: + { + const char *msg = "The command tried to enable an event in a new domain for a session that has already been started once."; + ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name, + exclusion_string, + msg, + print_channel_name(channel_name), + session_name, opt_filter); + ret = CMD_ERROR; + break; + } default: ERR("Event %s%s: %s (channel %s, session %s, filter \'%s\')", ev.name, exclusion_string, @@ -839,6 +971,7 @@ static int enable_events(char *session_name) session_name, opt_filter); break; } + free(exclusion_string); goto error; } else { MSG("Event %s%s: Filter '%s' successfully set",