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

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: Rebase on master. 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
« no previous file with comments | « test/unittests/eh-frame-iterator-unittest.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "test/unittests/test-utils.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 {
15
16 class EhFrameWriterTest : public TestWithZone {
17 protected:
18 // Being a 7bit positive integer, this also serves as its ULEB128 encoding.
19 static const int kTestRegisterCode = 0;
20
21 static EhFrameIterator MakeIterator(EhFrameWriter* writer) {
22 CodeDesc desc;
23 writer->GetEhFrame(&desc);
24 DCHECK_GT(desc.unwinding_info_size, 0);
25 return EhFrameIterator(desc.unwinding_info,
26 desc.unwinding_info + desc.unwinding_info_size);
27 }
28 };
29
30 const int EhFrameWriterTest::kTestRegisterCode;
31
32 } // namespace
33
34 TEST_F(EhFrameWriterTest, Alignment) {
35 EhFrameWriter writer(zone());
36 writer.Initialize();
37 writer.AdvanceLocation(42 * EhFrameConstants::kCodeAlignmentFactor);
38 writer.Finish(100);
39
40 EhFrameIterator iterator = MakeIterator(&writer);
41 ASSERT_EQ(0, EhFrameConstants::kEhFrameHdrSize % 4);
42 ASSERT_EQ(0, EhFrameConstants::kEhFrameTerminatorSize % 4);
43 EXPECT_EQ(0, (iterator.GetBufferSize() - EhFrameConstants::kEhFrameHdrSize -
44 EhFrameConstants::kEhFrameTerminatorSize) %
45 8);
46 }
47
48 TEST_F(EhFrameWriterTest, FDEHeader) {
49 static const int kProcedureSize = 0x5678abcd;
50
51 EhFrameWriter writer(zone());
52 writer.Initialize();
53 writer.Finish(kProcedureSize);
54
55 EhFrameIterator iterator = MakeIterator(&writer);
56 int cie_size = iterator.GetNextUInt32();
57 iterator.Skip(cie_size);
58
59 int fde_size = iterator.GetNextUInt32();
60 EXPECT_EQ(iterator.GetBufferSize(),
61 fde_size + cie_size + EhFrameConstants::kEhFrameTerminatorSize +
62 EhFrameConstants::kEhFrameHdrSize + 2 * kInt32Size);
63
64 int backwards_offset_to_cie_offset = iterator.GetCurrentOffset();
65 int backwards_offset_to_cie = iterator.GetNextUInt32();
66 EXPECT_EQ(backwards_offset_to_cie_offset, backwards_offset_to_cie);
67
68 int procedure_address_offset = iterator.GetCurrentOffset();
69 int procedure_address = iterator.GetNextUInt32();
70 EXPECT_EQ(-(procedure_address_offset + RoundUp(kProcedureSize, 8)),
71 procedure_address);
72
73 int procedure_size = iterator.GetNextUInt32();
74 EXPECT_EQ(kProcedureSize, procedure_size);
75 }
76
77 TEST_F(EhFrameWriterTest, SetOffset) {
78 static const int kOffset = 0x0badc0de;
79
80 EhFrameWriter writer(zone());
81 writer.Initialize();
82 writer.SetBaseAddressOffset(kOffset);
83 writer.Finish(100);
84
85 EhFrameIterator iterator = MakeIterator(&writer);
86 iterator.SkipToFdeDirectives();
87
88 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kDefCfaOffset,
89 iterator.GetNextOpcode());
90 EXPECT_EQ(kOffset, iterator.GetNextULeb128());
91 }
92
93 TEST_F(EhFrameWriterTest, IncreaseOffset) {
94 static const int kFirstOffset = 121;
95 static const int kSecondOffset = 16;
96
97 EhFrameWriter writer(zone());
98 writer.Initialize();
99 writer.SetBaseAddressOffset(kFirstOffset);
100 writer.IncreaseBaseAddressOffset(kSecondOffset);
101 writer.Finish(100);
102
103 EhFrameIterator iterator = MakeIterator(&writer);
104 iterator.SkipToFdeDirectives();
105
106 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kDefCfaOffset,
107 iterator.GetNextOpcode());
108 EXPECT_EQ(kFirstOffset, iterator.GetNextULeb128());
109
110 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kDefCfaOffset,
111 iterator.GetNextOpcode());
112 EXPECT_EQ(kFirstOffset + kSecondOffset, iterator.GetNextULeb128());
113 }
114
115 TEST_F(EhFrameWriterTest, SetRegister) {
116 Register test_register = Register::from_code(kTestRegisterCode);
117
118 EhFrameWriter writer(zone());
119 writer.Initialize();
120 writer.SetBaseAddressRegister(test_register);
121 writer.Finish(100);
122
123 EhFrameIterator iterator = MakeIterator(&writer);
124 iterator.SkipToFdeDirectives();
125
126 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kDefCfaRegister,
127 iterator.GetNextOpcode());
128 EXPECT_EQ(kTestRegisterCode, iterator.GetNextULeb128());
129 }
130
131 TEST_F(EhFrameWriterTest, SetRegisterAndOffset) {
132 Register test_register = Register::from_code(kTestRegisterCode);
133 static const int kOffset = 0x0badc0de;
134
135 EhFrameWriter writer(zone());
136 writer.Initialize();
137 writer.SetBaseAddressRegisterAndOffset(test_register, kOffset);
138 writer.Finish(100);
139
140 EhFrameIterator iterator = MakeIterator(&writer);
141 iterator.SkipToFdeDirectives();
142
143 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kDefCfa, iterator.GetNextOpcode());
144 EXPECT_EQ(kTestRegisterCode, iterator.GetNextULeb128());
145 EXPECT_EQ(kOffset, iterator.GetNextULeb128());
146 }
147
148 TEST_F(EhFrameWriterTest, PcOffsetEncoding6bit) {
149 static const int kOffset = 42;
150
151 EhFrameWriter writer(zone());
152 writer.Initialize();
153 writer.AdvanceLocation(kOffset * EhFrameConstants::kCodeAlignmentFactor);
154 writer.Finish(100);
155
156 EhFrameIterator iterator = MakeIterator(&writer);
157 iterator.SkipToFdeDirectives();
158
159 EXPECT_EQ((1 << 6) | kOffset, iterator.GetNextByte());
160 }
161
162 TEST_F(EhFrameWriterTest, PcOffsetEncoding6bitDelta) {
163 static const int kFirstOffset = 42;
164 static const int kSecondOffset = 62;
165
166 EhFrameWriter writer(zone());
167 writer.Initialize();
168 writer.AdvanceLocation(kFirstOffset * EhFrameConstants::kCodeAlignmentFactor);
169 writer.AdvanceLocation(kSecondOffset *
170 EhFrameConstants::kCodeAlignmentFactor);
171 writer.Finish(100);
172
173 EhFrameIterator iterator = MakeIterator(&writer);
174 iterator.SkipToFdeDirectives();
175
176 EXPECT_EQ((1 << 6) | kFirstOffset, iterator.GetNextByte());
177 EXPECT_EQ((1 << 6) | (kSecondOffset - kFirstOffset), iterator.GetNextByte());
178 }
179
180 TEST_F(EhFrameWriterTest, PcOffsetEncoding8bit) {
181 static const int kOffset = 0x42;
182
183 EhFrameWriter writer(zone());
184 writer.Initialize();
185 writer.AdvanceLocation(kOffset * EhFrameConstants::kCodeAlignmentFactor);
186 writer.Finish(100);
187
188 EhFrameIterator iterator = MakeIterator(&writer);
189 iterator.SkipToFdeDirectives();
190
191 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
192 iterator.GetNextOpcode());
193 EXPECT_EQ(kOffset, iterator.GetNextByte());
194 }
195
196 TEST_F(EhFrameWriterTest, PcOffsetEncoding8bitDelta) {
197 static const int kFirstOffset = 0x10;
198 static const int kSecondOffset = 0x70;
199 static const int kThirdOffset = 0xb5;
200
201 EhFrameWriter writer(zone());
202 writer.Initialize();
203 writer.AdvanceLocation(kFirstOffset * EhFrameConstants::kCodeAlignmentFactor);
204 writer.AdvanceLocation(kSecondOffset *
205 EhFrameConstants::kCodeAlignmentFactor);
206 writer.AdvanceLocation(kThirdOffset * EhFrameConstants::kCodeAlignmentFactor);
207 writer.Finish(100);
208
209 EhFrameIterator iterator = MakeIterator(&writer);
210 iterator.SkipToFdeDirectives();
211
212 EXPECT_EQ((1 << 6) | kFirstOffset, iterator.GetNextByte());
213
214 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
215 iterator.GetNextOpcode());
216 EXPECT_EQ(kSecondOffset - kFirstOffset, iterator.GetNextByte());
217
218 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
219 iterator.GetNextOpcode());
220 EXPECT_EQ(kThirdOffset - kSecondOffset, iterator.GetNextByte());
221 }
222
223 TEST_F(EhFrameWriterTest, PcOffsetEncoding16bit) {
224 static const int kOffset = kMaxUInt8 + 42;
225 ASSERT_LT(kOffset, kMaxUInt16);
226
227 EhFrameWriter writer(zone());
228 writer.Initialize();
229 writer.AdvanceLocation(kOffset * EhFrameConstants::kCodeAlignmentFactor);
230 writer.Finish(100);
231
232 EhFrameIterator iterator = MakeIterator(&writer);
233 iterator.SkipToFdeDirectives();
234
235 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc2,
236 iterator.GetNextOpcode());
237 EXPECT_EQ(kOffset, iterator.GetNextUInt16());
238 }
239
240 TEST_F(EhFrameWriterTest, PcOffsetEncoding16bitDelta) {
241 static const int kFirstOffset = 0x41;
242 static const int kSecondOffset = kMaxUInt8 + 0x42;
243
244 EhFrameWriter writer(zone());
245 writer.Initialize();
246 writer.AdvanceLocation(kFirstOffset * EhFrameConstants::kCodeAlignmentFactor);
247 writer.AdvanceLocation(kSecondOffset *
248 EhFrameConstants::kCodeAlignmentFactor);
249 writer.Finish(100);
250
251 EhFrameIterator iterator = MakeIterator(&writer);
252 iterator.SkipToFdeDirectives();
253
254 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
255 iterator.GetNextOpcode());
256 EXPECT_EQ(kFirstOffset, iterator.GetNextByte());
257
258 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc2,
259 iterator.GetNextOpcode());
260 EXPECT_EQ(kSecondOffset - kFirstOffset, iterator.GetNextUInt16());
261 }
262
263 TEST_F(EhFrameWriterTest, PcOffsetEncoding32bit) {
264 static const int kOffset = kMaxUInt16 + 42;
265
266 EhFrameWriter writer(zone());
267 writer.Initialize();
268 writer.AdvanceLocation(kOffset * EhFrameConstants::kCodeAlignmentFactor);
269 writer.Finish(100);
270
271 EhFrameIterator iterator = MakeIterator(&writer);
272 iterator.SkipToFdeDirectives();
273
274 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc4,
275 iterator.GetNextOpcode());
276 EXPECT_EQ(kOffset, iterator.GetNextUInt32());
277 }
278
279 TEST_F(EhFrameWriterTest, PcOffsetEncoding32bitDelta) {
280 static const int kFirstOffset = kMaxUInt16 + 0x42;
281 static const int kSecondOffset = kMaxUInt16 + 0x67;
282
283 EhFrameWriter writer(zone());
284 writer.Initialize();
285 writer.AdvanceLocation(kFirstOffset * EhFrameConstants::kCodeAlignmentFactor);
286 writer.AdvanceLocation(kSecondOffset *
287 EhFrameConstants::kCodeAlignmentFactor);
288 writer.Finish(100);
289
290 EhFrameIterator iterator = MakeIterator(&writer);
291 iterator.SkipToFdeDirectives();
292
293 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc4,
294 iterator.GetNextOpcode());
295 EXPECT_EQ(kFirstOffset, iterator.GetNextUInt32());
296
297 EXPECT_EQ((1 << 6) | (kSecondOffset - kFirstOffset), iterator.GetNextByte());
298 }
299
300 TEST_F(EhFrameWriterTest, SaveRegisterUnsignedOffset) {
301 Register test_register = Register::from_code(kTestRegisterCode);
302 static const int kOffset =
303 EhFrameConstants::kDataAlignmentFactor > 0 ? 12344 : -12344;
304
305 EhFrameWriter writer(zone());
306 writer.Initialize();
307 writer.RecordRegisterSavedToStack(test_register, kOffset);
308 writer.Finish(100);
309
310 EhFrameIterator iterator = MakeIterator(&writer);
311 iterator.SkipToFdeDirectives();
312
313 EXPECT_EQ((2 << 6) | kTestRegisterCode, iterator.GetNextByte());
314 EXPECT_EQ(kOffset / EhFrameConstants::kDataAlignmentFactor,
315 iterator.GetNextULeb128());
316 }
317
318 TEST_F(EhFrameWriterTest, SaveRegisterSignedOffset) {
319 Register test_register = Register::from_code(kTestRegisterCode);
320 static const int kOffset =
321 EhFrameConstants::kDataAlignmentFactor < 0 ? 12344 : -12344;
322
323 ASSERT_EQ(kOffset % EhFrameConstants::kDataAlignmentFactor, 0);
324
325 EhFrameWriter writer(zone());
326 writer.Initialize();
327 writer.RecordRegisterSavedToStack(test_register, kOffset);
328 writer.Finish(100);
329
330 EhFrameIterator iterator = MakeIterator(&writer);
331 iterator.SkipToFdeDirectives();
332
333 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kOffsetExtendedSf,
334 iterator.GetNextOpcode());
335 EXPECT_EQ(kTestRegisterCode, iterator.GetNextULeb128());
336 EXPECT_EQ(kOffset / EhFrameConstants::kDataAlignmentFactor,
337 iterator.GetNextSLeb128());
338 }
339
340 TEST_F(EhFrameWriterTest, RegisterNotModified) {
341 Register test_register = Register::from_code(kTestRegisterCode);
342
343 EhFrameWriter writer(zone());
344 writer.Initialize();
345 writer.RecordRegisterNotModified(test_register);
346 writer.Finish(100);
347
348 EhFrameIterator iterator = MakeIterator(&writer);
349 iterator.SkipToFdeDirectives();
350
351 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kSameValue,
352 iterator.GetNextOpcode());
353 EXPECT_EQ(kTestRegisterCode, iterator.GetNextULeb128());
354 }
355
356 TEST_F(EhFrameWriterTest, RegisterFollowsInitialRule) {
357 Register test_register = Register::from_code(kTestRegisterCode);
358
359 EhFrameWriter writer(zone());
360 writer.Initialize();
361 writer.RecordRegisterFollowsInitialRule(test_register);
362 writer.Finish(100);
363
364 EhFrameIterator iterator = MakeIterator(&writer);
365 iterator.SkipToFdeDirectives();
366
367 EXPECT_EQ((3 << 6) | kTestRegisterCode, iterator.GetNextByte());
368 }
369
370 TEST_F(EhFrameWriterTest, EhFrameHdrLayout) {
371 static const int kCodeSize = 10;
372 static const int kPaddingSize = 6;
373
374 EhFrameWriter writer(zone());
375 writer.Initialize();
376 writer.Finish(kCodeSize);
377
378 EhFrameIterator iterator = MakeIterator(&writer);
379
380 // Skip the .eh_frame.
381
382 int encoded_cie_size = iterator.GetNextUInt32();
383 iterator.Skip(encoded_cie_size);
384 int cie_size = encoded_cie_size + kInt32Size;
385
386 int encoded_fde_size = iterator.GetNextUInt32();
387 iterator.Skip(encoded_fde_size);
388 int fde_size = encoded_fde_size + kInt32Size;
389
390 iterator.Skip(EhFrameConstants::kEhFrameTerminatorSize);
391
392 int eh_frame_size =
393 cie_size + fde_size + EhFrameConstants::kEhFrameTerminatorSize;
394
395 //
396 // Plugging some numbers in the DSO layout shown in eh-frame.cc:
397 //
398 // | ... |
399 // +---------------+ <-- (E) ---------
400 // | | ^
401 // | Instructions | 10 bytes | .text
402 // | | v
403 // +---------------+ <----------------
404 // |///////////////|
405 // |////Padding////| 6 bytes
406 // |///////////////|
407 // +---------------+ <---(D)----------
408 // | | ^
409 // | CIE | cie_size bytes* |
410 // | | |
411 // +---------------+ <-- (C) |
412 // | | | .eh_frame
413 // | FDE | fde_size bytes |
414 // | | |
415 // +---------------+ |
416 // | terminator | 4 bytes v
417 // +---------------+ <-- (B) ---------
418 // | version | ^
419 // +---------------+ 4 bytes |
420 // | encoding | |
421 // | specifiers | |
422 // +---------------+ <---(A) | .eh_frame_hdr
423 // | offset to | |
424 // | .eh_frame | |
425 // +---------------+ |
426 // | ... | ...
427 //
428 // (*) the size of the CIE is platform dependent.
429 //
430
431 int eh_frame_hdr_version = iterator.GetNextByte();
432 EXPECT_EQ(EhFrameConstants::kEhFrameHdrVersion, eh_frame_hdr_version);
433
434 // .eh_frame pointer encoding specifier.
435 EXPECT_EQ(EhFrameConstants::kSData4 | EhFrameConstants::kPcRel,
436 iterator.GetNextByte());
437
438 // Lookup table size encoding specifier.
439 EXPECT_EQ(EhFrameConstants::kUData4, iterator.GetNextByte());
440
441 // Lookup table pointers encoding specifier.
442 EXPECT_EQ(EhFrameConstants::kSData4 | EhFrameConstants::kDataRel,
443 iterator.GetNextByte());
444
445 // A -> D
446 int offset_to_eh_frame = iterator.GetNextUInt32();
447 EXPECT_EQ(-(EhFrameConstants::kFdeVersionSize +
448 EhFrameConstants::kFdeEncodingSpecifiersSize + eh_frame_size),
449 offset_to_eh_frame);
450
451 int lut_entries = iterator.GetNextUInt32();
452 EXPECT_EQ(1, lut_entries);
453
454 // B -> E
455 int offset_to_procedure = iterator.GetNextUInt32();
456 EXPECT_EQ(-(eh_frame_size + kPaddingSize + kCodeSize), offset_to_procedure);
457
458 // B -> C
459 int offset_to_fde = iterator.GetNextUInt32();
460 EXPECT_EQ(-(fde_size + EhFrameConstants::kEhFrameTerminatorSize),
461 offset_to_fde);
462 }
463
464 #endif
OLDNEW
« no previous file with comments | « test/unittests/eh-frame-iterator-unittest.cc ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698