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