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