diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-24 11:30:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-30 12:56:19 +0000 |
commit | 6036726eb981b6c4b42047513b9d3f4ac865daac (patch) | |
tree | 673593e70678e7789766d1f732eb51f613a2703b /chromium/base/profiler | |
parent | 466052c4e7c052268fd931888cd58961da94c586 (diff) | |
download | qtwebengine-chromium-6036726eb981b6c4b42047513b9d3f4ac865daac.tar.gz |
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/base/profiler')
-rw-r--r-- | chromium/base/profiler/native_stack_sampler.h | 4 | ||||
-rw-r--r-- | chromium/base/profiler/native_stack_sampler_mac.cc | 175 | ||||
-rw-r--r-- | chromium/base/profiler/native_stack_sampler_win.cc | 103 | ||||
-rw-r--r-- | chromium/base/profiler/stack_sampling_profiler.cc | 141 | ||||
-rw-r--r-- | chromium/base/profiler/stack_sampling_profiler.h | 184 | ||||
-rw-r--r-- | chromium/base/profiler/stack_sampling_profiler_unittest.cc | 99 | ||||
-rw-r--r-- | chromium/base/profiler/win32_stack_frame_unwinder.cc | 2 |
7 files changed, 155 insertions, 553 deletions
diff --git a/chromium/base/profiler/native_stack_sampler.h b/chromium/base/profiler/native_stack_sampler.h index 5d7e9b07715..381b5ef2d1c 100644 --- a/chromium/base/profiler/native_stack_sampler.h +++ b/chromium/base/profiler/native_stack_sampler.h @@ -62,8 +62,8 @@ class NativeStackSampler { // Notifies the sampler that we're starting to record a new profile. virtual void ProfileRecordingStarting() = 0; - // Records a set of internal frames and returns them. - virtual std::vector<StackSamplingProfiler::InternalFrame> RecordStackFrames( + // Records a set of frames and returns them. + virtual std::vector<StackSamplingProfiler::Frame> RecordStackFrames( StackBuffer* stackbuffer, StackSamplingProfiler::ProfileBuilder* profile_builder) = 0; diff --git a/chromium/base/profiler/native_stack_sampler_mac.cc b/chromium/base/profiler/native_stack_sampler_mac.cc index d45c7a8c836..e11f1bdd211 100644 --- a/chromium/base/profiler/native_stack_sampler_mac.cc +++ b/chromium/base/profiler/native_stack_sampler_mac.cc @@ -25,6 +25,7 @@ #include "base/mac/mach_logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/sampling_heap_profiler/module_cache.h" #include "base/strings/string_number_conversions.h" extern "C" { @@ -34,94 +35,10 @@ void _sigtramp(int, int, struct sigset*); namespace base { using Frame = StackSamplingProfiler::Frame; -using InternalFrame = StackSamplingProfiler::InternalFrame; -using Module = StackSamplingProfiler::Module; -using InternalModule = StackSamplingProfiler::InternalModule; using ProfileBuilder = StackSamplingProfiler::ProfileBuilder; namespace { -// ModuleCacheEntry records a module's address range (half-open) in memory and -// the module itself. -struct ModuleCacheEntry { - ModuleCacheEntry(uintptr_t start, - uintptr_t end, - InternalModule internal_module) - : base_address(start), - end_address(end), - internal_module(std::move(internal_module)){}; - - // Base address of the represented module. - uintptr_t base_address; - - // First address off the end of the represented module. - uintptr_t end_address; - - // Module information. - InternalModule internal_module; -}; - -// Module identifiers --------------------------------------------------------- - -// Returns the unique build ID for a module loaded at |module_addr|. Returns the -// empty string if the function fails to get the build ID. -// -// Build IDs are created by the concatenation of the module's GUID (Windows) / -// UUID (Mac) and an "age" field that indicates how many times that GUID/UUID -// has been reused. In Windows binaries, the "age" field is present in the -// module header, but on the Mac, UUIDs are never reused and so the "age" value -// appended to the UUID is always 0. -std::string GetUniqueId(const void* module_addr) { - const mach_header_64* mach_header = - reinterpret_cast<const mach_header_64*>(module_addr); - DCHECK_EQ(MH_MAGIC_64, mach_header->magic); - - size_t offset = sizeof(mach_header_64); - size_t offset_limit = sizeof(mach_header_64) + mach_header->sizeofcmds; - - for (uint32_t i = 0; i < mach_header->ncmds; ++i) { - if (offset + sizeof(load_command) >= offset_limit) - return std::string(); - - const load_command* current_cmd = reinterpret_cast<const load_command*>( - reinterpret_cast<const uint8_t*>(mach_header) + offset); - - if (offset + current_cmd->cmdsize > offset_limit) { - // This command runs off the end of the command list. This is malformed. - return std::string(); - } - - if (current_cmd->cmd == LC_UUID) { - if (current_cmd->cmdsize < sizeof(uuid_command)) { - // This "UUID command" is too small. This is malformed. - return std::string(); - } - - const uuid_command* uuid_cmd = - reinterpret_cast<const uuid_command*>(current_cmd); - static_assert(sizeof(uuid_cmd->uuid) == sizeof(uuid_t), - "UUID field of UUID command should be 16 bytes."); - // The ID is comprised of the UUID concatenated with the Mac's "age" value - // which is always 0. - return HexEncode(&uuid_cmd->uuid, sizeof(uuid_cmd->uuid)) + "0"; - } - offset += current_cmd->cmdsize; - } - return std::string(); -} - -// Returns the size of the _TEXT segment of the module loaded at |module_addr|. -size_t GetModuleTextSize(const void* module_addr) { - const mach_header_64* mach_header = - reinterpret_cast<const mach_header_64*>(module_addr); - DCHECK_EQ(MH_MAGIC_64, mach_header->magic); - - unsigned long module_size; - getsegmentdata(mach_header, SEG_TEXT, &module_size); - - return module_size; -} - // Stack walking -------------------------------------------------------------- // Fills |state| with |target_thread|'s context. @@ -210,6 +127,8 @@ uint32_t GetFrameOffset(int compact_unwind_info) { (((1 << __builtin_popcount(UNWIND_X86_64_RBP_FRAME_OFFSET))) - 1)); } +} // namespace + // True if the unwind from |leaf_frame_rip| may trigger a crash bug in // unw_init_local. If so, the stack walk should be aborted at the leaf frame. bool MayTriggerUnwInitLocalCrash(uint64_t leaf_frame_rip) { @@ -238,11 +157,13 @@ bool MayTriggerUnwInitLocalCrash(uint64_t leaf_frame_rip) { vm_size_t size = sizeof(unused); return vm_read_overwrite(current_task(), reinterpret_cast<vm_address_t>(info.dli_fbase) + - GetModuleTextSize(info.dli_fbase), + ModuleCache::GetModuleTextSize(info.dli_fbase), sizeof(unused), reinterpret_cast<vm_address_t>(&unused), &size) != 0; } +namespace { + // Check if the cursor contains a valid-looking frame pointer for frame pointer // unwinds. If the stack frame has a frame pointer, stepping the cursor will // involve indexing memory access off of that pointer. In that case, @@ -336,6 +257,8 @@ class ScopedSuspendThread { DISALLOW_COPY_AND_ASSIGN(ScopedSuspendThread); }; +} // namespace + // NativeStackSamplerMac ------------------------------------------------------ class NativeStackSamplerMac : public NativeStackSampler { @@ -346,15 +269,11 @@ class NativeStackSamplerMac : public NativeStackSampler { // StackSamplingProfiler::NativeStackSampler: void ProfileRecordingStarting() override; - std::vector<InternalFrame> RecordStackFrames( + std::vector<Frame> RecordStackFrames( StackBuffer* stack_buffer, ProfileBuilder* profile_builder) override; private: - // Returns the InternalModule containing |instruction_pointer|, adding it to - // module_cache_entry_ if it's not already present. - InternalModule GetInternalModule(uintptr_t instruction_pointer); - // Walks the stack represented by |unwind_context|, calling back to the // provided lambda for each frame. Returns false if an error occurred, // otherwise returns true. @@ -380,7 +299,7 @@ class NativeStackSamplerMac : public NativeStackSampler { const void* const thread_stack_base_address_; // Maps a module's address range to the module. - std::vector<ModuleCacheEntry> module_cache_entry_; + ModuleCache module_cache_; // The address range of |_sigtramp|, the signal trampoline function. uintptr_t sigtramp_start_; @@ -408,15 +327,15 @@ NativeStackSamplerMac::NativeStackSamplerMac( NativeStackSamplerMac::~NativeStackSamplerMac() {} void NativeStackSamplerMac::ProfileRecordingStarting() { - module_cache_entry_.clear(); + module_cache_.Clear(); } -std::vector<InternalFrame> NativeStackSamplerMac::RecordStackFrames( +std::vector<Frame> NativeStackSamplerMac::RecordStackFrames( StackBuffer* stack_buffer, ProfileBuilder* profile_builder) { x86_thread_state64_t thread_state; - const std::vector<InternalFrame> empty_internal_frames; + const std::vector<Frame> empty_frames; // Copy the stack. @@ -428,19 +347,19 @@ std::vector<InternalFrame> NativeStackSamplerMac::RecordStackFrames( // default heap acquired by the target thread before it was suspended. ScopedSuspendThread suspend_thread(thread_port_); if (!suspend_thread.was_successful()) - return empty_internal_frames; + return empty_frames; if (!GetThreadState(thread_port_, &thread_state)) - return empty_internal_frames; + return empty_frames; auto stack_top = reinterpret_cast<uintptr_t>(thread_stack_base_address_); uintptr_t stack_bottom = thread_state.__rsp; if (stack_bottom >= stack_top) - return empty_internal_frames; + return empty_frames; uintptr_t stack_size = stack_top - stack_bottom; if (stack_size > stack_buffer->size()) - return empty_internal_frames; + return empty_frames; profile_builder->RecordAnnotations(); @@ -460,16 +379,16 @@ std::vector<InternalFrame> NativeStackSamplerMac::RecordStackFrames( // Reserve enough memory for most stacks, to avoid repeated allocations. // Approximately 99.9% of recorded stacks are 128 frames or fewer. - std::vector<InternalFrame> internal_frames; - internal_frames.reserve(128); + std::vector<Frame> frames; + frames.reserve(128); // Avoid an out-of-bounds read bug in libunwind that can crash us in some // circumstances. If we're subject to that case, just record the first frame // and bail. See MayTriggerUnwInitLocalCrash for details. uintptr_t rip = thread_state.__rip; if (MayTriggerUnwInitLocalCrash(rip)) { - internal_frames.emplace_back(rip, GetInternalModule(rip)); - return internal_frames; + frames.emplace_back(rip, module_cache_.GetModuleForAddress(rip)); + return frames; } const auto continue_predicate = [this, @@ -488,43 +407,13 @@ std::vector<InternalFrame> NativeStackSamplerMac::RecordStackFrames( return HasValidRbp(unwind_cursor, new_stack_top); }; - WalkStack( - thread_state, - [&internal_frames](uintptr_t frame_ip, InternalModule internal_module) { - internal_frames.emplace_back(frame_ip, std::move(internal_module)); - }, - continue_predicate); + WalkStack(thread_state, + [&frames](uintptr_t frame_ip, ModuleCache::Module module) { + frames.emplace_back(frame_ip, std::move(module)); + }, + continue_predicate); - return internal_frames; -} - -InternalModule NativeStackSamplerMac::GetInternalModule( - uintptr_t instruction_pointer) { - // Check if |instruction_pointer| is in the address range of a module we've - // already seen. - auto loc = - std::find_if(module_cache_entry_.begin(), module_cache_entry_.end(), - [instruction_pointer](const ModuleCacheEntry& entry) { - return instruction_pointer >= entry.base_address && - instruction_pointer < entry.end_address; - }); - if (loc != module_cache_entry_.end()) - return loc->internal_module; - - Dl_info inf; - if (!dladdr(reinterpret_cast<const void*>(instruction_pointer), &inf)) - return InternalModule(); - - auto base_module_address = reinterpret_cast<uintptr_t>(inf.dli_fbase); - - InternalModule internal_module( - base_module_address, GetUniqueId(inf.dli_fbase), FilePath(inf.dli_fname)); - - module_cache_entry_.emplace_back( - base_module_address, - base_module_address + GetModuleTextSize(inf.dli_fbase), internal_module); - - return internal_module; + return frames; } template <typename StackFrameCallback, typename ContinueUnwindPredicate> @@ -553,11 +442,11 @@ bool NativeStackSamplerMac::WalkStackFromContext( // libunwind adds the expected stack size, it will look for the return // address in the wrong place. This check should ensure that we bail before // trying to deref a bad IP obtained this way in the previous frame. - InternalModule internal_module = GetInternalModule(rip); - if (!internal_module.is_valid) + const ModuleCache::Module& module = module_cache_.GetModuleForAddress(rip); + if (!module.is_valid) return false; - callback(static_cast<uintptr_t>(rip), internal_module); + callback(static_cast<uintptr_t>(rip), module); if (!continue_unwind(&unwind_cursor)) return false; @@ -618,14 +507,16 @@ void NativeStackSamplerMac::WalkStack( } } -} // namespace +// NativeStackSampler --------------------------------------------------------- +// static std::unique_ptr<NativeStackSampler> NativeStackSampler::Create( PlatformThreadId thread_id, NativeStackSamplerTestDelegate* test_delegate) { return std::make_unique<NativeStackSamplerMac>(thread_id, test_delegate); } +// static size_t NativeStackSampler::GetStackBufferSize() { // In platform_thread_mac's GetDefaultThreadStackSize(), RLIMIT_STACK is used // for all stacks, not just the main thread's, so it is good for use here. diff --git a/chromium/base/profiler/native_stack_sampler_win.cc b/chromium/base/profiler/native_stack_sampler_win.cc index b9b1773e896..3a3fbcfd441 100644 --- a/chromium/base/profiler/native_stack_sampler_win.cc +++ b/chromium/base/profiler/native_stack_sampler_win.cc @@ -6,7 +6,6 @@ #include <windows.h> -#include <objbase.h> #include <stddef.h> #include <winternl.h> @@ -21,21 +20,13 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/profiler/win32_stack_frame_unwinder.h" +#include "base/sampling_heap_profiler/module_cache.h" #include "base/stl_util.h" -#include "base/strings/string16.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" #include "base/time/time.h" -#include "base/win/pe_image.h" -#include "base/win/scoped_handle.h" namespace base { using Frame = StackSamplingProfiler::Frame; -using InternalFrame = StackSamplingProfiler::InternalFrame; -using Module = StackSamplingProfiler::Module; -using InternalModule = StackSamplingProfiler::InternalModule; using ProfileBuilder = StackSamplingProfiler::ProfileBuilder; // Stack recording functions -------------------------------------------------- @@ -203,34 +194,6 @@ void RecordStack(CONTEXT* context, std::vector<RecordedFrame>* stack) { #endif } -// Gets the unique build ID for a module. Windows build IDs are created by a -// concatenation of a GUID and AGE fields found in the headers of a module. The -// GUID is stored in the first 16 bytes and the AGE is stored in the last 4 -// bytes. Returns the empty string if the function fails to get the build ID. -// -// Example: -// dumpbin chrome.exe /headers | find "Format:" -// ... Format: RSDS, {16B2A428-1DED-442E-9A36-FCE8CBD29726}, 10, ... -// -// The resulting buildID string of this instance of chrome.exe is -// "16B2A4281DED442E9A36FCE8CBD2972610". -// -// Note that the AGE field is encoded in decimal, not hex. -std::string GetBuildIDForModule(HMODULE module_handle) { - GUID guid; - DWORD age; - win::PEImage(module_handle).GetDebugId(&guid, &age, /* pdb_file= */ nullptr); - const int kGUIDSize = 39; - string16 build_id; - int result = - ::StringFromGUID2(guid, WriteInto(&build_id, kGUIDSize), kGUIDSize); - if (result != kGUIDSize) - return std::string(); - RemoveChars(build_id, L"{}-", &build_id); - build_id += StringPrintf(L"%d", age); - return UTF16ToUTF8(build_id); -} - // ScopedDisablePriorityBoost ------------------------------------------------- // Disables priority boost on a thread for the lifetime of the object. @@ -382,6 +345,8 @@ void SuspendThreadAndRecordStack( RecordStack(&thread_context, stack); } +} // namespace + // NativeStackSamplerWin ------------------------------------------------------ class NativeStackSamplerWin : public NativeStackSampler { @@ -392,19 +357,13 @@ class NativeStackSamplerWin : public NativeStackSampler { // StackSamplingProfiler::NativeStackSampler: void ProfileRecordingStarting() override; - std::vector<InternalFrame> RecordStackFrames( + std::vector<Frame> RecordStackFrames( StackBuffer* stack_buffer, ProfileBuilder* profile_builder) override; private: - // Attempts to query the module filename, base address, and id for - // |module_handle|, and returns them in an InternalModule object. - static InternalModule GetModuleForHandle(HMODULE module_handle); - - // Creates a set of internal frames with the information represented by - // |stack|. - std::vector<InternalFrame> CreateInternalFrames( - const std::vector<RecordedFrame>& stack); + // Creates a set of frames with the information represented by |stack|. + std::vector<Frame> CreateFrames(const std::vector<RecordedFrame>& stack); win::ScopedHandle thread_handle_; @@ -413,8 +372,8 @@ class NativeStackSamplerWin : public NativeStackSampler { // The stack base address corresponding to |thread_handle_|. const void* const thread_stack_base_address_; - // The internal module objects, indexed by the module handle. - std::map<HMODULE, InternalModule> module_cache_; + // The module objects, indexed by the module handle. + std::map<HMODULE, ModuleCache::Module> module_cache_; DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); }; @@ -433,7 +392,7 @@ void NativeStackSamplerWin::ProfileRecordingStarting() { module_cache_.clear(); } -std::vector<InternalFrame> NativeStackSamplerWin::RecordStackFrames( +std::vector<Frame> NativeStackSamplerWin::RecordStackFrames( StackBuffer* stack_buffer, ProfileBuilder* profile_builder) { DCHECK(stack_buffer); @@ -443,58 +402,43 @@ std::vector<InternalFrame> NativeStackSamplerWin::RecordStackFrames( stack_buffer->buffer(), stack_buffer->size(), &stack, profile_builder, test_delegate_); - return CreateInternalFrames(stack); -} - -// static -InternalModule NativeStackSamplerWin::GetModuleForHandle( - HMODULE module_handle) { - wchar_t module_name[MAX_PATH]; - DWORD result_length = - ::GetModuleFileName(module_handle, module_name, size(module_name)); - if (result_length == 0) - return InternalModule(); - - const std::string& module_id = GetBuildIDForModule(module_handle); - if (module_id.empty()) - return InternalModule(); - - return InternalModule(reinterpret_cast<uintptr_t>(module_handle), module_id, - FilePath(module_name)); + return CreateFrames(stack); } -std::vector<InternalFrame> NativeStackSamplerWin::CreateInternalFrames( +std::vector<Frame> NativeStackSamplerWin::CreateFrames( const std::vector<RecordedFrame>& stack) { - std::vector<InternalFrame> internal_frames; - internal_frames.reserve(stack.size()); + std::vector<Frame> frames; + frames.reserve(stack.size()); for (const auto& frame : stack) { auto frame_ip = reinterpret_cast<uintptr_t>(frame.instruction_pointer); HMODULE module_handle = frame.module.Get(); if (!module_handle) { - internal_frames.emplace_back(frame_ip, InternalModule()); + frames.emplace_back(frame_ip, ModuleCache::Module()); continue; } auto loc = module_cache_.find(module_handle); if (loc != module_cache_.end()) { - internal_frames.emplace_back(frame_ip, loc->second); + frames.emplace_back(frame_ip, loc->second); continue; } - InternalModule internal_module = GetModuleForHandle(module_handle); - if (internal_module.is_valid) - module_cache_.insert(std::make_pair(module_handle, internal_module)); + ModuleCache::Module module = + ModuleCache::CreateModuleForHandle(module_handle); + if (module.is_valid) + module_cache_.insert(std::make_pair(module_handle, module)); - internal_frames.emplace_back(frame_ip, std::move(internal_module)); + frames.emplace_back(frame_ip, std::move(module)); } - return internal_frames; + return frames; } -} // namespace +// NativeStackSampler --------------------------------------------------------- +// static std::unique_ptr<NativeStackSampler> NativeStackSampler::Create( PlatformThreadId thread_id, NativeStackSamplerTestDelegate* test_delegate) { @@ -512,6 +456,7 @@ std::unique_ptr<NativeStackSampler> NativeStackSampler::Create( return std::unique_ptr<NativeStackSampler>(); } +// static size_t NativeStackSampler::GetStackBufferSize() { // The default Win32 reserved stack size is 1 MB and Chrome Windows threads // currently always use the default, but this allows for expansion if it diff --git a/chromium/base/profiler/stack_sampling_profiler.cc b/chromium/base/profiler/stack_sampling_profiler.cc index 02df814f8cc..4f1ad1d92ba 100644 --- a/chromium/base/profiler/stack_sampling_profiler.cc +++ b/chromium/base/profiler/stack_sampling_profiler.cc @@ -5,6 +5,7 @@ #include "base/profiler/stack_sampling_profiler.h" #include <algorithm> +#include <map> #include <utility> #include "base/atomic_sequence_num.h" @@ -25,8 +26,6 @@ namespace base { -const size_t kUnknownModuleIndex = static_cast<size_t>(-1); - namespace { // This value is used to initialize the WaitableEvent object. This MUST BE set @@ -41,85 +40,14 @@ const int kNullProfilerId = -1; } // namespace -// StackSamplingProfiler::Module ---------------------------------------------- - -StackSamplingProfiler::Module::Module() : base_address(0u) {} - -StackSamplingProfiler::Module::Module(uintptr_t base_address, - const std::string& id, - const FilePath& filename) - : base_address(base_address), id(id), filename(filename) {} - -StackSamplingProfiler::Module::~Module() = default; - -// StackSamplingProfiler::InternalModule -------------------------------------- - -StackSamplingProfiler::InternalModule::InternalModule() : is_valid(false) {} - -StackSamplingProfiler::InternalModule::InternalModule(uintptr_t base_address, - const std::string& id, - const FilePath& filename) - : base_address(base_address), id(id), filename(filename), is_valid(true) {} - -StackSamplingProfiler::InternalModule::~InternalModule() = default; - -// StackSamplingProfiler::Frame ----------------------------------------------- +// StackSamplingProfiler::Frame ------------------------------------- StackSamplingProfiler::Frame::Frame(uintptr_t instruction_pointer, - size_t module_index) - : instruction_pointer(instruction_pointer), module_index(module_index) {} + ModuleCache::Module module) + : instruction_pointer(instruction_pointer), module(std::move(module)) {} StackSamplingProfiler::Frame::~Frame() = default; -StackSamplingProfiler::Frame::Frame() - : instruction_pointer(0), module_index(kUnknownModuleIndex) {} - -// StackSamplingProfiler::InternalFrame ------------------------------------- - -StackSamplingProfiler::InternalFrame::InternalFrame( - uintptr_t instruction_pointer, - InternalModule internal_module) - : instruction_pointer(instruction_pointer), - internal_module(std::move(internal_module)) {} - -StackSamplingProfiler::InternalFrame::~InternalFrame() = default; - -// StackSamplingProfiler::Sample ---------------------------------------------- - -StackSamplingProfiler::Sample::Sample() = default; - -StackSamplingProfiler::Sample::Sample(const Sample& sample) = default; - -StackSamplingProfiler::Sample::~Sample() = default; - -StackSamplingProfiler::Sample::Sample(const Frame& frame) { - frames.push_back(std::move(frame)); -} - -StackSamplingProfiler::Sample::Sample(const std::vector<Frame>& frames) - : frames(frames) {} - -// StackSamplingProfiler::CallStackProfile ------------------------------------ - -StackSamplingProfiler::CallStackProfile::CallStackProfile() = default; - -StackSamplingProfiler::CallStackProfile::CallStackProfile( - CallStackProfile&& other) = default; - -StackSamplingProfiler::CallStackProfile::~CallStackProfile() = default; - -StackSamplingProfiler::CallStackProfile& -StackSamplingProfiler::CallStackProfile::operator=(CallStackProfile&& other) = - default; - -StackSamplingProfiler::CallStackProfile -StackSamplingProfiler::CallStackProfile::CopyForTesting() const { - return CallStackProfile(*this); -} - -StackSamplingProfiler::CallStackProfile::CallStackProfile( - const CallStackProfile& other) = default; - // StackSamplingProfiler::SamplingThread -------------------------------------- class StackSamplingProfiler::SamplingThread : public Thread { @@ -698,9 +626,22 @@ StackSamplingProfiler::StackSamplingProfiler( const SamplingParams& params, std::unique_ptr<ProfileBuilder> profile_builder, NativeStackSamplerTestDelegate* test_delegate) + : StackSamplingProfiler(thread_id, + params, + std::move(profile_builder), + nullptr, + test_delegate) {} + +StackSamplingProfiler::StackSamplingProfiler( + PlatformThreadId thread_id, + const SamplingParams& params, + std::unique_ptr<ProfileBuilder> profile_builder, + std::unique_ptr<NativeStackSampler> sampler, + NativeStackSamplerTestDelegate* test_delegate) : thread_id_(thread_id), params_(params), profile_builder_(std::move(profile_builder)), + native_sampler_(std::move(sampler)), // The event starts "signaled" so code knows it's safe to start thread // and "manual" so that it can be waited in multiple places. profiling_inactive_(kResetPolicy, WaitableEvent::InitialState::SIGNALED), @@ -734,10 +675,10 @@ void StackSamplingProfiler::Start() { // already. DCHECK(profile_builder_); - std::unique_ptr<NativeStackSampler> native_sampler = - NativeStackSampler::Create(thread_id_, test_delegate_); + if (!native_sampler_) + native_sampler_ = NativeStackSampler::Create(thread_id_, test_delegate_); - if (!native_sampler) + if (!native_sampler_) return; // The IsSignaled() check below requires that the WaitableEvent be manually @@ -755,7 +696,7 @@ void StackSamplingProfiler::Start() { DCHECK_EQ(kNullProfilerId, profiler_id_); profiler_id_ = SamplingThread::GetInstance()->Add( std::make_unique<SamplingThread::CollectionContext>( - thread_id_, params_, &profiling_inactive_, std::move(native_sampler), + thread_id_, params_, &profiling_inactive_, std::move(native_sampler_), std::move(profile_builder_))); DCHECK_NE(kNullProfilerId, profiler_id_); } @@ -765,44 +706,4 @@ void StackSamplingProfiler::Stop() { profiler_id_ = kNullProfilerId; } -// StackSamplingProfiler::Frame global functions ------------------------------ - -bool operator==(const StackSamplingProfiler::Module& a, - const StackSamplingProfiler::Module& b) { - return a.base_address == b.base_address && a.id == b.id && - a.filename == b.filename; -} - -bool operator==(const StackSamplingProfiler::Sample& a, - const StackSamplingProfiler::Sample& b) { - return a.process_milestones == b.process_milestones && a.frames == b.frames; -} - -bool operator!=(const StackSamplingProfiler::Sample& a, - const StackSamplingProfiler::Sample& b) { - return !(a == b); -} - -bool operator<(const StackSamplingProfiler::Sample& a, - const StackSamplingProfiler::Sample& b) { - if (a.process_milestones != b.process_milestones) - return a.process_milestones < b.process_milestones; - - return a.frames < b.frames; -} - -bool operator==(const StackSamplingProfiler::Frame& a, - const StackSamplingProfiler::Frame& b) { - return a.instruction_pointer == b.instruction_pointer && - a.module_index == b.module_index; -} - -bool operator<(const StackSamplingProfiler::Frame& a, - const StackSamplingProfiler::Frame& b) { - if (a.module_index != b.module_index) - return a.module_index < b.module_index; - - return a.instruction_pointer < b.instruction_pointer; -} - } // namespace base diff --git a/chromium/base/profiler/stack_sampling_profiler.h b/chromium/base/profiler/stack_sampling_profiler.h index e43349a8fe0..4020be84db2 100644 --- a/chromium/base/profiler/stack_sampling_profiler.h +++ b/chromium/base/profiler/stack_sampling_profiler.h @@ -5,26 +5,19 @@ #ifndef BASE_PROFILER_STACK_SAMPLING_PROFILER_H_ #define BASE_PROFILER_STACK_SAMPLING_PROFILER_H_ -#include <stddef.h> - -#include <map> #include <memory> -#include <string> #include <vector> #include "base/base_export.h" -#include "base/files/file_path.h" #include "base/macros.h" -#include "base/strings/string16.h" +#include "base/sampling_heap_profiler/module_cache.h" #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" namespace base { -// Identifies an unknown module. -BASE_EXPORT extern const size_t kUnknownModuleIndex; - +class NativeStackSampler; class NativeStackSamplerTestDelegate; // StackSamplingProfiler periodically stops a thread to sample its stack, for @@ -40,8 +33,11 @@ class NativeStackSamplerTestDelegate; // // To process the profiles, use a custom ProfileBuilder subclass: // class SubProfileBuilder : // public base::StackSamplingProfiler::ProfileBuilder{...} +// +// // On Android the |sampler| is not implemented in base. So, client can pass +// // in |sampler| to use while profiling. // base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()), -// params, std::make_unique<SubProfileBuilder>(...)); +// params, std::make_unique<SubProfileBuilder>(...), <optional> sampler); // // profiler.Start(); // // ... work being done on the target thread here ... @@ -56,141 +52,20 @@ class NativeStackSamplerTestDelegate; // by the profiler. class BASE_EXPORT StackSamplingProfiler { public: - // Module represents the module (DLL or exe) corresponding to a stack frame. - struct BASE_EXPORT Module { - Module(); - Module(uintptr_t base_address, - const std::string& id, - const FilePath& filename); - ~Module(); - - // Points to the base address of the module. - uintptr_t base_address; - - // An opaque binary string that uniquely identifies a particular program - // version with high probability. This is parsed from headers of the loaded - // module. - // For binaries generated by GNU tools: - // Contents of the .note.gnu.build-id field. - // On Windows: - // GUID + AGE in the debug image headers of a module. - std::string id; - - // The filename of the module. - FilePath filename; - }; - - // InternalModule represents the module (DLL or exe) and its validness state. - // Different from Module, it has an additional field "is_valid". + // Frame represents an individual sampled stack frame with full module + // information. // // This struct is only used for sampling data transfer from NativeStackSampler // to ProfileBuilder. - struct BASE_EXPORT InternalModule { - InternalModule(); - InternalModule(uintptr_t base_address, - const std::string& id, - const FilePath& filename); - ~InternalModule(); - - // Points to the base address of the module. - uintptr_t base_address; - - // An opaque binary string that uniquely identifies a particular program - // version with high probability. This is parsed from headers of the loaded - // module. - // For binaries generated by GNU tools: - // Contents of the .note.gnu.build-id field. - // On Windows: - // GUID + AGE in the debug image headers of a module. - std::string id; - - // The filename of the module. - FilePath filename; - - // The validness of the module. - bool is_valid; - }; - - // Frame represents an individual sampled stack frame with module information. struct BASE_EXPORT Frame { - Frame(uintptr_t instruction_pointer, size_t module_index); + Frame(uintptr_t instruction_pointer, ModuleCache::Module module); ~Frame(); - // Default constructor to satisfy IPC macros. Do not use explicitly. - Frame(); - - // The sampled instruction pointer within the function. - uintptr_t instruction_pointer; - - // Index of the module in CallStackProfile::modules. We don't represent - // module state directly here to save space. - size_t module_index; - }; - - // InternalFrame represents an individual sampled stack frame with full module - // information. This is different from Frame which only contains module index. - // - // This struct is only used for sampling data transfer from NativeStackSampler - // to ProfileBuilder. - struct BASE_EXPORT InternalFrame { - InternalFrame(uintptr_t instruction_pointer, - InternalModule internal_module); - ~InternalFrame(); - // The sampled instruction pointer within the function. uintptr_t instruction_pointer; // The module information. - InternalModule internal_module; - }; - - // Sample represents a set of stack frames with some extra information. - struct BASE_EXPORT Sample { - Sample(); - Sample(const Sample& sample); - ~Sample(); - - // These constructors are used only during testing. - Sample(const Frame& frame); - Sample(const std::vector<Frame>& frames); - - // The entire stack frame when the sample is taken. - std::vector<Frame> frames; - - // A bit-field indicating which process milestones have passed. This can be - // used to tell where in the process lifetime the samples are taken. Just - // as a "lifetime" can only move forward, these bits mark the milestones of - // the processes life as they occur. Bits can be set but never reset. The - // actual definition of the individual bits is left to the user of this - // module. - uint32_t process_milestones = 0; - }; - - // CallStackProfile represents a set of samples. - struct BASE_EXPORT CallStackProfile { - CallStackProfile(); - CallStackProfile(CallStackProfile&& other); - ~CallStackProfile(); - - CallStackProfile& operator=(CallStackProfile&& other); - - CallStackProfile CopyForTesting() const; - - std::vector<Module> modules; - std::vector<Sample> samples; - - // Duration of this profile. - TimeDelta profile_duration; - - // Time between samples. - TimeDelta sampling_period; - - private: - // Copying is possible but expensive so disallow it except for internal use - // (i.e. CopyForTesting); use std::move instead. - CallStackProfile(const CallStackProfile& other); - - DISALLOW_ASSIGN(CallStackProfile); + ModuleCache::Module module; }; // Represents parameters that configure the sampling. @@ -251,10 +126,8 @@ class BASE_EXPORT StackSamplingProfiler { // deadlock. virtual void RecordAnnotations() = 0; - // Records a new set of internal frames. Invoked when sampling a sample - // completes. - virtual void OnSampleCompleted( - std::vector<InternalFrame> internal_frames) = 0; + // Records a new set of frames. Invoked when sampling a sample completes. + virtual void OnSampleCompleted(std::vector<Frame> frames) = 0; // Finishes the profile construction with |profile_duration| and // |sampling_period|. Invoked when sampling a profile completes. @@ -284,6 +157,15 @@ class BASE_EXPORT StackSamplingProfiler { std::unique_ptr<ProfileBuilder> profile_builder, NativeStackSamplerTestDelegate* test_delegate = nullptr); + // Same as above function, with custom |sampler| implementation. The sampler + // on Android is not implemented in base. + StackSamplingProfiler( + PlatformThreadId thread_id, + const SamplingParams& params, + std::unique_ptr<ProfileBuilder> profile_builder, + std::unique_ptr<NativeStackSampler> sampler, + NativeStackSamplerTestDelegate* test_delegate = nullptr); + // Stops any profiling currently taking place before destroying the profiler. // This will block until profile_builder_'s OnProfileCompleted function has // executed if profiling has started but not already finished. @@ -314,11 +196,16 @@ class BASE_EXPORT StackSamplingProfiler { const SamplingParams params_; - // Receives the sampling data and builds a CallStackProfile. The ownership of - // this object will be transferred to the sampling thread when thread sampling + // Receives the sampling data and builds a profile. The ownership of this + // object will be transferred to the sampling thread when thread sampling // starts. std::unique_ptr<ProfileBuilder> profile_builder_; + // Stack sampler which stops the thread and collects stack frames. The + // ownership of this object will be transferred to the sampling thread when + // thread sampling starts. + std::unique_ptr<NativeStackSampler> native_sampler_; + // This starts "signaled", is reset when sampling begins, and is signaled // when that sampling is complete and the profile_builder_'s // OnProfileCompleted function has executed. @@ -334,21 +221,6 @@ class BASE_EXPORT StackSamplingProfiler { DISALLOW_COPY_AND_ASSIGN(StackSamplingProfiler); }; -// These operators permit types to be compared and used in a map of Samples, as -// done in tests and by the metrics provider code. -BASE_EXPORT bool operator==(const StackSamplingProfiler::Module& a, - const StackSamplingProfiler::Module& b); -BASE_EXPORT bool operator==(const StackSamplingProfiler::Sample& a, - const StackSamplingProfiler::Sample& b); -BASE_EXPORT bool operator!=(const StackSamplingProfiler::Sample& a, - const StackSamplingProfiler::Sample& b); -BASE_EXPORT bool operator<(const StackSamplingProfiler::Sample& a, - const StackSamplingProfiler::Sample& b); -BASE_EXPORT bool operator==(const StackSamplingProfiler::Frame& a, - const StackSamplingProfiler::Frame& b); -BASE_EXPORT bool operator<(const StackSamplingProfiler::Frame& a, - const StackSamplingProfiler::Frame& b); - } // namespace base #endif // BASE_PROFILER_STACK_SAMPLING_PROFILER_H_ diff --git a/chromium/base/profiler/stack_sampling_profiler_unittest.cc b/chromium/base/profiler/stack_sampling_profiler_unittest.cc index b0f883624f6..b19b9dcf21c 100644 --- a/chromium/base/profiler/stack_sampling_profiler_unittest.cc +++ b/chromium/base/profiler/stack_sampling_profiler_unittest.cc @@ -65,12 +65,7 @@ namespace base { using SamplingParams = StackSamplingProfiler::SamplingParams; using Frame = StackSamplingProfiler::Frame; using Frames = std::vector<Frame>; -using InternalFrame = StackSamplingProfiler::InternalFrame; -using InternalFrames = std::vector<InternalFrame>; -using InternalFrameSets = std::vector<std::vector<InternalFrame>>; -using Module = StackSamplingProfiler::Module; -using InternalModule = StackSamplingProfiler::InternalModule; -using Sample = StackSamplingProfiler::Sample; +using FrameSets = std::vector<std::vector<Frame>>; namespace { @@ -280,12 +275,11 @@ NOINLINE const void* TargetThread::GetProgramCounter() { #endif } -// Profile consists of a set of internal frame sets and other sampling -// information. +// Profile consists of a set of frame sets and other sampling information. struct Profile { Profile() = default; Profile(Profile&& other) = default; - Profile(const InternalFrameSets& frame_sets, + Profile(const FrameSets& frame_sets, int annotation_count, TimeDelta profile_duration, TimeDelta sampling_period); @@ -294,8 +288,8 @@ struct Profile { Profile& operator=(Profile&& other) = default; - // The collected internal frame sets. - InternalFrameSets frame_sets; + // The collected frame sets. + FrameSets frame_sets; // The number of invocations of RecordAnnotations(). int annotation_count; @@ -307,7 +301,7 @@ struct Profile { TimeDelta sampling_period; }; -Profile::Profile(const InternalFrameSets& frame_sets, +Profile::Profile(const FrameSets& frame_sets, int annotation_count, TimeDelta profile_duration, TimeDelta sampling_period) @@ -321,7 +315,7 @@ Profile::Profile(const InternalFrameSets& frame_sets, // this should run as quickly as possible. using ProfileCompletedCallback = Callback<void(Profile)>; -// TestProfileBuilder collects internal frames produced by the profiler. +// TestProfileBuilder collects frames produced by the profiler. class TestProfileBuilder : public StackSamplingProfiler::ProfileBuilder { public: TestProfileBuilder(const ProfileCompletedCallback& callback); @@ -330,13 +324,13 @@ class TestProfileBuilder : public StackSamplingProfiler::ProfileBuilder { // StackSamplingProfiler::ProfileBuilder: void RecordAnnotations() override; - void OnSampleCompleted(InternalFrames internal_frames) override; + void OnSampleCompleted(Frames frames) override; void OnProfileCompleted(TimeDelta profile_duration, TimeDelta sampling_period) override; private: - // The sets of internal frames recorded. - std::vector<InternalFrames> frame_sets_; + // The sets of frames recorded. + std::vector<Frames> frame_sets_; // The number of invocations of RecordAnnotations(). int annotation_count_ = 0; @@ -356,8 +350,8 @@ void TestProfileBuilder::RecordAnnotations() { ++annotation_count_; } -void TestProfileBuilder::OnSampleCompleted(InternalFrames internal_frames) { - frame_sets_.push_back(std::move(internal_frames)); +void TestProfileBuilder::OnSampleCompleted(Frames frames) { + frame_sets_.push_back(std::move(frames)); } void TestProfileBuilder::OnProfileCompleted(TimeDelta profile_duration, @@ -476,11 +470,11 @@ std::vector<std::unique_ptr<TestProfilerInfo>> CreateProfilers( return profilers; } -// Captures internal frames as specified by |params| on the TargetThread, and -// returns them. Waits up to |profiler_wait_time| for the profiler to complete. -InternalFrameSets CaptureFrameSets(const SamplingParams& params, - TimeDelta profiler_wait_time) { - InternalFrameSets frame_sets; +// Captures frames as specified by |params| on the TargetThread, and returns +// them. Waits up to |profiler_wait_time| for the profiler to complete. +FrameSets CaptureFrameSets(const SamplingParams& params, + TimeDelta profiler_wait_time) { + FrameSets frame_sets; WithTargetThread([¶ms, &frame_sets, profiler_wait_time](PlatformThreadId target_thread_id) { TestProfilerInfo info(target_thread_id, params); @@ -533,8 +527,8 @@ const void* MaybeFixupFunctionAddressForILT(const void* function_address) { // Searches through the frames in |sample|, returning an iterator to the first // frame that has an instruction pointer within |target_function|. Returns // sample.end() if no such frames are found. -InternalFrames::const_iterator FindFirstFrameWithinFunction( - const InternalFrames& frames, +Frames::const_iterator FindFirstFrameWithinFunction( + const Frames& frames, TargetFunction target_function) { uintptr_t function_start = reinterpret_cast<uintptr_t>(MaybeFixupFunctionAddressForILT( @@ -551,12 +545,12 @@ InternalFrames::const_iterator FindFirstFrameWithinFunction( } // Formats a sample into a string that can be output for test diagnostics. -std::string FormatSampleForDiagnosticOutput(const InternalFrames& frames) { +std::string FormatSampleForDiagnosticOutput(const Frames& frames) { std::string output; for (const auto& frame : frames) { output += StringPrintf( "0x%p %s\n", reinterpret_cast<const void*>(frame.instruction_pointer), - frame.internal_module.filename.AsUTF8Unsafe().c_str()); + frame.module.filename.AsUTF8Unsafe().c_str()); } return output; } @@ -653,11 +647,11 @@ void TestLibraryUnload(bool wait_until_unloaded) { // Look up the frames. ASSERT_EQ(1u, profile.frame_sets.size()); - const InternalFrames& frames = profile.frame_sets[0]; + const Frames& frames = profile.frame_sets[0]; // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction( + Frames::const_iterator end_frame = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(end_frame != frames.end()) << "Function at " @@ -690,9 +684,8 @@ void TestLibraryUnload(bool wait_until_unloaded) { // Check that the stack contains a frame for // TargetThread::CallThroughOtherLibrary(). - InternalFrames::const_iterator other_library_frame = - FindFirstFrameWithinFunction(frames, - &TargetThread::CallThroughOtherLibrary); + Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( + frames, &TargetThread::CallThroughOtherLibrary); ASSERT_TRUE(other_library_frame != frames.end()) << "Function at " << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( @@ -735,8 +728,7 @@ class StackSamplingProfilerTest : public testing::Test { } // namespace -// Checks that the basic expected information is present in sampled internal -// frames. +// Checks that the basic expected information is present in sampled frames. // // macOS ASAN is not yet supported - crbug.com/718628. #if !(defined(ADDRESS_SANITIZER) && defined(OS_MACOSX)) @@ -749,19 +741,19 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Basic) { params.sampling_interval = TimeDelta::FromMilliseconds(0); params.samples_per_profile = 1; - InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); + FrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); // Check that the size of the frame sets are correct. ASSERT_EQ(1u, frame_sets.size()); - const InternalFrames& frames = frame_sets[0]; + const Frames& frames = frame_sets[0]; // Check that all the modules are valid. for (const auto& frame : frames) - EXPECT_TRUE(frame.internal_module.is_valid); + EXPECT_TRUE(frame.module.is_valid); // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - InternalFrames::const_iterator loc = FindFirstFrameWithinFunction( + Frames::const_iterator loc = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(loc != frames.end()) << "Function at " @@ -804,11 +796,11 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Alloca) { // Look up the frames. ASSERT_EQ(1u, profile.frame_sets.size()); - const InternalFrames& frames = profile.frame_sets[0]; + const Frames& frames = profile.frame_sets[0]; // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction( + Frames::const_iterator end_frame = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(end_frame != frames.end()) << "Function at " @@ -818,7 +810,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Alloca) { << FormatSampleForDiagnosticOutput(frames); // Check that the stack contains a frame for TargetThread::CallWithAlloca(). - InternalFrames::const_iterator alloca_frame = + Frames::const_iterator alloca_frame = FindFirstFrameWithinFunction(frames, &TargetThread::CallWithAlloca); ASSERT_TRUE(alloca_frame != frames.end()) << "Function at " @@ -932,20 +924,20 @@ PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) { }); } -// Checks that no internal frames are captured if the profiling is stopped -// during the initial delay. +// Checks that no frames are captured if the profiling is stopped during the +// initial delay. PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) { SamplingParams params; params.initial_delay = TimeDelta::FromSeconds(60); - InternalFrameSets frame_sets = + FrameSets frame_sets = CaptureFrameSets(params, TimeDelta::FromMilliseconds(0)); EXPECT_TRUE(frame_sets.empty()); } -// Checks that tasks can be stopped before completion and incomplete internal -// frames are captured. +// Checks that tasks can be stopped before completion and incomplete frames are +// captured. PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) { // Test delegate that counts samples. class SampleRecordedEvent : public NativeStackSamplerTestDelegate { @@ -1013,7 +1005,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) { params.sampling_interval = TimeDelta::FromMilliseconds(0); params.samples_per_profile = 1; - InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); + FrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); ASSERT_EQ(1u, frame_sets.size()); frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); @@ -1075,7 +1067,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, SamplerIdleShutdown) { params.sampling_interval = TimeDelta::FromMilliseconds(0); params.samples_per_profile = 1; - InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); + FrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); ASSERT_EQ(1u, frame_sets.size()); // Capture thread should still be running at this point. @@ -1100,7 +1092,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, params.sampling_interval = TimeDelta::FromMilliseconds(0); params.samples_per_profile = 1; - InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); + FrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta()); ASSERT_EQ(1u, frame_sets.size()); // Capture thread should still be running at this point. @@ -1318,13 +1310,12 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_OtherLibrary) { // Look up the frames. ASSERT_EQ(1u, profile.frame_sets.size()); - const InternalFrames& frames = profile.frame_sets[0]; + const Frames& frames = profile.frame_sets[0]; // Check that the stack contains a frame for // TargetThread::CallThroughOtherLibrary(). - InternalFrames::const_iterator other_library_frame = - FindFirstFrameWithinFunction(frames, - &TargetThread::CallThroughOtherLibrary); + Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( + frames, &TargetThread::CallThroughOtherLibrary); ASSERT_TRUE(other_library_frame != frames.end()) << "Function at " << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( @@ -1334,7 +1325,7 @@ PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_OtherLibrary) { // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction( + Frames::const_iterator end_frame = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(end_frame != frames.end()) << "Function at " diff --git a/chromium/base/profiler/win32_stack_frame_unwinder.cc b/chromium/base/profiler/win32_stack_frame_unwinder.cc index a3f5f74b853..a337c160d59 100644 --- a/chromium/base/profiler/win32_stack_frame_unwinder.cc +++ b/chromium/base/profiler/win32_stack_frame_unwinder.cc @@ -119,6 +119,8 @@ Win32StackFrameUnwinder::~Win32StackFrameUnwinder() {} bool Win32StackFrameUnwinder::TryUnwind(CONTEXT* context, ScopedModuleHandle* module) { #ifdef _WIN64 + // TODO(chengx): update base::ModuleCache to return a ScopedModuleHandle and + // use it for this module lookup. ScopedModuleHandle frame_module = unwind_functions_->GetModuleForProgramCounter(context->Rip); if (!frame_module.IsValid()) { |