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

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

Powered by Google App Engine
This is Rietveld 408576698