Predator
[unstable] git snapshot
Main Page
Related Pages
Namespaces
Data Structures
Files
File List
Globals
symheap.hh
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2009-2011 Kamil Dudka <kdudka@redhat.com>
3
* Copyright (C) 2010 Petr Peringer, FIT
4
*
5
* This file is part of predator.
6
*
7
* predator is free software: you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, either version 3 of the License, or
10
* any later version.
11
*
12
* predator is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with predator. If not, see <http://www.gnu.org/licenses/>.
19
*/
20
21
#ifndef H_GUARD_SYM_HEAP_H
22
#define H_GUARD_SYM_HEAP_H
23
24
/**
25
* @file symheap.hh
26
* SymHeap - the elementary representation of the state of program memory
27
*/
28
29
#include "
config.h
"
30
31
#include "
intrange.hh
"
32
#include "
symid.hh
"
33
#include "
util.hh
"
34
35
#include <
cl/code_listener.h
>
36
37
#include <map>
// for TValMap
38
#include <set>
// for TCVarSet
39
#include <string>
40
#include <vector>
// for many types
41
42
class
SymBackTrace
;
43
44
/// classification of kind of origins a value may come from
45
enum
EValueOrigin
{
46
VO_INVALID
,
///< reserved for signalling error states
47
VO_ASSIGNED
,
///< known result of an operation
48
VO_UNKNOWN
,
///< value was abstracted out and guessed later on
49
VO_REINTERPRET
,
///< a result of unsupported data reinterpretation
50
VO_DEREF_FAILED
,
///< a result of invalid dereference
51
VO_STACK
,
///< untouched contents of stack
52
VO_HEAP
///< untouched contents of heap
53
};
54
55
/// true for VO_HEAP and VO_STACK
56
bool
isUninitialized
(
EValueOrigin
);
57
58
/// classification of kind of objects a value may point to
59
enum
EValueTarget
{
60
VT_INVALID
,
///< completely invalid target
61
VT_UNKNOWN
,
///< arbitrary target
62
VT_COMPOSITE
,
///< value of a composite field (not a pointer to!)
63
VT_CUSTOM
,
///< non-pointer data, classified by ECustomValue
64
VT_OBJECT
,
///< target is a (possibly invalid) object
65
66
// TODO: drop this?
67
VT_RANGE
///< an offset value where offset is given by range
68
};
69
70
/// TODO: drop this!
71
bool
isAnyDataArea
(
EValueTarget
);
72
73
/// classification of the storage class for objects
74
enum
EStorageClass
{
75
SC_INVALID
,
///< reserved for signalling error states
76
SC_UNKNOWN
,
///< no assumptions, the object may be even shared
77
SC_STATIC
,
///< safely allocated in static data if not a 0+ obj
78
SC_ON_HEAP
,
///< safely allocated on heap except for 0+ objects
79
SC_ON_STACK
///< safely allocated on stack except for 0+ objects
80
};
81
82
/// true for SC_ON_HEAP
83
bool
isOnHeap
(
EStorageClass
);
84
85
/// true for SC_STATIC and SC_ON_STACK
86
bool
isProgramVar
(
EStorageClass
);
87
88
/// classification of the target of an address (a.k.a. target specifier)
89
enum
ETargetSpecifier
{
90
TS_INVALID
,
///< reserved for signalling error states
91
TS_REGION
,
///< the only allowed TS for addresses of regions
92
TS_FIRST
,
///< target is the first node of an abstract object
93
TS_LAST
,
///< target is the last node of an abstract object
94
TS_ALL
///< target is any node of an abstract object
95
};
96
97
/// enumeration of custom values, such as integer literals, or code pointers
98
enum
ECustomValue
{
99
CV_INVALID
,
///< reserved for signalling error states
100
CV_FNC
,
///< code pointer
101
CV_INT_RANGE
,
///< a closed interval over integral domain
102
CV_REAL
,
///< floating-point number
103
CV_STRING
///< string literal
104
};
105
106
union
CustomValueData
{
107
int
uid
;
///< unique ID as assigned by Code Listener
108
double
fpn
;
///< floating-point number
109
std::string *
str
;
///< string literal
110
IR::Range
rng
;
///< closed interval over integral domain
111
};
112
113
/// representation of a custom value, such as integer literal, or code pointer
114
class
CustomValue
{
115
public
:
116
// cppcheck-suppress uninitVar
117
CustomValue
():
118
code_
(
CV_INVALID
)
119
{
120
}
121
122
~CustomValue
();
123
CustomValue
(
const
CustomValue
&);
124
CustomValue
&
operator=
(
const
CustomValue
&);
125
126
explicit
CustomValue
(
int
uid
):
127
code_
(
CV_FNC
)
128
{
129
data_
.
uid
=
uid
;
130
}
131
132
explicit
CustomValue
(
const
IR::Range
&
rng
):
133
code_
(
CV_INT_RANGE
)
134
{
135
data_
.
rng
=
rng
;
136
}
137
138
explicit
CustomValue
(
const
double
fpn
):
139
code_
(
CV_REAL
)
140
{
141
data_
.
fpn
=
fpn
;
142
}
143
144
explicit
CustomValue
(
const
char
*
str
):
145
code_
(
CV_STRING
)
146
{
147
data_
.
str
=
new
std::string(str);
148
}
149
150
/// custom value classification
151
ECustomValue
code
()
const
{
152
return
code_
;
153
}
154
155
/// unique ID as assigned by Code Listener (only for CV_FNC)
156
int
uid
()
const
;
157
158
/// closed interval over integral domain (only for CV_INT_RANGE)
159
IR::Range
&
rng
();
160
161
/// closed interval over integral domain (only for CV_INT_RANGE)
162
const
IR::Range
&
rng
()
const
{
163
return
const_cast<
CustomValue
*
>
(
this
)->
rng
();
164
}
165
166
/// floating-point number (only for CV_REAL)
167
double
fpn
()
const
;
168
169
/// string literal (only for CV_STRING)
170
const
std::string &
str
()
const
;
171
172
private
:
173
friend
bool
operator==
(
const
CustomValue
&,
const
CustomValue
&);
174
175
ECustomValue
code_
;
176
CustomValueData
data_
;
177
};
178
179
bool
operator==
(
const
CustomValue
&a,
const
CustomValue
&b);
180
181
inline
bool
operator!=
(
const
CustomValue
&a,
const
CustomValue
&b)
182
{
183
return
!
operator==
(a, b);
184
}
185
186
namespace
CodeStorage {
187
struct
Storage;
188
}
189
190
namespace
Trace {
191
class
Node;
192
}
193
194
/// a type used for integral offsets (changing this is known to cause problems)
195
typedef
IR::TInt
TOffset
;
196
197
/// a type used for block sizes (do not set this to anything else than TOffset)
198
typedef
IR::TInt
TSizeOf
;
199
200
/// a type used for block size ranges (do not try to change this one either)
201
typedef
IR::Range
TSizeRange
;
202
203
/// a container to store offsets to
204
typedef
std::vector<TOffset>
TOffList
;
205
206
/// container used to store value IDs to
207
typedef
std::vector<TValId>
TValList
;
208
209
/// container used to store object IDs to
210
typedef
std::vector<TObjId>
TObjList
;
211
212
/// container used to store value IDs to
213
typedef
std::set<TValId>
TValSet
;
214
215
/// container used to store object IDs to
216
typedef
std::set<TObjId>
TObjSet
;
217
218
/// a type used for (injective) value IDs mapping
219
typedef
std::map<TValId, TValId>
TValMap
;
220
221
/// a type used for (injective) object IDs mapping
222
typedef
std::map<TObjId, TObjId>
TObjMap
;
223
224
/// a type used for type-info
225
typedef
const
struct
cl_type
*
TObjType
;
226
227
/// a class of type (structure, pointer, union, ...)
228
typedef
enum
cl_type_e
TObjCode
;
229
230
/// a reference to CodeStorage::Storage instance describing the analyzed code
231
typedef
const
CodeStorage::Storage
&
TStorRef
;
232
233
/// a type used for prototype level (0 means not a prototype)
234
typedef
short
TProtoLevel
;
235
236
/**
237
* bundles static identification of a variable with its instance number
238
*
239
* In order to enable call recursion, we need to distinguish among various
240
* instances of the same automatic variable in case a function is called
241
* recursively.
242
*/
243
struct
CVar
{
244
/// static identification of a variable
245
int
uid
;
246
247
/// zero for global/static variables, instance number 1..n otherwise
248
int
inst
;
249
250
CVar
():
251
uid
(-1),
252
inst
(-1)
253
{
254
}
255
256
CVar
(
int
uid_,
int
inst_):
257
uid
(uid_),
258
inst
(inst_)
259
{
260
}
261
};
262
263
inline
bool
operator==
(
const
CVar
&a,
const
CVar
&b)
264
{
265
if
(a.
uid
!= b.
uid
)
266
return
false
;
267
268
if
(-1 == a.
uid
)
269
// do not match .inst when a.uid == -1 == b.uid
270
return
true
;
271
272
return
a.
inst
== b.
inst
;
273
}
274
275
inline
bool
operator!=
(
const
CVar
&a,
const
CVar
&b)
276
{
277
return
!
operator==
(a, b);
278
}
279
280
/// bundles static identification of a function with its call instance number
281
struct
CallInst
{
282
int
uid
;
///< uid of the function
283
int
inst
;
///< how many instances of the fnc we have on the stack
284
285
CallInst
(
const
SymBackTrace
*);
286
287
CallInst
(
int
uid_,
int
inst_):
288
uid
(uid_),
289
inst
(inst_)
290
{
291
}
292
};
293
294
/**
295
* lexicographical comparison of CallInst objects
296
* @note we need it in order to place the objects into ordered containers
297
*/
298
inline
bool
operator<
(
const
CallInst
&a,
const
CallInst
&b)
299
{
300
if
(a.
uid
< b.
uid
)
301
return
true
;
302
else
if
(b.
uid
< a.
uid
)
303
return
false
;
304
else
305
// we know (a.uid == b.uid) at this point, let's compare .inst
306
return
a.
inst
< b.
inst
;
307
}
308
309
/// a list of _program_ variables
310
typedef
std::vector<CVar>
TCVarList
;
311
312
/// a set of _program_ variables
313
typedef
std::set<CVar>
TCVarSet
;
314
315
/// only uninitialized or nullified blocks; generic arrays and strings need more
316
struct
UniformBlock
{
317
TOffset
off
;
///< relative placement of the block wrt. the root
318
TSizeOf
size
;
///< size of the block in bytes
319
TValId
tplValue
;
///< value you need to clone on object instantiation
320
};
321
322
/// a container used to return list of uniform blocks
323
typedef
std::map<TOffset, UniformBlock>
TUniBlockMap
;
324
325
/**
326
* lexicographical comparison of CVar objects
327
* @note we need it in order to place the objects into ordered containers
328
*/
329
inline
bool
operator<
(
const
CVar
&a,
const
CVar
&b)
330
{
331
if
(a.
uid
< b.
uid
)
332
return
true
;
333
else
if
(b.
uid
< a.
uid
)
334
return
false
;
335
else
336
// we know (a.uid == b.uid) at this point, let's compare .inst
337
return
a.
inst
< b.
inst
;
338
}
339
340
class
FldList
;
341
342
/// SymHeapCore - the elementary representation of the state of program memory
343
class
SymHeapCore
{
344
public
:
345
/// create an empty symbolic heap
346
SymHeapCore
(
TStorRef
,
Trace::Node
*);
347
348
/// destruction of the symbolic heap invalidates all IDs of its entities
349
virtual
~SymHeapCore
();
350
351
/// relatively cheap operation as long as SH_COPY_ON_WRITE is enabled
352
SymHeapCore
(
const
SymHeapCore
&);
353
354
/// relatively cheap operation as long as SH_COPY_ON_WRITE is enabled
355
SymHeapCore
&
operator=
(
const
SymHeapCore
&);
356
357
/// exchange the contents with the other heap (works in constant time)
358
virtual
void
swap
(
SymHeapCore
&);
359
360
/// each symbolic heap is associated with a CodeStorage model of code
361
TStorRef
stor
()
const
{
return
stor_
; }
362
363
/// each symbolic heap is associated with a trace graph node
364
Trace::Node
*
traceNode
()
const
;
365
366
/// update the current trace graph node that the heap is associated with
367
void
traceUpdate
(
Trace::Node
*);
368
369
/// the last assigned ID of a heap entity (not necessarily still valid)
370
unsigned
lastId
()
const
;
371
372
public
:
373
/**
374
* collect all objects having the given value inside
375
* @param dst reference to a container to store the result to
376
* @param val ID of the value to look for
377
* @param liveOnly if true, exclude objects that are no longer alive
378
* @note The operation may return from 0 to n objects.
379
*/
380
void
usedBy
(
FldList
&dst,
TValId
val,
bool
liveOnly =
false
)
const
;
381
382
/// return how many objects have the value inside
383
unsigned
usedByCount
(
TValId
val)
const
;
384
385
/// return all objects that point at/inside the given object
386
void
pointedBy
(
FldList
&dst,
TObjId
)
const
;
387
388
/// return how many objects point at/inside the given object
389
unsigned
pointedByCount
(
TObjId
)
const
;
390
391
/// write an uninitialized or nullified block of memory
392
void
writeUniformBlock
(
393
const
TObjId
obj,
394
const
UniformBlock
&ub,
395
TValSet
*killedPtrs = 0);
396
397
/// copy 'size' bytes of raw memory from 'src' to 'dst'
398
void
copyBlockOfRawMemory
(
399
const
TValId
dst,
400
const
TValId
src,
401
const
TSizeOf
size,
402
TValSet
*killedPtrs = 0);
403
404
public
:
405
/// define an explicit Neq predicate
406
void
addNeq
(
TValId
v1,
TValId
v2);
407
408
/// remove an explicit Neq predicate if defined
409
void
delNeq
(
TValId
v1,
TValId
v2);
410
411
/// true if there is an @b explicit Neq relation over the given values
412
bool
chkNeq
(
TValId
v1,
TValId
v2)
const
;
413
414
/// collect values connect with the given value via an extra predicate
415
void
gatherRelatedValues
(
TValList
&dst,
TValId
val)
const
;
416
417
/// transfer as many as possible extra heap predicates from this to dst
418
void
copyRelevantPreds
(
SymHeapCore
&dst,
const
TValMap
&valMap)
const
;
419
420
/// true if all Neq predicates can be mapped to Neq predicates in ref
421
bool
matchPreds
(
422
const
SymHeapCore
&ref,
423
const
TValMap
&valMap,
424
const
bool
nonZeroOnly =
false
)
425
const
;
426
427
public
:
428
/// translate the given address by the given offset
429
TValId
valByOffset
(
TValId
,
TOffset
offset);
430
431
/// create (or recycle) a VT_RANGE value at the given allocated address
432
TValId
valByRange
(
TValId
at,
IR::Range
range);
433
434
/// translate the given value by the given offset
435
TValId
valShift
(
TValId
valToShift,
TValId
shiftBy);
436
437
/// classify the object the given value points to
438
EValueTarget
valTarget
(
TValId
)
const
;
439
440
/// classify where the given value originates from
441
EValueOrigin
valOrigin
(
TValId
)
const
;
442
443
/// return the target specifier of the given address
444
ETargetSpecifier
targetSpec
(
TValId
addr)
const
;
445
446
/// return the object that the given address points to
447
TObjId
objByAddr
(
TValId
addr)
const
;
448
449
/// classify the storage class of the given object
450
EStorageClass
objStorClass
(
TObjId
)
const
;
451
452
/// return size (in bytes) of the given object
453
TSizeRange
objSize
(
TObjId
)
const
;
454
455
/// target address at the given object with target specifier and offset
456
virtual
TValId
addrOfTarget
(
TObjId
,
ETargetSpecifier
,
TOffset
off = 0);
457
458
public
:
459
/// return the address of the root which the given value is binded to
460
TValId
valRoot
(
TValId
)
const
;
461
462
/// return the relative placement from the root
463
TOffset
valOffset
(
TValId
)
const
;
464
465
/// return the offset range associated with the given VT_RANGE value
466
IR::Range
valOffsetRange
(
TValId
)
const
;
467
468
/// narrow down the offset range of the given VT_RANGE value
469
void
valRestrictRange
(
TValId
,
IR::Range
win);
470
471
/// difference between two pointers (makes sense only for shared roots)
472
TValId
diffPointers
(
const
TValId
v1,
const
TValId
v2);
473
474
/// return count of bytes (including NULL) we can safely read as string
475
TSizeRange
valSizeOfString
(
TValId
)
const
;
476
477
/// return the region corresponding to the given program variable
478
TObjId
regionByVar
(
CVar
,
bool
createIfNeeded);
479
480
/// clone the given object, including the outgoing has-value edges
481
virtual
TObjId
objClone
(
TObjId
);
482
483
public
:
484
/// replace all occurrences of val by replaceBy
485
virtual
void
valReplace
(
TValId
val,
TValId
replaceBy);
486
487
/// return the list of objects satisfying the given filtering predicate
488
void
gatherObjects
(
TObjList
&dst,
bool
(*)(
EStorageClass
) = 0)
const
;
489
490
/// list of live fields (including ptrs) inside the given object
491
void
gatherLiveFields
(
FldList
&dst,
TObjId
)
const
;
492
493
/// list of live pointers inside the give object
494
void
gatherLivePointers
(
FldList
&dst,
TObjId
)
const
;
495
496
/// list of uninitialized and nullified uniform blocks of the given obj
497
void
gatherUniformBlocks
(
TUniBlockMap
&dst,
TObjId
)
const
;
498
499
/// experimental optimization of joinUniBlocksCore()
500
bool
findCoveringUniBlocks
(
501
TUniBlockMap
*pCovered,
502
const
TObjId
root,
503
UniformBlock
block)
504
const
;
505
506
/// return program variable that the given object maps to
507
CVar
cVarByObject
(
TObjId
)
const
;
508
509
/**
510
* composite object given by val (applicable only on VT_COMPOSITE vals)
511
* @todo should we operate on FldHandle instead?
512
*/
513
TFldId
valGetComposite
(
TValId
val)
const
;
514
515
public
:
516
/// allocate a chunk of stack of known size from the select call stack
517
TObjId
stackAlloc
(
const
TSizeRange
&size,
const
CallInst
&from);
518
519
/// clear the list of anonymous stack objects of the given call instance
520
void
clearAnonStackObjects
(
TObjList
&dst,
const
CallInst
&of);
521
522
/// allocate a chunk of heap of known size
523
TObjId
heapAlloc
(
const
TSizeRange
&size);
524
525
/// return true if the given object can be still accessed safely
526
bool
isValid
(
TObjId
)
const
;
527
528
/// invalidate the given object
529
virtual
void
objInvalidate
(
TObjId
);
530
531
/// update the estimated type-info of the given object
532
void
objSetEstimatedType
(
TObjId
obj, TObjType clt);
533
534
/// return the estimated type-info of the given object
535
TObjType
objEstimatedType
(
TObjId
obj)
const
;
536
537
/// create a @b generic value, otherwise use addrOfTarget()
538
TValId
valCreate
(
EValueTarget
code,
EValueOrigin
origin);
539
540
/// wrap a custom value, such as integer literal, or code pointer
541
TValId
valWrapCustom
(
CustomValue
data);
542
543
/// unwrap a custom value, such as integer literal, or code pointer
544
const
CustomValue
&
valUnwrapCustom
(
TValId
)
const
;
545
546
public
:
547
/// prototype level of the given object (0 means not a prototype)
548
TProtoLevel
objProtoLevel
(
TObjId
)
const
;
549
550
/// set prototype level of the given boject (0 means not a prototype)
551
void
objSetProtoLevel
(
TObjId
obj,
TProtoLevel
level);
552
553
protected
:
554
/// return a @b data pointer inside the given object at the given offset
555
TFldId
ptrLookup
(
TObjId
obj,
TOffset
off);
556
557
/// return a field of the specified type at the specified offset in obj
558
TFldId
fldLookup
(
TObjId
obj,
TOffset
off, TObjType clt);
559
560
/// increment the external reference count of the given object
561
void
fldEnter
(
TFldId
);
562
563
/// decrement the external reference count (may trigger its destruction)
564
void
fldLeave
(
TFldId
);
565
566
/// FldHandle takes care of external reference count
567
friend
class
FldHandle
;
568
friend
class
PtrHandle
;
569
570
protected
:
571
// these should be accessed indirectly via FldHandle
572
TValId
valueOf
(
TFldId
fld);
573
TValId
placedAt
(
TFldId
fld);
574
TObjId
objByField
(
TFldId
fld)
const
;
575
TOffset
fieldOffset
(
TFldId
fld)
const
;
576
TObjType
fieldType
(
TFldId
fld)
const
;
577
void
setValOfField
(
TFldId
fld,
TValId
val,
TValSet
*killedPtrs = 0);
578
579
protected
:
580
TStorRef
stor_
;
581
582
private
:
583
struct
Private;
584
Private *
d
;
585
};
586
587
class
FldHandle
{
588
public
:
589
FldHandle
():
590
sh_
(0),
591
id_
(
FLD_INVALID
)
592
{
593
}
594
595
FldHandle
(
SymHeapCore
&
sh
,
TObjId
obj
, TObjType clt,
TOffset
off = 0):
596
sh_
(&sh),
597
id_
(sh.fldLookup(obj, off, clt))
598
{
599
if
(0 <
id_
)
600
sh_
->
fldEnter
(
id_
);
601
}
602
603
explicit
FldHandle
(
const
TFldId
special):
604
sh_
(0),
605
id_
(special)
606
{
607
CL_BREAK_IF
(0 < special);
608
}
609
610
FldHandle
(
const
FldHandle
&tpl):
611
sh_
(tpl.
sh_
),
612
id_
(tpl.
id_
)
613
{
614
if
(0 <
id_
)
615
sh_
->
fldEnter
(
id_
);
616
}
617
618
FldHandle
(
SymHeapCore
&
sh
,
const
FldHandle
&tpl):
619
sh_
(&sh),
620
id_
(tpl.
id_
)
621
{
622
if
(0 <
id_
)
623
sh_
->
fldEnter
(
id_
);
624
}
625
626
~FldHandle
() {
627
if
(0 <
id_
)
628
sh_
->
fldLeave
(
id_
);
629
}
630
631
FldHandle
&
operator=
(
const
FldHandle
&tpl) {
632
if
(0 <
id_
)
633
sh_
->
fldLeave
(
id_
);
634
635
sh_
= tpl.
sh_
;
636
id_
= tpl.
id_
;
637
if
(0 <
id_
)
638
sh_
->
fldEnter
(
id_
);
639
640
return
*
this
;
641
}
642
643
public
:
644
/// return the SymHeapCore instance associated with this handle
645
SymHeapCore
*
sh
()
const
{
return
sh_
; }
646
647
/// return raw field ID inside this handle (used mainly internally)
648
TFldId
fieldId
()
const
{
return
id_
; }
649
650
/// true if the given handle is valid (does not imply field validity)
651
bool
isValidHandle
()
const
{
return
(0 <
id_
); }
652
653
/// return the object that the field is part of
654
TObjId
obj
()
const
{
return
sh_
->
objByField
(
id_
); }
655
656
/// return the offset at which the field is placed within the object
657
TOffset
offset
()
const
{
return
sh_
->
fieldOffset
(
id_
); }
658
659
/// return the value inside the field (may trigger its initialization)
660
TValId
value
()
const
{
return
sh_
->
valueOf
(
id_
); }
661
662
/// return the address of the field (may trigger address instantiation)
663
TValId
placedAt
()
const
{
return
sh_
->
placedAt
(
id_
); }
664
665
/// static type-info of the given object (return 0 if not available)
666
TObjType
type
()
const
{
667
return
(this->
isValidHandle
())
668
?
sh_
->
fieldType
(
id_
)
669
: 0;
670
}
671
672
/// assign the given value, caller is responsible for garbage collecting
673
void
setValue
(
const
TValId
val,
TValSet
*killedPtrs = 0)
const
{
674
sh_
->
setValOfField
(
id_
, val, killedPtrs);
675
}
676
677
protected
:
678
FldHandle
(
SymHeapCore
&
sh
,
TFldId
id
):
679
sh_
(&sh),
680
id_
(id)
681
{
682
if
(0 <
id_
)
683
sh_
->
fldEnter
(
id_
);
684
}
685
686
friend
class
SymHeapCore
;
687
688
// TODO: remove this
689
friend
class
SymProc
;
690
691
// TODO: remove this
692
friend
const
char
*
valNullLabel
(
const
SymHeapCore
&,
const
TFldId
);
693
694
protected
:
695
SymHeapCore
*
sh_
;
696
TFldId
id_
;
697
};
698
699
/// this allows to insert FldHandle instances into std::set
700
inline
bool
operator<
(
const
FldHandle
&a,
const
FldHandle
&b)
701
{
702
if
(a.
sh
() < b.
sh
())
703
return
true
;
704
705
if
(b.
sh
() < a.
sh
())
706
return
false
;
707
708
return
(a.
fieldId
() < b.
fieldId
());
709
}
710
711
inline
bool
operator==
(
const
FldHandle
&a,
const
FldHandle
&b)
712
{
713
return
(a.
sh
() == b.
sh
())
714
&& (a.
fieldId
() == b.
fieldId
());
715
}
716
717
inline
bool
operator!=
(
const
FldHandle
&a,
const
FldHandle
&b)
718
{
719
return
!
operator==
(a, b);
720
}
721
722
class
PtrHandle
:
public
FldHandle
{
723
public
:
724
PtrHandle
(
SymHeapCore
&
sh
,
const
TObjId
obj
,
const
TOffset
off = 0):
725
FldHandle
(sh, sh.ptrLookup(obj, off))
726
{
727
if
(0 <
id_
)
728
sh_
->
fldEnter
(
id_
);
729
}
730
};
731
732
/// ugly, but typedefs do not support partial declarations
733
class
FldList
:
public
std::vector<FldHandle> { };
734
735
/// set of object handles
736
typedef
std::set<FldHandle>
TFldSet
;
737
738
/// a type used for minimal segment length (0+, 1+, ...)
739
typedef
short
TMinLen
;
740
741
/// enumeration of abstract object (although OK_REGION is not abstract)
742
enum
EObjKind
{
743
OK_REGION
= 0,
///< concrete object (not a segment)
744
OK_SLS
,
///< singly-linked list segment
745
OK_DLS
,
///< doubly-linked list segment
746
OK_OBJ_OR_NULL
,
///< 0..1 object, assume NULL if not allocated
747
OK_SEE_THROUGH
,
///< 0..1 object, see through if not allocated
748
OK_SEE_THROUGH_2N
///< OK_SEE_THROUGH with two next pointers
749
};
750
751
inline
bool
isMayExistObj
(
const
enum
EObjKind
kind)
752
{
753
switch
(kind) {
754
case
OK_OBJ_OR_NULL
:
755
case
OK_SEE_THROUGH
:
756
case
OK_SEE_THROUGH_2N
:
757
return
true
;
758
759
default
:
760
return
false
;
761
}
762
}
763
764
/// tuple of binding offsets assigned to abstract objects
765
struct
BindingOff
{
766
TOffset
head
;
///< target offset
767
TOffset
next
;
///< offset of the 'next' or 'r' pointer
768
TOffset
prev
;
///< offset of the 'prev' or 'l' pointer
769
770
BindingOff
():
771
head
(0),
772
next
(0),
773
prev
(0)
774
{
775
}
776
777
BindingOff
(
EObjKind
kind):
778
head
(-1),
779
next
(-1),
780
prev
(-1)
781
{
782
CL_BREAK_IF
(
OK_OBJ_OR_NULL
!= kind);
783
(void) kind;
784
}
785
};
786
787
/// point-wise comparison of BindingOff
788
inline
bool
operator==
(
const
BindingOff
&off1,
const
BindingOff
&off2)
789
{
790
return
off1.
head
== off2.
head
791
&& off1.
next
== off2.
next
792
&& off1.
prev
== off2.
prev
;
793
}
794
795
/// point-wise comparison of BindingOff
796
inline
bool
operator!=
(
const
BindingOff
&off1,
const
BindingOff
&off2)
797
{
798
return
!
operator==
(off1, off2);
799
}
800
801
/// extension of SymHeapCore dealing with abstract objects (list segments etc.)
802
class
SymHeap
:
public
SymHeapCore
{
803
public
:
804
/// create an empty symbolic heap
805
SymHeap
(
TStorRef
,
Trace::Node
*);
806
807
/// destruction of the symbolic heap invalidates all IDs of its entities
808
virtual
~SymHeap
();
809
810
/// relatively cheap operation as long as SH_COPY_ON_WRITE is enabled
811
SymHeap
(
const
SymHeap
&);
812
813
/// relatively cheap operation as long as SH_COPY_ON_WRITE is enabled
814
SymHeap
&
operator=
(
const
SymHeap
&);
815
816
virtual
void
swap
(
SymHeapCore
&);
817
818
public
:
819
/// kind of object (region, SLS, DLS, ...)
820
EObjKind
objKind
(
TObjId
)
const
;
821
822
/// tuple of binding offsets (next, prev, ...)
823
const
BindingOff
&
segBinding
(
TObjId
seg)
const
;
824
825
/// set properties of an abstract object, set abstract if not already
826
void
objSetAbstract
(
827
TObjId
seg,
828
EObjKind
kind,
829
const
BindingOff
&off);
830
831
/// set the given abstract object to be a concrete object (drops props)
832
void
objSetConcrete
(
TObjId
);
833
834
/// read the minimal segment length of the given abstract object
835
TMinLen
segMinLength
(
TObjId
seg)
const
;
836
837
/// assign the minimal segment length of the given abstract object
838
void
segSetMinLength
(
TObjId
seg, TMinLen len);
839
840
public
:
841
// just overrides (inherits the dox)
842
virtual
TValId
addrOfTarget
(
TObjId
,
ETargetSpecifier
,
TOffset
off = 0);
843
virtual
void
objInvalidate
(
TObjId
);
844
virtual
TObjId
objClone
(
TObjId
);
845
846
private
:
847
struct
Private;
848
Private *
d
;
849
};
850
851
/// enable/disable built-in self-checks (takes effect only in debug build)
852
void
enableProtectedMode
(
bool
enable);
853
854
/// temporarily disable protected mode of SymHeap in a debug build
855
class
ProtectionIntrusion
{
856
public
:
857
ProtectionIntrusion
() {
858
enableProtectedMode
(
false
);
859
}
860
861
~ProtectionIntrusion
() {
862
enableProtectedMode
(
true
);
863
}
864
};
865
866
#endif
/* H_GUARD_SYM_HEAP_H */
Generated on Sun Feb 10 2013 17:38:16 for Predator by
1.8.3.1