2 /*--------------------------------------------------------------------*/
3 /*--- Store and compare stack backtraces m_execontext.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 Julian Seward
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_debuglog.h"
33 #include "pub_core_libcassert.h"
34 #include "pub_core_libcprint.h" // For VG_(message)()
35 #include "pub_core_mallocfree.h"
36 #include "pub_core_options.h"
37 #include "pub_core_stacktrace.h"
38 #include "pub_core_machine.h" // VG_(get_IP)
39 #include "pub_core_vki.h" // To keep pub_core_threadstate.h happy
40 #include "pub_core_libcsetjmp.h" // Ditto
41 #include "pub_core_threadstate.h" // VG_(is_valid_tid)
42 #include "pub_core_execontext.h" // self
44 /*------------------------------------------------------------*/
45 /*--- Low-level ExeContext storage. ---*/
46 /*------------------------------------------------------------*/
48 /* The first 4 IP values are used in comparisons to remove duplicate
49 errors, and for comparing against suppression specifications. The
50 rest are purely informational (but often important).
52 The contexts are stored in a traditional chained hash table, so as
53 to allow quick determination of whether a new context already
54 exists. The hash table starts small and expands dynamically, so as
55 to keep the load factor below 1.0.
57 The idea is only to ever store any one context once, so as to save
58 space and make exact comparisons faster. */
61 /* Primes for the hash table */
63 #define N_EC_PRIMES 18
65 static SizeT ec_primes[N_EC_PRIMES] = {
66 769UL, 1543UL, 3079UL, 6151UL,
67 12289UL, 24593UL, 49157UL, 98317UL,
68 196613UL, 393241UL, 786433UL, 1572869UL,
69 3145739UL, 6291469UL, 12582917UL, 25165843UL,
70 50331653UL, 100663319UL
74 /* Each element is present in a hash chain, and also contains a
75 variable length array of guest code addresses (the useful part). */
78 struct _ExeContext* chain;
79 /* A 32-bit unsigned integer that uniquely identifies this
80 ExeContext. Memcheck uses these for origin tracking. Values
81 must be nonzero (else Memcheck's origin tracking is hosed), must
82 be a multiple of four, and must be unique. Hence they start at
85 /* Variable-length array. The size is 'n_ips'; at
86 least 1, at most VG_DEEPEST_BACKTRACE. [0] is the current IP,
87 [1] is its caller, [2] is the caller of [1], etc. */
93 /* This is the dynamically expanding hash table. */
94 static ExeContext** ec_htab; /* array [ec_htab_size] of ExeContext* */
95 static SizeT ec_htab_size; /* one of the values in ec_primes */
96 static SizeT ec_htab_size_idx; /* 0 .. N_EC_PRIMES-1 */
98 /* ECU serial number */
99 static UInt ec_next_ecu = 4; /* We must never issue zero */
102 /* Stats only: the number of times the system was searched to locate a
104 static ULong ec_searchreqs;
106 /* Stats only: the number of full context comparisons done. */
107 static ULong ec_searchcmps;
109 /* Stats only: total number of stored contexts. */
110 static ULong ec_totstored;
112 /* Number of 2, 4 and (fast) full cmps done. */
113 static ULong ec_cmp2s;
114 static ULong ec_cmp4s;
115 static ULong ec_cmpAlls;
118 /*------------------------------------------------------------*/
119 /*--- Exported functions. ---*/
120 /*------------------------------------------------------------*/
123 /* Initialise this subsystem. */
124 static void init_ExeContext_storage ( void )
127 static Bool init_done = False;
128 if (LIKELY(init_done))
137 ec_htab_size_idx = 0;
138 ec_htab_size = ec_primes[ec_htab_size_idx];
139 ec_htab = VG_(arena_malloc)(VG_AR_EXECTXT, "execontext.iEs1",
140 sizeof(ExeContext*) * ec_htab_size);
141 for (i = 0; i < ec_htab_size; i++)
149 void VG_(print_ExeContext_stats) ( void )
151 init_ExeContext_storage();
152 VG_(message)(Vg_DebugMsg,
153 " exectx: %'lu lists, %'llu contexts (avg %'llu per list)\n",
154 ec_htab_size, ec_totstored, ec_totstored / (ULong)ec_htab_size
156 VG_(message)(Vg_DebugMsg,
157 " exectx: %'llu searches, %'llu full compares (%'llu per 1000)\n",
158 ec_searchreqs, ec_searchcmps,
161 : ( (ec_searchcmps * 1000ULL) / ec_searchreqs )
163 VG_(message)(Vg_DebugMsg,
164 " exectx: %'llu cmp2, %'llu cmp4, %'llu cmpAll\n",
165 ec_cmp2s, ec_cmp4s, ec_cmpAlls
170 /* Print an ExeContext. */
171 void VG_(pp_ExeContext) ( ExeContext* ec )
173 VG_(pp_StackTrace)( ec->ips, ec->n_ips );
177 /* Compare two ExeContexts. Number of callers considered depends on res. */
178 Bool VG_(eq_ExeContext) ( VgRes res, ExeContext* e1, ExeContext* e2 )
182 if (e1 == NULL || e2 == NULL)
185 // Must be at least one address in each trace.
186 tl_assert(e1->n_ips >= 1 && e2->n_ips >= 1);
190 /* Just compare the top two callers. */
192 for (i = 0; i < 2; i++) {
193 if ( (e1->n_ips <= i) && (e2->n_ips <= i)) return True;
194 if ( (e1->n_ips <= i) && !(e2->n_ips <= i)) return False;
195 if (!(e1->n_ips <= i) && (e2->n_ips <= i)) return False;
196 if (e1->ips[i] != e2->ips[i]) return False;
201 /* Just compare the top four callers. */
203 for (i = 0; i < 4; i++) {
204 if ( (e1->n_ips <= i) && (e2->n_ips <= i)) return True;
205 if ( (e1->n_ips <= i) && !(e2->n_ips <= i)) return False;
206 if (!(e1->n_ips <= i) && (e2->n_ips <= i)) return False;
207 if (e1->ips[i] != e2->ips[i]) return False;
213 /* Compare them all -- just do pointer comparison. */
214 if (e1 != e2) return False;
218 VG_(core_panic)("VG_(eq_ExeContext): unrecognised VgRes");
222 /* VG_(record_ExeContext) is the head honcho here. Take a snapshot of
223 the client's stack. Search our collection of ExeContexts to see if
224 we already have it, and if not, allocate a new one. Either way,
225 return a pointer to the context. If there is a matching context we
226 guarantee to not allocate a new one. Thus we never store
227 duplicates, and so exact equality can be quickly done as equality
228 on the returned ExeContext* values themselves. Inspired by Hugs's
231 Also checks whether the hash table needs expanding, and expands it
234 static inline UWord ROLW ( UWord w, Int n )
236 Int bpw = 8 * sizeof(UWord);
237 w = (w << n) | (w >> (bpw-n));
241 static UWord calc_hash ( Addr* ips, UInt n_ips, UWord htab_sz )
245 vg_assert(htab_sz > 0);
246 for (i = 0; i < n_ips; i++) {
248 hash = ROLW(hash, 19);
250 return hash % htab_sz;
253 static void resize_ec_htab ( void )
257 ExeContext** new_ec_htab;
259 vg_assert(ec_htab_size_idx >= 0 && ec_htab_size_idx < N_EC_PRIMES);
260 if (ec_htab_size_idx == N_EC_PRIMES-1)
261 return; /* out of primes - can't resize further */
263 new_size = ec_primes[ec_htab_size_idx + 1];
264 new_ec_htab = VG_(arena_malloc)(VG_AR_EXECTXT, "execontext.reh1",
265 sizeof(ExeContext*) * new_size);
269 "resizing htab from size %lu to %lu (idx %lu) Total#ECs=%llu\n",
270 ec_htab_size, new_size, ec_htab_size_idx + 1, ec_totstored);
272 for (i = 0; i < new_size; i++)
273 new_ec_htab[i] = NULL;
275 for (i = 0; i < ec_htab_size; i++) {
276 ExeContext* cur = ec_htab[i];
278 ExeContext* next = cur->chain;
279 UWord hash = calc_hash(cur->ips, cur->n_ips, new_size);
280 vg_assert(hash < new_size);
281 cur->chain = new_ec_htab[hash];
282 new_ec_htab[hash] = cur;
287 VG_(arena_free)(VG_AR_EXECTXT, ec_htab);
288 ec_htab = new_ec_htab;
289 ec_htab_size = new_size;
293 /* Do the first part of getting a stack trace: actually unwind the
294 stack, and hand the results off to the duplicate-trace-finder
296 static ExeContext* record_ExeContext_wrk2 ( Addr* ips, UInt n_ips ); /*fwds*/
297 static ExeContext* record_ExeContext_wrk ( ThreadId tid, Word first_ip_delta,
300 Addr ips[VG_DEEPEST_BACKTRACE];
303 init_ExeContext_storage();
305 vg_assert(sizeof(void*) == sizeof(UWord));
306 vg_assert(sizeof(void*) == sizeof(Addr));
308 vg_assert(VG_(is_valid_tid)(tid));
310 vg_assert(VG_(clo_backtrace_size) >= 1 &&
311 VG_(clo_backtrace_size) <= VG_DEEPEST_BACKTRACE);
315 ips[0] = VG_(get_IP)(tid);
317 n_ips = VG_(get_StackTrace)( tid, ips, VG_(clo_backtrace_size),
318 NULL/*array to dump SP values in*/,
319 NULL/*array to dump FP values in*/,
323 return record_ExeContext_wrk2 ( ips, n_ips );
326 /* Do the second part of getting a stack trace: ips[0 .. n_ips-1]
327 holds a proposed trace. Find or allocate a suitable ExeContext.
328 Note that callers must have done init_ExeContext_storage() before
329 getting to this point. */
330 static ExeContext* record_ExeContext_wrk2 ( Addr* ips, UInt n_ips )
337 ExeContext *prev2, *prev;
341 tl_assert(n_ips >= 1 && n_ips <= VG_(clo_backtrace_size));
343 /* Now figure out if we've seen this one before. First hash it so
344 as to determine the list number. */
345 hash = calc_hash( ips, n_ips, ec_htab_size );
347 /* And (the expensive bit) look a for matching entry in the list. */
353 list = ec_htab[hash];
356 if (list == NULL) break;
359 for (i = 0; i < n_ips; i++) {
360 if (list->ips[i] != ips[i]) {
372 /* Yay! We found it. Once every 8 searches, move it one step
373 closer to the start of the list to make future searches
375 if (0 == ((ctr++) & 7)) {
376 if (prev2 != NULL && prev != NULL) {
377 /* Found at 3rd or later position in the chain. */
378 vg_assert(prev2->chain == prev);
379 vg_assert(prev->chain == list);
381 prev->chain = list->chain;
384 else if (prev2 == NULL && prev != NULL) {
385 /* Found at 2nd position in the chain. */
386 vg_assert(ec_htab[hash] == prev);
387 vg_assert(prev->chain == list);
388 prev->chain = list->chain;
390 ec_htab[hash] = list;
396 /* Bummer. We have to allocate a new context record. */
399 new_ec = VG_(arena_malloc)( VG_AR_EXECTXT, "execontext.rEw2.2",
400 sizeof(struct _ExeContext)
401 + n_ips * sizeof(Addr) );
403 for (i = 0; i < n_ips; i++)
404 new_ec->ips[i] = ips[i];
406 vg_assert(VG_(is_plausible_ECU)(ec_next_ecu));
407 new_ec->ecu = ec_next_ecu;
409 if (ec_next_ecu == 0) {
410 /* Urr. Now we're hosed; we emitted 2^30 ExeContexts already
411 and have run out of numbers. Not sure what to do. */
412 VG_(core_panic)("m_execontext: more than 2^30 ExeContexts created");
415 new_ec->n_ips = n_ips;
416 new_ec->chain = ec_htab[hash];
417 ec_htab[hash] = new_ec;
419 /* Resize the hash table, maybe? */
420 if ( ((ULong)ec_totstored) > ((ULong)ec_htab_size) ) {
421 vg_assert(ec_htab_size_idx >= 0 && ec_htab_size_idx < N_EC_PRIMES);
422 if (ec_htab_size_idx < N_EC_PRIMES-1)
429 ExeContext* VG_(record_ExeContext)( ThreadId tid, Word first_ip_delta ) {
430 return record_ExeContext_wrk( tid, first_ip_delta,
431 False/*!first_ip_only*/ );
434 ExeContext* VG_(record_depth_1_ExeContext)( ThreadId tid ) {
435 return record_ExeContext_wrk( tid, 0/*first_ip_delta*/,
436 True/*first_ip_only*/ );
439 ExeContext* VG_(make_depth_1_ExeContext_from_Addr)( Addr a ) {
440 init_ExeContext_storage();
441 return record_ExeContext_wrk2( &a, 1 );
444 StackTrace VG_(get_ExeContext_StackTrace) ( ExeContext* e ) {
448 UInt VG_(get_ECU_from_ExeContext)( ExeContext* e ) {
449 vg_assert(VG_(is_plausible_ECU)(e->ecu));
453 Int VG_(get_ExeContext_n_ips)( ExeContext* e ) {
454 vg_assert(e->n_ips >= 1);
458 ExeContext* VG_(get_ExeContext_from_ECU)( UInt ecu )
462 vg_assert(VG_(is_plausible_ECU)(ecu));
463 vg_assert(ec_htab_size > 0);
464 for (i = 0; i < ec_htab_size; i++) {
465 for (ec = ec_htab[i]; ec; ec = ec->chain) {
473 ExeContext* VG_(make_ExeContext_from_StackTrace)( Addr* ips, UInt n_ips )
475 return record_ExeContext_wrk2(ips, n_ips);
478 /*--------------------------------------------------------------------*/
479 /*--- end m_execontext.c ---*/
480 /*--------------------------------------------------------------------*/