diff options
Diffstat (limited to 'chromium/chrome/common/profiler/thread_profiler.cc')
-rw-r--r-- | chromium/chrome/common/profiler/thread_profiler.cc | 93 |
1 files changed, 90 insertions, 3 deletions
diff --git a/chromium/chrome/common/profiler/thread_profiler.cc b/chromium/chrome/common/profiler/thread_profiler.cc index f32a9ef3a1d..7a4d3ce9483 100644 --- a/chromium/chrome/common/profiler/thread_profiler.cc +++ b/chromium/chrome/common/profiler/thread_profiler.cc @@ -6,6 +6,7 @@ #include <string> #include <utility> +#include <vector> #include "base/bind.h" #include "base/command_line.h" @@ -25,6 +26,21 @@ #include "content/public/common/content_switches.h" #include "content/public/common/service_names.mojom.h" #include "services/service_manager/embedder/switches.h" +#include "services/service_manager/sandbox/sandbox.h" + +#if defined(OS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) +#include "base/android/apk_assets.h" +#include "base/files/memory_mapped_file.h" +#include "base/profiler/arm_cfi_table.h" +#include "base/profiler/chrome_unwinder_android.h" +#include "chrome/android/modules/stack_unwinder/public/module.h" + +extern "C" { +// The address of |__executable_start| is the base address of the executable or +// shared library. +extern char __executable_start; +} +#endif // defined(OS_ANDROID) using CallStackProfileBuilder = metrics::CallStackProfileBuilder; using CallStackProfileParams = metrics::CallStackProfileParams; @@ -51,8 +67,13 @@ CallStackProfileParams::Process GetProcess() { return CallStackProfileParams::RENDERER_PROCESS; if (process_type == switches::kGpuProcess) return CallStackProfileParams::GPU_PROCESS; - if (process_type == switches::kUtilityProcess) + if (process_type == switches::kUtilityProcess) { + auto sandbox_type = + service_manager::SandboxTypeFromCommandLine(*command_line); + if (sandbox_type == service_manager::SandboxType::kNetwork) + return CallStackProfileParams::NETWORK_SERVICE_PROCESS; return CallStackProfileParams::UTILITY_PROCESS; + } if (process_type == service_manager::switches::kZygoteProcess) return CallStackProfileParams::ZYGOTE_PROCESS; if (process_type == switches::kPpapiPluginProcess) @@ -62,6 +83,69 @@ CallStackProfileParams::Process GetProcess() { return CallStackProfileParams::UNKNOWN_PROCESS; } +const base::RepeatingCallback<std::vector<std::unique_ptr<base::Unwinder>>()>& +GetCoreUnwindersFactory() { + const auto create_unwinders_factory = []() { +#if defined(OS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE) + static constexpr char kCfiFileName[] = "assets/unwind_cfi_32"; + + // The module is loadable if the profiler is enabled for the current + // process. + CHECK(StackSamplingConfiguration::Get() + ->IsProfilerEnabledForCurrentProcess()); + + class UnwindersFactory { + public: + UnwindersFactory() + : module_(stack_unwinder::Module::Load()), + memory_regions_map_(module_->CreateMemoryRegionsMap()) { + base::MemoryMappedFile::Region cfi_region; + int fd = base::android::OpenApkAsset(kCfiFileName, &cfi_region); + DCHECK(fd >= 0); + bool mapped_file_ok = + chrome_cfi_file_.Initialize(base::File(fd), cfi_region); + DCHECK(mapped_file_ok); + chrome_cfi_table_ = base::ArmCFITable::Parse( + {chrome_cfi_file_.data(), chrome_cfi_file_.length()}); + DCHECK(chrome_cfi_table_); + } + UnwindersFactory(const UnwindersFactory&) = delete; + UnwindersFactory& operator=(const UnwindersFactory&) = delete; + + std::vector<std::unique_ptr<base::Unwinder>> Run() { + std::vector<std::unique_ptr<base::Unwinder>> unwinders; + unwinders.push_back(module_->CreateNativeUnwinder( + memory_regions_map_.get(), + reinterpret_cast<uintptr_t>(&__executable_start))); + unwinders.push_back(std::make_unique<base::ChromeUnwinderAndroid>( + chrome_cfi_table_.get(), + reinterpret_cast<uintptr_t>(&__executable_start))); + return unwinders; + } + + private: + const std::unique_ptr<stack_unwinder::Module> module_; + const std::unique_ptr<stack_unwinder::MemoryRegionsMap> + memory_regions_map_; + base::MemoryMappedFile chrome_cfi_file_; + std::unique_ptr<base::ArmCFITable> chrome_cfi_table_; + }; + + return base::BindRepeating(&UnwindersFactory::Run, + std::make_unique<UnwindersFactory>()); +#else + return base::BindRepeating( + []() -> std::vector<std::unique_ptr<base::Unwinder>> { return {}; }); +#endif + }; + + static base::NoDestructor< + base::RepeatingCallback<std::vector<std::unique_ptr<base::Unwinder>>()>> + native_unwinder_factory(create_unwinders_factory()); + + return *native_unwinder_factory; +} + } // namespace // The scheduler works by splitting execution time into repeated periods such @@ -234,12 +318,14 @@ ThreadProfiler::ThreadProfiler( const base::StackSamplingProfiler::SamplingParams sampling_params = StackSamplingConfiguration::Get()->GetSamplingParams(); + startup_profiler_ = std::make_unique<StackSamplingProfiler>( base::GetSamplingProfilerCurrentThreadToken(), sampling_params, std::make_unique<CallStackProfileBuilder>( CallStackProfileParams(GetProcess(), thread, CallStackProfileParams::PROCESS_STARTUP), - work_id_recorder_.get())); + work_id_recorder_.get()), + GetCoreUnwindersFactory().Run()); startup_profiler_->Start(); @@ -303,7 +389,8 @@ void ThreadProfiler::StartPeriodicSamplingCollection() { work_id_recorder_.get(), base::BindOnce(&ThreadProfiler::OnPeriodicCollectionCompleted, owning_thread_task_runner_, - weak_factory_.GetWeakPtr()))); + weak_factory_.GetWeakPtr())), + GetCoreUnwindersFactory().Run()); if (aux_unwinder_factory_) periodic_profiler_->AddAuxUnwinder(aux_unwinder_factory_.Run()); |