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

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

Issue 2444143002: Add process lifetime annotations to stack samples. (Closed)
Patch Set: updated proto to pass individual repeated enumeration values Created 4 years, 1 month 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
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>
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/bind.h"
Mike Wittman 2016/11/02 21:44:04 This can be removed.
bcwhite 2016/11/03 18:29:49 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"
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"
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 // IMPORTANT NOTE: No allocations from the default heap may occur in the 313 // IMPORTANT NOTE: No allocations from the default heap may occur in the
313 // ScopedSuspendThread scope, including indirectly via use of DCHECK/CHECK or 314 // ScopedSuspendThread scope, including indirectly via use of DCHECK/CHECK or
314 // other logging statements. Otherwise this code can deadlock on heap locks in 315 // other logging statements. Otherwise this code can deadlock on heap locks in
315 // the default heap acquired by the target thread before it was suspended. 316 // the default heap acquired by the target thread before it was suspended.
316 void SuspendThreadAndRecordStack( 317 void SuspendThreadAndRecordStack(
317 HANDLE thread_handle, 318 HANDLE thread_handle,
318 const void* base_address, 319 const void* base_address,
319 void* stack_copy_buffer, 320 void* stack_copy_buffer,
320 size_t stack_copy_buffer_size, 321 size_t stack_copy_buffer_size,
321 std::vector<RecordedFrame>* stack, 322 std::vector<RecordedFrame>* stack,
323 NativeStackSampler::AnnotateCallback annotator,
324 StackSamplingProfiler::Sample* sample,
322 NativeStackSamplerTestDelegate* test_delegate) { 325 NativeStackSamplerTestDelegate* test_delegate) {
323 DCHECK(stack->empty()); 326 DCHECK(stack->empty());
324 327
325 CONTEXT thread_context = {0}; 328 CONTEXT thread_context = {0};
326 thread_context.ContextFlags = CONTEXT_FULL; 329 thread_context.ContextFlags = CONTEXT_FULL;
327 // The stack bounds are saved to uintptr_ts for use outside 330 // The stack bounds are saved to uintptr_ts for use outside
328 // ScopedSuspendThread, as the thread's memory is not safe to dereference 331 // ScopedSuspendThread, as the thread's memory is not safe to dereference
329 // beyond that point. 332 // beyond that point.
330 const uintptr_t top = reinterpret_cast<uintptr_t>(base_address); 333 const uintptr_t top = reinterpret_cast<uintptr_t>(base_address);
331 uintptr_t bottom = 0u; 334 uintptr_t bottom = 0u;
(...skipping 14 matching lines...) Expand all
346 349
347 if ((top - bottom) > stack_copy_buffer_size) 350 if ((top - bottom) > stack_copy_buffer_size)
348 return; 351 return;
349 352
350 // Dereferencing a pointer in the guard page in a thread that doesn't own 353 // Dereferencing a pointer in the guard page in a thread that doesn't own
351 // the stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a crash. 354 // the stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a crash.
352 // This occurs very rarely, but reliably over the population. 355 // This occurs very rarely, but reliably over the population.
353 if (PointsToGuardPage(bottom)) 356 if (PointsToGuardPage(bottom))
354 return; 357 return;
355 358
359 (*annotator)(sample);
360
356 std::memcpy(stack_copy_buffer, reinterpret_cast<const void*>(bottom), 361 std::memcpy(stack_copy_buffer, reinterpret_cast<const void*>(bottom),
357 top - bottom); 362 top - bottom);
358 } 363 }
359 364
360 if (test_delegate) 365 if (test_delegate)
361 test_delegate->OnPreStackWalk(); 366 test_delegate->OnPreStackWalk();
362 367
363 RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer); 368 RewritePointersToStackMemory(top, bottom, &thread_context, stack_copy_buffer);
364 369
365 RecordStack(&thread_context, stack); 370 RecordStack(&thread_context, stack);
366 } 371 }
367 372
368 // NativeStackSamplerWin ------------------------------------------------------ 373 // NativeStackSamplerWin ------------------------------------------------------
369 374
370 class NativeStackSamplerWin : public NativeStackSampler { 375 class NativeStackSamplerWin : public NativeStackSampler {
371 public: 376 public:
372 NativeStackSamplerWin(win::ScopedHandle thread_handle, 377 NativeStackSamplerWin(win::ScopedHandle thread_handle,
378 AnnotateCallback annotator,
373 NativeStackSamplerTestDelegate* test_delegate); 379 NativeStackSamplerTestDelegate* test_delegate);
374 ~NativeStackSamplerWin() override; 380 ~NativeStackSamplerWin() override;
375 381
376 // StackSamplingProfiler::NativeStackSampler: 382 // StackSamplingProfiler::NativeStackSampler:
377 void ProfileRecordingStarting( 383 void ProfileRecordingStarting(
378 std::vector<StackSamplingProfiler::Module>* modules) override; 384 std::vector<StackSamplingProfiler::Module>* modules) override;
379 void RecordStackSample(StackSamplingProfiler::Sample* sample) override; 385 void RecordStackSample(StackSamplingProfiler::Sample* sample) override;
380 void ProfileRecordingStopped() override; 386 void ProfileRecordingStopped() override;
381 387
382 private: 388 private:
(...skipping 18 matching lines...) Expand all
401 size_t GetModuleIndex(HMODULE module_handle, 407 size_t GetModuleIndex(HMODULE module_handle,
402 std::vector<StackSamplingProfiler::Module>* modules); 408 std::vector<StackSamplingProfiler::Module>* modules);
403 409
404 // Copies the information represented by |stack| into |sample| and |modules|. 410 // Copies the information represented by |stack| into |sample| and |modules|.
405 void CopyToSample(const std::vector<RecordedFrame>& stack, 411 void CopyToSample(const std::vector<RecordedFrame>& stack,
406 StackSamplingProfiler::Sample* sample, 412 StackSamplingProfiler::Sample* sample,
407 std::vector<StackSamplingProfiler::Module>* modules); 413 std::vector<StackSamplingProfiler::Module>* modules);
408 414
409 win::ScopedHandle thread_handle_; 415 win::ScopedHandle thread_handle_;
410 416
417 const AnnotateCallback annotator_;
418
411 NativeStackSamplerTestDelegate* const test_delegate_; 419 NativeStackSamplerTestDelegate* const test_delegate_;
412 420
413 // The stack base address corresponding to |thread_handle_|. 421 // The stack base address corresponding to |thread_handle_|.
414 const void* const thread_stack_base_address_; 422 const void* const thread_stack_base_address_;
415 423
416 // Buffer to use for copies of the stack. We use the same buffer for all the 424 // Buffer to use for copies of the stack. We use the same buffer for all the
417 // samples to avoid the overhead of multiple allocations and frees. 425 // samples to avoid the overhead of multiple allocations and frees.
418 const std::unique_ptr<unsigned char[]> stack_copy_buffer_; 426 const std::unique_ptr<unsigned char[]> stack_copy_buffer_;
419 427
420 // Weak. Points to the modules associated with the profile being recorded 428 // Weak. Points to the modules associated with the profile being recorded
421 // between ProfileRecordingStarting() and ProfileRecordingStopped(). 429 // between ProfileRecordingStarting() and ProfileRecordingStopped().
422 std::vector<StackSamplingProfiler::Module>* current_modules_; 430 std::vector<StackSamplingProfiler::Module>* current_modules_;
423 431
424 // Maps a module handle to the corresponding Module's index within 432 // Maps a module handle to the corresponding Module's index within
425 // current_modules_. 433 // current_modules_.
426 std::map<HMODULE, size_t> profile_module_index_; 434 std::map<HMODULE, size_t> profile_module_index_;
427 435
428 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); 436 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
429 }; 437 };
430 438
431 NativeStackSamplerWin::NativeStackSamplerWin( 439 NativeStackSamplerWin::NativeStackSamplerWin(
432 win::ScopedHandle thread_handle, 440 win::ScopedHandle thread_handle,
441 AnnotateCallback annotator,
433 NativeStackSamplerTestDelegate* test_delegate) 442 NativeStackSamplerTestDelegate* test_delegate)
434 : thread_handle_(thread_handle.Take()), test_delegate_(test_delegate), 443 : thread_handle_(thread_handle.Take()),
444 annotator_(annotator),
445 test_delegate_(test_delegate),
435 thread_stack_base_address_( 446 thread_stack_base_address_(
436 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase), 447 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase),
437 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) { 448 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) {
438 } 449 }
439 450
440 NativeStackSamplerWin::~NativeStackSamplerWin() { 451 NativeStackSamplerWin::~NativeStackSamplerWin() {
441 } 452 }
442 453
443 void NativeStackSamplerWin::ProfileRecordingStarting( 454 void NativeStackSamplerWin::ProfileRecordingStarting(
444 std::vector<StackSamplingProfiler::Module>* modules) { 455 std::vector<StackSamplingProfiler::Module>* modules) {
445 current_modules_ = modules; 456 current_modules_ = modules;
446 profile_module_index_.clear(); 457 profile_module_index_.clear();
447 } 458 }
448 459
449 void NativeStackSamplerWin::RecordStackSample( 460 void NativeStackSamplerWin::RecordStackSample(
450 StackSamplingProfiler::Sample* sample) { 461 StackSamplingProfiler::Sample* sample) {
451 DCHECK(current_modules_); 462 DCHECK(current_modules_);
452 463
453 if (!stack_copy_buffer_) 464 if (!stack_copy_buffer_)
454 return; 465 return;
455 466
456 std::vector<RecordedFrame> stack; 467 std::vector<RecordedFrame> stack;
457 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, 468 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_,
458 stack_copy_buffer_.get(), kStackCopyBufferSize, 469 stack_copy_buffer_.get(), kStackCopyBufferSize,
459 &stack, test_delegate_); 470 &stack, annotator_, sample, test_delegate_);
460 CopyToSample(stack, sample, current_modules_); 471 CopyToSample(stack, sample, current_modules_);
461 } 472 }
462 473
463 void NativeStackSamplerWin::ProfileRecordingStopped() { 474 void NativeStackSamplerWin::ProfileRecordingStopped() {
464 current_modules_ = nullptr; 475 current_modules_ = nullptr;
465 } 476 }
466 477
467 // static 478 // static
468 bool NativeStackSamplerWin::GetModuleForHandle( 479 bool NativeStackSamplerWin::GetModuleForHandle(
469 HMODULE module_handle, 480 HMODULE module_handle,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 module_handle, modules->size() - 1)).first; 512 module_handle, modules->size() - 1)).first;
502 } 513 }
503 514
504 return loc->second; 515 return loc->second;
505 } 516 }
506 517
507 void NativeStackSamplerWin::CopyToSample( 518 void NativeStackSamplerWin::CopyToSample(
508 const std::vector<RecordedFrame>& stack, 519 const std::vector<RecordedFrame>& stack,
509 StackSamplingProfiler::Sample* sample, 520 StackSamplingProfiler::Sample* sample,
510 std::vector<StackSamplingProfiler::Module>* modules) { 521 std::vector<StackSamplingProfiler::Module>* modules) {
511 sample->clear(); 522 sample->frames.clear();
512 sample->reserve(stack.size()); 523 sample->frames.reserve(stack.size());
513 524
514 for (const RecordedFrame& frame : stack) { 525 for (const RecordedFrame& frame : stack) {
515 sample->push_back(StackSamplingProfiler::Frame( 526 sample->frames.push_back(StackSamplingProfiler::Frame(
516 reinterpret_cast<uintptr_t>(frame.instruction_pointer), 527 reinterpret_cast<uintptr_t>(frame.instruction_pointer),
517 GetModuleIndex(frame.module.Get(), modules))); 528 GetModuleIndex(frame.module.Get(), modules)));
518 } 529 }
519 } 530 }
520 531
521 } // namespace 532 } // namespace
522 533
523 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create( 534 std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
524 PlatformThreadId thread_id, 535 PlatformThreadId thread_id,
536 AnnotateCallback annotator,
525 NativeStackSamplerTestDelegate* test_delegate) { 537 NativeStackSamplerTestDelegate* test_delegate) {
526 #if _WIN64 538 #if _WIN64
527 // Get the thread's handle. 539 // Get the thread's handle.
528 HANDLE thread_handle = ::OpenThread( 540 HANDLE thread_handle = ::OpenThread(
529 THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, 541 THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
530 FALSE, 542 FALSE,
531 thread_id); 543 thread_id);
532 544
533 if (thread_handle) { 545 if (thread_handle) {
534 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( 546 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin(
535 win::ScopedHandle(thread_handle), test_delegate)); 547 win::ScopedHandle(thread_handle), annotator, test_delegate));
536 } 548 }
537 #endif 549 #endif
538 return std::unique_ptr<NativeStackSampler>(); 550 return std::unique_ptr<NativeStackSampler>();
539 } 551 }
540 552
541 } // namespace base 553 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698