Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(583)

Side by Side Diff: base/profiler/native_stack_sampler_win.cc

Issue 2444143002: Add process lifetime annotations to stack samples. (Closed)
Patch Set: abandon generator for on-the-fly Profiles creation Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/profiler/native_stack_sampler_posix.cc ('k') | base/profiler/stack_sampling_profiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 // IMPORTANT NOTE: No allocations from the default heap may occur in the 325 // IMPORTANT NOTE: No allocations from the default heap may occur in the
326 // ScopedSuspendThread scope, including indirectly via use of DCHECK/CHECK or 326 // ScopedSuspendThread scope, including indirectly via use of DCHECK/CHECK or
327 // other logging statements. Otherwise this code can deadlock on heap locks in 327 // other logging statements. Otherwise this code can deadlock on heap locks in
328 // the default heap acquired by the target thread before it was suspended. 328 // the default heap acquired by the target thread before it was suspended.
329 void SuspendThreadAndRecordStack( 329 void SuspendThreadAndRecordStack(
330 HANDLE thread_handle, 330 HANDLE thread_handle,
331 const void* base_address, 331 const void* base_address,
332 void* stack_copy_buffer, 332 void* stack_copy_buffer,
333 size_t stack_copy_buffer_size, 333 size_t stack_copy_buffer_size,
334 std::vector<RecordedFrame>* stack, 334 std::vector<RecordedFrame>* stack,
335 NativeStackSampler::AnnotateCallback annotator,
336 StackSamplingProfiler::Sample* sample,
335 NativeStackSamplerTestDelegate* test_delegate) { 337 NativeStackSamplerTestDelegate* test_delegate) {
336 DCHECK(stack->empty()); 338 DCHECK(stack->empty());
337 339
338 CONTEXT thread_context = {0}; 340 CONTEXT thread_context = {0};
339 thread_context.ContextFlags = CONTEXT_FULL; 341 thread_context.ContextFlags = CONTEXT_FULL;
340 // The stack bounds are saved to uintptr_ts for use outside 342 // The stack bounds are saved to uintptr_ts for use outside
341 // ScopedSuspendThread, as the thread's memory is not safe to dereference 343 // ScopedSuspendThread, as the thread's memory is not safe to dereference
342 // beyond that point. 344 // beyond that point.
343 const uintptr_t top = reinterpret_cast<uintptr_t>(base_address); 345 const uintptr_t top = reinterpret_cast<uintptr_t>(base_address);
344 uintptr_t bottom = 0u; 346 uintptr_t bottom = 0u;
(...skipping 14 matching lines...) Expand all
359 361
360 if ((top - bottom) > stack_copy_buffer_size) 362 if ((top - bottom) > stack_copy_buffer_size)
361 return; 363 return;
362 364
363 // Dereferencing a pointer in the guard page in a thread that doesn't own 365 // Dereferencing a pointer in the guard page in a thread that doesn't own
364 // the stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a crash. 366 // the stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a crash.
365 // This occurs very rarely, but reliably over the population. 367 // This occurs very rarely, but reliably over the population.
366 if (PointsToGuardPage(bottom)) 368 if (PointsToGuardPage(bottom))
367 return; 369 return;
368 370
371 (*annotator)(sample);
372
369 CopyMemoryFromStack(stack_copy_buffer, 373 CopyMemoryFromStack(stack_copy_buffer,
370 reinterpret_cast<const void*>(bottom), top - bottom); 374 reinterpret_cast<const void*>(bottom), top - bottom);
371 } 375 }
372 376
373 if (test_delegate) 377 if (test_delegate)
374 test_delegate->OnPreStackWalk(); 378 test_delegate->OnPreStackWalk();
375 379
376 RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer); 380 RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer);
377 381
378 RecordStack(&thread_context, stack); 382 RecordStack(&thread_context, stack);
379 } 383 }
380 384
381 // NativeStackSamplerWin ------------------------------------------------------ 385 // NativeStackSamplerWin ------------------------------------------------------
382 386
383 class NativeStackSamplerWin : public NativeStackSampler { 387 class NativeStackSamplerWin : public NativeStackSampler {
384 public: 388 public:
385 NativeStackSamplerWin(win::ScopedHandle thread_handle, 389 NativeStackSamplerWin(win::ScopedHandle thread_handle,
390 AnnotateCallback annotator,
386 NativeStackSamplerTestDelegate* test_delegate); 391 NativeStackSamplerTestDelegate* test_delegate);
387 ~NativeStackSamplerWin() override; 392 ~NativeStackSamplerWin() override;
388 393
389 // StackSamplingProfiler::NativeStackSampler: 394 // StackSamplingProfiler::NativeStackSampler:
390 void ProfileRecordingStarting( 395 void ProfileRecordingStarting(
391 std::vector<StackSamplingProfiler::Module>* modules) override; 396 std::vector<StackSamplingProfiler::Module>* modules) override;
392 void RecordStackSample(StackSamplingProfiler::Sample* sample) override; 397 void RecordStackSample(StackSamplingProfiler::Sample* sample) override;
393 void ProfileRecordingStopped() override; 398 void ProfileRecordingStopped() override;
394 399
395 private: 400 private:
(...skipping 18 matching lines...) Expand all
414 size_t GetModuleIndex(HMODULE module_handle, 419 size_t GetModuleIndex(HMODULE module_handle,
415 std::vector<StackSamplingProfiler::Module>* modules); 420 std::vector<StackSamplingProfiler::Module>* modules);
416 421
417 // Copies the information represented by |stack| into |sample| and |modules|. 422 // Copies the information represented by |stack| into |sample| and |modules|.
418 void CopyToSample(const std::vector<RecordedFrame>& stack, 423 void CopyToSample(const std::vector<RecordedFrame>& stack,
419 StackSamplingProfiler::Sample* sample, 424 StackSamplingProfiler::Sample* sample,
420 std::vector<StackSamplingProfiler::Module>* modules); 425 std::vector<StackSamplingProfiler::Module>* modules);
421 426
422 win::ScopedHandle thread_handle_; 427 win::ScopedHandle thread_handle_;
423 428
429 const AnnotateCallback annotator_;
430
424 NativeStackSamplerTestDelegate* const test_delegate_; 431 NativeStackSamplerTestDelegate* const test_delegate_;
425 432
426 // The stack base address corresponding to |thread_handle_|. 433 // The stack base address corresponding to |thread_handle_|.
427 const void* const thread_stack_base_address_; 434 const void* const thread_stack_base_address_;
428 435
429 // Buffer to use for copies of the stack. We use the same buffer for all the 436 // Buffer to use for copies of the stack. We use the same buffer for all the
430 // samples to avoid the overhead of multiple allocations and frees. 437 // samples to avoid the overhead of multiple allocations and frees.
431 const std::unique_ptr<unsigned char[]> stack_copy_buffer_; 438 const std::unique_ptr<unsigned char[]> stack_copy_buffer_;
432 439
433 // Weak. Points to the modules associated with the profile being recorded 440 // Weak. Points to the modules associated with the profile being recorded
434 // between ProfileRecordingStarting() and ProfileRecordingStopped(). 441 // between ProfileRecordingStarting() and ProfileRecordingStopped().
435 std::vector<StackSamplingProfiler::Module>* current_modules_; 442 std::vector<StackSamplingProfiler::Module>* current_modules_;
436 443
437 // Maps a module handle to the corresponding Module's index within 444 // Maps a module handle to the corresponding Module's index within
438 // current_modules_. 445 // current_modules_.
439 std::map<HMODULE, size_t> profile_module_index_; 446 std::map<HMODULE, size_t> profile_module_index_;
440 447
441 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); 448 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
442 }; 449 };
443 450
444 NativeStackSamplerWin::NativeStackSamplerWin( 451 NativeStackSamplerWin::NativeStackSamplerWin(
445 win::ScopedHandle thread_handle, 452 win::ScopedHandle thread_handle,
453 AnnotateCallback annotator,
446 NativeStackSamplerTestDelegate* test_delegate) 454 NativeStackSamplerTestDelegate* test_delegate)
447 : thread_handle_(thread_handle.Take()), test_delegate_(test_delegate), 455 : thread_handle_(thread_handle.Take()),
456 annotator_(annotator),
457 test_delegate_(test_delegate),
448 thread_stack_base_address_( 458 thread_stack_base_address_(
449 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase), 459 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase),
450 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) { 460 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) {
461 DCHECK(annotator_);
451 } 462 }
452 463
453 NativeStackSamplerWin::~NativeStackSamplerWin() { 464 NativeStackSamplerWin::~NativeStackSamplerWin() {
454 } 465 }
455 466
456 void NativeStackSamplerWin::ProfileRecordingStarting( 467 void NativeStackSamplerWin::ProfileRecordingStarting(
457 std::vector<StackSamplingProfiler::Module>* modules) { 468 std::vector<StackSamplingProfiler::Module>* modules) {
458 current_modules_ = modules; 469 current_modules_ = modules;
459 profile_module_index_.clear(); 470 profile_module_index_.clear();
460 } 471 }
461 472
462 void NativeStackSamplerWin::RecordStackSample( 473 void NativeStackSamplerWin::RecordStackSample(
463 StackSamplingProfiler::Sample* sample) { 474 StackSamplingProfiler::Sample* sample) {
464 DCHECK(current_modules_); 475 DCHECK(current_modules_);
465 476
466 if (!stack_copy_buffer_) 477 if (!stack_copy_buffer_)
467 return; 478 return;
468 479
469 std::vector<RecordedFrame> stack; 480 std::vector<RecordedFrame> stack;
470 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, 481 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_,
471 stack_copy_buffer_.get(), kStackCopyBufferSize, 482 stack_copy_buffer_.get(), kStackCopyBufferSize,
472 &stack, test_delegate_); 483 &stack, annotator_, sample, test_delegate_);
473 CopyToSample(stack, sample, current_modules_); 484 CopyToSample(stack, sample, current_modules_);
474 } 485 }
475 486
476 void NativeStackSamplerWin::ProfileRecordingStopped() { 487 void NativeStackSamplerWin::ProfileRecordingStopped() {
477 current_modules_ = nullptr; 488 current_modules_ = nullptr;
478 } 489 }
479 490
480 // static 491 // static
481 bool NativeStackSamplerWin::GetModuleForHandle( 492 bool NativeStackSamplerWin::GetModuleForHandle(
482 HMODULE module_handle, 493 HMODULE module_handle,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 module_handle, modules->size() - 1)).first; 525 module_handle, modules->size() - 1)).first;
515 } 526 }
516 527
517 return loc->second; 528 return loc->second;
518 } 529 }
519 530
520 void NativeStackSamplerWin::CopyToSample( 531 void NativeStackSamplerWin::CopyToSample(
521 const std::vector<RecordedFrame>& stack, 532 const std::vector<RecordedFrame>& stack,
522 StackSamplingProfiler::Sample* sample, 533 StackSamplingProfiler::Sample* sample,
523 std::vector<StackSamplingProfiler::Module>* modules) { 534 std::vector<StackSamplingProfiler::Module>* modules) {
524 sample->clear(); 535 sample->frames.clear();
525 sample->reserve(stack.size()); 536 sample->frames.reserve(stack.size());
526 537
527 for (const RecordedFrame& frame : stack) { 538 for (const RecordedFrame& frame : stack) {
528 sample->push_back(StackSamplingProfiler::Frame( 539 sample->frames.push_back(StackSamplingProfiler::Frame(
529 reinterpret_cast<uintptr_t>(frame.instruction_pointer), 540 reinterpret_cast<uintptr_t>(frame.instruction_pointer),
530 GetModuleIndex(frame.module.Get(), modules))); 541 GetModuleIndex(frame.module.Get(), modules)));
531 } 542 }
532 } 543 }
533 544
534 } // namespace 545 } // namespace
535 546
536 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create( 547 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
537 PlatformThreadId thread_id, 548 PlatformThreadId thread_id,
549 AnnotateCallback annotator,
538 NativeStackSamplerTestDelegate* test_delegate) { 550 NativeStackSamplerTestDelegate* test_delegate) {
539 #if _WIN64 551 #if _WIN64
540 // Get the thread's handle. 552 // Get the thread's handle.
541 HANDLE thread_handle = ::OpenThread( 553 HANDLE thread_handle = ::OpenThread(
542 THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, 554 THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
543 FALSE, 555 FALSE,
544 thread_id); 556 thread_id);
545 557
546 if (thread_handle) { 558 if (thread_handle) {
547 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( 559 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin(
548 win::ScopedHandle(thread_handle), test_delegate)); 560 win::ScopedHandle(thread_handle), annotator, test_delegate));
549 } 561 }
550 #endif 562 #endif
551 return std::unique_ptr<NativeStackSampler>(); 563 return std::unique_ptr<NativeStackSampler>();
552 } 564 }
553 565
554 } // namespace base 566 } // namespace base
OLDNEW
« no previous file with comments | « base/profiler/native_stack_sampler_posix.cc ('k') | base/profiler/stack_sampling_profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698