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  TValId atAddr,
42  TValId pointingTo,
43  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, TValId addr);
83 
84 TValId prevValFromSegAddr(const SymHeap &sh, 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 inline TMinLen objMinLength(const SymHeap &sh, TObjId obj)
108 {
109  if (!sh.isValid(obj))
110  return 0;
111 
112  const EObjKind kind = sh.objKind(obj);
113  if (OK_REGION == kind)
114  return 1;
115 
116  return sh.segMinLength(obj);
117 }
118 
119 /// return true if the given pair of values is proven to be non-equal
120 bool segProveNeq(const SymHeap &sh, TValId v1, TValId v2);
121 
122 /// if the current segment min length is lower than the given one, update it!
123 inline void segIncreaseMinLength(SymHeap &sh, const TObjId seg, TMinLen len)
124 {
125  CL_BREAK_IF(!len);
126 
127  if (sh.segMinLength(seg) < len)
128  sh.segSetMinLength(seg, len);
129 }
130 
131 /// we know (v1 != v2), update related segments in the given heap accordingly!
132 bool segApplyNeq(SymHeap &sh, TValId v1, TValId v2);
133 
134 inline bool isObjWithBinding(const EObjKind kind)
135 {
136  switch (kind) {
137  case OK_REGION:
138  case OK_OBJ_OR_NULL:
139  return false;
140 
141  case OK_SLS:
142  case OK_DLS:
143  case OK_SEE_THROUGH:
144  case OK_SEE_THROUGH_2N:
145  break;
146  }
147 
148  return true;
149 }
150 
151 inline void buildIgnoreList(
152  TFldSet &ignoreList,
153  const SymHeap &sh,
154  const TObjId obj)
155 {
156  SymHeap &writable = const_cast<SymHeap &>(sh);
157  TOffset off;
158  FldHandle tmp;
159 
160  const EObjKind kind = sh.objKind(obj);
161  switch (kind) {
162  case OK_REGION:
163  case OK_OBJ_OR_NULL:
164  return;
165 
166  case OK_DLS:
167  case OK_SEE_THROUGH_2N:
168  // preserve 'peer' field
169  off = sh.segBinding(obj).prev;
170  tmp = PtrHandle(writable, obj, off);
171  ignoreList.insert(tmp);
172  // fall through!
173 
174  case OK_SLS:
175  case OK_SEE_THROUGH:
176  // preserve 'next' field
177  off = sh.segBinding(obj).next;
178  tmp = PtrHandle(writable, obj, off);
179  ignoreList.insert(tmp);
180  }
181 }
182 
183 inline void buildIgnoreList(
184  TFldSet &ignoreList,
185  SymHeap &sh,
186  const TObjId obj,
187  const BindingOff &bf)
188 {
189  const PtrHandle next(sh, obj, bf.next);
190  if (next.isValidHandle())
191  ignoreList.insert(next);
192 
193  const PtrHandle prev(sh, obj, bf.prev);
194  if (prev.isValidHandle())
195  ignoreList.insert(prev);
196 }
197 
198 /// look through possibly empty objects and return the value seen
199 TValId lookThrough(const SymHeap &sh, TValId val, TValSet *pSeen = 0);
200 
201 /// true if all segments have populated next/prev pointers
202 bool segCheckConsistency(const SymHeap &sh);
203 
204 #endif /* H_GUARD_SYMSEG_H */