brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · d633d15 Raw
328 lines · c
1// SPDX-License-Identifier: GPL-2.02/* For general debugging purposes */3 4#include <inttypes.h>5#include <string.h>6#include <stdarg.h>7#include <stdio.h>8#include <stdlib.h>9#include <sys/wait.h>10#include <api/debug.h>11#include <linux/kernel.h>12#include <linux/time64.h>13#include <sys/time.h>14#ifdef HAVE_BACKTRACE_SUPPORT15#include <execinfo.h>16#endif17#include "color.h"18#include "event.h"19#include "debug.h"20#include "print_binary.h"21#include "target.h"22#include "trace-event.h"23#include "ui/helpline.h"24#include "ui/ui.h"25#include "util/parse-sublevel-options.h"26 27#include <linux/ctype.h>28 29#ifdef HAVE_LIBTRACEEVENT30#include <traceevent/event-parse.h>31#else32#define LIBTRACEEVENT_VERSION 033#endif34 35int verbose;36int debug_kmaps;37int debug_peo_args;38bool dump_trace = false, quiet = false;39int debug_ordered_events;40static int redirect_to_stderr;41int debug_data_convert;42static FILE *_debug_file;43bool debug_display_time;44int debug_type_profile;45 46FILE *debug_file(void)47{48	if (!_debug_file) {49		pr_warning_once("debug_file not set");50		debug_set_file(stderr);51	}52	return _debug_file;53}54 55void debug_set_file(FILE *file)56{57	_debug_file = file;58}59 60void debug_set_display_time(bool set)61{62	debug_display_time = set;63}64 65static int fprintf_time(FILE *file)66{67	struct timeval tod;68	struct tm ltime;69	char date[64];70 71	if (!debug_display_time)72		return 0;73 74	if (gettimeofday(&tod, NULL) != 0)75		return 0;76 77	if (localtime_r(&tod.tv_sec, &ltime) == NULL)78		return 0;79 80	strftime(date, sizeof(date),  "%F %H:%M:%S", &ltime);81	return fprintf(file, "[%s.%06lu] ", date, (long)tod.tv_usec);82}83 84int veprintf(int level, int var, const char *fmt, va_list args)85{86	int ret = 0;87 88	if (var >= level) {89		if (use_browser >= 1 && !redirect_to_stderr) {90			ui_helpline__vshow(fmt, args);91		} else {92			ret = fprintf_time(debug_file());93			ret += vfprintf(debug_file(), fmt, args);94		}95	}96 97	return ret;98}99 100int eprintf(int level, int var, const char *fmt, ...)101{102	va_list args;103	int ret;104 105	va_start(args, fmt);106	ret = veprintf(level, var, fmt, args);107	va_end(args);108 109	return ret;110}111 112static int veprintf_time(u64 t, const char *fmt, va_list args)113{114	int ret = 0;115	u64 secs, usecs, nsecs = t;116 117	secs   = nsecs / NSEC_PER_SEC;118	nsecs -= secs  * NSEC_PER_SEC;119	usecs  = nsecs / NSEC_PER_USEC;120 121	ret = fprintf(debug_file(), "[%13" PRIu64 ".%06" PRIu64 "] ", secs, usecs);122	ret += vfprintf(debug_file(), fmt, args);123	return ret;124}125 126int eprintf_time(int level, int var, u64 t, const char *fmt, ...)127{128	int ret = 0;129	va_list args;130 131	if (var >= level) {132		va_start(args, fmt);133		ret = veprintf_time(t, fmt, args);134		va_end(args);135	}136 137	return ret;138}139 140/*141 * Overloading libtraceevent standard info print142 * function, display with -v in perf.143 */144void pr_stat(const char *fmt, ...)145{146	va_list args;147 148	va_start(args, fmt);149	veprintf(1, verbose, fmt, args);150	va_end(args);151	eprintf(1, verbose, "\n");152}153 154int dump_printf(const char *fmt, ...)155{156	va_list args;157	int ret = 0;158 159	if (dump_trace) {160		va_start(args, fmt);161		ret = vprintf(fmt, args);162		va_end(args);163	}164 165	return ret;166}167 168static int trace_event_printer(enum binary_printer_ops op,169			       unsigned int val, void *extra, FILE *fp)170{171	const char *color = PERF_COLOR_BLUE;172	union perf_event *event = (union perf_event *)extra;173	unsigned char ch = (unsigned char)val;174	int printed = 0;175 176	switch (op) {177	case BINARY_PRINT_DATA_BEGIN:178		printed += fprintf(fp, ".");179		printed += color_fprintf(fp, color, "\n. ... raw event: size %d bytes\n",180					 event->header.size);181		break;182	case BINARY_PRINT_LINE_BEGIN:183		printed += fprintf(fp, ".");184		break;185	case BINARY_PRINT_ADDR:186		printed += color_fprintf(fp, color, "  %04x: ", val);187		break;188	case BINARY_PRINT_NUM_DATA:189		printed += color_fprintf(fp, color, " %02x", val);190		break;191	case BINARY_PRINT_NUM_PAD:192		printed += color_fprintf(fp, color, "   ");193		break;194	case BINARY_PRINT_SEP:195		printed += color_fprintf(fp, color, "  ");196		break;197	case BINARY_PRINT_CHAR_DATA:198		printed += color_fprintf(fp, color, "%c",199			      isprint(ch) && isascii(ch) ? ch : '.');200		break;201	case BINARY_PRINT_CHAR_PAD:202		printed += color_fprintf(fp, color, " ");203		break;204	case BINARY_PRINT_LINE_END:205		printed += color_fprintf(fp, color, "\n");206		break;207	case BINARY_PRINT_DATA_END:208		printed += fprintf(fp, "\n");209		break;210	default:211		break;212	}213 214	return printed;215}216 217void trace_event(union perf_event *event)218{219	unsigned char *raw_event = (void *)event;220 221	if (!dump_trace)222		return;223 224	print_binary(raw_event, event->header.size, 16,225		     trace_event_printer, event);226}227 228static struct sublevel_option debug_opts[] = {229	{ .name = "verbose",		.value_ptr = &verbose },230	{ .name = "ordered-events",	.value_ptr = &debug_ordered_events},231	{ .name = "stderr",		.value_ptr = &redirect_to_stderr},232	{ .name = "data-convert",	.value_ptr = &debug_data_convert },233	{ .name = "perf-event-open",	.value_ptr = &debug_peo_args },234	{ .name = "kmaps",		.value_ptr = &debug_kmaps },235	{ .name = "type-profile",	.value_ptr = &debug_type_profile },236	{ .name = NULL, }237};238 239int perf_debug_option(const char *str)240{241	int ret;242 243	ret = perf_parse_sublevel_options(str, debug_opts);244	if (ret)245		return ret;246 247	/* Allow only verbose value in range (0, 10), otherwise set 0. */248	verbose = (verbose < 0) || (verbose > 10) ? 0 : verbose;249 250#if LIBTRACEEVENT_VERSION >= MAKE_LIBTRACEEVENT_VERSION(1, 3, 0)251	if (verbose == 1)252		tep_set_loglevel(TEP_LOG_INFO);253	else if (verbose == 2)254		tep_set_loglevel(TEP_LOG_DEBUG);255	else if (verbose >= 3)256		tep_set_loglevel(TEP_LOG_ALL);257#endif258	return 0;259}260 261int perf_quiet_option(void)262{263	struct sublevel_option *opt = &debug_opts[0];264 265	/* disable all debug messages */266	while (opt->name) {267		*opt->value_ptr = -1;268		opt++;269	}270 271	/* For debug variables that are used as bool types, set to 0. */272	redirect_to_stderr = 0;273	debug_peo_args = 0;274	debug_kmaps = 0;275	debug_type_profile = 0;276 277	return 0;278}279 280#define DEBUG_WRAPPER(__n, __l)				\281static int pr_ ## __n ## _wrapper(const char *fmt, ...)	\282{							\283	va_list args;					\284	int ret;					\285							\286	va_start(args, fmt);				\287	ret = veprintf(__l, verbose, fmt, args);	\288	va_end(args);					\289	return ret;					\290}291 292DEBUG_WRAPPER(warning, 0);293DEBUG_WRAPPER(debug, 1);294 295void perf_debug_setup(void)296{297	debug_set_file(stderr);298	libapi_set_print(pr_warning_wrapper, pr_warning_wrapper, pr_debug_wrapper);299}300 301/* Obtain a backtrace and print it to stdout. */302#ifdef HAVE_BACKTRACE_SUPPORT303void dump_stack(void)304{305	void *array[16];306	size_t size = backtrace(array, ARRAY_SIZE(array));307	char **strings = backtrace_symbols(array, size);308	size_t i;309 310	printf("Obtained %zd stack frames.\n", size);311 312	for (i = 0; i < size; i++)313		printf("%s\n", strings[i]);314 315	free(strings);316}317#else318void dump_stack(void) {}319#endif320 321void sighandler_dump_stack(int sig)322{323	psignal(sig, "perf");324	dump_stack();325	signal(sig, SIG_DFL);326	raise(sig);327}328