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

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: LUT => lookup table (for clarity). 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 "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 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriterTest::kTestRegisterCode;
31
32 } // namespace
33
34 TEST_F(EhFrameWriterTest, Alignment) {
35 EhFrameWriter writer(zone());
36 writer.Initialize();
37 writer.AdvanceLocation(42);
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);
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);
169 writer.AdvanceLocation(kSecondOffset);
170 writer.Finish(100);
171
172 EhFrameIterator iterator = MakeIterator(&writer);
173 iterator.SkipToFDEDirectives();
174
175 EXPECT_EQ((1 << 6) | kFirstOffset, iterator.GetNextByte());
176 EXPECT_EQ((1 << 6) | (kSecondOffset - kFirstOffset), iterator.GetNextByte());
177 }
178
179 TEST_F(EhFrameWriterTest, PcOffsetEncoding8bit) {
180 static const int kOffset = 0x42;
181
182 EhFrameWriter writer(zone());
183 writer.Initialize();
184 writer.AdvanceLocation(kOffset);
185 writer.Finish(100);
186
187 EhFrameIterator iterator = MakeIterator(&writer);
188 iterator.SkipToFDEDirectives();
189
190 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
191 iterator.GetNextOpcode());
192 EXPECT_EQ(kOffset, iterator.GetNextByte());
193 }
194
195 TEST_F(EhFrameWriterTest, PcOffsetEncoding8bitDelta) {
196 static const int kFirstOffset = 0x10;
197 static const int kSecondOffset = 0x70;
198 static const int kThirdOffset = 0xb5;
199
200 EhFrameWriter writer(zone());
201 writer.Initialize();
202 writer.AdvanceLocation(kFirstOffset);
203 writer.AdvanceLocation(kSecondOffset);
204 writer.AdvanceLocation(kThirdOffset);
205 writer.Finish(100);
206
207 EhFrameIterator iterator = MakeIterator(&writer);
208 iterator.SkipToFDEDirectives();
209
210 EXPECT_EQ((1 << 6) | kFirstOffset, iterator.GetNextByte());
211
212 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
213 iterator.GetNextOpcode());
214 EXPECT_EQ(kSecondOffset - kFirstOffset, iterator.GetNextByte());
215
216 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
217 iterator.GetNextOpcode());
218 EXPECT_EQ(kThirdOffset - kSecondOffset, iterator.GetNextByte());
219 }
220
221 TEST_F(EhFrameWriterTest, PcOffsetEncoding16bit) {
222 static const int kOffset = kMaxUInt8 + 42;
223 ASSERT_LT(kOffset, kMaxUInt16);
224
225 EhFrameWriter writer(zone());
226 writer.Initialize();
227 writer.AdvanceLocation(kOffset);
228 writer.Finish(100);
229
230 EhFrameIterator iterator = MakeIterator(&writer);
231 iterator.SkipToFDEDirectives();
232
233 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc2,
234 iterator.GetNextOpcode());
235 EXPECT_EQ(kOffset, iterator.GetNextUInt16());
236 }
237
238 TEST_F(EhFrameWriterTest, PcOffsetEncoding16bitDelta) {
239 static const int kFirstOffset = 0x41;
240 static const int kSecondOffset = kMaxUInt8 + 0x42;
241
242 EhFrameWriter writer(zone());
243 writer.Initialize();
244 writer.AdvanceLocation(kFirstOffset);
245 writer.AdvanceLocation(kSecondOffset);
246 writer.Finish(100);
247
248 EhFrameIterator iterator = MakeIterator(&writer);
249 iterator.SkipToFDEDirectives();
250
251 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1,
252 iterator.GetNextOpcode());
253 EXPECT_EQ(kFirstOffset, iterator.GetNextByte());
254
255 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc2,
256 iterator.GetNextOpcode());
257 EXPECT_EQ(kSecondOffset - kFirstOffset, iterator.GetNextUInt16());
258 }
259
260 TEST_F(EhFrameWriterTest, PcOffsetEncoding32bit) {
261 static const int kOffset = kMaxUInt16 + 42;
262
263 EhFrameWriter writer(zone());
264 writer.Initialize();
265 writer.AdvanceLocation(kOffset);
266 writer.Finish(100);
267
268 EhFrameIterator iterator = MakeIterator(&writer);
269 iterator.SkipToFDEDirectives();
270
271 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc4,
272 iterator.GetNextOpcode());
273 EXPECT_EQ(kOffset, iterator.GetNextUInt32());
274 }
275
276 TEST_F(EhFrameWriterTest, PcOffsetEncoding32bitDelta) {
277 static const int kFirstOffset = kMaxUInt16 + 0x42;
278 static const int kSecondOffset = kMaxUInt16 + 0x67;
279
280 EhFrameWriter writer(zone());
281 writer.Initialize();
282 writer.AdvanceLocation(kFirstOffset);
283 writer.AdvanceLocation(kSecondOffset);
284 writer.Finish(100);
285
286 EhFrameIterator iterator = MakeIterator(&writer);
287 iterator.SkipToFDEDirectives();
288
289 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kAdvanceLoc4,
290 iterator.GetNextOpcode());
291 EXPECT_EQ(kFirstOffset, iterator.GetNextUInt32());
292
293 EXPECT_EQ((1 << 6) | (kSecondOffset - kFirstOffset), iterator.GetNextByte());
294 }
295
296 TEST_F(EhFrameWriterTest, SaveRegisterUnsignedOffset) {
297 Register test_register = Register::from_code(kTestRegisterCode);
298 static const int kOffset =
299 EhFrameConstants::kDataAlignmentFactor > 0 ? 12344 : -12344;
300
301 EhFrameWriter writer(zone());
302 writer.Initialize();
303 writer.RecordRegisterSavedToStack(test_register, kOffset);
304 writer.Finish(100);
305
306 EhFrameIterator iterator = MakeIterator(&writer);
307 iterator.SkipToFDEDirectives();
308
309 EXPECT_EQ((2 << 6) | kTestRegisterCode, iterator.GetNextByte());
310 EXPECT_EQ(kOffset / EhFrameConstants::kDataAlignmentFactor,
311 iterator.GetNextULEB128());
312 }
313
314 TEST_F(EhFrameWriterTest, SaveRegisterSignedOffset) {
315 Register test_register = Register::from_code(kTestRegisterCode);
316 static const int kOffset =
317 EhFrameConstants::kDataAlignmentFactor < 0 ? 12344 : -12344;
318
319 ASSERT_EQ(kOffset % EhFrameConstants::kDataAlignmentFactor, 0);
320
321 EhFrameWriter writer(zone());
322 writer.Initialize();
323 writer.RecordRegisterSavedToStack(test_register, kOffset);
324 writer.Finish(100);
325
326 EhFrameIterator iterator = MakeIterator(&writer);
327 iterator.SkipToFDEDirectives();
328
329 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kOffsetExtendedSf,
330 iterator.GetNextOpcode());
331 EXPECT_EQ(kTestRegisterCode, iterator.GetNextULEB128());
332 EXPECT_EQ(kOffset / EhFrameConstants::kDataAlignmentFactor,
333 iterator.GetNextSLEB128());
334 }
335
336 TEST_F(EhFrameWriterTest, RegisterNotModified) {
337 Register test_register = Register::from_code(kTestRegisterCode);
338
339 EhFrameWriter writer(zone());
340 writer.Initialize();
341 writer.RecordRegisterNotModified(test_register);
342 writer.Finish(100);
343
344 EhFrameIterator iterator = MakeIterator(&writer);
345 iterator.SkipToFDEDirectives();
346
347 EXPECT_EQ(EhFrameConstants::DwarfOpcodes::kSameValue,
348 iterator.GetNextOpcode());
349 EXPECT_EQ(kTestRegisterCode, iterator.GetNextULEB128());
350 }
351
352 TEST_F(EhFrameWriterTest, RegisterFollowsInitialRule) {
353 Register test_register = Register::from_code(kTestRegisterCode);
354
355 EhFrameWriter writer(zone());
356 writer.Initialize();
357 writer.RecordRegisterFollowsInitialRule(test_register);
358 writer.Finish(100);
359
360 EhFrameIterator iterator = MakeIterator(&writer);
361 iterator.SkipToFDEDirectives();
362
363 EXPECT_EQ((3 << 6) | kTestRegisterCode, iterator.GetNextByte());
364 }
365
366 TEST_F(EhFrameWriterTest, EhFrameHdrLayout) {
367 static const int kCodeSize = 10;
368 static const int kPaddingSize = 6;
369
370 EhFrameWriter writer(zone());
371 writer.Initialize();
372 writer.Finish(kCodeSize);
373
374 EhFrameIterator iterator = MakeIterator(&writer);
375
376 // Skip the .eh_frame.
377
378 int encoded_cie_size = iterator.GetNextUInt32();
379 iterator.Skip(encoded_cie_size);
380 int cie_size = encoded_cie_size + kInt32Size;
381
382 int encoded_fde_size = iterator.GetNextUInt32();
383 iterator.Skip(encoded_fde_size);
384 int fde_size = encoded_fde_size + kInt32Size;
385
386 iterator.Skip(EhFrameConstants::kEhFrameTerminatorSize);
387
388 int eh_frame_size =
389 cie_size + fde_size + EhFrameConstants::kEhFrameTerminatorSize;
390
391 //
392 // Plugging some numbers in the DSO layout shown in eh-frame.cc:
393 //
394 // | ... |
395 // +---------------+ <-- (E) ---------
396 // | | ^
397 // | Instructions | 10 bytes | .text
398 // | | v
399 // +---------------+ <----------------
400 // |///////////////|
401 // |////Padding////| 6 bytes
402 // |///////////////|
403 // +---------------+ <---(D)----------
404 // | | ^
405 // | CIE | cie_size bytes* |
406 // | | |
407 // +---------------+ <-- (C) |
408 // | | | .eh_frame
409 // | FDE | fde_size bytes |
410 // | | |
411 // +---------------+ |
412 // | terminator | 4 bytes v
413 // +---------------+ <-- (B) ---------
414 // | version | ^
415 // +---------------+ 4 bytes |
416 // | encoding | |
417 // | specifiers | |
418 // +---------------+ <---(A) | .eh_frame_hdr
419 // | offset to | |
420 // | .eh_frame | |
421 // +---------------+ |
422 // | ... | ...
423 //
424 // (*) the size of the CIE is platform dependent.
425 //
426
427 int eh_frame_hdr_version = iterator.GetNextByte();
428 EXPECT_EQ(EhFrameConstants::kEhFrameHdrVersion, eh_frame_hdr_version);
429
430 // .eh_frame pointer encoding specifier.
431 EXPECT_EQ(EhFrameConstants::kSData4 | EhFrameConstants::kPcRel,
432 iterator.GetNextByte());
433
434 // LUT size encoding specifier.
435 EXPECT_EQ(EhFrameConstants::kUData4, iterator.GetNextByte());
436
437 // LUT pointers encoding specifier.
438 EXPECT_EQ(EhFrameConstants::kSData4 | EhFrameConstants::kDataRel,
439 iterator.GetNextByte());
440
441 // A -> D
442 int offset_to_eh_frame = iterator.GetNextUInt32();
443 EXPECT_EQ(-(EhFrameConstants::kFdeVersionSize +
444 EhFrameConstants::kFdeEncodingSpecifiersSize + eh_frame_size),
445 offset_to_eh_frame);
446
447 int lut_entries = iterator.GetNextUInt32();
448 EXPECT_EQ(1, lut_entries);
449
450 // B -> E
451 int offset_to_procedure = iterator.GetNextUInt32();
452 EXPECT_EQ(-(eh_frame_size + kPaddingSize + kCodeSize), offset_to_procedure);
453
454 // B -> C
455 int offset_to_fde = iterator.GetNextUInt32();
456 EXPECT_EQ(-(fde_size + EhFrameConstants::kEhFrameTerminatorSize),
457 offset_to_fde);
458 }
459
460 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698