dwarf2diehandler_unittest.cc
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 <jimb@mozilla.com> <jimb@red-bean.com> 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. 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. 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. 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. 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 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. 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 }