File: Stream.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (225 lines) | stat: -rw-r--r-- 4,962 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#pragma once
#include "Utils/Bitwise.h"
#include "Registers.h"

namespace code {
	namespace dwarf {

		/**
		 * Definitions of some useful DWARF constants.
		 */
#define DW_CFA_advance_loc        0x40 // + delta
#define DW_CFA_offset             0x80 // + register
#define DW_CFA_restore            0xC0 // + register
#define DW_CFA_nop                0x00
#define DW_CFA_set_loc            0x01
#define DW_CFA_advance_loc1       0x02
#define DW_CFA_advance_loc2       0x03
#define DW_CFA_advance_loc4       0x04
#define DW_CFA_offset_extended    0x05
#define DW_CFA_restore_extended   0x06
#define DW_CFA_undefined          0x07
#define DW_CFA_same_value         0x08
#define DW_CFA_register           0x09
#define DW_CFA_remember_state     0x0a
#define DW_CFA_restore_state      0x0b
#define DW_CFA_def_cfa            0x0c
#define DW_CFA_def_cfa_register   0x0d
#define DW_CFA_def_cfa_offset     0x0e
#define DW_CFA_def_cfa_expression 0x0f
#define DW_CFA_expression         0x10
#define DW_CFA_offset_extended_sf 0x11
#define DW_CFA_def_cfa_sf         0x12
#define DW_CFA_def_cfa_offset_sf  0x13
#define DW_CFA_val_offset         0x14
#define DW_CFA_val_offset_sf      0x15
#define DW_CFA_val_expression     0x16

#define DW_EH_PE_absptr 0x00

		// Extensions specific to AARCH64 (ARM64)
#define DW_CFA_AARCH64_negate_ra_state 0x2D
#define DW_CFA_AARCH64_negate_ra_state_with_pc 0x2C

		/**
		 * Output to a buffer in DWARF compatible format.
		 */
		struct DStream {
			byte *to;
			nat pos;
			nat len;

			// Initialize.
			DStream(byte *to, nat len) : to(to), pos(0), len(len) {}
			DStream(byte *to, nat len, nat pos) : to(to), pos(pos), len(len) {}

			// Did we run out of space?
			bool overflow() const {
				return pos > len;
			}

			// Write a byte.
			void putByte(byte b) {
				if (pos < len)
					to[pos] = b;
				pos++;
			}

			// Write a pointer.
			void putPtr(const void *value) {
				if (pos + sizeof(value) <= len) {
					const void **d = (const void **)&to[pos];
					*d = value;
				}
				pos += sizeof(value);
			}

			// Write an unsigned number (encoded as LEB128).
			void putUNum(nat value) {
				while (value >= 0x80) {
					putByte((value & 0x7F) | 0x80);
					value >>= 7;
				}
				putByte(value & 0x7F);
			}

			// Write a signed number (encoded as LEB128).
			void putSNum(int value) {
				nat src = value;
				nat bits = value;
				if (value < 0) {
					bits = ~bits; // make 'positive'
					bits <<= 1; // make sure to get at least one sign bit in the output.
				}

				while (bits >= 0x80) {
					putByte((src & 0x7F) | 0x80);
					src >>= 7;
					bits >>= 7;
				}
				putByte(src & 0x7F);
			}

			// Write OP-codes.
			void putOp(byte op) {
				putByte(op);
			}
			void putSOp(byte op, int p1) {
				putByte(op);
				putSNum(p1);
			}
			void putUOp(byte op, nat p1) {
				putByte(op);
				putUNum(p1);
			}
			void putSOp(byte op, int p1, int p2) {
				putByte(op);
				putSNum(p1);
				putSNum(p2);
			}
			void putUOp(byte op, nat p1, nat p2) {
				putByte(op);
				putUNum(p1);
				putUNum(p2);
			}

			// Encode the 'advance_loc' op-code.
			void putAdvance(nat bytes) {
				if (bytes <= 0x3F) {
					putByte(DW_CFA_advance_loc + bytes);
				} else if (bytes <= 0xFF) {
					putByte(DW_CFA_advance_loc1);
					putByte(bytes);
				} else if (bytes <= 0xFFFF) {
					putByte(DW_CFA_advance_loc2);
					putByte(bytes & 0xFF);
					putByte(bytes >> 8);
				} else {
					putByte(DW_CFA_advance_loc4);
					putByte(bytes & 0xFF);
					putByte((bytes & 0xFF00) >> 8);
					putByte((bytes & 0xFF0000) >> 16);
					putByte(bytes >> 24);
				}
			}
		};

		class FDEStream : public DStream {
		public:
			FDEStream(FDE *to, Nat &pos) : DStream(to->data, FDE_DATA), dest(pos) {
				this->pos = dest;
			}

			~FDEStream() {
				dest = pos;
				dbg_assert(!overflow(), L"Increase FDE_DATA to at least " + ::toS(roundUp(pos, nat(sizeof(void *)))) + L"!");
			}

			Nat &dest;
		};


		class FDEIStream {
		public:
			FDEIStream(FDE *from) : data(from->data), len(FDE_DATA), pos(from->firstFree()) {}

			Byte getByte() {
				if (pos < len)
					return data[pos++];
				else
					return 0x0;
			}

			Nat getUNum() {
				Nat out = 0;
				Nat shift = 0;
				while (true) {
					Byte b = getByte();
					if (b & 0x80) {
						out |= (b & 0x7F) << shift;
						shift += 7;
					} else {
						out |= b << shift;
						shift += 7;
						break;
					}
				}
				return out;
			}

			Int getSNum() {
				Nat out = 0;
				Nat shift = 0;
				while (true) {
					Byte b = getByte();
					if (b & 0x80) {
						out |= (b & 0x7F) << shift;
						shift += 7;
					} else {
						out |= b << shift;
						shift += 7;
						break;
					}
				}

				// Check if negative:
				if (out >> (shift - 1)) {
					// Yes, that means we need to add sign bits:
					out |= Nat(0xFFFFFFFF) << shift;
				}

				return Int(out);
			}

			Bool atEnd() const {
				return pos >= len;
			}

		private:
			Byte *data;
			Nat len;
			Nat pos;
		};

	}
}