OLD | NEW |
---|---|
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 | 60 |
61 namespace agent { | 61 namespace agent { |
62 namespace asan { | 62 namespace asan { |
63 | 63 |
64 namespace { | 64 namespace { |
65 | 65 |
66 using agent::asan::AsanLogger; | 66 using agent::asan::AsanLogger; |
67 using agent::asan::StackCaptureCache; | 67 using agent::asan::StackCaptureCache; |
68 using agent::asan::WindowsHeapAdapter; | 68 using agent::asan::WindowsHeapAdapter; |
69 | 69 |
70 enum CrashReporterType { | |
71 kDefaultCrashReporterType, | |
72 kBreakpadCrashReporterType, | |
73 kKaskoCrashReporterType, | |
74 kCrashpadCrashReporterType, | |
75 }; | |
76 | |
70 // A custom exception code we use to indicate that the exception originated | 77 // A custom exception code we use to indicate that the exception originated |
71 // from Asan, and shouldn't be processed again by our unhandled exception | 78 // from Asan, and shouldn't be processed again by our unhandled exception |
72 // handler. This value has been created according to the rules here: | 79 // handler. This value has been created according to the rules here: |
73 // http://msdn.microsoft.com/en-us/library/windows/hardware/ff543026(v=vs.85).as px | 80 // http://msdn.microsoft.com/en-us/library/windows/hardware/ff543026(v=vs.85).as px |
74 // See winerror.h for more details. | 81 // See winerror.h for more details. |
75 static const DWORD kAsanFacility = 0x68B; // No more than 11 bits. | 82 static const DWORD kAsanFacility = 0x68B; // No more than 11 bits. |
76 static const DWORD kAsanStatus = 0x5AD0; // No more than 16 bits. | 83 static const DWORD kAsanStatus = 0x5AD0; // No more than 16 bits. |
77 static const DWORD kAsanException = | 84 static const DWORD kAsanException = |
78 (3 << 30) | // Severity = error. | 85 (3 << 30) | // Severity = error. |
79 (1 << 29) | // Customer defined code (not defined by MS). | 86 (1 << 29) | // Customer defined code (not defined by MS). |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
380 ->WriteCorruptHeapInfo(corrupt_ranges, size, buffer, error_info); \ | 387 ->WriteCorruptHeapInfo(corrupt_ranges, size, buffer, error_info); \ |
381 } \ | 388 } \ |
382 } | 389 } |
383 | 390 |
384 void LaunchMessageBox(const base::StringPiece& message) { | 391 void LaunchMessageBox(const base::StringPiece& message) { |
385 // TODO(chrisha): Consider making this close itself with a timeout to prevent | 392 // TODO(chrisha): Consider making this close itself with a timeout to prevent |
386 // hangs on the waterfall. | 393 // hangs on the waterfall. |
387 ::MessageBoxA(nullptr, message.data(), nullptr, MB_OK | MB_ICONEXCLAMATION); | 394 ::MessageBoxA(nullptr, message.data(), nullptr, MB_OK | MB_ICONEXCLAMATION); |
388 } | 395 } |
389 | 396 |
390 std::unique_ptr<ReporterInterface> CreateCrashReporter(AsanLogger* logger) { | 397 // Gets the preferred crash reporter type from the environment. This will |
398 // override experiments or command-lines, and is largely meant for local | |
399 // testing. | |
400 CrashReporterType GetCrashReporterTypeFromEnvironment( | |
401 AsanLogger* logger) { | |
402 DCHECK_NE(static_cast<AsanLogger*>(nullptr), logger); | |
391 std::unique_ptr<ReporterInterface> reporter; | 403 std::unique_ptr<ReporterInterface> reporter; |
392 | 404 |
393 // First try to grab the preferred crash reporter, overridden by the | |
394 // environment. | |
395 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 405 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
396 std::string reporter_name; | 406 std::string reporter_name; |
397 if (env->GetVar("SYZYASAN_CRASH_REPORTER", &reporter_name)) { | 407 static const char kSyzyAsanCrashReporterEnv[] = |
398 if (reporter_name == "crashpad") | 408 "SYZYASAN_CRASH_REPORTER"; |
399 reporter.reset(reporters::CrashpadReporter::Create().release()); | 409 if (!env->GetVar(kSyzyAsanCrashReporterEnv, &reporter_name)) |
400 else if (reporter_name == "kasko") | 410 return kDefaultCrashReporterType; |
401 reporter.reset(reporters::KaskoReporter::Create().release()); | |
402 else if (reporter_name == "breakpad") | |
403 reporter.reset(reporters::BreakpadReporter::Create().release()); | |
404 | 411 |
405 if (reporter.get() != nullptr) { | 412 CrashReporterType type = kDefaultCrashReporterType; |
406 logger->Write(base::StringPrintf( | 413 if (reporter_name == "crashpad") { |
407 "Using requested \"%s\" crash reporter.", reporter_name)); | 414 type = kCrashpadCrashReporterType; |
408 return reporter; | 415 } else if (reporter_name == "kasko") { |
409 } else { | 416 type = kKaskoCrashReporterType; |
410 logger->Write(base::StringPrintf( | 417 } else if (reporter_name == "breakpad") { |
411 "Unable to create requested \"%s\" crash reporter.", reporter_name)); | 418 type = kBreakpadCrashReporterType; |
412 } | |
413 } | 419 } |
414 | 420 |
415 // No crash reporter was explicitly specified, or it was unable to be | 421 if (type != kDefaultCrashReporterType) { |
416 // initialized. Try all of them, starting with the most recent. | 422 logger->Write(base::StringPrintf("Encountered %s=\"%s\".", |
423 kSyzyAsanCrashReporterEnv, reporter_name.c_str())); | |
424 } else { | |
425 logger->Write(base::StringPrintf("Ignoring %s=\"%s\".", | |
426 kSyzyAsanCrashReporterEnv, reporter_name.c_str())); | |
427 } | |
417 | 428 |
418 // Don't try grabbing a Crashpad reporter by default, as we're not yet | 429 return type; |
419 // ready to ship this. | 430 } |
420 // TODO(chrisha): Add Crashpad support behind a feature flag. | 431 |
432 // Attempts to create a crash reporter, starting with the most modern. | |
433 std::unique_ptr<ReporterInterface> CreateCrashReporter( | |
434 AsanLogger* logger, CrashReporterType reporter_type) { | |
435 std::unique_ptr<ReporterInterface> reporter; | |
436 | |
437 // Crashpad is not yet enabled by default. | |
438 if (reporter_type == kCrashpadCrashReporterType) | |
439 reporter.reset(reporters::CrashpadReporter::Create().release()); | |
421 | 440 |
422 // Try to initialize a Kasko crash reporter. | 441 // Try to initialize a Kasko crash reporter. |
423 if (reporter.get() == nullptr) | 442 if (reporter.get() == nullptr && |
443 (reporter_type == kKaskoCrashReporterType || | |
444 reporter_type == kDefaultCrashReporterType)) { | |
424 reporter.reset(reporters::KaskoReporter::Create().release()); | 445 reporter.reset(reporters::KaskoReporter::Create().release()); |
446 } | |
425 | 447 |
426 // If that failed then try to initialize a Breakpad reporter. | 448 // If that failed then try to initialize a Breakpad reporter. |
427 if (reporter.get() == nullptr) | 449 if (reporter.get() == nullptr && |
450 (reporter_type == kBreakpadCrashReporterType || | |
451 reporter_type == kDefaultCrashReporterType)) { | |
428 reporter.reset(reporters::BreakpadReporter::Create().release()); | 452 reporter.reset(reporters::BreakpadReporter::Create().release()); |
453 } | |
429 | 454 |
430 return reporter; | 455 return reporter; |
431 } | 456 } |
432 | 457 |
433 } // namespace | 458 } // namespace |
434 | 459 |
435 base::Lock AsanRuntime::lock_; | 460 base::Lock AsanRuntime::lock_; |
436 AsanRuntime* AsanRuntime::runtime_ = NULL; | 461 AsanRuntime* AsanRuntime::runtime_ = NULL; |
437 LPTOP_LEVEL_EXCEPTION_FILTER AsanRuntime::previous_uef_ = NULL; | 462 LPTOP_LEVEL_EXCEPTION_FILTER AsanRuntime::previous_uef_ = NULL; |
438 bool AsanRuntime::uef_installed_ = false; | 463 bool AsanRuntime::uef_installed_ = false; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 if (!SetUpMemoryNotifier()) | 501 if (!SetUpMemoryNotifier()) |
477 return false; | 502 return false; |
478 if (!SetUpLogger()) | 503 if (!SetUpLogger()) |
479 return false; | 504 return false; |
480 if (!SetUpStackCache()) | 505 if (!SetUpStackCache()) |
481 return false; | 506 return false; |
482 if (!SetUpHeapManager()) | 507 if (!SetUpHeapManager()) |
483 return false; | 508 return false; |
484 WindowsHeapAdapter::SetUp(heap_manager_.get()); | 509 WindowsHeapAdapter::SetUp(heap_manager_.get()); |
485 | 510 |
511 // Determine the preferred crash reporter type, as specified in the | |
512 // environment. If this isn't present it defaults to | |
513 // kDefaultCrashReporterType, in which case experiments or command-line flags | |
514 // may specify the crash reporter to use. | |
515 CrashReporterType crash_reporter_type = | |
Sébastien Marchand
2016/06/01 16:38:55
We also have a 'disable_breakpad_reporting ' flag
chrisha
2016/06/02 17:45:30
Yup, the flag still exists and works. This line is
| |
516 GetCrashReporterTypeFromEnvironment(logger()); | |
517 | |
486 if (params_.feature_randomization) { | 518 if (params_.feature_randomization) { |
487 AsanFeatureSet feature_set = GenerateRandomFeatureSet(); | 519 AsanFeatureSet feature_set = GenerateRandomFeatureSet(); |
488 PropagateFeatureSet(feature_set); | 520 PropagateFeatureSet(feature_set); |
521 | |
522 // If no specific crash reporter has been specified, then allow the | |
523 // experiment to specify it. | |
524 if (crash_reporter_type == kDefaultCrashReporterType && | |
525 (feature_set & ASAN_FEATURE_ENABLE_CRASHPAD) != 0) { | |
526 crash_reporter_type = kCrashpadCrashReporterType; | |
527 } | |
489 } | 528 } |
490 | 529 |
491 // Propagates the flags values to the different modules. | 530 // Propagates the flags values to the different modules. |
492 PropagateParams(); | 531 PropagateParams(); |
493 | 532 |
494 // The name 'disable_breakpad_reporting' is legacy; this actually means to | 533 // The name 'disable_breakpad_reporting' is legacy; this actually means to |
495 // disable all external crash reporting integration. | 534 // disable all external crash reporting integration. |
496 if (!params_.disable_breakpad_reporting) | 535 if (!params_.disable_breakpad_reporting) { |
497 crash_reporter_.reset(CreateCrashReporter(logger()).release()); | 536 crash_reporter_.reset( |
537 CreateCrashReporter(logger(), crash_reporter_type).release()); | |
chrisha
2016/06/02 17:45:30
And it won't be created if --disable_breakpad_repo
| |
538 } | |
498 | 539 |
499 // Set up the appropriate error handler depending on whether or not | 540 // Set up the appropriate error handler depending on whether or not |
500 // we successfully found a crash reporter. | 541 // we successfully initialized a crash reporter. |
501 if (crash_reporter_.get() != nullptr) { | 542 if (crash_reporter_.get() != nullptr) { |
502 logger_->Write(base::StringPrintf( | 543 logger_->Write(base::StringPrintf( |
503 "SyzyASAN: Using %s for error reporting.", | 544 "SyzyASAN: Using %s for error reporting.", |
504 crash_reporter_->GetName())); | 545 crash_reporter_->GetName())); |
505 SetErrorCallBack(base::Bind(&CrashReporterErrorHandler)); | 546 SetErrorCallBack(base::Bind(&CrashReporterErrorHandler)); |
506 } else { | 547 } else { |
507 logger_->Write("SyzyASAN: Using default error reporting handler."); | 548 logger_->Write("SyzyASAN: Using default error reporting handler."); |
508 SetErrorCallBack(base::Bind(&DefaultErrorHandler)); | 549 SetErrorCallBack(base::Bind(&DefaultErrorHandler)); |
509 } | 550 } |
510 | 551 |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
954 } | 995 } |
955 | 996 |
956 // Print the Windbg information to display the free stack if present. | 997 // Print the Windbg information to display the free stack if present. |
957 if (error_info->block_info.free_stack_size != NULL) { | 998 if (error_info->block_info.free_stack_size != NULL) { |
958 AsanDbgMessage(L"Free stack trace:"); | 999 AsanDbgMessage(L"Free stack trace:"); |
959 AsanDbgCmd(L"dps %p l%d", error_info->block_info.free_stack, | 1000 AsanDbgCmd(L"dps %p l%d", error_info->block_info.free_stack, |
960 error_info->block_info.free_stack_size); | 1001 error_info->block_info.free_stack_size); |
961 } | 1002 } |
962 } | 1003 } |
963 | 1004 |
1005 // static | |
964 AsanFeatureSet AsanRuntime::GenerateRandomFeatureSet() { | 1006 AsanFeatureSet AsanRuntime::GenerateRandomFeatureSet() { |
965 AsanFeatureSet enabled_features = | 1007 AsanFeatureSet enabled_features = |
966 static_cast<AsanFeatureSet>(base::RandGenerator(ASAN_FEATURE_MAX)); | 1008 static_cast<AsanFeatureSet>(base::RandGenerator(ASAN_FEATURE_MAX)); |
967 DCHECK_LT(enabled_features, ASAN_FEATURE_MAX); | 1009 DCHECK_LT(enabled_features, ASAN_FEATURE_MAX); |
968 enabled_features &= kAsanValidFeatures; | 1010 enabled_features &= kAsanValidFeatures; |
969 return enabled_features; | 1011 return enabled_features; |
970 } | 1012 } |
971 | 1013 |
972 void AsanRuntime::PropagateFeatureSet(AsanFeatureSet feature_set) { | 1014 void AsanRuntime::PropagateFeatureSet(AsanFeatureSet feature_set) { |
973 DCHECK_EQ(0U, feature_set & ~kAsanValidFeatures); | 1015 DCHECK_EQ(0U, feature_set & ~kAsanValidFeatures); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1192 DCHECK(heap_manager_); | 1234 DCHECK(heap_manager_); |
1193 heap_manager_->DisableDeferredFreeThread(); | 1235 heap_manager_->DisableDeferredFreeThread(); |
1194 } | 1236 } |
1195 | 1237 |
1196 AsanFeatureSet AsanRuntime::GetEnabledFeatureSet() { | 1238 AsanFeatureSet AsanRuntime::GetEnabledFeatureSet() { |
1197 AsanFeatureSet enabled_features = static_cast<AsanFeatureSet>(0U); | 1239 AsanFeatureSet enabled_features = static_cast<AsanFeatureSet>(0U); |
1198 if (heap_manager_->enable_page_protections_) | 1240 if (heap_manager_->enable_page_protections_) |
1199 enabled_features |= ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS; | 1241 enabled_features |= ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS; |
1200 if (params_.enable_large_block_heap) | 1242 if (params_.enable_large_block_heap) |
1201 enabled_features |= ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP; | 1243 enabled_features |= ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP; |
1244 if (crash_reporter_->GetName() == reporters::CrashpadReporter::kName) | |
1245 enabled_features |= ASAN_FEATURE_ENABLE_CRASHPAD; | |
1202 | 1246 |
1203 return enabled_features; | 1247 return enabled_features; |
1204 } | 1248 } |
1205 | 1249 |
1206 } // namespace asan | 1250 } // namespace asan |
1207 } // namespace agent | 1251 } // namespace agent |
OLD | NEW |