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 15ValuePieceLocation& 16ValuePieceLocation::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 48ValueLocation::ValueLocation() 49 : 50 fBigEndian(false), 51 fWritable(false) 52{ 53} 54 55 56ValueLocation::ValueLocation(bool bigEndian) 57 : 58 fBigEndian(bigEndian), 59 fWritable(false) 60{ 61} 62 63 64ValueLocation::ValueLocation(bool bigEndian, const ValuePieceLocation& piece) 65 : 66 fBigEndian(bigEndian) 67{ 68 AddPiece(piece); 69} 70 71 72ValueLocation::ValueLocation(const ValueLocation& other) 73 : 74 fPieces(other.fPieces), 75 fBigEndian(other.fBigEndian) 76{ 77} 78 79 80bool 81ValueLocation::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 95bool 96ValueLocation::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 214void 215ValueLocation::Clear() 216{ 217 fWritable = false; 218 fPieces.clear(); 219} 220 221 222bool 223ValueLocation::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 242int32 243ValueLocation::CountPieces() const 244{ 245 return fPieces.size(); 246} 247 248 249ValuePieceLocation 250ValueLocation::PieceAt(int32 index) const 251{ 252 if (index < 0 || index >= (int32)fPieces.size()) 253 return ValuePieceLocation(); 254 255 return fPieces[index]; 256} 257 258 259bool 260ValueLocation::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 269ValueLocation& 270ValueLocation::operator=(const ValueLocation& other) 271{ 272 fPieces = other.fPieces; 273 fBigEndian = other.fBigEndian; 274 return *this; 275} 276 277 278void 279ValueLocation::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