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.
TEST(Dwarf2DIEHandler,SkipCompilationUnit)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.
TEST(Dwarf2DIEHandler,SkipRootDIE)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.
TEST(Dwarf2DIEHandler,SkipRootDIEChildren)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.
TEST(Dwarf2DIEHandler,PassAttributeValues)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
TEST(Dwarf2DIEHandler,FindAndSkipChildren)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.
TEST(Dwarf2DIEHandler,FreeHandlersOnStack)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 }
525