diff --git a/contrib/trace/trace.awk b/contrib/trace/trace.awk index 8c8854a90..6bd5b10a5 100755 --- a/contrib/trace/trace.awk +++ b/contrib/trace/trace.awk @@ -44,6 +44,8 @@ BEGIN { indents[">",i-1] = indents[">",i-1] " " indents["<",i] = indents["<",i-1] " " indents["<",i-1] = indents["<",i-1] " " + indents[" ",i] = indents[" ",i-1] "##" + indents[" ",i-1] = indents[" ",i-1] " " } } @@ -61,7 +63,13 @@ function getptr(ptr) } { - # input format: + # input format: [|...] + if ($3 == "#") { # this is a trace comment + printf "%s %s ", $1, indents[" ",$2] + $1=""; $2=""; $3="" + print substr($0,4) + next + } getptr($3); caller_loc=loc; caller_name=name getptr($5); callee_loc=loc; callee_name=name printf "%s %s %s %s %s [%s:%s] %s [%s:%s]\n", diff --git a/include/common/standard.h b/include/common/standard.h index 535efa736..18d90566d 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -1105,6 +1105,10 @@ char *env_expand(char *in); */ void debug_hexdump(FILE *out, const char *pfx, const char *buf, unsigned int baseaddr, int len); +/* this is used to emit traces when building with TRACE=1 */ +__attribute__((format(printf, 1, 2))) +void trace(char *fmt, ...); + /* used from everywhere just to drain results we don't want to read and which * recent versions of gcc increasingly and annoyingly complain about. */ diff --git a/src/standard.c b/src/standard.c index 174edd2cc..db312dd18 100644 --- a/src/standard.c +++ b/src/standard.c @@ -3880,6 +3880,12 @@ void debug_hexdump(FILE *out, const char *pfx, const char *buf, } } +/* do nothing, just a placeholder for debugging calls, the real one is in trace.c */ +__attribute__((weak,format(printf, 1, 2))) +void trace(char *msg, ...) +{ +} + /* * Local variables: * c-indent-level: 8 diff --git a/src/trace.c b/src/trace.c index 4bbbc302a..9425be9f7 100644 --- a/src/trace.c +++ b/src/trace.c @@ -29,11 +29,20 @@ * * where is '>' when entering a function and '<' when leaving. * + * It is also possible to emit comments using the trace() function which uses + * the printf() format. Such comments are then inserted by replacing the caller + * pointer with a sharp ('#') like this : + * + * # + * or : + * # + * * The article below is a nice explanation of how this works : * http://balau82.wordpress.com/2010/10/06/trace-and-profile-function-calls-with-gcc/ */ #include +#include #include #include #include @@ -229,3 +238,33 @@ void __cyg_profile_func_exit(void *to, void *from) if (!disabled) return make_line(from, to, level--, '<'); } + +/* the one adds comments in the trace above. The output format is : + * # + */ +__attribute__((format(printf, 1, 2))) +void trace(char *fmt, ...) +{ + va_list ap; + + if (unlikely(!log) && !open_trace()) + return; + + if (unlikely(!fast_time)) + gettimeofday(now_ptr, NULL); + + if (!use_tsc) + fprintf(log, "%u.%06u %d # ", + (unsigned int)now_ptr->tv_sec, + (unsigned int)now_ptr->tv_usec, + level + 1); + else + fprintf(log, "%llx %d # ", + rdtsc(), level + 1); + + va_start(ap, fmt); + vfprintf(log, fmt, ap); + va_end(ap); + fputc('\n', log); + fflush(log); +}