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