xref: /haiku/src/kits/debugger/dwarf/DataReader.h (revision 4c07199d8201fcf267e90be0d24b76799d03cea6)
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