1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "gtest/gtest.h"
7 #include "gmock/gmock.h"
8 #include "LulCommonExt.h"
9 #include "LulDwarfExt.h"
10 #include "LulDwarfInt.h"
11 #include "LulTestInfrastructure.h"
12
13 using testing::Test;
14 using testing::Return;
15 using testing::Sequence;
16 using testing::InSequence;
17 using testing::_;
18 using lul_test::CFISection;
19 using lul_test::test_assembler::kBigEndian;
20 using lul_test::test_assembler::kLittleEndian;
21 using lul_test::test_assembler::Label;
22
23 #define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section) /**/
24 #define PERHAPS_WRITE_EH_FRAME_FILE(name, section) /**/
25
26 // Set this to 0 to make LUL be completely silent during tests.
27 // Set it to 1 to get logging output from LUL, presumably for
28 // the purpose of debugging it.
29 #define DEBUG_LUL_TEST_DWARF 0
30
31 // LUL needs a callback for its logging sink.
32 static void
gtest_logging_sink_for_LulTestDwarf(const char * str)33 gtest_logging_sink_for_LulTestDwarf(const char* str) {
34 if (DEBUG_LUL_TEST_DWARF == 0) {
35 return;
36 }
37 // Ignore any trailing \n, since LOG will add one anyway.
38 size_t n = strlen(str);
39 if (n > 0 && str[n-1] == '\n') {
40 char* tmp = strdup(str);
41 tmp[n-1] = 0;
42 fprintf(stderr, "LUL-in-gtest: %s\n", tmp);
43 free(tmp);
44 } else {
45 fprintf(stderr, "LUL-in-gtest: %s\n", str);
46 }
47 }
48
49 namespace lul {
50
51 class MockCallFrameInfoHandler : public CallFrameInfo::Handler {
52 public:
53 MOCK_METHOD6(Entry, bool(size_t offset, uint64 address, uint64 length,
54 uint8 version, const std::string &augmentation,
55 unsigned return_address));
56 MOCK_METHOD2(UndefinedRule, bool(uint64 address, int reg));
57 MOCK_METHOD2(SameValueRule, bool(uint64 address, int reg));
58 MOCK_METHOD4(OffsetRule, bool(uint64 address, int reg, int base_register,
59 long offset));
60 MOCK_METHOD4(ValOffsetRule, bool(uint64 address, int reg, int base_register,
61 long offset));
62 MOCK_METHOD3(RegisterRule, bool(uint64 address, int reg, int base_register));
63 MOCK_METHOD3(ExpressionRule, bool(uint64 address, int reg,
64 const std::string &expression));
65 MOCK_METHOD3(ValExpressionRule, bool(uint64 address, int reg,
66 const std::string &expression));
67 MOCK_METHOD0(End, bool());
68 MOCK_METHOD2(PersonalityRoutine, bool(uint64 address, bool indirect));
69 MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64 address, bool indirect));
70 MOCK_METHOD0(SignalHandler, bool());
71 };
72
73 class MockCallFrameErrorReporter : public CallFrameInfo::Reporter {
74 public:
MockCallFrameErrorReporter()75 MockCallFrameErrorReporter()
76 : Reporter(gtest_logging_sink_for_LulTestDwarf,
77 "mock filename", "mock section")
78 { }
79 MOCK_METHOD2(Incomplete, void(uint64, CallFrameInfo::EntryKind));
80 MOCK_METHOD1(EarlyEHTerminator, void(uint64));
81 MOCK_METHOD2(CIEPointerOutOfRange, void(uint64, uint64));
82 MOCK_METHOD2(BadCIEId, void(uint64, uint64));
83 MOCK_METHOD2(UnrecognizedVersion, void(uint64, int version));
84 MOCK_METHOD2(UnrecognizedAugmentation, void(uint64, const string &));
85 MOCK_METHOD2(InvalidPointerEncoding, void(uint64, uint8));
86 MOCK_METHOD2(UnusablePointerEncoding, void(uint64, uint8));
87 MOCK_METHOD2(RestoreInCIE, void(uint64, uint64));
88 MOCK_METHOD3(BadInstruction, void(uint64, CallFrameInfo::EntryKind, uint64));
89 MOCK_METHOD3(NoCFARule, void(uint64, CallFrameInfo::EntryKind, uint64));
90 MOCK_METHOD3(EmptyStateStack, void(uint64, CallFrameInfo::EntryKind, uint64));
91 MOCK_METHOD3(ClearingCFARule, void(uint64, CallFrameInfo::EntryKind, uint64));
92 };
93
94 struct CFIFixture {
95
96 enum { kCFARegister = CallFrameInfo::Handler::kCFARegister };
97
CFIFixturelul::CFIFixture98 CFIFixture() {
99 // Default expectations for the data handler.
100 //
101 // - Leave Entry and End without expectations, as it's probably a
102 // good idea to set those explicitly in each test.
103 //
104 // - Expect the *Rule functions to not be called,
105 // so that each test can simply list the calls they expect.
106 //
107 // I gather I could use StrictMock for this, but the manual seems
108 // to suggest using that only as a last resort, and this isn't so
109 // bad.
110 EXPECT_CALL(handler, UndefinedRule(_, _)).Times(0);
111 EXPECT_CALL(handler, SameValueRule(_, _)).Times(0);
112 EXPECT_CALL(handler, OffsetRule(_, _, _, _)).Times(0);
113 EXPECT_CALL(handler, ValOffsetRule(_, _, _, _)).Times(0);
114 EXPECT_CALL(handler, RegisterRule(_, _, _)).Times(0);
115 EXPECT_CALL(handler, ExpressionRule(_, _, _)).Times(0);
116 EXPECT_CALL(handler, ValExpressionRule(_, _, _)).Times(0);
117 EXPECT_CALL(handler, PersonalityRoutine(_, _)).Times(0);
118 EXPECT_CALL(handler, LanguageSpecificDataArea(_, _)).Times(0);
119 EXPECT_CALL(handler, SignalHandler()).Times(0);
120
121 // Default expectations for the error/warning reporer.
122 EXPECT_CALL(reporter, Incomplete(_, _)).Times(0);
123 EXPECT_CALL(reporter, EarlyEHTerminator(_)).Times(0);
124 EXPECT_CALL(reporter, CIEPointerOutOfRange(_, _)).Times(0);
125 EXPECT_CALL(reporter, BadCIEId(_, _)).Times(0);
126 EXPECT_CALL(reporter, UnrecognizedVersion(_, _)).Times(0);
127 EXPECT_CALL(reporter, UnrecognizedAugmentation(_, _)).Times(0);
128 EXPECT_CALL(reporter, InvalidPointerEncoding(_, _)).Times(0);
129 EXPECT_CALL(reporter, UnusablePointerEncoding(_, _)).Times(0);
130 EXPECT_CALL(reporter, RestoreInCIE(_, _)).Times(0);
131 EXPECT_CALL(reporter, BadInstruction(_, _, _)).Times(0);
132 EXPECT_CALL(reporter, NoCFARule(_, _, _)).Times(0);
133 EXPECT_CALL(reporter, EmptyStateStack(_, _, _)).Times(0);
134 EXPECT_CALL(reporter, ClearingCFARule(_, _, _)).Times(0);
135 }
136
137 MockCallFrameInfoHandler handler;
138 MockCallFrameErrorReporter reporter;
139 };
140
141 class LulDwarfCFI: public CFIFixture, public Test { };
142
TEST_F(LulDwarfCFI,EmptyRegion)143 TEST_F(LulDwarfCFI, EmptyRegion) {
144 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
145 EXPECT_CALL(handler, End()).Times(0);
146 static const char data[1] = { 42 };
147
148 ByteReader reader(ENDIANNESS_BIG);
149 CallFrameInfo parser(data, 0, &reader, &handler, &reporter);
150 EXPECT_TRUE(parser.Start());
151 }
152
TEST_F(LulDwarfCFI,IncompleteLength32)153 TEST_F(LulDwarfCFI, IncompleteLength32) {
154 CFISection section(kBigEndian, 8);
155 section
156 // Not even long enough for an initial length.
157 .D16(0xa0f)
158 // Padding to keep valgrind happy. We subtract these off when we
159 // construct the parser.
160 .D16(0);
161
162 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
163 EXPECT_CALL(handler, End()).Times(0);
164
165 EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
166 .WillOnce(Return());
167
168 string contents;
169 ASSERT_TRUE(section.GetContents(&contents));
170
171 ByteReader reader(ENDIANNESS_BIG);
172 reader.SetAddressSize(8);
173 CallFrameInfo parser(contents.data(), contents.size() - 2,
174 &reader, &handler, &reporter);
175 EXPECT_FALSE(parser.Start());
176 }
177
TEST_F(LulDwarfCFI,IncompleteLength64)178 TEST_F(LulDwarfCFI, IncompleteLength64) {
179 CFISection section(kLittleEndian, 4);
180 section
181 // An incomplete 64-bit DWARF initial length.
182 .D32(0xffffffff).D32(0x71fbaec2)
183 // Padding to keep valgrind happy. We subtract these off when we
184 // construct the parser.
185 .D32(0);
186
187 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
188 EXPECT_CALL(handler, End()).Times(0);
189
190 EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
191 .WillOnce(Return());
192
193 string contents;
194 ASSERT_TRUE(section.GetContents(&contents));
195
196 ByteReader reader(ENDIANNESS_LITTLE);
197 reader.SetAddressSize(4);
198 CallFrameInfo parser(contents.data(), contents.size() - 4,
199 &reader, &handler, &reporter);
200 EXPECT_FALSE(parser.Start());
201 }
202
TEST_F(LulDwarfCFI,IncompleteId32)203 TEST_F(LulDwarfCFI, IncompleteId32) {
204 CFISection section(kBigEndian, 8);
205 section
206 .D32(3) // Initial length, not long enough for id
207 .D8(0xd7).D8(0xe5).D8(0xf1) // incomplete id
208 .CIEHeader(8727, 3983, 8889, 3, "")
209 .FinishEntry();
210
211 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
212 EXPECT_CALL(handler, End()).Times(0);
213
214 EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
215 .WillOnce(Return());
216
217 string contents;
218 ASSERT_TRUE(section.GetContents(&contents));
219
220 ByteReader reader(ENDIANNESS_BIG);
221 reader.SetAddressSize(8);
222 CallFrameInfo parser(contents.data(), contents.size(),
223 &reader, &handler, &reporter);
224 EXPECT_FALSE(parser.Start());
225 }
226
TEST_F(LulDwarfCFI,BadId32)227 TEST_F(LulDwarfCFI, BadId32) {
228 CFISection section(kBigEndian, 8);
229 section
230 .D32(0x100) // Initial length
231 .D32(0xe802fade) // bogus ID
232 .Append(0x100 - 4, 0x42); // make the length true
233 section
234 .CIEHeader(1672, 9872, 8529, 3, "")
235 .FinishEntry();
236
237 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
238 EXPECT_CALL(handler, End()).Times(0);
239
240 EXPECT_CALL(reporter, CIEPointerOutOfRange(_, 0xe802fade))
241 .WillOnce(Return());
242
243 string contents;
244 ASSERT_TRUE(section.GetContents(&contents));
245
246 ByteReader reader(ENDIANNESS_BIG);
247 reader.SetAddressSize(8);
248 CallFrameInfo parser(contents.data(), contents.size(),
249 &reader, &handler, &reporter);
250 EXPECT_FALSE(parser.Start());
251 }
252
253 // A lone CIE shouldn't cause any handler calls.
TEST_F(LulDwarfCFI,SingleCIE)254 TEST_F(LulDwarfCFI, SingleCIE) {
255 CFISection section(kLittleEndian, 4);
256 section.CIEHeader(0xffe799a8, 0x3398dcdd, 0x6e9683de, 3, "");
257 section.Append(10, lul::DW_CFA_nop);
258 section.FinishEntry();
259
260 PERHAPS_WRITE_DEBUG_FRAME_FILE("SingleCIE", section);
261
262 EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
263 EXPECT_CALL(handler, End()).Times(0);
264
265 string contents;
266 EXPECT_TRUE(section.GetContents(&contents));
267 ByteReader reader(ENDIANNESS_LITTLE);
268 reader.SetAddressSize(4);
269 CallFrameInfo parser(contents.data(), contents.size(),
270 &reader, &handler, &reporter);
271 EXPECT_TRUE(parser.Start());
272 }
273
274 // One FDE, one CIE.
TEST_F(LulDwarfCFI,OneFDE)275 TEST_F(LulDwarfCFI, OneFDE) {
276 CFISection section(kBigEndian, 4);
277 Label cie;
278 section
279 .Mark(&cie)
280 .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "")
281 .FinishEntry()
282 .FDEHeader(cie, 0x7714740d, 0x3d5a10cd)
283 .FinishEntry();
284
285 PERHAPS_WRITE_DEBUG_FRAME_FILE("OneFDE", section);
286
287 {
288 InSequence s;
289 EXPECT_CALL(handler,
290 Entry(_, 0x7714740d, 0x3d5a10cd, 3, "", 0x6b6efb87))
291 .WillOnce(Return(true));
292 EXPECT_CALL(handler, End()).WillOnce(Return(true));
293 }
294
295 string contents;
296 EXPECT_TRUE(section.GetContents(&contents));
297 ByteReader reader(ENDIANNESS_BIG);
298 reader.SetAddressSize(4);
299 CallFrameInfo parser(contents.data(), contents.size(),
300 &reader, &handler, &reporter);
301 EXPECT_TRUE(parser.Start());
302 }
303
304 // Two FDEs share a CIE.
TEST_F(LulDwarfCFI,TwoFDEsOneCIE)305 TEST_F(LulDwarfCFI, TwoFDEsOneCIE) {
306 CFISection section(kBigEndian, 4);
307 Label cie;
308 section
309 // First FDE. readelf complains about this one because it makes
310 // a forward reference to its CIE.
311 .FDEHeader(cie, 0xa42744df, 0xa3b42121)
312 .FinishEntry()
313 // CIE.
314 .Mark(&cie)
315 .CIEHeader(0x04f7dc7b, 0x3d00c05f, 0xbd43cb59, 3, "")
316 .FinishEntry()
317 // Second FDE.
318 .FDEHeader(cie, 0x6057d391, 0x700f608d)
319 .FinishEntry();
320
321 PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsOneCIE", section);
322
323 {
324 InSequence s;
325 EXPECT_CALL(handler,
326 Entry(_, 0xa42744df, 0xa3b42121, 3, "", 0xbd43cb59))
327 .WillOnce(Return(true));
328 EXPECT_CALL(handler, End()).WillOnce(Return(true));
329 }
330 {
331 InSequence s;
332 EXPECT_CALL(handler,
333 Entry(_, 0x6057d391, 0x700f608d, 3, "", 0xbd43cb59))
334 .WillOnce(Return(true));
335 EXPECT_CALL(handler, End()).WillOnce(Return(true));
336 }
337
338 string contents;
339 EXPECT_TRUE(section.GetContents(&contents));
340 ByteReader reader(ENDIANNESS_BIG);
341 reader.SetAddressSize(4);
342 CallFrameInfo parser(contents.data(), contents.size(),
343 &reader, &handler, &reporter);
344 EXPECT_TRUE(parser.Start());
345 }
346
347 // Two FDEs, two CIEs.
TEST_F(LulDwarfCFI,TwoFDEsTwoCIEs)348 TEST_F(LulDwarfCFI, TwoFDEsTwoCIEs) {
349 CFISection section(kLittleEndian, 8);
350 Label cie1, cie2;
351 section
352 // First CIE.
353 .Mark(&cie1)
354 .CIEHeader(0x694d5d45, 0x4233221b, 0xbf45e65a, 3, "")
355 .FinishEntry()
356 // First FDE which cites second CIE. readelf complains about
357 // this one because it makes a forward reference to its CIE.
358 .FDEHeader(cie2, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL)
359 .FinishEntry()
360 // Second FDE, which cites first CIE.
361 .FDEHeader(cie1, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL)
362 .FinishEntry()
363 // Second CIE.
364 .Mark(&cie2)
365 .CIEHeader(0xfba3fad7, 0x6287e1fd, 0x61d2c581, 2, "")
366 .FinishEntry();
367
368 PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsTwoCIEs", section);
369
370 {
371 InSequence s;
372 EXPECT_CALL(handler,
373 Entry(_, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL, 2,
374 "", 0x61d2c581))
375 .WillOnce(Return(true));
376 EXPECT_CALL(handler, End()).WillOnce(Return(true));
377 }
378 {
379 InSequence s;
380 EXPECT_CALL(handler,
381 Entry(_, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL, 3,
382 "", 0xbf45e65a))
383 .WillOnce(Return(true));
384 EXPECT_CALL(handler, End()).WillOnce(Return(true));
385 }
386
387 string contents;
388 EXPECT_TRUE(section.GetContents(&contents));
389 ByteReader reader(ENDIANNESS_LITTLE);
390 reader.SetAddressSize(8);
391 CallFrameInfo parser(contents.data(), contents.size(),
392 &reader, &handler, &reporter);
393 EXPECT_TRUE(parser.Start());
394 }
395
396 // An FDE whose CIE specifies a version we don't recognize.
TEST_F(LulDwarfCFI,BadVersion)397 TEST_F(LulDwarfCFI, BadVersion) {
398 CFISection section(kBigEndian, 4);
399 Label cie1, cie2;
400 section
401 .Mark(&cie1)
402 .CIEHeader(0xca878cf0, 0x7698ec04, 0x7b616f54, 0x52, "")
403 .FinishEntry()
404 // We should skip this entry, as its CIE specifies a version we
405 // don't recognize.
406 .FDEHeader(cie1, 0x08852292, 0x2204004a)
407 .FinishEntry()
408 // Despite the above, we should visit this entry.
409 .Mark(&cie2)
410 .CIEHeader(0x7c3ae7c9, 0xb9b9a512, 0x96cb3264, 3, "")
411 .FinishEntry()
412 .FDEHeader(cie2, 0x2094735a, 0x6e875501)
413 .FinishEntry();
414
415 PERHAPS_WRITE_DEBUG_FRAME_FILE("BadVersion", section);
416
417 EXPECT_CALL(reporter, UnrecognizedVersion(_, 0x52))
418 .WillOnce(Return());
419
420 {
421 InSequence s;
422 // We should see no mention of the first FDE, but we should get
423 // a call to Entry for the second.
424 EXPECT_CALL(handler, Entry(_, 0x2094735a, 0x6e875501, 3, "",
425 0x96cb3264))
426 .WillOnce(Return(true));
427 EXPECT_CALL(handler, End())
428 .WillOnce(Return(true));
429 }
430
431 string contents;
432 EXPECT_TRUE(section.GetContents(&contents));
433 ByteReader reader(ENDIANNESS_BIG);
434 reader.SetAddressSize(4);
435 CallFrameInfo parser(contents.data(), contents.size(),
436 &reader, &handler, &reporter);
437 EXPECT_FALSE(parser.Start());
438 }
439
440 // An FDE whose CIE specifies an augmentation we don't recognize.
TEST_F(LulDwarfCFI,BadAugmentation)441 TEST_F(LulDwarfCFI, BadAugmentation) {
442 CFISection section(kBigEndian, 4);
443 Label cie1, cie2;
444 section
445 .Mark(&cie1)
446 .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "spaniels!")
447 .FinishEntry()
448 // We should skip this entry, as its CIE specifies an
449 // augmentation we don't recognize.
450 .FDEHeader(cie1, 0x7714740d, 0x3d5a10cd)
451 .FinishEntry()
452 // Despite the above, we should visit this entry.
453 .Mark(&cie2)
454 .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 3, "")
455 .FinishEntry()
456 .FDEHeader(cie2, 0x7bf0fda0, 0xcbcd28d8)
457 .FinishEntry();
458
459 PERHAPS_WRITE_DEBUG_FRAME_FILE("BadAugmentation", section);
460
461 EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "spaniels!"))
462 .WillOnce(Return());
463
464 {
465 InSequence s;
466 // We should see no mention of the first FDE, but we should get
467 // a call to Entry for the second.
468 EXPECT_CALL(handler, Entry(_, 0x7bf0fda0, 0xcbcd28d8, 3, "",
469 0xf2f519b2))
470 .WillOnce(Return(true));
471 EXPECT_CALL(handler, End())
472 .WillOnce(Return(true));
473 }
474
475 string contents;
476 EXPECT_TRUE(section.GetContents(&contents));
477 ByteReader reader(ENDIANNESS_BIG);
478 reader.SetAddressSize(4);
479 CallFrameInfo parser(contents.data(), contents.size(),
480 &reader, &handler, &reporter);
481 EXPECT_FALSE(parser.Start());
482 }
483
484 // The return address column field is a byte in CFI version 1
485 // (DWARF2), but a ULEB128 value in version 3 (DWARF3).
TEST_F(LulDwarfCFI,CIEVersion1ReturnColumn)486 TEST_F(LulDwarfCFI, CIEVersion1ReturnColumn) {
487 CFISection section(kBigEndian, 4);
488 Label cie;
489 section
490 // CIE, using the version 1 format: return column is a ubyte.
491 .Mark(&cie)
492 // Use a value for the return column that is parsed differently
493 // as a ubyte and as a ULEB128.
494 .CIEHeader(0xbcdea24f, 0x5be28286, 0x9f, 1, "")
495 .FinishEntry()
496 // FDE, citing that CIE.
497 .FDEHeader(cie, 0xb8d347b5, 0x825e55dc)
498 .FinishEntry();
499
500 PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion1ReturnColumn", section);
501
502 {
503 InSequence s;
504 EXPECT_CALL(handler, Entry(_, 0xb8d347b5, 0x825e55dc, 1, "", 0x9f))
505 .WillOnce(Return(true));
506 EXPECT_CALL(handler, End()).WillOnce(Return(true));
507 }
508
509 string contents;
510 EXPECT_TRUE(section.GetContents(&contents));
511 ByteReader reader(ENDIANNESS_BIG);
512 reader.SetAddressSize(4);
513 CallFrameInfo parser(contents.data(), contents.size(),
514 &reader, &handler, &reporter);
515 EXPECT_TRUE(parser.Start());
516 }
517
518 // The return address column field is a byte in CFI version 1
519 // (DWARF2), but a ULEB128 value in version 3 (DWARF3).
TEST_F(LulDwarfCFI,CIEVersion3ReturnColumn)520 TEST_F(LulDwarfCFI, CIEVersion3ReturnColumn) {
521 CFISection section(kBigEndian, 4);
522 Label cie;
523 section
524 // CIE, using the version 3 format: return column is a ULEB128.
525 .Mark(&cie)
526 // Use a value for the return column that is parsed differently
527 // as a ubyte and as a ULEB128.
528 .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 3, "")
529 .FinishEntry()
530 // FDE, citing that CIE.
531 .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
532 .FinishEntry();
533
534 PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section);
535
536 {
537 InSequence s;
538 EXPECT_CALL(handler, Entry(_, 0x86763f2b, 0x2a66dc23, 3, "", 0x89))
539 .WillOnce(Return(true));
540 EXPECT_CALL(handler, End()).WillOnce(Return(true));
541 }
542
543 string contents;
544 EXPECT_TRUE(section.GetContents(&contents));
545 ByteReader reader(ENDIANNESS_BIG);
546 reader.SetAddressSize(4);
547 CallFrameInfo parser(contents.data(), contents.size(),
548 &reader, &handler, &reporter);
549 EXPECT_TRUE(parser.Start());
550 }
551
552 struct CFIInsnFixture: public CFIFixture {
CFIInsnFixturelul::CFIInsnFixture553 CFIInsnFixture() : CFIFixture() {
554 data_factor = 0xb6f;
555 return_register = 0x9be1ed9f;
556 version = 3;
557 cfa_base_register = 0x383a3aa;
558 cfa_offset = 0xf748;
559 }
560
561 // Prepare SECTION to receive FDE instructions.
562 //
563 // - Append a stock CIE header that establishes the fixture's
564 // code_factor, data_factor, return_register, version, and
565 // augmentation values.
566 // - Have the CIE set up a CFA rule using cfa_base_register and
567 // cfa_offset.
568 // - Append a stock FDE header, referring to the above CIE, for the
569 // fde_size bytes at fde_start. Choose fde_start and fde_size
570 // appropriately for the section's address size.
571 // - Set appropriate expectations on handler in sequence s for the
572 // frame description entry and the CIE's CFA rule.
573 //
574 // On return, SECTION is ready to have FDE instructions appended to
575 // it, and its FinishEntry member called.
StockCIEAndFDElul::CFIInsnFixture576 void StockCIEAndFDE(CFISection *section) {
577 // Choose appropriate constants for our address size.
578 if (section->AddressSize() == 4) {
579 fde_start = 0xc628ecfbU;
580 fde_size = 0x5dee04a2;
581 code_factor = 0x60b;
582 } else {
583 assert(section->AddressSize() == 8);
584 fde_start = 0x0005c57ce7806bd3ULL;
585 fde_size = 0x2699521b5e333100ULL;
586 code_factor = 0x01008e32855274a8ULL;
587 }
588
589 // Create the CIE.
590 (*section)
591 .Mark(&cie_label)
592 .CIEHeader(code_factor, data_factor, return_register, version,
593 "")
594 .D8(lul::DW_CFA_def_cfa)
595 .ULEB128(cfa_base_register)
596 .ULEB128(cfa_offset)
597 .FinishEntry();
598
599 // Create the FDE.
600 section->FDEHeader(cie_label, fde_start, fde_size);
601
602 // Expect an Entry call for the FDE and a ValOffsetRule call for the
603 // CIE's CFA rule.
604 EXPECT_CALL(handler, Entry(_, fde_start, fde_size, version, "",
605 return_register))
606 .InSequence(s)
607 .WillOnce(Return(true));
608 EXPECT_CALL(handler, ValOffsetRule(fde_start, kCFARegister,
609 cfa_base_register, cfa_offset))
610 .InSequence(s)
611 .WillOnce(Return(true));
612 }
613
614 // Run the contents of SECTION through a CallFrameInfo parser,
615 // expecting parser.Start to return SUCCEEDS. Caller may optionally
616 // supply, via READER, its own ByteReader. If that's absent, a
617 // local one is used.
ParseSectionlul::CFIInsnFixture618 void ParseSection(CFISection *section,
619 bool succeeds = true, ByteReader* reader = nullptr) {
620 string contents;
621 EXPECT_TRUE(section->GetContents(&contents));
622 lul::Endianness endianness;
623 if (section->endianness() == kBigEndian)
624 endianness = ENDIANNESS_BIG;
625 else {
626 assert(section->endianness() == kLittleEndian);
627 endianness = ENDIANNESS_LITTLE;
628 }
629 ByteReader local_reader(endianness);
630 ByteReader* reader_to_use = reader ? reader : &local_reader;
631 reader_to_use->SetAddressSize(section->AddressSize());
632 CallFrameInfo parser(contents.data(), contents.size(),
633 reader_to_use, &handler, &reporter);
634 if (succeeds)
635 EXPECT_TRUE(parser.Start());
636 else
637 EXPECT_FALSE(parser.Start());
638 }
639
640 Label cie_label;
641 Sequence s;
642 uint64 code_factor;
643 int data_factor;
644 unsigned return_register;
645 unsigned version;
646 unsigned cfa_base_register;
647 int cfa_offset;
648 uint64 fde_start, fde_size;
649 };
650
651 class LulDwarfCFIInsn: public CFIInsnFixture, public Test { };
652
TEST_F(LulDwarfCFIInsn,DW_CFA_set_loc)653 TEST_F(LulDwarfCFIInsn, DW_CFA_set_loc) {
654 CFISection section(kBigEndian, 4);
655 StockCIEAndFDE(§ion);
656 section
657 .D8(lul::DW_CFA_set_loc).D32(0xb1ee3e7a)
658 // Use DW_CFA_def_cfa to force a handler call that we can use to
659 // check the effect of the DW_CFA_set_loc.
660 .D8(lul::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee)
661 .FinishEntry();
662
663 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_set_loc", section);
664
665 EXPECT_CALL(handler,
666 ValOffsetRule(0xb1ee3e7a, kCFARegister, 0x4defb431, 0x6d17b0ee))
667 .InSequence(s)
668 .WillOnce(Return(true));
669 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
670
671 ParseSection(§ion);
672 }
673
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc)674 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc) {
675 CFISection section(kBigEndian, 8);
676 StockCIEAndFDE(§ion);
677 section
678 .D8(lul::DW_CFA_advance_loc | 0x2a)
679 // Use DW_CFA_def_cfa to force a handler call that we can use to
680 // check the effect of the DW_CFA_advance_loc.
681 .D8(lul::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf)
682 .FinishEntry();
683
684 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc", section);
685
686 EXPECT_CALL(handler,
687 ValOffsetRule(fde_start + 0x2a * code_factor,
688 kCFARegister, 0x5bbb3715, 0x0186c7bf))
689 .InSequence(s)
690 .WillOnce(Return(true));
691 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
692
693 ParseSection(§ion);
694 }
695
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc1)696 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc1) {
697 CFISection section(kLittleEndian, 8);
698 StockCIEAndFDE(§ion);
699 section
700 .D8(lul::DW_CFA_advance_loc1).D8(0xd8)
701 .D8(lul::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93)
702 .FinishEntry();
703
704 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc1", section);
705
706 EXPECT_CALL(handler,
707 ValOffsetRule((fde_start + 0xd8 * code_factor),
708 kCFARegister, 0x69d5696a, 0x1eb7fc93))
709 .InSequence(s)
710 .WillOnce(Return(true));
711 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
712
713 ParseSection(§ion);
714 }
715
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc2)716 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc2) {
717 CFISection section(kLittleEndian, 4);
718 StockCIEAndFDE(§ion);
719 section
720 .D8(lul::DW_CFA_advance_loc2).D16(0x3adb)
721 .D8(lul::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37)
722 .FinishEntry();
723
724 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc2", section);
725
726 EXPECT_CALL(handler,
727 ValOffsetRule((fde_start + 0x3adb * code_factor),
728 kCFARegister, 0x3a368bed, 0x3194ee37))
729 .InSequence(s)
730 .WillOnce(Return(true));
731 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
732
733 ParseSection(§ion);
734 }
735
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc4)736 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc4) {
737 CFISection section(kBigEndian, 8);
738 StockCIEAndFDE(§ion);
739 section
740 .D8(lul::DW_CFA_advance_loc4).D32(0x15813c88)
741 .D8(lul::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb)
742 .FinishEntry();
743
744 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc4", section);
745
746 EXPECT_CALL(handler,
747 ValOffsetRule((fde_start + 0x15813c88ULL * code_factor),
748 kCFARegister, 0x135270c5, 0x24bad7cb))
749 .InSequence(s)
750 .WillOnce(Return(true));
751 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
752
753 ParseSection(§ion);
754 }
755
TEST_F(LulDwarfCFIInsn,DW_CFA_MIPS_advance_loc8)756 TEST_F(LulDwarfCFIInsn, DW_CFA_MIPS_advance_loc8) {
757 code_factor = 0x2d;
758 CFISection section(kBigEndian, 8);
759 StockCIEAndFDE(§ion);
760 section
761 .D8(lul::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL)
762 .D8(lul::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f)
763 .FinishEntry();
764
765 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc8", section);
766
767 EXPECT_CALL(handler,
768 ValOffsetRule((fde_start + 0x3c4f3945b92c14ULL * code_factor),
769 kCFARegister, 0xe17ed602, 0x3d162e7f))
770 .InSequence(s)
771 .WillOnce(Return(true));
772 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
773
774 ParseSection(§ion);
775 }
776
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa)777 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa) {
778 CFISection section(kLittleEndian, 4);
779 StockCIEAndFDE(§ion);
780 section
781 .D8(lul::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7)
782 .FinishEntry();
783
784 PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_def_cfa", section);
785
786 EXPECT_CALL(handler,
787 ValOffsetRule(fde_start, kCFARegister, 0x4e363a85, 0x815f9aa7))
788 .InSequence(s).WillOnce(Return(true));
789 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
790
791 ParseSection(§ion);
792 }
793
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_sf)794 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_sf) {
795 CFISection section(kBigEndian, 4);
796 StockCIEAndFDE(§ion);
797 section
798 .D8(lul::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea)
799 .D8(lul::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2)
800 .FinishEntry();
801
802 EXPECT_CALL(handler,
803 ValOffsetRule(fde_start, kCFARegister, 0x8ccb32b7,
804 0x9ea * data_factor))
805 .InSequence(s).WillOnce(Return(true));
806 EXPECT_CALL(handler,
807 ValOffsetRule(fde_start, kCFARegister, 0x9b40f5da,
808 -0x40a2 * data_factor))
809 .InSequence(s).WillOnce(Return(true));
810 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
811
812 ParseSection(§ion);
813 }
814
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_register)815 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_register) {
816 CFISection section(kLittleEndian, 8);
817 StockCIEAndFDE(§ion);
818 section
819 .D8(lul::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363)
820 .FinishEntry();
821
822 EXPECT_CALL(handler,
823 ValOffsetRule(fde_start, kCFARegister, 0x3e7e9363, cfa_offset))
824 .InSequence(s).WillOnce(Return(true));
825 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
826
827 ParseSection(§ion);
828 }
829
830 // DW_CFA_def_cfa_register should have no effect when applied to a
831 // non-base/offset rule.
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_registerBadRule)832 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_registerBadRule) {
833 ByteReader reader(ENDIANNESS_BIG);
834 CFISection section(kBigEndian, 4);
835 StockCIEAndFDE(§ion);
836 section
837 .D8(lul::DW_CFA_def_cfa_expression).Block("needle in a haystack")
838 .D8(lul::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49)
839 .FinishEntry();
840
841 EXPECT_CALL(handler,
842 ValExpressionRule(fde_start, kCFARegister,
843 "needle in a haystack"))
844 .WillRepeatedly(Return(true));
845 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
846
847 ParseSection(§ion, true, &reader);
848 }
849
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_offset)850 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_offset) {
851 CFISection section(kBigEndian, 4);
852 StockCIEAndFDE(§ion);
853 section
854 .D8(lul::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
855 .FinishEntry();
856
857 EXPECT_CALL(handler,
858 ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
859 0x1e8e3b9b))
860 .InSequence(s).WillOnce(Return(true));
861 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
862
863 ParseSection(§ion);
864 }
865
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_offset_sf)866 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_offset_sf) {
867 CFISection section(kLittleEndian, 4);
868 StockCIEAndFDE(§ion);
869 section
870 .D8(lul::DW_CFA_def_cfa_offset_sf).LEB128(0x970)
871 .D8(lul::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd)
872 .FinishEntry();
873
874 EXPECT_CALL(handler,
875 ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
876 0x970 * data_factor))
877 .InSequence(s).WillOnce(Return(true));
878 EXPECT_CALL(handler,
879 ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
880 -0x2cd * data_factor))
881 .InSequence(s).WillOnce(Return(true));
882 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
883
884 ParseSection(§ion);
885 }
886
887 // DW_CFA_def_cfa_offset should have no effect when applied to a
888 // non-base/offset rule.
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_offsetBadRule)889 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_offsetBadRule) {
890 ByteReader reader(ENDIANNESS_BIG);
891 CFISection section(kBigEndian, 4);
892 StockCIEAndFDE(§ion);
893 section
894 .D8(lul::DW_CFA_def_cfa_expression).Block("six ways to Sunday")
895 .D8(lul::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
896 .FinishEntry();
897
898 EXPECT_CALL(handler,
899 ValExpressionRule(fde_start, kCFARegister,
900 "six ways to Sunday"))
901 .WillRepeatedly(Return(true));
902 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
903
904 ParseSection(§ion, true, &reader);
905 }
906
907
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa_expression)908 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa_expression) {
909 ByteReader reader(ENDIANNESS_LITTLE);
910 CFISection section(kLittleEndian, 8);
911 StockCIEAndFDE(§ion);
912 section
913 .D8(lul::DW_CFA_def_cfa_expression).Block("eating crow")
914 .FinishEntry();
915
916 EXPECT_CALL(handler, ValExpressionRule(fde_start, kCFARegister,
917 "eating crow"))
918 .InSequence(s).WillOnce(Return(true));
919 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
920
921 ParseSection(§ion, true, &reader);
922 }
923
TEST_F(LulDwarfCFIInsn,DW_CFA_undefined)924 TEST_F(LulDwarfCFIInsn, DW_CFA_undefined) {
925 CFISection section(kLittleEndian, 4);
926 StockCIEAndFDE(§ion);
927 section
928 .D8(lul::DW_CFA_undefined).ULEB128(0x300ce45d)
929 .FinishEntry();
930
931 EXPECT_CALL(handler, UndefinedRule(fde_start, 0x300ce45d))
932 .InSequence(s).WillOnce(Return(true));
933 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
934
935 ParseSection(§ion);
936 }
937
TEST_F(LulDwarfCFIInsn,DW_CFA_same_value)938 TEST_F(LulDwarfCFIInsn, DW_CFA_same_value) {
939 CFISection section(kLittleEndian, 4);
940 StockCIEAndFDE(§ion);
941 section
942 .D8(lul::DW_CFA_same_value).ULEB128(0x3865a760)
943 .FinishEntry();
944
945 EXPECT_CALL(handler, SameValueRule(fde_start, 0x3865a760))
946 .InSequence(s).WillOnce(Return(true));
947 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
948
949 ParseSection(§ion);
950 }
951
TEST_F(LulDwarfCFIInsn,DW_CFA_offset)952 TEST_F(LulDwarfCFIInsn, DW_CFA_offset) {
953 CFISection section(kBigEndian, 4);
954 StockCIEAndFDE(§ion);
955 section
956 .D8(lul::DW_CFA_offset | 0x2c).ULEB128(0x9f6)
957 .FinishEntry();
958
959 EXPECT_CALL(handler,
960 OffsetRule(fde_start, 0x2c, kCFARegister, 0x9f6 * data_factor))
961 .InSequence(s).WillOnce(Return(true));
962 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
963
964 ParseSection(§ion);
965 }
966
TEST_F(LulDwarfCFIInsn,DW_CFA_offset_extended)967 TEST_F(LulDwarfCFIInsn, DW_CFA_offset_extended) {
968 CFISection section(kBigEndian, 4);
969 StockCIEAndFDE(§ion);
970 section
971 .D8(lul::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48)
972 .FinishEntry();
973
974 EXPECT_CALL(handler,
975 OffsetRule(fde_start,
976 0x402b, kCFARegister, 0xb48 * data_factor))
977 .InSequence(s).WillOnce(Return(true));
978 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
979
980 ParseSection(§ion);
981 }
982
TEST_F(LulDwarfCFIInsn,DW_CFA_offset_extended_sf)983 TEST_F(LulDwarfCFIInsn, DW_CFA_offset_extended_sf) {
984 CFISection section(kBigEndian, 8);
985 StockCIEAndFDE(§ion);
986 section
987 .D8(lul::DW_CFA_offset_extended_sf)
988 .ULEB128(0x997c23ee).LEB128(0x2d00)
989 .D8(lul::DW_CFA_offset_extended_sf)
990 .ULEB128(0x9519eb82).LEB128(-0xa77)
991 .FinishEntry();
992
993 EXPECT_CALL(handler,
994 OffsetRule(fde_start, 0x997c23ee,
995 kCFARegister, 0x2d00 * data_factor))
996 .InSequence(s).WillOnce(Return(true));
997 EXPECT_CALL(handler,
998 OffsetRule(fde_start, 0x9519eb82,
999 kCFARegister, -0xa77 * data_factor))
1000 .InSequence(s).WillOnce(Return(true));
1001 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1002
1003 ParseSection(§ion);
1004 }
1005
TEST_F(LulDwarfCFIInsn,DW_CFA_val_offset)1006 TEST_F(LulDwarfCFIInsn, DW_CFA_val_offset) {
1007 CFISection section(kBigEndian, 4);
1008 StockCIEAndFDE(§ion);
1009 section
1010 .D8(lul::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673)
1011 .FinishEntry();
1012
1013 EXPECT_CALL(handler,
1014 ValOffsetRule(fde_start, 0x623562fe,
1015 kCFARegister, 0x673 * data_factor))
1016 .InSequence(s).WillOnce(Return(true));
1017 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1018
1019 ParseSection(§ion);
1020 }
1021
TEST_F(LulDwarfCFIInsn,DW_CFA_val_offset_sf)1022 TEST_F(LulDwarfCFIInsn, DW_CFA_val_offset_sf) {
1023 CFISection section(kBigEndian, 4);
1024 StockCIEAndFDE(§ion);
1025 section
1026 .D8(lul::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab)
1027 .D8(lul::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2)
1028 .FinishEntry();
1029
1030 EXPECT_CALL(handler,
1031 ValOffsetRule(fde_start, 0x6f4f,
1032 kCFARegister, 0xaab * data_factor))
1033 .InSequence(s).WillOnce(Return(true));
1034 EXPECT_CALL(handler,
1035 ValOffsetRule(fde_start, 0x2483,
1036 kCFARegister, -0x8a2 * data_factor))
1037 .InSequence(s).WillOnce(Return(true));
1038 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1039
1040 ParseSection(§ion);
1041 }
1042
TEST_F(LulDwarfCFIInsn,DW_CFA_register)1043 TEST_F(LulDwarfCFIInsn, DW_CFA_register) {
1044 CFISection section(kLittleEndian, 8);
1045 StockCIEAndFDE(§ion);
1046 section
1047 .D8(lul::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414)
1048 .FinishEntry();
1049
1050 EXPECT_CALL(handler, RegisterRule(fde_start, 0x278d18f9, 0x1a684414))
1051 .InSequence(s).WillOnce(Return(true));
1052 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1053
1054 ParseSection(§ion);
1055 }
1056
TEST_F(LulDwarfCFIInsn,DW_CFA_expression)1057 TEST_F(LulDwarfCFIInsn, DW_CFA_expression) {
1058 ByteReader reader(ENDIANNESS_BIG);
1059 CFISection section(kBigEndian, 8);
1060 StockCIEAndFDE(§ion);
1061 section
1062 .D8(lul::DW_CFA_expression).ULEB128(0xa1619fb2)
1063 .Block("plus ça change, plus c'est la même chose")
1064 .FinishEntry();
1065
1066 EXPECT_CALL(handler,
1067 ExpressionRule(fde_start, 0xa1619fb2,
1068 "plus ça change, plus c'est la même chose"))
1069 .InSequence(s).WillOnce(Return(true));
1070 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1071
1072 ParseSection(§ion, true, &reader);
1073 }
1074
TEST_F(LulDwarfCFIInsn,DW_CFA_val_expression)1075 TEST_F(LulDwarfCFIInsn, DW_CFA_val_expression) {
1076 ByteReader reader(ENDIANNESS_BIG);
1077 CFISection section(kBigEndian, 4);
1078 StockCIEAndFDE(§ion);
1079 section
1080 .D8(lul::DW_CFA_val_expression).ULEB128(0xc5e4a9e3)
1081 .Block("he who has the gold makes the rules")
1082 .FinishEntry();
1083
1084 EXPECT_CALL(handler,
1085 ValExpressionRule(fde_start, 0xc5e4a9e3,
1086 "he who has the gold makes the rules"))
1087 .InSequence(s).WillOnce(Return(true));
1088 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1089
1090 ParseSection(§ion, true, &reader);
1091 }
1092
TEST_F(LulDwarfCFIInsn,DW_CFA_restore)1093 TEST_F(LulDwarfCFIInsn, DW_CFA_restore) {
1094 CFISection section(kLittleEndian, 8);
1095 code_factor = 0x01bd188a9b1fa083ULL;
1096 data_factor = -0x1ac8;
1097 return_register = 0x8c35b049;
1098 version = 2;
1099 fde_start = 0x2d70fe998298bbb1ULL;
1100 fde_size = 0x46ccc2e63cf0b108ULL;
1101 Label cie;
1102 section
1103 .Mark(&cie)
1104 .CIEHeader(code_factor, data_factor, return_register, version,
1105 "")
1106 // Provide a CFA rule, because register rules require them.
1107 .D8(lul::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8)
1108 // Provide an offset(N) rule for register 0x3c.
1109 .D8(lul::DW_CFA_offset | 0x3c).ULEB128(0xb348)
1110 .FinishEntry()
1111 // In the FDE...
1112 .FDEHeader(cie, fde_start, fde_size)
1113 // At a second address, provide a new offset(N) rule for register 0x3c.
1114 .D8(lul::DW_CFA_advance_loc | 0x13)
1115 .D8(lul::DW_CFA_offset | 0x3c).ULEB128(0x9a50)
1116 // At a third address, restore the original rule for register 0x3c.
1117 .D8(lul::DW_CFA_advance_loc | 0x01)
1118 .D8(lul::DW_CFA_restore | 0x3c)
1119 .FinishEntry();
1120
1121 {
1122 InSequence s;
1123 EXPECT_CALL(handler,
1124 Entry(_, fde_start, fde_size, version, "", return_register))
1125 .WillOnce(Return(true));
1126 // CIE's CFA rule.
1127 EXPECT_CALL(handler,
1128 ValOffsetRule(fde_start,
1129 kCFARegister, 0x6ca1d50e, 0x372e38e8))
1130 .WillOnce(Return(true));
1131 // CIE's rule for register 0x3c.
1132 EXPECT_CALL(handler,
1133 OffsetRule(fde_start, 0x3c,
1134 kCFARegister, 0xb348 * data_factor))
1135 .WillOnce(Return(true));
1136 // FDE's rule for register 0x3c.
1137 EXPECT_CALL(handler,
1138 OffsetRule(fde_start + 0x13 * code_factor, 0x3c,
1139 kCFARegister, 0x9a50 * data_factor))
1140 .WillOnce(Return(true));
1141 // Restore CIE's rule for register 0x3c.
1142 EXPECT_CALL(handler,
1143 OffsetRule(fde_start + (0x13 + 0x01) * code_factor, 0x3c,
1144 kCFARegister, 0xb348 * data_factor))
1145 .WillOnce(Return(true));
1146 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1147 }
1148
1149 ParseSection(§ion);
1150 }
1151
TEST_F(LulDwarfCFIInsn,DW_CFA_restoreNoRule)1152 TEST_F(LulDwarfCFIInsn, DW_CFA_restoreNoRule) {
1153 CFISection section(kBigEndian, 4);
1154 code_factor = 0x005f78143c1c3b82ULL;
1155 data_factor = 0x25d0;
1156 return_register = 0xe8;
1157 version = 1;
1158 fde_start = 0x4062e30f;
1159 fde_size = 0x5302a389;
1160 Label cie;
1161 section
1162 .Mark(&cie)
1163 .CIEHeader(code_factor, data_factor, return_register, version, "")
1164 // Provide a CFA rule, because register rules require them.
1165 .D8(lul::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127)
1166 .FinishEntry()
1167 // In the FDE...
1168 .FDEHeader(cie, fde_start, fde_size)
1169 // At a second address, provide an offset(N) rule for register 0x2c.
1170 .D8(lul::DW_CFA_advance_loc | 0x7)
1171 .D8(lul::DW_CFA_offset | 0x2c).ULEB128(0x1f47)
1172 // At a third address, restore the (missing) CIE rule for register 0x2c.
1173 .D8(lul::DW_CFA_advance_loc | 0xb)
1174 .D8(lul::DW_CFA_restore | 0x2c)
1175 .FinishEntry();
1176
1177 {
1178 InSequence s;
1179 EXPECT_CALL(handler,
1180 Entry(_, fde_start, fde_size, version, "", return_register))
1181 .WillOnce(Return(true));
1182 // CIE's CFA rule.
1183 EXPECT_CALL(handler,
1184 ValOffsetRule(fde_start,
1185 kCFARegister, 0x470aa334, 0x099ef127))
1186 .WillOnce(Return(true));
1187 // FDE's rule for register 0x2c.
1188 EXPECT_CALL(handler,
1189 OffsetRule(fde_start + 0x7 * code_factor, 0x2c,
1190 kCFARegister, 0x1f47 * data_factor))
1191 .WillOnce(Return(true));
1192 // Restore CIE's (missing) rule for register 0x2c.
1193 EXPECT_CALL(handler,
1194 SameValueRule(fde_start + (0x7 + 0xb) * code_factor, 0x2c))
1195 .WillOnce(Return(true));
1196 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1197 }
1198
1199 ParseSection(§ion);
1200 }
1201
TEST_F(LulDwarfCFIInsn,DW_CFA_restore_extended)1202 TEST_F(LulDwarfCFIInsn, DW_CFA_restore_extended) {
1203 CFISection section(kBigEndian, 4);
1204 code_factor = 0x126e;
1205 data_factor = -0xd8b;
1206 return_register = 0x77711787;
1207 version = 3;
1208 fde_start = 0x01f55a45;
1209 fde_size = 0x452adb80;
1210 Label cie;
1211 section
1212 .Mark(&cie)
1213 .CIEHeader(code_factor, data_factor, return_register, version,
1214 "", true /* dwarf64 */ )
1215 // Provide a CFA rule, because register rules require them.
1216 .D8(lul::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5)
1217 // Provide an offset(N) rule for register 0x0f9b8a1c.
1218 .D8(lul::DW_CFA_offset_extended)
1219 .ULEB128(0x0f9b8a1c).ULEB128(0xc979)
1220 .FinishEntry()
1221 // In the FDE...
1222 .FDEHeader(cie, fde_start, fde_size)
1223 // At a second address, provide a new offset(N) rule for reg 0x0f9b8a1c.
1224 .D8(lul::DW_CFA_advance_loc | 0x3)
1225 .D8(lul::DW_CFA_offset_extended)
1226 .ULEB128(0x0f9b8a1c).ULEB128(0x3b7b)
1227 // At a third address, restore the original rule for register 0x0f9b8a1c.
1228 .D8(lul::DW_CFA_advance_loc | 0x04)
1229 .D8(lul::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c)
1230 .FinishEntry();
1231
1232 {
1233 InSequence s;
1234 EXPECT_CALL(handler,
1235 Entry(_, fde_start, fde_size, version, "", return_register))
1236 .WillOnce(Return(true));
1237 // CIE's CFA rule.
1238 EXPECT_CALL(handler,
1239 ValOffsetRule(fde_start, kCFARegister, 0x56fa0edd, 0x097f78a5))
1240 .WillOnce(Return(true));
1241 // CIE's rule for register 0x0f9b8a1c.
1242 EXPECT_CALL(handler,
1243 OffsetRule(fde_start, 0x0f9b8a1c, kCFARegister,
1244 0xc979 * data_factor))
1245 .WillOnce(Return(true));
1246 // FDE's rule for register 0x0f9b8a1c.
1247 EXPECT_CALL(handler,
1248 OffsetRule(fde_start + 0x3 * code_factor, 0x0f9b8a1c,
1249 kCFARegister, 0x3b7b * data_factor))
1250 .WillOnce(Return(true));
1251 // Restore CIE's rule for register 0x0f9b8a1c.
1252 EXPECT_CALL(handler,
1253 OffsetRule(fde_start + (0x3 + 0x4) * code_factor, 0x0f9b8a1c,
1254 kCFARegister, 0xc979 * data_factor))
1255 .WillOnce(Return(true));
1256 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1257 }
1258
1259 ParseSection(§ion);
1260 }
1261
TEST_F(LulDwarfCFIInsn,DW_CFA_remember_and_restore_state)1262 TEST_F(LulDwarfCFIInsn, DW_CFA_remember_and_restore_state) {
1263 CFISection section(kLittleEndian, 8);
1264 StockCIEAndFDE(§ion);
1265
1266 // We create a state, save it, modify it, and then restore. We
1267 // refer to the state that is overridden the restore as the
1268 // "outgoing" state, and the restored state the "incoming" state.
1269 //
1270 // Register outgoing incoming expect
1271 // 1 offset(N) no rule new "same value" rule
1272 // 2 register(R) offset(N) report changed rule
1273 // 3 offset(N) offset(M) report changed offset
1274 // 4 offset(N) offset(N) no report
1275 // 5 offset(N) no rule new "same value" rule
1276 section
1277 // Create the "incoming" state, which we will save and later restore.
1278 .D8(lul::DW_CFA_offset | 2).ULEB128(0x9806)
1279 .D8(lul::DW_CFA_offset | 3).ULEB128(0x995d)
1280 .D8(lul::DW_CFA_offset | 4).ULEB128(0x7055)
1281 .D8(lul::DW_CFA_remember_state)
1282 // Advance to a new instruction; an implementation could legitimately
1283 // ignore all but the final rule for a given register at a given address.
1284 .D8(lul::DW_CFA_advance_loc | 1)
1285 // Create the "outgoing" state, which we will discard.
1286 .D8(lul::DW_CFA_offset | 1).ULEB128(0xea1a)
1287 .D8(lul::DW_CFA_register).ULEB128(2).ULEB128(0x1d2a3767)
1288 .D8(lul::DW_CFA_offset | 3).ULEB128(0xdd29)
1289 .D8(lul::DW_CFA_offset | 5).ULEB128(0xf1ce)
1290 // At a third address, restore the incoming state.
1291 .D8(lul::DW_CFA_advance_loc | 1)
1292 .D8(lul::DW_CFA_restore_state)
1293 .FinishEntry();
1294
1295 uint64 addr = fde_start;
1296
1297 // Expect the incoming rules to be reported.
1298 EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor))
1299 .InSequence(s).WillOnce(Return(true));
1300 EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor))
1301 .InSequence(s).WillOnce(Return(true));
1302 EXPECT_CALL(handler, OffsetRule(addr, 4, kCFARegister, 0x7055 * data_factor))
1303 .InSequence(s).WillOnce(Return(true));
1304
1305 addr += code_factor;
1306
1307 // After the save, we establish the outgoing rule set.
1308 EXPECT_CALL(handler, OffsetRule(addr, 1, kCFARegister, 0xea1a * data_factor))
1309 .InSequence(s).WillOnce(Return(true));
1310 EXPECT_CALL(handler, RegisterRule(addr, 2, 0x1d2a3767))
1311 .InSequence(s).WillOnce(Return(true));
1312 EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0xdd29 * data_factor))
1313 .InSequence(s).WillOnce(Return(true));
1314 EXPECT_CALL(handler, OffsetRule(addr, 5, kCFARegister, 0xf1ce * data_factor))
1315 .InSequence(s).WillOnce(Return(true));
1316
1317 addr += code_factor;
1318
1319 // Finally, after the restore, expect to see the differences from
1320 // the outgoing to the incoming rules reported.
1321 EXPECT_CALL(handler, SameValueRule(addr, 1))
1322 .InSequence(s).WillOnce(Return(true));
1323 EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor))
1324 .InSequence(s).WillOnce(Return(true));
1325 EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor))
1326 .InSequence(s).WillOnce(Return(true));
1327 EXPECT_CALL(handler, SameValueRule(addr, 5))
1328 .InSequence(s).WillOnce(Return(true));
1329
1330 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1331
1332 ParseSection(§ion);
1333 }
1334
1335 // Check that restoring a rule set reports changes to the CFA rule.
TEST_F(LulDwarfCFIInsn,DW_CFA_remember_and_restore_stateCFA)1336 TEST_F(LulDwarfCFIInsn, DW_CFA_remember_and_restore_stateCFA) {
1337 CFISection section(kBigEndian, 4);
1338 StockCIEAndFDE(§ion);
1339
1340 section
1341 .D8(lul::DW_CFA_remember_state)
1342 .D8(lul::DW_CFA_advance_loc | 1)
1343 .D8(lul::DW_CFA_def_cfa_offset).ULEB128(0x90481102)
1344 .D8(lul::DW_CFA_advance_loc | 1)
1345 .D8(lul::DW_CFA_restore_state)
1346 .FinishEntry();
1347
1348 EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, kCFARegister,
1349 cfa_base_register, 0x90481102))
1350 .InSequence(s).WillOnce(Return(true));
1351 EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor * 2, kCFARegister,
1352 cfa_base_register, cfa_offset))
1353 .InSequence(s).WillOnce(Return(true));
1354
1355 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1356
1357 ParseSection(§ion);
1358 }
1359
TEST_F(LulDwarfCFIInsn,DW_CFA_nop)1360 TEST_F(LulDwarfCFIInsn, DW_CFA_nop) {
1361 CFISection section(kLittleEndian, 4);
1362 StockCIEAndFDE(§ion);
1363 section
1364 .D8(lul::DW_CFA_nop)
1365 .D8(lul::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b)
1366 .D8(lul::DW_CFA_nop)
1367 .FinishEntry();
1368
1369 EXPECT_CALL(handler,
1370 ValOffsetRule(fde_start, kCFARegister, 0x3fb8d4f1, 0x078dc67b))
1371 .InSequence(s).WillOnce(Return(true));
1372 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1373
1374 ParseSection(§ion);
1375 }
1376
TEST_F(LulDwarfCFIInsn,DW_CFA_GNU_window_save)1377 TEST_F(LulDwarfCFIInsn, DW_CFA_GNU_window_save) {
1378 CFISection section(kBigEndian, 4);
1379 StockCIEAndFDE(§ion);
1380 section
1381 .D8(lul::DW_CFA_GNU_window_save)
1382 .FinishEntry();
1383
1384 // Don't include all the rules in any particular sequence.
1385
1386 // The caller's %o0-%o7 have become the callee's %i0-%i7. This is
1387 // the GCC register numbering.
1388 for (int i = 8; i < 16; i++)
1389 EXPECT_CALL(handler, RegisterRule(fde_start, i, i + 16))
1390 .WillOnce(Return(true));
1391 // The caller's %l0-%l7 and %i0-%i7 have been saved at the top of
1392 // its frame.
1393 for (int i = 16; i < 32; i++)
1394 EXPECT_CALL(handler, OffsetRule(fde_start, i, kCFARegister, (i-16) * 4))
1395 .WillOnce(Return(true));
1396
1397 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1398
1399 ParseSection(§ion);
1400 }
1401
TEST_F(LulDwarfCFIInsn,DW_CFA_GNU_args_size)1402 TEST_F(LulDwarfCFIInsn, DW_CFA_GNU_args_size) {
1403 CFISection section(kLittleEndian, 8);
1404 StockCIEAndFDE(§ion);
1405 section
1406 .D8(lul::DW_CFA_GNU_args_size).ULEB128(0xeddfa520)
1407 // Verify that we see this, meaning we parsed the above properly.
1408 .D8(lul::DW_CFA_offset | 0x23).ULEB128(0x269)
1409 .FinishEntry();
1410
1411 EXPECT_CALL(handler,
1412 OffsetRule(fde_start, 0x23, kCFARegister, 0x269 * data_factor))
1413 .InSequence(s).WillOnce(Return(true));
1414 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1415
1416 ParseSection(§ion);
1417 }
1418
TEST_F(LulDwarfCFIInsn,DW_CFA_GNU_negative_offset_extended)1419 TEST_F(LulDwarfCFIInsn, DW_CFA_GNU_negative_offset_extended) {
1420 CFISection section(kLittleEndian, 4);
1421 StockCIEAndFDE(§ion);
1422 section
1423 .D8(lul::DW_CFA_GNU_negative_offset_extended)
1424 .ULEB128(0x430cc87a).ULEB128(0x613)
1425 .FinishEntry();
1426
1427 EXPECT_CALL(handler,
1428 OffsetRule(fde_start, 0x430cc87a,
1429 kCFARegister, -0x613 * data_factor))
1430 .InSequence(s).WillOnce(Return(true));
1431 EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
1432
1433 ParseSection(§ion);
1434 }
1435
1436 // Three FDEs: skip the second
TEST_F(LulDwarfCFIInsn,SkipFDE)1437 TEST_F(LulDwarfCFIInsn, SkipFDE) {
1438 CFISection section(kBigEndian, 4);
1439 Label cie;
1440 section
1441 // CIE, used by all FDEs.
1442 .Mark(&cie)
1443 .CIEHeader(0x010269f2, 0x9177, 0xedca5849, 2, "")
1444 .D8(lul::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad)
1445 .FinishEntry()
1446 // First FDE.
1447 .FDEHeader(cie, 0xa870ebdd, 0x60f6aa4)
1448 .D8(lul::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf)
1449 .FinishEntry()
1450 // Second FDE.
1451 .FDEHeader(cie, 0xc534f7c0, 0xf6552e9, true /* dwarf64 */)
1452 .D8(lul::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18)
1453 .FinishEntry()
1454 // Third FDE.
1455 .FDEHeader(cie, 0xf681cfc8, 0x7e4594e)
1456 .D8(lul::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4)
1457 .FinishEntry();
1458
1459 {
1460 InSequence s;
1461
1462 // Process the first FDE.
1463 EXPECT_CALL(handler, Entry(_, 0xa870ebdd, 0x60f6aa4, 2, "", 0xedca5849))
1464 .WillOnce(Return(true));
1465 EXPECT_CALL(handler, ValOffsetRule(0xa870ebdd, kCFARegister,
1466 0x42ed390b, 0x98f43aad))
1467 .WillOnce(Return(true));
1468 EXPECT_CALL(handler, RegisterRule(0xa870ebdd, 0x3a860351, 0x6c9a6bcf))
1469 .WillOnce(Return(true));
1470 EXPECT_CALL(handler, End())
1471 .WillOnce(Return(true));
1472
1473 // Skip the second FDE.
1474 EXPECT_CALL(handler, Entry(_, 0xc534f7c0, 0xf6552e9, 2, "", 0xedca5849))
1475 .WillOnce(Return(false));
1476
1477 // Process the third FDE.
1478 EXPECT_CALL(handler, Entry(_, 0xf681cfc8, 0x7e4594e, 2, "", 0xedca5849))
1479 .WillOnce(Return(true));
1480 EXPECT_CALL(handler, ValOffsetRule(0xf681cfc8, kCFARegister,
1481 0x42ed390b, 0x98f43aad))
1482 .WillOnce(Return(true));
1483 EXPECT_CALL(handler, RegisterRule(0xf681cfc8, 0x26c53934, 0x18eeb8a4))
1484 .WillOnce(Return(true));
1485 EXPECT_CALL(handler, End())
1486 .WillOnce(Return(true));
1487 }
1488
1489 ParseSection(§ion);
1490 }
1491
1492 // Quit processing in the middle of an entry's instructions.
TEST_F(LulDwarfCFIInsn,QuitMidentry)1493 TEST_F(LulDwarfCFIInsn, QuitMidentry) {
1494 CFISection section(kLittleEndian, 8);
1495 StockCIEAndFDE(§ion);
1496 section
1497 .D8(lul::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431)
1498 .D8(lul::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat")
1499 .FinishEntry();
1500
1501 EXPECT_CALL(handler, RegisterRule(fde_start, 0xe0cf850d, 0x15aab431))
1502 .InSequence(s).WillOnce(Return(false));
1503 EXPECT_CALL(handler, End())
1504 .InSequence(s).WillOnce(Return(true));
1505
1506 ParseSection(§ion, false);
1507 }
1508
1509 class LulDwarfCFIRestore: public CFIInsnFixture, public Test { };
1510
TEST_F(LulDwarfCFIRestore,RestoreUndefinedRuleUnchanged)1511 TEST_F(LulDwarfCFIRestore, RestoreUndefinedRuleUnchanged) {
1512 CFISection section(kLittleEndian, 4);
1513 StockCIEAndFDE(§ion);
1514 section
1515 .D8(lul::DW_CFA_undefined).ULEB128(0x0bac878e)
1516 .D8(lul::DW_CFA_remember_state)
1517 .D8(lul::DW_CFA_advance_loc | 1)
1518 .D8(lul::DW_CFA_restore_state)
1519 .FinishEntry();
1520
1521 EXPECT_CALL(handler, UndefinedRule(fde_start, 0x0bac878e))
1522 .InSequence(s).WillOnce(Return(true));
1523 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1524
1525 ParseSection(§ion);
1526 }
1527
TEST_F(LulDwarfCFIRestore,RestoreUndefinedRuleChanged)1528 TEST_F(LulDwarfCFIRestore, RestoreUndefinedRuleChanged) {
1529 CFISection section(kLittleEndian, 4);
1530 StockCIEAndFDE(§ion);
1531 section
1532 .D8(lul::DW_CFA_undefined).ULEB128(0x7dedff5f)
1533 .D8(lul::DW_CFA_remember_state)
1534 .D8(lul::DW_CFA_advance_loc | 1)
1535 .D8(lul::DW_CFA_same_value).ULEB128(0x7dedff5f)
1536 .D8(lul::DW_CFA_advance_loc | 1)
1537 .D8(lul::DW_CFA_restore_state)
1538 .FinishEntry();
1539
1540 EXPECT_CALL(handler, UndefinedRule(fde_start, 0x7dedff5f))
1541 .InSequence(s).WillOnce(Return(true));
1542 EXPECT_CALL(handler, SameValueRule(fde_start + code_factor, 0x7dedff5f))
1543 .InSequence(s).WillOnce(Return(true));
1544 EXPECT_CALL(handler, UndefinedRule(fde_start + 2 * code_factor, 0x7dedff5f))
1545 .InSequence(s).WillOnce(Return(true));
1546 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1547
1548 ParseSection(§ion);
1549 }
1550
TEST_F(LulDwarfCFIRestore,RestoreSameValueRuleUnchanged)1551 TEST_F(LulDwarfCFIRestore, RestoreSameValueRuleUnchanged) {
1552 CFISection section(kLittleEndian, 4);
1553 StockCIEAndFDE(§ion);
1554 section
1555 .D8(lul::DW_CFA_same_value).ULEB128(0xadbc9b3a)
1556 .D8(lul::DW_CFA_remember_state)
1557 .D8(lul::DW_CFA_advance_loc | 1)
1558 .D8(lul::DW_CFA_restore_state)
1559 .FinishEntry();
1560
1561 EXPECT_CALL(handler, SameValueRule(fde_start, 0xadbc9b3a))
1562 .InSequence(s).WillOnce(Return(true));
1563 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1564
1565 ParseSection(§ion);
1566 }
1567
TEST_F(LulDwarfCFIRestore,RestoreSameValueRuleChanged)1568 TEST_F(LulDwarfCFIRestore, RestoreSameValueRuleChanged) {
1569 CFISection section(kLittleEndian, 4);
1570 StockCIEAndFDE(§ion);
1571 section
1572 .D8(lul::DW_CFA_same_value).ULEB128(0x3d90dcb5)
1573 .D8(lul::DW_CFA_remember_state)
1574 .D8(lul::DW_CFA_advance_loc | 1)
1575 .D8(lul::DW_CFA_undefined).ULEB128(0x3d90dcb5)
1576 .D8(lul::DW_CFA_advance_loc | 1)
1577 .D8(lul::DW_CFA_restore_state)
1578 .FinishEntry();
1579
1580 EXPECT_CALL(handler, SameValueRule(fde_start, 0x3d90dcb5))
1581 .InSequence(s).WillOnce(Return(true));
1582 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x3d90dcb5))
1583 .InSequence(s).WillOnce(Return(true));
1584 EXPECT_CALL(handler, SameValueRule(fde_start + 2 * code_factor, 0x3d90dcb5))
1585 .InSequence(s).WillOnce(Return(true));
1586 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1587
1588 ParseSection(§ion);
1589 }
1590
TEST_F(LulDwarfCFIRestore,RestoreOffsetRuleUnchanged)1591 TEST_F(LulDwarfCFIRestore, RestoreOffsetRuleUnchanged) {
1592 CFISection section(kLittleEndian, 4);
1593 StockCIEAndFDE(§ion);
1594 section
1595 .D8(lul::DW_CFA_offset | 0x14).ULEB128(0xb6f)
1596 .D8(lul::DW_CFA_remember_state)
1597 .D8(lul::DW_CFA_advance_loc | 1)
1598 .D8(lul::DW_CFA_restore_state)
1599 .FinishEntry();
1600
1601 EXPECT_CALL(handler, OffsetRule(fde_start, 0x14,
1602 kCFARegister, 0xb6f * data_factor))
1603 .InSequence(s).WillOnce(Return(true));
1604 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1605
1606 ParseSection(§ion);
1607 }
1608
TEST_F(LulDwarfCFIRestore,RestoreOffsetRuleChanged)1609 TEST_F(LulDwarfCFIRestore, RestoreOffsetRuleChanged) {
1610 CFISection section(kLittleEndian, 4);
1611 StockCIEAndFDE(§ion);
1612 section
1613 .D8(lul::DW_CFA_offset | 0x21).ULEB128(0xeb7)
1614 .D8(lul::DW_CFA_remember_state)
1615 .D8(lul::DW_CFA_advance_loc | 1)
1616 .D8(lul::DW_CFA_undefined).ULEB128(0x21)
1617 .D8(lul::DW_CFA_advance_loc | 1)
1618 .D8(lul::DW_CFA_restore_state)
1619 .FinishEntry();
1620
1621 EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
1622 kCFARegister, 0xeb7 * data_factor))
1623 .InSequence(s).WillOnce(Return(true));
1624 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x21))
1625 .InSequence(s).WillOnce(Return(true));
1626 EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21,
1627 kCFARegister, 0xeb7 * data_factor))
1628 .InSequence(s).WillOnce(Return(true));
1629 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1630
1631 ParseSection(§ion);
1632 }
1633
TEST_F(LulDwarfCFIRestore,RestoreOffsetRuleChangedOffset)1634 TEST_F(LulDwarfCFIRestore, RestoreOffsetRuleChangedOffset) {
1635 CFISection section(kLittleEndian, 4);
1636 StockCIEAndFDE(§ion);
1637 section
1638 .D8(lul::DW_CFA_offset | 0x21).ULEB128(0x134)
1639 .D8(lul::DW_CFA_remember_state)
1640 .D8(lul::DW_CFA_advance_loc | 1)
1641 .D8(lul::DW_CFA_offset | 0x21).ULEB128(0xf4f)
1642 .D8(lul::DW_CFA_advance_loc | 1)
1643 .D8(lul::DW_CFA_restore_state)
1644 .FinishEntry();
1645
1646 EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
1647 kCFARegister, 0x134 * data_factor))
1648 .InSequence(s).WillOnce(Return(true));
1649 EXPECT_CALL(handler, OffsetRule(fde_start + code_factor, 0x21,
1650 kCFARegister, 0xf4f * data_factor))
1651 .InSequence(s).WillOnce(Return(true));
1652 EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21,
1653 kCFARegister, 0x134 * data_factor))
1654 .InSequence(s).WillOnce(Return(true));
1655 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1656
1657 ParseSection(§ion);
1658 }
1659
TEST_F(LulDwarfCFIRestore,RestoreValOffsetRuleUnchanged)1660 TEST_F(LulDwarfCFIRestore, RestoreValOffsetRuleUnchanged) {
1661 CFISection section(kLittleEndian, 4);
1662 StockCIEAndFDE(§ion);
1663 section
1664 .D8(lul::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c)
1665 .D8(lul::DW_CFA_remember_state)
1666 .D8(lul::DW_CFA_advance_loc | 1)
1667 .D8(lul::DW_CFA_restore_state)
1668 .FinishEntry();
1669
1670 EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x829caee6,
1671 kCFARegister, 0xe4c * data_factor))
1672 .InSequence(s).WillOnce(Return(true));
1673 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1674
1675 ParseSection(§ion);
1676 }
1677
TEST_F(LulDwarfCFIRestore,RestoreValOffsetRuleChanged)1678 TEST_F(LulDwarfCFIRestore, RestoreValOffsetRuleChanged) {
1679 CFISection section(kLittleEndian, 4);
1680 StockCIEAndFDE(§ion);
1681 section
1682 .D8(lul::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7)
1683 .D8(lul::DW_CFA_remember_state)
1684 .D8(lul::DW_CFA_advance_loc | 1)
1685 .D8(lul::DW_CFA_undefined).ULEB128(0xf17c36d6)
1686 .D8(lul::DW_CFA_advance_loc | 1)
1687 .D8(lul::DW_CFA_restore_state)
1688 .FinishEntry();
1689
1690 EXPECT_CALL(handler, ValOffsetRule(fde_start, 0xf17c36d6,
1691 kCFARegister, 0xeb7 * data_factor))
1692 .InSequence(s).WillOnce(Return(true));
1693 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xf17c36d6))
1694 .InSequence(s).WillOnce(Return(true));
1695 EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0xf17c36d6,
1696 kCFARegister, 0xeb7 * data_factor))
1697 .InSequence(s).WillOnce(Return(true));
1698 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1699
1700 ParseSection(§ion);
1701 }
1702
TEST_F(LulDwarfCFIRestore,RestoreValOffsetRuleChangedValOffset)1703 TEST_F(LulDwarfCFIRestore, RestoreValOffsetRuleChangedValOffset) {
1704 CFISection section(kLittleEndian, 4);
1705 StockCIEAndFDE(§ion);
1706 section
1707 .D8(lul::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562)
1708 .D8(lul::DW_CFA_remember_state)
1709 .D8(lul::DW_CFA_advance_loc | 1)
1710 .D8(lul::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88)
1711 .D8(lul::DW_CFA_advance_loc | 1)
1712 .D8(lul::DW_CFA_restore_state)
1713 .FinishEntry();
1714
1715 EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x2cf0ab1b,
1716 kCFARegister, 0x562 * data_factor))
1717 .InSequence(s).WillOnce(Return(true));
1718 EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, 0x2cf0ab1b,
1719 kCFARegister, 0xe88 * data_factor))
1720 .InSequence(s).WillOnce(Return(true));
1721 EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0x2cf0ab1b,
1722 kCFARegister, 0x562 * data_factor))
1723 .InSequence(s).WillOnce(Return(true));
1724 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1725
1726 ParseSection(§ion);
1727 }
1728
TEST_F(LulDwarfCFIRestore,RestoreRegisterRuleUnchanged)1729 TEST_F(LulDwarfCFIRestore, RestoreRegisterRuleUnchanged) {
1730 CFISection section(kLittleEndian, 4);
1731 StockCIEAndFDE(§ion);
1732 section
1733 .D8(lul::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce)
1734 .D8(lul::DW_CFA_remember_state)
1735 .D8(lul::DW_CFA_advance_loc | 1)
1736 .D8(lul::DW_CFA_restore_state)
1737 .FinishEntry();
1738
1739 EXPECT_CALL(handler, RegisterRule(fde_start, 0x77514acc, 0x464de4ce))
1740 .InSequence(s).WillOnce(Return(true));
1741 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1742
1743 ParseSection(§ion);
1744 }
1745
TEST_F(LulDwarfCFIRestore,RestoreRegisterRuleChanged)1746 TEST_F(LulDwarfCFIRestore, RestoreRegisterRuleChanged) {
1747 CFISection section(kLittleEndian, 4);
1748 StockCIEAndFDE(§ion);
1749 section
1750 .D8(lul::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559)
1751 .D8(lul::DW_CFA_remember_state)
1752 .D8(lul::DW_CFA_advance_loc | 1)
1753 .D8(lul::DW_CFA_undefined).ULEB128(0xe39acce5)
1754 .D8(lul::DW_CFA_advance_loc | 1)
1755 .D8(lul::DW_CFA_restore_state)
1756 .FinishEntry();
1757
1758 EXPECT_CALL(handler, RegisterRule(fde_start, 0xe39acce5, 0x095f1559))
1759 .InSequence(s).WillOnce(Return(true));
1760 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xe39acce5))
1761 .InSequence(s).WillOnce(Return(true));
1762 EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xe39acce5,
1763 0x095f1559))
1764 .InSequence(s).WillOnce(Return(true));
1765 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1766
1767 ParseSection(§ion);
1768 }
1769
TEST_F(LulDwarfCFIRestore,RestoreRegisterRuleChangedRegister)1770 TEST_F(LulDwarfCFIRestore, RestoreRegisterRuleChangedRegister) {
1771 CFISection section(kLittleEndian, 4);
1772 StockCIEAndFDE(§ion);
1773 section
1774 .D8(lul::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a)
1775 .D8(lul::DW_CFA_remember_state)
1776 .D8(lul::DW_CFA_advance_loc | 1)
1777 .D8(lul::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742)
1778 .D8(lul::DW_CFA_advance_loc | 1)
1779 .D8(lul::DW_CFA_restore_state)
1780 .FinishEntry();
1781
1782 EXPECT_CALL(handler, RegisterRule(fde_start, 0xd40e21b1, 0x16607d6a))
1783 .InSequence(s).WillOnce(Return(true));
1784 EXPECT_CALL(handler, RegisterRule(fde_start + code_factor, 0xd40e21b1,
1785 0xbabb4742))
1786 .InSequence(s).WillOnce(Return(true));
1787 EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xd40e21b1,
1788 0x16607d6a))
1789 .InSequence(s).WillOnce(Return(true));
1790 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1791
1792 ParseSection(§ion);
1793 }
1794
TEST_F(LulDwarfCFIRestore,RestoreExpressionRuleUnchanged)1795 TEST_F(LulDwarfCFIRestore, RestoreExpressionRuleUnchanged) {
1796 ByteReader reader(ENDIANNESS_LITTLE);
1797 CFISection section(kLittleEndian, 4);
1798 StockCIEAndFDE(§ion);
1799 section
1800 .D8(lul::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf")
1801 .D8(lul::DW_CFA_remember_state)
1802 .D8(lul::DW_CFA_advance_loc | 1)
1803 .D8(lul::DW_CFA_restore_state)
1804 .FinishEntry();
1805
1806 EXPECT_CALL(handler, ExpressionRule(fde_start, 0x666ae152, "dwarf"))
1807 .InSequence(s).WillOnce(Return(true));
1808 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1809
1810 ParseSection(§ion, true, &reader);
1811 }
1812
TEST_F(LulDwarfCFIRestore,RestoreExpressionRuleChanged)1813 TEST_F(LulDwarfCFIRestore, RestoreExpressionRuleChanged) {
1814 ByteReader reader(ENDIANNESS_LITTLE);
1815 CFISection section(kLittleEndian, 4);
1816 StockCIEAndFDE(§ion);
1817 section
1818 .D8(lul::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf")
1819 .D8(lul::DW_CFA_remember_state)
1820 .D8(lul::DW_CFA_advance_loc | 1)
1821 .D8(lul::DW_CFA_undefined).ULEB128(0xb5ca5c46)
1822 .D8(lul::DW_CFA_advance_loc | 1)
1823 .D8(lul::DW_CFA_restore_state)
1824 .FinishEntry();
1825
1826 EXPECT_CALL(handler, ExpressionRule(fde_start, 0xb5ca5c46, "elf"))
1827 .InSequence(s).WillOnce(Return(true));
1828 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46))
1829 .InSequence(s).WillOnce(Return(true));
1830 EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46,
1831 "elf"))
1832 .InSequence(s).WillOnce(Return(true));
1833 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1834
1835 ParseSection(§ion, true, &reader);
1836 }
1837
TEST_F(LulDwarfCFIRestore,RestoreExpressionRuleChangedExpression)1838 TEST_F(LulDwarfCFIRestore, RestoreExpressionRuleChangedExpression) {
1839 ByteReader reader(ENDIANNESS_LITTLE);
1840 CFISection section(kLittleEndian, 4);
1841 StockCIEAndFDE(§ion);
1842 section
1843 .D8(lul::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf")
1844 .D8(lul::DW_CFA_remember_state)
1845 .D8(lul::DW_CFA_advance_loc | 1)
1846 .D8(lul::DW_CFA_expression).ULEB128(0x500f5739).Block("orc")
1847 .D8(lul::DW_CFA_advance_loc | 1)
1848 .D8(lul::DW_CFA_restore_state)
1849 .FinishEntry();
1850
1851 EXPECT_CALL(handler, ExpressionRule(fde_start, 0x500f5739, "smurf"))
1852 .InSequence(s).WillOnce(Return(true));
1853 EXPECT_CALL(handler, ExpressionRule(fde_start + code_factor, 0x500f5739,
1854 "orc"))
1855 .InSequence(s).WillOnce(Return(true));
1856 // Expectations are not wishes.
1857 EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0x500f5739,
1858 "smurf"))
1859 .InSequence(s).WillOnce(Return(true));
1860 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1861
1862 ParseSection(§ion, true, &reader);
1863 }
1864
TEST_F(LulDwarfCFIRestore,RestoreValExpressionRuleUnchanged)1865 TEST_F(LulDwarfCFIRestore, RestoreValExpressionRuleUnchanged) {
1866 ByteReader reader(ENDIANNESS_LITTLE);
1867 CFISection section(kLittleEndian, 4);
1868 StockCIEAndFDE(§ion);
1869 section
1870 .D8(lul::DW_CFA_val_expression).ULEB128(0x666ae152)
1871 .Block("hideous")
1872 .D8(lul::DW_CFA_remember_state)
1873 .D8(lul::DW_CFA_advance_loc | 1)
1874 .D8(lul::DW_CFA_restore_state)
1875 .FinishEntry();
1876
1877 EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x666ae152, "hideous"))
1878 .InSequence(s).WillOnce(Return(true));
1879 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1880
1881 ParseSection(§ion, true, &reader);
1882 }
1883
TEST_F(LulDwarfCFIRestore,RestoreValExpressionRuleChanged)1884 TEST_F(LulDwarfCFIRestore, RestoreValExpressionRuleChanged) {
1885 ByteReader reader(ENDIANNESS_LITTLE);
1886 CFISection section(kLittleEndian, 4);
1887 StockCIEAndFDE(§ion);
1888 section
1889 .D8(lul::DW_CFA_val_expression).ULEB128(0xb5ca5c46)
1890 .Block("revolting")
1891 .D8(lul::DW_CFA_remember_state)
1892 .D8(lul::DW_CFA_advance_loc | 1)
1893 .D8(lul::DW_CFA_undefined).ULEB128(0xb5ca5c46)
1894 .D8(lul::DW_CFA_advance_loc | 1)
1895 .D8(lul::DW_CFA_restore_state)
1896 .FinishEntry();
1897
1898 PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChanged", section);
1899
1900 EXPECT_CALL(handler, ValExpressionRule(fde_start, 0xb5ca5c46, "revolting"))
1901 .InSequence(s).WillOnce(Return(true));
1902 EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46))
1903 .InSequence(s).WillOnce(Return(true));
1904 EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46,
1905 "revolting"))
1906 .InSequence(s).WillOnce(Return(true));
1907 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1908
1909 ParseSection(§ion, true, &reader);
1910 }
1911
TEST_F(LulDwarfCFIRestore,RestoreValExpressionRuleChangedValExpression)1912 TEST_F(LulDwarfCFIRestore, RestoreValExpressionRuleChangedValExpression) {
1913 ByteReader reader(ENDIANNESS_LITTLE);
1914 CFISection section(kLittleEndian, 4);
1915 StockCIEAndFDE(§ion);
1916 section
1917 .D8(lul::DW_CFA_val_expression).ULEB128(0x500f5739)
1918 .Block("repulsive")
1919 .D8(lul::DW_CFA_remember_state)
1920 .D8(lul::DW_CFA_advance_loc | 1)
1921 .D8(lul::DW_CFA_val_expression).ULEB128(0x500f5739)
1922 .Block("nauseous")
1923 .D8(lul::DW_CFA_advance_loc | 1)
1924 .D8(lul::DW_CFA_restore_state)
1925 .FinishEntry();
1926
1927 PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChangedValExpression",
1928 section);
1929
1930 EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x500f5739, "repulsive"))
1931 .InSequence(s).WillOnce(Return(true));
1932 EXPECT_CALL(handler, ValExpressionRule(fde_start + code_factor, 0x500f5739,
1933 "nauseous"))
1934 .InSequence(s).WillOnce(Return(true));
1935 // Expectations are not wishes.
1936 EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0x500f5739,
1937 "repulsive"))
1938 .InSequence(s).WillOnce(Return(true));
1939 EXPECT_CALL(handler, End()).WillOnce(Return(true));
1940
1941 ParseSection(§ion, true, &reader);
1942 }
1943
1944 struct EHFrameFixture: public CFIInsnFixture {
EHFrameFixturelul::EHFrameFixture1945 EHFrameFixture()
1946 : CFIInsnFixture(), section(kBigEndian, 4, true) {
1947 encoded_pointer_bases.cfi = 0x7f496cb2;
1948 encoded_pointer_bases.text = 0x540f67b6;
1949 encoded_pointer_bases.data = 0xe3eab768;
1950 section.SetEncodedPointerBases(encoded_pointer_bases);
1951 }
1952 CFISection section;
1953 CFISection::EncodedPointerBases encoded_pointer_bases;
1954
1955 // Parse CFIInsnFixture::ParseSection, but parse the section as
1956 // .eh_frame data, supplying stock base addresses.
ParseEHFrameSectionlul::EHFrameFixture1957 void ParseEHFrameSection(CFISection *section, bool succeeds = true) {
1958 EXPECT_TRUE(section->ContainsEHFrame());
1959 string contents;
1960 EXPECT_TRUE(section->GetContents(&contents));
1961 lul::Endianness endianness;
1962 if (section->endianness() == kBigEndian)
1963 endianness = ENDIANNESS_BIG;
1964 else {
1965 assert(section->endianness() == kLittleEndian);
1966 endianness = ENDIANNESS_LITTLE;
1967 }
1968 ByteReader reader(endianness);
1969 reader.SetAddressSize(section->AddressSize());
1970 reader.SetCFIDataBase(encoded_pointer_bases.cfi, contents.data());
1971 reader.SetTextBase(encoded_pointer_bases.text);
1972 reader.SetDataBase(encoded_pointer_bases.data);
1973 CallFrameInfo parser(contents.data(), contents.size(),
1974 &reader, &handler, &reporter, true);
1975 if (succeeds)
1976 EXPECT_TRUE(parser.Start());
1977 else
1978 EXPECT_FALSE(parser.Start());
1979 }
1980
1981 };
1982
1983 class LulDwarfEHFrame: public EHFrameFixture, public Test { };
1984
1985 // A simple CIE, an FDE, and a terminator.
TEST_F(LulDwarfEHFrame,Terminator)1986 TEST_F(LulDwarfEHFrame, Terminator) {
1987 Label cie;
1988 section
1989 .Mark(&cie)
1990 .CIEHeader(9968, 2466, 67, 1, "")
1991 .D8(lul::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372)
1992 .FinishEntry()
1993 .FDEHeader(cie, 0x848037a1, 0x7b30475e)
1994 .D8(lul::DW_CFA_set_loc).D32(0x17713850)
1995 .D8(lul::DW_CFA_undefined).ULEB128(5721)
1996 .FinishEntry()
1997 .D32(0) // Terminate the sequence.
1998 // This FDE should be ignored.
1999 .FDEHeader(cie, 0xf19629fe, 0x439fb09b)
2000 .FinishEntry();
2001
2002 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.Terminator", section);
2003
2004 EXPECT_CALL(handler, Entry(_, 0x848037a1, 0x7b30475e, 1, "", 67))
2005 .InSequence(s).WillOnce(Return(true));
2006 EXPECT_CALL(handler, ValOffsetRule(0x848037a1, kCFARegister, 3772, 1372))
2007 .InSequence(s).WillOnce(Return(true));
2008 EXPECT_CALL(handler, UndefinedRule(0x17713850, 5721))
2009 .InSequence(s).WillOnce(Return(true));
2010 EXPECT_CALL(handler, End())
2011 .InSequence(s).WillOnce(Return(true));
2012 EXPECT_CALL(reporter, EarlyEHTerminator(_))
2013 .InSequence(s).WillOnce(Return());
2014
2015 ParseEHFrameSection(§ion);
2016 }
2017
2018 // The parser should recognize the Linux Standards Base 'z' augmentations.
TEST_F(LulDwarfEHFrame,SimpleFDE)2019 TEST_F(LulDwarfEHFrame, SimpleFDE) {
2020 lul::DwarfPointerEncoding lsda_encoding =
2021 lul::DwarfPointerEncoding(lul::DW_EH_PE_indirect
2022 | lul::DW_EH_PE_datarel
2023 | lul::DW_EH_PE_sdata2);
2024 lul::DwarfPointerEncoding fde_encoding =
2025 lul::DwarfPointerEncoding(lul::DW_EH_PE_textrel
2026 | lul::DW_EH_PE_udata2);
2027
2028 section.SetPointerEncoding(fde_encoding);
2029 section.SetEncodedPointerBases(encoded_pointer_bases);
2030 Label cie;
2031 section
2032 .Mark(&cie)
2033 .CIEHeader(4873, 7012, 100, 1, "zSLPR")
2034 .ULEB128(7) // Augmentation data length
2035 .D8(lsda_encoding) // LSDA pointer format
2036 .D8(lul::DW_EH_PE_pcrel) // personality pointer format
2037 .EncodedPointer(0x97baa00, lul::DW_EH_PE_pcrel) // and value
2038 .D8(fde_encoding) // FDE pointer format
2039 .D8(lul::DW_CFA_def_cfa).ULEB128(6706).ULEB128(31)
2040 .FinishEntry()
2041 .FDEHeader(cie, 0x540f6b56, 0xf686)
2042 .ULEB128(2) // Augmentation data length
2043 .EncodedPointer(0xe3eab475, lsda_encoding) // LSDA pointer, signed
2044 .D8(lul::DW_CFA_set_loc)
2045 .EncodedPointer(0x540fa4ce, fde_encoding)
2046 .D8(lul::DW_CFA_undefined).ULEB128(0x675e)
2047 .FinishEntry()
2048 .D32(0); // terminator
2049
2050 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.SimpleFDE", section);
2051
2052 EXPECT_CALL(handler, Entry(_, 0x540f6b56, 0xf686, 1, "zSLPR", 100))
2053 .InSequence(s).WillOnce(Return(true));
2054 EXPECT_CALL(handler, PersonalityRoutine(0x97baa00, false))
2055 .InSequence(s).WillOnce(Return(true));
2056 EXPECT_CALL(handler, LanguageSpecificDataArea(0xe3eab475, true))
2057 .InSequence(s).WillOnce(Return(true));
2058 EXPECT_CALL(handler, SignalHandler())
2059 .InSequence(s).WillOnce(Return(true));
2060 EXPECT_CALL(handler, ValOffsetRule(0x540f6b56, kCFARegister, 6706, 31))
2061 .InSequence(s).WillOnce(Return(true));
2062 EXPECT_CALL(handler, UndefinedRule(0x540fa4ce, 0x675e))
2063 .InSequence(s).WillOnce(Return(true));
2064 EXPECT_CALL(handler, End())
2065 .InSequence(s).WillOnce(Return(true));
2066
2067 ParseEHFrameSection(§ion);
2068 }
2069
2070 // Check that we can handle an empty 'z' augmentation.
TEST_F(LulDwarfEHFrame,EmptyZ)2071 TEST_F(LulDwarfEHFrame, EmptyZ) {
2072 Label cie;
2073 section
2074 .Mark(&cie)
2075 .CIEHeader(5955, 5805, 228, 1, "z")
2076 .ULEB128(0) // Augmentation data length
2077 .D8(lul::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247)
2078 .FinishEntry()
2079 .FDEHeader(cie, 0xda007738, 0xfb55c641)
2080 .ULEB128(0) // Augmentation data length
2081 .D8(lul::DW_CFA_advance_loc1).D8(11)
2082 .D8(lul::DW_CFA_undefined).ULEB128(3769)
2083 .FinishEntry();
2084
2085 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.EmptyZ", section);
2086
2087 EXPECT_CALL(handler, Entry(_, 0xda007738, 0xfb55c641, 1, "z", 228))
2088 .InSequence(s).WillOnce(Return(true));
2089 EXPECT_CALL(handler, ValOffsetRule(0xda007738, kCFARegister, 3629, 247))
2090 .InSequence(s).WillOnce(Return(true));
2091 EXPECT_CALL(handler, UndefinedRule(0xda007738 + 11 * 5955, 3769))
2092 .InSequence(s).WillOnce(Return(true));
2093 EXPECT_CALL(handler, End())
2094 .InSequence(s).WillOnce(Return(true));
2095
2096 ParseEHFrameSection(§ion);
2097 }
2098
2099 // Check that we recognize bad 'z' augmentation characters.
TEST_F(LulDwarfEHFrame,BadZ)2100 TEST_F(LulDwarfEHFrame, BadZ) {
2101 Label cie;
2102 section
2103 .Mark(&cie)
2104 .CIEHeader(6937, 1045, 142, 1, "zQ")
2105 .ULEB128(0) // Augmentation data length
2106 .D8(lul::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725)
2107 .FinishEntry()
2108 .FDEHeader(cie, 0x1293efa8, 0x236f53f2)
2109 .ULEB128(0) // Augmentation data length
2110 .D8(lul::DW_CFA_advance_loc | 12)
2111 .D8(lul::DW_CFA_register).ULEB128(5667).ULEB128(3462)
2112 .FinishEntry();
2113
2114 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.BadZ", section);
2115
2116 EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "zQ"))
2117 .WillOnce(Return());
2118
2119 ParseEHFrameSection(§ion, false);
2120 }
2121
TEST_F(LulDwarfEHFrame,zL)2122 TEST_F(LulDwarfEHFrame, zL) {
2123 Label cie;
2124 lul::DwarfPointerEncoding lsda_encoding =
2125 lul::DwarfPointerEncoding(lul::DW_EH_PE_funcrel | lul::DW_EH_PE_udata2);
2126 section
2127 .Mark(&cie)
2128 .CIEHeader(9285, 9959, 54, 1, "zL")
2129 .ULEB128(1) // Augmentation data length
2130 .D8(lsda_encoding) // encoding for LSDA pointer in FDE
2131
2132 .FinishEntry()
2133 .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
2134 .ULEB128(2) // Augmentation data length
2135 .EncodedPointer(0xd40099cd, lsda_encoding) // LSDA pointer
2136 .FinishEntry()
2137 .D32(0); // terminator
2138
2139 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zL", section);
2140
2141 EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zL", 54))
2142 .InSequence(s).WillOnce(Return(true));
2143 EXPECT_CALL(handler, LanguageSpecificDataArea(0xd40099cd, false))
2144 .InSequence(s).WillOnce(Return(true));
2145 EXPECT_CALL(handler, End())
2146 .InSequence(s).WillOnce(Return(true));
2147
2148 ParseEHFrameSection(§ion);
2149 }
2150
TEST_F(LulDwarfEHFrame,zP)2151 TEST_F(LulDwarfEHFrame, zP) {
2152 Label cie;
2153 lul::DwarfPointerEncoding personality_encoding =
2154 lul::DwarfPointerEncoding(lul::DW_EH_PE_datarel | lul::DW_EH_PE_udata2);
2155 section
2156 .Mark(&cie)
2157 .CIEHeader(1097, 6313, 17, 1, "zP")
2158 .ULEB128(3) // Augmentation data length
2159 .D8(personality_encoding) // encoding for personality routine
2160 .EncodedPointer(0xe3eaccac, personality_encoding) // value
2161 .FinishEntry()
2162 .FDEHeader(cie, 0x0c8350c9, 0xbef11087)
2163 .ULEB128(0) // Augmentation data length
2164 .FinishEntry()
2165 .D32(0); // terminator
2166
2167 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zP", section);
2168
2169 EXPECT_CALL(handler, Entry(_, 0x0c8350c9, 0xbef11087, 1, "zP", 17))
2170 .InSequence(s).WillOnce(Return(true));
2171 EXPECT_CALL(handler, PersonalityRoutine(0xe3eaccac, false))
2172 .InSequence(s).WillOnce(Return(true));
2173 EXPECT_CALL(handler, End())
2174 .InSequence(s).WillOnce(Return(true));
2175
2176 ParseEHFrameSection(§ion);
2177 }
2178
TEST_F(LulDwarfEHFrame,zR)2179 TEST_F(LulDwarfEHFrame, zR) {
2180 Label cie;
2181 lul::DwarfPointerEncoding pointer_encoding =
2182 lul::DwarfPointerEncoding(lul::DW_EH_PE_textrel | lul::DW_EH_PE_sdata2);
2183 section.SetPointerEncoding(pointer_encoding);
2184 section
2185 .Mark(&cie)
2186 .CIEHeader(8011, 5496, 75, 1, "zR")
2187 .ULEB128(1) // Augmentation data length
2188 .D8(pointer_encoding) // encoding for FDE addresses
2189 .FinishEntry()
2190 .FDEHeader(cie, 0x540f9431, 0xbd0)
2191 .ULEB128(0) // Augmentation data length
2192 .FinishEntry()
2193 .D32(0); // terminator
2194
2195 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zR", section);
2196
2197 EXPECT_CALL(handler, Entry(_, 0x540f9431, 0xbd0, 1, "zR", 75))
2198 .InSequence(s).WillOnce(Return(true));
2199 EXPECT_CALL(handler, End())
2200 .InSequence(s).WillOnce(Return(true));
2201
2202 ParseEHFrameSection(§ion);
2203 }
2204
TEST_F(LulDwarfEHFrame,zS)2205 TEST_F(LulDwarfEHFrame, zS) {
2206 Label cie;
2207 section
2208 .Mark(&cie)
2209 .CIEHeader(9217, 7694, 57, 1, "zS")
2210 .ULEB128(0) // Augmentation data length
2211 .FinishEntry()
2212 .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
2213 .ULEB128(0) // Augmentation data length
2214 .FinishEntry()
2215 .D32(0); // terminator
2216
2217 PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zS", section);
2218
2219 EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zS", 57))
2220 .InSequence(s).WillOnce(Return(true));
2221 EXPECT_CALL(handler, SignalHandler())
2222 .InSequence(s).WillOnce(Return(true));
2223 EXPECT_CALL(handler, End())
2224 .InSequence(s).WillOnce(Return(true));
2225
2226 ParseEHFrameSection(§ion);
2227 }
2228
2229 // These tests require manual inspection of the test output.
2230 struct CFIReporterFixture {
CFIReporterFixturelul::CFIReporterFixture2231 CFIReporterFixture() : reporter(gtest_logging_sink_for_LulTestDwarf,
2232 "test file name", "test section name") { }
2233 CallFrameInfo::Reporter reporter;
2234 };
2235
2236 class LulDwarfCFIReporter: public CFIReporterFixture, public Test { };
2237
TEST_F(LulDwarfCFIReporter,Incomplete)2238 TEST_F(LulDwarfCFIReporter, Incomplete) {
2239 reporter.Incomplete(0x0102030405060708ULL, CallFrameInfo::kUnknown);
2240 }
2241
TEST_F(LulDwarfCFIReporter,EarlyEHTerminator)2242 TEST_F(LulDwarfCFIReporter, EarlyEHTerminator) {
2243 reporter.EarlyEHTerminator(0x0102030405060708ULL);
2244 }
2245
TEST_F(LulDwarfCFIReporter,CIEPointerOutOfRange)2246 TEST_F(LulDwarfCFIReporter, CIEPointerOutOfRange) {
2247 reporter.CIEPointerOutOfRange(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
2248 }
2249
TEST_F(LulDwarfCFIReporter,BadCIEId)2250 TEST_F(LulDwarfCFIReporter, BadCIEId) {
2251 reporter.BadCIEId(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
2252 }
2253
TEST_F(LulDwarfCFIReporter,UnrecognizedVersion)2254 TEST_F(LulDwarfCFIReporter, UnrecognizedVersion) {
2255 reporter.UnrecognizedVersion(0x0123456789abcdefULL, 43);
2256 }
2257
TEST_F(LulDwarfCFIReporter,UnrecognizedAugmentation)2258 TEST_F(LulDwarfCFIReporter, UnrecognizedAugmentation) {
2259 reporter.UnrecognizedAugmentation(0x0123456789abcdefULL, "poodles");
2260 }
2261
TEST_F(LulDwarfCFIReporter,InvalidPointerEncoding)2262 TEST_F(LulDwarfCFIReporter, InvalidPointerEncoding) {
2263 reporter.InvalidPointerEncoding(0x0123456789abcdefULL, 0x42);
2264 }
2265
TEST_F(LulDwarfCFIReporter,UnusablePointerEncoding)2266 TEST_F(LulDwarfCFIReporter, UnusablePointerEncoding) {
2267 reporter.UnusablePointerEncoding(0x0123456789abcdefULL, 0x42);
2268 }
2269
TEST_F(LulDwarfCFIReporter,RestoreInCIE)2270 TEST_F(LulDwarfCFIReporter, RestoreInCIE) {
2271 reporter.RestoreInCIE(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
2272 }
2273
TEST_F(LulDwarfCFIReporter,BadInstruction)2274 TEST_F(LulDwarfCFIReporter, BadInstruction) {
2275 reporter.BadInstruction(0x0123456789abcdefULL, CallFrameInfo::kFDE,
2276 0xfedcba9876543210ULL);
2277 }
2278
TEST_F(LulDwarfCFIReporter,NoCFARule)2279 TEST_F(LulDwarfCFIReporter, NoCFARule) {
2280 reporter.NoCFARule(0x0123456789abcdefULL, CallFrameInfo::kCIE,
2281 0xfedcba9876543210ULL);
2282 }
2283
TEST_F(LulDwarfCFIReporter,EmptyStateStack)2284 TEST_F(LulDwarfCFIReporter, EmptyStateStack) {
2285 reporter.EmptyStateStack(0x0123456789abcdefULL, CallFrameInfo::kTerminator,
2286 0xfedcba9876543210ULL);
2287 }
2288
TEST_F(LulDwarfCFIReporter,ClearingCFARule)2289 TEST_F(LulDwarfCFIReporter, ClearingCFARule) {
2290 reporter.ClearingCFARule(0x0123456789abcdefULL, CallFrameInfo::kFDE,
2291 0xfedcba9876543210ULL);
2292 }
2293 class LulDwarfExpr : public Test { };
2294
2295 class MockSummariser : public Summariser {
2296 public:
MockSummariser()2297 MockSummariser() : Summariser(nullptr, 0, nullptr) {}
2298 MOCK_METHOD2(Entry, void(uintptr_t, uintptr_t));
2299 MOCK_METHOD0(End, void());
2300 MOCK_METHOD5(Rule, void(uintptr_t, int, LExprHow, int16_t, int64_t));
2301 MOCK_METHOD1(AddPfxInstr, uint32_t(PfxInstr));
2302 };
2303
TEST_F(LulDwarfExpr,SimpleTransliteration)2304 TEST_F(LulDwarfExpr, SimpleTransliteration) {
2305 MockSummariser summ;
2306 ByteReader reader(ENDIANNESS_LITTLE);
2307
2308 CFISection section(kLittleEndian, 8);
2309 section
2310 .D8(DW_OP_lit0)
2311 .D8(DW_OP_lit31)
2312 .D8(DW_OP_breg0 + 17).LEB128(-1234)
2313 .D8(DW_OP_const4s).D32(0xFEDC9876)
2314 .D8(DW_OP_deref)
2315 .D8(DW_OP_and)
2316 .D8(DW_OP_plus)
2317 .D8(DW_OP_minus)
2318 .D8(DW_OP_shl)
2319 .D8(DW_OP_ge);
2320 string expr;
2321 bool ok = section.GetContents(&expr);
2322 EXPECT_TRUE(ok);
2323
2324 {
2325 InSequence s;
2326 // required start marker
2327 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Start, 0)));
2328 // DW_OP_lit0
2329 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_SImm32, 0)));
2330 // DW_OP_lit31
2331 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_SImm32, 31)));
2332 // DW_OP_breg17 -1234
2333 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_DwReg, 17)));
2334 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_SImm32, -1234)));
2335 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Add)));
2336 // DW_OP_const4s 0xFEDC9876
2337 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_SImm32, 0xFEDC9876)));
2338 // DW_OP_deref
2339 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Deref)));
2340 // DW_OP_and
2341 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_And)));
2342 // DW_OP_plus
2343 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Add)));
2344 // DW_OP_minus
2345 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Sub)));
2346 // DW_OP_shl
2347 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Shl)));
2348 // DW_OP_ge
2349 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_CmpGES)));
2350 // required end marker
2351 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_End)));
2352 }
2353
2354 int32_t ix = parseDwarfExpr(&summ, &reader, expr, false, false, false);
2355 EXPECT_TRUE(ix >= 0);
2356 }
2357
TEST_F(LulDwarfExpr,UnknownOpcode)2358 TEST_F(LulDwarfExpr, UnknownOpcode) {
2359 MockSummariser summ;
2360 ByteReader reader(ENDIANNESS_LITTLE);
2361
2362 CFISection section(kLittleEndian, 8);
2363 section
2364 .D8(DW_OP_lo_user - 1);
2365 string expr;
2366 bool ok = section.GetContents(&expr);
2367 EXPECT_TRUE(ok);
2368
2369 {
2370 InSequence s;
2371 // required start marker
2372 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Start, 0)));
2373 }
2374
2375 int32_t ix = parseDwarfExpr(&summ, &reader, expr, false, false, false);
2376 EXPECT_TRUE(ix == -1);
2377 }
2378
TEST_F(LulDwarfExpr,ExpressionOverrun)2379 TEST_F(LulDwarfExpr, ExpressionOverrun) {
2380 MockSummariser summ;
2381 ByteReader reader(ENDIANNESS_LITTLE);
2382
2383 CFISection section(kLittleEndian, 8);
2384 section
2385 .D8(DW_OP_const4s).D8(0x12).D8(0x34).D8(0x56);
2386 string expr;
2387 bool ok = section.GetContents(&expr);
2388 EXPECT_TRUE(ok);
2389
2390 {
2391 InSequence s;
2392 // required start marker
2393 EXPECT_CALL(summ, AddPfxInstr(PfxInstr(PX_Start, 0)));
2394 // DW_OP_const4s followed by 3 (a.k.a. not enough) bytes
2395 // We expect PfxInstr(PX_Simm32, not-known-for-sure-32-bit-immediate)
2396 // Hence must use _ as the argument.
2397 EXPECT_CALL(summ, AddPfxInstr(_));
2398 }
2399
2400 int32_t ix = parseDwarfExpr(&summ, &reader, expr, false, false, false);
2401 EXPECT_TRUE(ix == -1);
2402 }
2403
2404 // We'll need to mention specific Dwarf registers in the EvaluatePfxExpr tests,
2405 // and those names are arch-specific, so a bit of macro magic is helpful.
2406 #if defined(GP_ARCH_arm)
2407 # define TESTED_REG_STRUCT_NAME r11
2408 # define TESTED_REG_DWARF_NAME DW_REG_ARM_R11
2409 #elif defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
2410 # define TESTED_REG_STRUCT_NAME xbp
2411 # define TESTED_REG_DWARF_NAME DW_REG_INTEL_XBP
2412 #else
2413 # error "Unknown plat"
2414 #endif
2415
2416 struct EvaluatePfxExprFixture {
2417 // Creates:
2418 // initial stack, AVMA 0x12345678, at offset 4 bytes = 0xdeadbeef
2419 // initial regs, with XBP = 0x14141356
2420 // initial CFA = 0x5432ABCD
EvaluatePfxExprFixturelul::EvaluatePfxExprFixture2421 EvaluatePfxExprFixture() {
2422 // The test stack.
2423 si.mStartAvma = 0x12345678;
2424 si.mLen = 0;
2425 # define XX(_byte) do { si.mContents[si.mLen++] = (_byte); } while (0)
2426 XX(0x55); XX(0x55); XX(0x55); XX(0x55);
2427 if (sizeof(void*) == 8) {
2428 // le64
2429 XX(0xEF); XX(0xBE); XX(0xAD); XX(0xDE); XX(0); XX(0); XX(0); XX(0);
2430 } else {
2431 // le32
2432 XX(0xEF); XX(0xBE); XX(0xAD); XX(0xDE);
2433 }
2434 XX(0xAA); XX(0xAA); XX(0xAA); XX(0xAA);
2435 # undef XX
2436 // The initial CFA.
2437 initialCFA = TaggedUWord(0x5432ABCD);
2438 // The initial register state.
2439 memset(®s, 0, sizeof(regs));
2440 regs.TESTED_REG_STRUCT_NAME = TaggedUWord(0x14141356);
2441 }
2442
2443 StackImage si;
2444 TaggedUWord initialCFA;
2445 UnwindRegs regs;
2446 };
2447
2448 class LulDwarfEvaluatePfxExpr : public EvaluatePfxExprFixture, public Test { };
2449
TEST_F(LulDwarfEvaluatePfxExpr,NormalEvaluation)2450 TEST_F(LulDwarfEvaluatePfxExpr, NormalEvaluation) {
2451 vector<PfxInstr> instrs;
2452 // Put some junk at the start of the insn sequence.
2453 instrs.push_back(PfxInstr(PX_End));
2454 instrs.push_back(PfxInstr(PX_End));
2455
2456 // Now the real sequence
2457 // stack is empty
2458 instrs.push_back(PfxInstr(PX_Start, 1));
2459 // 0x5432ABCD
2460 instrs.push_back(PfxInstr(PX_SImm32, 0x31415927));
2461 // 0x5432ABCD 0x31415927
2462 instrs.push_back(PfxInstr(PX_DwReg, TESTED_REG_DWARF_NAME));
2463 // 0x5432ABCD 0x31415927 0x14141356
2464 instrs.push_back(PfxInstr(PX_SImm32, 42));
2465 // 0x5432ABCD 0x31415927 0x14141356 42
2466 instrs.push_back(PfxInstr(PX_Sub));
2467 // 0x5432ABCD 0x31415927 0x1414132c
2468 instrs.push_back(PfxInstr(PX_Add));
2469 // 0x5432ABCD 0x45556c53
2470 instrs.push_back(PfxInstr(PX_SImm32, si.mStartAvma + 4));
2471 // 0x5432ABCD 0x45556c53 0x1234567c
2472 instrs.push_back(PfxInstr(PX_Deref));
2473 // 0x5432ABCD 0x45556c53 0xdeadbeef
2474 instrs.push_back(PfxInstr(PX_SImm32, 0xFE01DC23));
2475 // 0x5432ABCD 0x45556c53 0xdeadbeef 0xFE01DC23
2476 instrs.push_back(PfxInstr(PX_And));
2477 // 0x5432ABCD 0x45556c53 0xde019c23
2478 instrs.push_back(PfxInstr(PX_SImm32, 7));
2479 // 0x5432ABCD 0x45556c53 0xde019c23 7
2480 instrs.push_back(PfxInstr(PX_Shl));
2481 // 0x5432ABCD 0x45556c53 0x6f00ce1180
2482 instrs.push_back(PfxInstr(PX_SImm32, 0x7fffffff));
2483 // 0x5432ABCD 0x45556c53 0x6f00ce1180 7fffffff
2484 instrs.push_back(PfxInstr(PX_And));
2485 // 0x5432ABCD 0x45556c53 0x00ce1180
2486 instrs.push_back(PfxInstr(PX_Add));
2487 // 0x5432ABCD 0x46237dd3
2488 instrs.push_back(PfxInstr(PX_Sub));
2489 // 0xe0f2dfa
2490
2491 instrs.push_back(PfxInstr(PX_End));
2492
2493 TaggedUWord res = EvaluatePfxExpr(2/*offset of start insn*/,
2494 ®s, initialCFA, &si, instrs);
2495 EXPECT_TRUE(res.Valid());
2496 EXPECT_TRUE(res.Value() == 0xe0f2dfa);
2497 }
2498
TEST_F(LulDwarfEvaluatePfxExpr,EmptySequence)2499 TEST_F(LulDwarfEvaluatePfxExpr, EmptySequence) {
2500 vector<PfxInstr> instrs;
2501 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2502 EXPECT_FALSE(res.Valid());
2503 }
2504
TEST_F(LulDwarfEvaluatePfxExpr,BogusStartPoint)2505 TEST_F(LulDwarfEvaluatePfxExpr, BogusStartPoint) {
2506 vector<PfxInstr> instrs;
2507 instrs.push_back(PfxInstr(PX_SImm32, 42));
2508 instrs.push_back(PfxInstr(PX_SImm32, 24));
2509 instrs.push_back(PfxInstr(PX_SImm32, 4224));
2510 TaggedUWord res = EvaluatePfxExpr(1, ®s, initialCFA, &si, instrs);
2511 EXPECT_FALSE(res.Valid());
2512 }
2513
TEST_F(LulDwarfEvaluatePfxExpr,MissingEndMarker)2514 TEST_F(LulDwarfEvaluatePfxExpr, MissingEndMarker) {
2515 vector<PfxInstr> instrs;
2516 instrs.push_back(PfxInstr(PX_Start, 0));
2517 instrs.push_back(PfxInstr(PX_SImm32, 24));
2518 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2519 EXPECT_FALSE(res.Valid());
2520 }
2521
TEST_F(LulDwarfEvaluatePfxExpr,StackUnderflow)2522 TEST_F(LulDwarfEvaluatePfxExpr, StackUnderflow) {
2523 vector<PfxInstr> instrs;
2524 instrs.push_back(PfxInstr(PX_Start, 0));
2525 instrs.push_back(PfxInstr(PX_End));
2526 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2527 EXPECT_FALSE(res.Valid());
2528 }
2529
TEST_F(LulDwarfEvaluatePfxExpr,StackNoUnderflow)2530 TEST_F(LulDwarfEvaluatePfxExpr, StackNoUnderflow) {
2531 vector<PfxInstr> instrs;
2532 instrs.push_back(PfxInstr(PX_Start, 1/*push the initial CFA*/));
2533 instrs.push_back(PfxInstr(PX_End));
2534 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2535 EXPECT_TRUE(res.Valid());
2536 EXPECT_TRUE(res == initialCFA);
2537 }
2538
TEST_F(LulDwarfEvaluatePfxExpr,StackOverflow)2539 TEST_F(LulDwarfEvaluatePfxExpr, StackOverflow) {
2540 vector<PfxInstr> instrs;
2541 instrs.push_back(PfxInstr(PX_Start, 0));
2542 for (int i = 0; i < 10+1; i++) {
2543 instrs.push_back(PfxInstr(PX_SImm32, i + 100));
2544 }
2545 instrs.push_back(PfxInstr(PX_End));
2546 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2547 EXPECT_FALSE(res.Valid());
2548 }
2549
TEST_F(LulDwarfEvaluatePfxExpr,StackNoOverflow)2550 TEST_F(LulDwarfEvaluatePfxExpr, StackNoOverflow) {
2551 vector<PfxInstr> instrs;
2552 instrs.push_back(PfxInstr(PX_Start, 0));
2553 for (int i = 0; i < 10+0; i++) {
2554 instrs.push_back(PfxInstr(PX_SImm32, i + 100));
2555 }
2556 instrs.push_back(PfxInstr(PX_End));
2557 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2558 EXPECT_TRUE(res.Valid());
2559 EXPECT_TRUE(res == TaggedUWord(109));
2560 }
2561
TEST_F(LulDwarfEvaluatePfxExpr,OutOfRangeShl)2562 TEST_F(LulDwarfEvaluatePfxExpr, OutOfRangeShl) {
2563 vector<PfxInstr> instrs;
2564 instrs.push_back(PfxInstr(PX_Start, 0));
2565 instrs.push_back(PfxInstr(PX_SImm32, 1234));
2566 instrs.push_back(PfxInstr(PX_SImm32, 5678));
2567 instrs.push_back(PfxInstr(PX_Shl));
2568 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2569 EXPECT_TRUE(!res.Valid());
2570 }
2571
TEST_F(LulDwarfEvaluatePfxExpr,TestCmpGES)2572 TEST_F(LulDwarfEvaluatePfxExpr, TestCmpGES) {
2573 const int32_t argsL[6] = { 0, 0, 1, -2, -1, -2 };
2574 const int32_t argsR[6] = { 0, 1, 0, -2, -2, -1 };
2575 // expecting: t f t t t f = 101110 = 0x2E
2576 vector<PfxInstr> instrs;
2577 instrs.push_back(PfxInstr(PX_Start, 0));
2578 // The "running total"
2579 instrs.push_back(PfxInstr(PX_SImm32, 0));
2580 for (unsigned int i = 0; i < sizeof(argsL)/sizeof(argsL[0]); i++) {
2581 // Shift the "running total" at the bottom of the stack left by one bit
2582 instrs.push_back(PfxInstr(PX_SImm32, 1));
2583 instrs.push_back(PfxInstr(PX_Shl));
2584 // Push both test args and do the comparison
2585 instrs.push_back(PfxInstr(PX_SImm32, argsL[i]));
2586 instrs.push_back(PfxInstr(PX_SImm32, argsR[i]));
2587 instrs.push_back(PfxInstr(PX_CmpGES));
2588 // Or the result into the running total
2589 instrs.push_back(PfxInstr(PX_Or));
2590 }
2591 instrs.push_back(PfxInstr(PX_End));
2592 TaggedUWord res = EvaluatePfxExpr(0, ®s, initialCFA, &si, instrs);
2593 EXPECT_TRUE(res.Valid());
2594 EXPECT_TRUE(res == TaggedUWord(0x2E));
2595 }
2596
2597 } // namespace lul
2598