1 /* 2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef DATA_READER_H 6 #define DATA_READER_H 7 8 9 #include <string.h> 10 11 #include "Types.h" 12 13 14 class DataReader { 15 public: 16 DataReader() 17 : 18 fData(NULL), 19 fSize(0), 20 fInitialSize(0), 21 fAddressSize(4), 22 fIsBigEndian(false), 23 fOverflow(false) 24 { 25 } 26 27 DataReader(const void* data, off_t size, uint8 addressSize, bool isBigEndian) 28 { 29 SetTo(data, size, addressSize, isBigEndian); 30 } 31 32 void SetTo(const void* data, off_t size, uint8 addressSize, bool isBigEndian) 33 { 34 fData = (const uint8*)data; 35 fInitialSize = fSize = size; 36 fAddressSize = addressSize; 37 fIsBigEndian = isBigEndian; 38 fOverflow = false; 39 } 40 41 DataReader RestrictedReader() 42 { 43 return *this; 44 } 45 46 DataReader RestrictedReader(off_t maxLength) 47 { 48 return DataReader(fData, maxLength, fAddressSize, fIsBigEndian); 49 } 50 51 DataReader RestrictedReader(off_t relativeOffset, off_t maxLength) 52 { 53 return DataReader(fData + relativeOffset, maxLength, fAddressSize, fIsBigEndian); 54 } 55 56 bool HasData() const 57 { 58 return fSize > 0; 59 } 60 61 uint32 AddressSize() const 62 { 63 return fAddressSize; 64 } 65 66 bool IsBigEndian() const 67 { 68 return fIsBigEndian; 69 } 70 71 void SetAddressSize(uint8 addressSize) 72 { 73 fAddressSize = addressSize; 74 } 75 76 bool HasOverflow() const 77 { 78 return fOverflow; 79 } 80 81 const void* Data() const 82 { 83 return fData; 84 } 85 86 off_t BytesRemaining() const 87 { 88 return fSize; 89 } 90 91 off_t Offset() const 92 { 93 return fInitialSize - fSize; 94 } 95 96 void SeekAbsolute(off_t offset) 97 { 98 if (offset < 0) 99 offset = 0; 100 else if (offset > fInitialSize) 101 offset = fInitialSize; 102 103 fData += offset - Offset(); 104 fSize = fInitialSize - offset; 105 } 106 107 //TODO: take care of host vs target endianness 108 template<typename Type> 109 Type Read(const Type& defaultValue) 110 { 111 if (fSize < (off_t)sizeof(Type)) { 112 fOverflow = true; 113 fSize = 0; 114 return defaultValue; 115 } 116 117 Type data; 118 memcpy(&data, fData, sizeof(Type)); 119 120 fData += sizeof(Type); 121 fSize -= sizeof(Type); 122 123 return data; 124 } 125 126 target_addr_t ReadAddress(target_addr_t defaultValue) 127 { 128 return fAddressSize == 4 129 ? (target_addr_t)Read<uint32>(defaultValue) 130 : (target_addr_t)Read<uint64>(defaultValue); 131 } 132 133 uint64 ReadUnsignedLEB128(uint64 defaultValue) 134 { 135 uint64 result = 0; 136 int shift = 0; 137 while (true) { 138 uint8 byte = Read<uint8>(0); 139 result |= uint64(byte & 0x7f) << shift; 140 if ((byte & 0x80) == 0) 141 break; 142 shift += 7; 143 } 144 145 return fOverflow ? defaultValue : result; 146 } 147 148 int64 ReadSignedLEB128(int64 defaultValue) 149 { 150 int64 result = 0; 151 int shift = 0; 152 while (true) { 153 uint8 byte = Read<uint8>(0); 154 result |= uint64(byte & 0x7f) << shift; 155 shift += 7; 156 157 if ((byte & 0x80) == 0) { 158 // sign extend 159 if ((byte & 0x40) != 0 && shift < 64) 160 result |= -((uint64)1 << shift); 161 break; 162 } 163 } 164 165 return fOverflow ? defaultValue : result; 166 } 167 168 uint64 ReadUInt(size_t numBytes, uint64 defaultValue) 169 { 170 uint64 result = 0; 171 if (fIsBigEndian) { 172 for (size_t i = 0; i < numBytes; i++) { 173 uint8 byte = Read<uint8>(0); 174 result <<= 8; 175 result |= (uint64)byte; 176 } 177 } else { 178 int shift = 0; 179 for (size_t i = 0; i < numBytes; i++) { 180 uint8 byte = Read<uint8>(0); 181 result |= (uint64)byte << shift; 182 shift += 8; 183 } 184 } 185 186 return fOverflow ? defaultValue : result; 187 } 188 189 uint32 ReadU24(uint32 defaultValue) 190 { 191 return ReadUInt(3, defaultValue); 192 } 193 194 const char* ReadString() 195 { 196 const char* string = (const char*)fData; 197 while (fSize > 0) { 198 fData++; 199 fSize--; 200 201 if (fData[-1] == 0) 202 return string; 203 } 204 205 fOverflow = true; 206 return NULL; 207 } 208 209 uint64 ReadInitialLength(bool& _dwarf64) 210 { 211 uint64 length = Read<uint32>(0); 212 _dwarf64 = (length == 0xffffffff); 213 if (_dwarf64) 214 length = Read<uint64>(0); 215 return length; 216 } 217 218 bool Skip(off_t bytes) 219 { 220 if (bytes < 0) 221 return false; 222 223 if (bytes > fSize) { 224 fSize = 0; 225 fOverflow = true; 226 return false; 227 } 228 229 fData += bytes; 230 fSize -= bytes; 231 232 return true; 233 } 234 235 private: 236 const uint8* fData; 237 off_t fSize; 238 off_t fInitialSize; 239 uint8 fAddressSize; 240 bool fIsBigEndian; 241 bool fOverflow; 242 }; 243 244 245 #endif // DATA_READER_H 246