xref: /haiku/src/kits/debugger/types/ValueLocation.cpp (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
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