Home | History | Annotate | Download | only in atrace
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "atrace"
     18 
     19 #include <errno.h>
     20 #include <fcntl.h>
     21 #include <getopt.h>
     22 #include <inttypes.h>
     23 #include <signal.h>
     24 #include <stdarg.h>
     25 #include <stdbool.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <time.h>
     30 #include <unistd.h>
     31 #include <zlib.h>
     32 
     33 #include <fstream>
     34 #include <memory>
     35 
     36 #include <binder/IBinder.h>
     37 #include <binder/IServiceManager.h>
     38 #include <binder/Parcel.h>
     39 
     40 #include <android/hidl/manager/1.0/IServiceManager.h>
     41 #include <hidl/ServiceManagement.h>
     42 
     43 #include <pdx/default_transport/service_utility.h>
     44 #include <utils/String8.h>
     45 #include <utils/Timers.h>
     46 #include <utils/Tokenizer.h>
     47 #include <utils/Trace.h>
     48 #include <android-base/file.h>
     49 #include <android-base/macros.h>
     50 #include <android-base/properties.h>
     51 #include <android-base/stringprintf.h>
     52 
     53 using namespace android;
     54 using pdx::default_transport::ServiceUtility;
     55 
     56 using std::string;
     57 
     58 #define MAX_SYS_FILES 10
     59 #define MAX_PACKAGES 16
     60 
     61 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
     62 
     63 const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
     64 const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
     65 const char* k_coreServiceCategory = "core_services";
     66 const char* k_pdxServiceCategory = "pdx";
     67 const char* k_coreServicesProp = "ro.atrace.core.services";
     68 
     69 typedef enum { OPT, REQ } requiredness  ;
     70 
     71 struct TracingCategory {
     72     // The name identifying the category.
     73     const char* name;
     74 
     75     // A longer description of the category.
     76     const char* longname;
     77 
     78     // The userland tracing tags that the category enables.
     79     uint64_t tags;
     80 
     81     // The fname==NULL terminated list of /sys/ files that the category
     82     // enables.
     83     struct {
     84         // Whether the file must be writable in order to enable the tracing
     85         // category.
     86         requiredness required;
     87 
     88         // The path to the enable file.
     89         const char* path;
     90     } sysfiles[MAX_SYS_FILES];
     91 };
     92 
     93 /* Tracing categories */
     94 static const TracingCategory k_categories[] = {
     95     { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
     96         { OPT,      "events/mdss/enable" },
     97     } },
     98     { "input",      "Input",            ATRACE_TAG_INPUT, { } },
     99     { "view",       "View System",      ATRACE_TAG_VIEW, { } },
    100     { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
    101     { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
    102     { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
    103     { "sm",         "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
    104     { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
    105     { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
    106     { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
    107     { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
    108     { "app",        "Application",      ATRACE_TAG_APP, { } },
    109     { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
    110     { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
    111     { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
    112     { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
    113     { "power",      "Power Management", ATRACE_TAG_POWER, { } },
    114     { "pm",         "Package Manager",  ATRACE_TAG_PACKAGE_MANAGER, { } },
    115     { "ss",         "System Server",    ATRACE_TAG_SYSTEM_SERVER, { } },
    116     { "database",   "Database",         ATRACE_TAG_DATABASE, { } },
    117     { "network",    "Network",          ATRACE_TAG_NETWORK, { } },
    118     { "adb",        "ADB",              ATRACE_TAG_ADB, { } },
    119     { k_coreServiceCategory, "Core services", 0, { } },
    120     { k_pdxServiceCategory, "PDX services", 0, { } },
    121     { "sched",      "CPU Scheduling",   0, {
    122         { REQ,      "events/sched/sched_switch/enable" },
    123         { REQ,      "events/sched/sched_wakeup/enable" },
    124         { OPT,      "events/sched/sched_waking/enable" },
    125         { OPT,      "events/sched/sched_blocked_reason/enable" },
    126         { OPT,      "events/sched/sched_cpu_hotplug/enable" },
    127         { OPT,      "events/cgroup/enable" },
    128     } },
    129     { "irq",        "IRQ Events",   0, {
    130         { REQ,      "events/irq/enable" },
    131         { OPT,      "events/ipi/enable" },
    132     } },
    133     { "i2c",        "I2C Events",   0, {
    134         { REQ,      "events/i2c/enable" },
    135         { REQ,      "events/i2c/i2c_read/enable" },
    136         { REQ,      "events/i2c/i2c_write/enable" },
    137         { REQ,      "events/i2c/i2c_result/enable" },
    138         { REQ,      "events/i2c/i2c_reply/enable" },
    139         { OPT,      "events/i2c/smbus_read/enable" },
    140         { OPT,      "events/i2c/smbus_write/enable" },
    141         { OPT,      "events/i2c/smbus_result/enable" },
    142         { OPT,      "events/i2c/smbus_reply/enable" },
    143     } },
    144     { "freq",       "CPU Frequency",    0, {
    145         { REQ,      "events/power/cpu_frequency/enable" },
    146         { OPT,      "events/power/clock_set_rate/enable" },
    147         { OPT,      "events/power/cpu_frequency_limits/enable" },
    148     } },
    149     { "membus",     "Memory Bus Utilization", 0, {
    150         { REQ,      "events/memory_bus/enable" },
    151     } },
    152     { "idle",       "CPU Idle",         0, {
    153         { REQ,      "events/power/cpu_idle/enable" },
    154     } },
    155     { "disk",       "Disk I/O",         0, {
    156         { OPT,      "events/f2fs/f2fs_sync_file_enter/enable" },
    157         { OPT,      "events/f2fs/f2fs_sync_file_exit/enable" },
    158         { OPT,      "events/f2fs/f2fs_write_begin/enable" },
    159         { OPT,      "events/f2fs/f2fs_write_end/enable" },
    160         { OPT,      "events/ext4/ext4_da_write_begin/enable" },
    161         { OPT,      "events/ext4/ext4_da_write_end/enable" },
    162         { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
    163         { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
    164         { REQ,      "events/block/block_rq_issue/enable" },
    165         { REQ,      "events/block/block_rq_complete/enable" },
    166     } },
    167     { "mmc",        "eMMC commands",    0, {
    168         { REQ,      "events/mmc/enable" },
    169     } },
    170     { "load",       "CPU Load",         0, {
    171         { REQ,      "events/cpufreq_interactive/enable" },
    172     } },
    173     { "sync",       "Synchronization",  0, {
    174         { REQ,      "events/sync/enable" },
    175     } },
    176     { "workq",      "Kernel Workqueues", 0, {
    177         { REQ,      "events/workqueue/enable" },
    178     } },
    179     { "memreclaim", "Kernel Memory Reclaim", 0, {
    180         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
    181         { REQ,      "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
    182         { REQ,      "events/vmscan/mm_vmscan_kswapd_wake/enable" },
    183         { REQ,      "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
    184         { REQ,      "events/lowmemorykiller/enable" },
    185     } },
    186     { "regulators",  "Voltage and Current Regulators", 0, {
    187         { REQ,      "events/regulator/enable" },
    188     } },
    189     { "binder_driver", "Binder Kernel driver", 0, {
    190         { REQ,      "events/binder/binder_transaction/enable" },
    191         { REQ,      "events/binder/binder_transaction_received/enable" },
    192         { OPT,      "events/binder/binder_set_priority/enable" },
    193     } },
    194     { "binder_lock", "Binder global lock trace", 0, {
    195         { OPT,      "events/binder/binder_lock/enable" },
    196         { OPT,      "events/binder/binder_locked/enable" },
    197         { OPT,      "events/binder/binder_unlock/enable" },
    198     } },
    199     { "pagecache",  "Page cache", 0, {
    200         { REQ,      "events/filemap/enable" },
    201     } },
    202 };
    203 
    204 /* Command line options */
    205 static int g_traceDurationSeconds = 5;
    206 static bool g_traceOverwrite = false;
    207 static int g_traceBufferSizeKB = 2048;
    208 static bool g_compress = false;
    209 static bool g_nohup = false;
    210 static int g_initialSleepSecs = 0;
    211 static const char* g_categoriesFile = NULL;
    212 static const char* g_kernelTraceFuncs = NULL;
    213 static const char* g_debugAppCmdLine = "";
    214 static const char* g_outputFile = nullptr;
    215 
    216 /* Global state */
    217 static bool g_tracePdx = false;
    218 static bool g_traceAborted = false;
    219 static bool g_categoryEnables[arraysize(k_categories)] = {};
    220 static std::string g_traceFolder;
    221 
    222 /* Sys file paths */
    223 static const char* k_traceClockPath =
    224     "trace_clock";
    225 
    226 static const char* k_traceBufferSizePath =
    227     "buffer_size_kb";
    228 
    229 static const char* k_traceCmdlineSizePath =
    230     "saved_cmdlines_size";
    231 
    232 static const char* k_tracingOverwriteEnablePath =
    233     "options/overwrite";
    234 
    235 static const char* k_currentTracerPath =
    236     "current_tracer";
    237 
    238 static const char* k_printTgidPath =
    239     "options/print-tgid";
    240 
    241 static const char* k_funcgraphAbsTimePath =
    242     "options/funcgraph-abstime";
    243 
    244 static const char* k_funcgraphCpuPath =
    245     "options/funcgraph-cpu";
    246 
    247 static const char* k_funcgraphProcPath =
    248     "options/funcgraph-proc";
    249 
    250 static const char* k_funcgraphFlatPath =
    251     "options/funcgraph-flat";
    252 
    253 static const char* k_funcgraphDurationPath =
    254     "options/funcgraph-duration";
    255 
    256 static const char* k_ftraceFilterPath =
    257     "set_ftrace_filter";
    258 
    259 static const char* k_tracingOnPath =
    260     "tracing_on";
    261 
    262 static const char* k_tracePath =
    263     "trace";
    264 
    265 static const char* k_traceStreamPath =
    266     "trace_pipe";
    267 
    268 static const char* k_traceMarkerPath =
    269     "trace_marker";
    270 
    271 // Check whether a file exists.
    272 static bool fileExists(const char* filename) {
    273     return access((g_traceFolder + filename).c_str(), F_OK) != -1;
    274 }
    275 
    276 // Check whether a file is writable.
    277 static bool fileIsWritable(const char* filename) {
    278     return access((g_traceFolder + filename).c_str(), W_OK) != -1;
    279 }
    280 
    281 // Truncate a file.
    282 static bool truncateFile(const char* path)
    283 {
    284     // This uses creat rather than truncate because some of the debug kernel
    285     // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
    286     // calls to truncate, but they are cleared by calls to creat.
    287     int traceFD = creat((g_traceFolder + path).c_str(), 0);
    288     if (traceFD == -1) {
    289         fprintf(stderr, "error truncating %s: %s (%d)\n", (g_traceFolder + path).c_str(),
    290             strerror(errno), errno);
    291         return false;
    292     }
    293 
    294     close(traceFD);
    295 
    296     return true;
    297 }
    298 
    299 static bool _writeStr(const char* filename, const char* str, int flags)
    300 {
    301     std::string fullFilename = g_traceFolder + filename;
    302     int fd = open(fullFilename.c_str(), flags);
    303     if (fd == -1) {
    304         fprintf(stderr, "error opening %s: %s (%d)\n", fullFilename.c_str(),
    305                 strerror(errno), errno);
    306         return false;
    307     }
    308 
    309     bool ok = true;
    310     ssize_t len = strlen(str);
    311     if (write(fd, str, len) != len) {
    312         fprintf(stderr, "error writing to %s: %s (%d)\n", fullFilename.c_str(),
    313                 strerror(errno), errno);
    314         ok = false;
    315     }
    316 
    317     close(fd);
    318 
    319     return ok;
    320 }
    321 
    322 // Write a string to a file, returning true if the write was successful.
    323 static bool writeStr(const char* filename, const char* str)
    324 {
    325     return _writeStr(filename, str, O_WRONLY);
    326 }
    327 
    328 // Append a string to a file, returning true if the write was successful.
    329 static bool appendStr(const char* filename, const char* str)
    330 {
    331     return _writeStr(filename, str, O_APPEND|O_WRONLY);
    332 }
    333 
    334 static void writeClockSyncMarker()
    335 {
    336   char buffer[128];
    337   int len = 0;
    338   int fd = open((g_traceFolder + k_traceMarkerPath).c_str(), O_WRONLY);
    339   if (fd == -1) {
    340       fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
    341               strerror(errno), errno);
    342       return;
    343   }
    344   float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
    345 
    346   len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
    347   if (write(fd, buffer, len) != len) {
    348       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
    349   }
    350 
    351   int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
    352   len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
    353   if (write(fd, buffer, len) != len) {
    354       fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
    355   }
    356 
    357   close(fd);
    358 }
    359 
    360 // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
    361 // file.
    362 static bool setKernelOptionEnable(const char* filename, bool enable)
    363 {
    364     return writeStr(filename, enable ? "1" : "0");
    365 }
    366 
    367 // Check whether the category is supported on the device with the current
    368 // rootness.  A category is supported only if all its required /sys/ files are
    369 // writable and if enabling the category will enable one or more tracing tags
    370 // or /sys/ files.
    371 static bool isCategorySupported(const TracingCategory& category)
    372 {
    373     if (strcmp(category.name, k_coreServiceCategory) == 0) {
    374         return !android::base::GetProperty(k_coreServicesProp, "").empty();
    375     }
    376 
    377     if (strcmp(category.name, k_pdxServiceCategory) == 0) {
    378         return true;
    379     }
    380 
    381     bool ok = category.tags != 0;
    382     for (int i = 0; i < MAX_SYS_FILES; i++) {
    383         const char* path = category.sysfiles[i].path;
    384         bool req = category.sysfiles[i].required == REQ;
    385         if (path != NULL) {
    386             if (req) {
    387                 if (!fileIsWritable(path)) {
    388                     return false;
    389                 } else {
    390                     ok = true;
    391                 }
    392             } else {
    393                 ok = true;
    394             }
    395         }
    396     }
    397     return ok;
    398 }
    399 
    400 // Check whether the category would be supported on the device if the user
    401 // were root.  This function assumes that root is able to write to any file
    402 // that exists.  It performs the same logic as isCategorySupported, but it
    403 // uses file existence rather than writability in the /sys/ file checks.
    404 static bool isCategorySupportedForRoot(const TracingCategory& category)
    405 {
    406     bool ok = category.tags != 0;
    407     for (int i = 0; i < MAX_SYS_FILES; i++) {
    408         const char* path = category.sysfiles[i].path;
    409         bool req = category.sysfiles[i].required == REQ;
    410         if (path != NULL) {
    411             if (req) {
    412                 if (!fileExists(path)) {
    413                     return false;
    414                 } else {
    415                     ok = true;
    416                 }
    417             } else {
    418                 ok |= fileExists(path);
    419             }
    420         }
    421     }
    422     return ok;
    423 }
    424 
    425 // Enable or disable overwriting of the kernel trace buffers.  Disabling this
    426 // will cause tracing to stop once the trace buffers have filled up.
    427 static bool setTraceOverwriteEnable(bool enable)
    428 {
    429     return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
    430 }
    431 
    432 // Enable or disable kernel tracing.
    433 static bool setTracingEnabled(bool enable)
    434 {
    435     return setKernelOptionEnable(k_tracingOnPath, enable);
    436 }
    437 
    438 // Clear the contents of the kernel trace.
    439 static bool clearTrace()
    440 {
    441     return truncateFile(k_tracePath);
    442 }
    443 
    444 // Set the size of the kernel's trace buffer in kilobytes.
    445 static bool setTraceBufferSizeKB(int size)
    446 {
    447     char str[32] = "1";
    448     int len;
    449     if (size < 1) {
    450         size = 1;
    451     }
    452     snprintf(str, 32, "%d", size);
    453     return writeStr(k_traceBufferSizePath, str);
    454 }
    455 
    456 // Set the default size of cmdline hashtable
    457 static bool setCmdlineSize()
    458 {
    459     if (fileExists(k_traceCmdlineSizePath)) {
    460         return writeStr(k_traceCmdlineSizePath, "8192");
    461     }
    462     return true;
    463 }
    464 
    465 // Set the clock to the best available option while tracing. Use 'boot' if it's
    466 // available; otherwise, use 'mono'. If neither are available use 'global'.
    467 // Any write to the trace_clock sysfs file will reset the buffer, so only
    468 // update it if the requested value is not the current value.
    469 static bool setClock()
    470 {
    471     std::ifstream clockFile((g_traceFolder + k_traceClockPath).c_str(), O_RDONLY);
    472     std::string clockStr((std::istreambuf_iterator<char>(clockFile)),
    473         std::istreambuf_iterator<char>());
    474 
    475     std::string newClock;
    476     if (clockStr.find("boot") != std::string::npos) {
    477         newClock = "boot";
    478     } else if (clockStr.find("mono") != std::string::npos) {
    479         newClock = "mono";
    480     } else {
    481         newClock = "global";
    482     }
    483 
    484     size_t begin = clockStr.find("[") + 1;
    485     size_t end = clockStr.find("]");
    486     if (newClock.compare(0, std::string::npos, clockStr, begin, end-begin) == 0) {
    487         return true;
    488     }
    489     return writeStr(k_traceClockPath, newClock.c_str());
    490 }
    491 
    492 static bool setPrintTgidEnableIfPresent(bool enable)
    493 {
    494     if (fileExists(k_printTgidPath)) {
    495         return setKernelOptionEnable(k_printTgidPath, enable);
    496     }
    497     return true;
    498 }
    499 
    500 // Poke all the binder-enabled processes in the system to get them to re-read
    501 // their system properties.
    502 static bool pokeBinderServices()
    503 {
    504     sp<IServiceManager> sm = defaultServiceManager();
    505     Vector<String16> services = sm->listServices();
    506     for (size_t i = 0; i < services.size(); i++) {
    507         sp<IBinder> obj = sm->checkService(services[i]);
    508         if (obj != NULL) {
    509             Parcel data;
    510             if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
    511                     NULL, 0) != OK) {
    512                 if (false) {
    513                     // XXX: For some reason this fails on tablets trying to
    514                     // poke the "phone" service.  It's not clear whether some
    515                     // are expected to fail.
    516                     String8 svc(services[i]);
    517                     fprintf(stderr, "error poking binder service %s\n",
    518                         svc.string());
    519                     return false;
    520                 }
    521             }
    522         }
    523     }
    524     return true;
    525 }
    526 
    527 // Poke all the HAL processes in the system to get them to re-read
    528 // their system properties.
    529 static void pokeHalServices()
    530 {
    531     using ::android::hidl::base::V1_0::IBase;
    532     using ::android::hidl::manager::V1_0::IServiceManager;
    533     using ::android::hardware::hidl_string;
    534     using ::android::hardware::Return;
    535 
    536     sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
    537 
    538     if (sm == nullptr) {
    539         fprintf(stderr, "failed to get IServiceManager to poke hal services\n");
    540         return;
    541     }
    542 
    543     auto listRet = sm->list([&](const auto &interfaces) {
    544         for (size_t i = 0; i < interfaces.size(); i++) {
    545             string fqInstanceName = interfaces[i];
    546             string::size_type n = fqInstanceName.find("/");
    547             if (n == std::string::npos || interfaces[i].size() == n+1)
    548                 continue;
    549             hidl_string fqInterfaceName = fqInstanceName.substr(0, n);
    550             hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
    551             Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName);
    552             if (!interfaceRet.isOk()) {
    553                 // ignore
    554                 continue;
    555             }
    556 
    557             sp<IBase> interface = interfaceRet;
    558             if (interface == nullptr) {
    559                 // ignore
    560                 continue;
    561             }
    562 
    563             auto notifyRet = interface->notifySyspropsChanged();
    564             if (!notifyRet.isOk()) {
    565                 // ignore
    566             }
    567         }
    568     });
    569     if (!listRet.isOk()) {
    570         // TODO(b/34242478) fix this when we determine the correct ACL
    571         //fprintf(stderr, "failed to list services: %s\n", listRet.description().c_str());
    572     }
    573 }
    574 
    575 // Set the trace tags that userland tracing uses, and poke the running
    576 // processes to pick up the new value.
    577 static bool setTagsProperty(uint64_t tags)
    578 {
    579     std::string value = android::base::StringPrintf("%#" PRIx64, tags);
    580     if (!android::base::SetProperty(k_traceTagsProperty, value)) {
    581         fprintf(stderr, "error setting trace tags system property\n");
    582         return false;
    583     }
    584     return true;
    585 }
    586 
    587 static void clearAppProperties()
    588 {
    589     for (int i = 0; i < MAX_PACKAGES; i++) {
    590         std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
    591         if (!android::base::SetProperty(key, "")) {
    592             fprintf(stderr, "failed to clear system property: %s\n", key.c_str());
    593         }
    594     }
    595     if (!android::base::SetProperty(k_traceAppsNumberProperty, "")) {
    596         fprintf(stderr, "failed to clear system property: %s",
    597               k_traceAppsNumberProperty);
    598     }
    599 }
    600 
    601 // Set the system property that indicates which apps should perform
    602 // application-level tracing.
    603 static bool setAppCmdlineProperty(char* cmdline)
    604 {
    605     int i = 0;
    606     char* start = cmdline;
    607     while (start != NULL) {
    608         if (i == MAX_PACKAGES) {
    609             fprintf(stderr, "error: only 16 packages could be traced at once\n");
    610             clearAppProperties();
    611             return false;
    612         }
    613         char* end = strchr(start, ',');
    614         if (end != NULL) {
    615             *end = '\0';
    616             end++;
    617         }
    618         std::string key = android::base::StringPrintf(k_traceAppsPropertyTemplate, i);
    619         if (!android::base::SetProperty(key, start)) {
    620             fprintf(stderr, "error setting trace app %d property to %s\n", i, key.c_str());
    621             clearAppProperties();
    622             return false;
    623         }
    624         start = end;
    625         i++;
    626     }
    627 
    628     std::string value = android::base::StringPrintf("%d", i);
    629     if (!android::base::SetProperty(k_traceAppsNumberProperty, value)) {
    630         fprintf(stderr, "error setting trace app number property to %s\n", value.c_str());
    631         clearAppProperties();
    632         return false;
    633     }
    634     return true;
    635 }
    636 
    637 // Disable all /sys/ enable files.
    638 static bool disableKernelTraceEvents() {
    639     bool ok = true;
    640     for (size_t i = 0; i < arraysize(k_categories); i++) {
    641         const TracingCategory &c = k_categories[i];
    642         for (int j = 0; j < MAX_SYS_FILES; j++) {
    643             const char* path = c.sysfiles[j].path;
    644             if (path != NULL && fileIsWritable(path)) {
    645                 ok &= setKernelOptionEnable(path, false);
    646             }
    647         }
    648     }
    649     return ok;
    650 }
    651 
    652 // Verify that the comma separated list of functions are being traced by the
    653 // kernel.
    654 static bool verifyKernelTraceFuncs(const char* funcs)
    655 {
    656     std::string buf;
    657     if (!android::base::ReadFileToString(g_traceFolder + k_ftraceFilterPath, &buf)) {
    658          fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
    659             strerror(errno), errno);
    660          return false;
    661     }
    662 
    663     String8 funcList = String8::format("\n%s",buf.c_str());
    664 
    665     // Make sure that every function listed in funcs is in the list we just
    666     // read from the kernel, except for wildcard inputs.
    667     bool ok = true;
    668     char* myFuncs = strdup(funcs);
    669     char* func = strtok(myFuncs, ",");
    670     while (func) {
    671         if (!strchr(func, '*')) {
    672             String8 fancyFunc = String8::format("\n%s\n", func);
    673             bool found = funcList.find(fancyFunc.string(), 0) >= 0;
    674             if (!found || func[0] == '\0') {
    675                 fprintf(stderr, "error: \"%s\" is not a valid kernel function "
    676                         "to trace.\n", func);
    677                 ok = false;
    678             }
    679         }
    680         func = strtok(NULL, ",");
    681     }
    682     free(myFuncs);
    683     return ok;
    684 }
    685 
    686 // Set the comma separated list of functions that the kernel is to trace.
    687 static bool setKernelTraceFuncs(const char* funcs)
    688 {
    689     bool ok = true;
    690 
    691     if (funcs == NULL || funcs[0] == '\0') {
    692         // Disable kernel function tracing.
    693         if (fileIsWritable(k_currentTracerPath)) {
    694             ok &= writeStr(k_currentTracerPath, "nop");
    695         }
    696         if (fileIsWritable(k_ftraceFilterPath)) {
    697             ok &= truncateFile(k_ftraceFilterPath);
    698         }
    699     } else {
    700         // Enable kernel function tracing.
    701         ok &= writeStr(k_currentTracerPath, "function_graph");
    702         ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
    703         ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
    704         ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
    705         ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
    706 
    707         // Set the requested filter functions.
    708         ok &= truncateFile(k_ftraceFilterPath);
    709         char* myFuncs = strdup(funcs);
    710         char* func = strtok(myFuncs, ",");
    711         while (func) {
    712             ok &= appendStr(k_ftraceFilterPath, func);
    713             func = strtok(NULL, ",");
    714         }
    715         free(myFuncs);
    716 
    717         // Verify that the set functions are being traced.
    718         if (ok) {
    719             ok &= verifyKernelTraceFuncs(funcs);
    720         }
    721     }
    722 
    723     return ok;
    724 }
    725 
    726 static bool setCategoryEnable(const char* name, bool enable)
    727 {
    728     for (size_t i = 0; i < arraysize(k_categories); i++) {
    729         const TracingCategory& c = k_categories[i];
    730         if (strcmp(name, c.name) == 0) {
    731             if (isCategorySupported(c)) {
    732                 g_categoryEnables[i] = enable;
    733                 return true;
    734             } else {
    735                 if (isCategorySupportedForRoot(c)) {
    736                     fprintf(stderr, "error: category \"%s\" requires root "
    737                             "privileges.\n", name);
    738                 } else {
    739                     fprintf(stderr, "error: category \"%s\" is not supported "
    740                             "on this device.\n", name);
    741                 }
    742                 return false;
    743             }
    744         }
    745     }
    746     fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
    747     return false;
    748 }
    749 
    750 static bool setCategoriesEnableFromFile(const char* categories_file)
    751 {
    752     if (!categories_file) {
    753         return true;
    754     }
    755     Tokenizer* tokenizer = NULL;
    756     if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
    757         return false;
    758     }
    759     bool ok = true;
    760     while (!tokenizer->isEol()) {
    761         String8 token = tokenizer->nextToken(" ");
    762         if (token.isEmpty()) {
    763             tokenizer->skipDelimiters(" ");
    764             continue;
    765         }
    766         ok &= setCategoryEnable(token.string(), true);
    767     }
    768     delete tokenizer;
    769     return ok;
    770 }
    771 
    772 // Set all the kernel tracing settings to the desired state for this trace
    773 // capture.
    774 static bool setUpTrace()
    775 {
    776     bool ok = true;
    777 
    778     // Set up the tracing options.
    779     ok &= setCategoriesEnableFromFile(g_categoriesFile);
    780     ok &= setTraceOverwriteEnable(g_traceOverwrite);
    781     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
    782     // TODO: Re-enable after stabilization
    783     //ok &= setCmdlineSize();
    784     ok &= setClock();
    785     ok &= setPrintTgidEnableIfPresent(true);
    786     ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
    787 
    788     // Set up the tags property.
    789     uint64_t tags = 0;
    790     for (size_t i = 0; i < arraysize(k_categories); i++) {
    791         if (g_categoryEnables[i]) {
    792             const TracingCategory &c = k_categories[i];
    793             tags |= c.tags;
    794         }
    795     }
    796     ok &= setTagsProperty(tags);
    797 
    798     bool coreServicesTagEnabled = false;
    799     for (size_t i = 0; i < arraysize(k_categories); i++) {
    800         if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
    801             coreServicesTagEnabled = g_categoryEnables[i];
    802         }
    803 
    804         // Set whether to poke PDX services in this session.
    805         if (strcmp(k_categories[i].name, k_pdxServiceCategory) == 0) {
    806             g_tracePdx = g_categoryEnables[i];
    807         }
    808     }
    809 
    810     std::string packageList(g_debugAppCmdLine);
    811     if (coreServicesTagEnabled) {
    812         if (!packageList.empty()) {
    813             packageList += ",";
    814         }
    815         packageList += android::base::GetProperty(k_coreServicesProp, "");
    816     }
    817     ok &= setAppCmdlineProperty(&packageList[0]);
    818     ok &= pokeBinderServices();
    819     pokeHalServices();
    820 
    821     if (g_tracePdx) {
    822         ok &= ServiceUtility::PokeServices();
    823     }
    824 
    825     // Disable all the sysfs enables.  This is done as a separate loop from
    826     // the enables to allow the same enable to exist in multiple categories.
    827     ok &= disableKernelTraceEvents();
    828 
    829     // Enable all the sysfs enables that are in an enabled category.
    830     for (size_t i = 0; i < arraysize(k_categories); i++) {
    831         if (g_categoryEnables[i]) {
    832             const TracingCategory &c = k_categories[i];
    833             for (int j = 0; j < MAX_SYS_FILES; j++) {
    834                 const char* path = c.sysfiles[j].path;
    835                 bool required = c.sysfiles[j].required == REQ;
    836                 if (path != NULL) {
    837                     if (fileIsWritable(path)) {
    838                         ok &= setKernelOptionEnable(path, true);
    839                     } else if (required) {
    840                         fprintf(stderr, "error writing file %s\n", path);
    841                         ok = false;
    842                     }
    843                 }
    844             }
    845         }
    846     }
    847 
    848     return ok;
    849 }
    850 
    851 // Reset all the kernel tracing settings to their default state.
    852 static void cleanUpTrace()
    853 {
    854     // Disable all tracing that we're able to.
    855     disableKernelTraceEvents();
    856 
    857     // Reset the system properties.
    858     setTagsProperty(0);
    859     clearAppProperties();
    860     pokeBinderServices();
    861 
    862     if (g_tracePdx) {
    863         ServiceUtility::PokeServices();
    864     }
    865 
    866     // Set the options back to their defaults.
    867     setTraceOverwriteEnable(true);
    868     setTraceBufferSizeKB(1);
    869     setPrintTgidEnableIfPresent(false);
    870     setKernelTraceFuncs(NULL);
    871 }
    872 
    873 
    874 // Enable tracing in the kernel.
    875 static bool startTrace()
    876 {
    877     return setTracingEnabled(true);
    878 }
    879 
    880 // Disable tracing in the kernel.
    881 static void stopTrace()
    882 {
    883     setTracingEnabled(false);
    884 }
    885 
    886 // Read data from the tracing pipe and forward to stdout
    887 static void streamTrace()
    888 {
    889     char trace_data[4096];
    890     int traceFD = open((g_traceFolder + k_traceStreamPath).c_str(), O_RDWR);
    891     if (traceFD == -1) {
    892         fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
    893                 strerror(errno), errno);
    894         return;
    895     }
    896     while (!g_traceAborted) {
    897         ssize_t bytes_read = read(traceFD, trace_data, 4096);
    898         if (bytes_read > 0) {
    899             write(STDOUT_FILENO, trace_data, bytes_read);
    900             fflush(stdout);
    901         } else {
    902             if (!g_traceAborted) {
    903                 fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
    904                         bytes_read, errno, strerror(errno));
    905             }
    906             break;
    907         }
    908     }
    909 }
    910 
    911 // Read the current kernel trace and write it to stdout.
    912 static void dumpTrace(int outFd)
    913 {
    914     ALOGI("Dumping trace");
    915     int traceFD = open((g_traceFolder + k_tracePath).c_str(), O_RDWR);
    916     if (traceFD == -1) {
    917         fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
    918                 strerror(errno), errno);
    919         return;
    920     }
    921 
    922     if (g_compress) {
    923         z_stream zs;
    924         memset(&zs, 0, sizeof(zs));
    925 
    926         int result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
    927         if (result != Z_OK) {
    928             fprintf(stderr, "error initializing zlib: %d\n", result);
    929             close(traceFD);
    930             return;
    931         }
    932 
    933         constexpr size_t bufSize = 64*1024;
    934         std::unique_ptr<uint8_t> in(new uint8_t[bufSize]);
    935         std::unique_ptr<uint8_t> out(new uint8_t[bufSize]);
    936         if (!in || !out) {
    937             fprintf(stderr, "couldn't allocate buffers\n");
    938             close(traceFD);
    939             return;
    940         }
    941 
    942         int flush = Z_NO_FLUSH;
    943 
    944         zs.next_out = reinterpret_cast<Bytef*>(out.get());
    945         zs.avail_out = bufSize;
    946 
    947         do {
    948 
    949             if (zs.avail_in == 0) {
    950                 // More input is needed.
    951                 result = read(traceFD, in.get(), bufSize);
    952                 if (result < 0) {
    953                     fprintf(stderr, "error reading trace: %s (%d)\n",
    954                             strerror(errno), errno);
    955                     result = Z_STREAM_END;
    956                     break;
    957                 } else if (result == 0) {
    958                     flush = Z_FINISH;
    959                 } else {
    960                     zs.next_in = reinterpret_cast<Bytef*>(in.get());
    961                     zs.avail_in = result;
    962                 }
    963             }
    964 
    965             if (zs.avail_out == 0) {
    966                 // Need to write the output.
    967                 result = write(outFd, out.get(), bufSize);
    968                 if ((size_t)result < bufSize) {
    969                     fprintf(stderr, "error writing deflated trace: %s (%d)\n",
    970                             strerror(errno), errno);
    971                     result = Z_STREAM_END; // skip deflate error message
    972                     zs.avail_out = bufSize; // skip the final write
    973                     break;
    974                 }
    975                 zs.next_out = reinterpret_cast<Bytef*>(out.get());
    976                 zs.avail_out = bufSize;
    977             }
    978 
    979         } while ((result = deflate(&zs, flush)) == Z_OK);
    980 
    981         if (result != Z_STREAM_END) {
    982             fprintf(stderr, "error deflating trace: %s\n", zs.msg);
    983         }
    984 
    985         if (zs.avail_out < bufSize) {
    986             size_t bytes = bufSize - zs.avail_out;
    987             result = write(outFd, out.get(), bytes);
    988             if ((size_t)result < bytes) {
    989                 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
    990                         strerror(errno), errno);
    991             }
    992         }
    993 
    994         result = deflateEnd(&zs);
    995         if (result != Z_OK) {
    996             fprintf(stderr, "error cleaning up zlib: %d\n", result);
    997         }
    998     } else {
    999         char buf[4096];
   1000         ssize_t rc;
   1001         while ((rc = TEMP_FAILURE_RETRY(read(traceFD, buf, sizeof(buf)))) > 0) {
   1002             if (!android::base::WriteFully(outFd, buf, rc)) {
   1003                 fprintf(stderr, "error writing trace: %s\n", strerror(errno));
   1004                 break;
   1005             }
   1006         }
   1007         if (rc == -1) {
   1008             fprintf(stderr, "error dumping trace: %s\n", strerror(errno));
   1009         }
   1010     }
   1011 
   1012     close(traceFD);
   1013 }
   1014 
   1015 static void handleSignal(int /*signo*/)
   1016 {
   1017     if (!g_nohup) {
   1018         g_traceAborted = true;
   1019     }
   1020 }
   1021 
   1022 static void registerSigHandler()
   1023 {
   1024     struct sigaction sa;
   1025     sigemptyset(&sa.sa_mask);
   1026     sa.sa_flags = 0;
   1027     sa.sa_handler = handleSignal;
   1028     sigaction(SIGHUP, &sa, NULL);
   1029     sigaction(SIGINT, &sa, NULL);
   1030     sigaction(SIGQUIT, &sa, NULL);
   1031     sigaction(SIGTERM, &sa, NULL);
   1032 }
   1033 
   1034 static void listSupportedCategories()
   1035 {
   1036     for (size_t i = 0; i < arraysize(k_categories); i++) {
   1037         const TracingCategory& c = k_categories[i];
   1038         if (isCategorySupported(c)) {
   1039             printf("  %10s - %s\n", c.name, c.longname);
   1040         }
   1041     }
   1042 }
   1043 
   1044 // Print the command usage help to stderr.
   1045 static void showHelp(const char *cmd)
   1046 {
   1047     fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
   1048     fprintf(stderr, "options include:\n"
   1049                     "  -a appname      enable app-level tracing for a comma "
   1050                         "separated list of cmdlines\n"
   1051                     "  -b N            use a trace buffer size of N KB\n"
   1052                     "  -c              trace into a circular buffer\n"
   1053                     "  -f filename     use the categories written in a file as space-separated\n"
   1054                     "                    values in a line\n"
   1055                     "  -k fname,...    trace the listed kernel functions\n"
   1056                     "  -n              ignore signals\n"
   1057                     "  -s N            sleep for N seconds before tracing [default 0]\n"
   1058                     "  -t N            trace for N seconds [default 5]\n"
   1059                     "  -z              compress the trace dump\n"
   1060                     "  --async_start   start circular trace and return immediately\n"
   1061                     "  --async_dump    dump the current contents of circular trace buffer\n"
   1062                     "  --async_stop    stop tracing and dump the current contents of circular\n"
   1063                     "                    trace buffer\n"
   1064                     "  --stream        stream trace to stdout as it enters the trace buffer\n"
   1065                     "                    Note: this can take significant CPU time, and is best\n"
   1066                     "                    used for measuring things that are not affected by\n"
   1067                     "                    CPU performance, like pagecache usage.\n"
   1068                     "  --list_categories\n"
   1069                     "                  list the available tracing categories\n"
   1070                     " -o filename      write the trace to the specified file instead\n"
   1071                     "                    of stdout.\n"
   1072             );
   1073 }
   1074 
   1075 bool findTraceFiles()
   1076 {
   1077     static const std::string debugfs_path = "/sys/kernel/debug/tracing/";
   1078     static const std::string tracefs_path = "/sys/kernel/tracing/";
   1079     static const std::string trace_file = "trace_marker";
   1080 
   1081     bool tracefs = access((tracefs_path + trace_file).c_str(), F_OK) != -1;
   1082     bool debugfs = access((debugfs_path + trace_file).c_str(), F_OK) != -1;
   1083 
   1084     if (!tracefs && !debugfs) {
   1085         fprintf(stderr, "Error: Did not find trace folder\n");
   1086         return false;
   1087     }
   1088 
   1089     if (tracefs) {
   1090         g_traceFolder = tracefs_path;
   1091     } else {
   1092         g_traceFolder = debugfs_path;
   1093     }
   1094 
   1095     return true;
   1096 }
   1097 
   1098 int main(int argc, char **argv)
   1099 {
   1100     bool async = false;
   1101     bool traceStart = true;
   1102     bool traceStop = true;
   1103     bool traceDump = true;
   1104     bool traceStream = false;
   1105 
   1106     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
   1107         showHelp(argv[0]);
   1108         exit(0);
   1109     }
   1110 
   1111     if (!findTraceFiles()) {
   1112         fprintf(stderr, "No trace folder found\n");
   1113         exit(-1);
   1114     }
   1115 
   1116     for (;;) {
   1117         int ret;
   1118         int option_index = 0;
   1119         static struct option long_options[] = {
   1120             {"async_start",     no_argument, 0,  0 },
   1121             {"async_stop",      no_argument, 0,  0 },
   1122             {"async_dump",      no_argument, 0,  0 },
   1123             {"list_categories", no_argument, 0,  0 },
   1124             {"stream",          no_argument, 0,  0 },
   1125             {           0,                0, 0,  0 }
   1126         };
   1127 
   1128         ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
   1129                           long_options, &option_index);
   1130 
   1131         if (ret < 0) {
   1132             for (int i = optind; i < argc; i++) {
   1133                 if (!setCategoryEnable(argv[i], true)) {
   1134                     fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
   1135                     exit(1);
   1136                 }
   1137             }
   1138             break;
   1139         }
   1140 
   1141         switch(ret) {
   1142             case 'a':
   1143                 g_debugAppCmdLine = optarg;
   1144             break;
   1145 
   1146             case 'b':
   1147                 g_traceBufferSizeKB = atoi(optarg);
   1148             break;
   1149 
   1150             case 'c':
   1151                 g_traceOverwrite = true;
   1152             break;
   1153 
   1154             case 'f':
   1155                 g_categoriesFile = optarg;
   1156             break;
   1157 
   1158             case 'k':
   1159                 g_kernelTraceFuncs = optarg;
   1160             break;
   1161 
   1162             case 'n':
   1163                 g_nohup = true;
   1164             break;
   1165 
   1166             case 's':
   1167                 g_initialSleepSecs = atoi(optarg);
   1168             break;
   1169 
   1170             case 't':
   1171                 g_traceDurationSeconds = atoi(optarg);
   1172             break;
   1173 
   1174             case 'z':
   1175                 g_compress = true;
   1176             break;
   1177 
   1178             case 'o':
   1179                 g_outputFile = optarg;
   1180             break;
   1181 
   1182             case 0:
   1183                 if (!strcmp(long_options[option_index].name, "async_start")) {
   1184                     async = true;
   1185                     traceStop = false;
   1186                     traceDump = false;
   1187                     g_traceOverwrite = true;
   1188                 } else if (!strcmp(long_options[option_index].name, "async_stop")) {
   1189                     async = true;
   1190                     traceStart = false;
   1191                 } else if (!strcmp(long_options[option_index].name, "async_dump")) {
   1192                     async = true;
   1193                     traceStart = false;
   1194                     traceStop = false;
   1195                 } else if (!strcmp(long_options[option_index].name, "stream")) {
   1196                     traceStream = true;
   1197                     traceDump = false;
   1198                 } else if (!strcmp(long_options[option_index].name, "list_categories")) {
   1199                     listSupportedCategories();
   1200                     exit(0);
   1201                 }
   1202             break;
   1203 
   1204             default:
   1205                 fprintf(stderr, "\n");
   1206                 showHelp(argv[0]);
   1207                 exit(-1);
   1208             break;
   1209         }
   1210     }
   1211 
   1212     registerSigHandler();
   1213 
   1214     if (g_initialSleepSecs > 0) {
   1215         sleep(g_initialSleepSecs);
   1216     }
   1217 
   1218     bool ok = true;
   1219     ok &= setUpTrace();
   1220     ok &= startTrace();
   1221 
   1222     if (ok && traceStart) {
   1223         if (!traceStream) {
   1224             printf("capturing trace...");
   1225             fflush(stdout);
   1226         }
   1227 
   1228         // We clear the trace after starting it because tracing gets enabled for
   1229         // each CPU individually in the kernel. Having the beginning of the trace
   1230         // contain entries from only one CPU can cause "begin" entries without a
   1231         // matching "end" entry to show up if a task gets migrated from one CPU to
   1232         // another.
   1233         ok = clearTrace();
   1234 
   1235         writeClockSyncMarker();
   1236         if (ok && !async && !traceStream) {
   1237             // Sleep to allow the trace to be captured.
   1238             struct timespec timeLeft;
   1239             timeLeft.tv_sec = g_traceDurationSeconds;
   1240             timeLeft.tv_nsec = 0;
   1241             do {
   1242                 if (g_traceAborted) {
   1243                     break;
   1244                 }
   1245             } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
   1246         }
   1247 
   1248         if (traceStream) {
   1249             streamTrace();
   1250         }
   1251     }
   1252 
   1253     // Stop the trace and restore the default settings.
   1254     if (traceStop)
   1255         stopTrace();
   1256 
   1257     if (ok && traceDump) {
   1258         if (!g_traceAborted) {
   1259             printf(" done\n");
   1260             fflush(stdout);
   1261             int outFd = STDOUT_FILENO;
   1262             if (g_outputFile) {
   1263                 outFd = open(g_outputFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
   1264             }
   1265             if (outFd == -1) {
   1266                 printf("Failed to open '%s', err=%d", g_outputFile, errno);
   1267             } else {
   1268                 dprintf(outFd, "TRACE:\n");
   1269                 dumpTrace(outFd);
   1270                 if (g_outputFile) {
   1271                     close(outFd);
   1272                 }
   1273             }
   1274         } else {
   1275             printf("\ntrace aborted.\n");
   1276             fflush(stdout);
   1277         }
   1278         clearTrace();
   1279     } else if (!ok) {
   1280         fprintf(stderr, "unable to start tracing\n");
   1281     }
   1282 
   1283     // Reset the trace buffer size to 1.
   1284     if (traceStop)
   1285         cleanUpTrace();
   1286 
   1287     return g_traceAborted ? 1 : 0;
   1288 }
   1289