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