OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/profiler/native_stack_sampler.h" | 5 #include "base/profiler/native_stack_sampler.h" |
6 | 6 |
7 #include <objbase.h> | 7 #include <objbase.h> |
8 #include <windows.h> | 8 #include <windows.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 #include <winternl.h> | 10 #include <winternl.h> |
11 | 11 |
12 #include <cstdlib> | 12 #include <cstdlib> |
13 #include <map> | 13 #include <map> |
14 #include <memory> | 14 #include <memory> |
15 #include <utility> | 15 #include <utility> |
16 #include <vector> | 16 #include <vector> |
17 | 17 |
18 #include "base/atomicops.h" | |
Mike Wittman
2017/01/24 17:20:57
No longer needed.
bcwhite
2017/02/07 15:16:36
Done.
| |
18 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
19 #include "base/logging.h" | 20 #include "base/logging.h" |
20 #include "base/macros.h" | 21 #include "base/macros.h" |
22 #include "base/memory/ptr_util.h" | |
21 #include "base/profiler/win32_stack_frame_unwinder.h" | 23 #include "base/profiler/win32_stack_frame_unwinder.h" |
22 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
23 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
24 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
27 #include "base/synchronization/lock.h" | |
Mike Wittman
2017/01/24 17:20:57
No longer needed.
bcwhite
2017/02/07 15:16:36
Done.
| |
25 #include "base/time/time.h" | 28 #include "base/time/time.h" |
26 #include "base/win/pe_image.h" | 29 #include "base/win/pe_image.h" |
27 #include "base/win/scoped_handle.h" | 30 #include "base/win/scoped_handle.h" |
28 | 31 |
29 namespace base { | 32 namespace base { |
30 | 33 |
31 // Stack recording functions -------------------------------------------------- | 34 // Stack recording functions -------------------------------------------------- |
32 | 35 |
33 namespace { | 36 namespace { |
34 | 37 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 // NativeStackSamplerWin ------------------------------------------------------ | 388 // NativeStackSamplerWin ------------------------------------------------------ |
386 | 389 |
387 class NativeStackSamplerWin : public NativeStackSampler { | 390 class NativeStackSamplerWin : public NativeStackSampler { |
388 public: | 391 public: |
389 NativeStackSamplerWin(win::ScopedHandle thread_handle, | 392 NativeStackSamplerWin(win::ScopedHandle thread_handle, |
390 AnnotateCallback annotator, | 393 AnnotateCallback annotator, |
391 NativeStackSamplerTestDelegate* test_delegate); | 394 NativeStackSamplerTestDelegate* test_delegate); |
392 ~NativeStackSamplerWin() override; | 395 ~NativeStackSamplerWin() override; |
393 | 396 |
394 // StackSamplingProfiler::NativeStackSampler: | 397 // StackSamplingProfiler::NativeStackSampler: |
398 std::unique_ptr<Common> CreateCommon() override; | |
395 void ProfileRecordingStarting( | 399 void ProfileRecordingStarting( |
400 Common* common, | |
396 std::vector<StackSamplingProfiler::Module>* modules) override; | 401 std::vector<StackSamplingProfiler::Module>* modules) override; |
397 void RecordStackSample(StackSamplingProfiler::Sample* sample) override; | 402 void RecordStackSample(Common* common, |
398 void ProfileRecordingStopped() override; | 403 StackSamplingProfiler::Sample* sample) override; |
404 void ProfileRecordingStopped(Common* common) override; | |
399 | 405 |
400 private: | 406 private: |
401 enum { | 407 enum { |
402 // Intended to hold the largest stack used by Chrome. The default Win32 | 408 // Intended to hold the largest stack used by Chrome. The default Win32 |
403 // reserved stack size is 1 MB and Chrome Windows threads currently always | 409 // reserved stack size is 1 MB and Chrome Windows threads currently always |
404 // use the default, but this allows for expansion if it occurs. The size | 410 // use the default, but this allows for expansion if it occurs. The size |
405 // beyond the actual stack size consists of unallocated virtual memory pages | 411 // beyond the actual stack size consists of unallocated virtual memory pages |
406 // so carries little cost (just a bit of wasted address space). | 412 // so carries little cost (just a bit of wasted address space). |
407 kStackCopyBufferSize = 2 * 1024 * 1024 | 413 kStackCopyBufferSize = 2 * 1024 * 1024 |
408 }; | 414 }; |
409 | 415 |
416 class WinCommon : public Common { | |
Mike Wittman
2017/01/24 17:20:57
WinCommon => CommonWin (or actually StackBufferWin
bcwhite
2017/02/07 15:16:35
Done.
| |
417 public: | |
418 WinCommon() {} | |
419 ~WinCommon() override {} | |
420 | |
421 // Buffer to use for copies of the stack. | |
422 unsigned char stack_copy_buffer_[kStackCopyBufferSize]; | |
423 }; | |
424 | |
410 // Attempts to query the module filename, base address, and id for | 425 // Attempts to query the module filename, base address, and id for |
411 // |module_handle|, and store them in |module|. Returns true if it succeeded. | 426 // |module_handle|, and store them in |module|. Returns true if it succeeded. |
412 static bool GetModuleForHandle(HMODULE module_handle, | 427 static bool GetModuleForHandle(HMODULE module_handle, |
413 StackSamplingProfiler::Module* module); | 428 StackSamplingProfiler::Module* module); |
414 | 429 |
415 // Gets the index for the Module corresponding to |module_handle| in | 430 // Gets the index for the Module corresponding to |module_handle| in |
416 // |modules|, adding it if it's not already present. Returns | 431 // |modules|, adding it if it's not already present. Returns |
417 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be | 432 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be |
418 // determined for |module|. | 433 // determined for |module|. |
419 size_t GetModuleIndex(HMODULE module_handle, | 434 size_t GetModuleIndex(HMODULE module_handle, |
420 std::vector<StackSamplingProfiler::Module>* modules); | 435 std::vector<StackSamplingProfiler::Module>* modules); |
421 | 436 |
422 // Copies the information represented by |stack| into |sample| and |modules|. | 437 // Copies the information represented by |stack| into |sample| and |modules|. |
423 void CopyToSample(const std::vector<RecordedFrame>& stack, | 438 void CopyToSample(const std::vector<RecordedFrame>& stack, |
424 StackSamplingProfiler::Sample* sample, | 439 StackSamplingProfiler::Sample* sample, |
425 std::vector<StackSamplingProfiler::Module>* modules); | 440 std::vector<StackSamplingProfiler::Module>* modules); |
426 | 441 |
427 win::ScopedHandle thread_handle_; | 442 win::ScopedHandle thread_handle_; |
428 | 443 |
429 const AnnotateCallback annotator_; | 444 const AnnotateCallback annotator_; |
430 | 445 |
431 NativeStackSamplerTestDelegate* const test_delegate_; | 446 NativeStackSamplerTestDelegate* const test_delegate_; |
432 | 447 |
433 // The stack base address corresponding to |thread_handle_|. | 448 // The stack base address corresponding to |thread_handle_|. |
434 const void* const thread_stack_base_address_; | 449 const void* const thread_stack_base_address_; |
435 | 450 |
436 // Buffer to use for copies of the stack. We use the same buffer for all the | |
437 // samples to avoid the overhead of multiple allocations and frees. | |
438 const std::unique_ptr<unsigned char[]> stack_copy_buffer_; | |
439 | |
440 // Weak. Points to the modules associated with the profile being recorded | 451 // Weak. Points to the modules associated with the profile being recorded |
441 // between ProfileRecordingStarting() and ProfileRecordingStopped(). | 452 // between ProfileRecordingStarting() and ProfileRecordingStopped(). |
442 std::vector<StackSamplingProfiler::Module>* current_modules_; | 453 std::vector<StackSamplingProfiler::Module>* current_modules_; |
443 | 454 |
444 // Maps a module handle to the corresponding Module's index within | 455 // Maps a module handle to the corresponding Module's index within |
445 // current_modules_. | 456 // current_modules_. |
446 std::map<HMODULE, size_t> profile_module_index_; | 457 std::map<HMODULE, size_t> profile_module_index_; |
447 | 458 |
459 // This "in use" flag is used to validate the assumption that there are no | |
460 // concurrent stack sampling requests regardless of how many instances of | |
461 // this class are currently active. | |
462 static subtle::AtomicWord stack_copy_buffer_in_use_; | |
Mike Wittman
2017/01/24 17:20:57
No longer needed.
bcwhite
2017/02/07 15:16:35
Done.
| |
463 | |
448 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); | 464 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); |
449 }; | 465 }; |
450 | 466 |
451 NativeStackSamplerWin::NativeStackSamplerWin( | 467 NativeStackSamplerWin::NativeStackSamplerWin( |
452 win::ScopedHandle thread_handle, | 468 win::ScopedHandle thread_handle, |
453 AnnotateCallback annotator, | 469 AnnotateCallback annotator, |
454 NativeStackSamplerTestDelegate* test_delegate) | 470 NativeStackSamplerTestDelegate* test_delegate) |
455 : thread_handle_(thread_handle.Take()), | 471 : thread_handle_(thread_handle.Take()), |
456 annotator_(annotator), | 472 annotator_(annotator), |
457 test_delegate_(test_delegate), | 473 test_delegate_(test_delegate), |
458 thread_stack_base_address_( | 474 thread_stack_base_address_( |
459 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase), | 475 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase) { |
460 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) { | |
461 DCHECK(annotator_); | 476 DCHECK(annotator_); |
462 } | 477 } |
463 | 478 |
464 NativeStackSamplerWin::~NativeStackSamplerWin() { | 479 NativeStackSamplerWin::~NativeStackSamplerWin() { |
465 } | 480 } |
466 | 481 |
482 std::unique_ptr<NativeStackSampler::Common> | |
483 NativeStackSamplerWin::CreateCommon() { | |
484 return MakeUnique<WinCommon>(); | |
485 } | |
486 | |
467 void NativeStackSamplerWin::ProfileRecordingStarting( | 487 void NativeStackSamplerWin::ProfileRecordingStarting( |
488 Common* common, | |
468 std::vector<StackSamplingProfiler::Module>* modules) { | 489 std::vector<StackSamplingProfiler::Module>* modules) { |
469 current_modules_ = modules; | 490 current_modules_ = modules; |
470 profile_module_index_.clear(); | 491 profile_module_index_.clear(); |
471 } | 492 } |
472 | 493 |
473 void NativeStackSamplerWin::RecordStackSample( | 494 void NativeStackSamplerWin::RecordStackSample( |
495 Common* common, | |
474 StackSamplingProfiler::Sample* sample) { | 496 StackSamplingProfiler::Sample* sample) { |
497 DCHECK(common); | |
475 DCHECK(current_modules_); | 498 DCHECK(current_modules_); |
476 | 499 |
477 if (!stack_copy_buffer_) | |
478 return; | |
479 | |
480 std::vector<RecordedFrame> stack; | 500 std::vector<RecordedFrame> stack; |
481 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, | 501 SuspendThreadAndRecordStack( |
482 stack_copy_buffer_.get(), kStackCopyBufferSize, | 502 thread_handle_.Get(), thread_stack_base_address_, |
483 &stack, annotator_, sample, test_delegate_); | 503 reinterpret_cast<WinCommon*>(common)->stack_copy_buffer_, |
Mike Wittman
2017/01/24 17:20:57
static_cast for downcast
bcwhite
2017/02/07 15:16:36
Done.
| |
504 kStackCopyBufferSize, &stack, annotator_, sample, test_delegate_); | |
484 CopyToSample(stack, sample, current_modules_); | 505 CopyToSample(stack, sample, current_modules_); |
485 } | 506 } |
486 | 507 |
487 void NativeStackSamplerWin::ProfileRecordingStopped() { | 508 void NativeStackSamplerWin::ProfileRecordingStopped(Common* common) { |
488 current_modules_ = nullptr; | 509 current_modules_ = nullptr; |
489 } | 510 } |
490 | 511 |
491 // static | 512 // static |
492 bool NativeStackSamplerWin::GetModuleForHandle( | 513 bool NativeStackSamplerWin::GetModuleForHandle( |
493 HMODULE module_handle, | 514 HMODULE module_handle, |
494 StackSamplingProfiler::Module* module) { | 515 StackSamplingProfiler::Module* module) { |
495 wchar_t module_name[MAX_PATH]; | 516 wchar_t module_name[MAX_PATH]; |
496 DWORD result_length = | 517 DWORD result_length = |
497 GetModuleFileName(module_handle, module_name, arraysize(module_name)); | 518 GetModuleFileName(module_handle, module_name, arraysize(module_name)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 | 578 |
558 if (thread_handle) { | 579 if (thread_handle) { |
559 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( | 580 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( |
560 win::ScopedHandle(thread_handle), annotator, test_delegate)); | 581 win::ScopedHandle(thread_handle), annotator, test_delegate)); |
561 } | 582 } |
562 #endif | 583 #endif |
563 return std::unique_ptr<NativeStackSampler>(); | 584 return std::unique_ptr<NativeStackSampler>(); |
564 } | 585 } |
565 | 586 |
566 } // namespace base | 587 } // namespace base |
OLD | NEW |