Predator  [unstable] git snapshot
symseg.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Kamil Dudka <kdudka@redhat.com>
3  *
4  * This file is part of predator.
5  *
6  * predator is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * any later version.
10  *
11  * predator is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with predator. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef H_GUARD_SYMSEG_H
21 #define H_GUARD_SYMSEG_H
22 
23 /**
24  * @file symseg.hh
25  * some generic utilities operating on list segments (SLS, DLS, Linux lists)
26  */
27 
28 #include "config.h"
29 #include "symheap.hh"
30 #include "symutil.hh"
31 
32 /**
33  * return true if there is a list segment among the given pair of values
34  * @param sh an instance of symbolic heap
35  * @param atAddr address of the heap object for consideration
36  * @param pointingTo target address of the given potential list segment
37  * @param kind kind of list segment to look for
38  */
39 bool haveSeg(
40  const SymHeap &sh,
41  const TValId atAddr,
42  const TValId pointingTo,
43  const EObjKind kind);
44 
45 /**
46  * return true if there is a DLS (Doubly-linked List Segment) among the given
47  * pair of values
48  * @param sh an instance of symbolic heap
49  * @param atAddr address of the heap object for consideration
50  * @param peerAddr potential address of DLS peer object
51  */
52 bool haveDlSegAt(const SymHeap &sh, TValId atAddr, TValId peerAddr);
53 
54 /// return 'next' pointer in the given segment
55 inline PtrHandle nextPtrFromSeg(const SymHeap &sh, TObjId seg)
56 {
57  CL_BREAK_IF(OK_REGION == sh.objKind(seg));
58 
59  const BindingOff &off = sh.segBinding(seg);
60  return PtrHandle(const_cast<SymHeap &>(sh), seg, off.next);
61 }
62 
63 /// return 'prev' pointer in the given segment
64 inline PtrHandle prevPtrFromSeg(const SymHeap &sh, TObjId seg)
65 {
66  CL_BREAK_IF(OK_REGION == sh.objKind(seg));
67 
68  const BindingOff &off = sh.segBinding(seg);
69  return PtrHandle(const_cast<SymHeap &>(sh), seg, off.prev);
70 }
71 
72 /// return the value of 'next' in the given segment
73 inline TValId nextValFromSeg(const SymHeap &sh, TObjId seg)
74 {
75  if (OK_OBJ_OR_NULL == sh.objKind(seg))
76  return VAL_NULL;
77 
78  const FldHandle ptrNext = nextPtrFromSeg(sh, seg);
79  return ptrNext.value();
80 }
81 
82 TValId nextValFromSegAddr(const SymHeap &sh, const TValId addr);
83 
84 TValId prevValFromSegAddr(const SymHeap &sh, const TValId addr);
85 
86 inline TOffset headOffset(const SymHeap &sh, const TObjId seg)
87 {
88  const EObjKind kind = sh.objKind(seg);
89  CL_BREAK_IF(OK_REGION == kind);
90 
91  return (OK_OBJ_OR_NULL == kind)
92  ? 0
93  : sh.segBinding(seg).head;
94 }
95 
96 /// return address of segment's head (useful mainly for Linux lists)
98 {
99  CL_BREAK_IF(OK_REGION == sh.objKind(seg));
100 
101  const BindingOff &off = sh.segBinding(seg);
102 
103  SymHeap &shWritable = const_cast<SymHeap &>(sh);
104  return shWritable.addrOfTarget(seg, ts, off.head);
105 }
106 
107 /// we require obj to be an abstract object
108 inline TObjId segNextObj(SymHeap &sh, TObjId obj)
109 {
110  const EObjKind kind = sh.objKind(obj);
111  if (OK_OBJ_OR_NULL == kind)
112  return OBJ_NULL;
113 
114  const BindingOff off = sh.segBinding(obj);
115  const TOffset offNext = (OK_DLS == kind)
116  ? off.prev
117  : off.next;
118 
119  return nextObj(sh, obj, offNext);
120 }
121 
122 inline TMinLen objMinLength(const SymHeap &sh, TObjId obj)
123 {
124  if (!sh.isValid(obj))
125  return 0;
126 
127  const EObjKind kind = sh.objKind(obj);
128  if (OK_REGION == kind)
129  return 1;
130 
131  return sh.segMinLength(obj);
132 }
133 
134 /// return true if the given pair of values is proven to be non-equal
135 bool segProveNeq(const SymHeap &sh, TValId v1, TValId v2);
136 
137 /// if the current segment min length is lower than the given one, update it!
138 inline void segIncreaseMinLength(SymHeap &sh, const TObjId seg, TMinLen len)
139 {
140  CL_BREAK_IF(!len);
141 
142  if (sh.segMinLength(seg) < len)
143  sh.segSetMinLength(seg, len);
144 }
145 
146 /// we know (v1 != v2), update related segments in the given heap accordingly!
147 bool segApplyNeq(SymHeap &sh, TValId v1, TValId v2);
148 
149 inline bool isObjWithBinding(const EObjKind kind)
150 {
151  switch (kind) {
152  case OK_REGION:
153  case OK_OBJ_OR_NULL:
154  return false;
155 
156  case OK_SLS:
157  case OK_DLS:
158  case OK_SEE_THROUGH:
159  case OK_SEE_THROUGH_2N:
160  break;
161  }
162 
163  return true;
164 }
165 
166 inline void buildIgnoreList(
167  TFldSet &ignoreList,
168  const SymHeap &sh,
169  const TObjId obj)
170 {
171  SymHeap &writable = const_cast<SymHeap &>(sh);
172  TOffset off;
173  FldHandle tmp;
174 
175  const EObjKind kind = sh.objKind(obj);
176  switch (kind) {
177  case OK_REGION:
178  case OK_OBJ_OR_NULL:
179  return;
180 
181  case OK_DLS:
182  case OK_SEE_THROUGH_2N:
183  // preserve 'peer' field
184  off = sh.segBinding(obj).prev;
185  tmp = PtrHandle(writable, obj, off);
186  ignoreList.insert(tmp);
187  // fall through!
188 
189  case OK_SLS:
190  case OK_SEE_THROUGH:
191  // preserve 'next' field
192  off = sh.segBinding(obj).next;
193  tmp = PtrHandle(writable, obj, off);
194  ignoreList.insert(tmp);
195  }
196 }
197 
198 inline void buildIgnoreList(
199  TFldSet &ignoreList,
200  SymHeap &sh,
201  const TObjId obj,
202  const BindingOff &bf)
203 {
204  const PtrHandle next(sh, obj, bf.next);
205  if (next.isValidHandle())
206  ignoreList.insert(next);
207 
208  const PtrHandle prev(sh, obj, bf.prev);
209  if (prev.isValidHandle())
210  ignoreList.insert(prev);
211 }
212 
213 /// look through possibly empty objects and return the value seen
214 TValId lookThrough(const SymHeap &sh, TValId val, TValSet *pSeen = 0);
215 
216 /// true if all segments have populated next/prev pointers
217 bool segCheckConsistency(const SymHeap &sh);
218 
219 #endif /* H_GUARD_SYMSEG_H */