Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
Main Page
Related Pages
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Pages
include
common.h
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011, 2012, 2013, 2014 The University of Utah
3
*
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2 of
7
* the License, or (at your option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17
*/
18
19
#ifndef __COMMON_H__
20
#define __COMMON_H__
21
22
#include <stdint.h>
23
#include <inttypes.h>
24
25
typedef
enum
{
26
RESULT_SUCCESS
= 0,
27
RESULT_ERROR
= 1,
28
RESULT_ABORT
= 2,
29
}
result_t
;
30
31
/*
32
* For now, thread ids are a 32-bit int. This is enough, for instance,
33
* to do TIDs on Linux (because pids on 64-bit are still int32_ts. Note
34
* that we have reserved INT32_MAX as our "global" identifier.
35
*/
36
typedef
int32_t
tid_t
;
37
#define PRIiTID PRIi32
38
39
/* Might have to split these out into platform-specific stuff later; for
40
* now, just make them big enough for anything.
41
*
42
* Also, we only support debugging 32-bit targets on a 32-bit host. We
43
* support 32-bit targets on a 64-bit host, but not the reverse for
44
* now. That case would only have meaning if we wanted to investigate a
45
* non-live target (i.e., a 64-bit memory dump) on a 32-bit host. Even
46
* then, we would still need all the 64-bit debuginfo files... and they
47
* wouldn't be likely to be on a 32-bit host. SO, for now, we don't
48
* support this case.
49
*/
50
#if __WORDSIZE == 64
51
typedef
uint64_t
ADDR
;
52
typedef
int64_t
OFFSET
;
53
typedef
uint64_t
REGVAL
;
54
#define PRIxADDR PRIx64
55
#define PRIxFULLADDR "016"PRIx64
56
#define PRIuADDR PRIu64
57
#define PRIiOFFSET PRIi64
58
#define PRIxOFFSET PRIx64
59
#define PRIxREGVAL PRIx64
60
#define PRIuREGVAL PRIu64
61
#define ADDRMAX UINT64_MAX
62
#define OFFSETMAX UINT64_MAX
63
#else
64
typedef
uint32_t
ADDR
;
65
typedef
int32_t
OFFSET
;
66
typedef
uint32_t
REGVAL
;
67
#define PRIxADDR PRIx32
68
#define PRIxFULLADDR "016"PRIx32
69
#define PRIuADDR PRIu32
70
#define PRIiOFFSET PRIi32
71
#define PRIxOFFSET PRIx32
72
#define PRIxREGVAL PRIx32
73
#define PRIuREGVAL PRIu32
74
#define ADDRMAX UINT32_MAX
75
#define OFFSETMAX UINT32_MAX
76
#endif
77
78
#ifndef ptr_t
79
#define ptr_t unsigned long int
80
#endif
81
82
/*
83
* Define a "numeric" type; size should be the largest int for any
84
* target, for now. Later we might need something more
85
* flexible... sigh.
86
*/
87
typedef
int64_t
num_t
;
88
typedef
uint64_t
unum_t
;
89
#define PRIuNUM PRIu64
90
#define PRIiNUM PRIi64
91
#define PRIxNUM PRIx64
92
93
typedef
int8_t
REG
;
94
#define PRIiREG PRIi8
95
96
/*
97
* We use small offsets for DWARF offset addrs. Saves mem in symbol
98
* structures, which is very important.
99
*/
100
typedef
int32_t
SMOFFSET
;
101
#define PRIiSMOFFSET PRIi32
102
#define PRIxSMOFFSET PRIx32
103
104
#define __PAGE_SIZE 0x1000
105
106
#define PROT_READ 0x1
107
#define PROT_WRITE 0x2
108
#define PROT_EXEC 0x4
109
#define PROT_SHARED 0x8
110
111
/*
112
* Reference count stuff.
113
*
114
* The way this stuff works is a bit unfortunate. I tried to hide it
115
* from the users, so that what they think they get is a simple
116
* lookup/release interface. They *can* call RHOLD themselves, but they
117
* should not need to if they go through the public functions in each
118
* sub-library that state that they claim locks for the object they are
119
* returning (i.e., some symbol lookup functions).
120
*
121
* So, it's good for users. It's not so good for debugging refcnt
122
* leaks; see below!
123
*/
124
typedef
uint32_t
REFCNT
;
125
#define PRIiREFCNT PRIu32
126
127
/*
128
* Reference count debugging is hard because of the ways we use it. We
129
* try to keep the use entirely internal, and hidden from user, but what
130
* this means is that we inevitably take locks on behalf of the user.
131
* This means we don't have good tracking for lock owners (we don't know
132
* the address of the "owning" object). So, when the user releases a
133
* lock on an object, we do not know who the "owning" object was. For
134
* these cases, we just keep a separate count, so we can determine in a
135
* rough sense whether the leak was internal or external.
136
*
137
* HOWEVER, this means that *inside* our libraries, we must not call the
138
* functions that RHOLD on the user's behalf. We must act more
139
* manually. In this way, we can know that our internal refcnting is
140
* sound, which is what we're really after -- because then both owners
141
* and their referents can be tracked. We can fix the user-side refcnt
142
* debugging more later if we ever care. But that is small potatoes.
143
*
144
* Also, inside our libraries, we must never call (objtype)_release
145
* functions! Those are intended for external use only. We must always
146
* call RPUT* directly.
147
*
148
* XXX: need to change user-API calls to a _lookup()/_release()
149
* paradigm. This will make the REFCNT stuff more obvious to them.
150
* Basically, any call that ends in _lookup() needs to have a )release()
151
* done on _lookup()'s return value.
152
*
153
*
154
* NB: this is important! Objects cannot reference each other; such
155
* objects may not get deleted since we do maintain data structures that
156
* contain any such object (i.e., a referenced object may not be on some
157
* global hashtable, but one it references may not be -- it may be
158
* buried in some symtab tree -- and if we deleted the top of that tree,
159
* we'll be left with a dangling ref). To solve this, we would need
160
* some library-wide, global, type-aware reftab -- more memory usage.
161
*
162
* So, avoid it for now by only allowing top-down refs. This means that
163
* objects that hold refs to lower ones must clear the lower objects'
164
* backrefs to them. This may or not break the object model, of course.
165
* For now, it's ok for the way this library uses objects. The real
166
* problem is symbol tables -- it is very possible that the symtab an
167
* object is on will go away during debugfile free operations. But, if
168
* we always only partially free debugfiles by freeing root symtabs,
169
* this problem won't matter. As a matter of fact, we already don't do
170
* partial free (only incremental load), so this doesn't matter. Just
171
* notes for the future...
172
*
173
* Ok, unfortunately, the future is now.
174
*
175
* In early versions of this library, we tried to get away with keeping
176
* non-cyclic, hierarchical parent->child refs only. But unfortunately,
177
* some of our objects keep refs to the parent and operations on them
178
* end up requiring a parent deref. So we have to make sure that the
179
* parent does not get dealloc'd until its children are gone. But, this
180
* brings up the cyclic ref problem. If an object gets unlinked from
181
* our global data structures, and it is no longer reachable but still
182
* need to be freed, we still have to know it needs to be freed -- but
183
* even this situation will never be arrived at for two objects that
184
* hold each other. One must hold weakly to the other, so we know when
185
* it is safe to deallocate the first.
186
*
187
* Imagine the scenario where symbols hold symbols/symtabs, are on
188
* symtabs, which are on either debugfiles or binfiles. Symbols hold
189
* symtabs/symbols; symtabs hold debugfiles/binfiles/symbols; debugfiles
190
* hold symtabs.
191
*
192
* Here's what we do. We keep two counts for each object. Strong refs
193
* are the parent->child refs; weak refs are the child->parent refs.
194
* Basically, the idea is that when any object's strong ref counter
195
* becomes 0, we can start deallocating the object. Deallocation must
196
* first 1) remove itself from all global data structures, such as
197
* caches, and 2) release refs to any of its children (any objects it
198
* has strong refs to), and remove them from its structures IFF they are
199
* freed themselves. If all children are freed, and there are no more
200
* weak refs to the object, we can finish freeing it (we need both
201
* constraints to know which children we must save and not remove from
202
* our object's data structures); else we must place the object on a
203
* global "to-free" hashtable. Then, when weak refs are released, the
204
* object that was weakly held must be checked to see if it can be
205
* released. That's how we will do this. This frees us from having to
206
* track ref holders.
207
*/
208
209
/*
210
* NB for internal users that use refcnts to protect objects:
211
*
212
* If an object maintains its own refcnt, plus it allows other objects
213
* to take weak refs to it, when it frees itself after its refcnt goes
214
* to 0, it must protect itself from getting double-freed by RPUTW,
215
* which will get called on it as it frees its children. So these
216
* functions just temporarily jack up its own refcnt temporarily to do
217
* that. By the time these are called, its refcnt is already 0, or
218
* we're forcing a free.
219
*/
220
#define RWGUARD(x) ++((x)->refcnt)
221
#define RWUNGUARD(x) --((x)->refcnt)
222
223
#ifdef REF_DEBUG
224
225
#include <glib.h>
226
/*
227
* NB: this table never gets freed unless you call REF_DEBUG_REPORT_FINISH().
228
*
229
* Oh, and this is NOT thread-safe, obviously. Make it so if you need it...
230
*/
231
232
/* This one holds data for distinct obj/owner pairs. */
233
extern
GHashTable *greftab;
234
/* This one holds data for self-owning objects (i.e., user-inspired refs). */
235
extern
GHashTable *grefstab;
236
237
/* This one holds data for distinct obj/owner pairs. */
238
extern
GHashTable *grefwtab;
239
/* This one holds data for self-owning objects (i.e., user-inspired refs). */
240
extern
GHashTable *grefwstab;
241
242
#define REFCNTDECL(trefcnt) REFCNT trefcnt
243
244
#define RHOLD(x,hx) \
245
do { \
246
GHashTable *htab; \
247
char *buf; \
248
unsigned int count; \
249
void *_hx = (hx); \
250
\
251
++((x)->refcnt); \
252
\
253
/* If self-ref, just save by caller function address. */
\
254
if ((x) == _hx) { \
255
_hx = (void *)__builtin_return_address(1); \
256
fprintf(stderr,"REFDEBUG: hold %p,%p (%d) (self)\n", \
257
(x),_hx,(x)->refcnt); \
258
\
259
if (unlikely(!grefstab)) { \
260
grefstab = g_hash_table_new(g_direct_hash,g_direct_equal); \
261
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
262
NULL,NULL); \
263
g_hash_table_insert(grefstab,(gpointer)(x),htab); \
264
} \
265
else if (!(htab = (GHashTable *)g_hash_table_lookup(grefstab,(x)))) { \
266
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
267
NULL,NULL); \
268
g_hash_table_insert(grefstab,(gpointer)(x),htab); \
269
} \
270
count = (unsigned int)(ptr_t)g_hash_table_lookup(htab,(gpointer)_hx); \
271
++count; \
272
g_hash_table_insert(htab,(gpointer)_hx,(void *)(ptr_t)count); \
273
/* XXX: we should track more than caller addr? */
\
274
} \
275
else { \
276
fprintf(stderr,"REFDEBUG: hold %p,%p (%d)\n", \
277
(x),_hx,(x)->refcnt); \
278
\
279
if (unlikely(!greftab)) { \
280
greftab = g_hash_table_new(g_direct_hash,g_direct_equal); \
281
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
282
NULL,NULL); \
283
g_hash_table_insert(greftab,(gpointer)(x),htab); \
284
} \
285
else if (!(htab = (GHashTable *)g_hash_table_lookup(greftab,(x)))) { \
286
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
287
NULL,free); \
288
g_hash_table_insert(greftab,(gpointer)(x),htab); \
289
} \
290
\
291
buf = malloc(sizeof(__FUNCTION__)+sizeof(__LINE__)+1+1); \
292
snprintf(buf,sizeof(__FUNCTION__)+sizeof(__LINE__)+1+1, \
293
"%s:%d",__FUNCTION__,__LINE__); \
294
g_hash_table_insert(htab,(gpointer)_hx,buf); \
295
} \
296
} while (0);
297
#define RHOLDW(x,hx) \
298
do { \
299
GHashTable *htab; \
300
char *buf; \
301
unsigned int count; \
302
void *_hx = (hx); \
303
\
304
++((x)->refcntw); \
305
\
306
/* If self-ref, just save by caller function address. */
\
307
if ((x) == _hx) { \
308
_hx = (void *)__builtin_return_address(1); \
309
fprintf(stderr,"REFDEBUG: holdw %p,%p (%d) (self)\n", \
310
(x),_hx,(x)->refcnt); \
311
\
312
if (unlikely(!grefwstab)) { \
313
grefwstab = g_hash_table_new(g_direct_hash,g_direct_equal); \
314
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
315
NULL,NULL); \
316
g_hash_table_insert(grefwstab,(gpointer)(x),htab); \
317
} \
318
else if (!(htab = (GHashTable *)g_hash_table_lookup(grefwstab,(x)))) { \
319
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
320
NULL,NULL); \
321
g_hash_table_insert(grefwstab,(gpointer)(x),htab); \
322
} \
323
count = (unsigned int)g_hash_table_lookup(htab,(gpointer)_hx); \
324
++count; \
325
g_hash_table_insert(htab,(gpointer)_hx,(void *)(ptr_t)count); \
326
/* XXX: we should track more than caller addr? */
\
327
} \
328
else { \
329
fprintf(stderr,"REFDEBUG: holdw %p,%p (%d)\n", \
330
(x),_hx,(x)->refcnt); \
331
\
332
if (unlikely(!grefwtab)) { \
333
grefwtab = g_hash_table_new(g_direct_hash,g_direct_equal); \
334
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
335
NULL,NULL); \
336
g_hash_table_insert(grefwtab,(gpointer)(x),htab); \
337
} \
338
else if (!(htab = (GHashTable *)g_hash_table_lookup(grefwtab,(x)))) { \
339
htab = g_hash_table_new_full(g_direct_hash,g_direct_equal, \
340
NULL,free); \
341
g_hash_table_insert(grefwtab,(gpointer)(x),htab); \
342
} \
343
\
344
buf = malloc(sizeof(__FUNCTION__)+sizeof(__LINE__)+1+1); \
345
snprintf(buf,sizeof(__FUNCTION__)+sizeof(__LINE__)+1+1, \
346
"%s:%d",__FUNCTION__,__LINE__); \
347
g_hash_table_insert(htab,(gpointer)_hx,buf); \
348
} \
349
} while (0);
350
#define RPUT(x,objtype,hx,rc) \
351
do { \
352
typeof(x) _x = (x); \
353
void *_hx = (hx); \
354
GHashTable *htab; \
355
/*unsigned int count; */
\
356
\
357
/* if ((x)->refcnt == 0) */
\
358
/* asm("int $3"); */
\
359
\
360
(rc) = (--((x)->refcnt) == 0) \
361
? objtype ## _free(x,0) : ((x)->refcnt); \
362
\
363
if (_x == _hx) { \
364
if (!grefstab) \
365
break; \
366
\
367
fprintf(stderr,"REFDEBUG: put %p,%p (%d) (self)\n",(x),_hx,(rc)); \
368
\
369
htab = (GHashTable *)g_hash_table_lookup(grefstab,_x); \
370
if (!htab) \
371
break; \
372
/* Can't track holder; just nuke hashtable. */
\
373
if ((rc) == 0) { \
374
g_hash_table_destroy(htab); \
375
g_hash_table_remove(grefstab,_x); \
376
} \
377
/*count = (unsigned int)g_hash_table_remove(htab,_hx); */
\
378
/*if (--count == 0) { */
\
379
/* if (g_hash_table_size(htab) == 0) */
\
380
/* g_hash_table_destroy(htab); */
\
381
/*} */
\
382
/*else */
\
383
/* g_hash_table_insert(htab,_hx,(gpointer)(ptr_t)count); */
\
384
} \
385
else { \
386
if (!greftab) \
387
break; \
388
\
389
fprintf(stderr,"REFDEBUG: put %p,%p (%d)\n",(x),_hx,(rc)); \
390
\
391
htab = (GHashTable *)g_hash_table_lookup(greftab,_x); \
392
if (!htab) \
393
break; \
394
g_hash_table_remove(htab,_hx); \
395
if (g_hash_table_size(htab) == 0) { \
396
g_hash_table_destroy(htab); \
397
g_hash_table_remove(greftab,_x); \
398
} \
399
} \
400
} while (0);
401
#define RPUTW(x,objtype,hx,rc) \
402
do { \
403
typeof(x) _x = (x); \
404
void *_hx = (hx); \
405
GHashTable *htab; \
406
\
407
/* if ((x)->refcntw == 0) */
\
408
/* asm("int $3"); */
\
409
\
410
(rc) = ((--((x)->refcntw) + (x)->refcnt) == 0) \
411
? objtype ## _free(x,0) : ((x)->refcntw + (x)->refcnt); \
412
\
413
if (_x == _hx) { \
414
if (!grefwstab) \
415
break; \
416
\
417
fprintf(stderr,"REFDEBUG: putw %p,%p (%d) (self)\n",(x),_hx,(rc)); \
418
\
419
htab = (GHashTable *)g_hash_table_lookup(grefwstab,_x); \
420
if (!htab) \
421
break; \
422
/* Can't track holder; just nuke hashtable. */
\
423
if ((rc) == 0) { \
424
g_hash_table_destroy(htab); \
425
g_hash_table_remove(grefwstab,_x); \
426
} \
427
} \
428
else { \
429
if (!grefwtab) \
430
break; \
431
\
432
fprintf(stderr,"REFDEBUG: putw %p,%p (%d)\n",(x),_hx,(rc)); \
433
\
434
htab = (GHashTable *)g_hash_table_lookup(grefwtab,_x); \
435
if (!htab) \
436
break; \
437
g_hash_table_remove(htab,_hx); \
438
if (g_hash_table_size(htab) == 0) { \
439
g_hash_table_destroy(htab); \
440
g_hash_table_remove(grefwtab,_x); \
441
} \
442
} \
443
} while (0);
444
/*
445
* Nobody should use RPUTNF/RPUTFF at all, ever -- it means you are not
446
* using refcnts appropriately. Do not enable them without talking to
447
* David, and you better have a darn good reason.
448
*/
449
//#if 0
450
#define RPUTFF(x,objtype,hx,rc) \
451
do { \
452
typeof(x) _x = (x); \
453
void *_hx = (hx); \
454
GHashTable *htab; \
455
unsigned int count; \
456
\
457
(rc) = (--((x)->refcnt) == 0) \
458
? objtype ## _free(x,1) : objtype ## _free(x,1); \
459
\
460
if (_x == _hx) { \
461
if (!grefstab) \
462
break; \
463
\
464
fprintf(stderr,"REFDEBUG: putf %p,%p (%d) (self)\n",(x),_hx,(rc)); \
465
\
466
htab = (GHashTable *)g_hash_table_lookup(grefstab,_x); \
467
if (!htab) \
468
break; \
469
count = (unsigned int)g_hash_table_remove(htab,_hx); \
470
if (--count == 0) { \
471
if (g_hash_table_size(htab) == 0) \
472
g_hash_table_destroy(htab); \
473
} \
474
else \
475
g_hash_table_insert(htab,_hx,(gpointer)(ptr_t)count); \
476
} \
477
else { \
478
if (!greftab) \
479
break; \
480
\
481
fprintf(stderr,"REFDEBUG: putf %p,%p (%d)\n",(x),_hx,(rc)); \
482
\
483
htab = (GHashTable *)g_hash_table_lookup(greftab,_x); \
484
if (!htab) \
485
break; \
486
g_hash_table_remove(htab,_hx); \
487
if (g_hash_table_size(htab) == 0) { \
488
g_hash_table_destroy(htab); \
489
g_hash_table_remove(greftab,_x); \
490
} \
491
} \
492
} while (0);
493
#define RPUTNF(x,hx,rc) \
494
do { \
495
typeof(x) _x = (x); \
496
void *_hx = (hx); \
497
GHashTable *htab; \
498
unsigned int count; \
499
\
500
(rc) = (--((x)->refcnt)); \
501
\
502
if (_x == _hx) { \
503
if (!grefstab) \
504
break; \
505
\
506
fprintf(stderr,"REFDEBUG: putn %p,%p (%d) (self)\n",(x),_hx,(rc)); \
507
\
508
htab = (GHashTable *)g_hash_table_lookup(grefstab,_x); \
509
if (!htab) \
510
break; \
511
count = (unsigned int)g_hash_table_remove(htab,_hx); \
512
if (--count == 0) { \
513
if (g_hash_table_size(htab) == 0) \
514
g_hash_table_destroy(htab); \
515
} \
516
else \
517
g_hash_table_insert(htab,_hx,(gpointer)(ptr_t)count); \
518
} \
519
else { \
520
if (!greftab) \
521
break; \
522
\
523
fprintf(stderr,"REFDEBUG: putn %p,%p (%d)\n",(x),_hx,(rc)); \
524
\
525
htab = (GHashTable *)g_hash_table_lookup(greftab,_x); \
526
if (!htab) \
527
break; \
528
g_hash_table_remove(htab,_hx); \
529
if (g_hash_table_size(htab) == 0) { \
530
g_hash_table_destroy(htab); \
531
g_hash_table_remove(greftab,_x); \
532
} \
533
} \
534
} while (0);
535
//#endif /* 0 */
536
/*
537
* You should call this when your main program terminates.
538
*/
539
#define REF_DEBUG_REPORT_FINISH() \
540
do { \
541
GHashTableIter iter,iter2; \
542
GHashTable *htab; \
543
void *_x,*_hx; \
544
char *info; \
545
unsigned int count; \
546
if (greftab) { \
547
g_hash_table_iter_init(&iter,greftab); \
548
while (g_hash_table_iter_next(&iter,&_x,(gpointer)&htab)) { \
549
fprintf(stderr,"REFDEBUG: %d refs held for %p :\n", \
550
g_hash_table_size(htab),_x); \
551
g_hash_table_iter_init(&iter2,htab); \
552
while (g_hash_table_iter_next(&iter2,&_hx,(gpointer)&info)) { \
553
fprintf(stderr," %p held %p : %s\n", \
554
_hx,_x,info); \
555
g_hash_table_iter_remove(&iter2); \
556
} \
557
g_hash_table_destroy(htab); \
558
\
559
/* asm("int $3"); */
\
560
} \
561
g_hash_table_destroy(greftab); \
562
greftab = NULL; \
563
} \
564
if (grefstab) { \
565
g_hash_table_iter_init(&iter,grefstab); \
566
while (g_hash_table_iter_next(&iter,&_x,(gpointer)&htab)) { \
567
fprintf(stderr,"REFDEBUG: %d refs self-held for %p :\n", \
568
g_hash_table_size(htab),_x); \
569
g_hash_table_iter_init(&iter2,htab); \
570
while (g_hash_table_iter_next(&iter2,&_hx,(gpointer)&info)) { \
571
count = (unsigned int)(ptr_t)info; \
572
fprintf(stderr," %p self-held %p : %d\n", \
573
_hx,_x,count); \
574
g_hash_table_iter_remove(&iter2); \
575
} \
576
g_hash_table_destroy(htab); \
577
\
578
/* asm("int $3"); */
\
579
} \
580
g_hash_table_destroy(grefstab); \
581
grefstab = NULL; \
582
} \
583
if (grefwtab) { \
584
g_hash_table_iter_init(&iter,grefwtab); \
585
while (g_hash_table_iter_next(&iter,&_x,(gpointer)&htab)) { \
586
fprintf(stderr,"REFDEBUG: %d weak refs held for %p :\n", \
587
g_hash_table_size(htab),_x); \
588
g_hash_table_iter_init(&iter2,htab); \
589
while (g_hash_table_iter_next(&iter2,&_hx,(gpointer)&info)) { \
590
fprintf(stderr," %p weakly held %p : %s\n", \
591
_hx,_x,info); \
592
g_hash_table_iter_remove(&iter2); \
593
} \
594
g_hash_table_destroy(htab); \
595
\
596
/* asm("int $3"); */
\
597
} \
598
g_hash_table_destroy(grefwtab); \
599
grefwtab = NULL; \
600
} \
601
if (grefwstab) { \
602
g_hash_table_iter_init(&iter,grefwstab); \
603
while (g_hash_table_iter_next(&iter,&_x,(gpointer)&htab)) { \
604
fprintf(stderr,"REFDEBUG: %d weak refs self-held for %p :\n", \
605
g_hash_table_size(htab),_x); \
606
g_hash_table_iter_init(&iter2,htab); \
607
while (g_hash_table_iter_next(&iter2,&_hx,(gpointer)&info)) { \
608
fprintf(stderr," %p weakly self-held %p : %s\n", \
609
_hx,_x,info); \
610
g_hash_table_iter_remove(&iter2); \
611
} \
612
g_hash_table_destroy(htab); \
613
\
614
/* asm("int $3"); */
\
615
} \
616
g_hash_table_destroy(grefwstab); \
617
grefwstab = NULL; \
618
} \
619
} while (0);
620
#else
621
#define REFCNTDECL(trefcnt)
622
#define RHOLD(x,hx) ++((x)->refcnt)
623
#define RHOLDW(x,hx) ++((x)->refcntw)
624
#define RPUT(x,objtype,hx,rc) ((rc) = (--((x)->refcnt) == 0) \
625
? objtype ## _free(x,0) \
626
: (x)->refcnt); \
627
(rc) += 0
628
#define RPUTW(x,objtype,hx,rc) ((rc) = ((--((x)->refcntw) + (x)->refcnt) == 0) \
629
? objtype ## _free(x,0) \
630
: (x)->refcntw + (x)->refcnt); \
631
(rc) += 0
632
/*
633
* Allows the caller to free the object even if the refcnt has gone
634
* negative. This is nice for the case that the caller allocates an
635
* object, and passes it into the library where something in there holds
636
* one or more refs to it. But, if the caller later decides it wants to
637
* "release" it because from its perspective it is no longer needed,
638
* then it can call this sloppy release mechanism which allows it to
639
* release an "implicit" ref.
640
*
641
* A cleaner way would be to hold a temp ref to it, and release that.
642
* But if an algorithm is multi-part, it may be hard to follow that
643
* strategy.
644
*/
645
#define RPUTIFZERO(x,objtype,rc) ((rc) = (x)->refcnt == 0 \
646
? objtype ## _free(x,0) \
647
: (x)->refcnt)
648
#define RPUTFF(x,objtype,hx,rc) ((rc) = (--((x)->refcnt) == 0) \
649
? objtype ## _free(x,1) \
650
: objtype ## _free(x,1)
651
#define RPUTNF(x,hx,rc) ((rc) = (--((x)->refcnt)))
652
653
#define REF_DEBUG_REPORT_FINISH() (void)
654
#endif
655
656
#endif
/* __COMMON_H__ */
tid_t
int32_t tid_t
Definition:
common.h:36
num_t
int64_t num_t
Definition:
common.h:87
SMOFFSET
int32_t SMOFFSET
Definition:
common.h:100
OFFSET
int32_t OFFSET
Definition:
common.h:65
RESULT_ABORT
Definition:
common.h:28
RESULT_ERROR
Definition:
common.h:27
result_t
result_t
Definition:
common.h:25
REGVAL
uint32_t REGVAL
Definition:
common.h:66
REG
int8_t REG
Definition:
common.h:93
ADDR
uint32_t ADDR
Definition:
common.h:64
REFCNT
uint32_t REFCNT
Definition:
common.h:124
unum_t
uint64_t unum_t
Definition:
common.h:88
RESULT_SUCCESS
Definition:
common.h:26
Generated on Thu Jul 27 2017 20:47:30 for Stackdb by
1.8.8