Coverage Report

Created: 2018-09-25 14:53

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