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

Unified Diff: tools/android/heap_profiler/heap_dump.c

Issue 2105873005: Remove tools/android/heap_profiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove heap_profiler_unittests from all targets Created 4 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/android/heap_profiler/DEPS ('k') | tools/android/heap_profiler/heap_profiler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/android/heap_profiler/heap_dump.c
diff --git a/tools/android/heap_profiler/heap_dump.c b/tools/android/heap_profiler/heap_dump.c
deleted file mode 100644
index e7bfbee1b043a62bd02de750d041e9617b5671bc..0000000000000000000000000000000000000000
--- a/tools/android/heap_profiler/heap_dump.c
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The client dump tool for libheap_profiler. It attaches to a process (given
-// its pid) and dumps all the libheap_profiler tracking information in JSON.
-// The JSON output looks like this:
-// {
-// "total_allocated": 908748493, # Total bytes allocated and not freed.
-// "num_allocs": 37542, # Number of allocations.
-// "num_stacks": 3723, # Number of allocation call-sites.
-// "allocs": # Optional. Printed only with the -x arg.
-// {
-// "beef1234": {"l": 17, "f": 1, "s": "1a"},
-// ^ ^ ^ ^ Index of the corresponding entry in the
-// | | | next "stacks" section. Essentially a ref
-// | | | to the call site that created the alloc.
-// | | |
-// | | +-------> Flags (last arg of heap_profiler_alloc).
-// | +----------------> Length of the Alloc.
-// +-----------------------------> Start address of the Alloc (hex).
-// },
-// "stacks":
-// {
-// "1a": {"l": 17, "f": [1074792772, 1100849864, 1100850688, ...]},
-// ^ ^ ^
-// | | +-----> Stack frames (absolute virtual addresses).
-// | +--------------> Bytes allocated and not freed by the call site.
-// +---------------------> Index of the entry (as for "allocs" xref).
-// Indexes are hex and might not be monotonic.
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ptrace.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "tools/android/heap_profiler/heap_profiler.h"
-
-static void lseek_abs(int fd, size_t off);
-static void read_proc_cmdline(char* cmdline, int size);
-static ssize_t read_safe(int fd, void* buf, size_t count);
-
-static int pid;
-
-
-static int dump_process_heap(
- int mem_fd,
- FILE* fmaps,
- bool dump_also_allocs,
- bool pedantic, // Enable pedantic consistency checks on memory counters.
- char* comment) {
- HeapStats stats;
- time_t tm;
- char cmdline[512];
-
- tm = time(NULL);
- read_proc_cmdline(cmdline, sizeof(cmdline));
-
- // Look for the mmap which contains the HeapStats in the target process vmem.
- // On Linux/Android, the libheap_profiler mmaps explicitly /dev/zero. The
- // region furthermore starts with a magic marker to disambiguate.
- bool stats_mmap_found = false;
- for (;;) {
- char line[1024];
- if (fgets(line, sizeof(line), fmaps) == NULL)
- break;
-
- uintptr_t start;
- uintptr_t end;
- char map_file[32];
- int ret = sscanf(line, "%"SCNxPTR"-%"SCNxPTR" rw-p %*s %*s %*s %31s",
- &start, &end, map_file);
- const size_t size = end - start + 1;
- if (ret != 3 || strcmp(map_file, "/dev/zero") != 0 || size < sizeof(stats))
- continue;
-
- // The mmap looks promising. Let's check for the magic marker.
- lseek_abs(mem_fd, start);
- ssize_t rsize = read_safe(mem_fd, &stats, sizeof(stats));
-
- if (rsize == -1) {
- perror("read");
- return -1;
- }
-
- if (rsize < sizeof(stats))
- continue;
-
- if (stats.magic_start == HEAP_PROFILER_MAGIC_MARKER) {
- stats_mmap_found = true;
- break;
- }
- }
-
- if (!stats_mmap_found) {
- fprintf(stderr, "Could not find the HeapStats area. "
- "It looks like libheap_profiler is not loaded.\n");
- return -1;
- }
-
- // Print JSON-formatted output.
- printf("{\n");
- printf(" \"pid\": %d,\n", pid);
- printf(" \"time\": %ld,\n", tm);
- printf(" \"comment\": \"%s\",\n", comment);
- printf(" \"cmdline\": \"%s\",\n", cmdline);
- printf(" \"pagesize\": %d,\n", getpagesize());
- printf(" \"total_allocated\": %zu,\n", stats.total_alloc_bytes);
- printf(" \"num_allocs\": %"PRIu32",\n", stats.num_allocs);
- printf(" \"num_stacks\": %"PRIu32",\n", stats.num_stack_traces);
-
- uint32_t dbg_counted_allocs = 0;
- size_t dbg_counted_total_alloc_bytes = 0;
- bool prepend_trailing_comma = false; // JSON syntax, I hate you.
- uint32_t i;
-
- // Dump the optional allocation table.
- if (dump_also_allocs) {
- printf(" \"allocs\": {");
- lseek_abs(mem_fd, (uintptr_t) stats.allocs);
- for (i = 0; i < stats.max_allocs; ++i) {
- Alloc alloc;
- if (read_safe(mem_fd, &alloc, sizeof(alloc)) != sizeof(alloc)) {
- fprintf(stderr, "ERROR: cannot read allocation table\n");
- perror("read");
- return -1;
- }
-
- // Skip empty (i.e. freed) entries.
- if (alloc.start == 0 && alloc.end == 0)
- continue;
-
- if (alloc.end < alloc.start) {
- fprintf(stderr, "ERROR: found inconsistent alloc.\n");
- return -1;
- }
-
- size_t alloc_size = alloc.end - alloc.start + 1;
- size_t stack_idx = (
- (uintptr_t) alloc.st - (uintptr_t) stats.stack_traces) /
- sizeof(StacktraceEntry);
- dbg_counted_total_alloc_bytes += alloc_size;
- ++dbg_counted_allocs;
-
- if (prepend_trailing_comma)
- printf(",");
- prepend_trailing_comma = true;
- printf("\"%"PRIxPTR"\": {\"l\": %zu, \"f\": %"PRIu32", \"s\": \"%zx\"}",
- alloc.start, alloc_size, alloc.flags, stack_idx);
- }
- printf("},\n");
-
- if (pedantic && dbg_counted_allocs != stats.num_allocs) {
- fprintf(stderr,
- "ERROR: inconsistent alloc count (%"PRIu32" vs %"PRIu32").\n",
- dbg_counted_allocs, stats.num_allocs);
- return -1;
- }
-
- if (pedantic && dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) {
- fprintf(stderr, "ERROR: inconsistent alloc totals (%zu vs %zu).\n",
- dbg_counted_total_alloc_bytes, stats.total_alloc_bytes);
- return -1;
- }
- }
-
- // Dump the distinct stack traces.
- printf(" \"stacks\": {");
- prepend_trailing_comma = false;
- dbg_counted_total_alloc_bytes = 0;
- lseek_abs(mem_fd, (uintptr_t) stats.stack_traces);
- for (i = 0; i < stats.max_stack_traces; ++i) {
- StacktraceEntry st;
- if (read_safe(mem_fd, &st, sizeof(st)) != sizeof(st)) {
- fprintf(stderr, "ERROR: cannot read stack trace table\n");
- perror("read");
- return -1;
- }
-
- // Skip empty (i.e. freed) entries.
- if (st.alloc_bytes == 0)
- continue;
-
- dbg_counted_total_alloc_bytes += st.alloc_bytes;
-
- if (prepend_trailing_comma)
- printf(",");
- prepend_trailing_comma = true;
-
- printf("\"%"PRIx32"\":{\"l\": %zu, \"f\": [", i, st.alloc_bytes);
- size_t n = 0;
- for (;;) {
- printf("%" PRIuPTR, st.frames[n]);
- ++n;
- if (n == HEAP_PROFILER_MAX_DEPTH || st.frames[n] == 0)
- break;
- else
- printf(",");
- }
- printf("]}");
- }
- printf("}\n}\n");
-
- if (pedantic && dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) {
- fprintf(stderr, "ERROR: inconsistent stacks totals (%zu vs %zu).\n",
- dbg_counted_total_alloc_bytes, stats.total_alloc_bytes);
- return -1;
- }
-
- fflush(stdout);
- return 0;
-}
-
-// Unfortunately lseek takes a *signed* offset, which is unsuitable for large
-// files like /proc/X/mem on 64-bit.
-static void lseek_abs(int fd, size_t off) {
-#define OFF_T_MAX ((off_t) ~(((uint64_t) 1) << (8 * sizeof(off_t) - 1)))
- if (off <= OFF_T_MAX) {
- lseek(fd, (off_t) off, SEEK_SET);
- return;
- }
- lseek(fd, (off_t) OFF_T_MAX, SEEK_SET);
- lseek(fd, (off_t) (off - OFF_T_MAX), SEEK_CUR);
-}
-
-static ssize_t read_safe(int fd, void* buf, size_t count) {
- ssize_t res;
- size_t bytes_read = 0;
- do {
- do {
- res = read(fd, buf + bytes_read, count - bytes_read);
- } while (res == -1 && errno == EINTR);
- if (res <= 0)
- break;
- bytes_read += res;
- } while (bytes_read < count);
- return bytes_read ? bytes_read : res;
-}
-
-static int open_proc_mem_fd() {
- char path[64];
- snprintf(path, sizeof(path), "/proc/%d/mem", pid);
- int mem_fd = open(path, O_RDONLY);
- if (mem_fd < 0) {
- fprintf(stderr, "Could not attach to target process virtual memory.\n");
- perror("open");
- }
- return mem_fd;
-}
-
-static FILE* open_proc_maps() {
- char path[64];
- snprintf(path, sizeof(path), "/proc/%d/maps", pid);
- FILE* fmaps = fopen(path, "r");
- if (fmaps == NULL) {
- fprintf(stderr, "Could not open %s.\n", path);
- perror("fopen");
- }
- return fmaps;
-}
-
-static void read_proc_cmdline(char* cmdline, int size) {
- char path[64];
- snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
- int cmdline_fd = open(path, O_RDONLY);
- if (cmdline_fd < 0) {
- fprintf(stderr, "Could not open %s.\n", path);
- perror("open");
- cmdline[0] = '\0';
- return;
- }
- int length = read_safe(cmdline_fd, cmdline, size);
- if (length < 0) {
- fprintf(stderr, "Could not read %s.\n", path);
- perror("read");
- length = 0;
- }
- close(cmdline_fd);
- cmdline[length] = '\0';
-}
-
-int main(int argc, char** argv) {
- char c;
- int ret = 0;
- bool dump_also_allocs = false;
- bool pedantic = true;
- char comment[1024] = { '\0' };
-
- while (((c = getopt(argc, argv, "xnc:")) & 0x80) == 0) {
- switch (c) {
- case 'x':
- dump_also_allocs = true;
- break;
- case 'n':
- pedantic = false;
- break;
- case 'c':
- strlcpy(comment, optarg, sizeof(comment));
- break;
- }
- }
-
- if (optind >= argc) {
- printf("Usage: %s [-n] [-x] [-c comment] pid\n"
- " -n: Skip pedantic checks on dump consistency.\n"
- " -x: Extended dump, includes individual allocations.\n"
- " -c: Appends the given comment to the JSON dump.\n",
- argv[0]);
- return -1;
- }
-
- pid = atoi(argv[optind]);
-
- if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
- perror("ptrace");
- return -1;
- }
-
- // Wait for the process to actually freeze.
- waitpid(pid, NULL, 0);
-
- int mem_fd = open_proc_mem_fd();
- if (mem_fd < 0)
- ret = -1;
-
- FILE* fmaps = open_proc_maps();
- if (fmaps == NULL)
- ret = -1;
-
- if (ret == 0)
- ret = dump_process_heap(mem_fd, fmaps, dump_also_allocs, pedantic, comment);
-
- ptrace(PTRACE_DETACH, pid, NULL, NULL);
-
- // Cleanup.
- fflush(stdout);
- close(mem_fd);
- fclose(fmaps);
- return ret;
-}
« no previous file with comments | « tools/android/heap_profiler/DEPS ('k') | tools/android/heap_profiler/heap_profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698