|
1 // -*- mode: c++ -*- |
|
2 |
|
3 // Copyright (c) 2010 Google Inc. All Rights Reserved. |
|
4 // |
|
5 // Redistribution and use in source and binary forms, with or without |
|
6 // modification, are permitted provided that the following conditions are |
|
7 // met: |
|
8 // |
|
9 // * Redistributions of source code must retain the above copyright |
|
10 // notice, this list of conditions and the following disclaimer. |
|
11 // * Redistributions in binary form must reproduce the above |
|
12 // copyright notice, this list of conditions and the following disclaimer |
|
13 // in the documentation and/or other materials provided with the |
|
14 // distribution. |
|
15 // * Neither the name of Google Inc. nor the names of its |
|
16 // contributors may be used to endorse or promote products derived from |
|
17 // this software without specific prior written permission. |
|
18 // |
|
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
30 |
|
31 // Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> |
|
32 |
|
33 // dwarf2diehander_unittest.cc: Unit tests for google_breakpad::DIEDispatcher. |
|
34 |
|
35 #include <string> |
|
36 #include <utility> |
|
37 |
|
38 #include "breakpad_googletest_includes.h" |
|
39 |
|
40 #include "common/dwarf/dwarf2diehandler.h" |
|
41 #include "common/using_std_string.h" |
|
42 |
|
43 using std::make_pair; |
|
44 |
|
45 using ::testing::_; |
|
46 using ::testing::ContainerEq; |
|
47 using ::testing::ElementsAreArray; |
|
48 using ::testing::Eq; |
|
49 using ::testing::InSequence; |
|
50 using ::testing::Return; |
|
51 using ::testing::Sequence; |
|
52 using ::testing::StrEq; |
|
53 |
|
54 using dwarf2reader::DIEDispatcher; |
|
55 using dwarf2reader::DIEHandler; |
|
56 using dwarf2reader::DwarfAttribute; |
|
57 using dwarf2reader::DwarfForm; |
|
58 using dwarf2reader::DwarfTag; |
|
59 using dwarf2reader::RootDIEHandler; |
|
60 |
|
61 class MockDIEHandler: public DIEHandler { |
|
62 public: |
|
63 MOCK_METHOD3(ProcessAttributeUnsigned, |
|
64 void(DwarfAttribute, DwarfForm, uint64)); |
|
65 MOCK_METHOD3(ProcessAttributeSigned, |
|
66 void(DwarfAttribute, DwarfForm, int64)); |
|
67 MOCK_METHOD3(ProcessAttributeReference, |
|
68 void(DwarfAttribute, DwarfForm, uint64)); |
|
69 MOCK_METHOD4(ProcessAttributeBuffer, |
|
70 void(DwarfAttribute, DwarfForm, const char *, uint64)); |
|
71 MOCK_METHOD3(ProcessAttributeString, |
|
72 void(DwarfAttribute, DwarfForm, const string &)); |
|
73 MOCK_METHOD3(ProcessAttributeSignature, |
|
74 void(DwarfAttribute, DwarfForm, uint64)); |
|
75 MOCK_METHOD0(EndAttributes, bool()); |
|
76 MOCK_METHOD2(FindChildHandler, DIEHandler *(uint64, DwarfTag)); |
|
77 MOCK_METHOD0(Finish, void()); |
|
78 }; |
|
79 |
|
80 class MockRootDIEHandler: public RootDIEHandler { |
|
81 public: |
|
82 MOCK_METHOD3(ProcessAttributeUnsigned, |
|
83 void(DwarfAttribute, DwarfForm, uint64)); |
|
84 MOCK_METHOD3(ProcessAttributeSigned, |
|
85 void(DwarfAttribute, DwarfForm, int64)); |
|
86 MOCK_METHOD3(ProcessAttributeReference, |
|
87 void(DwarfAttribute, DwarfForm, uint64)); |
|
88 MOCK_METHOD4(ProcessAttributeBuffer, |
|
89 void(DwarfAttribute, DwarfForm, const char *, uint64)); |
|
90 MOCK_METHOD3(ProcessAttributeString, |
|
91 void(DwarfAttribute, DwarfForm, const string &)); |
|
92 MOCK_METHOD3(ProcessAttributeSignature, |
|
93 void(DwarfAttribute, DwarfForm, uint64)); |
|
94 MOCK_METHOD0(EndAttributes, bool()); |
|
95 MOCK_METHOD2(FindChildHandler, DIEHandler *(uint64, DwarfTag)); |
|
96 MOCK_METHOD0(Finish, void()); |
|
97 MOCK_METHOD5(StartCompilationUnit, bool(uint64, uint8, uint8, uint64, uint8)); |
|
98 MOCK_METHOD2(StartRootDIE, bool(uint64, DwarfTag)); |
|
99 }; |
|
100 |
|
101 // If the handler elects to skip the compilation unit, the dispatcher |
|
102 // should tell the reader so. |
|
103 TEST(Dwarf2DIEHandler, SkipCompilationUnit) { |
|
104 Sequence s; |
|
105 MockRootDIEHandler mock_root_handler; |
|
106 DIEDispatcher die_dispatcher(&mock_root_handler); |
|
107 |
|
108 EXPECT_CALL(mock_root_handler, |
|
109 StartCompilationUnit(0x8d42aed77cfccf3eLL, |
|
110 0x89, 0xdc, |
|
111 0x2ecb4dc778a80f21LL, |
|
112 0x66)) |
|
113 .InSequence(s) |
|
114 .WillOnce(Return(false)); |
|
115 |
|
116 EXPECT_FALSE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL, |
|
117 0x89, 0xdc, |
|
118 0x2ecb4dc778a80f21LL, |
|
119 0x66)); |
|
120 } |
|
121 |
|
122 // If the handler elects to skip the root DIE, the dispatcher should |
|
123 // tell the reader so. |
|
124 TEST(Dwarf2DIEHandler, SkipRootDIE) { |
|
125 Sequence s; |
|
126 MockRootDIEHandler mock_root_handler; |
|
127 DIEDispatcher die_dispatcher(&mock_root_handler); |
|
128 |
|
129 EXPECT_CALL(mock_root_handler, |
|
130 StartCompilationUnit(0xde8994029fc8b999LL, 0xf4, 0x02, |
|
131 0xb00febffa76e2b2bLL, 0x5c)) |
|
132 .InSequence(s) |
|
133 .WillOnce(Return(true)); |
|
134 EXPECT_CALL(mock_root_handler, |
|
135 StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6)) |
|
136 .InSequence(s) |
|
137 .WillOnce(Return(false)); |
|
138 |
|
139 EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0xde8994029fc8b999LL, |
|
140 0xf4, 0x02, |
|
141 0xb00febffa76e2b2bLL, 0x5c)); |
|
142 EXPECT_FALSE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL, |
|
143 (DwarfTag) 0xb4f98da6)); |
|
144 die_dispatcher.EndDIE(0x7d08242b4b510cf2LL); |
|
145 } |
|
146 |
|
147 // If the handler elects to skip the root DIE's children, the |
|
148 // dispatcher should tell the reader so --- and avoid deleting the |
|
149 // root handler. |
|
150 TEST(Dwarf2DIEHandler, SkipRootDIEChildren) { |
|
151 MockRootDIEHandler mock_root_handler; |
|
152 DIEDispatcher die_dispatcher(&mock_root_handler); |
|
153 |
|
154 { |
|
155 InSequence s; |
|
156 |
|
157 EXPECT_CALL(mock_root_handler, |
|
158 StartCompilationUnit(0x15d6897480cc65a7LL, 0x26, 0xa0, |
|
159 0x09f8bf0767f91675LL, 0xdb)) |
|
160 .WillOnce(Return(true)); |
|
161 EXPECT_CALL(mock_root_handler, |
|
162 StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6)) |
|
163 .WillOnce(Return(true)); |
|
164 // Please don't tell me about my children. |
|
165 EXPECT_CALL(mock_root_handler, EndAttributes()) |
|
166 .WillOnce(Return(false)); |
|
167 EXPECT_CALL(mock_root_handler, Finish()) |
|
168 .WillOnce(Return()); |
|
169 } |
|
170 |
|
171 EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x15d6897480cc65a7LL, |
|
172 0x26, 0xa0, |
|
173 0x09f8bf0767f91675LL, 0xdb)); |
|
174 EXPECT_TRUE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL, |
|
175 (DwarfTag) 0xb4f98da6)); |
|
176 EXPECT_FALSE(die_dispatcher.StartDIE(0x435150ceedccda18LL, |
|
177 (DwarfTag) 0xc3a17bba)); |
|
178 die_dispatcher.EndDIE(0x435150ceedccda18LL); |
|
179 die_dispatcher.EndDIE(0x7d08242b4b510cf2LL); |
|
180 } |
|
181 |
|
182 // The dispatcher should pass attribute values through to the die |
|
183 // handler accurately. |
|
184 TEST(Dwarf2DIEHandler, PassAttributeValues) { |
|
185 MockRootDIEHandler mock_root_handler; |
|
186 DIEDispatcher die_dispatcher(&mock_root_handler); |
|
187 |
|
188 const char buffer[10] = { 0x24, 0x24, 0x35, 0x9a, 0xca, |
|
189 0xcf, 0xa8, 0x84, 0xa7, 0x18 }; |
|
190 string str = "\xc8\x26\x2e\x0d\xa4\x9c\x37\xd6\xfb\x1d"; |
|
191 |
|
192 // Set expectations. |
|
193 { |
|
194 InSequence s; |
|
195 |
|
196 // We'll like the compilation unit header. |
|
197 EXPECT_CALL(mock_root_handler, |
|
198 StartCompilationUnit(0x8d42aed77cfccf3eLL, 0x89, 0xdc, |
|
199 0x2ecb4dc778a80f21LL, 0x66)) |
|
200 .WillOnce(Return(true)); |
|
201 |
|
202 // We'll like the root DIE. |
|
203 EXPECT_CALL(mock_root_handler, |
|
204 StartRootDIE(0xe2222da01e29f2a9LL, (DwarfTag) 0x9829445c)) |
|
205 .WillOnce(Return(true)); |
|
206 |
|
207 // Expect some attribute values. |
|
208 EXPECT_CALL(mock_root_handler, |
|
209 ProcessAttributeUnsigned((DwarfAttribute) 0x1cc0bfed, |
|
210 (DwarfForm) 0x424f1468, |
|
211 0xa592571997facda1ULL)) |
|
212 .WillOnce(Return()); |
|
213 EXPECT_CALL(mock_root_handler, |
|
214 ProcessAttributeSigned((DwarfAttribute) 0x43694dc9, |
|
215 (DwarfForm) 0xf6f78901L, |
|
216 0x92602a4e3bf1f446LL)) |
|
217 .WillOnce(Return()); |
|
218 EXPECT_CALL(mock_root_handler, |
|
219 ProcessAttributeReference((DwarfAttribute) 0x4033e8cL, |
|
220 (DwarfForm) 0xf66fbe0bL, |
|
221 0x50fddef44734fdecULL)) |
|
222 .WillOnce(Return()); |
|
223 EXPECT_CALL(mock_root_handler, |
|
224 ProcessAttributeBuffer((DwarfAttribute) 0x25d7e0af, |
|
225 (DwarfForm) 0xe99a539a, |
|
226 buffer, sizeof(buffer))) |
|
227 .WillOnce(Return()); |
|
228 EXPECT_CALL(mock_root_handler, |
|
229 ProcessAttributeString((DwarfAttribute) 0x310ed065, |
|
230 (DwarfForm) 0x15762fec, |
|
231 StrEq(str))) |
|
232 .WillOnce(Return()); |
|
233 EXPECT_CALL(mock_root_handler, |
|
234 ProcessAttributeSignature((DwarfAttribute) 0x58790d72, |
|
235 (DwarfForm) 0x4159f138, |
|
236 0x94682463613e6a5fULL)) |
|
237 .WillOnce(Return()); |
|
238 EXPECT_CALL(mock_root_handler, EndAttributes()) |
|
239 .WillOnce(Return(true)); |
|
240 EXPECT_CALL(mock_root_handler, FindChildHandler(_, _)) |
|
241 .Times(0); |
|
242 EXPECT_CALL(mock_root_handler, Finish()) |
|
243 .WillOnce(Return()); |
|
244 } |
|
245 |
|
246 // Drive the dispatcher. |
|
247 |
|
248 // Report the CU header. |
|
249 EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL, |
|
250 0x89, 0xdc, |
|
251 0x2ecb4dc778a80f21LL, |
|
252 0x66)); |
|
253 // Report the root DIE. |
|
254 EXPECT_TRUE(die_dispatcher.StartDIE(0xe2222da01e29f2a9LL, |
|
255 (DwarfTag) 0x9829445c)); |
|
256 |
|
257 // Report some attribute values. |
|
258 die_dispatcher.ProcessAttributeUnsigned(0xe2222da01e29f2a9LL, |
|
259 (DwarfAttribute) 0x1cc0bfed, |
|
260 (DwarfForm) 0x424f1468, |
|
261 0xa592571997facda1ULL); |
|
262 die_dispatcher.ProcessAttributeSigned(0xe2222da01e29f2a9LL, |
|
263 (DwarfAttribute) 0x43694dc9, |
|
264 (DwarfForm) 0xf6f78901, |
|
265 0x92602a4e3bf1f446LL); |
|
266 die_dispatcher.ProcessAttributeReference(0xe2222da01e29f2a9LL, |
|
267 (DwarfAttribute) 0x4033e8c, |
|
268 (DwarfForm) 0xf66fbe0b, |
|
269 0x50fddef44734fdecULL); |
|
270 die_dispatcher.ProcessAttributeBuffer(0xe2222da01e29f2a9LL, |
|
271 (DwarfAttribute) 0x25d7e0af, |
|
272 (DwarfForm) 0xe99a539a, |
|
273 buffer, sizeof(buffer)); |
|
274 die_dispatcher.ProcessAttributeString(0xe2222da01e29f2a9LL, |
|
275 (DwarfAttribute) 0x310ed065, |
|
276 (DwarfForm) 0x15762fec, |
|
277 str); |
|
278 die_dispatcher.ProcessAttributeSignature(0xe2222da01e29f2a9LL, |
|
279 (DwarfAttribute) 0x58790d72, |
|
280 (DwarfForm) 0x4159f138, |
|
281 0x94682463613e6a5fULL); |
|
282 |
|
283 // Finish the root DIE (and thus the CU). |
|
284 die_dispatcher.EndDIE(0xe2222da01e29f2a9LL); |
|
285 } |
|
286 |
|
287 TEST(Dwarf2DIEHandler, FindAndSkipChildren) { |
|
288 MockRootDIEHandler mock_root_handler; |
|
289 MockDIEHandler *mock_child1_handler = new(MockDIEHandler); |
|
290 MockDIEHandler *mock_child3_handler = new(MockDIEHandler); |
|
291 DIEDispatcher die_dispatcher(&mock_root_handler); |
|
292 |
|
293 { |
|
294 InSequence s; |
|
295 |
|
296 // We'll like the compilation unit header. |
|
297 EXPECT_CALL(mock_root_handler, |
|
298 StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21, |
|
299 0x47dd3c764275a216LL, 0xa5)) |
|
300 .WillOnce(Return(true)); |
|
301 |
|
302 // Root DIE. |
|
303 { |
|
304 EXPECT_CALL(mock_root_handler, |
|
305 StartRootDIE(0x15f0e06bdfe3c372LL, (DwarfTag) 0xf5d60c59)) |
|
306 .WillOnce(Return(true)); |
|
307 EXPECT_CALL(mock_root_handler, |
|
308 ProcessAttributeSigned((DwarfAttribute) 0xf779a642, |
|
309 (DwarfForm) 0x2cb63027, |
|
310 0x18e744661769d08fLL)) |
|
311 .WillOnce(Return()); |
|
312 EXPECT_CALL(mock_root_handler, EndAttributes()) |
|
313 .WillOnce(Return(true)); |
|
314 |
|
315 // First child DIE. |
|
316 EXPECT_CALL(mock_root_handler, |
|
317 FindChildHandler(0x149f644f8116fe8cLL, |
|
318 (DwarfTag) 0xac2cbd8c)) |
|
319 .WillOnce(Return(mock_child1_handler)); |
|
320 { |
|
321 EXPECT_CALL(*mock_child1_handler, |
|
322 ProcessAttributeSigned((DwarfAttribute) 0xa6fd6f65, |
|
323 (DwarfForm) 0xe4f64c41, |
|
324 0x1b04e5444a55fe67LL)) |
|
325 .WillOnce(Return()); |
|
326 EXPECT_CALL(*mock_child1_handler, EndAttributes()) |
|
327 .WillOnce(Return(false)); |
|
328 // Skip first grandchild DIE and first great-grandchild DIE. |
|
329 EXPECT_CALL(*mock_child1_handler, Finish()) |
|
330 .WillOnce(Return()); |
|
331 } |
|
332 |
|
333 // Second child DIE. Root handler will decline to return a handler |
|
334 // for this child. |
|
335 EXPECT_CALL(mock_root_handler, |
|
336 FindChildHandler(0x97412be24875de9dLL, |
|
337 (DwarfTag) 0x505a068b)) |
|
338 .WillOnce(Return((DIEHandler *) NULL)); |
|
339 |
|
340 // Third child DIE. |
|
341 EXPECT_CALL(mock_root_handler, |
|
342 FindChildHandler(0x753c964c8ab538aeLL, |
|
343 (DwarfTag) 0x8c22970e)) |
|
344 .WillOnce(Return(mock_child3_handler)); |
|
345 { |
|
346 EXPECT_CALL(*mock_child3_handler, |
|
347 ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb, |
|
348 (DwarfForm) 0x610b7ae1, |
|
349 0x3ea5c609d7d7560fLL)) |
|
350 .WillOnce(Return()); |
|
351 EXPECT_CALL(*mock_child3_handler, EndAttributes()) |
|
352 .WillOnce(Return(true)); |
|
353 EXPECT_CALL(*mock_child3_handler, Finish()) |
|
354 .WillOnce(Return()); |
|
355 } |
|
356 |
|
357 EXPECT_CALL(mock_root_handler, Finish()) |
|
358 .WillOnce(Return()); |
|
359 } |
|
360 } |
|
361 |
|
362 |
|
363 // Drive the dispatcher. |
|
364 |
|
365 // Report the CU header. |
|
366 EXPECT_TRUE(die_dispatcher |
|
367 .StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21, |
|
368 0x47dd3c764275a216LL, 0xa5)); |
|
369 // Report the root DIE. |
|
370 { |
|
371 EXPECT_TRUE(die_dispatcher.StartDIE(0x15f0e06bdfe3c372LL, |
|
372 (DwarfTag) 0xf5d60c59)); |
|
373 die_dispatcher.ProcessAttributeSigned(0x15f0e06bdfe3c372LL, |
|
374 (DwarfAttribute) 0xf779a642, |
|
375 (DwarfForm) 0x2cb63027, |
|
376 0x18e744661769d08fLL); |
|
377 |
|
378 // First child DIE. |
|
379 { |
|
380 EXPECT_TRUE(die_dispatcher.StartDIE(0x149f644f8116fe8cLL, |
|
381 (DwarfTag) 0xac2cbd8c)); |
|
382 die_dispatcher.ProcessAttributeSigned(0x149f644f8116fe8cLL, |
|
383 (DwarfAttribute) 0xa6fd6f65, |
|
384 (DwarfForm) 0xe4f64c41, |
|
385 0x1b04e5444a55fe67LL); |
|
386 |
|
387 // First grandchild DIE. Will be skipped. |
|
388 { |
|
389 EXPECT_FALSE(die_dispatcher.StartDIE(0xd68de1ee0bd29419LL, |
|
390 (DwarfTag) 0x22f05a15)); |
|
391 // First great-grandchild DIE. Will be skipped without being |
|
392 // mentioned to any handler. |
|
393 { |
|
394 EXPECT_FALSE(die_dispatcher |
|
395 .StartDIE(0xb3076285d25cac25LL, |
|
396 (DwarfTag) 0xcff4061b)); |
|
397 die_dispatcher.EndDIE(0xb3076285d25cac25LL); |
|
398 } |
|
399 die_dispatcher.EndDIE(0xd68de1ee0bd29419LL); |
|
400 } |
|
401 die_dispatcher.EndDIE(0x149f644f8116fe8cLL); |
|
402 } |
|
403 |
|
404 // Second child DIE. Root handler will decline to find a handler for it. |
|
405 { |
|
406 EXPECT_FALSE(die_dispatcher.StartDIE(0x97412be24875de9dLL, |
|
407 (DwarfTag) 0x505a068b)); |
|
408 die_dispatcher.EndDIE(0x97412be24875de9dLL); |
|
409 } |
|
410 |
|
411 // Third child DIE. |
|
412 { |
|
413 EXPECT_TRUE(die_dispatcher.StartDIE(0x753c964c8ab538aeLL, |
|
414 (DwarfTag) 0x8c22970e)); |
|
415 die_dispatcher.ProcessAttributeSigned(0x753c964c8ab538aeLL, |
|
416 (DwarfAttribute) 0x4e2b7cfb, |
|
417 (DwarfForm) 0x610b7ae1, |
|
418 0x3ea5c609d7d7560fLL); |
|
419 die_dispatcher.EndDIE(0x753c964c8ab538aeLL); |
|
420 } |
|
421 |
|
422 // Finish the root DIE (and thus the CU). |
|
423 die_dispatcher.EndDIE(0x15f0e06bdfe3c372LL); |
|
424 } |
|
425 } |
|
426 |
|
427 // The DIEDispatcher destructor is supposed to delete all handlers on |
|
428 // the stack, except for the root. |
|
429 TEST(Dwarf2DIEHandler, FreeHandlersOnStack) { |
|
430 MockRootDIEHandler mock_root_handler; |
|
431 MockDIEHandler *mock_child_handler = new(MockDIEHandler); |
|
432 MockDIEHandler *mock_grandchild_handler = new(MockDIEHandler); |
|
433 |
|
434 { |
|
435 InSequence s; |
|
436 |
|
437 // We'll like the compilation unit header. |
|
438 EXPECT_CALL(mock_root_handler, |
|
439 StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89, |
|
440 0x76d392ff393ddda2LL, 0xbf)) |
|
441 .WillOnce(Return(true)); |
|
442 |
|
443 // Root DIE. |
|
444 { |
|
445 EXPECT_CALL(mock_root_handler, |
|
446 StartRootDIE(0xbf13b761691ddc91LL, (DwarfTag) 0x98980361)) |
|
447 .WillOnce(Return(true)); |
|
448 EXPECT_CALL(mock_root_handler, EndAttributes()) |
|
449 .WillOnce(Return(true)); |
|
450 |
|
451 // Child DIE. |
|
452 EXPECT_CALL(mock_root_handler, |
|
453 FindChildHandler(0x058f09240c5fc8c9LL, |
|
454 (DwarfTag) 0x898bf0d0)) |
|
455 .WillOnce(Return(mock_child_handler)); |
|
456 { |
|
457 EXPECT_CALL(*mock_child_handler, EndAttributes()) |
|
458 .WillOnce(Return(true)); |
|
459 |
|
460 // Grandchild DIE. |
|
461 EXPECT_CALL(*mock_child_handler, |
|
462 FindChildHandler(0x32dc00c9945dc0c8LL, |
|
463 (DwarfTag) 0x2802d007)) |
|
464 .WillOnce(Return(mock_grandchild_handler)); |
|
465 { |
|
466 EXPECT_CALL(*mock_grandchild_handler, |
|
467 ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb, |
|
468 (DwarfForm) 0x610b7ae1, |
|
469 0x3ea5c609d7d7560fLL)) |
|
470 .WillOnce(Return()); |
|
471 |
|
472 // At this point, we abandon the traversal, so none of the |
|
473 // usual stuff should get called. |
|
474 EXPECT_CALL(*mock_grandchild_handler, EndAttributes()) |
|
475 .Times(0); |
|
476 EXPECT_CALL(*mock_grandchild_handler, Finish()) |
|
477 .Times(0); |
|
478 } |
|
479 |
|
480 EXPECT_CALL(*mock_child_handler, Finish()) |
|
481 .Times(0); |
|
482 } |
|
483 |
|
484 EXPECT_CALL(mock_root_handler, Finish()) |
|
485 .Times(0); |
|
486 } |
|
487 } |
|
488 |
|
489 // The dispatcher. |
|
490 DIEDispatcher die_dispatcher(&mock_root_handler); |
|
491 |
|
492 // Report the CU header. |
|
493 EXPECT_TRUE(die_dispatcher |
|
494 .StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89, |
|
495 0x76d392ff393ddda2LL, 0xbf)); |
|
496 // Report the root DIE. |
|
497 { |
|
498 EXPECT_TRUE(die_dispatcher.StartDIE(0xbf13b761691ddc91LL, |
|
499 (DwarfTag) 0x98980361)); |
|
500 |
|
501 // Child DIE. |
|
502 { |
|
503 EXPECT_TRUE(die_dispatcher.StartDIE(0x058f09240c5fc8c9LL, |
|
504 (DwarfTag) 0x898bf0d0)); |
|
505 |
|
506 // Grandchild DIE. |
|
507 { |
|
508 EXPECT_TRUE(die_dispatcher.StartDIE(0x32dc00c9945dc0c8LL, |
|
509 (DwarfTag) 0x2802d007)); |
|
510 die_dispatcher.ProcessAttributeSigned(0x32dc00c9945dc0c8LL, |
|
511 (DwarfAttribute) 0x4e2b7cfb, |
|
512 (DwarfForm) 0x610b7ae1, |
|
513 0x3ea5c609d7d7560fLL); |
|
514 |
|
515 // Stop the traversal abruptly, so that there will still be |
|
516 // handlers on the stack when the dispatcher is destructed. |
|
517 |
|
518 // No EndDIE call... |
|
519 } |
|
520 // No EndDIE call... |
|
521 } |
|
522 // No EndDIE call... |
|
523 } |
|
524 } |