From: Willy Tarreau Date: Tue, 24 Oct 2017 08:58:20 +0000 (+0200) Subject: CONTRIB: trace: try to display the function's return value on exit X-Git-Tag: v1.8-rc1~241 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e8f0f1265f1b68578e82ae180c4be55647ad0675;p=thirdparty%2Fhaproxy.git CONTRIB: trace: try to display the function's return value on exit On x86_64, when gcc instruments functions and compiles at -O0, it saves the function's return value in register rbx before calling the trace callback. It provides a nice opportunity to display certain useful values (flags, booleans etc) during trace sessions. It's absolutely not guaranteed that it will always work but it provides a considerable help when it does so it's worth activating it. When building on a different architecture, the value 0 is always reported as the return value. On x86_64 with optimizations (-O), the RBX register will not necessarily match and random values will be reported, but since it's not the primary target it's not a problem. --- diff --git a/contrib/trace/trace.awk b/contrib/trace/trace.awk index 6bd5b10a5a..74d953ccdc 100755 --- a/contrib/trace/trace.awk +++ b/contrib/trace/trace.awk @@ -72,7 +72,7 @@ function getptr(ptr) } 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", - $1, indents[$4,$2], caller_name, $4, callee_name, caller_loc, $3, $4, callee_loc, $5 + printf "%s %s %s %s %s(%s) [%s:%s] %s [%s:%s]\n", + $1, indents[$4,$2], caller_name, $4, callee_name, $6, caller_loc, $3, $4, callee_loc, $5 } ' diff --git a/src/trace.c b/src/trace.c index 9425be9f71..ab23a74eda 100644 --- a/src/trace.c +++ b/src/trace.c @@ -171,7 +171,7 @@ static char *emit_hex(unsigned long h, char *out) return out; } -static void make_line(void *from, void *to, int level, char dir) +static void make_line(void *from, void *to, int level, char dir, long ret) { char *p = line; @@ -221,6 +221,12 @@ static void make_line(void *from, void *to, int level, char dir) *p++ = ' '; *p++ = '0'; *p++ = 'x'; p = emit_hex((unsigned long)to, p); + if (dir == '<') { + /* " %x", ret */ + *p++ = ' '; *p++ = '0'; *p++ = 'x'; + p = emit_hex(ret, p); + } + *p++ = '\n'; fwrite(line, p - line, 1, log); @@ -230,13 +236,21 @@ static void make_line(void *from, void *to, int level, char dir) void __cyg_profile_func_enter(void *to, void *from) { if (!disabled) - return make_line(from, to, ++level, '>'); + return make_line(from, to, ++level, '>', 0); } void __cyg_profile_func_exit(void *to, void *from) { + long ret = 0; + +#if defined(__x86_64__) + /* on x86_64, the return value (eax) is temporarily stored in ebx + * during the call to __cyg_profile_func_exit() so we can snoop it. + */ + asm volatile("mov %%rbx, %0" : "=r"(ret)); +#endif if (!disabled) - return make_line(from, to, level--, '<'); + return make_line(from, to, level--, '<', ret); } /* the one adds comments in the trace above. The output format is :