atrace.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <getopt.h>
  19. #include <inttypes.h>
  20. #include <signal.h>
  21. #include <stdarg.h>
  22. #include <stdbool.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <sys/sendfile.h>
  27. #include <time.h>
  28. #include <zlib.h>
  29. #include <binder/IBinder.h>
  30. #include <binder/IServiceManager.h>
  31. #include <binder/Parcel.h>
  32. #include <cutils/properties.h>
  33. #include <utils/String8.h>
  34. #include <utils/Timers.h>
  35. #include <utils/Trace.h>
  36. using namespace android;
  37. #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
  38. enum { MAX_SYS_FILES = 10 };
  39. const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
  40. const char* k_traceAppCmdlineProperty = "debug.atrace.app_cmdlines";
  41. typedef enum { OPT, REQ } requiredness ;
  42. struct TracingCategory {
  43. // The name identifying the category.
  44. const char* name;
  45. // A longer description of the category.
  46. const char* longname;
  47. // The userland tracing tags that the category enables.
  48. uint64_t tags;
  49. // The fname==NULL terminated list of /sys/ files that the category
  50. // enables.
  51. struct {
  52. // Whether the file must be writable in order to enable the tracing
  53. // category.
  54. requiredness required;
  55. // The path to the enable file.
  56. const char* path;
  57. } sysfiles[MAX_SYS_FILES];
  58. };
  59. /* Tracing categories */
  60. static const TracingCategory k_categories[] = {
  61. { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } },
  62. { "input", "Input", ATRACE_TAG_INPUT, { } },
  63. { "view", "View System", ATRACE_TAG_VIEW, { } },
  64. { "webview", "WebView", ATRACE_TAG_WEBVIEW, { } },
  65. { "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } },
  66. { "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
  67. { "sm", "Sync Manager", ATRACE_TAG_SYNC_MANAGER, { } },
  68. { "audio", "Audio", ATRACE_TAG_AUDIO, { } },
  69. { "video", "Video", ATRACE_TAG_VIDEO, { } },
  70. { "camera", "Camera", ATRACE_TAG_CAMERA, { } },
  71. { "hal", "Hardware Modules", ATRACE_TAG_HAL, { } },
  72. { "app", "Application", ATRACE_TAG_APP, { } },
  73. { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } },
  74. { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } },
  75. { "rs", "RenderScript", ATRACE_TAG_RS, { } },
  76. { "bionic", "Bionic C Library", ATRACE_TAG_BIONIC, { } },
  77. { "power", "Power Management", ATRACE_TAG_POWER, { } },
  78. { "sched", "CPU Scheduling", 0, {
  79. { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
  80. { REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
  81. { OPT, "/sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable" },
  82. } },
  83. { "irq", "IRQ Events", 0, {
  84. { REQ, "/sys/kernel/debug/tracing/events/irq/enable" },
  85. } },
  86. { "freq", "CPU Frequency", 0, {
  87. { REQ, "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
  88. { OPT, "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
  89. } },
  90. { "membus", "Memory Bus Utilization", 0, {
  91. { REQ, "/sys/kernel/debug/tracing/events/memory_bus/enable" },
  92. } },
  93. { "idle", "CPU Idle", 0, {
  94. { REQ, "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" },
  95. } },
  96. { "disk", "Disk I/O", 0, {
  97. { OPT, "/sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable" },
  98. { OPT, "/sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable" },
  99. { OPT, "/sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable" },
  100. { OPT, "/sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable" },
  101. { OPT, "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable" },
  102. { OPT, "/sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable" },
  103. { OPT, "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" },
  104. { OPT, "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" },
  105. { REQ, "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" },
  106. { REQ, "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" },
  107. } },
  108. { "mmc", "eMMC commands", 0, {
  109. { REQ, "/sys/kernel/debug/tracing/events/mmc/enable" },
  110. } },
  111. { "load", "CPU Load", 0, {
  112. { REQ, "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" },
  113. } },
  114. { "sync", "Synchronization", 0, {
  115. { REQ, "/sys/kernel/debug/tracing/events/sync/enable" },
  116. } },
  117. { "workq", "Kernel Workqueues", 0, {
  118. { REQ, "/sys/kernel/debug/tracing/events/workqueue/enable" },
  119. } },
  120. { "memreclaim", "Kernel Memory Reclaim", 0, {
  121. { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
  122. { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
  123. { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable" },
  124. { REQ, "/sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable" },
  125. } },
  126. { "regulators", "Voltage and Current Regulators", 0, {
  127. { REQ, "/sys/kernel/debug/tracing/events/regulator/enable" },
  128. } },
  129. };
  130. /* Command line options */
  131. static int g_traceDurationSeconds = 5;
  132. static bool g_traceOverwrite = false;
  133. static int g_traceBufferSizeKB = 2048;
  134. static bool g_compress = false;
  135. static bool g_nohup = false;
  136. static int g_initialSleepSecs = 0;
  137. static const char* g_kernelTraceFuncs = NULL;
  138. static const char* g_debugAppCmdLine = "";
  139. /* Global state */
  140. static bool g_traceAborted = false;
  141. static bool g_categoryEnables[NELEM(k_categories)] = {};
  142. /* Sys file paths */
  143. static const char* k_traceClockPath =
  144. "/sys/kernel/debug/tracing/trace_clock";
  145. static const char* k_traceBufferSizePath =
  146. "/sys/kernel/debug/tracing/buffer_size_kb";
  147. static const char* k_tracingOverwriteEnablePath =
  148. "/sys/kernel/debug/tracing/options/overwrite";
  149. static const char* k_currentTracerPath =
  150. "/sys/kernel/debug/tracing/current_tracer";
  151. static const char* k_printTgidPath =
  152. "/sys/kernel/debug/tracing/options/print-tgid";
  153. static const char* k_funcgraphAbsTimePath =
  154. "/sys/kernel/debug/tracing/options/funcgraph-abstime";
  155. static const char* k_funcgraphCpuPath =
  156. "/sys/kernel/debug/tracing/options/funcgraph-cpu";
  157. static const char* k_funcgraphProcPath =
  158. "/sys/kernel/debug/tracing/options/funcgraph-proc";
  159. static const char* k_funcgraphFlatPath =
  160. "/sys/kernel/debug/tracing/options/funcgraph-flat";
  161. static const char* k_funcgraphDurationPath =
  162. "/sys/kernel/debug/tracing/options/funcgraph-duration";
  163. static const char* k_ftraceFilterPath =
  164. "/sys/kernel/debug/tracing/set_ftrace_filter";
  165. static const char* k_tracingOnPath =
  166. "/sys/kernel/debug/tracing/tracing_on";
  167. static const char* k_tracePath =
  168. "/sys/kernel/debug/tracing/trace";
  169. static const char* k_traceMarkerPath =
  170. "/sys/kernel/debug/tracing/trace_marker";
  171. // Check whether a file exists.
  172. static bool fileExists(const char* filename) {
  173. return access(filename, F_OK) != -1;
  174. }
  175. // Check whether a file is writable.
  176. static bool fileIsWritable(const char* filename) {
  177. return access(filename, W_OK) != -1;
  178. }
  179. // Truncate a file.
  180. static bool truncateFile(const char* path)
  181. {
  182. // This uses creat rather than truncate because some of the debug kernel
  183. // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
  184. // calls to truncate, but they are cleared by calls to creat.
  185. int traceFD = creat(path, 0);
  186. if (traceFD == -1) {
  187. fprintf(stderr, "error truncating %s: %s (%d)\n", path,
  188. strerror(errno), errno);
  189. return false;
  190. }
  191. close(traceFD);
  192. return true;
  193. }
  194. static bool _writeStr(const char* filename, const char* str, int flags)
  195. {
  196. int fd = open(filename, flags);
  197. if (fd == -1) {
  198. fprintf(stderr, "error opening %s: %s (%d)\n", filename,
  199. strerror(errno), errno);
  200. return false;
  201. }
  202. bool ok = true;
  203. ssize_t len = strlen(str);
  204. if (write(fd, str, len) != len) {
  205. fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
  206. strerror(errno), errno);
  207. ok = false;
  208. }
  209. close(fd);
  210. return ok;
  211. }
  212. // Write a string to a file, returning true if the write was successful.
  213. static bool writeStr(const char* filename, const char* str)
  214. {
  215. return _writeStr(filename, str, O_WRONLY);
  216. }
  217. // Append a string to a file, returning true if the write was successful.
  218. static bool appendStr(const char* filename, const char* str)
  219. {
  220. return _writeStr(filename, str, O_APPEND|O_WRONLY);
  221. }
  222. static void writeClockSyncMarker()
  223. {
  224. char buffer[128];
  225. int len = 0;
  226. int fd = open(k_traceMarkerPath, O_WRONLY);
  227. if (fd == -1) {
  228. fprintf(stderr, "error opening %s: %s (%d)\n", k_traceMarkerPath,
  229. strerror(errno), errno);
  230. return;
  231. }
  232. float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f;
  233. len = snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
  234. if (write(fd, buffer, len) != len) {
  235. fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
  236. }
  237. int64_t realtime_in_ms = systemTime(CLOCK_REALTIME) / 1000000;
  238. len = snprintf(buffer, 128, "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", realtime_in_ms);
  239. if (write(fd, buffer, len) != len) {
  240. fprintf(stderr, "error writing clock sync marker %s (%d)\n", strerror(errno), errno);
  241. }
  242. close(fd);
  243. }
  244. // Enable or disable a kernel option by writing a "1" or a "0" into a /sys
  245. // file.
  246. static bool setKernelOptionEnable(const char* filename, bool enable)
  247. {
  248. return writeStr(filename, enable ? "1" : "0");
  249. }
  250. // Check whether the category is supported on the device with the current
  251. // rootness. A category is supported only if all its required /sys/ files are
  252. // writable and if enabling the category will enable one or more tracing tags
  253. // or /sys/ files.
  254. static bool isCategorySupported(const TracingCategory& category)
  255. {
  256. bool ok = category.tags != 0;
  257. for (int i = 0; i < MAX_SYS_FILES; i++) {
  258. const char* path = category.sysfiles[i].path;
  259. bool req = category.sysfiles[i].required == REQ;
  260. if (path != NULL) {
  261. if (req) {
  262. if (!fileIsWritable(path)) {
  263. return false;
  264. } else {
  265. ok = true;
  266. }
  267. } else {
  268. ok |= fileIsWritable(path);
  269. }
  270. }
  271. }
  272. return ok;
  273. }
  274. // Check whether the category would be supported on the device if the user
  275. // were root. This function assumes that root is able to write to any file
  276. // that exists. It performs the same logic as isCategorySupported, but it
  277. // uses file existance rather than writability in the /sys/ file checks.
  278. static bool isCategorySupportedForRoot(const TracingCategory& category)
  279. {
  280. bool ok = category.tags != 0;
  281. for (int i = 0; i < MAX_SYS_FILES; i++) {
  282. const char* path = category.sysfiles[i].path;
  283. bool req = category.sysfiles[i].required == REQ;
  284. if (path != NULL) {
  285. if (req) {
  286. if (!fileExists(path)) {
  287. return false;
  288. } else {
  289. ok = true;
  290. }
  291. } else {
  292. ok |= fileExists(path);
  293. }
  294. }
  295. }
  296. return ok;
  297. }
  298. // Enable or disable overwriting of the kernel trace buffers. Disabling this
  299. // will cause tracing to stop once the trace buffers have filled up.
  300. static bool setTraceOverwriteEnable(bool enable)
  301. {
  302. return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
  303. }
  304. // Enable or disable kernel tracing.
  305. static bool setTracingEnabled(bool enable)
  306. {
  307. return setKernelOptionEnable(k_tracingOnPath, enable);
  308. }
  309. // Clear the contents of the kernel trace.
  310. static bool clearTrace()
  311. {
  312. return truncateFile(k_tracePath);
  313. }
  314. // Set the size of the kernel's trace buffer in kilobytes.
  315. static bool setTraceBufferSizeKB(int size)
  316. {
  317. char str[32] = "1";
  318. int len;
  319. if (size < 1) {
  320. size = 1;
  321. }
  322. snprintf(str, 32, "%d", size);
  323. return writeStr(k_traceBufferSizePath, str);
  324. }
  325. // Read the trace_clock sysfs file and return true if it matches the requested
  326. // value. The trace_clock file format is:
  327. // local [global] counter uptime perf
  328. static bool isTraceClock(const char *mode)
  329. {
  330. int fd = open(k_traceClockPath, O_RDONLY);
  331. if (fd == -1) {
  332. fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath,
  333. strerror(errno), errno);
  334. return false;
  335. }
  336. char buf[4097];
  337. ssize_t n = read(fd, buf, 4096);
  338. close(fd);
  339. if (n == -1) {
  340. fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath,
  341. strerror(errno), errno);
  342. return false;
  343. }
  344. buf[n] = '\0';
  345. char *start = strchr(buf, '[');
  346. if (start == NULL) {
  347. return false;
  348. }
  349. start++;
  350. char *end = strchr(start, ']');
  351. if (end == NULL) {
  352. return false;
  353. }
  354. *end = '\0';
  355. return strcmp(mode, start) == 0;
  356. }
  357. // Enable or disable the kernel's use of the global clock. Disabling the global
  358. // clock will result in the kernel using a per-CPU local clock.
  359. // Any write to the trace_clock sysfs file will reset the buffer, so only
  360. // update it if the requested value is not the current value.
  361. static bool setGlobalClockEnable(bool enable)
  362. {
  363. const char *clock = enable ? "global" : "local";
  364. if (isTraceClock(clock)) {
  365. return true;
  366. }
  367. return writeStr(k_traceClockPath, clock);
  368. }
  369. static bool setPrintTgidEnableIfPresent(bool enable)
  370. {
  371. if (fileExists(k_printTgidPath)) {
  372. return setKernelOptionEnable(k_printTgidPath, enable);
  373. }
  374. return true;
  375. }
  376. // Poke all the binder-enabled processes in the system to get them to re-read
  377. // their system properties.
  378. static bool pokeBinderServices()
  379. {
  380. sp<IServiceManager> sm = defaultServiceManager();
  381. Vector<String16> services = sm->listServices();
  382. for (size_t i = 0; i < services.size(); i++) {
  383. sp<IBinder> obj = sm->checkService(services[i]);
  384. if (obj != NULL) {
  385. Parcel data;
  386. if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data,
  387. NULL, 0) != OK) {
  388. if (false) {
  389. // XXX: For some reason this fails on tablets trying to
  390. // poke the "phone" service. It's not clear whether some
  391. // are expected to fail.
  392. String8 svc(services[i]);
  393. fprintf(stderr, "error poking binder service %s\n",
  394. svc.string());
  395. return false;
  396. }
  397. }
  398. }
  399. }
  400. return true;
  401. }
  402. // Set the trace tags that userland tracing uses, and poke the running
  403. // processes to pick up the new value.
  404. static bool setTagsProperty(uint64_t tags)
  405. {
  406. char buf[64];
  407. snprintf(buf, 64, "%#" PRIx64, tags);
  408. if (property_set(k_traceTagsProperty, buf) < 0) {
  409. fprintf(stderr, "error setting trace tags system property\n");
  410. return false;
  411. }
  412. return true;
  413. }
  414. // Set the system property that indicates which apps should perform
  415. // application-level tracing.
  416. static bool setAppCmdlineProperty(const char* cmdline)
  417. {
  418. if (property_set(k_traceAppCmdlineProperty, cmdline) < 0) {
  419. fprintf(stderr, "error setting trace app system property\n");
  420. return false;
  421. }
  422. return true;
  423. }
  424. // Disable all /sys/ enable files.
  425. static bool disableKernelTraceEvents() {
  426. bool ok = true;
  427. for (int i = 0; i < NELEM(k_categories); i++) {
  428. const TracingCategory &c = k_categories[i];
  429. for (int j = 0; j < MAX_SYS_FILES; j++) {
  430. const char* path = c.sysfiles[j].path;
  431. if (path != NULL && fileIsWritable(path)) {
  432. ok &= setKernelOptionEnable(path, false);
  433. }
  434. }
  435. }
  436. return ok;
  437. }
  438. // Verify that the comma separated list of functions are being traced by the
  439. // kernel.
  440. static bool verifyKernelTraceFuncs(const char* funcs)
  441. {
  442. int fd = open(k_ftraceFilterPath, O_RDONLY);
  443. if (fd == -1) {
  444. fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
  445. strerror(errno), errno);
  446. return false;
  447. }
  448. char buf[4097];
  449. ssize_t n = read(fd, buf, 4096);
  450. close(fd);
  451. if (n == -1) {
  452. fprintf(stderr, "error reading %s: %s (%d)\n", k_ftraceFilterPath,
  453. strerror(errno), errno);
  454. return false;
  455. }
  456. buf[n] = '\0';
  457. String8 funcList = String8::format("\n%s", buf);
  458. // Make sure that every function listed in funcs is in the list we just
  459. // read from the kernel.
  460. bool ok = true;
  461. char* myFuncs = strdup(funcs);
  462. char* func = strtok(myFuncs, ",");
  463. while (func) {
  464. String8 fancyFunc = String8::format("\n%s\n", func);
  465. bool found = funcList.find(fancyFunc.string(), 0) >= 0;
  466. if (!found || func[0] == '\0') {
  467. fprintf(stderr, "error: \"%s\" is not a valid kernel function "
  468. "to trace.\n", func);
  469. ok = false;
  470. }
  471. func = strtok(NULL, ",");
  472. }
  473. free(myFuncs);
  474. return ok;
  475. }
  476. // Set the comma separated list of functions that the kernel is to trace.
  477. static bool setKernelTraceFuncs(const char* funcs)
  478. {
  479. bool ok = true;
  480. if (funcs == NULL || funcs[0] == '\0') {
  481. // Disable kernel function tracing.
  482. if (fileIsWritable(k_currentTracerPath)) {
  483. ok &= writeStr(k_currentTracerPath, "nop");
  484. }
  485. if (fileIsWritable(k_ftraceFilterPath)) {
  486. ok &= truncateFile(k_ftraceFilterPath);
  487. }
  488. } else {
  489. // Enable kernel function tracing.
  490. ok &= writeStr(k_currentTracerPath, "function_graph");
  491. ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
  492. ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
  493. ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
  494. ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
  495. // Set the requested filter functions.
  496. ok &= truncateFile(k_ftraceFilterPath);
  497. char* myFuncs = strdup(funcs);
  498. char* func = strtok(myFuncs, ",");
  499. while (func) {
  500. ok &= appendStr(k_ftraceFilterPath, func);
  501. func = strtok(NULL, ",");
  502. }
  503. free(myFuncs);
  504. // Verify that the set functions are being traced.
  505. if (ok) {
  506. ok &= verifyKernelTraceFuncs(funcs);
  507. }
  508. }
  509. return ok;
  510. }
  511. // Set all the kernel tracing settings to the desired state for this trace
  512. // capture.
  513. static bool setUpTrace()
  514. {
  515. bool ok = true;
  516. // Set up the tracing options.
  517. ok &= setTraceOverwriteEnable(g_traceOverwrite);
  518. ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
  519. ok &= setGlobalClockEnable(true);
  520. ok &= setPrintTgidEnableIfPresent(true);
  521. ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
  522. // Set up the tags property.
  523. uint64_t tags = 0;
  524. for (int i = 0; i < NELEM(k_categories); i++) {
  525. if (g_categoryEnables[i]) {
  526. const TracingCategory &c = k_categories[i];
  527. tags |= c.tags;
  528. }
  529. }
  530. ok &= setTagsProperty(tags);
  531. ok &= setAppCmdlineProperty(g_debugAppCmdLine);
  532. ok &= pokeBinderServices();
  533. // Disable all the sysfs enables. This is done as a separate loop from
  534. // the enables to allow the same enable to exist in multiple categories.
  535. ok &= disableKernelTraceEvents();
  536. // Enable all the sysfs enables that are in an enabled category.
  537. for (int i = 0; i < NELEM(k_categories); i++) {
  538. if (g_categoryEnables[i]) {
  539. const TracingCategory &c = k_categories[i];
  540. for (int j = 0; j < MAX_SYS_FILES; j++) {
  541. const char* path = c.sysfiles[j].path;
  542. bool required = c.sysfiles[j].required == REQ;
  543. if (path != NULL) {
  544. if (fileIsWritable(path)) {
  545. ok &= setKernelOptionEnable(path, true);
  546. } else if (required) {
  547. fprintf(stderr, "error writing file %s\n", path);
  548. ok = false;
  549. }
  550. }
  551. }
  552. }
  553. }
  554. return ok;
  555. }
  556. // Reset all the kernel tracing settings to their default state.
  557. static void cleanUpTrace()
  558. {
  559. // Disable all tracing that we're able to.
  560. disableKernelTraceEvents();
  561. // Reset the system properties.
  562. setTagsProperty(0);
  563. setAppCmdlineProperty("");
  564. pokeBinderServices();
  565. // Set the options back to their defaults.
  566. setTraceOverwriteEnable(true);
  567. setTraceBufferSizeKB(1);
  568. setGlobalClockEnable(false);
  569. setPrintTgidEnableIfPresent(false);
  570. setKernelTraceFuncs(NULL);
  571. }
  572. // Enable tracing in the kernel.
  573. static bool startTrace()
  574. {
  575. return setTracingEnabled(true);
  576. }
  577. // Disable tracing in the kernel.
  578. static void stopTrace()
  579. {
  580. setTracingEnabled(false);
  581. }
  582. // Read the current kernel trace and write it to stdout.
  583. static void dumpTrace()
  584. {
  585. int traceFD = open(k_tracePath, O_RDWR);
  586. if (traceFD == -1) {
  587. fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
  588. strerror(errno), errno);
  589. return;
  590. }
  591. if (g_compress) {
  592. z_stream zs;
  593. uint8_t *in, *out;
  594. int result, flush;
  595. memset(&zs, 0, sizeof(zs));
  596. result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
  597. if (result != Z_OK) {
  598. fprintf(stderr, "error initializing zlib: %d\n", result);
  599. close(traceFD);
  600. return;
  601. }
  602. const size_t bufSize = 64*1024;
  603. in = (uint8_t*)malloc(bufSize);
  604. out = (uint8_t*)malloc(bufSize);
  605. flush = Z_NO_FLUSH;
  606. zs.next_out = out;
  607. zs.avail_out = bufSize;
  608. do {
  609. if (zs.avail_in == 0) {
  610. // More input is needed.
  611. result = read(traceFD, in, bufSize);
  612. if (result < 0) {
  613. fprintf(stderr, "error reading trace: %s (%d)\n",
  614. strerror(errno), errno);
  615. result = Z_STREAM_END;
  616. break;
  617. } else if (result == 0) {
  618. flush = Z_FINISH;
  619. } else {
  620. zs.next_in = in;
  621. zs.avail_in = result;
  622. }
  623. }
  624. if (zs.avail_out == 0) {
  625. // Need to write the output.
  626. result = write(STDOUT_FILENO, out, bufSize);
  627. if ((size_t)result < bufSize) {
  628. fprintf(stderr, "error writing deflated trace: %s (%d)\n",
  629. strerror(errno), errno);
  630. result = Z_STREAM_END; // skip deflate error message
  631. zs.avail_out = bufSize; // skip the final write
  632. break;
  633. }
  634. zs.next_out = out;
  635. zs.avail_out = bufSize;
  636. }
  637. } while ((result = deflate(&zs, flush)) == Z_OK);
  638. if (result != Z_STREAM_END) {
  639. fprintf(stderr, "error deflating trace: %s\n", zs.msg);
  640. }
  641. if (zs.avail_out < bufSize) {
  642. size_t bytes = bufSize - zs.avail_out;
  643. result = write(STDOUT_FILENO, out, bytes);
  644. if ((size_t)result < bytes) {
  645. fprintf(stderr, "error writing deflated trace: %s (%d)\n",
  646. strerror(errno), errno);
  647. }
  648. }
  649. result = deflateEnd(&zs);
  650. if (result != Z_OK) {
  651. fprintf(stderr, "error cleaning up zlib: %d\n", result);
  652. }
  653. free(in);
  654. free(out);
  655. } else {
  656. ssize_t sent = 0;
  657. while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
  658. if (sent == -1) {
  659. fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
  660. errno);
  661. }
  662. }
  663. close(traceFD);
  664. }
  665. static void handleSignal(int /*signo*/)
  666. {
  667. if (!g_nohup) {
  668. g_traceAborted = true;
  669. }
  670. }
  671. static void registerSigHandler()
  672. {
  673. struct sigaction sa;
  674. sigemptyset(&sa.sa_mask);
  675. sa.sa_flags = 0;
  676. sa.sa_handler = handleSignal;
  677. sigaction(SIGHUP, &sa, NULL);
  678. sigaction(SIGINT, &sa, NULL);
  679. sigaction(SIGQUIT, &sa, NULL);
  680. sigaction(SIGTERM, &sa, NULL);
  681. }
  682. static bool setCategoryEnable(const char* name, bool enable)
  683. {
  684. for (int i = 0; i < NELEM(k_categories); i++) {
  685. const TracingCategory& c = k_categories[i];
  686. if (strcmp(name, c.name) == 0) {
  687. if (isCategorySupported(c)) {
  688. g_categoryEnables[i] = enable;
  689. return true;
  690. } else {
  691. if (isCategorySupportedForRoot(c)) {
  692. fprintf(stderr, "error: category \"%s\" requires root "
  693. "privileges.\n", name);
  694. } else {
  695. fprintf(stderr, "error: category \"%s\" is not supported "
  696. "on this device.\n", name);
  697. }
  698. return false;
  699. }
  700. }
  701. }
  702. fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
  703. return false;
  704. }
  705. static void listSupportedCategories()
  706. {
  707. for (int i = 0; i < NELEM(k_categories); i++) {
  708. const TracingCategory& c = k_categories[i];
  709. if (isCategorySupported(c)) {
  710. printf(" %10s - %s\n", c.name, c.longname);
  711. }
  712. }
  713. }
  714. // Print the command usage help to stderr.
  715. static void showHelp(const char *cmd)
  716. {
  717. fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
  718. fprintf(stderr, "options include:\n"
  719. " -a appname enable app-level tracing for a comma "
  720. "separated list of cmdlines\n"
  721. " -b N use a trace buffer size of N KB\n"
  722. " -c trace into a circular buffer\n"
  723. " -k fname,... trace the listed kernel functions\n"
  724. " -n ignore signals\n"
  725. " -s N sleep for N seconds before tracing [default 0]\n"
  726. " -t N trace for N seconds [defualt 5]\n"
  727. " -z compress the trace dump\n"
  728. " --async_start start circular trace and return immediatly\n"
  729. " --async_dump dump the current contents of circular trace buffer\n"
  730. " --async_stop stop tracing and dump the current contents of circular\n"
  731. " trace buffer\n"
  732. " --list_categories\n"
  733. " list the available tracing categories\n"
  734. );
  735. }
  736. int main(int argc, char **argv)
  737. {
  738. bool async = false;
  739. bool traceStart = true;
  740. bool traceStop = true;
  741. bool traceDump = true;
  742. if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
  743. showHelp(argv[0]);
  744. exit(0);
  745. }
  746. for (;;) {
  747. int ret;
  748. int option_index = 0;
  749. static struct option long_options[] = {
  750. {"async_start", no_argument, 0, 0 },
  751. {"async_stop", no_argument, 0, 0 },
  752. {"async_dump", no_argument, 0, 0 },
  753. {"list_categories", no_argument, 0, 0 },
  754. { 0, 0, 0, 0 }
  755. };
  756. ret = getopt_long(argc, argv, "a:b:ck:ns:t:z",
  757. long_options, &option_index);
  758. if (ret < 0) {
  759. for (int i = optind; i < argc; i++) {
  760. if (!setCategoryEnable(argv[i], true)) {
  761. fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]);
  762. exit(1);
  763. }
  764. }
  765. break;
  766. }
  767. switch(ret) {
  768. case 'a':
  769. g_debugAppCmdLine = optarg;
  770. break;
  771. case 'b':
  772. g_traceBufferSizeKB = atoi(optarg);
  773. break;
  774. case 'c':
  775. g_traceOverwrite = true;
  776. break;
  777. case 'k':
  778. g_kernelTraceFuncs = optarg;
  779. break;
  780. case 'n':
  781. g_nohup = true;
  782. break;
  783. case 's':
  784. g_initialSleepSecs = atoi(optarg);
  785. break;
  786. case 't':
  787. g_traceDurationSeconds = atoi(optarg);
  788. break;
  789. case 'z':
  790. g_compress = true;
  791. break;
  792. case 0:
  793. if (!strcmp(long_options[option_index].name, "async_start")) {
  794. async = true;
  795. traceStop = false;
  796. traceDump = false;
  797. g_traceOverwrite = true;
  798. } else if (!strcmp(long_options[option_index].name, "async_stop")) {
  799. async = true;
  800. traceStart = false;
  801. } else if (!strcmp(long_options[option_index].name, "async_dump")) {
  802. async = true;
  803. traceStart = false;
  804. traceStop = false;
  805. } else if (!strcmp(long_options[option_index].name, "list_categories")) {
  806. listSupportedCategories();
  807. exit(0);
  808. }
  809. break;
  810. default:
  811. fprintf(stderr, "\n");
  812. showHelp(argv[0]);
  813. exit(-1);
  814. break;
  815. }
  816. }
  817. registerSigHandler();
  818. if (g_initialSleepSecs > 0) {
  819. sleep(g_initialSleepSecs);
  820. }
  821. bool ok = true;
  822. ok &= setUpTrace();
  823. ok &= startTrace();
  824. if (ok && traceStart) {
  825. printf("capturing trace...");
  826. fflush(stdout);
  827. // We clear the trace after starting it because tracing gets enabled for
  828. // each CPU individually in the kernel. Having the beginning of the trace
  829. // contain entries from only one CPU can cause "begin" entries without a
  830. // matching "end" entry to show up if a task gets migrated from one CPU to
  831. // another.
  832. ok = clearTrace();
  833. writeClockSyncMarker();
  834. if (ok && !async) {
  835. // Sleep to allow the trace to be captured.
  836. struct timespec timeLeft;
  837. timeLeft.tv_sec = g_traceDurationSeconds;
  838. timeLeft.tv_nsec = 0;
  839. do {
  840. if (g_traceAborted) {
  841. break;
  842. }
  843. } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
  844. }
  845. }
  846. // Stop the trace and restore the default settings.
  847. if (traceStop)
  848. stopTrace();
  849. if (ok && traceDump) {
  850. if (!g_traceAborted) {
  851. printf(" done\nTRACE:\n");
  852. fflush(stdout);
  853. dumpTrace();
  854. } else {
  855. printf("\ntrace aborted.\n");
  856. fflush(stdout);
  857. }
  858. clearTrace();
  859. } else if (!ok) {
  860. fprintf(stderr, "unable to start tracing\n");
  861. }
  862. // Reset the trace buffer size to 1.
  863. if (traceStop)
  864. cleanUpTrace();
  865. return g_traceAborted ? 1 : 0;
  866. }