OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/eh-frame.h" | |
6 #include "testing/gtest/include/gtest/gtest.h" | |
7 | |
8 // Test enabled only on supported architectures. | |
9 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM) || \ | |
10 defined(V8_TARGET_ARCH_ARM64) | |
11 | |
12 using namespace v8::internal; | |
13 | |
14 namespace v8 { | |
15 namespace internal { | |
16 | |
17 class EhFrameWriterInternals : public testing::Test { | |
18 protected: | |
19 // Being a non-negative 6bit value, this also serves as its LEB128 encoding. | |
20 static const int kTestRegisterCode = 0; | |
rmcilroy
2016/07/05 10:56:13
I would test a more interesting code than '0', tha
| |
21 | |
22 void WriteULEB128(int value) { writer_.WriteULEB128(value); } | |
23 void WriteSLEB128(int value) { writer_.WriteSLEB128(value); } | |
24 void Align() { writer_.Align(); } | |
25 void WriteByte(byte c) { writer_.WriteByte(c); } | |
26 | |
27 static uint32_t DecodeULEB128(const byte* data, int* decoded_size) { | |
28 return EhFrameWriter::DecodeULEB128(data, decoded_size); | |
29 } | |
30 | |
31 static int32_t DecodeSLEB128(const byte* data, int* decoded_size) { | |
32 return EhFrameWriter::DecodeSLEB128(data, decoded_size); | |
33 } | |
34 | |
35 byte* eh_frame_buffer() { return writer_.eh_frame_buffer_.data(); } | |
36 int eh_frame_offset() const { return writer_.eh_frame_offset(); } | |
37 int cie_size() const { return writer_.cie_size_; } | |
38 int fde_offset() const { return writer_.fde_offset(); } | |
39 int procedure_address_offset() const { | |
40 return writer_.procedure_address_offset(); | |
41 } | |
42 int procedure_size_offset() const { return writer_.procedure_size_offset(); } | |
43 | |
44 EhFrameWriter writer_; | |
45 }; | |
46 | |
47 STATIC_CONST_MEMBER_DEFINITION const int | |
48 EhFrameWriterInternals::kTestRegisterCode; | |
rmcilroy
2016/07/05 10:56:13
Don't think you should need this?
Stefano Sanfilippo
2016/07/05 16:02:14
Also in this case, omitting this bit results in a
| |
49 | |
50 } // namespace internal | |
51 } // namespace v8 | |
52 | |
53 TEST_F(EhFrameWriterInternals, RecordsAlignment) { | |
rmcilroy
2016/07/05 10:56:13
The fixture should be named EhFrameWriterTest
Stefano Sanfilippo
2016/07/05 16:02:14
Done.
| |
54 writer_.Finish(100); | |
55 EXPECT_EQ(4, EhFrameWriter::kTerminatorSize); | |
56 EXPECT_EQ(0, EhFrameHdr::kRecordSize % 4); | |
57 EXPECT_EQ(0, (eh_frame_offset() - EhFrameHdr::kRecordSize - | |
58 EhFrameWriter::kTerminatorSize) % | |
59 8); | |
60 } | |
61 | |
62 TEST_F(EhFrameWriterInternals, Align) { | |
63 // Ensure the buffer size is not already aligned. | |
64 if (eh_frame_offset() % 8 == 0) WriteByte(0); | |
65 Align(); | |
66 EXPECT_EQ(eh_frame_offset() % 8, 0); | |
67 } | |
68 | |
69 TEST_F(EhFrameWriterInternals, AlignNop) { | |
70 Align(); | |
71 int first_size = eh_frame_offset(); | |
72 // This second align should result in a nop | |
73 Align(); | |
74 int second_size = eh_frame_offset(); | |
75 EXPECT_EQ(first_size, second_size); | |
76 } | |
77 | |
78 TEST_F(EhFrameWriterInternals, ProcedureBoundaries) { | |
79 writer_.Finish(100); | |
80 int32_t procedure_offset = | |
81 ReadUnalignedUInt32(eh_frame_buffer() + procedure_address_offset()); | |
82 EXPECT_EQ(-(procedure_address_offset() + RoundUp(100, 8)), procedure_offset); | |
83 uint32_t procedure_size = | |
84 ReadUnalignedUInt32(eh_frame_buffer() + procedure_size_offset()); | |
85 EXPECT_EQ(100, procedure_size); | |
86 } | |
87 | |
88 TEST_F(EhFrameWriterInternals, CIESize) { | |
89 writer_.Finish(42); | |
90 uint32_t encoded_cie_size = ReadUnalignedUInt32(eh_frame_buffer()); | |
91 // The encoded CIE size does not include the size field itself. | |
92 EXPECT_EQ(cie_size(), encoded_cie_size + kInt32Size); | |
93 } | |
94 | |
95 TEST_F(EhFrameWriterInternals, FDESize) { | |
96 writer_.Finish(42); | |
97 uint32_t fde_size = ReadUnalignedUInt32(eh_frame_buffer() + fde_offset()); | |
98 EXPECT_EQ(eh_frame_offset() - EhFrameHdr::kRecordSize - cie_size() - | |
99 EhFrameWriter::kTerminatorSize, | |
100 fde_size); | |
101 } | |
102 | |
103 TEST_F(EhFrameWriterInternals, SetOffset) { | |
104 Register base_register_before_update = writer_.base_register(); | |
105 int start = eh_frame_offset(); | |
106 writer_.SetBaseAddressOffset(64); | |
107 int end = eh_frame_offset(); | |
108 EXPECT_EQ(64, writer_.base_offset()); | |
109 EXPECT_TRUE(base_register_before_update.is(writer_.base_register())); | |
110 EXPECT_EQ(2, end - start); | |
111 EXPECT_EQ(EhFrameWriter::kDefCfaOffset, eh_frame_buffer()[start + 0]); | |
112 EXPECT_EQ(64, eh_frame_buffer()[start + 1]); | |
113 } | |
114 | |
115 TEST_F(EhFrameWriterInternals, IncreaseOffset) { | |
116 int base_offset_before_update = writer_.base_offset(); | |
117 Register base_register_before_update = writer_.base_register(); | |
118 int start = eh_frame_offset(); | |
119 writer_.IncreaseBaseAddressOffset(16); | |
120 int end = eh_frame_offset(); | |
121 EXPECT_EQ(base_offset_before_update + 16, writer_.base_offset()); | |
122 EXPECT_TRUE(base_register_before_update.is(writer_.base_register())); | |
123 EXPECT_EQ(2, end - start); | |
124 EXPECT_EQ(EhFrameWriter::kDefCfaOffset, eh_frame_buffer()[start + 0]); | |
125 EXPECT_EQ(base_offset_before_update + 16, eh_frame_buffer()[start + 1]); | |
126 } | |
127 | |
128 TEST_F(EhFrameWriterInternals, SetRegister) { | |
129 int base_offset_before_update = writer_.base_offset(); | |
130 int start = eh_frame_offset(); | |
131 Register test_register = Register::from_code(kTestRegisterCode); | |
132 writer_.SetBaseAddressRegister(test_register); | |
133 int end = eh_frame_offset(); | |
134 EXPECT_TRUE(writer_.base_register().is(test_register)); | |
135 EXPECT_EQ(base_offset_before_update, writer_.base_offset()); | |
136 EXPECT_EQ(2, end - start); | |
137 EXPECT_EQ(EhFrameWriter::kDefCfaRegister, eh_frame_buffer()[start + 0]); | |
138 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
139 } | |
140 | |
141 TEST_F(EhFrameWriterInternals, SetRegisterAndOffset) { | |
142 int start = eh_frame_offset(); | |
143 Register test_register = Register::from_code(0); | |
144 writer_.SetBaseAddressRegisterAndOffset(test_register, 24); | |
145 int end = eh_frame_offset(); | |
146 EXPECT_EQ(24, writer_.base_offset()); | |
147 EXPECT_TRUE(writer_.base_register().is(test_register)); | |
148 EXPECT_EQ(3, end - start); | |
149 EXPECT_EQ(EhFrameWriter::kDefCfa, eh_frame_buffer()[start + 0]); | |
150 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
151 EXPECT_EQ(24, eh_frame_buffer()[start + 2]); | |
152 } | |
153 | |
154 TEST_F(EhFrameWriterInternals, ULEB128Encoding) { | |
155 int start = eh_frame_offset(); | |
156 WriteULEB128(624485); | |
157 int end = eh_frame_offset(); | |
158 static const byte kExpectedEncoding[] = {0xe5, 0x8e, 0x26}; | |
159 | |
160 EXPECT_EQ(sizeof(kExpectedEncoding), end - start); | |
161 EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]); | |
162 EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]); | |
163 EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]); | |
164 } | |
165 | |
166 TEST_F(EhFrameWriterInternals, SLEB128EncodingPositive) { | |
167 int start = eh_frame_offset(); | |
168 WriteSLEB128(624485); | |
169 int end = eh_frame_offset(); | |
170 static const byte kExpectedEncoding[] = {0xe5, 0x8e, 0x26}; | |
171 | |
172 EXPECT_EQ(sizeof(kExpectedEncoding), end - start); | |
173 EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]); | |
174 EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]); | |
175 EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]); | |
176 } | |
177 | |
178 TEST_F(EhFrameWriterInternals, SLEB128EncodingNegative) { | |
179 int start = eh_frame_offset(); | |
180 WriteSLEB128(-624485); | |
181 int end = eh_frame_offset(); | |
182 static const byte kExpectedEncoding[] = {0x9b, 0xf1, 0x59}; | |
183 | |
184 EXPECT_EQ(sizeof(kExpectedEncoding), end - start); | |
185 EXPECT_EQ(kExpectedEncoding[0], eh_frame_buffer()[start + 0]); | |
186 EXPECT_EQ(kExpectedEncoding[1], eh_frame_buffer()[start + 1]); | |
187 EXPECT_EQ(kExpectedEncoding[2], eh_frame_buffer()[start + 2]); | |
188 } | |
189 | |
190 TEST_F(EhFrameWriterInternals, ULEB128Decoding) { | |
191 static const byte kEncoded[] = {0xe5, 0x8e, 0x26}; | |
192 int size = 0; | |
193 uint32_t value = DecodeULEB128(kEncoded, &size); | |
194 EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size); | |
195 EXPECT_EQ(624485, value); | |
196 } | |
197 | |
198 TEST_F(EhFrameWriterInternals, SLEB128DecodingPositive) { | |
199 static const byte kEncoded[] = {0xe5, 0x8e, 0x26}; | |
200 int size = 0; | |
201 int32_t value = DecodeSLEB128(kEncoded, &size); | |
202 EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size); | |
203 EXPECT_EQ(624485, value); | |
204 } | |
205 | |
206 TEST_F(EhFrameWriterInternals, SLEB128DecodingNegative) { | |
207 static const byte kEncoded[] = {0x9b, 0xf1, 0x59}; | |
208 int size = 0; | |
209 int32_t value = DecodeSLEB128(kEncoded, &size); | |
210 EXPECT_EQ(static_cast<int>(sizeof(kEncoded)), size); | |
211 EXPECT_EQ(-624485, value); | |
212 } | |
213 | |
214 TEST_F(EhFrameWriterInternals, PcOffsetEncoding6bit) { | |
215 EXPECT_EQ(0, writer_.last_pc_offset()); | |
216 int start = eh_frame_offset(); | |
217 writer_.AdvanceLocation(42); | |
218 int end = eh_frame_offset(); | |
219 EXPECT_EQ(1, end - start); | |
220 EXPECT_EQ((1 << 6) | 42, eh_frame_buffer()[start + 0]); | |
221 EXPECT_EQ(42, writer_.last_pc_offset()); | |
222 } | |
223 | |
224 TEST_F(EhFrameWriterInternals, PcOffsetEncoding6bitDelta) { | |
225 writer_.AdvanceLocation(42); | |
226 int start = eh_frame_offset(); | |
227 writer_.AdvanceLocation(65); | |
228 int end = eh_frame_offset(); | |
229 EXPECT_EQ(1, end - start); | |
230 EXPECT_EQ((1 << 6) | (65 - 42), eh_frame_buffer()[start + 0]); | |
231 EXPECT_EQ(65, writer_.last_pc_offset()); | |
232 } | |
233 | |
234 TEST_F(EhFrameWriterInternals, PcOffsetEncoding8bit) { | |
235 EXPECT_EQ(0, writer_.last_pc_offset()); | |
236 int start = eh_frame_offset(); | |
237 writer_.AdvanceLocation(0x42); | |
238 int end = eh_frame_offset(); | |
239 EXPECT_EQ(1 + sizeof(uint8_t), end - start); | |
240 EXPECT_EQ(EhFrameWriter::kAdvanceLoc1, eh_frame_buffer()[start + 0]); | |
241 EXPECT_EQ(0x42, eh_frame_buffer()[start + 1]); | |
242 EXPECT_EQ(0x42, writer_.last_pc_offset()); | |
243 } | |
244 | |
245 TEST_F(EhFrameWriterInternals, PcOffsetEncoding8bitDelta) { | |
246 writer_.AdvanceLocation(0x10); | |
247 int start = eh_frame_offset(); | |
248 writer_.AdvanceLocation(0x70); | |
249 int end = eh_frame_offset(); | |
250 EXPECT_EQ(1 + sizeof(uint8_t), end - start); | |
251 EXPECT_EQ(0x70 - 0x10, eh_frame_buffer()[start + 1]); | |
252 EXPECT_EQ(0x70, writer_.last_pc_offset()); | |
253 } | |
254 | |
255 TEST_F(EhFrameWriterInternals, PcOffsetEncoding16bit) { | |
256 EXPECT_EQ(0, writer_.last_pc_offset()); | |
257 int start = eh_frame_offset(); | |
258 writer_.AdvanceLocation(42 + kMaxUInt8); | |
259 int end = eh_frame_offset(); | |
260 EXPECT_EQ(1 + sizeof(uint16_t), end - start); | |
261 EXPECT_EQ(EhFrameWriter::kAdvanceLoc2, eh_frame_buffer()[start + 0]); | |
262 EXPECT_EQ(42 + kMaxUInt8, ReadUnalignedUInt16(eh_frame_buffer() + start + 1)); | |
263 EXPECT_EQ(42 + kMaxUInt8, writer_.last_pc_offset()); | |
264 } | |
265 | |
266 TEST_F(EhFrameWriterInternals, PcOffsetEncoding16bitDelta) { | |
267 writer_.AdvanceLocation(41); | |
268 int start = eh_frame_offset(); | |
269 writer_.AdvanceLocation(62 + kMaxUInt8); | |
270 int end = eh_frame_offset(); | |
271 EXPECT_EQ(1 + sizeof(uint16_t), end - start); | |
272 EXPECT_EQ(62 + kMaxUInt8 - 41, | |
273 ReadUnalignedUInt16(eh_frame_buffer() + start + 1)); | |
274 EXPECT_EQ(62 + kMaxUInt8, writer_.last_pc_offset()); | |
275 } | |
276 | |
277 TEST_F(EhFrameWriterInternals, PcOffsetEncoding32bit) { | |
278 EXPECT_EQ(0, writer_.last_pc_offset()); | |
279 int start = eh_frame_offset(); | |
280 writer_.AdvanceLocation(42 + kMaxUInt16); | |
281 int end = eh_frame_offset(); | |
282 EXPECT_EQ(1 + sizeof(uint32_t), end - start); | |
283 EXPECT_EQ(EhFrameWriter::kAdvanceLoc4, eh_frame_buffer()[start + 0]); | |
284 EXPECT_EQ(42 + kMaxUInt16, | |
285 ReadUnalignedUInt32(eh_frame_buffer() + start + 1)); | |
286 EXPECT_EQ(42 + kMaxUInt16, writer_.last_pc_offset()); | |
287 } | |
288 | |
289 TEST_F(EhFrameWriterInternals, PcOffsetEncoding32bitDelta) { | |
290 writer_.AdvanceLocation(41); | |
291 int start = eh_frame_offset(); | |
292 writer_.AdvanceLocation(62 + kMaxUInt16); | |
293 int end = eh_frame_offset(); | |
294 EXPECT_EQ(1 + sizeof(uint32_t), end - start); | |
295 EXPECT_EQ(62 + kMaxUInt16 - 41, | |
296 ReadUnalignedUInt32(eh_frame_buffer() + start + 1)); | |
297 EXPECT_EQ(62 + kMaxUInt16, writer_.last_pc_offset()); | |
298 } | |
299 | |
300 TEST_F(EhFrameWriterInternals, GetEhFrame) { | |
301 writer_.Finish(42); | |
302 CodeDesc code_desc; | |
303 writer_.GetEhFrame(&code_desc); | |
304 EXPECT_EQ(eh_frame_offset(), code_desc.unwinding_info_size); | |
305 EXPECT_EQ(0, memcmp(eh_frame_buffer(), code_desc.unwinding_info, | |
306 eh_frame_offset())); | |
307 } | |
308 | |
309 TEST_F(EhFrameWriterInternals, SaveRegisterPositiveOffset) { | |
310 int start = eh_frame_offset(); | |
311 Register test_register = Register::from_code(kTestRegisterCode); | |
312 writer_.RegisterSavedToStack(test_register, 16); | |
313 int end = eh_frame_offset(); | |
314 EXPECT_EQ(2, end - start); | |
315 EXPECT_EQ((2 << 6) | kTestRegisterCode, eh_frame_buffer()[start + 0]); | |
316 EXPECT_EQ(16 / std::abs(EhFrameWriter::kDataAlignmentFactor), | |
317 eh_frame_buffer()[start + 1]); | |
318 } | |
319 | |
320 TEST_F(EhFrameWriterInternals, SaveRegisterNegativeOffset) { | |
321 int start = eh_frame_offset(); | |
322 Register test_register = Register::from_code(kTestRegisterCode); | |
323 writer_.RegisterSavedToStack(test_register, -16); | |
324 int end = eh_frame_offset(); | |
325 EXPECT_EQ(3, end - start); | |
326 EXPECT_EQ(EhFrameWriter::kOffsetExtendedSf, eh_frame_buffer()[start + 0]); | |
327 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
328 if (EhFrameWriter::kDataAlignmentFactor == -4) { | |
329 EXPECT_EQ(0x7c, eh_frame_buffer()[start + 2]); // -4 SLEB128 encoded. | |
330 } else if (EhFrameWriter::kDataAlignmentFactor == -8) { | |
331 EXPECT_EQ(0x7e, eh_frame_buffer()[start + 2]); // -2 SLEB128 encoded. | |
332 } else { | |
333 EXPECT_TRUE(false && "Data alignment not handled in test."); | |
334 } | |
335 } | |
336 | |
337 TEST_F(EhFrameWriterInternals, SaveRegisterToTop) { | |
338 int base_offset_before_call = writer_.base_offset(); | |
339 int start = eh_frame_offset(); | |
340 Register test_register = Register::from_code(kTestRegisterCode); | |
341 writer_.RegisterSavedToStack(test_register); | |
342 int end = eh_frame_offset(); | |
343 EXPECT_EQ(base_offset_before_call, writer_.base_offset()); | |
344 EXPECT_GE(base_offset_before_call, 0); | |
345 EXPECT_EQ(2, end - start); | |
346 EXPECT_EQ((2 << 6) | kTestRegisterCode, eh_frame_buffer()[start + 0]); | |
347 EXPECT_EQ( | |
348 base_offset_before_call / std::abs(EhFrameWriter::kDataAlignmentFactor), | |
349 eh_frame_buffer()[start + 1]); | |
350 } | |
351 | |
352 TEST_F(EhFrameWriterInternals, RegisterIsValid) { | |
353 Register test_register = Register::from_code(kTestRegisterCode); | |
354 int start = eh_frame_offset(); | |
355 writer_.RegisterIsValid(test_register); | |
356 int end = eh_frame_offset(); | |
357 EXPECT_EQ(2, end - start); | |
358 EXPECT_EQ(EhFrameWriter::kSameValue, eh_frame_buffer()[start + 0]); | |
359 EXPECT_EQ(kTestRegisterCode, eh_frame_buffer()[start + 1]); | |
360 } | |
361 | |
362 #endif | |
OLD | NEW |