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/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/macros.h" | 20 #include "base/macros.h" |
21 #include "base/memory/ptr_util.h" | |
21 #include "base/profiler/win32_stack_frame_unwinder.h" | 22 #include "base/profiler/win32_stack_frame_unwinder.h" |
22 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
23 #include "base/strings/stringprintf.h" | 24 #include "base/strings/stringprintf.h" |
24 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
25 #include "base/time/time.h" | 26 #include "base/time/time.h" |
26 #include "base/win/pe_image.h" | 27 #include "base/win/pe_image.h" |
27 #include "base/win/scoped_handle.h" | 28 #include "base/win/scoped_handle.h" |
28 | 29 |
29 namespace base { | 30 namespace base { |
30 | 31 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 | 380 |
380 RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer); | 381 RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer); |
381 | 382 |
382 RecordStack(&thread_context, stack); | 383 RecordStack(&thread_context, stack); |
383 } | 384 } |
384 | 385 |
385 // NativeStackSamplerWin ------------------------------------------------------ | 386 // NativeStackSamplerWin ------------------------------------------------------ |
386 | 387 |
387 class NativeStackSamplerWin : public NativeStackSampler { | 388 class NativeStackSamplerWin : public NativeStackSampler { |
388 public: | 389 public: |
390 // Intended to hold the largest stack used by Chrome. The default Win32 | |
391 // reserved stack size is 1 MB and Chrome Windows threads currently always | |
392 // use the default, but this allows for expansion if it occurs. The size | |
393 // beyond the actual stack size consists of unallocated virtual memory pages | |
394 // so carries little cost (just a bit of wasted address space). | |
395 static constexpr size_t kStackCopyBufferSize = 2 * 1024 * 1024; | |
Mike Wittman
2017/05/10 17:17:21
This can be moved back into the private section.
bcwhite
2017/05/11 16:56:31
It has to be public to be accessible to NativeStac
Mike Wittman
2017/05/11 21:07:02
Ah, right.
Since it's only used by NativeStackSam
bcwhite
2017/05/12 13:11:29
Done.
| |
396 | |
389 NativeStackSamplerWin(win::ScopedHandle thread_handle, | 397 NativeStackSamplerWin(win::ScopedHandle thread_handle, |
390 AnnotateCallback annotator, | 398 AnnotateCallback annotator, |
391 NativeStackSamplerTestDelegate* test_delegate); | 399 NativeStackSamplerTestDelegate* test_delegate); |
392 ~NativeStackSamplerWin() override; | 400 ~NativeStackSamplerWin() override; |
393 | 401 |
394 // StackSamplingProfiler::NativeStackSampler: | 402 // StackSamplingProfiler::NativeStackSampler: |
395 void ProfileRecordingStarting( | 403 void ProfileRecordingStarting( |
396 std::vector<StackSamplingProfiler::Module>* modules) override; | 404 std::vector<StackSamplingProfiler::Module>* modules) override; |
397 void RecordStackSample(StackSamplingProfiler::Sample* sample) override; | 405 void RecordStackSample(StackBuffer* stack_buffer, |
398 void ProfileRecordingStopped() override; | 406 StackSamplingProfiler::Sample* sample) override; |
407 void ProfileRecordingStopped(StackBuffer* stack_buffer) override; | |
399 | 408 |
400 private: | 409 private: |
401 // Intended to hold the largest stack used by Chrome. The default Win32 | |
402 // reserved stack size is 1 MB and Chrome Windows threads currently always | |
403 // use the default, but this allows for expansion if it occurs. The size | |
404 // beyond the actual stack size consists of unallocated virtual memory pages | |
405 // so carries little cost (just a bit of wasted address space). | |
406 static constexpr size_t kStackCopyBufferSize = 2 * 1024 * 1024; | |
407 | |
408 // Attempts to query the module filename, base address, and id for | 410 // Attempts to query the module filename, base address, and id for |
409 // |module_handle|, and store them in |module|. Returns true if it succeeded. | 411 // |module_handle|, and store them in |module|. Returns true if it succeeded. |
410 static bool GetModuleForHandle(HMODULE module_handle, | 412 static bool GetModuleForHandle(HMODULE module_handle, |
411 StackSamplingProfiler::Module* module); | 413 StackSamplingProfiler::Module* module); |
412 | 414 |
413 // Gets the index for the Module corresponding to |module_handle| in | 415 // Gets the index for the Module corresponding to |module_handle| in |
414 // |modules|, adding it if it's not already present. Returns | 416 // |modules|, adding it if it's not already present. Returns |
415 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be | 417 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be |
416 // determined for |module|. | 418 // determined for |module|. |
417 size_t GetModuleIndex(HMODULE module_handle, | 419 size_t GetModuleIndex(HMODULE module_handle, |
418 std::vector<StackSamplingProfiler::Module>* modules); | 420 std::vector<StackSamplingProfiler::Module>* modules); |
419 | 421 |
420 // Copies the information represented by |stack| into |sample| and |modules|. | 422 // Copies the information represented by |stack| into |sample| and |modules|. |
421 void CopyToSample(const std::vector<RecordedFrame>& stack, | 423 void CopyToSample(const std::vector<RecordedFrame>& stack, |
422 StackSamplingProfiler::Sample* sample, | 424 StackSamplingProfiler::Sample* sample, |
423 std::vector<StackSamplingProfiler::Module>* modules); | 425 std::vector<StackSamplingProfiler::Module>* modules); |
424 | 426 |
425 win::ScopedHandle thread_handle_; | 427 win::ScopedHandle thread_handle_; |
426 | 428 |
427 const AnnotateCallback annotator_; | 429 const AnnotateCallback annotator_; |
428 | 430 |
429 NativeStackSamplerTestDelegate* const test_delegate_; | 431 NativeStackSamplerTestDelegate* const test_delegate_; |
430 | 432 |
431 // The stack base address corresponding to |thread_handle_|. | 433 // The stack base address corresponding to |thread_handle_|. |
432 const void* const thread_stack_base_address_; | 434 const void* const thread_stack_base_address_; |
433 | 435 |
434 // Buffer to use for copies of the stack. We use the same buffer for all the | |
435 // samples to avoid the overhead of multiple allocations and frees. | |
436 const std::unique_ptr<unsigned char[]> stack_copy_buffer_; | |
437 | |
438 // Weak. Points to the modules associated with the profile being recorded | 436 // Weak. Points to the modules associated with the profile being recorded |
439 // between ProfileRecordingStarting() and ProfileRecordingStopped(). | 437 // between ProfileRecordingStarting() and ProfileRecordingStopped(). |
440 std::vector<StackSamplingProfiler::Module>* current_modules_; | 438 std::vector<StackSamplingProfiler::Module>* current_modules_; |
441 | 439 |
442 // Maps a module handle to the corresponding Module's index within | 440 // Maps a module handle to the corresponding Module's index within |
443 // current_modules_. | 441 // current_modules_. |
444 std::map<HMODULE, size_t> profile_module_index_; | 442 std::map<HMODULE, size_t> profile_module_index_; |
445 | 443 |
446 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); | 444 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); |
447 }; | 445 }; |
448 | 446 |
449 NativeStackSamplerWin::NativeStackSamplerWin( | 447 NativeStackSamplerWin::NativeStackSamplerWin( |
450 win::ScopedHandle thread_handle, | 448 win::ScopedHandle thread_handle, |
451 AnnotateCallback annotator, | 449 AnnotateCallback annotator, |
452 NativeStackSamplerTestDelegate* test_delegate) | 450 NativeStackSamplerTestDelegate* test_delegate) |
453 : thread_handle_(thread_handle.Take()), | 451 : thread_handle_(thread_handle.Take()), |
454 annotator_(annotator), | 452 annotator_(annotator), |
455 test_delegate_(test_delegate), | 453 test_delegate_(test_delegate), |
456 thread_stack_base_address_( | 454 thread_stack_base_address_( |
457 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase), | 455 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase) { |
458 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) { | |
459 DCHECK(annotator_); | 456 DCHECK(annotator_); |
460 } | 457 } |
461 | 458 |
462 NativeStackSamplerWin::~NativeStackSamplerWin() { | 459 NativeStackSamplerWin::~NativeStackSamplerWin() { |
463 } | 460 } |
464 | 461 |
465 void NativeStackSamplerWin::ProfileRecordingStarting( | 462 void NativeStackSamplerWin::ProfileRecordingStarting( |
466 std::vector<StackSamplingProfiler::Module>* modules) { | 463 std::vector<StackSamplingProfiler::Module>* modules) { |
467 current_modules_ = modules; | 464 current_modules_ = modules; |
468 profile_module_index_.clear(); | 465 profile_module_index_.clear(); |
469 } | 466 } |
470 | 467 |
471 void NativeStackSamplerWin::RecordStackSample( | 468 void NativeStackSamplerWin::RecordStackSample( |
469 StackBuffer* stack_buffer, | |
472 StackSamplingProfiler::Sample* sample) { | 470 StackSamplingProfiler::Sample* sample) { |
471 DCHECK(stack_buffer); | |
473 DCHECK(current_modules_); | 472 DCHECK(current_modules_); |
474 | 473 |
475 std::vector<RecordedFrame> stack; | 474 std::vector<RecordedFrame> stack; |
476 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, | 475 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, |
477 stack_copy_buffer_.get(), kStackCopyBufferSize, | 476 stack_buffer->buffer(), stack_buffer->size(), |
478 &stack, annotator_, sample, test_delegate_); | 477 &stack, annotator_, sample, test_delegate_); |
479 CopyToSample(stack, sample, current_modules_); | 478 CopyToSample(stack, sample, current_modules_); |
480 } | 479 } |
481 | 480 |
482 void NativeStackSamplerWin::ProfileRecordingStopped() { | 481 void NativeStackSamplerWin::ProfileRecordingStopped(StackBuffer* stack_buffer) { |
483 current_modules_ = nullptr; | 482 current_modules_ = nullptr; |
484 } | 483 } |
485 | 484 |
486 // static | 485 // static |
487 bool NativeStackSamplerWin::GetModuleForHandle( | 486 bool NativeStackSamplerWin::GetModuleForHandle( |
488 HMODULE module_handle, | 487 HMODULE module_handle, |
489 StackSamplingProfiler::Module* module) { | 488 StackSamplingProfiler::Module* module) { |
490 wchar_t module_name[MAX_PATH]; | 489 wchar_t module_name[MAX_PATH]; |
491 DWORD result_length = | 490 DWORD result_length = |
492 GetModuleFileName(module_handle, module_name, arraysize(module_name)); | 491 GetModuleFileName(module_handle, module_name, arraysize(module_name)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
551 thread_id); | 550 thread_id); |
552 | 551 |
553 if (thread_handle) { | 552 if (thread_handle) { |
554 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( | 553 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( |
555 win::ScopedHandle(thread_handle), annotator, test_delegate)); | 554 win::ScopedHandle(thread_handle), annotator, test_delegate)); |
556 } | 555 } |
557 #endif | 556 #endif |
558 return std::unique_ptr<NativeStackSampler>(); | 557 return std::unique_ptr<NativeStackSampler>(); |
559 } | 558 } |
560 | 559 |
560 std::unique_ptr<NativeStackSampler::StackBuffer> | |
561 NativeStackSampler::CreateStackBuffer() { | |
562 return MakeUnique<StackBuffer>(NativeStackSamplerWin::kStackCopyBufferSize); | |
563 } | |
564 | |
561 } // namespace base | 565 } // namespace base |
OLD | NEW |