Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: obsolete/breakpad/common/dwarf/dwarf2reader_cfi_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698