1fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/*
2fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * Copyright (C) 2012 The Android Open Source Project
3fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis *
4fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
5fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * you may not use this file except in compliance with the License.
6fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * You may obtain a copy of the License at
7fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis *
8fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
9fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis *
10fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * Unless required by applicable law or agreed to in writing, software
11fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
12fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * See the License for the specific language governing permissions and
14fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * limitations under the License.
15fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis */
16fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
172cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence#define LOG_TAG "atrace"
1840b26b4fc597f105823bc1e2a640e4df8baea243John Reck
19fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <errno.h>
20fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <fcntl.h>
214edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling#include <getopt.h>
2292dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn#include <inttypes.h>
23fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <signal.h>
24fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdarg.h>
25fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdbool.h>
26fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdio.h>
27fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdlib.h>
283da5d235dab9469ccec567c4ebbb5206f4558a18Elliott Hughes#include <string.h>
29fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <sys/sendfile.h>
30fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <time.h>
31d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen#include <unistd.h>
327b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis#include <zlib.h>
33fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
34ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson#include <fstream>
35a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes#include <memory>
36a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes
376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/IBinder.h>
386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/IServiceManager.h>
396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/Parcel.h>
406eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
41ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen#include <android/hidl/manager/1.0/IServiceManager.h>
42ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen#include <hidl/ServiceManagement.h>
436eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <cutils/properties.h>
446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <utils/String8.h>
46469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck#include <utils/Timers.h>
4746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda#include <utils/Tokenizer.h>
486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <utils/Trace.h>
49d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini#include <android-base/file.h>
506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
516eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisusing namespace android;
526eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
53ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenenusing std::string;
54ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
55ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown
564144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv#define MAX_SYS_FILES 10
574144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv#define MAX_PACKAGES 16
586eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisconst char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
604144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv
614144eff1e261f6462be3753fc9543d82f9a4fd96sergeyvconst char* k_traceAppsNumberProperty = "debug.atrace.app_number";
624144eff1e261f6462be3753fc9543d82f9a4fd96sergeyvconst char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
63db40415e05e39c1f4faa62735f435b031e53af7csergeyvconst char* k_coreServiceCategory = "core_services";
64db40415e05e39c1f4faa62735f435b031e53af7csergeyvconst char* k_coreServicesProp = "ro.atrace.core.services";
656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennistypedef enum { OPT, REQ } requiredness  ;
676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstruct TracingCategory {
696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // The name identifying the category.
706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    const char* name;
716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // A longer description of the category.
736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    const char* longname;
746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // The userland tracing tags that the category enables.
766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    uint64_t tags;
776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // The fname==NULL terminated list of /sys/ files that the category
796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // enables.
806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    struct {
816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        // Whether the file must be writable in order to enable the tracing
826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        // category.
836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        requiredness required;
846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        // The path to the enable file.
866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const char* path;
876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } sysfiles[MAX_SYS_FILES];
886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis};
896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis/* Tracing categories */
916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic const TracingCategory k_categories[] = {
92b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, { } },
93b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "input",      "Input",            ATRACE_TAG_INPUT, { } },
94b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "view",       "View System",      ATRACE_TAG_VIEW, { } },
95b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
96b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
97b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
9870ec2941530766bdca09ef2983a3ff794c028ee6Patrick Auchter    { "sm",         "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
99b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
100b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
101b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
102b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
1033200b0bf507936ecf43784191880e4e91c54568cJeff Brown    { "app",        "Application",      ATRACE_TAG_APP, { } },
1049380d78c98d8b8fbce9ade5881fab7134fadc015Dianne Hackborn    { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
105eff2e8d2374692213204468433e3d96e7472ea02Jamie Gennis    { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
106f0f2841d95a26247dfa0b31a6bfa8b010fe89aa2Tim Murray    { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
107750aa9743c0c4c592213fbb39b8d328bd0075fd6Brigid Smith    { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
1083200b0bf507936ecf43784191880e4e91c54568cJeff Brown    { "power",      "Power Management", ATRACE_TAG_POWER, { } },
10901e111b5a02440c0684494e9286709285e20097fTodd Kennedy    { "pm",         "Package Manager",  ATRACE_TAG_PACKAGE_MANAGER, { } },
1107cc4977ccd98a4ee557c8382bbc705eef702bdb6Yasuhiro Matsuda    { "ss",         "System Server",    ATRACE_TAG_SYSTEM_SERVER, { } },
111bbd7d991db7cdb0f09a765d23e32c7441eb0393fGreg Hackmann    { "database",   "Database",         ATRACE_TAG_DATABASE, { } },
1120f97c1d775dd95fab5142d7aae6d34b80b4c2312Felipe Leme    { "network",    "Network",          ATRACE_TAG_NETWORK, { } },
113468b4cb566fd81d7181764d3f7121125c7db3b24Josh Gao    { "adb",        "ADB",              ATRACE_TAG_ADB, { } },
114db40415e05e39c1f4faa62735f435b031e53af7csergeyv    { k_coreServiceCategory, "Core services", 0, { } },
115b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "sched",      "CPU Scheduling",   0, {
1162cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/sched/sched_switch/enable" },
1172cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/sched/sched_wakeup/enable" },
118237c363006dbc0e55dde8f4f37e0b5af15433840Joel Fernandes        { OPT,      "events/sched/sched_waking/enable" },
1192cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/sched/sched_blocked_reason/enable" },
1202cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/sched/sched_cpu_hotplug/enable" },
1216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
122f440d398faad3bafe2e7f365c62163aca45e36a3Dan Willemsen    { "irq",        "IRQ Events",   0, {
1232cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/irq/enable" },
1242cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ipi/enable" },
125f440d398faad3bafe2e7f365c62163aca45e36a3Dan Willemsen    } },
12643fb6787bcb749c6d848235e82fa17a002379bbfMichael Wright    { "i2c",        "I2C Events",   0, {
1272cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/enable" },
1282cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_read/enable" },
1292cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_write/enable" },
1302cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_result/enable" },
1312cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_reply/enable" },
1322cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_read/enable" },
1332cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_write/enable" },
1342cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_result/enable" },
1352cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_reply/enable" },
13643fb6787bcb749c6d848235e82fa17a002379bbfMichael Wright    } },
137b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "freq",       "CPU Frequency",    0, {
1382cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/power/cpu_frequency/enable" },
1392cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/power/clock_set_rate/enable" },
1402cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/power/cpu_frequency_limits/enable" },
1416eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
142b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "membus",     "Memory Bus Utilization", 0, {
1432cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/memory_bus/enable" },
1446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
145b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "idle",       "CPU Idle",         0, {
1462cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/power/cpu_idle/enable" },
1476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
148b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "disk",       "Disk I/O",         0, {
1492cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_sync_file_enter/enable" },
1502cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_sync_file_exit/enable" },
1512cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_write_begin/enable" },
1522cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_write_end/enable" },
1532cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_da_write_begin/enable" },
1542cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_da_write_end/enable" },
1552cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
1562cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
1572cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/block/block_rq_issue/enable" },
1582cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/block/block_rq_complete/enable" },
1596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
160d3fa5616160c53d5bec8cd91d65f3732413c1a56Ken Sumrall    { "mmc",        "eMMC commands",    0, {
1612cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/mmc/enable" },
162d3fa5616160c53d5bec8cd91d65f3732413c1a56Ken Sumrall    } },
163b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "load",       "CPU Load",         0, {
1642cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/cpufreq_interactive/enable" },
1656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
166b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "sync",       "Synchronization",  0, {
1672cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/sync/enable" },
1686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
169b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "workq",      "Kernel Workqueues", 0, {
1702cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/workqueue/enable" },
1716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
172580407f1075fe97d7466724f71cc03816b7404feColin Cross    { "memreclaim", "Kernel Memory Reclaim", 0, {
1732cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
1742cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
1752cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
1762cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
177580407f1075fe97d7466724f71cc03816b7404feColin Cross    } },
178c2c6ecd1195481f5813a721a7d20a73c0795c135Aaron Schulman    { "regulators",  "Voltage and Current Regulators", 0, {
1792cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/regulator/enable" },
180c2c6ecd1195481f5813a721a7d20a73c0795c135Aaron Schulman    } },
181ae473363270724550699a7fd9c110a839f79964cScott Bauer    { "binder_driver", "Binder Kernel driver", 0, {
1822cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_transaction/enable" },
1832cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_transaction_received/enable" },
184ae473363270724550699a7fd9c110a839f79964cScott Bauer    } },
185ae473363270724550699a7fd9c110a839f79964cScott Bauer    { "binder_lock", "Binder global lock trace", 0, {
1862cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_lock/enable" },
1872cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_locked/enable" },
1882cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_unlock/enable" },
189ae473363270724550699a7fd9c110a839f79964cScott Bauer    } },
1907048161951761cd5fe0109c34204ba8229f9eddfMartijn Coenen    { "pagecache",  "Page cache", 0, {
1912cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/filemap/enable" },
1927048161951761cd5fe0109c34204ba8229f9eddfMartijn Coenen    } },
1936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis};
1946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
195fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Command line options */
196fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic int g_traceDurationSeconds = 5;
197fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceOverwrite = false;
198cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic int g_traceBufferSizeKB = 2048;
1997b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennisstatic bool g_compress = false;
20031be80f02cddda55e75614884038fa4645b694cdGlenn Kastenstatic bool g_nohup = false;
20131be80f02cddda55e75614884038fa4645b694cdGlenn Kastenstatic int g_initialSleepSecs = 0;
20246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsudastatic const char* g_categoriesFile = NULL;
203e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* g_kernelTraceFuncs = NULL;
204f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennisstatic const char* g_debugAppCmdLine = "";
20540b26b4fc597f105823bc1e2a640e4df8baea243John Reckstatic const char* g_outputFile = nullptr;
206fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
207fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Global state */
208fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceAborted = false;
2096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool g_categoryEnables[NELEM(k_categories)] = {};
2102cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrencestatic std::string g_traceFolder;
211fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
212fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Sys file paths */
213fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceClockPath =
2142cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace_clock";
215fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
216cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_traceBufferSizePath =
2172cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "buffer_size_kb";
218cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
219efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandesstatic const char* k_traceCmdlineSizePath =
220efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandes    "saved_cmdlines_size";
221efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandes
222fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOverwriteEnablePath =
2232cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/overwrite";
224fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
225e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_currentTracerPath =
2262cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "current_tracer";
227e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
228e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_printTgidPath =
2292cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/print-tgid";
230e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
231e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphAbsTimePath =
2322cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-abstime";
233e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
234e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphCpuPath =
2352cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-cpu";
236e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
237e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphProcPath =
2382cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-proc";
239e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
240e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphFlatPath =
2412cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-flat";
242e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
243e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphDurationPath =
2442cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-duration";
245e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
246e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_ftraceFilterPath =
2472cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "set_ftrace_filter";
248e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
249fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOnPath =
2502cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "tracing_on";
251fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
252fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracePath =
2532cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace";
254fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
255d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenenstatic const char* k_traceStreamPath =
2562cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace_pipe";
257d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen
258469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reckstatic const char* k_traceMarkerPath =
2592cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace_marker";
260469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck
261e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis// Check whether a file exists.
262e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennisstatic bool fileExists(const char* filename) {
2632cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    return access((g_traceFolder + filename).c_str(), F_OK) != -1;
264e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis}
265e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis
2666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether a file is writable.
2676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool fileIsWritable(const char* filename) {
2682cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    return access((g_traceFolder + filename).c_str(), W_OK) != -1;
2696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
2706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
271e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Truncate a file.
272e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool truncateFile(const char* path)
273fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
27443122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    // This uses creat rather than truncate because some of the debug kernel
27543122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
27643122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    // calls to truncate, but they are cleared by calls to creat.
2772cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int traceFD = creat((g_traceFolder + path).c_str(), 0);
27843122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    if (traceFD == -1) {
2792cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "error truncating %s: %s (%d)\n", (g_traceFolder + path).c_str(),
28043122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis            strerror(errno), errno);
281e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        return false;
282e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
283e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
28443122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    close(traceFD);
28543122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis
286e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return true;
287e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
288e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
289e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool _writeStr(const char* filename, const char* str, int flags)
290e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
2912cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    std::string fullFilename = g_traceFolder + filename;
2922cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int fd = open(fullFilename.c_str(), flags);
293fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (fd == -1) {
2942cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "error opening %s: %s (%d)\n", fullFilename.c_str(),
295fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                strerror(errno), errno);
296fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        return false;
297fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
298fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
299fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    bool ok = true;
300fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    ssize_t len = strlen(str);
301fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (write(fd, str, len) != len) {
3022cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "error writing to %s: %s (%d)\n", fullFilename.c_str(),
303fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                strerror(errno), errno);
304fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        ok = false;
305fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
306fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
307fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    close(fd);
308fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
309fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return ok;
310fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
311fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
312e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Write a string to a file, returning true if the write was successful.
313e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool writeStr(const char* filename, const char* str)
314e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
315e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return _writeStr(filename, str, O_WRONLY);
316e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
317e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
318e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Append a string to a file, returning true if the write was successful.
319e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool appendStr(const char* filename, const char* str)
320e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
321e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return _writeStr(filename, str, O_APPEND|O_WRONLY);
322e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
323e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
324469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reckstatic void writeClockSyncMarker()
325469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck{
326469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck  char buffer[128];
3270bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  int len = 0;
3282cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence  int fd = open((g_traceFolder + k_traceMarkerPath).c_str(), O_WRONLY);
3290bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  if (fd == -1) {
3300bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
3310bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen              strerror(errno), errno);
3320bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      return;
3330bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  }
334469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck  float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
3350bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen
3360bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
3370bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  if (write(fd, buffer, len) != len) {
3380bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
3390bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  }
3400bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen
3410bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
3420bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
3430bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  if (write(fd, buffer, len) != len) {
3440bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
3450bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  }
3460bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen
3470bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  close(fd);
348469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck}
349469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck
3506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
3516eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// file.
352fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable)
353fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
354fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return writeStr(filename, enable ? "1" : "0");
355fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
356fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
3576eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether the category is supported on the device with the current
3586eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// rootness.  A category is supported only if all its required /sys/ files are
3596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// writable and if enabling the category will enable one or more tracing tags
3606eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// or /sys/ files.
3616eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool isCategorySupported(const TracingCategory& category)
3623169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis{
363db40415e05e39c1f4faa62735f435b031e53af7csergeyv    if (strcmp(category.name, k_coreServiceCategory) == 0) {
364db40415e05e39c1f4faa62735f435b031e53af7csergeyv        char value[PROPERTY_VALUE_MAX];
365db40415e05e39c1f4faa62735f435b031e53af7csergeyv        property_get(k_coreServicesProp, value, "");
366db40415e05e39c1f4faa62735f435b031e53af7csergeyv        return strlen(value) != 0;
367db40415e05e39c1f4faa62735f435b031e53af7csergeyv    }
368db40415e05e39c1f4faa62735f435b031e53af7csergeyv
3696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    bool ok = category.tags != 0;
3706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < MAX_SYS_FILES; i++) {
3716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const char* path = category.sysfiles[i].path;
3726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        bool req = category.sysfiles[i].required == REQ;
3736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (path != NULL) {
3746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (req) {
3756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (!fileIsWritable(path)) {
3766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    return false;
3776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                } else {
3786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    ok = true;
3796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
3806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            } else {
3816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                ok |= fileIsWritable(path);
3826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
3836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
384e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis    }
385e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis    return ok;
386cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis}
387cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
3886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether the category would be supported on the device if the user
3896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// were root.  This function assumes that root is able to write to any file
3906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// that exists.  It performs the same logic as isCategorySupported, but it
391b5c95475996c59bacb0ee760f11bf792f71e0c77Fabien Sanglard// uses file existence rather than writability in the /sys/ file checks.
3926eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool isCategorySupportedForRoot(const TracingCategory& category)
3939ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling{
3946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    bool ok = category.tags != 0;
3956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < MAX_SYS_FILES; i++) {
3966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const char* path = category.sysfiles[i].path;
3976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        bool req = category.sysfiles[i].required == REQ;
3986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (path != NULL) {
3996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (req) {
4006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (!fileExists(path)) {
4016eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    return false;
4026eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                } else {
4036eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    ok = true;
4046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
4056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            } else {
4066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                ok |= fileExists(path);
4076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
4086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
4099ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling    }
4109ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling    return ok;
4119ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling}
4129ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling
4136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Enable or disable overwriting of the kernel trace buffers.  Disabling this
4146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// will cause tracing to stop once the trace buffers have filled up.
4156eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setTraceOverwriteEnable(bool enable)
416ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown{
4176eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
418ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown}
419ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown
420fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable kernel tracing.
421fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTracingEnabled(bool enable)
422fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
423fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return setKernelOptionEnable(k_tracingOnPath, enable);
424fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
425fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
426fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Clear the contents of the kernel trace.
427fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool clearTrace()
428fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
429e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return truncateFile(k_tracePath);
430fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
431fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
432cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Set the size of the kernel's trace buffer in kilobytes.
433cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setTraceBufferSizeKB(int size)
434cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{
435cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    char str[32] = "1";
436cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    int len;
437cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    if (size < 1) {
438cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis        size = 1;
439cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    }
440cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    snprintf(str, 32, "%d", size);
441cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    return writeStr(k_traceBufferSizePath, str);
442cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis}
443cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
444efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandes// Set the default size of cmdline hashtable
445efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandesstatic bool setCmdlineSize()
446efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandes{
4479351f72049a2bc65170afcf131008c8bd1710959Joel Fernandes    if (fileExists(k_traceCmdlineSizePath)) {
4489351f72049a2bc65170afcf131008c8bd1710959Joel Fernandes        return writeStr(k_traceCmdlineSizePath, "8192");
4499351f72049a2bc65170afcf131008c8bd1710959Joel Fernandes    }
4509351f72049a2bc65170afcf131008c8bd1710959Joel Fernandes    return true;
451efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandes}
452efb73a96b559f88a168b1cfbd5a3ad865ab8f937Joel Fernandes
453ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson// Set the clock to the best available option while tracing. Use 'boot' if it's
454ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson// available; otherwise, use 'mono'. If neither are available use 'global'.
455b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross// Any write to the trace_clock sysfs file will reset the buffer, so only
456b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross// update it if the requested value is not the current value.
457ea826794184be368f65f099ceac4fc31234700f6Carmen Jacksonstatic bool setClock()
458fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
459ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
460ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
461ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        std::istreambuf_iterator<char>());
462ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson
463ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    std::string newClock;
464ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    if (clockStr.find("boot") != std::string::npos) {
465ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        newClock = "boot";
466ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    } else if (clockStr.find("mono") != std::string::npos) {
467ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        newClock = "mono";
468ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    } else {
469ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        newClock = "global";
470ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    }
471b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross
472ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    size_t begin = clockStr.find("[") + 1;
473ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    size_t end = clockStr.find("]");
474ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
475b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross        return true;
476b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross    }
477ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    return writeStr(k_traceClockPath, newClock.c_str());
478fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
479fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
480e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool setPrintTgidEnableIfPresent(bool enable)
481e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
482e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    if (fileExists(k_printTgidPath)) {
483e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        return setKernelOptionEnable(k_printTgidPath, enable);
484e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
485e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return true;
486e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
487e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
4886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Poke all the binder-enabled processes in the system to get them to re-read
4896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// their system properties.
4906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool pokeBinderServices()
4916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
4926eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    sp<IServiceManager> sm = defaultServiceManager();
4936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    Vector<String16> services = sm->listServices();
4946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (size_t i = 0; i < services.size(); i++) {
4956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        sp<IBinder> obj = sm->checkService(services[i]);
4966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (obj != NULL) {
4976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            Parcel data;
4986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
4996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    NULL, 0) != OK) {
5006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (false) {
5016eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    // XXX: For some reason this fails on tablets trying to
5026eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    // poke the "phone" service.  It's not clear whether some
5036eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    // are expected to fail.
5046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    String8 svc(services[i]);
5056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    fprintf(stderr, "error poking binder service %s\n",
5066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        svc.string());
5076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    return false;
5086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
5096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
5106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
5116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
5126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    return true;
5136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
5146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
515ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen// Poke all the HAL processes in the system to get them to re-read
516ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen// their system properties.
517ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenenstatic void pokeHalServices()
518ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen{
519f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen    using ::android::hidl::base::V1_0::IBase;
520ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    using ::android::hidl::manager::V1_0::IServiceManager;
521ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    using ::android::hardware::hidl_string;
522f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen    using ::android::hardware::Return;
523ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen
524ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
525a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland
526a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland    if (sm == nullptr) {
527a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland        fprintf(stderr, "failed to get IServiceManager to poke hal services\n");
528a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland        return;
529a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland    }
530a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland
5318cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong    auto listRet = sm->list([&](const auto &interfaces) {
532ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen        for (size_t i = 0; i < interfaces.size(); i++) {
533ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            string fqInstanceName = interfaces[i];
534ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            string::size_type n = fqInstanceName.find("/");
535ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            if (n == std::string::npos || interfaces[i].size() == n+1)
536ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen                continue;
537ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            hidl_string fqInterfaceName = fqInstanceName.substr(0, n);
538ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
539f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName);
540f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            if (!interfaceRet.isOk()) {
5411e4a7fbdd392cb5af35bca169d90b35850a9e9f4Martijn Coenen                // ignore
542f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen                continue;
543f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            }
5447320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson
545f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            sp<IBase> interface = interfaceRet;
5467320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson            if (interface == nullptr) {
5477320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson                // ignore
5487320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson                continue;
5497320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson            }
5507320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson
551f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            auto notifyRet = interface->notifySyspropsChanged();
552f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            if (!notifyRet.isOk()) {
5531e4a7fbdd392cb5af35bca169d90b35850a9e9f4Martijn Coenen                // ignore
5548cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong            }
555ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen        }
556ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    });
5578cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong    if (!listRet.isOk()) {
55864d54eb0465c7c372ea1b57a9fa4984be0cd79f8Martijn Coenen        // TODO(b/34242478) fix this when we determine the correct ACL
55964d54eb0465c7c372ea1b57a9fa4984be0cd79f8Martijn Coenen        //fprintf(stderr, "failed to list services: %s\n", listRet.description().c_str());
5608cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong    }
561ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen}
562ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen
5636eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Set the trace tags that userland tracing uses, and poke the running
5646eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// processes to pick up the new value.
5656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setTagsProperty(uint64_t tags)
5666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
5674144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    char buf[PROPERTY_VALUE_MAX];
5684144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    snprintf(buf, sizeof(buf), "%#" PRIx64, tags);
5696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    if (property_set(k_traceTagsProperty, buf) < 0) {
5706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        fprintf(stderr, "error setting trace tags system property\n");
5716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        return false;
5726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
573f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    return true;
574f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis}
575f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis
5764144eff1e261f6462be3753fc9543d82f9a4fd96sergeyvstatic void clearAppProperties()
5774144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv{
5784144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    char buf[PROPERTY_KEY_MAX];
5794144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    for (int i = 0; i < MAX_PACKAGES; i++) {
5804144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
5814144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        if (property_set(buf, "") < 0) {
5824144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            fprintf(stderr, "failed to clear system property: %s\n", buf);
5834144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        }
5844144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    }
5854144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    if (property_set(k_traceAppsNumberProperty, "") < 0) {
5864144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        fprintf(stderr, "failed to clear system property: %s",
5874144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv              k_traceAppsNumberProperty);
5884144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    }
5894144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv}
5904144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv
591f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis// Set the system property that indicates which apps should perform
592f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis// application-level tracing.
59309a7987fb59ed6843d51acf0161d66ed3eb2252fDan Austinstatic bool setAppCmdlineProperty(char* cmdline)
594f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis{
5954144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    char buf[PROPERTY_KEY_MAX];
5964144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    int i = 0;
59709a7987fb59ed6843d51acf0161d66ed3eb2252fDan Austin    char* start = cmdline;
5984144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    while (start != NULL) {
5994144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        if (i == MAX_PACKAGES) {
6004144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            fprintf(stderr, "error: only 16 packages could be traced at once\n");
6014144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            clearAppProperties();
6024144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            return false;
6034144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        }
6044144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        char* end = strchr(start, ',');
6054144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        if (end != NULL) {
6064144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            *end = '\0';
6074144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            end++;
6084144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        }
6094144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
6104144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        if (property_set(buf, start) < 0) {
6114144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            fprintf(stderr, "error setting trace app %d property to %s\n", i, buf);
6124144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            clearAppProperties();
6134144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            return false;
6144144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        }
6154144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        start = end;
6164144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        i++;
6174144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    }
6184144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv
6194144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    snprintf(buf, sizeof(buf), "%d", i);
6204144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    if (property_set(k_traceAppsNumberProperty, buf) < 0) {
6214144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        fprintf(stderr, "error setting trace app number property to %s\n", buf);
6224144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        clearAppProperties();
623f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis        return false;
624f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    }
625f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    return true;
6266eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
6276eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
6286eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Disable all /sys/ enable files.
6296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool disableKernelTraceEvents() {
6306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    bool ok = true;
6316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < NELEM(k_categories); i++) {
6326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const TracingCategory &c = k_categories[i];
6336eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        for (int j = 0; j < MAX_SYS_FILES; j++) {
6346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            const char* path = c.sysfiles[j].path;
6356eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (path != NULL && fileIsWritable(path)) {
6366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                ok &= setKernelOptionEnable(path, false);
6376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
6386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
6396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
6406eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    return ok;
6416eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
6426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
643e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Verify that the comma separated list of functions are being traced by the
644e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// kernel.
645e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool verifyKernelTraceFuncs(const char* funcs)
646e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
647d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini    std::string buf;
6482cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (!android::base::ReadFileToString(g_traceFolder + k_ftraceFilterPath, &buf)) {
649d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini         fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
650e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            strerror(errno), errno);
651d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini         return false;
652e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
653e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
654d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini    String8 funcList = String8::format("\n%s",buf.c_str());
655e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
656e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    // Make sure that every function listed in funcs is in the list we just
657a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot    // read from the kernel, except for wildcard inputs.
658e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    bool ok = true;
659e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    char* myFuncs = strdup(funcs);
660e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    char* func = strtok(myFuncs, ",");
661e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    while (func) {
662a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot        if (!strchr(func, '*')) {
663a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            String8 fancyFunc = String8::format("\n%s\n", func);
664a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            bool found = funcList.find(fancyFunc.string(), 0) >= 0;
665a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            if (!found || func[0] == '\0') {
666a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot                fprintf(stderr, "error: \"%s\" is not a valid kernel function "
667a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot                        "to trace.\n", func);
668a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot                ok = false;
669a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            }
670e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
671e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        func = strtok(NULL, ",");
672e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
673e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    free(myFuncs);
674e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return ok;
675e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
676e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
677e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Set the comma separated list of functions that the kernel is to trace.
678e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool setKernelTraceFuncs(const char* funcs)
679e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
680e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    bool ok = true;
681e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
682e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    if (funcs == NULL || funcs[0] == '\0') {
683e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Disable kernel function tracing.
6846f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis        if (fileIsWritable(k_currentTracerPath)) {
6856f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            ok &= writeStr(k_currentTracerPath, "nop");
6866f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis        }
6876f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis        if (fileIsWritable(k_ftraceFilterPath)) {
688e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            ok &= truncateFile(k_ftraceFilterPath);
689e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
690e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    } else {
691e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Enable kernel function tracing.
692e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= writeStr(k_currentTracerPath, "function_graph");
693e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
694e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
695e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
696e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
697e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
698e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Set the requested filter functions.
699e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= truncateFile(k_ftraceFilterPath);
700e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        char* myFuncs = strdup(funcs);
701e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        char* func = strtok(myFuncs, ",");
702e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        while (func) {
703e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            ok &= appendStr(k_ftraceFilterPath, func);
704e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            func = strtok(NULL, ",");
705e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
706e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        free(myFuncs);
707e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
708e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Verify that the set functions are being traced.
709e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        if (ok) {
710e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            ok &= verifyKernelTraceFuncs(funcs);
711e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
712e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
713e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
714e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return ok;
715e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
716e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
71746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsudastatic bool setCategoryEnable(const char* name, bool enable)
71846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda{
71946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    for (int i = 0; i < NELEM(k_categories); i++) {
72046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        const TracingCategory& c = k_categories[i];
72146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        if (strcmp(name, c.name) == 0) {
72246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            if (isCategorySupported(c)) {
72346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                g_categoryEnables[i] = enable;
72446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                return true;
72546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            } else {
72646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                if (isCategorySupportedForRoot(c)) {
72746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    fprintf(stderr, "error: category \"%s\" requires root "
72846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                            "privileges.\n", name);
72946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                } else {
73046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    fprintf(stderr, "error: category \"%s\" is not supported "
73146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                            "on this device.\n", name);
73246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                }
73346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                return false;
73446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            }
73546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        }
73646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
73746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
73846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    return false;
73946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda}
74046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda
74146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsudastatic bool setCategoriesEnableFromFile(const char* categories_file)
74246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda{
74346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    if (!categories_file) {
74446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        return true;
74546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
74646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    Tokenizer* tokenizer = NULL;
74746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
74846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        return false;
74946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
75046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    bool ok = true;
75146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    while (!tokenizer->isEol()) {
75246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        String8 token = tokenizer->nextToken(" ");
75346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        if (token.isEmpty()) {
75446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            tokenizer->skipDelimiters(" ");
75546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            continue;
75646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        }
75746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        ok &= setCategoryEnable(token.string(), true);
75846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
75946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    delete tokenizer;
76046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    return ok;
76146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda}
76246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda
763e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Set all the kernel tracing settings to the desired state for this trace
764e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// capture.
765e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool setUpTrace()
766fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
767fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    bool ok = true;
768fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
7696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Set up the tracing options.
77046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    ok &= setCategoriesEnableFromFile(g_categoriesFile);
771fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    ok &= setTraceOverwriteEnable(g_traceOverwrite);
772cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
773b5d1e187cf4a178173a01b93330bcfc262283f7cJohn Reck    // TODO: Re-enable after stabilization
774b5d1e187cf4a178173a01b93330bcfc262283f7cJohn Reck    //ok &= setCmdlineSize();
775ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    ok &= setClock();
776e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    ok &= setPrintTgidEnableIfPresent(true);
777e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
778fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
7796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Set up the tags property.
7806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    uint64_t tags = 0;
7816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < NELEM(k_categories); i++) {
7826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (g_categoryEnables[i]) {
7836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            const TracingCategory &c = k_categories[i];
7846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            tags |= c.tags;
7856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
7866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
7876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    ok &= setTagsProperty(tags);
788db40415e05e39c1f4faa62735f435b031e53af7csergeyv
789db40415e05e39c1f4faa62735f435b031e53af7csergeyv    bool coreServicesTagEnabled = false;
790db40415e05e39c1f4faa62735f435b031e53af7csergeyv    for (int i = 0; i < NELEM(k_categories); i++) {
791db40415e05e39c1f4faa62735f435b031e53af7csergeyv        if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
792db40415e05e39c1f4faa62735f435b031e53af7csergeyv            coreServicesTagEnabled = g_categoryEnables[i];
793db40415e05e39c1f4faa62735f435b031e53af7csergeyv        }
794db40415e05e39c1f4faa62735f435b031e53af7csergeyv    }
795db40415e05e39c1f4faa62735f435b031e53af7csergeyv
796db40415e05e39c1f4faa62735f435b031e53af7csergeyv    std::string packageList(g_debugAppCmdLine);
797db40415e05e39c1f4faa62735f435b031e53af7csergeyv    if (coreServicesTagEnabled) {
798db40415e05e39c1f4faa62735f435b031e53af7csergeyv        char value[PROPERTY_VALUE_MAX];
799db40415e05e39c1f4faa62735f435b031e53af7csergeyv        property_get(k_coreServicesProp, value, "");
800db40415e05e39c1f4faa62735f435b031e53af7csergeyv        if (!packageList.empty()) {
801db40415e05e39c1f4faa62735f435b031e53af7csergeyv            packageList += ",";
802db40415e05e39c1f4faa62735f435b031e53af7csergeyv        }
803db40415e05e39c1f4faa62735f435b031e53af7csergeyv        packageList += value;
804db40415e05e39c1f4faa62735f435b031e53af7csergeyv    }
80509a7987fb59ed6843d51acf0161d66ed3eb2252fDan Austin    ok &= setAppCmdlineProperty(&packageList[0]);
806f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    ok &= pokeBinderServices();
807ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    pokeHalServices();
8086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
8096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Disable all the sysfs enables.  This is done as a separate loop from
8106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // the enables to allow the same enable to exist in multiple categories.
8116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    ok &= disableKernelTraceEvents();
8126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
8136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Enable all the sysfs enables that are in an enabled category.
8146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < NELEM(k_categories); i++) {
8156eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (g_categoryEnables[i]) {
8166eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            const TracingCategory &c = k_categories[i];
8176eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            for (int j = 0; j < MAX_SYS_FILES; j++) {
8186eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                const char* path = c.sysfiles[j].path;
8196eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                bool required = c.sysfiles[j].required == REQ;
8206eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (path != NULL) {
8216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    if (fileIsWritable(path)) {
8226eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        ok &= setKernelOptionEnable(path, true);
8236eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    } else if (required) {
8246eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        fprintf(stderr, "error writing file %s\n", path);
8256eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        ok = false;
8266eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    }
8276eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
8286eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
8296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
8304b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis    }
8314b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis
832fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return ok;
833fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
834fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
835e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Reset all the kernel tracing settings to their default state.
836e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic void cleanUpTrace()
837fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
8386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Disable all tracing that we're able to.
8396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    disableKernelTraceEvents();
8406eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
841f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    // Reset the system properties.
8426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    setTagsProperty(0);
8434144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    clearAppProperties();
844f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    pokeBinderServices();
8456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
846fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    // Set the options back to their defaults.
847fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    setTraceOverwriteEnable(true);
848e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setTraceBufferSizeKB(1);
849e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setPrintTgidEnableIfPresent(false);
850e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setKernelTraceFuncs(NULL);
851e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
852e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
853e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
854e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Enable tracing in the kernel.
855e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool startTrace()
856e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
857e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return setTracingEnabled(true);
858e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
859cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
860e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Disable tracing in the kernel.
861e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic void stopTrace()
862e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
863e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setTracingEnabled(false);
864fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
865fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
866d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen// Read data from the tracing pipe and forward to stdout
867d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenenstatic void streamTrace()
868d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen{
869d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    char trace_data[4096];
8702cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int traceFD = open((g_traceFolder + k_traceStreamPath).c_str(), O_RDWR);
871d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    if (traceFD == -1) {
872d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
873d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                strerror(errno), errno);
874d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        return;
875d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    }
876d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    while (!g_traceAborted) {
877d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        ssize_t bytes_read = read(traceFD, trace_data, 4096);
878d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (bytes_read > 0) {
879d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            write(STDOUT_FILENO, trace_data, bytes_read);
880d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            fflush(stdout);
881d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        } else {
882d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            if (!g_traceAborted) {
883d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
884d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                        bytes_read, errno, strerror(errno));
885d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            }
886d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            break;
887d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        }
888d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    }
889d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen}
890d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen
891fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Read the current kernel trace and write it to stdout.
89240b26b4fc597f105823bc1e2a640e4df8baea243John Reckstatic void dumpTrace(int outFd)
893fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
8946c8ac921ead0771b36281763d3724d67c9146c62John Reck    ALOGI("Dumping trace");
8952cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int traceFD = open((g_traceFolder + k_tracePath).c_str(), O_RDWR);
896fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (traceFD == -1) {
897fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
898fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                strerror(errno), errno);
899fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        return;
900fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
901fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
9027b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis    if (g_compress) {
9037b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        z_stream zs;
9043da5d235dab9469ccec567c4ebbb5206f4558a18Elliott Hughes        memset(&zs, 0, sizeof(zs));
905a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes
906a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
9077b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (result != Z_OK) {
9087b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error initializing zlib: %d\n", result);
9097b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            close(traceFD);
9107b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            return;
9117b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
9127b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
913a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        constexpr size_t bufSize = 64*1024;
914a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
915a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
916a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        if (!in || !out) {
917a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes            fprintf(stderr, "couldn't allocate buffers\n");
918a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes            close(traceFD);
919a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes            return;
920a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        }
921a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes
922a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        int flush = Z_NO_FLUSH;
9237b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
924a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        zs.next_out = reinterpret_cast<Bytef*>(out.get());
9257b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        zs.avail_out = bufSize;
9267b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9277b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        do {
9287b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9297b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            if (zs.avail_in == 0) {
9307b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                // More input is needed.
931a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes                result = read(traceFD, in.get(), bufSize);
9327b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                if (result < 0) {
9337b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    fprintf(stderr, "error reading trace: %s (%d)\n",
9347b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                            strerror(errno), errno);
9357b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    result = Z_STREAM_END;
9367b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    break;
9377b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                } else if (result == 0) {
9387b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    flush = Z_FINISH;
9397b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                } else {
940a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes                    zs.next_in = reinterpret_cast<Bytef*>(in.get());
9417b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    zs.avail_in = result;
9427b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                }
9437b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            }
9447b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9457b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            if (zs.avail_out == 0) {
9467b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                // Need to write the output.
947b59e2961471db9ede954a3d843e0bb545bb290faElliott Hughes                result = write(outFd, out.get(), bufSize);
9487b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                if ((size_t)result < bufSize) {
9497b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    fprintf(stderr, "error writing deflated trace: %s (%d)\n",
9507b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                            strerror(errno), errno);
9517b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    result = Z_STREAM_END; // skip deflate error message
9527b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    zs.avail_out = bufSize; // skip the final write
9537b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    break;
9547b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                }
955a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes                zs.next_out = reinterpret_cast<Bytef*>(out.get());
9567b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                zs.avail_out = bufSize;
9577b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            }
9587b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9597b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        } while ((result = deflate(&zs, flush)) == Z_OK);
9607b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9617b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (result != Z_STREAM_END) {
9627b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error deflating trace: %s\n", zs.msg);
9637b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
9647b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9657b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (zs.avail_out < bufSize) {
9667b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            size_t bytes = bufSize - zs.avail_out;
967b59e2961471db9ede954a3d843e0bb545bb290faElliott Hughes            result = write(outFd, out.get(), bytes);
9687b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            if ((size_t)result < bytes) {
9697b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                fprintf(stderr, "error writing deflated trace: %s (%d)\n",
9707b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                        strerror(errno), errno);
9717b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            }
9727b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
9737b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9747b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        result = deflateEnd(&zs);
9757b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (result != Z_OK) {
9767b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error cleaning up zlib: %d\n", result);
9777b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
9787b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis    } else {
9797b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        ssize_t sent = 0;
98040b26b4fc597f105823bc1e2a640e4df8baea243John Reck        while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
9817b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (sent == -1) {
9827b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
9837b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    errno);
9847b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
985fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
986fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
987fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    close(traceFD);
988fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
989fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
99092dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzynstatic void handleSignal(int /*signo*/)
991fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
99231be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    if (!g_nohup) {
99331be80f02cddda55e75614884038fa4645b694cdGlenn Kasten        g_traceAborted = true;
99431be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    }
995fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
996fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
9976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void registerSigHandler()
9986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
999fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    struct sigaction sa;
1000fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigemptyset(&sa.sa_mask);
1001fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sa.sa_flags = 0;
1002fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sa.sa_handler = handleSignal;
1003fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGHUP, &sa, NULL);
1004fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGINT, &sa, NULL);
1005fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGQUIT, &sa, NULL);
1006fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGTERM, &sa, NULL);
1007fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
1008fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
10096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void listSupportedCategories()
10106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
10116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < NELEM(k_categories); i++) {
10126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const TracingCategory& c = k_categories[i];
10136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (isCategorySupported(c)) {
10146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            printf("  %10s - %s\n", c.name, c.longname);
10156eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
10166eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
10176eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
10186eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
10196eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Print the command usage help to stderr.
10206eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void showHelp(const char *cmd)
10216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
10226eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
10236eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    fprintf(stderr, "options include:\n"
1024f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis                    "  -a appname      enable app-level tracing for a comma "
1025f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis                        "separated list of cmdlines\n"
10266eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -b N            use a trace buffer size of N KB\n"
10276eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -c              trace into a circular buffer\n"
102846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    "  -f filename     use the categories written in a file as space-separated\n"
102946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    "                    values in a line\n"
1030e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis                    "  -k fname,...    trace the listed kernel functions\n"
10316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -n              ignore signals\n"
10326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -s N            sleep for N seconds before tracing [default 0]\n"
1033b5c95475996c59bacb0ee760f11bf792f71e0c77Fabien Sanglard                    "  -t N            trace for N seconds [default 5]\n"
10346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -z              compress the trace dump\n"
1035b5c95475996c59bacb0ee760f11bf792f71e0c77Fabien Sanglard                    "  --async_start   start circular trace and return immediately\n"
10366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  --async_dump    dump the current contents of circular trace buffer\n"
10376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  --async_stop    stop tracing and dump the current contents of circular\n"
10386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "                    trace buffer\n"
1039d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "  --stream        stream trace to stdout as it enters the trace buffer\n"
1040d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "                    Note: this can take significant CPU time, and is best\n"
1041d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "                    used for measuring things that are not affected by\n"
1042d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "                    CPU performance, like pagecache usage.\n"
104392573f1ba0d5360d7bfa8ab8935118db7a251f62Jamie Gennis                    "  --list_categories\n"
104492573f1ba0d5360d7bfa8ab8935118db7a251f62Jamie Gennis                    "                  list the available tracing categories\n"
104540b26b4fc597f105823bc1e2a640e4df8baea243John Reck                    " -o filename      write the trace to the specified file instead\n"
104640b26b4fc597f105823bc1e2a640e4df8baea243John Reck                    "                    of stdout.\n"
10476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            );
10486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
10496eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
10502cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrencebool findTraceFiles()
10512cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence{
10522cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    static const std::string debugfs_path = "/sys/kernel/debug/tracing/";
10532cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    static const std::string tracefs_path = "/sys/kernel/tracing/";
10542cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    static const std::string trace_file = "trace_marker";
10552cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
10562cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    bool tracefs = access((tracefs_path + trace_file).c_str(), F_OK) != -1;
10572cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    bool debugfs = access((debugfs_path + trace_file).c_str(), F_OK) != -1;
10582cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
10592cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (!tracefs && !debugfs) {
10602cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "Error: Did not find trace folder\n");
10612cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        return false;
10622cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    }
10632cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
10642cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (tracefs) {
10652cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        g_traceFolder = tracefs_path;
10662cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    } else {
10672cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        g_traceFolder = debugfs_path;
10682cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    }
10692cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
10702cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    return true;
10712cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence}
10722cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
1073fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisint main(int argc, char **argv)
1074fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
10754edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool async = false;
10764edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool traceStart = true;
10774edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool traceStop = true;
10784edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool traceDump = true;
1079d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    bool traceStream = false;
10804b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis
1081fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
1082fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        showHelp(argv[0]);
1083fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        exit(0);
1084fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1085fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
10862cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (!findTraceFiles()) {
10872cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "No trace folder found\n");
10882cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        exit(-1);
10892cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    }
10902cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
1091fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    for (;;) {
1092fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        int ret;
10934edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling        int option_index = 0;
10944edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling        static struct option long_options[] = {
10954edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling            {"async_start",     no_argument, 0,  0 },
10964edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling            {"async_stop",      no_argument, 0,  0 },
10974edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling            {"async_dump",      no_argument, 0,  0 },
10986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            {"list_categories", no_argument, 0,  0 },
1099d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            {"stream",          no_argument, 0,  0 },
11006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            {           0,                0, 0,  0 }
11014edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling        };
1102fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
110340b26b4fc597f105823bc1e2a640e4df8baea243John Reck        ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
11044edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                          long_options, &option_index);
1105fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1106fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        if (ret < 0) {
11076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            for (int i = optind; i < argc; i++) {
11086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (!setCategoryEnable(argv[i], true)) {
11096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
11106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    exit(1);
11116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
11126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
1113fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1114fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1115fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1116fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        switch(ret) {
1117f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis            case 'a':
1118f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis                g_debugAppCmdLine = optarg;
1119f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis            break;
1120f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis
1121cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis            case 'b':
1122cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis                g_traceBufferSizeKB = atoi(optarg);
1123cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis            break;
1124cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
1125fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            case 'c':
1126fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                g_traceOverwrite = true;
1127fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1128fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
112946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            case 'f':
113046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                g_categoriesFile = optarg;
113146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            break;
113246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda
1133e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            case 'k':
1134e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis                g_kernelTraceFuncs = optarg;
11356f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            break;
1136e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
113731be80f02cddda55e75614884038fa4645b694cdGlenn Kasten            case 'n':
113831be80f02cddda55e75614884038fa4645b694cdGlenn Kasten                g_nohup = true;
11396f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            break;
114031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten
1141fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            case 's':
114231be80f02cddda55e75614884038fa4645b694cdGlenn Kasten                g_initialSleepSecs = atoi(optarg);
114331be80f02cddda55e75614884038fa4645b694cdGlenn Kasten            break;
114431be80f02cddda55e75614884038fa4645b694cdGlenn Kasten
1145fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            case 't':
1146fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                g_traceDurationSeconds = atoi(optarg);
1147fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1148fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
11497b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            case 'z':
11507b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                g_compress = true;
11517b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            break;
11527b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
115340b26b4fc597f105823bc1e2a640e4df8baea243John Reck            case 'o':
115440b26b4fc597f105823bc1e2a640e4df8baea243John Reck                g_outputFile = optarg;
115540b26b4fc597f105823bc1e2a640e4df8baea243John Reck            break;
115640b26b4fc597f105823bc1e2a640e4df8baea243John Reck
11574edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling            case 0:
11584edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                if (!strcmp(long_options[option_index].name, "async_start")) {
11594edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    async = true;
11604edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceStop = false;
11614edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceDump = false;
11624edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    g_traceOverwrite = true;
11634edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                } else if (!strcmp(long_options[option_index].name, "async_stop")) {
11644edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    async = true;
11654ba2b63bff492815a86954c272a36d886f5bccecJohn Reck                    traceStart = false;
11664edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                } else if (!strcmp(long_options[option_index].name, "async_dump")) {
11674edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    async = true;
11684edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceStart = false;
11694edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceStop = false;
1170d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                } else if (!strcmp(long_options[option_index].name, "stream")) {
1171d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    traceStream = true;
1172d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    traceDump = false;
11736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                } else if (!strcmp(long_options[option_index].name, "list_categories")) {
11746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    listSupportedCategories();
11756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    exit(0);
11764edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                }
11776f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            break;
11784edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling
1179fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            default:
1180cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis                fprintf(stderr, "\n");
1181fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                showHelp(argv[0]);
1182fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                exit(-1);
1183fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1184fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1185fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1186fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1187fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    registerSigHandler();
1188fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
118931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    if (g_initialSleepSecs > 0) {
119031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten        sleep(g_initialSleepSecs);
119131be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    }
119231be80f02cddda55e75614884038fa4645b694cdGlenn Kasten
1193e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    bool ok = true;
1194e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    ok &= setUpTrace();
1195e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    ok &= startTrace();
1196fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
11974edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    if (ok && traceStart) {
1198d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (!traceStream) {
1199d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            printf("capturing trace...");
1200d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            fflush(stdout);
1201d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        }
1202fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1203fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // We clear the trace after starting it because tracing gets enabled for
1204fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // each CPU individually in the kernel. Having the beginning of the trace
1205fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // contain entries from only one CPU can cause "begin" entries without a
1206fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // matching "end" entry to show up if a task gets migrated from one CPU to
1207fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // another.
1208fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        ok = clearTrace();
1209fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
12100bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen        writeClockSyncMarker();
1211d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (ok && !async && !traceStream) {
1212fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            // Sleep to allow the trace to be captured.
1213fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            struct timespec timeLeft;
1214fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            timeLeft.tv_sec = g_traceDurationSeconds;
1215fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            timeLeft.tv_nsec = 0;
1216fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            do {
1217fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                if (g_traceAborted) {
1218fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                    break;
1219fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                }
1220fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
1221fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1222d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen
1223d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (traceStream) {
1224d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            streamTrace();
1225d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        }
1226fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1227fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1228fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    // Stop the trace and restore the default settings.
12294edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    if (traceStop)
12306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        stopTrace();
1231fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
12324edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    if (ok && traceDump) {
1233fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        if (!g_traceAborted) {
123440b26b4fc597f105823bc1e2a640e4df8baea243John Reck            printf(" done\n");
1235fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            fflush(stdout);
123640b26b4fc597f105823bc1e2a640e4df8baea243John Reck            int outFd = STDOUT_FILENO;
123740b26b4fc597f105823bc1e2a640e4df8baea243John Reck            if (g_outputFile) {
1238c579198835539100087ba71f5bbf38c3c09422e6Martijn Coenen                outFd = open(g_outputFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
123940b26b4fc597f105823bc1e2a640e4df8baea243John Reck            }
124040b26b4fc597f105823bc1e2a640e4df8baea243John Reck            if (outFd == -1) {
124140b26b4fc597f105823bc1e2a640e4df8baea243John Reck                printf("Failed to open '%s', err=%d", g_outputFile, errno);
124240b26b4fc597f105823bc1e2a640e4df8baea243John Reck            } else {
124340b26b4fc597f105823bc1e2a640e4df8baea243John Reck                dprintf(outFd, "TRACE:\n");
124440b26b4fc597f105823bc1e2a640e4df8baea243John Reck                dumpTrace(outFd);
124540b26b4fc597f105823bc1e2a640e4df8baea243John Reck                if (g_outputFile) {
124640b26b4fc597f105823bc1e2a640e4df8baea243John Reck                    close(outFd);
124740b26b4fc597f105823bc1e2a640e4df8baea243John Reck                }
124840b26b4fc597f105823bc1e2a640e4df8baea243John Reck            }
1249fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        } else {
1250fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            printf("\ntrace aborted.\n");
1251fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            fflush(stdout);
1252fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1253fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        clearTrace();
12544edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    } else if (!ok) {
1255fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        fprintf(stderr, "unable to start tracing\n");
1256fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1257fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1258cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    // Reset the trace buffer size to 1.
12594edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    if (traceStop)
1260e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        cleanUpTrace();
1261cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
1262fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return g_traceAborted ? 1 : 0;
1263fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
1264