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