Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: test/unittests/eh-frame-writer-unittest.cc

Issue 2023503002: Reland Implement .eh_frame writer and disassembler. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@eh-frame-base
Patch Set: SaveRegisterToStack => RegisterSavedToStack. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698