3 LD_PRELOAD library that gives statistic on number of roundtrips in an application.
5 $XREPLY_BACKTRACE defines whether and how backtraces will be printed for every
6 roundtrip. If not set, only total number of roundtrips is printed after the process
7 exits. If set to a number, backtrace for every roundtrip will be printed, and the
8 backtraces will be as deep as the given number. If set to C<number> (e.g. C10),
9 the backtraces will be "compressed" - every backtrace will be printed only once
10 after the process exits, together with number of times it occurred.
22 #include <X11/Xlibint.h>
24 /* Since these symbols are weak, the apps can provide their own, and therefore
25 e.g. temporarily suspend counting of roundtrips. At least theoretically,
26 I haven't really tried it.
28 __attribute((weak
)) long ___xreply_reply_count
= 0;
29 __attribute((weak
)) int ___xreply_reply_enabled
= 1;
31 #define MAX_BACKTRACES 1024
33 extern long ___xreply_reply_count
;
34 extern int ___xreply_reply_enabled
;
36 typedef Status (*xreply_ptr_t
)(Display
*,xReply
*,int,Bool
);
38 static xreply_ptr_t xreply_ptr
= NULL
;
39 static int xreply_backtrace_set
= 0;
40 static int xreply_backtrace_type
= 0;
48 static struct xreply_struct backtraces
[ MAX_BACKTRACES
];
49 static int backtraces_size
= 0;
51 static int xreply_compare( const void* left
, const void* right
)
53 int left_count
= ((struct xreply_struct
*)left
)->count
;
54 int right_count
= ((struct xreply_struct
*)right
)->count
;
55 return right_count
- left_count
;
58 static void xreply_print(void)
62 fd
= open( "/proc/self/cmdline", O_RDONLY
);
65 read( fd
, tmp
, 1024 );
69 fprintf( stderr
, "XREPLY (%d : %s): %ld\n", getpid(), tmp
, ___xreply_reply_count
);
70 if( xreply_backtrace_type
< 0 )
73 qsort( backtraces
, backtraces_size
, sizeof( struct xreply_struct
), xreply_compare
);
77 fprintf( stderr
, "%d:%s\n\n", backtraces
[ i
].count
, backtraces
[ i
].text
);
81 static void xreply_backtrace()
84 int n
= backtrace(trace
, 256);
85 char** strings
= backtrace_symbols (trace
, n
);
87 if( xreply_backtrace_type
> 0 )
89 fprintf( stderr
, "%ld [\n", ___xreply_reply_count
);
90 if( n
> xreply_backtrace_type
)
91 n
= xreply_backtrace_type
;
96 fprintf( stderr
, "%d: %s\n", i
, strings
[ i
] );
97 fprintf( stderr
, "]\n" );
101 char stack
[ 256 * 20 ];
105 if( n
> -xreply_backtrace_type
)
106 n
= -xreply_backtrace_type
;
111 const char* start
= strrchr( strings
[ i
], '[' );
113 assert( !"No [ in address." );
115 if( sscanf( start
+ 1, "0x%lx", &addr
) != 1 )
116 assert( !"Failed to parse address." );
117 if( sizeof( void* ) == 4 )
119 sprintf( stack
+ pos
, "0x%8lx", addr
);
122 else if( sizeof( void* ) == 8 )
124 sprintf( stack
+ pos
, "0x%16lx", addr
);
128 assert( !"Unknown sizeof( void* )." );
133 if( strcmp( backtraces
[ i
].key
, stack
) == 0 )
135 ++backtraces
[ i
].count
;
138 if( i
== backtraces_size
)
140 int stack_text_size
= 10;
142 char* stack_text_pos
;
146 stack_text_size
+= strlen( strings
[ i
] ) + 5;
147 stack_text
= stack_text_pos
= malloc( stack_text_size
);
152 stack_text_pos
= stpcpy( stack_text_pos
, "\n" );
153 stack_text_pos
= stpcpy( stack_text_pos
, strings
[ i
] );
155 backtraces
[ backtraces_size
].key
= strdup( stack
);
156 backtraces
[ backtraces_size
].text
= stack_text
;
157 backtraces
[ backtraces_size
].count
= 1;
159 if( backtraces_size
>= MAX_BACKTRACES
)
160 assert( !"MAX_BACKTRACES reached." );
167 _XReply (dpy
, rep
, extra
, discard
)
168 register Display
*dpy
;
169 register xReply
*rep
;
170 int extra
; /* number of 32-bit words expected after the reply */
171 Bool discard
; /* should I discard data following "extra" words? */
173 if( ___xreply_reply_enabled
)
174 ++___xreply_reply_count
;
175 if( xreply_backtrace_set
== 0 )
177 if( getenv( "XREPLY_BACKTRACE" ) != NULL
)
178 { // C<number> - compress backtraces, saved as negative value in xreply_backtrace_type
179 if( getenv( "XREPLY_BACKTRACE" )[ 0 ] == 'C' )
180 xreply_backtrace_type
= -atoi( getenv( "XREPLY_BACKTRACE" ) + 1 );
181 else // <number> - print the backtrace every time
182 xreply_backtrace_type
= atoi( getenv( "XREPLY_BACKTRACE" ));
185 xreply_backtrace_type
= 0;
187 if( xreply_backtrace_type
!= 0 )
189 if( xreply_ptr
== NULL
)
191 xreply_ptr
= (xreply_ptr_t
)dlsym( RTLD_NEXT
, "_XReply" );
192 if( xreply_ptr
== NULL
)
193 assert( !"dlsym() failed." );
194 atexit( xreply_print
);
196 return xreply_ptr( dpy
, rep
, extra
, discard
);