Debugger: Split into core library and application.
[haiku.git] / src / kits / debugger / types / ValueLocation.cpp
blobab5738487c2484e4b7a9fe7ba60e53bcfb662df3
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 */
7 #include <stdio.h>
9 #include "ValueLocation.h"
12 // #pragma mark - ValuePieceLocation
15 ValuePieceLocation&
16 ValuePieceLocation::Normalize(bool bigEndian)
18 uint64 excessMSBs = bitOffset / 8;
19 uint64 excessLSBs = size - (bitOffset + bitSize + 7) / 8;
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;
41 return *this;
45 // #pragma mark - ValueLocation
48 ValueLocation::ValueLocation()
50 fBigEndian(false),
51 fWritable(false)
56 ValueLocation::ValueLocation(bool bigEndian)
58 fBigEndian(bigEndian),
59 fWritable(false)
64 ValueLocation::ValueLocation(bool bigEndian, const ValuePieceLocation& piece)
66 fBigEndian(bigEndian)
68 AddPiece(piece);
72 ValueLocation::ValueLocation(const ValueLocation& other)
74 fPieces(other.fPieces),
75 fBigEndian(other.fBigEndian)
80 bool
81 ValueLocation::SetToByteOffset(const ValueLocation& other, uint64 byteOffset,
82 uint64 byteSize)
84 Clear();
86 fBigEndian = other.fBigEndian;
87 ValuePieceLocation piece = other.PieceAt(0);
88 piece.SetToMemory(piece.address + byteOffset);
89 piece.SetSize(byteSize);
91 return AddPiece(piece);
95 bool
96 ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
97 uint64 bitSize)
99 Clear();
101 fBigEndian = other.fBigEndian;
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;
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;
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.
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;
134 bitsToSkip -= tempPiece.bitSize;
137 // handle partial piece
138 if (bitsToSkip > 0) {
139 piece.bitOffset += bitsToSkip;
140 piece.bitSize -= bitsToSkip;
141 piece.Normalize(fBigEndian);
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;
154 if (!AddPiece(piece))
155 return false;
157 if (++i >= count)
158 break;
160 if (!piece.Copy(other.PieceAt(i)))
161 return false;
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.
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;
179 bitsToSkip -= piece.bitSize;
182 // handle partial piece
183 if (bitsToSkip > 0) {
184 piece.bitSize -= bitsToSkip;
185 piece.Normalize(fBigEndian);
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;
199 if (!AddPiece(piece))
200 return false;
202 if (++i >= count)
203 break;
205 if (!piece.Copy(other.PieceAt(i)))
206 return false;
210 return true;
214 void
215 ValueLocation::Clear()
217 fWritable = false;
218 fPieces.clear();
222 bool
223 ValueLocation::AddPiece(const ValuePieceLocation& piece)
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;
233 if (fPieces.size() == 1)
234 fWritable = piece.writable;
235 else
236 fWritable = fWritable && piece.writable;
238 return true;
242 int32
243 ValueLocation::CountPieces() const
245 return fPieces.size();
249 ValuePieceLocation
250 ValueLocation::PieceAt(int32 index) const
252 if (index < 0 || index >= (int32)fPieces.size())
253 return ValuePieceLocation();
255 return fPieces[index];
259 bool
260 ValueLocation::SetPieceAt(int32 index, const ValuePieceLocation& piece)
262 if (index < 0 || index >= (int32)fPieces.size())
263 return false;
265 return fPieces[index].Copy(piece);
269 ValueLocation&
270 ValueLocation::operator=(const ValueLocation& other)
272 fPieces = other.fPieces;
273 fBigEndian = other.fBigEndian;
274 return *this;
278 void
279 ValueLocation::Dump() const
281 int32 count = fPieces.size();
282 printf("ValueLocation: %s endian, %" B_PRId32 " pieces:\n",
283 fBigEndian ? "big" : "little", count);
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;
307 printf(" size: %" B_PRIu64 " (%" B_PRIu64 " bits), offset: %" B_PRIu64
308 " bits\n", piece.size, piece.bitSize, piece.bitOffset);