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(&section);
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(&section);
657 }
658 
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc)659 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc) {
660   CFISection section(kBigEndian, 8);
661   StockCIEAndFDE(&section);
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(&section);
680 }
681 
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc1)682 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc1) {
683   CFISection section(kLittleEndian, 8);
684   StockCIEAndFDE(&section);
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(&section);
701 }
702 
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc2)703 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc2) {
704   CFISection section(kLittleEndian, 4);
705   StockCIEAndFDE(&section);
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(&section);
722 }
723 
TEST_F(LulDwarfCFIInsn,DW_CFA_advance_loc4)724 TEST_F(LulDwarfCFIInsn, DW_CFA_advance_loc4) {
725   CFISection section(kBigEndian, 8);
726   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
766 }
767 
TEST_F(LulDwarfCFIInsn,DW_CFA_def_cfa)768 TEST_F(LulDwarfCFIInsn, DW_CFA_def_cfa) {
769   CFISection section(kLittleEndian, 4);
770   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section, true, &reader);
914 }
915 
TEST_F(LulDwarfCFIInsn,DW_CFA_undefined)916 TEST_F(LulDwarfCFIInsn, DW_CFA_undefined) {
917   CFISection section(kLittleEndian, 4);
918   StockCIEAndFDE(&section);
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(&section);
927 }
928 
TEST_F(LulDwarfCFIInsn,DW_CFA_same_value)929 TEST_F(LulDwarfCFIInsn, DW_CFA_same_value) {
930   CFISection section(kLittleEndian, 4);
931   StockCIEAndFDE(&section);
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(&section);
940 }
941 
TEST_F(LulDwarfCFIInsn,DW_CFA_offset)942 TEST_F(LulDwarfCFIInsn, DW_CFA_offset) {
943   CFISection section(kBigEndian, 4);
944   StockCIEAndFDE(&section);
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(&section);
954 }
955 
TEST_F(LulDwarfCFIInsn,DW_CFA_offset_extended)956 TEST_F(LulDwarfCFIInsn, DW_CFA_offset_extended) {
957   CFISection section(kBigEndian, 4);
958   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
995 }
996 
TEST_F(LulDwarfCFIInsn,DW_CFA_val_offset)997 TEST_F(LulDwarfCFIInsn, DW_CFA_val_offset) {
998   CFISection section(kBigEndian, 4);
999   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
1036 }
1037 
TEST_F(LulDwarfCFIInsn,DW_CFA_register)1038 TEST_F(LulDwarfCFIInsn, DW_CFA_register) {
1039   CFISection section(kLittleEndian, 8);
1040   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section, 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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
1377 }
1378 
TEST_F(LulDwarfCFIInsn,DW_CFA_nop)1379 TEST_F(LulDwarfCFIInsn, DW_CFA_nop) {
1380   CFISection section(kLittleEndian, 4);
1381   StockCIEAndFDE(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section);
1557 }
1558 
TEST_F(LulDwarfCFIRestore,RestoreUndefinedRuleChanged)1559 TEST_F(LulDwarfCFIRestore, RestoreUndefinedRuleChanged) {
1560   CFISection section(kLittleEndian, 4);
1561   StockCIEAndFDE(&section);
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(&section);
1584 }
1585 
TEST_F(LulDwarfCFIRestore,RestoreSameValueRuleUnchanged)1586 TEST_F(LulDwarfCFIRestore, RestoreSameValueRuleUnchanged) {
1587   CFISection section(kLittleEndian, 4);
1588   StockCIEAndFDE(&section);
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(&section);
1602 }
1603 
TEST_F(LulDwarfCFIRestore,RestoreSameValueRuleChanged)1604 TEST_F(LulDwarfCFIRestore, RestoreSameValueRuleChanged) {
1605   CFISection section(kLittleEndian, 4);
1606   StockCIEAndFDE(&section);
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(&section);
1629 }
1630 
TEST_F(LulDwarfCFIRestore,RestoreOffsetRuleUnchanged)1631 TEST_F(LulDwarfCFIRestore, RestoreOffsetRuleUnchanged) {
1632   CFISection section(kLittleEndian, 4);
1633   StockCIEAndFDE(&section);
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(&section);
1648 }
1649 
TEST_F(LulDwarfCFIRestore,RestoreOffsetRuleChanged)1650 TEST_F(LulDwarfCFIRestore, RestoreOffsetRuleChanged) {
1651   CFISection section(kLittleEndian, 4);
1652   StockCIEAndFDE(&section);
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(&section);
1677 }
1678 
TEST_F(LulDwarfCFIRestore,RestoreOffsetRuleChangedOffset)1679 TEST_F(LulDwarfCFIRestore, RestoreOffsetRuleChangedOffset) {
1680   CFISection section(kLittleEndian, 4);
1681   StockCIEAndFDE(&section);
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(&section);
1707 }
1708 
TEST_F(LulDwarfCFIRestore,RestoreValOffsetRuleUnchanged)1709 TEST_F(LulDwarfCFIRestore, RestoreValOffsetRuleUnchanged) {
1710   CFISection section(kLittleEndian, 4);
1711   StockCIEAndFDE(&section);
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(&section);
1727 }
1728 
TEST_F(LulDwarfCFIRestore,RestoreValOffsetRuleChanged)1729 TEST_F(LulDwarfCFIRestore, RestoreValOffsetRuleChanged) {
1730   CFISection section(kLittleEndian, 4);
1731   StockCIEAndFDE(&section);
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(&section);
1757 }
1758 
TEST_F(LulDwarfCFIRestore,RestoreValOffsetRuleChangedValOffset)1759 TEST_F(LulDwarfCFIRestore, RestoreValOffsetRuleChangedValOffset) {
1760   CFISection section(kLittleEndian, 4);
1761   StockCIEAndFDE(&section);
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(&section);
1789 }
1790 
TEST_F(LulDwarfCFIRestore,RestoreRegisterRuleUnchanged)1791 TEST_F(LulDwarfCFIRestore, RestoreRegisterRuleUnchanged) {
1792   CFISection section(kLittleEndian, 4);
1793   StockCIEAndFDE(&section);
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(&section);
1808 }
1809 
TEST_F(LulDwarfCFIRestore,RestoreRegisterRuleChanged)1810 TEST_F(LulDwarfCFIRestore, RestoreRegisterRuleChanged) {
1811   CFISection section(kLittleEndian, 4);
1812   StockCIEAndFDE(&section);
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(&section);
1837 }
1838 
TEST_F(LulDwarfCFIRestore,RestoreRegisterRuleChangedRegister)1839 TEST_F(LulDwarfCFIRestore, RestoreRegisterRuleChangedRegister) {
1840   CFISection section(kLittleEndian, 4);
1841   StockCIEAndFDE(&section);
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(&section);
1868 }
1869 
TEST_F(LulDwarfCFIRestore,RestoreExpressionRuleUnchanged)1870 TEST_F(LulDwarfCFIRestore, RestoreExpressionRuleUnchanged) {
1871   ByteReader reader(ENDIANNESS_LITTLE);
1872   CFISection section(kLittleEndian, 4);
1873   StockCIEAndFDE(&section);
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(&section, 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(&section);
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(&section, 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(&section);
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(&section, 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(&section);
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(&section, 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(&section);
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(&section, 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(&section);
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(&section, 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(&section);
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(&section);
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(&section);
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(&section, 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(&section);
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(&section);
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(&section);
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(&section);
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(&regs, 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*/, &regs,
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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, 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, &regs, initialCFA, &si, instrs);
2720   EXPECT_TRUE(res.Valid());
2721   EXPECT_TRUE(res == TaggedUWord(0x2E));
2722 }
2723 
2724 }  // namespace lul
2725