xref: /haiku/src/kits/debugger/dwarf/DataReader.h (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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 		fOverflow(false)
23 	{
24 	}
25 
26 	DataReader(const void* data, off_t size, uint8 addressSize)
27 	{
28 		SetTo(data, size, addressSize);
29 	}
30 
31 	void SetTo(const void* data, off_t size, uint8 addressSize)
32 	{
33 		fData = (const uint8*)data;
34 		fInitialSize = fSize = size;
35 		fAddressSize = addressSize;
36 		fOverflow = false;
37 	}
38 
39 	DataReader RestrictedReader()
40 	{
41 		return *this;
42 	}
43 
44 	DataReader RestrictedReader(off_t maxLength)
45 	{
46 		return DataReader(fData, maxLength, fAddressSize);
47 	}
48 
49 	DataReader RestrictedReader(off_t relativeOffset, off_t maxLength)
50 	{
51 		return DataReader(fData + relativeOffset, maxLength, fAddressSize);
52 	}
53 
54 	bool HasData() const
55 	{
56 		return fSize > 0;
57 	}
58 
59 	uint32 AddressSize() const
60 	{
61 		return fAddressSize;
62 	}
63 
64 	void SetAddressSize(uint8 addressSize)
65 	{
66 		fAddressSize = addressSize;
67 	}
68 
69 	bool HasOverflow() const
70 	{
71 		return fOverflow;
72 	}
73 
74 	const void* Data() const
75 	{
76 		return fData;
77 	}
78 
79 	off_t BytesRemaining() const
80 	{
81 		return fSize;
82 	}
83 
84 	off_t Offset() const
85 	{
86 		return fInitialSize - fSize;
87 	}
88 
89 	void SeekAbsolute(off_t offset)
90 	{
91 		if (offset < 0)
92 			offset = 0;
93 		else if (offset > fInitialSize)
94 			offset = fInitialSize;
95 
96 		fData += offset - Offset();
97 		fSize = fInitialSize - offset;
98 	}
99 
100 	template<typename Type>
101 	Type Read(const Type& defaultValue)
102 	{
103 		if (fSize < (off_t)sizeof(Type)) {
104 			fOverflow = true;
105 			fSize = 0;
106 			return defaultValue;
107 		}
108 
109 		Type data;
110 		memcpy(&data, fData, sizeof(Type));
111 
112 		fData += sizeof(Type);
113 		fSize -= sizeof(Type);
114 
115 		return data;
116 	}
117 
118 	target_addr_t ReadAddress(target_addr_t defaultValue)
119 	{
120 		return fAddressSize == 4
121 			? (target_addr_t)Read<uint32>(defaultValue)
122 			: (target_addr_t)Read<uint64>(defaultValue);
123 	}
124 
125 	uint64 ReadUnsignedLEB128(uint64 defaultValue)
126 	{
127 		uint64 result = 0;
128 		int shift = 0;
129 		while (true) {
130 			uint8 byte = Read<uint8>(0);
131 			result |= uint64(byte & 0x7f) << shift;
132 			if ((byte & 0x80) == 0)
133 				break;
134 			shift += 7;
135 		}
136 
137 		return fOverflow ? defaultValue : result;
138 	}
139 
140 	int64 ReadSignedLEB128(int64 defaultValue)
141 	{
142 		int64 result = 0;
143 		int shift = 0;
144 		while (true) {
145 			uint8 byte = Read<uint8>(0);
146 			result |= uint64(byte & 0x7f) << shift;
147 			shift += 7;
148 
149 			if ((byte & 0x80) == 0) {
150 				// sign extend
151 				if ((byte & 0x40) != 0 && shift < 64)
152 					result |= -((uint64)1 << shift);
153 				break;
154 			}
155 		}
156 
157 		return fOverflow ? defaultValue : result;
158 	}
159 
160 	uint32 ReadU24(uint32 defaultValue)
161 	{
162 		uint8 res1 = Read<uint8>(0);
163 		uint8 res2 = Read<uint8>(0);
164 		uint8 res3 = Read<uint8>(0);
165 #if defined(__HAIKU_LITTLE_ENDIAN)
166 		uint32 result = res1 | (res2 << 8) | (res3 << 16);
167 #elif defined(__HAIKU_BIG_ENDIAN)
168 		uint32 result = res3 | (res2 << 8) | (res1 << 16);
169 #else
170 #error endiannes not defined
171 #endif
172 		return fOverflow ? defaultValue : result;
173 	}
174 
175 	const char* ReadString()
176 	{
177 		const char* string = (const char*)fData;
178 		while (fSize > 0) {
179 			fData++;
180 			fSize--;
181 
182 			if (fData[-1] == 0)
183 				return string;
184 		}
185 
186 		fOverflow = true;
187 		return NULL;
188 	}
189 
190 	uint64 ReadInitialLength(bool& _dwarf64)
191 	{
192 		uint64 length = Read<uint32>(0);
193 		_dwarf64 = (length == 0xffffffff);
194 		if (_dwarf64)
195 			length = Read<uint64>(0);
196 		return length;
197 	}
198 
199 	bool Skip(off_t bytes)
200 	{
201 		if (bytes < 0)
202 			return false;
203 
204 		if (bytes > fSize) {
205 			fSize = 0;
206 			fOverflow = true;
207 			return false;
208 		}
209 
210 		fData += bytes;
211 		fSize -= bytes;
212 
213 		return true;
214 	}
215 
216 private:
217 	const uint8*	fData;
218 	off_t			fSize;
219 	off_t			fInitialSize;
220 	uint8			fAddressSize;
221 	bool			fOverflow;
222 };
223 
224 
225 #endif	// DATA_READER_H
226