135 lines
3.4 KiB
C++
135 lines
3.4 KiB
C++
// Copyright 2017 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.
|
|
|
|
#include <inttypes.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#include "atrace_process_dump.h"
|
|
#include "logging.h"
|
|
|
|
namespace {
|
|
|
|
std::unique_ptr<AtraceProcessDump> g_prog;
|
|
|
|
void ParseFullDumpConfig(const std::string& config, AtraceProcessDump* prog) {
|
|
using FullDumpMode = AtraceProcessDump::FullDumpMode;
|
|
if (config == "all") {
|
|
prog->set_full_dump_mode(FullDumpMode::kAllProcesses);
|
|
} else if (config == "apps") {
|
|
prog->set_full_dump_mode(FullDumpMode::kAllJavaApps);
|
|
} else {
|
|
std::set<std::string> whitelist;
|
|
std::istringstream ss(config);
|
|
std::string entry;
|
|
while (std::getline(ss, entry, ',')) {
|
|
whitelist.insert(entry);
|
|
}
|
|
if (whitelist.empty())
|
|
return;
|
|
prog->set_full_dump_mode(FullDumpMode::kOnlyWhitelisted);
|
|
prog->set_full_dump_whitelist(whitelist);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc == 2 && !strcmp(argv[1], "--echo-ts")) {
|
|
// Used by clock sync marker to correct the difference between
|
|
// Linux monotonic clocks on the device and host.
|
|
printf("%" PRIu64 "\n", time_utils::GetTimestamp());
|
|
return 0;
|
|
}
|
|
|
|
bool background = false;
|
|
int dump_interval_ms = 5000;
|
|
char out_file[PATH_MAX] = {};
|
|
bool dump_to_file = false;
|
|
int count = -1;
|
|
|
|
AtraceProcessDump* prog = new AtraceProcessDump();
|
|
g_prog = std::unique_ptr<AtraceProcessDump>(prog);
|
|
|
|
if (geteuid()) {
|
|
fprintf(stderr, "Must run as root\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int opt;
|
|
while ((opt = getopt(argc, argv, "bm:gst:o:c:")) != -1) {
|
|
switch (opt) {
|
|
case 'b':
|
|
background = true;
|
|
break;
|
|
case 'm':
|
|
ParseFullDumpConfig(optarg, prog);
|
|
break;
|
|
case 'g':
|
|
prog->enable_graphics_stats();
|
|
break;
|
|
case 's':
|
|
prog->enable_print_smaps();
|
|
break;
|
|
case 't':
|
|
dump_interval_ms = atoi(optarg);
|
|
CHECK(dump_interval_ms > 0);
|
|
break;
|
|
case 'c':
|
|
count = atoi(optarg);
|
|
CHECK(count > 0);
|
|
break;
|
|
case 'o':
|
|
strncpy(out_file, optarg, sizeof(out_file));
|
|
dump_to_file = true;
|
|
break;
|
|
default:
|
|
fprintf(stderr,
|
|
"Usage: %s [-b] [-m full_dump_filter] [-g] [-s] "
|
|
"[-t dump_interval_ms] "
|
|
"[-c dumps_count] [-o out.json]\n",
|
|
argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
prog->set_dump_count(count);
|
|
prog->SetDumpInterval(dump_interval_ms);
|
|
|
|
FILE* out_stream = stdout;
|
|
char tmp_file[PATH_MAX];
|
|
if (dump_to_file) {
|
|
unlink(out_file);
|
|
sprintf(tmp_file, "%s.tmp", out_file);
|
|
out_stream = fopen(tmp_file, "w");
|
|
CHECK(out_stream);
|
|
}
|
|
|
|
if (background) {
|
|
if (!dump_to_file) {
|
|
fprintf(stderr, "-b requires -o for output dump path.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf("Continuing in background. kill -TERM to terminate the daemon.\n");
|
|
CHECK(daemon(0 /* nochdir */, 0 /* noclose */) == 0);
|
|
}
|
|
|
|
auto on_exit = [](int) { g_prog->Stop(); };
|
|
signal(SIGINT, on_exit);
|
|
signal(SIGTERM, on_exit);
|
|
|
|
prog->RunAndPrintJson(out_stream);
|
|
fclose(out_stream);
|
|
|
|
if (dump_to_file)
|
|
rename(tmp_file, out_file);
|
|
}
|