OLD | NEW |
| (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 §ion); | |
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(§ion); | |
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(§ion); | |
708 } | |
709 | |
710 TEST_F(CFIInsn, DW_CFA_advance_loc) { | |
711 CFISection section(kBigEndian, 8); | |
712 StockCIEAndFDE(§ion); | |
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(§ion); | |
730 } | |
731 | |
732 TEST_F(CFIInsn, DW_CFA_advance_loc1) { | |
733 CFISection section(kLittleEndian, 8); | |
734 StockCIEAndFDE(§ion); | |
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(§ion); | |
750 } | |
751 | |
752 TEST_F(CFIInsn, DW_CFA_advance_loc2) { | |
753 CFISection section(kLittleEndian, 4); | |
754 StockCIEAndFDE(§ion); | |
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(§ion); | |
770 } | |
771 | |
772 TEST_F(CFIInsn, DW_CFA_advance_loc4) { | |
773 CFISection section(kBigEndian, 8); | |
774 StockCIEAndFDE(§ion); | |
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(§ion); | |
790 } | |
791 | |
792 TEST_F(CFIInsn, DW_CFA_MIPS_advance_loc8) { | |
793 code_factor = 0x2d; | |
794 CFISection section(kBigEndian, 8); | |
795 StockCIEAndFDE(§ion); | |
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(§ion); | |
811 } | |
812 | |
813 TEST_F(CFIInsn, DW_CFA_def_cfa) { | |
814 CFISection section(kLittleEndian, 4); | |
815 StockCIEAndFDE(§ion); | |
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(§ion); | |
828 } | |
829 | |
830 TEST_F(CFIInsn, DW_CFA_def_cfa_sf) { | |
831 CFISection section(kBigEndian, 4); | |
832 StockCIEAndFDE(§ion); | |
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(§ion); | |
849 } | |
850 | |
851 TEST_F(CFIInsn, DW_CFA_def_cfa_register) { | |
852 CFISection section(kLittleEndian, 8); | |
853 StockCIEAndFDE(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
883 } | |
884 | |
885 TEST_F(CFIInsn, DW_CFA_def_cfa_offset) { | |
886 CFISection section(kBigEndian, 4); | |
887 StockCIEAndFDE(§ion); | |
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(§ion); | |
899 } | |
900 | |
901 TEST_F(CFIInsn, DW_CFA_def_cfa_offset_sf) { | |
902 CFISection section(kLittleEndian, 4); | |
903 StockCIEAndFDE(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
938 } | |
939 | |
940 TEST_F(CFIInsn, DW_CFA_def_cfa_expression) { | |
941 CFISection section(kLittleEndian, 8); | |
942 StockCIEAndFDE(§ion); | |
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(§ion); | |
953 } | |
954 | |
955 TEST_F(CFIInsn, DW_CFA_undefined) { | |
956 CFISection section(kLittleEndian, 4); | |
957 StockCIEAndFDE(§ion); | |
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(§ion); | |
967 } | |
968 | |
969 TEST_F(CFIInsn, DW_CFA_same_value) { | |
970 CFISection section(kLittleEndian, 4); | |
971 StockCIEAndFDE(§ion); | |
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(§ion); | |
981 } | |
982 | |
983 TEST_F(CFIInsn, DW_CFA_offset) { | |
984 CFISection section(kBigEndian, 4); | |
985 StockCIEAndFDE(§ion); | |
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(§ion); | |
996 } | |
997 | |
998 TEST_F(CFIInsn, DW_CFA_offset_extended) { | |
999 CFISection section(kBigEndian, 4); | |
1000 StockCIEAndFDE(§ion); | |
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(§ion); | |
1011 } | |
1012 | |
1013 TEST_F(CFIInsn, DW_CFA_offset_extended_sf) { | |
1014 CFISection section(kBigEndian, 8); | |
1015 StockCIEAndFDE(§ion); | |
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(§ion); | |
1034 } | |
1035 | |
1036 TEST_F(CFIInsn, DW_CFA_val_offset) { | |
1037 CFISection section(kBigEndian, 4); | |
1038 StockCIEAndFDE(§ion); | |
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(§ion); | |
1050 } | |
1051 | |
1052 TEST_F(CFIInsn, DW_CFA_val_offset_sf) { | |
1053 CFISection section(kBigEndian, 4); | |
1054 StockCIEAndFDE(§ion); | |
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(§ion); | |
1071 } | |
1072 | |
1073 TEST_F(CFIInsn, DW_CFA_register) { | |
1074 CFISection section(kLittleEndian, 8); | |
1075 StockCIEAndFDE(§ion); | |
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(§ion); | |
1085 } | |
1086 | |
1087 TEST_F(CFIInsn, DW_CFA_expression) { | |
1088 CFISection section(kBigEndian, 8); | |
1089 StockCIEAndFDE(§ion); | |
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(§ion); | |
1102 } | |
1103 | |
1104 TEST_F(CFIInsn, DW_CFA_val_expression) { | |
1105 CFISection section(kBigEndian, 4); | |
1106 StockCIEAndFDE(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
1285 } | |
1286 | |
1287 TEST_F(CFIInsn, DW_CFA_remember_and_restore_state) { | |
1288 CFISection section(kLittleEndian, 8); | |
1289 StockCIEAndFDE(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
1383 } | |
1384 | |
1385 TEST_F(CFIInsn, DW_CFA_nop) { | |
1386 CFISection section(kLittleEndian, 4); | |
1387 StockCIEAndFDE(§ion); | |
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(§ion); | |
1400 } | |
1401 | |
1402 TEST_F(CFIInsn, DW_CFA_GNU_window_save) { | |
1403 CFISection section(kBigEndian, 4); | |
1404 StockCIEAndFDE(§ion); | |
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(§ion); | |
1425 } | |
1426 | |
1427 TEST_F(CFIInsn, DW_CFA_GNU_args_size) { | |
1428 CFISection section(kLittleEndian, 8); | |
1429 StockCIEAndFDE(§ion); | |
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(§ion); | |
1442 } | |
1443 | |
1444 TEST_F(CFIInsn, DW_CFA_GNU_negative_offset_extended) { | |
1445 CFISection section(kLittleEndian, 4); | |
1446 StockCIEAndFDE(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion, false); | |
1532 } | |
1533 | |
1534 class CFIRestore: public CFIInsnFixture, public Test { }; | |
1535 | |
1536 TEST_F(CFIRestore, RestoreUndefinedRuleUnchanged) { | |
1537 CFISection section(kLittleEndian, 4); | |
1538 StockCIEAndFDE(§ion); | |
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(§ion); | |
1551 } | |
1552 | |
1553 TEST_F(CFIRestore, RestoreUndefinedRuleChanged) { | |
1554 CFISection section(kLittleEndian, 4); | |
1555 StockCIEAndFDE(§ion); | |
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(§ion); | |
1574 } | |
1575 | |
1576 TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) { | |
1577 CFISection section(kLittleEndian, 4); | |
1578 StockCIEAndFDE(§ion); | |
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(§ion); | |
1591 } | |
1592 | |
1593 TEST_F(CFIRestore, RestoreSameValueRuleChanged) { | |
1594 CFISection section(kLittleEndian, 4); | |
1595 StockCIEAndFDE(§ion); | |
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(§ion); | |
1614 } | |
1615 | |
1616 TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) { | |
1617 CFISection section(kLittleEndian, 4); | |
1618 StockCIEAndFDE(§ion); | |
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(§ion); | |
1632 } | |
1633 | |
1634 TEST_F(CFIRestore, RestoreOffsetRuleChanged) { | |
1635 CFISection section(kLittleEndian, 4); | |
1636 StockCIEAndFDE(§ion); | |
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(§ion); | |
1657 } | |
1658 | |
1659 TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) { | |
1660 CFISection section(kLittleEndian, 4); | |
1661 StockCIEAndFDE(§ion); | |
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(§ion); | |
1683 } | |
1684 | |
1685 TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) { | |
1686 CFISection section(kLittleEndian, 4); | |
1687 StockCIEAndFDE(§ion); | |
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(§ion); | |
1701 } | |
1702 | |
1703 TEST_F(CFIRestore, RestoreValOffsetRuleChanged) { | |
1704 CFISection section(kLittleEndian, 4); | |
1705 StockCIEAndFDE(§ion); | |
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(§ion); | |
1726 } | |
1727 | |
1728 TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) { | |
1729 CFISection section(kLittleEndian, 4); | |
1730 StockCIEAndFDE(§ion); | |
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(§ion); | |
1752 } | |
1753 | |
1754 TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) { | |
1755 CFISection section(kLittleEndian, 4); | |
1756 StockCIEAndFDE(§ion); | |
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(§ion); | |
1769 } | |
1770 | |
1771 TEST_F(CFIRestore, RestoreRegisterRuleChanged) { | |
1772 CFISection section(kLittleEndian, 4); | |
1773 StockCIEAndFDE(§ion); | |
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(§ion); | |
1793 } | |
1794 | |
1795 TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) { | |
1796 CFISection section(kLittleEndian, 4); | |
1797 StockCIEAndFDE(§ion); | |
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(§ion); | |
1818 } | |
1819 | |
1820 TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) { | |
1821 CFISection section(kLittleEndian, 4); | |
1822 StockCIEAndFDE(§ion); | |
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(§ion); | |
1835 } | |
1836 | |
1837 TEST_F(CFIRestore, RestoreExpressionRuleChanged) { | |
1838 CFISection section(kLittleEndian, 4); | |
1839 StockCIEAndFDE(§ion); | |
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(§ion); | |
1859 } | |
1860 | |
1861 TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) { | |
1862 CFISection section(kLittleEndian, 4); | |
1863 StockCIEAndFDE(§ion); | |
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(§ion); | |
1885 } | |
1886 | |
1887 TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) { | |
1888 CFISection section(kLittleEndian, 4); | |
1889 StockCIEAndFDE(§ion); | |
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(§ion); | |
1903 } | |
1904 | |
1905 TEST_F(CFIRestore, RestoreValExpressionRuleChanged) { | |
1906 CFISection section(kLittleEndian, 4); | |
1907 StockCIEAndFDE(§ion); | |
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(§ion); | |
1930 } | |
1931 | |
1932 TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) { | |
1933 CFISection section(kLittleEndian, 4); | |
1934 StockCIEAndFDE(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion, 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(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion); | |
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(§ion_names_header.name) | |
2402 .AppendCString(".shstrtab") | |
2403 .Mark(&cfi_header.name) | |
2404 .AppendCString(cfi_name) | |
2405 .Mark(§ion_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(§ion_table, null_header); | |
2412 AppendSectionHeader(§ion_table, section_names_header); | |
2413 AppendSectionHeader(§ion_table, cfi_header); | |
2414 | |
2415 // Append the section table and the section contents to the ELF file. | |
2416 elf | |
2417 .Mark(§ion_table_offset) | |
2418 .Append(section_table) | |
2419 .Mark(§ion_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 | |
OLD | NEW |