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 <time.h>
30d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen#include <unistd.h>
317b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis#include <zlib.h>
32fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
33ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson#include <fstream>
34a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes#include <memory>
35a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes
366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/IBinder.h>
376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/IServiceManager.h>
386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/Parcel.h>
396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
40ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen#include <android/hidl/manager/1.0/IServiceManager.h>
41ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen#include <hidl/ServiceManagement.h>
426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
43a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka#include <pdx/default_transport/service_utility.h>
446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <utils/String8.h>
45469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck#include <utils/Timers.h>
4646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda#include <utils/Tokenizer.h>
476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <utils/Trace.h>
48d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini#include <android-base/file.h>
495fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes#include <android-base/macros.h>
505fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes#include <android-base/properties.h>
515fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes#include <android-base/stringprintf.h>
526eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
536eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisusing namespace android;
54a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabakausing pdx::default_transport::ServiceUtility;
556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
56ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenenusing std::string;
57ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown
584144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv#define MAX_SYS_FILES 10
596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
606eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisconst char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
6165ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jacksonconst char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated";
624144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv
634144eff1e261f6462be3753fc9543d82f9a4fd96sergeyvconst char* k_traceAppsNumberProperty = "debug.atrace.app_number";
644144eff1e261f6462be3753fc9543d82f9a4fd96sergeyvconst char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
65db40415e05e39c1f4faa62735f435b031e53af7csergeyvconst char* k_coreServiceCategory = "core_services";
66a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabakaconst char* k_pdxServiceCategory = "pdx";
67db40415e05e39c1f4faa62735f435b031e53af7csergeyvconst char* k_coreServicesProp = "ro.atrace.core.services";
686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennistypedef enum { OPT, REQ } requiredness  ;
706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstruct TracingCategory {
726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // The name identifying the category.
736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    const char* name;
746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // A longer description of the category.
766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    const char* longname;
776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // The userland tracing tags that the category enables.
796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    uint64_t tags;
806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // The fname==NULL terminated list of /sys/ files that the category
826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // enables.
836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    struct {
846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        // Whether the file must be writable in order to enable the tracing
856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        // category.
866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        requiredness required;
876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        // The path to the enable file.
896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const char* path;
906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } sysfiles[MAX_SYS_FILES];
916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis};
926eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis/* Tracing categories */
946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic const TracingCategory k_categories[] = {
95732a29a4a6f07958bd15e01c5ec1fdab53243374John Reck    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
96732a29a4a6f07958bd15e01c5ec1fdab53243374John Reck        { OPT,      "events/mdss/enable" },
97e2c104625d60ee2be3d727f7074fe649c3fed377Wei Wang        { OPT,      "events/sde/enable" },
98732a29a4a6f07958bd15e01c5ec1fdab53243374John Reck    } },
99b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "input",      "Input",            ATRACE_TAG_INPUT, { } },
100b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "view",       "View System",      ATRACE_TAG_VIEW, { } },
101b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
102b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
103b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
10470ec2941530766bdca09ef2983a3ff794c028ee6Patrick Auchter    { "sm",         "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
105b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
106b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
107b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
108b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
1099380d78c98d8b8fbce9ade5881fab7134fadc015Dianne Hackborn    { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
110eff2e8d2374692213204468433e3d96e7472ea02Jamie Gennis    { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
111f0f2841d95a26247dfa0b31a6bfa8b010fe89aa2Tim Murray    { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
112750aa9743c0c4c592213fbb39b8d328bd0075fd6Brigid Smith    { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
1133200b0bf507936ecf43784191880e4e91c54568cJeff Brown    { "power",      "Power Management", ATRACE_TAG_POWER, { } },
11401e111b5a02440c0684494e9286709285e20097fTodd Kennedy    { "pm",         "Package Manager",  ATRACE_TAG_PACKAGE_MANAGER, { } },
1157cc4977ccd98a4ee557c8382bbc705eef702bdb6Yasuhiro Matsuda    { "ss",         "System Server",    ATRACE_TAG_SYSTEM_SERVER, { } },
116bbd7d991db7cdb0f09a765d23e32c7441eb0393fGreg Hackmann    { "database",   "Database",         ATRACE_TAG_DATABASE, { } },
1170f97c1d775dd95fab5142d7aae6d34b80b4c2312Felipe Leme    { "network",    "Network",          ATRACE_TAG_NETWORK, { } },
118468b4cb566fd81d7181764d3f7121125c7db3b24Josh Gao    { "adb",        "ADB",              ATRACE_TAG_ADB, { } },
11947791e972a0127399808e429361e99c8a3a50c38Martijn Coenen    { "vibrator",   "Vibrator",         ATRACE_TAG_VIBRATOR, { } },
12047791e972a0127399808e429361e99c8a3a50c38Martijn Coenen    { "aidl",       "AIDL calls",       ATRACE_TAG_AIDL, { } },
121db40415e05e39c1f4faa62735f435b031e53af7csergeyv    { k_coreServiceCategory, "Core services", 0, { } },
122a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka    { k_pdxServiceCategory, "PDX services", 0, { } },
123b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "sched",      "CPU Scheduling",   0, {
1242cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/sched/sched_switch/enable" },
1252cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/sched/sched_wakeup/enable" },
126ee593e27cf607ab4603f65e89a7a366c5f154942Joel Fernandes        { OPT,      "events/sched/sched_waking/enable" },
1272cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/sched/sched_blocked_reason/enable" },
1282cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/sched/sched_cpu_hotplug/enable" },
129ca49dfccbadab5ac57d4f8bb31b2a6a0a51c0fb2Wei Wang        { OPT,      "events/sched/sched_pi_setprio/enable" },
1304dfca7c9d7decf492b244cd031d98c30c6a592ebJoel Fernandes        { OPT,      "events/cgroup/enable" },
1316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
132f440d398faad3bafe2e7f365c62163aca45e36a3Dan Willemsen    { "irq",        "IRQ Events",   0, {
1332cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/irq/enable" },
1342cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ipi/enable" },
135f440d398faad3bafe2e7f365c62163aca45e36a3Dan Willemsen    } },
1360ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes    { "irqoff",     "IRQ-disabled code section tracing", 0, {
1370ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes        { REQ,      "events/preemptirq/irq_enable/enable" },
1380ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes        { REQ,      "events/preemptirq/irq_disable/enable" },
1390ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes    } },
1400ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes    { "preemptoff", "Preempt-disabled code section tracing", 0, {
1410ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes        { REQ,      "events/preemptirq/preempt_enable/enable" },
1420ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes        { REQ,      "events/preemptirq/preempt_disable/enable" },
1430ad0f3059ffca0c6e1de680ca7e68d5150b8b14fJoel Fernandes    } },
14443fb6787bcb749c6d848235e82fa17a002379bbfMichael Wright    { "i2c",        "I2C Events",   0, {
1452cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/enable" },
1462cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_read/enable" },
1472cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_write/enable" },
1482cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_result/enable" },
1492cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/i2c/i2c_reply/enable" },
1502cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_read/enable" },
1512cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_write/enable" },
1522cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_result/enable" },
1532cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/i2c/smbus_reply/enable" },
15443fb6787bcb749c6d848235e82fa17a002379bbfMichael Wright    } },
155b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "freq",       "CPU Frequency",    0, {
1562cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/power/cpu_frequency/enable" },
1572cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/power/clock_set_rate/enable" },
158afc2f970e479dca5f9676474879b0b8d4beac82aKevin DuBois        { OPT,      "events/power/clock_disable/enable" },
159afc2f970e479dca5f9676474879b0b8d4beac82aKevin DuBois        { OPT,      "events/power/clock_enable/enable" },
160391efc2e4a00e6e408d5a21c138ef8bcba90eb90Wei Wang        { OPT,      "events/clk/clk_set_rate/enable" },
161391efc2e4a00e6e408d5a21c138ef8bcba90eb90Wei Wang        { OPT,      "events/clk/clk_disable/enable" },
162391efc2e4a00e6e408d5a21c138ef8bcba90eb90Wei Wang        { OPT,      "events/clk/clk_enable/enable" },
1632cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/power/cpu_frequency_limits/enable" },
1646eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
165b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "membus",     "Memory Bus Utilization", 0, {
1662cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/memory_bus/enable" },
1676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
168b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "idle",       "CPU Idle",         0, {
1692cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/power/cpu_idle/enable" },
1706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
171b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "disk",       "Disk I/O",         0, {
1722cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_sync_file_enter/enable" },
1732cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_sync_file_exit/enable" },
1742cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_write_begin/enable" },
1752cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/f2fs/f2fs_write_end/enable" },
1762cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_da_write_begin/enable" },
1772cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_da_write_end/enable" },
1782cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
1792cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
1802cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/block/block_rq_issue/enable" },
1812cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/block/block_rq_complete/enable" },
1826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
183d3fa5616160c53d5bec8cd91d65f3732413c1a56Ken Sumrall    { "mmc",        "eMMC commands",    0, {
1842cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/mmc/enable" },
185d3fa5616160c53d5bec8cd91d65f3732413c1a56Ken Sumrall    } },
186b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "load",       "CPU Load",         0, {
1872cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/cpufreq_interactive/enable" },
1886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
189b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "sync",       "Synchronization",  0, {
190ae001a33fbfeb30f91ab33e675de7c3efa49111cJesse Hall        // before linux kernel 4.9
191ae001a33fbfeb30f91ab33e675de7c3efa49111cJesse Hall        { OPT,      "events/sync/enable" },
192ae001a33fbfeb30f91ab33e675de7c3efa49111cJesse Hall        // starting in linux kernel 4.9
193ae001a33fbfeb30f91ab33e675de7c3efa49111cJesse Hall        { OPT,      "events/fence/enable" },
1946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
195b2a89e3155969e5bc9653966069d6dbabdd3f623Jamie Gennis    { "workq",      "Kernel Workqueues", 0, {
1962cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/workqueue/enable" },
1976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    } },
198580407f1075fe97d7466724f71cc03816b7404feColin Cross    { "memreclaim", "Kernel Memory Reclaim", 0, {
1992cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
2002cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
2012cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
2022cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
203f1f62e3b73fa5b84a552332beeacce874fd9429cMarc Hittinger        { REQ,      "events/lowmemorykiller/enable" },
204580407f1075fe97d7466724f71cc03816b7404feColin Cross    } },
205c2c6ecd1195481f5813a721a7d20a73c0795c135Aaron Schulman    { "regulators",  "Voltage and Current Regulators", 0, {
2062cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/regulator/enable" },
207c2c6ecd1195481f5813a721a7d20a73c0795c135Aaron Schulman    } },
208ae473363270724550699a7fd9c110a839f79964cScott Bauer    { "binder_driver", "Binder Kernel driver", 0, {
2092cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_transaction/enable" },
2102cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/binder/binder_transaction_received/enable" },
2117f3d7a2234d7fedc1333152a0567dec74d82ee9cMartijn Coenen        { OPT,      "events/binder/binder_set_priority/enable" },
212ae473363270724550699a7fd9c110a839f79964cScott Bauer    } },
213ae473363270724550699a7fd9c110a839f79964cScott Bauer    { "binder_lock", "Binder global lock trace", 0, {
214eb8acbf4af7f1ad7ae94337dc3e0d6a38eab4178Howard Chen        { OPT,      "events/binder/binder_lock/enable" },
215eb8acbf4af7f1ad7ae94337dc3e0d6a38eab4178Howard Chen        { OPT,      "events/binder/binder_locked/enable" },
216eb8acbf4af7f1ad7ae94337dc3e0d6a38eab4178Howard Chen        { OPT,      "events/binder/binder_unlock/enable" },
217ae473363270724550699a7fd9c110a839f79964cScott Bauer    } },
2187048161951761cd5fe0109c34204ba8229f9eddfMartijn Coenen    { "pagecache",  "Page cache", 0, {
2192cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        { REQ,      "events/filemap/enable" },
2207048161951761cd5fe0109c34204ba8229f9eddfMartijn Coenen    } },
2216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis};
2226eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
223fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Command line options */
224fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic int g_traceDurationSeconds = 5;
225fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceOverwrite = false;
226cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic int g_traceBufferSizeKB = 2048;
2277b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennisstatic bool g_compress = false;
22831be80f02cddda55e75614884038fa4645b694cdGlenn Kastenstatic bool g_nohup = false;
22931be80f02cddda55e75614884038fa4645b694cdGlenn Kastenstatic int g_initialSleepSecs = 0;
23046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsudastatic const char* g_categoriesFile = NULL;
231e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* g_kernelTraceFuncs = NULL;
232f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennisstatic const char* g_debugAppCmdLine = "";
23340b26b4fc597f105823bc1e2a640e4df8baea243John Reckstatic const char* g_outputFile = nullptr;
234fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
235fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Global state */
236a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabakastatic bool g_tracePdx = false;
237fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceAborted = false;
2385fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughesstatic bool g_categoryEnables[arraysize(k_categories)] = {};
2392cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrencestatic std::string g_traceFolder;
240fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
241fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Sys file paths */
242fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceClockPath =
2432cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace_clock";
244fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
245cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_traceBufferSizePath =
2462cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "buffer_size_kb";
247cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
248734e378a7387b2d51f40f4e4cba8887703bd1839Chih-Hung Hsieh#if 0
249734e378a7387b2d51f40f4e4cba8887703bd1839Chih-Hung Hsieh// TODO: Re-enable after stabilization
250ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandesstatic const char* k_traceCmdlineSizePath =
251ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandes    "saved_cmdlines_size";
252734e378a7387b2d51f40f4e4cba8887703bd1839Chih-Hung Hsieh#endif
253ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandes
254fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOverwriteEnablePath =
2552cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/overwrite";
256fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
257e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_currentTracerPath =
2582cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "current_tracer";
259e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
260e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_printTgidPath =
2612cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/print-tgid";
262e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
263e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphAbsTimePath =
2642cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-abstime";
265e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
266e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphCpuPath =
2672cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-cpu";
268e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
269e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphProcPath =
2702cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-proc";
271e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
272e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_funcgraphFlatPath =
2732cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "options/funcgraph-flat";
274e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
275e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic const char* k_ftraceFilterPath =
2762cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "set_ftrace_filter";
277e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
278fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOnPath =
2792cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "tracing_on";
280fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
281fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracePath =
2822cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace";
283fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
284d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenenstatic const char* k_traceStreamPath =
2852cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace_pipe";
286d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen
287469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reckstatic const char* k_traceMarkerPath =
2882cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    "trace_marker";
289469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck
290e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis// Check whether a file exists.
291e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennisstatic bool fileExists(const char* filename) {
2922cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    return access((g_traceFolder + filename).c_str(), F_OK) != -1;
293e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis}
294e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis
2956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether a file is writable.
2966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool fileIsWritable(const char* filename) {
2972cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    return access((g_traceFolder + filename).c_str(), W_OK) != -1;
2986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
2996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
300e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Truncate a file.
301e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool truncateFile(const char* path)
302fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
30343122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    // This uses creat rather than truncate because some of the debug kernel
30443122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
30543122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    // calls to truncate, but they are cleared by calls to creat.
3062cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int traceFD = creat((g_traceFolder + path).c_str(), 0);
30743122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    if (traceFD == -1) {
3082cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "error truncating %s: %s (%d)\n", (g_traceFolder + path).c_str(),
30943122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis            strerror(errno), errno);
310e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        return false;
311e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
312e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
31343122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis    close(traceFD);
31443122e7e672eb170334a4467dd41cf4bd545bae5Jamie Gennis
315e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return true;
316e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
317e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
318e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool _writeStr(const char* filename, const char* str, int flags)
319e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
3202cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    std::string fullFilename = g_traceFolder + filename;
3212cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int fd = open(fullFilename.c_str(), flags);
322fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (fd == -1) {
3232cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "error opening %s: %s (%d)\n", fullFilename.c_str(),
324fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                strerror(errno), errno);
325fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        return false;
326fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
327fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
328fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    bool ok = true;
329fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    ssize_t len = strlen(str);
330fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (write(fd, str, len) != len) {
3312cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "error writing to %s: %s (%d)\n", fullFilename.c_str(),
332fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                strerror(errno), errno);
333fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        ok = false;
334fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
335fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
336fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    close(fd);
337fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
338fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return ok;
339fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
340fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
341e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Write a string to a file, returning true if the write was successful.
342e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool writeStr(const char* filename, const char* str)
343e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
344e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return _writeStr(filename, str, O_WRONLY);
345e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
346e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
347e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Append a string to a file, returning true if the write was successful.
348e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool appendStr(const char* filename, const char* str)
349e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
350e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return _writeStr(filename, str, O_APPEND|O_WRONLY);
351e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
352e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
353469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reckstatic void writeClockSyncMarker()
354469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck{
355469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck  char buffer[128];
3560bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  int len = 0;
3572cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence  int fd = open((g_traceFolder + k_traceMarkerPath).c_str(), O_WRONLY);
3580bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  if (fd == -1) {
3590bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
3600bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen              strerror(errno), errno);
3610bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      return;
3620bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  }
363469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck  float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
3640bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen
3650bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
3660bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  if (write(fd, buffer, len) != len) {
3670bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
3680bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  }
3690bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen
3700bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
3710bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
3720bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  if (write(fd, buffer, len) != len) {
3730bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen      fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
3740bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  }
3750bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen
3760bcd97a7485d971c5276e19b1a6c2672539dc38dMartijn Coenen  close(fd);
377469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck}
378469a194051f1657b3f77ff2f5d84a60f7521fabaJohn Reck
3796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
3806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// file.
381fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable)
382fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
383fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return writeStr(filename, enable ? "1" : "0");
384fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
385fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
3866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether the category is supported on the device with the current
3876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// rootness.  A category is supported only if all its required /sys/ files are
3886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// writable and if enabling the category will enable one or more tracing tags
3896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// or /sys/ files.
3906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool isCategorySupported(const TracingCategory& category)
3913169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis{
392db40415e05e39c1f4faa62735f435b031e53af7csergeyv    if (strcmp(category.name, k_coreServiceCategory) == 0) {
3935fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes        return !android::base::GetProperty(k_coreServicesProp, "").empty();
394db40415e05e39c1f4faa62735f435b031e53af7csergeyv    }
395db40415e05e39c1f4faa62735f435b031e53af7csergeyv
396a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka    if (strcmp(category.name, k_pdxServiceCategory) == 0) {
397a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka        return true;
398a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka    }
399a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka
4006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    bool ok = category.tags != 0;
4016eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < MAX_SYS_FILES; i++) {
4026eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const char* path = category.sysfiles[i].path;
4036eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        bool req = category.sysfiles[i].required == REQ;
4046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (path != NULL) {
4056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (req) {
4066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (!fileIsWritable(path)) {
4076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    return false;
4086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                } else {
4096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    ok = true;
4106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
4116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            } else {
412eb8acbf4af7f1ad7ae94337dc3e0d6a38eab4178Howard Chen                ok = true;
4136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
4146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
415e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis    }
416e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis    return ok;
417cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis}
418cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
4196eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether the category would be supported on the device if the user
4206eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// were root.  This function assumes that root is able to write to any file
4216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// that exists.  It performs the same logic as isCategorySupported, but it
422b5c95475996c59bacb0ee760f11bf792f71e0c77Fabien Sanglard// uses file existence rather than writability in the /sys/ file checks.
4236eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool isCategorySupportedForRoot(const TracingCategory& category)
4249ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling{
4256eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    bool ok = category.tags != 0;
4266eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (int i = 0; i < MAX_SYS_FILES; i++) {
4276eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const char* path = category.sysfiles[i].path;
4286eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        bool req = category.sysfiles[i].required == REQ;
4296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (path != NULL) {
4306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (req) {
4316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (!fileExists(path)) {
4326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    return false;
4336eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                } else {
4346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    ok = true;
4356eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
4366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            } else {
4376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                ok |= fileExists(path);
4386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
4396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
4409ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling    }
4419ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling    return ok;
4429ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling}
4439ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling
4446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Enable or disable overwriting of the kernel trace buffers.  Disabling this
4456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// will cause tracing to stop once the trace buffers have filled up.
4466eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setTraceOverwriteEnable(bool enable)
447ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown{
4486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
449ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown}
450ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown
45165ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson// Set the user initiated trace property
45265ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jacksonstatic bool setUserInitiatedTraceProperty(bool enable)
45365ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson{
45465ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson    if (!android::base::SetProperty(k_userInitiatedTraceProperty, enable ? "1" : "")) {
45565ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson        fprintf(stderr, "error setting user initiated strace system property\n");
45665ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson        return false;
45765ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson    }
45865ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson    return true;
45965ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson}
46065ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson
461fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable kernel tracing.
462fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTracingEnabled(bool enable)
463fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
464fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return setKernelOptionEnable(k_tracingOnPath, enable);
465fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
466fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
467fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Clear the contents of the kernel trace.
468fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool clearTrace()
469fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
470e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return truncateFile(k_tracePath);
471fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
472fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
473cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Set the size of the kernel's trace buffer in kilobytes.
474cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setTraceBufferSizeKB(int size)
475cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{
476cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    char str[32] = "1";
477cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    if (size < 1) {
478cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis        size = 1;
479cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    }
480cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    snprintf(str, 32, "%d", size);
481cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    return writeStr(k_traceBufferSizePath, str);
482cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis}
483cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
484734e378a7387b2d51f40f4e4cba8887703bd1839Chih-Hung Hsieh#if 0
485734e378a7387b2d51f40f4e4cba8887703bd1839Chih-Hung Hsieh// TODO: Re-enable after stabilization
486ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandes// Set the default size of cmdline hashtable
487ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandesstatic bool setCmdlineSize()
488ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandes{
489ce964f2e6088761f3e2b22535010872327eff264Joel Fernandes    if (fileExists(k_traceCmdlineSizePath)) {
490ce964f2e6088761f3e2b22535010872327eff264Joel Fernandes        return writeStr(k_traceCmdlineSizePath, "8192");
491ce964f2e6088761f3e2b22535010872327eff264Joel Fernandes    }
492ce964f2e6088761f3e2b22535010872327eff264Joel Fernandes    return true;
493ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandes}
494734e378a7387b2d51f40f4e4cba8887703bd1839Chih-Hung Hsieh#endif
495ed80bd04cc3bf80082b1d733ef06d90a29c6270aJoel Fernandes
496ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson// Set the clock to the best available option while tracing. Use 'boot' if it's
497ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson// available; otherwise, use 'mono'. If neither are available use 'global'.
498b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross// Any write to the trace_clock sysfs file will reset the buffer, so only
499b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross// update it if the requested value is not the current value.
500ea826794184be368f65f099ceac4fc31234700f6Carmen Jacksonstatic bool setClock()
501fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
502ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
503ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
504ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        std::istreambuf_iterator<char>());
505ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson
506ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    std::string newClock;
507ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    if (clockStr.find("boot") != std::string::npos) {
508ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        newClock = "boot";
509ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    } else if (clockStr.find("mono") != std::string::npos) {
510ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        newClock = "mono";
511ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    } else {
512ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson        newClock = "global";
513ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    }
514b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross
515cb057c2e6bf23b43df49282c0db26b663e4535f7Chih-Hung Hsieh    size_t begin = clockStr.find('[') + 1;
516cb057c2e6bf23b43df49282c0db26b663e4535f7Chih-Hung Hsieh    size_t end = clockStr.find(']');
517ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
518b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross        return true;
519b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749Colin Cross    }
520ea826794184be368f65f099ceac4fc31234700f6Carmen Jackson    return writeStr(k_traceClockPath, newClock.c_str());
521fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
522fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
523e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool setPrintTgidEnableIfPresent(bool enable)
524e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
525e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    if (fileExists(k_printTgidPath)) {
526e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        return setKernelOptionEnable(k_printTgidPath, enable);
527e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
528e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return true;
529e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
530e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
5316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Poke all the binder-enabled processes in the system to get them to re-read
5326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// their system properties.
5336eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool pokeBinderServices()
5346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
5356eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    sp<IServiceManager> sm = defaultServiceManager();
5366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    Vector<String16> services = sm->listServices();
5376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    for (size_t i = 0; i < services.size(); i++) {
5386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        sp<IBinder> obj = sm->checkService(services[i]);
5396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (obj != NULL) {
5406eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            Parcel data;
5416eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
5426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    NULL, 0) != OK) {
5436eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (false) {
5446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    // XXX: For some reason this fails on tablets trying to
5456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    // poke the "phone" service.  It's not clear whether some
5466eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    // are expected to fail.
5476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    String8 svc(services[i]);
5486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    fprintf(stderr, "error poking binder service %s\n",
5496eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        svc.string());
5506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    return false;
5516eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
5526eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
5536eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
5546eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
5556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    return true;
5566eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
5576eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
558ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen// Poke all the HAL processes in the system to get them to re-read
559ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen// their system properties.
560ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenenstatic void pokeHalServices()
561ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen{
562f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen    using ::android::hidl::base::V1_0::IBase;
563ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    using ::android::hidl::manager::V1_0::IServiceManager;
564ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    using ::android::hardware::hidl_string;
565f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen    using ::android::hardware::Return;
566ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen
567ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
568a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland
569a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland    if (sm == nullptr) {
570a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland        fprintf(stderr, "failed to get IServiceManager to poke hal services\n");
571a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland        return;
572a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland    }
573a42866b4cb9218cc80b8217ff9ad6458c3c4864eSteven Moreland
5748cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong    auto listRet = sm->list([&](const auto &interfaces) {
575ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen        for (size_t i = 0; i < interfaces.size(); i++) {
576ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            string fqInstanceName = interfaces[i];
577cb057c2e6bf23b43df49282c0db26b663e4535f7Chih-Hung Hsieh            string::size_type n = fqInstanceName.find('/');
578ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            if (n == std::string::npos || interfaces[i].size() == n+1)
579ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen                continue;
580ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            hidl_string fqInterfaceName = fqInstanceName.substr(0, n);
581ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen            hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
582f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName);
583f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            if (!interfaceRet.isOk()) {
5841e4a7fbdd392cb5af35bca169d90b35850a9e9f4Martijn Coenen                // ignore
585f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen                continue;
586f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            }
5877320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson
588f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            sp<IBase> interface = interfaceRet;
5897320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson            if (interface == nullptr) {
5907320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson                // ignore
5917320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson                continue;
5927320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson            }
5937320612aeb8674a63106299f2cba5d23df1ca03bCarmen Jackson
594f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            auto notifyRet = interface->notifySyspropsChanged();
595f6ac84820198b66b687738cb5ec32b19e74fef2aMartijn Coenen            if (!notifyRet.isOk()) {
5961e4a7fbdd392cb5af35bca169d90b35850a9e9f4Martijn Coenen                // ignore
5978cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong            }
598ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen        }
599ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    });
6008cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong    if (!listRet.isOk()) {
60164d54eb0465c7c372ea1b57a9fa4984be0cd79f8Martijn Coenen        // TODO(b/34242478) fix this when we determine the correct ACL
60264d54eb0465c7c372ea1b57a9fa4984be0cd79f8Martijn Coenen        //fprintf(stderr, "failed to list services: %s\n", listRet.description().c_str());
6038cf4ed19624a7ca1dd2d8d5b0dee15ca2bcdba04Yifan Hong    }
604ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen}
605ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen
6066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Set the trace tags that userland tracing uses, and poke the running
6076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// processes to pick up the new value.
6086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setTagsProperty(uint64_t tags)
6096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
6105fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    std::string value = android::base::StringPrintf("%#" PRIx64, tags);
6115fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    if (!android::base::SetProperty(k_traceTagsProperty, value)) {
6126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        fprintf(stderr, "error setting trace tags system property\n");
6136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        return false;
6146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
615f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    return true;
616f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis}
617f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis
6184144eff1e261f6462be3753fc9543d82f9a4fd96sergeyvstatic void clearAppProperties()
6194144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv{
6205fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
6214144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        fprintf(stderr, "failed to clear system property: %s",
6224144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv              k_traceAppsNumberProperty);
6234144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    }
6244144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv}
6254144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv
626f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis// Set the system property that indicates which apps should perform
627f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis// application-level tracing.
62809a7987fb59ed6843d51acf0161d66ed3eb2252fDan Austinstatic bool setAppCmdlineProperty(char* cmdline)
629f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis{
6304144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    int i = 0;
63109a7987fb59ed6843d51acf0161d66ed3eb2252fDan Austin    char* start = cmdline;
6324144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    while (start != NULL) {
6334144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        char* end = strchr(start, ',');
6344144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        if (end != NULL) {
6354144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            *end = '\0';
6364144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            end++;
6374144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        }
6385fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes        std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
6395fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes        if (!android::base::SetProperty(key, start)) {
6405fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes            fprintf(stderr, "error setting trace app %d property to %s\n", i, key.c_str());
6414144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            clearAppProperties();
6424144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv            return false;
6434144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        }
6444144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        start = end;
6454144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        i++;
6464144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv    }
6474144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv
6485fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    std::string value = android::base::StringPrintf("%d", i);
6495fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    if (!android::base::SetProperty(k_traceAppsNumberProperty, value)) {
6505fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes        fprintf(stderr, "error setting trace app number property to %s\n", value.c_str());
6514144eff1e261f6462be3753fc9543d82f9a4fd96sergeyv        clearAppProperties();
652f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis        return false;
653f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    }
654f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    return true;
6556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
6566eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
6576eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Disable all /sys/ enable files.
6586eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool disableKernelTraceEvents() {
6596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    bool ok = true;
6605fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    for (size_t i = 0; i < arraysize(k_categories); i++) {
6616eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const TracingCategory &c = k_categories[i];
6626eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        for (int j = 0; j < MAX_SYS_FILES; j++) {
6636eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            const char* path = c.sysfiles[j].path;
6646eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            if (path != NULL && fileIsWritable(path)) {
6656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                ok &= setKernelOptionEnable(path, false);
6666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
6676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
6686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
6696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    return ok;
6706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
6716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
672e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Verify that the comma separated list of functions are being traced by the
673e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// kernel.
674e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool verifyKernelTraceFuncs(const char* funcs)
675e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
676d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini    std::string buf;
6772cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (!android::base::ReadFileToString(g_traceFolder + k_ftraceFilterPath, &buf)) {
678d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini         fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
679e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            strerror(errno), errno);
680d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini         return false;
681e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
682e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
683d8419c29e3a32cf9eebed8ef7f34e27fa756b17eStephane Gasparini    String8 funcList = String8::format("\n%s",buf.c_str());
684e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
685e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    // Make sure that every function listed in funcs is in the list we just
686a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot    // read from the kernel, except for wildcard inputs.
687e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    bool ok = true;
688e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    char* myFuncs = strdup(funcs);
689e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    char* func = strtok(myFuncs, ",");
690e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    while (func) {
691a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot        if (!strchr(func, '*')) {
692a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            String8 fancyFunc = String8::format("\n%s\n", func);
693a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            bool found = funcList.find(fancyFunc.string(), 0) >= 0;
694a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            if (!found || func[0] == '\0') {
695a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot                fprintf(stderr, "error: \"%s\" is not a valid kernel function "
696a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot                        "to trace.\n", func);
697a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot                ok = false;
698a2c228770ea1cadc1d06406baad899b8c500389aThomas Buhot            }
699e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
700e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        func = strtok(NULL, ",");
701e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
702e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    free(myFuncs);
703e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return ok;
704e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
705e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
706e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Set the comma separated list of functions that the kernel is to trace.
707e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool setKernelTraceFuncs(const char* funcs)
708e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
709e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    bool ok = true;
710e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
711e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    if (funcs == NULL || funcs[0] == '\0') {
712e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Disable kernel function tracing.
7136f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis        if (fileIsWritable(k_currentTracerPath)) {
7146f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            ok &= writeStr(k_currentTracerPath, "nop");
7156f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis        }
7166f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis        if (fileIsWritable(k_ftraceFilterPath)) {
717e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            ok &= truncateFile(k_ftraceFilterPath);
718e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
719e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    } else {
720e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Enable kernel function tracing.
721e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= writeStr(k_currentTracerPath, "function_graph");
722e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
723e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
724e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
725e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
726e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
727e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Set the requested filter functions.
728e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        ok &= truncateFile(k_ftraceFilterPath);
729e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        char* myFuncs = strdup(funcs);
730e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        char* func = strtok(myFuncs, ",");
731e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        while (func) {
732e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            ok &= appendStr(k_ftraceFilterPath, func);
733e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            func = strtok(NULL, ",");
734e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
735e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        free(myFuncs);
736e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
737e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        // Verify that the set functions are being traced.
738e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        if (ok) {
739e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            ok &= verifyKernelTraceFuncs(funcs);
740e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis        }
741e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    }
742e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
743e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return ok;
744e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
745e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
74646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsudastatic bool setCategoryEnable(const char* name, bool enable)
74746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda{
7485fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    for (size_t i = 0; i < arraysize(k_categories); i++) {
74946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        const TracingCategory& c = k_categories[i];
75046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        if (strcmp(name, c.name) == 0) {
75146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            if (isCategorySupported(c)) {
75246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                g_categoryEnables[i] = enable;
75346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                return true;
75446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            } else {
75546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                if (isCategorySupportedForRoot(c)) {
75646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    fprintf(stderr, "error: category \"%s\" requires root "
75746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                            "privileges.\n", name);
75846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                } else {
75946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    fprintf(stderr, "error: category \"%s\" is not supported "
76046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                            "on this device.\n", name);
76146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                }
76246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                return false;
76346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            }
76446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        }
76546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
76646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
76746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    return false;
76846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda}
76946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda
77046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsudastatic bool setCategoriesEnableFromFile(const char* categories_file)
77146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda{
77246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    if (!categories_file) {
77346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        return true;
77446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
77546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    Tokenizer* tokenizer = NULL;
77646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
77746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        return false;
77846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
77946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    bool ok = true;
78046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    while (!tokenizer->isEol()) {
78146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        String8 token = tokenizer->nextToken(" ");
78246c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        if (token.isEmpty()) {
78346c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            tokenizer->skipDelimiters(" ");
78446c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            continue;
78546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        }
78646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda        ok &= setCategoryEnable(token.string(), true);
78746c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    }
78846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    delete tokenizer;
78946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda    return ok;
79046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda}
79146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda
792550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearmanstatic bool setUpUserspaceTracing()
793fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
794fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    bool ok = true;
795fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
7966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Set up the tags property.
7976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    uint64_t tags = 0;
7985fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    for (size_t i = 0; i < arraysize(k_categories); i++) {
7996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (g_categoryEnables[i]) {
8006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            const TracingCategory &c = k_categories[i];
8016eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            tags |= c.tags;
8026eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
8036eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
8046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    ok &= setTagsProperty(tags);
805db40415e05e39c1f4faa62735f435b031e53af7csergeyv
806db40415e05e39c1f4faa62735f435b031e53af7csergeyv    bool coreServicesTagEnabled = false;
8075fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    for (size_t i = 0; i < arraysize(k_categories); i++) {
808db40415e05e39c1f4faa62735f435b031e53af7csergeyv        if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
809db40415e05e39c1f4faa62735f435b031e53af7csergeyv            coreServicesTagEnabled = g_categoryEnables[i];
810db40415e05e39c1f4faa62735f435b031e53af7csergeyv        }
811a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka
812a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka        // Set whether to poke PDX services in this session.
813a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka        if (strcmp(k_categories[i].name, k_pdxServiceCategory) == 0) {
814a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka            g_tracePdx = g_categoryEnables[i];
815a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka        }
816db40415e05e39c1f4faa62735f435b031e53af7csergeyv    }
817db40415e05e39c1f4faa62735f435b031e53af7csergeyv
818db40415e05e39c1f4faa62735f435b031e53af7csergeyv    std::string packageList(g_debugAppCmdLine);
819db40415e05e39c1f4faa62735f435b031e53af7csergeyv    if (coreServicesTagEnabled) {
820db40415e05e39c1f4faa62735f435b031e53af7csergeyv        if (!packageList.empty()) {
821db40415e05e39c1f4faa62735f435b031e53af7csergeyv            packageList += ",";
822db40415e05e39c1f4faa62735f435b031e53af7csergeyv        }
8235fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes        packageList += android::base::GetProperty(k_coreServicesProp, "");
824db40415e05e39c1f4faa62735f435b031e53af7csergeyv    }
82509a7987fb59ed6843d51acf0161d66ed3eb2252fDan Austin    ok &= setAppCmdlineProperty(&packageList[0]);
826f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis    ok &= pokeBinderServices();
827ee9b97e85d153309cd6d076c54eefef991ac846dMartijn Coenen    pokeHalServices();
8286eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
829a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka    if (g_tracePdx) {
830a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka        ok &= ServiceUtility::PokeServices();
831a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka    }
832a6c0a721bd442f15d70a50815ef78a6c8ac6b1c9Corey Tabaka
833550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    return ok;
834550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman}
835550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
836550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearmanstatic void cleanUpUserspaceTracing()
837550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman{
838550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    setTagsProperty(0);
839550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    clearAppProperties();
840550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    pokeBinderServices();
841550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
842550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    if (g_tracePdx) {
843550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        ServiceUtility::PokeServices();
844550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    }
845550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman}
846550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
847550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
848550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman// Set all the kernel tracing settings to the desired state for this trace
849550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman// capture.
850550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearmanstatic bool setUpKernelTracing()
851550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman{
852550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    bool ok = true;
853550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
85465ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson    ok &= setUserInitiatedTraceProperty(true);
85565ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson
856550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    // Set up the tracing options.
857550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    ok &= setCategoriesEnableFromFile(g_categoriesFile);
858550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    ok &= setTraceOverwriteEnable(g_traceOverwrite);
859550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
860550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    // TODO: Re-enable after stabilization
861550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    //ok &= setCmdlineSize();
862550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    ok &= setClock();
863550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    ok &= setPrintTgidEnableIfPresent(true);
864550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
865550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
8666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Disable all the sysfs enables.  This is done as a separate loop from
8676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // the enables to allow the same enable to exist in multiple categories.
8686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    ok &= disableKernelTraceEvents();
8696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
8706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Enable all the sysfs enables that are in an enabled category.
8715fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    for (size_t i = 0; i < arraysize(k_categories); i++) {
8726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (g_categoryEnables[i]) {
8736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            const TracingCategory &c = k_categories[i];
8746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            for (int j = 0; j < MAX_SYS_FILES; j++) {
8756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                const char* path = c.sysfiles[j].path;
8766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                bool required = c.sysfiles[j].required == REQ;
8776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (path != NULL) {
8786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    if (fileIsWritable(path)) {
8796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        ok &= setKernelOptionEnable(path, true);
8806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    } else if (required) {
8816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        fprintf(stderr, "error writing file %s\n", path);
8826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                        ok = false;
8836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    }
8846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
8856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
8866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
8874b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis    }
8884b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis
889fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return ok;
890fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
891fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
892e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Reset all the kernel tracing settings to their default state.
893550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearmanstatic void cleanUpKernelTracing()
894fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
8956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    // Disable all tracing that we're able to.
8966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    disableKernelTraceEvents();
8976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
898fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    // Set the options back to their defaults.
899fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    setTraceOverwriteEnable(true);
900e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setTraceBufferSizeKB(1);
901e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setPrintTgidEnableIfPresent(false);
902e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setKernelTraceFuncs(NULL);
90365ecfbba620e4710331b26db4ebf087ca6d92a2bCarmen Jackson    setUserInitiatedTraceProperty(false);
904e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
905e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
906e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Enable tracing in the kernel.
907e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic bool startTrace()
908e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
909e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    return setTracingEnabled(true);
910e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis}
911cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
912e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis// Disable tracing in the kernel.
913e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennisstatic void stopTrace()
914e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis{
915e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    setTracingEnabled(false);
916fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
917fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
918d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen// Read data from the tracing pipe and forward to stdout
919d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenenstatic void streamTrace()
920d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen{
921d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    char trace_data[4096];
9222cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int traceFD = open((g_traceFolder + k_traceStreamPath).c_str(), O_RDWR);
923d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    if (traceFD == -1) {
924d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
925d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                strerror(errno), errno);
926d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        return;
927d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    }
928d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    while (!g_traceAborted) {
929d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        ssize_t bytes_read = read(traceFD, trace_data, 4096);
930d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (bytes_read > 0) {
931d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            write(STDOUT_FILENO, trace_data, bytes_read);
932d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            fflush(stdout);
933d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        } else {
934d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            if (!g_traceAborted) {
935d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
936d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                        bytes_read, errno, strerror(errno));
937d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            }
938d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            break;
939d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        }
940d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    }
941d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen}
942d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen
943fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Read the current kernel trace and write it to stdout.
94440b26b4fc597f105823bc1e2a640e4df8baea243John Reckstatic void dumpTrace(int outFd)
945fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
9466c8ac921ead0771b36281763d3724d67c9146c62John Reck    ALOGI("Dumping trace");
9472cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    int traceFD = open((g_traceFolder + k_tracePath).c_str(), O_RDWR);
948fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (traceFD == -1) {
949fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
950fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                strerror(errno), errno);
951fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        return;
952fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
953fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
9547b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis    if (g_compress) {
9557b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        z_stream zs;
9563da5d235dab9469ccec567c4ebbb5206f4558a18Elliott Hughes        memset(&zs, 0, sizeof(zs));
957a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes
958a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
9597b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (result != Z_OK) {
9607b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error initializing zlib: %d\n", result);
9617b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            close(traceFD);
9627b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            return;
9637b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
9647b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
965a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        constexpr size_t bufSize = 64*1024;
966a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
967a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
968a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        if (!in || !out) {
969a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes            fprintf(stderr, "couldn't allocate buffers\n");
970a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes            close(traceFD);
971a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes            return;
972a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        }
973a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes
974a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        int flush = Z_NO_FLUSH;
9757b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
976a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes        zs.next_out = reinterpret_cast<Bytef*>(out.get());
9777b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        zs.avail_out = bufSize;
9787b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9797b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        do {
9807b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9817b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            if (zs.avail_in == 0) {
9827b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                // More input is needed.
983a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes                result = read(traceFD, in.get(), bufSize);
9847b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                if (result < 0) {
9857b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    fprintf(stderr, "error reading trace: %s (%d)\n",
9867b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                            strerror(errno), errno);
9877b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    result = Z_STREAM_END;
9887b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    break;
9897b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                } else if (result == 0) {
9907b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    flush = Z_FINISH;
9917b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                } else {
992a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes                    zs.next_in = reinterpret_cast<Bytef*>(in.get());
9937b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    zs.avail_in = result;
9947b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                }
9957b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            }
9967b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
9977b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            if (zs.avail_out == 0) {
9987b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                // Need to write the output.
999b59e2961471db9ede954a3d843e0bb545bb290faElliott Hughes                result = write(outFd, out.get(), bufSize);
10007b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                if ((size_t)result < bufSize) {
10017b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    fprintf(stderr, "error writing deflated trace: %s (%d)\n",
10027b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                            strerror(errno), errno);
10037b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    result = Z_STREAM_END; // skip deflate error message
10047b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    zs.avail_out = bufSize; // skip the final write
10057b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                    break;
10067b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                }
1007a252f4db5df0a3802b471680bb32f2cbbd21c548Elliott Hughes                zs.next_out = reinterpret_cast<Bytef*>(out.get());
10087b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                zs.avail_out = bufSize;
10097b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            }
10107b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
10117b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        } while ((result = deflate(&zs, flush)) == Z_OK);
10127b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
10137b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (result != Z_STREAM_END) {
10147b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error deflating trace: %s\n", zs.msg);
10157b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
10167b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
10177b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (zs.avail_out < bufSize) {
10187b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            size_t bytes = bufSize - zs.avail_out;
1019b59e2961471db9ede954a3d843e0bb545bb290faElliott Hughes            result = write(outFd, out.get(), bytes);
10207b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            if ((size_t)result < bytes) {
10217b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                fprintf(stderr, "error writing deflated trace: %s (%d)\n",
10227b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                        strerror(errno), errno);
10237b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            }
10247b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
10257b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
10267b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        result = deflateEnd(&zs);
10277b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        if (result != Z_OK) {
10287b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            fprintf(stderr, "error cleaning up zlib: %d\n", result);
10297b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
10307b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis    } else {
1031d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao        char buf[4096];
1032d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao        ssize_t rc;
1033d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao        while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
1034d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao            if (!android::base::WriteFully(outFd, buf, rc)) {
1035d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao                fprintf(stderr, "error writing trace: %s\n", strerror(errno));
1036d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao                break;
1037d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao            }
1038d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao        }
1039d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao        if (rc == -1) {
1040d3d36e71f274a1f6df1eb77db5a6abfb12035c75Josh Gao            fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
10417b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis        }
1042fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1043fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1044fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    close(traceFD);
1045fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
1046fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
104792dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzynstatic void handleSignal(int /*signo*/)
1048fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
104931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    if (!g_nohup) {
105031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten        g_traceAborted = true;
105131be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    }
1052fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
1053fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
10546eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void registerSigHandler()
10556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
1056fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    struct sigaction sa;
1057fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigemptyset(&sa.sa_mask);
1058fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sa.sa_flags = 0;
1059fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sa.sa_handler = handleSignal;
1060fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGHUP, &sa, NULL);
1061fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGINT, &sa, NULL);
1062fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGQUIT, &sa, NULL);
1063fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    sigaction(SIGTERM, &sa, NULL);
1064fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
1065fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
10666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void listSupportedCategories()
10676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
10685fd6ff6b7670cce9ed17e06764db59d44ba15575Elliott Hughes    for (size_t i = 0; i < arraysize(k_categories); i++) {
10696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        const TracingCategory& c = k_categories[i];
10706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        if (isCategorySupported(c)) {
10716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            printf("  %10s - %s\n", c.name, c.longname);
10726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        }
10736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    }
10746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
10756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
10766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Print the command usage help to stderr.
10776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void showHelp(const char *cmd)
10786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{
10796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
10806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis    fprintf(stderr, "options include:\n"
1081f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis                    "  -a appname      enable app-level tracing for a comma "
1082519a0790d7039ee9ed52ae057de30db0fddaee59Daniel Colascione                        "separated list of cmdlines; * is a wildcard matching any process\n"
10836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -b N            use a trace buffer size of N KB\n"
10846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -c              trace into a circular buffer\n"
108546c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    "  -f filename     use the categories written in a file as space-separated\n"
108646c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                    "                    values in a line\n"
1087e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis                    "  -k fname,...    trace the listed kernel functions\n"
10886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -n              ignore signals\n"
10896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -s N            sleep for N seconds before tracing [default 0]\n"
1090b5c95475996c59bacb0ee760f11bf792f71e0c77Fabien Sanglard                    "  -t N            trace for N seconds [default 5]\n"
10916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  -z              compress the trace dump\n"
1092b5c95475996c59bacb0ee760f11bf792f71e0c77Fabien Sanglard                    "  --async_start   start circular trace and return immediately\n"
10936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  --async_dump    dump the current contents of circular trace buffer\n"
10946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "  --async_stop    stop tracing and dump the current contents of circular\n"
10956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    "                    trace buffer\n"
1096d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "  --stream        stream trace to stdout as it enters the trace buffer\n"
1097d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "                    Note: this can take significant CPU time, and is best\n"
1098d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "                    used for measuring things that are not affected by\n"
1099d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    "                    CPU performance, like pagecache usage.\n"
110092573f1ba0d5360d7bfa8ab8935118db7a251f62Jamie Gennis                    "  --list_categories\n"
110192573f1ba0d5360d7bfa8ab8935118db7a251f62Jamie Gennis                    "                  list the available tracing categories\n"
110240b26b4fc597f105823bc1e2a640e4df8baea243John Reck                    " -o filename      write the trace to the specified file instead\n"
110340b26b4fc597f105823bc1e2a640e4df8baea243John Reck                    "                    of stdout.\n"
11046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            );
11056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}
11066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis
11072cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrencebool findTraceFiles()
11082cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence{
11092cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    static const std::string debugfs_path = "/sys/kernel/debug/tracing/";
11102cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    static const std::string tracefs_path = "/sys/kernel/tracing/";
11112cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    static const std::string trace_file = "trace_marker";
11122cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
11132cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    bool tracefs = access((tracefs_path + trace_file).c_str(), F_OK) != -1;
11142cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    bool debugfs = access((debugfs_path + trace_file).c_str(), F_OK) != -1;
11152cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
11162cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (!tracefs && !debugfs) {
11172cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "Error: Did not find trace folder\n");
11182cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        return false;
11192cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    }
11202cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
11212cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (tracefs) {
11222cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        g_traceFolder = tracefs_path;
11232cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    } else {
11242cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        g_traceFolder = debugfs_path;
11252cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    }
11262cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
11272cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    return true;
11282cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence}
11292cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
1130fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisint main(int argc, char **argv)
1131fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{
11324edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool async = false;
11334edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool traceStart = true;
11344edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool traceStop = true;
11354edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    bool traceDump = true;
1136d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen    bool traceStream = false;
1137550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    bool onlyUserspace = false;
11384b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis
1139fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
1140fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        showHelp(argv[0]);
1141fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        exit(0);
1142fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1143fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
11442cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    if (!findTraceFiles()) {
11452cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        fprintf(stderr, "No trace folder found\n");
11462cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence        exit(-1);
11472cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence    }
11482cd93cc4ce68da81815351db75cbda4b357e6753Paul Lawrence
1149fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    for (;;) {
1150fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        int ret;
11514edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling        int option_index = 0;
11524edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling        static struct option long_options[] = {
1153550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {"async_start",       no_argument, 0,  0 },
1154550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {"async_stop",        no_argument, 0,  0 },
1155550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {"async_dump",        no_argument, 0,  0 },
1156550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {"only_userspace",    no_argument, 0,  0 },
1157550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {"list_categories",   no_argument, 0,  0 },
1158550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {"stream",            no_argument, 0,  0 },
1159550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            {           0,                  0, 0,  0 }
11604edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling        };
1161fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
116240b26b4fc597f105823bc1e2a640e4df8baea243John Reck        ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
11634edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                          long_options, &option_index);
1164fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1165fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        if (ret < 0) {
11666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            for (int i = optind; i < argc; i++) {
11676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                if (!setCategoryEnable(argv[i], true)) {
11686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
11696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    exit(1);
11706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                }
11716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis            }
1172fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1173fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1174fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1175fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        switch(ret) {
1176f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis            case 'a':
1177f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis                g_debugAppCmdLine = optarg;
1178f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis            break;
1179f7f29c8f9d56dc908e501ae789e418a9974b6bceJamie Gennis
1180cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis            case 'b':
1181cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis                g_traceBufferSizeKB = atoi(optarg);
1182cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis            break;
1183cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
1184fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            case 'c':
1185fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                g_traceOverwrite = true;
1186fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1187fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
118846c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            case 'f':
118946c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda                g_categoriesFile = optarg;
119046c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda            break;
119146c51fb1adf8bc011b7d5b1c98a89303acb8c57bYasuhiro Matsuda
1192e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis            case 'k':
1193e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis                g_kernelTraceFuncs = optarg;
11946f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            break;
1195e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis
119631be80f02cddda55e75614884038fa4645b694cdGlenn Kasten            case 'n':
119731be80f02cddda55e75614884038fa4645b694cdGlenn Kasten                g_nohup = true;
11986f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            break;
119931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten
1200fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            case 's':
120131be80f02cddda55e75614884038fa4645b694cdGlenn Kasten                g_initialSleepSecs = atoi(optarg);
120231be80f02cddda55e75614884038fa4645b694cdGlenn Kasten            break;
120331be80f02cddda55e75614884038fa4645b694cdGlenn Kasten
1204fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            case 't':
1205fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                g_traceDurationSeconds = atoi(optarg);
1206fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1207fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
12087b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            case 'z':
12097b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis                g_compress = true;
12107b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis            break;
12117b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis
121240b26b4fc597f105823bc1e2a640e4df8baea243John Reck            case 'o':
121340b26b4fc597f105823bc1e2a640e4df8baea243John Reck                g_outputFile = optarg;
121440b26b4fc597f105823bc1e2a640e4df8baea243John Reck            break;
121540b26b4fc597f105823bc1e2a640e4df8baea243John Reck
12164edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling            case 0:
12174edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                if (!strcmp(long_options[option_index].name, "async_start")) {
12184edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    async = true;
12194edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceStop = false;
12204edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceDump = false;
12214edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    g_traceOverwrite = true;
12224edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                } else if (!strcmp(long_options[option_index].name, "async_stop")) {
12234edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    async = true;
12244ba2b63bff492815a86954c272a36d886f5bccecJohn Reck                    traceStart = false;
12254edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                } else if (!strcmp(long_options[option_index].name, "async_dump")) {
12264edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    async = true;
12274edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceStart = false;
12284edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                    traceStop = false;
1229550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman                } else if (!strcmp(long_options[option_index].name, "only_userspace")) {
1230550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman                    onlyUserspace = true;
1231d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                } else if (!strcmp(long_options[option_index].name, "stream")) {
1232d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    traceStream = true;
1233d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen                    traceDump = false;
12346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                } else if (!strcmp(long_options[option_index].name, "list_categories")) {
12356eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    listSupportedCategories();
12366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis                    exit(0);
12374edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling                }
12386f6f3f710b4dec2952298ae65d5f1674535c63f0Jamie Gennis            break;
12394edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling
1240fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            default:
1241cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis                fprintf(stderr, "\n");
1242fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                showHelp(argv[0]);
1243fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                exit(-1);
1244fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            break;
1245fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1246fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1247fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1248550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    if (onlyUserspace) {
1249550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        if (!async || !(traceStart || traceStop)) {
1250550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            fprintf(stderr, "--only_userspace can only be used with "
1251550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman                    "--async_start or --async_stop\n");
1252550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            exit(1);
1253550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        }
1254550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    }
1255550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
1256fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    registerSigHandler();
1257fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
125831be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    if (g_initialSleepSecs > 0) {
125931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten        sleep(g_initialSleepSecs);
126031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten    }
126131be80f02cddda55e75614884038fa4645b694cdGlenn Kasten
1262e9b8cfb63297b14253c5b464190fc5752457a38eJamie Gennis    bool ok = true;
1263550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
1264190cb7dd5e14e586916da51fdecaf446697633efWei Wang    if (traceStart) {
1265550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        ok &= setUpUserspaceTracing();
1266550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    }
1267550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
1268550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    if (ok && traceStart && !onlyUserspace) {
1269550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        ok &= setUpKernelTracing();
1270190cb7dd5e14e586916da51fdecaf446697633efWei Wang        ok &= startTrace();
1271190cb7dd5e14e586916da51fdecaf446697633efWei Wang    }
1272fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
12734edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    if (ok && traceStart) {
1274550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
1275550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        if (!traceStream && !onlyUserspace) {
1276ac53e73bba9b311bc92e40a58ad98c5e65d49d17Carmen Jackson            printf("capturing trace...");
1277d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            fflush(stdout);
1278d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        }
1279fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1280fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // We clear the trace after starting it because tracing gets enabled for
1281fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // each CPU individually in the kernel. Having the beginning of the trace
1282fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // contain entries from only one CPU can cause "begin" entries without a
1283fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // matching "end" entry to show up if a task gets migrated from one CPU to
1284fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        // another.
1285550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        if (!onlyUserspace)
1286550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            ok = clearTrace();
1287550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman
1288550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        if (!onlyUserspace)
1289550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            writeClockSyncMarker();
1290fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1291d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (ok && !async && !traceStream) {
1292fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            // Sleep to allow the trace to be captured.
1293fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            struct timespec timeLeft;
1294fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            timeLeft.tv_sec = g_traceDurationSeconds;
1295fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            timeLeft.tv_nsec = 0;
1296fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            do {
1297fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                if (g_traceAborted) {
1298fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                    break;
1299fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis                }
1300fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
1301fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1302d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen
1303d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        if (traceStream) {
1304d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen            streamTrace();
1305d95358713b98875733e91fe8fb0459a0b88eab14Martijn Coenen        }
1306fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1307fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1308fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    // Stop the trace and restore the default settings.
1309550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    if (traceStop && !onlyUserspace)
13106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis        stopTrace();
1311fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1312550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    if (ok && traceDump && !onlyUserspace) {
1313fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        if (!g_traceAborted) {
131440b26b4fc597f105823bc1e2a640e4df8baea243John Reck            printf(" done\n");
1315fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            fflush(stdout);
131640b26b4fc597f105823bc1e2a640e4df8baea243John Reck            int outFd = STDOUT_FILENO;
131740b26b4fc597f105823bc1e2a640e4df8baea243John Reck            if (g_outputFile) {
1318c579198835539100087ba71f5bbf38c3c09422e6Martijn Coenen                outFd = open(g_outputFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
131940b26b4fc597f105823bc1e2a640e4df8baea243John Reck            }
132040b26b4fc597f105823bc1e2a640e4df8baea243John Reck            if (outFd == -1) {
132140b26b4fc597f105823bc1e2a640e4df8baea243John Reck                printf("Failed to open '%s', err=%d", g_outputFile, errno);
132240b26b4fc597f105823bc1e2a640e4df8baea243John Reck            } else {
132340b26b4fc597f105823bc1e2a640e4df8baea243John Reck                dprintf(outFd, "TRACE:\n");
132440b26b4fc597f105823bc1e2a640e4df8baea243John Reck                dumpTrace(outFd);
132540b26b4fc597f105823bc1e2a640e4df8baea243John Reck                if (g_outputFile) {
132640b26b4fc597f105823bc1e2a640e4df8baea243John Reck                    close(outFd);
132740b26b4fc597f105823bc1e2a640e4df8baea243John Reck                }
132840b26b4fc597f105823bc1e2a640e4df8baea243John Reck            }
1329fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        } else {
1330fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            printf("\ntrace aborted.\n");
1331fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis            fflush(stdout);
1332fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        }
1333fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        clearTrace();
13344edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling    } else if (!ok) {
1335fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis        fprintf(stderr, "unable to start tracing\n");
1336fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    }
1337fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis
1338cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis    // Reset the trace buffer size to 1.
1339550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    if (traceStop) {
1340550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        cleanUpUserspaceTracing();
1341550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman        if (!onlyUserspace)
1342550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman            cleanUpKernelTracing();
1343550b18cac578fd4faa9addaf172a21ecd99839ddHector Dearman    }
1344cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis
1345fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis    return g_traceAborted ? 1 : 0;
1346fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis}
1347