1 /*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2013, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7 #include <stdio.h>
8
9 #include "ValueLocation.h"
10
11
12 // #pragma mark - ValuePieceLocation
13
14
15 ValuePieceLocation&
Normalize(bool bigEndian)16 ValuePieceLocation::Normalize(bool bigEndian)
17 {
18 uint64 excessMSBs = bitOffset / 8;
19 uint64 excessLSBs = size - (bitOffset + bitSize + 7) / 8;
20
21 if (excessMSBs > 0 || excessLSBs > 0) {
22 switch (type) {
23 case VALUE_PIECE_LOCATION_MEMORY:
24 if (bigEndian)
25 address += excessMSBs;
26 else
27 address += excessLSBs;
28 bitOffset -= excessMSBs * 8;
29 size -= excessMSBs + excessLSBs;
30 break;
31 case VALUE_PIECE_LOCATION_UNKNOWN:
32 bitOffset -= excessMSBs * 8;
33 size -= excessMSBs + excessLSBs;
34 break;
35 case VALUE_PIECE_LOCATION_REGISTER:
36 default:
37 break;
38 }
39 }
40
41 return *this;
42 }
43
44
45 // #pragma mark - ValueLocation
46
47
ValueLocation()48 ValueLocation::ValueLocation()
49 :
50 fBigEndian(false),
51 fWritable(false)
52 {
53 }
54
55
ValueLocation(bool bigEndian)56 ValueLocation::ValueLocation(bool bigEndian)
57 :
58 fBigEndian(bigEndian),
59 fWritable(false)
60 {
61 }
62
63
ValueLocation(bool bigEndian,const ValuePieceLocation & piece)64 ValueLocation::ValueLocation(bool bigEndian, const ValuePieceLocation& piece)
65 :
66 fBigEndian(bigEndian)
67 {
68 AddPiece(piece);
69 }
70
71
ValueLocation(const ValueLocation & other)72 ValueLocation::ValueLocation(const ValueLocation& other)
73 :
74 fPieces(other.fPieces),
75 fBigEndian(other.fBigEndian)
76 {
77 }
78
79
80 bool
SetToByteOffset(const ValueLocation & other,uint64 byteOffset,uint64 byteSize)81 ValueLocation::SetToByteOffset(const ValueLocation& other, uint64 byteOffset,
82 uint64 byteSize)
83 {
84 Clear();
85
86 fBigEndian = other.fBigEndian;
87 ValuePieceLocation piece = other.PieceAt(0);
88 piece.SetToMemory(piece.address + byteOffset);
89 piece.SetSize(byteSize);
90
91 return AddPiece(piece);
92 }
93
94
95 bool
SetTo(const ValueLocation & other,uint64 bitOffset,uint64 bitSize)96 ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
97 uint64 bitSize)
98 {
99 Clear();
100
101 fBigEndian = other.fBigEndian;
102
103 // compute the total bit size
104 int32 count = other.CountPieces();
105 uint64 totalBitSize = 0;
106 for (int32 i = 0; i < count; i++) {
107 const ValuePieceLocation &piece = other.PieceAt(i);
108 totalBitSize += piece.bitSize;
109 }
110
111 // adjust requested bit offset/size to something reasonable, if necessary
112 if (bitOffset + bitSize > totalBitSize) {
113 if (bitOffset >= totalBitSize)
114 return true;
115 bitSize = totalBitSize - bitOffset;
116 }
117
118 if (fBigEndian) {
119 // Big endian: Skip the superfluous most significant bits, copy the
120 // pieces we need (cutting the first and the last one as needed) and
121 // ignore the remaining pieces.
122
123 // skip pieces for the most significant bits we don't need anymore
124 uint64 bitsToSkip = bitOffset;
125 int32 i;
126 ValuePieceLocation piece;
127 for (i = 0; i < count; i++) {
128 const ValuePieceLocation& tempPiece = other.PieceAt(i);
129 if (tempPiece.bitSize > bitsToSkip) {
130 if (!piece.Copy(tempPiece))
131 return false;
132 break;
133 }
134 bitsToSkip -= tempPiece.bitSize;
135 }
136
137 // handle partial piece
138 if (bitsToSkip > 0) {
139 piece.bitOffset += bitsToSkip;
140 piece.bitSize -= bitsToSkip;
141 piece.Normalize(fBigEndian);
142 }
143
144 // handle remaining pieces
145 while (bitSize > 0) {
146 if (piece.bitSize > bitSize) {
147 // the piece is bigger than the remaining size -- cut it
148 piece.bitSize = bitSize;
149 piece.Normalize(fBigEndian);
150 bitSize = 0;
151 } else
152 bitSize -= piece.bitSize;
153
154 if (!AddPiece(piece))
155 return false;
156
157 if (++i >= count)
158 break;
159
160 if (!piece.Copy(other.PieceAt(i)))
161 return false;
162 }
163 } else {
164 // Little endian: Skip the superfluous least significant bits, copy the
165 // pieces we need (cutting the first and the last one as needed) and
166 // ignore the remaining pieces.
167
168 // skip pieces for the least significant bits we don't need anymore
169 uint64 bitsToSkip = totalBitSize - bitOffset - bitSize;
170 int32 i;
171 ValuePieceLocation piece;
172 for (i = 0; i < count; i++) {
173 const ValuePieceLocation& tempPiece = other.PieceAt(i);
174 if (tempPiece.bitSize > bitsToSkip) {
175 if (!piece.Copy(tempPiece))
176 return false;
177 break;
178 }
179 bitsToSkip -= piece.bitSize;
180 }
181
182 // handle partial piece
183 if (bitsToSkip > 0) {
184 piece.bitSize -= bitsToSkip;
185 piece.Normalize(fBigEndian);
186 }
187
188 // handle remaining pieces
189 while (bitSize > 0) {
190 if (piece.bitSize > bitSize) {
191 // the piece is bigger than the remaining size -- cut it
192 piece.bitOffset += piece.bitSize - bitSize;
193 piece.bitSize = bitSize;
194 piece.Normalize(fBigEndian);
195 bitSize = 0;
196 } else
197 bitSize -= piece.bitSize;
198
199 if (!AddPiece(piece))
200 return false;
201
202 if (++i >= count)
203 break;
204
205 if (!piece.Copy(other.PieceAt(i)))
206 return false;
207 }
208 }
209
210 return true;
211 }
212
213
214 void
Clear()215 ValueLocation::Clear()
216 {
217 fWritable = false;
218 fPieces.clear();
219 }
220
221
222 bool
AddPiece(const ValuePieceLocation & piece)223 ValueLocation::AddPiece(const ValuePieceLocation& piece)
224 {
225 // Just add, don't normalize. This allows for using the class with different
226 // semantics (e.g. in the DWARF code).
227 try {
228 fPieces.push_back(piece);
229 } catch (...) {
230 return false;
231 }
232
233 if (fPieces.size() == 1)
234 fWritable = piece.writable;
235 else
236 fWritable = fWritable && piece.writable;
237
238 return true;
239 }
240
241
242 int32
CountPieces() const243 ValueLocation::CountPieces() const
244 {
245 return fPieces.size();
246 }
247
248
249 ValuePieceLocation
PieceAt(int32 index) const250 ValueLocation::PieceAt(int32 index) const
251 {
252 if (index < 0 || index >= (int32)fPieces.size())
253 return ValuePieceLocation();
254
255 return fPieces[index];
256 }
257
258
259 bool
SetPieceAt(int32 index,const ValuePieceLocation & piece)260 ValueLocation::SetPieceAt(int32 index, const ValuePieceLocation& piece)
261 {
262 if (index < 0 || index >= (int32)fPieces.size())
263 return false;
264
265 return fPieces[index].Copy(piece);
266 }
267
268
269 ValueLocation&
operator =(const ValueLocation & other)270 ValueLocation::operator=(const ValueLocation& other)
271 {
272 fPieces = other.fPieces;
273 fBigEndian = other.fBigEndian;
274 return *this;
275 }
276
277
278 void
Dump() const279 ValueLocation::Dump() const
280 {
281 int32 count = fPieces.size();
282 printf("ValueLocation: %s endian, %" B_PRId32 " pieces:\n",
283 fBigEndian ? "big" : "little", count);
284
285 for (int32 i = 0; i < count; i++) {
286 const ValuePieceLocation& piece = fPieces[i];
287 switch (piece.type) {
288 case VALUE_PIECE_LOCATION_INVALID:
289 printf(" invalid\n");
290 continue;
291 case VALUE_PIECE_LOCATION_UNKNOWN:
292 printf(" unknown");
293 break;
294 case VALUE_PIECE_LOCATION_MEMORY:
295 printf(" address %#" B_PRIx64, piece.address);
296 break;
297 case VALUE_PIECE_LOCATION_REGISTER:
298 printf(" register %" B_PRIu32, piece.reg);
299 break;
300 case VALUE_PIECE_LOCATION_IMPLICIT:
301 printf(" implicit value: ");
302 for (uint32 j = 0; j < piece.size; j++)
303 printf("%x ", ((char *)piece.value)[j]);
304 break;
305 }
306
307 printf(" size: %" B_PRIu64 " (%" B_PRIu64 " bits), offset: %" B_PRIu64
308 " bits\n", piece.size, piece.bitSize, piece.bitOffset);
309 }
310 }
311