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 } 525