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

Unified Diff: components/tracing/common/process_metrics_memory_dump_provider.cc

Issue 2601193002: Emit VMRegions for macOS when doing process memory dumps. (Closed)
Patch Set: Don't use symbol on windows. 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 side-by-side diff with in-line comments
Download patch
Index: components/tracing/common/process_metrics_memory_dump_provider.cc
diff --git a/components/tracing/common/process_metrics_memory_dump_provider.cc b/components/tracing/common/process_metrics_memory_dump_provider.cc
index 593755bada11899c83bd93f32689d819cd09fae7..5a5d16d4cbb51952f1959f4fe3f144ebef53618a 100644
--- a/components/tracing/common/process_metrics_memory_dump_provider.cc
+++ b/components/tracing/common/process_metrics_memory_dump_provider.cc
@@ -24,6 +24,14 @@
#include "base/trace_event/process_memory_totals.h"
#include "build/build_config.h"
+#if defined(OS_MACOSX)
+#include <mach/mach.h>
+#include <mach-o/loader.h>
+#include <mach-o/dyld_images.h>
+
+#include "base/mac/mach_logging.h"
+#endif // defined(OS_MACOSX)
+
namespace tracing {
namespace {
@@ -219,6 +227,73 @@ bool ProcessMetricsMemoryDumpProvider::DumpProcessMemoryMaps(
}
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_MACOSX)
+bool ProcessMetricsMemoryDumpProvider::DumpProcessMemoryMaps(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ using VMRegion = base::trace_event::ProcessMemoryMaps::VMRegion;
+ task_dyld_info_data_t dyld_info;
+ mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
+ kern_return_t kr =
+ task_info(mach_task_self(), TASK_DYLD_INFO,
+ reinterpret_cast<task_info_t>(&dyld_info), &count);
+ if (kr != KERN_SUCCESS) {
+ MACH_LOG(WARNING, kr) << "task_info";
+ return false;
+ }
+
+ const struct dyld_all_image_infos* all_image_infos =
+ reinterpret_cast<const struct dyld_all_image_infos*>(
+ dyld_info.all_image_info_addr);
+
+ for (size_t i = 0; i < all_image_infos->infoArrayCount; i++) {
+ const char* image_name = all_image_infos->infoArray[i].imageFilePath;
+
+ // The public definition for dyld_all_image_infos/dyld_image_info is wrong
+ // for 64-bit platforms. We explicitly cast to struct mach_header_64 even
+ // though the public definition claims that this is a struct mach_header.
+ const struct mach_header_64* const header =
+ reinterpret_cast<const struct mach_header_64* const>(
+ all_image_infos->infoArray[i].imageLoadAddress);
+
+ const struct load_command* load_cmd =
+ reinterpret_cast<const struct load_command*>(header + 1);
+ VMRegion region;
+ for (unsigned int i = 0; load_cmd && (i < header->ncmds); ++i) {
+ if (load_cmd->cmd == LC_SEGMENT_64) {
+ const segment_command_64* seg =
+ reinterpret_cast<const segment_command_64*>(load_cmd);
+
+ if (!strcmp(seg->segname, "__TEXT")) {
Mark Mentovai 2017/01/03 20:07:46 You can use SEG_TEXT as a symbolic name for __TEXT
+ region.size_in_bytes = seg->vmsize;
+
+ // It's not clear what "protection_flags" means for an entire
Mark Mentovai 2017/01/03 20:07:46 They’re the access bits set when the region is ini
+ // VMRegion, since pages can have their own protection flags.
+ // segment_command_64 exposes "initprot" and "maxprot". We use
+ // "maxprot".
+ if (seg->maxprot & VM_PROT_READ)
+ region.protection_flags |= VMRegion::kProtectionFlagsRead;
+ if (seg->maxprot & VM_PROT_WRITE)
+ region.protection_flags |= VMRegion::kProtectionFlagsWrite;
+ if (seg->maxprot & VM_PROT_EXECUTE)
+ region.protection_flags |= VMRegion::kProtectionFlagsExec;
+ break;
+ }
+ }
+
+ load_cmd = reinterpret_cast<const struct load_command*>(
+ reinterpret_cast<const char*>(load_cmd) + load_cmd->cmdsize);
Mark Mentovai 2017/01/03 20:07:46 Avoid running beyond header->sizeofcmds, bearing i
+ }
+
+ region.mapped_file = image_name;
+ region.start_address = reinterpret_cast<uint64_t>(header);
Mark Mentovai 2017/01/03 20:07:46 For this to be valid, __TEXT needs to be at offset
+ pmd->process_mmaps()->AddVMRegion(region);
+ }
+ pmd->set_has_process_mmaps();
Mark Mentovai 2017/01/03 20:07:46 This only gets things that dyld knows about, inclu
Primiano Tucci (use gerrit) 2017/01/06 10:43:44 On Linux/Android we deliberately decided to grab a
+ return true;
+}
+#endif // defined(OS_MACOSX)
+
// static
void ProcessMetricsMemoryDumpProvider::RegisterForProcess(
base::ProcessId process) {
@@ -267,11 +342,11 @@ bool ProcessMetricsMemoryDumpProvider::OnMemoryDump(
base::trace_event::ProcessMemoryDump* pmd) {
bool res = DumpProcessTotals(args, pmd);
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
if (args.level_of_detail ==
base::trace_event::MemoryDumpLevelOfDetail::DETAILED)
res &= DumpProcessMemoryMaps(args, pmd);
-#endif
+#endif // defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
return res;
}

Powered by Google App Engine
This is Rietveld 408576698