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

Side by Side 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 3 years, 11 months 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 "components/tracing/common/process_metrics_memory_dump_provider.h" 5 #include "components/tracing/common/process_metrics_memory_dump_provider.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <map> 10 #include <map>
11 11
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/files/scoped_file.h" 13 #include "base/files/scoped_file.h"
14 #include "base/format_macros.h" 14 #include "base/format_macros.h"
15 #include "base/lazy_instance.h" 15 #include "base/lazy_instance.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/process/process_metrics.h" 18 #include "base/process/process_metrics.h"
19 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/trace_event/memory_dump_manager.h" 21 #include "base/trace_event/memory_dump_manager.h"
22 #include "base/trace_event/process_memory_dump.h" 22 #include "base/trace_event/process_memory_dump.h"
23 #include "base/trace_event/process_memory_maps.h" 23 #include "base/trace_event/process_memory_maps.h"
24 #include "base/trace_event/process_memory_totals.h" 24 #include "base/trace_event/process_memory_totals.h"
25 #include "build/build_config.h" 25 #include "build/build_config.h"
26 26
27 #if defined(OS_MACOSX)
28 #include <mach/mach.h>
29 #include <mach-o/loader.h>
30 #include <mach-o/dyld_images.h>
31
32 #include "base/mac/mach_logging.h"
33 #endif // defined(OS_MACOSX)
34
27 namespace tracing { 35 namespace tracing {
28 36
29 namespace { 37 namespace {
30 38
31 base::LazyInstance< 39 base::LazyInstance<
32 std::map<base::ProcessId, 40 std::map<base::ProcessId,
33 std::unique_ptr<ProcessMetricsMemoryDumpProvider>>>::Leaky 41 std::unique_ptr<ProcessMetricsMemoryDumpProvider>>>::Leaky
34 g_dump_providers_map = LAZY_INSTANCE_INITIALIZER; 42 g_dump_providers_map = LAZY_INSTANCE_INITIALIZER;
35 43
36 #if defined(OS_LINUX) || defined(OS_ANDROID) 44 #if defined(OS_LINUX) || defined(OS_ANDROID)
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r")); 220 base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r"));
213 res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps()); 221 res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps());
214 } 222 }
215 223
216 if (res) 224 if (res)
217 pmd->set_has_process_mmaps(); 225 pmd->set_has_process_mmaps();
218 return res; 226 return res;
219 } 227 }
220 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 228 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
221 229
230 #if defined(OS_MACOSX)
231 bool ProcessMetricsMemoryDumpProvider::DumpProcessMemoryMaps(
232 const base::trace_event::MemoryDumpArgs& args,
233 base::trace_event::ProcessMemoryDump* pmd) {
234 using VMRegion = base::trace_event::ProcessMemoryMaps::VMRegion;
235 task_dyld_info_data_t dyld_info;
236 mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
237 kern_return_t kr =
238 task_info(mach_task_self(), TASK_DYLD_INFO,
239 reinterpret_cast<task_info_t>(&dyld_info), &count);
240 if (kr != KERN_SUCCESS) {
241 MACH_LOG(WARNING, kr) << "task_info";
242 return false;
243 }
244
245 const struct dyld_all_image_infos* all_image_infos =
246 reinterpret_cast<const struct dyld_all_image_infos*>(
247 dyld_info.all_image_info_addr);
248
249 for (size_t i = 0; i < all_image_infos->infoArrayCount; i++) {
250 const char* image_name = all_image_infos->infoArray[i].imageFilePath;
251
252 // The public definition for dyld_all_image_infos/dyld_image_info is wrong
253 // for 64-bit platforms. We explicitly cast to struct mach_header_64 even
254 // though the public definition claims that this is a struct mach_header.
255 const struct mach_header_64* const header =
256 reinterpret_cast<const struct mach_header_64* const>(
257 all_image_infos->infoArray[i].imageLoadAddress);
258
259 const struct load_command* load_cmd =
260 reinterpret_cast<const struct load_command*>(header + 1);
261 VMRegion region;
262 for (unsigned int i = 0; load_cmd && (i < header->ncmds); ++i) {
263 if (load_cmd->cmd == LC_SEGMENT_64) {
264 const segment_command_64* seg =
265 reinterpret_cast<const segment_command_64*>(load_cmd);
266
267 if (!strcmp(seg->segname, "__TEXT")) {
Mark Mentovai 2017/01/03 20:07:46 You can use SEG_TEXT as a symbolic name for __TEXT
268 region.size_in_bytes = seg->vmsize;
269
270 // 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
271 // VMRegion, since pages can have their own protection flags.
272 // segment_command_64 exposes "initprot" and "maxprot". We use
273 // "maxprot".
274 if (seg->maxprot & VM_PROT_READ)
275 region.protection_flags |= VMRegion::kProtectionFlagsRead;
276 if (seg->maxprot & VM_PROT_WRITE)
277 region.protection_flags |= VMRegion::kProtectionFlagsWrite;
278 if (seg->maxprot & VM_PROT_EXECUTE)
279 region.protection_flags |= VMRegion::kProtectionFlagsExec;
280 break;
281 }
282 }
283
284 load_cmd = reinterpret_cast<const struct load_command*>(
285 reinterpret_cast<const char*>(load_cmd) + load_cmd->cmdsize);
Mark Mentovai 2017/01/03 20:07:46 Avoid running beyond header->sizeofcmds, bearing i
286 }
287
288 region.mapped_file = image_name;
289 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
290 pmd->process_mmaps()->AddVMRegion(region);
291 }
292 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
293 return true;
294 }
295 #endif // defined(OS_MACOSX)
296
222 // static 297 // static
223 void ProcessMetricsMemoryDumpProvider::RegisterForProcess( 298 void ProcessMetricsMemoryDumpProvider::RegisterForProcess(
224 base::ProcessId process) { 299 base::ProcessId process) {
225 std::unique_ptr<ProcessMetricsMemoryDumpProvider> metrics_provider( 300 std::unique_ptr<ProcessMetricsMemoryDumpProvider> metrics_provider(
226 new ProcessMetricsMemoryDumpProvider(process)); 301 new ProcessMetricsMemoryDumpProvider(process));
227 base::trace_event::MemoryDumpProvider::Options options; 302 base::trace_event::MemoryDumpProvider::Options options;
228 options.target_pid = process; 303 options.target_pid = process;
229 options.is_fast_polling_supported = true; 304 options.is_fast_polling_supported = true;
230 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( 305 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
231 metrics_provider.get(), "ProcessMemoryMetrics", nullptr, options); 306 metrics_provider.get(), "ProcessMemoryMetrics", nullptr, options);
(...skipping 28 matching lines...) Expand all
260 335
261 ProcessMetricsMemoryDumpProvider::~ProcessMetricsMemoryDumpProvider() {} 336 ProcessMetricsMemoryDumpProvider::~ProcessMetricsMemoryDumpProvider() {}
262 337
263 // Called at trace dump point time. Creates a snapshot of the memory maps for 338 // Called at trace dump point time. Creates a snapshot of the memory maps for
264 // the current process. 339 // the current process.
265 bool ProcessMetricsMemoryDumpProvider::OnMemoryDump( 340 bool ProcessMetricsMemoryDumpProvider::OnMemoryDump(
266 const base::trace_event::MemoryDumpArgs& args, 341 const base::trace_event::MemoryDumpArgs& args,
267 base::trace_event::ProcessMemoryDump* pmd) { 342 base::trace_event::ProcessMemoryDump* pmd) {
268 bool res = DumpProcessTotals(args, pmd); 343 bool res = DumpProcessTotals(args, pmd);
269 344
270 #if defined(OS_LINUX) || defined(OS_ANDROID) 345 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
271 if (args.level_of_detail == 346 if (args.level_of_detail ==
272 base::trace_event::MemoryDumpLevelOfDetail::DETAILED) 347 base::trace_event::MemoryDumpLevelOfDetail::DETAILED)
273 res &= DumpProcessMemoryMaps(args, pmd); 348 res &= DumpProcessMemoryMaps(args, pmd);
274 #endif 349 #endif // defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
275 return res; 350 return res;
276 } 351 }
277 352
278 bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals( 353 bool ProcessMetricsMemoryDumpProvider::DumpProcessTotals(
279 const base::trace_event::MemoryDumpArgs& args, 354 const base::trace_event::MemoryDumpArgs& args,
280 base::trace_event::ProcessMemoryDump* pmd) { 355 base::trace_event::ProcessMemoryDump* pmd) {
281 const uint64_t rss_bytes = rss_bytes_for_testing 356 const uint64_t rss_bytes = rss_bytes_for_testing
282 ? rss_bytes_for_testing 357 ? rss_bytes_for_testing
283 : process_metrics_->GetWorkingSetSize(); 358 : process_metrics_->GetWorkingSetSize();
284 359
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 #endif 442 #endif
368 } 443 }
369 444
370 void ProcessMetricsMemoryDumpProvider::SuspendFastMemoryPolling() { 445 void ProcessMetricsMemoryDumpProvider::SuspendFastMemoryPolling() {
371 #if defined(OS_LINUX) || defined(OS_ANDROID) 446 #if defined(OS_LINUX) || defined(OS_ANDROID)
372 fast_polling_statm_fd_.reset(); 447 fast_polling_statm_fd_.reset();
373 #endif 448 #endif
374 } 449 }
375 450
376 } // namespace tracing 451 } // namespace tracing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698