summaryrefslogtreecommitdiff
path: root/chromium/chrome/common/profiler/thread_profiler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/common/profiler/thread_profiler.cc')
-rw-r--r--chromium/chrome/common/profiler/thread_profiler.cc93
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());