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