1*00c7fec1SAndroid Build Coastguard Worker/* 2*00c7fec1SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project 3*00c7fec1SAndroid Build Coastguard Worker * 4*00c7fec1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*00c7fec1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*00c7fec1SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*00c7fec1SAndroid Build Coastguard Worker * 8*00c7fec1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*00c7fec1SAndroid Build Coastguard Worker * 10*00c7fec1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*00c7fec1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*00c7fec1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*00c7fec1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*00c7fec1SAndroid Build Coastguard Worker * limitations under the License. 15*00c7fec1SAndroid Build Coastguard Worker */ 16*00c7fec1SAndroid Build Coastguard Worker 17*00c7fec1SAndroid Build Coastguard Worker#ifndef __TRACE_DEV_INC 18*00c7fec1SAndroid Build Coastguard Worker#define __TRACE_DEV_INC 19*00c7fec1SAndroid Build Coastguard Worker 20*00c7fec1SAndroid Build Coastguard Worker#define LOG_TAG "cutils-trace" 21*00c7fec1SAndroid Build Coastguard Worker 22*00c7fec1SAndroid Build Coastguard Worker#include <errno.h> 23*00c7fec1SAndroid Build Coastguard Worker#include <fcntl.h> 24*00c7fec1SAndroid Build Coastguard Worker#include <fnmatch.h> 25*00c7fec1SAndroid Build Coastguard Worker#include <limits.h> 26*00c7fec1SAndroid Build Coastguard Worker#include <pthread.h> 27*00c7fec1SAndroid Build Coastguard Worker#include <stdatomic.h> 28*00c7fec1SAndroid Build Coastguard Worker#include <stdlib.h> 29*00c7fec1SAndroid Build Coastguard Worker#include <string.h> 30*00c7fec1SAndroid Build Coastguard Worker#include <sys/types.h> 31*00c7fec1SAndroid Build Coastguard Worker 32*00c7fec1SAndroid Build Coastguard Worker#include <cutils/compiler.h> 33*00c7fec1SAndroid Build Coastguard Worker#include <cutils/properties.h> 34*00c7fec1SAndroid Build Coastguard Worker#include <cutils/trace.h> 35*00c7fec1SAndroid Build Coastguard Worker#include <log/log.h> 36*00c7fec1SAndroid Build Coastguard Worker#include <log/log_properties.h> 37*00c7fec1SAndroid Build Coastguard Worker 38*00c7fec1SAndroid Build Coastguard Worker#if defined(__BIONIC__) 39*00c7fec1SAndroid Build Coastguard Worker#include <sys/system_properties.h> 40*00c7fec1SAndroid Build Coastguard Worker#endif 41*00c7fec1SAndroid Build Coastguard Worker 42*00c7fec1SAndroid Build Coastguard Worker/** 43*00c7fec1SAndroid Build Coastguard Worker * Maximum size of a message that can be logged to the trace buffer. 44*00c7fec1SAndroid Build Coastguard Worker * Note this message includes a tag, the pid, and the string given as the name. 45*00c7fec1SAndroid Build Coastguard Worker * Names should be kept short to get the most use of the trace buffer. 46*00c7fec1SAndroid Build Coastguard Worker */ 47*00c7fec1SAndroid Build Coastguard Worker#define ATRACE_MESSAGE_LENGTH 1024 48*00c7fec1SAndroid Build Coastguard Worker 49*00c7fec1SAndroid Build Coastguard Workerconstexpr uint32_t kSeqNoNotInit = static_cast<uint32_t>(-1); 50*00c7fec1SAndroid Build Coastguard Worker 51*00c7fec1SAndroid Build Coastguard Workeratomic_bool atrace_is_ready = false; 52*00c7fec1SAndroid Build Coastguard Workerint atrace_marker_fd = -1; 53*00c7fec1SAndroid Build Coastguard Workeruint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY; 54*00c7fec1SAndroid Build Coastguard Workerstatic atomic_bool atrace_is_enabled = true; 55*00c7fec1SAndroid Build Coastguard Workerstatic pthread_mutex_t atrace_tags_mutex = PTHREAD_MUTEX_INITIALIZER; 56*00c7fec1SAndroid Build Coastguard Worker 57*00c7fec1SAndroid Build Coastguard Worker/** 58*00c7fec1SAndroid Build Coastguard Worker * Sequence number of debug.atrace.tags.enableflags the last time the enabled 59*00c7fec1SAndroid Build Coastguard Worker * tags were reloaded. 60*00c7fec1SAndroid Build Coastguard Worker **/ 61*00c7fec1SAndroid Build Coastguard Workerstatic _Atomic(uint32_t) last_sequence_number = kSeqNoNotInit; 62*00c7fec1SAndroid Build Coastguard Worker 63*00c7fec1SAndroid Build Coastguard Worker#if defined(__BIONIC__) 64*00c7fec1SAndroid Build Coastguard Worker// All zero prop_info that has a sequence number of 0. This is easier than 65*00c7fec1SAndroid Build Coastguard Worker// depending on implementation details of the property implementation. 66*00c7fec1SAndroid Build Coastguard Worker// 67*00c7fec1SAndroid Build Coastguard Worker// prop_info is static_assert-ed to be 96 bytes, which cannot change due to 68*00c7fec1SAndroid Build Coastguard Worker// ABI compatibility. 69*00c7fec1SAndroid Build Coastguard Workeralignas(uint64_t) static char empty_pi[96]; 70*00c7fec1SAndroid Build Coastguard Workerstatic const prop_info* atrace_property_info = reinterpret_cast<const prop_info*>(empty_pi); 71*00c7fec1SAndroid Build Coastguard Worker#endif 72*00c7fec1SAndroid Build Coastguard Worker 73*00c7fec1SAndroid Build Coastguard Worker/** 74*00c7fec1SAndroid Build Coastguard Worker * This is called when the sequence number of debug.atrace.tags.enableflags 75*00c7fec1SAndroid Build Coastguard Worker * changes and we need to reload the enabled tags. 76*00c7fec1SAndroid Build Coastguard Worker **/ 77*00c7fec1SAndroid Build Coastguard Workerstatic void atrace_seq_number_changed(uint32_t prev_seq_no, uint32_t seq_no); 78*00c7fec1SAndroid Build Coastguard Worker 79*00c7fec1SAndroid Build Coastguard Workervoid atrace_init() { 80*00c7fec1SAndroid Build Coastguard Worker#if defined(__BIONIC__) 81*00c7fec1SAndroid Build Coastguard Worker uint32_t seq_no = __system_property_serial(atrace_property_info); // Acquire semantics. 82*00c7fec1SAndroid Build Coastguard Worker#else 83*00c7fec1SAndroid Build Coastguard Worker uint32_t seq_no = 0; 84*00c7fec1SAndroid Build Coastguard Worker#endif 85*00c7fec1SAndroid Build Coastguard Worker uint32_t prev_seq_no = atomic_load_explicit(&last_sequence_number, memory_order_relaxed); 86*00c7fec1SAndroid Build Coastguard Worker if (CC_UNLIKELY(seq_no != prev_seq_no)) { 87*00c7fec1SAndroid Build Coastguard Worker atrace_seq_number_changed(prev_seq_no, seq_no); 88*00c7fec1SAndroid Build Coastguard Worker } 89*00c7fec1SAndroid Build Coastguard Worker} 90*00c7fec1SAndroid Build Coastguard Worker 91*00c7fec1SAndroid Build Coastguard Workeruint64_t atrace_get_enabled_tags() 92*00c7fec1SAndroid Build Coastguard Worker{ 93*00c7fec1SAndroid Build Coastguard Worker atrace_init(); 94*00c7fec1SAndroid Build Coastguard Worker return atrace_enabled_tags; 95*00c7fec1SAndroid Build Coastguard Worker} 96*00c7fec1SAndroid Build Coastguard Worker 97*00c7fec1SAndroid Build Coastguard Worker// Check whether the given command line matches one of the comma-separated 98*00c7fec1SAndroid Build Coastguard Worker// values listed in the app_cmdlines property. 99*00c7fec1SAndroid Build Coastguard Workerstatic bool atrace_is_cmdline_match(const char* cmdline) 100*00c7fec1SAndroid Build Coastguard Worker{ 101*00c7fec1SAndroid Build Coastguard Worker int count = property_get_int32("debug.atrace.app_number", 0); 102*00c7fec1SAndroid Build Coastguard Worker 103*00c7fec1SAndroid Build Coastguard Worker char buf[PROPERTY_KEY_MAX]; 104*00c7fec1SAndroid Build Coastguard Worker char value[PROPERTY_VALUE_MAX]; 105*00c7fec1SAndroid Build Coastguard Worker 106*00c7fec1SAndroid Build Coastguard Worker for (int i = 0; i < count; i++) { 107*00c7fec1SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "debug.atrace.app_%d", i); 108*00c7fec1SAndroid Build Coastguard Worker property_get(buf, value, ""); 109*00c7fec1SAndroid Build Coastguard Worker if (fnmatch(value, cmdline, FNM_NOESCAPE) == 0) { 110*00c7fec1SAndroid Build Coastguard Worker return true; 111*00c7fec1SAndroid Build Coastguard Worker } 112*00c7fec1SAndroid Build Coastguard Worker } 113*00c7fec1SAndroid Build Coastguard Worker 114*00c7fec1SAndroid Build Coastguard Worker return false; 115*00c7fec1SAndroid Build Coastguard Worker} 116*00c7fec1SAndroid Build Coastguard Worker 117*00c7fec1SAndroid Build Coastguard Worker// Determine whether application-level tracing is enabled for this process. 118*00c7fec1SAndroid Build Coastguard Workerstatic bool atrace_is_app_tracing_enabled() 119*00c7fec1SAndroid Build Coastguard Worker{ 120*00c7fec1SAndroid Build Coastguard Worker bool result = false; 121*00c7fec1SAndroid Build Coastguard Worker 122*00c7fec1SAndroid Build Coastguard Worker // Check whether tracing is enabled for this process. 123*00c7fec1SAndroid Build Coastguard Worker FILE * file = fopen("/proc/self/cmdline", "re"); 124*00c7fec1SAndroid Build Coastguard Worker if (file) { 125*00c7fec1SAndroid Build Coastguard Worker char cmdline[4096]; 126*00c7fec1SAndroid Build Coastguard Worker if (fgets(cmdline, sizeof(cmdline), file)) { 127*00c7fec1SAndroid Build Coastguard Worker result = atrace_is_cmdline_match(cmdline); 128*00c7fec1SAndroid Build Coastguard Worker } else { 129*00c7fec1SAndroid Build Coastguard Worker ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno); 130*00c7fec1SAndroid Build Coastguard Worker } 131*00c7fec1SAndroid Build Coastguard Worker fclose(file); 132*00c7fec1SAndroid Build Coastguard Worker } else { 133*00c7fec1SAndroid Build Coastguard Worker ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno), 134*00c7fec1SAndroid Build Coastguard Worker errno); 135*00c7fec1SAndroid Build Coastguard Worker } 136*00c7fec1SAndroid Build Coastguard Worker 137*00c7fec1SAndroid Build Coastguard Worker return result; 138*00c7fec1SAndroid Build Coastguard Worker} 139*00c7fec1SAndroid Build Coastguard Worker 140*00c7fec1SAndroid Build Coastguard Worker// Read the sysprop and return the value tags should be set to 141*00c7fec1SAndroid Build Coastguard Workerstatic uint64_t atrace_get_property() 142*00c7fec1SAndroid Build Coastguard Worker{ 143*00c7fec1SAndroid Build Coastguard Worker char value[PROPERTY_VALUE_MAX]; 144*00c7fec1SAndroid Build Coastguard Worker char *endptr; 145*00c7fec1SAndroid Build Coastguard Worker uint64_t tags; 146*00c7fec1SAndroid Build Coastguard Worker 147*00c7fec1SAndroid Build Coastguard Worker property_get("debug.atrace.tags.enableflags", value, "0"); 148*00c7fec1SAndroid Build Coastguard Worker errno = 0; 149*00c7fec1SAndroid Build Coastguard Worker tags = strtoull(value, &endptr, 0); 150*00c7fec1SAndroid Build Coastguard Worker if (value[0] == '\0' || *endptr != '\0') { 151*00c7fec1SAndroid Build Coastguard Worker ALOGE("Error parsing trace property: Not a number: %s", value); 152*00c7fec1SAndroid Build Coastguard Worker return 0; 153*00c7fec1SAndroid Build Coastguard Worker } else if (errno == ERANGE || tags == ULLONG_MAX) { 154*00c7fec1SAndroid Build Coastguard Worker ALOGE("Error parsing trace property: Number too large: %s", value); 155*00c7fec1SAndroid Build Coastguard Worker return 0; 156*00c7fec1SAndroid Build Coastguard Worker } 157*00c7fec1SAndroid Build Coastguard Worker 158*00c7fec1SAndroid Build Coastguard Worker // Only set the "app" tag if this process was selected for app-level debug 159*00c7fec1SAndroid Build Coastguard Worker // tracing. 160*00c7fec1SAndroid Build Coastguard Worker if (atrace_is_app_tracing_enabled()) { 161*00c7fec1SAndroid Build Coastguard Worker tags |= ATRACE_TAG_APP; 162*00c7fec1SAndroid Build Coastguard Worker } else { 163*00c7fec1SAndroid Build Coastguard Worker tags &= ~ATRACE_TAG_APP; 164*00c7fec1SAndroid Build Coastguard Worker } 165*00c7fec1SAndroid Build Coastguard Worker 166*00c7fec1SAndroid Build Coastguard Worker return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK; 167*00c7fec1SAndroid Build Coastguard Worker} 168*00c7fec1SAndroid Build Coastguard Worker 169*00c7fec1SAndroid Build Coastguard Worker// Update tags if tracing is ready. Useful as a sysprop change callback. 170*00c7fec1SAndroid Build Coastguard Workervoid atrace_update_tags() 171*00c7fec1SAndroid Build Coastguard Worker{ 172*00c7fec1SAndroid Build Coastguard Worker uint64_t tags; 173*00c7fec1SAndroid Build Coastguard Worker if (atomic_load_explicit(&atrace_is_enabled, memory_order_acquire)) { 174*00c7fec1SAndroid Build Coastguard Worker tags = atrace_get_property(); 175*00c7fec1SAndroid Build Coastguard Worker pthread_mutex_lock(&atrace_tags_mutex); 176*00c7fec1SAndroid Build Coastguard Worker atrace_enabled_tags = tags; 177*00c7fec1SAndroid Build Coastguard Worker pthread_mutex_unlock(&atrace_tags_mutex); 178*00c7fec1SAndroid Build Coastguard Worker } else { 179*00c7fec1SAndroid Build Coastguard Worker // Tracing is disabled for this process, so we simply don't 180*00c7fec1SAndroid Build Coastguard Worker // initialize the tags. 181*00c7fec1SAndroid Build Coastguard Worker pthread_mutex_lock(&atrace_tags_mutex); 182*00c7fec1SAndroid Build Coastguard Worker atrace_enabled_tags = ATRACE_TAG_NOT_READY; 183*00c7fec1SAndroid Build Coastguard Worker pthread_mutex_unlock(&atrace_tags_mutex); 184*00c7fec1SAndroid Build Coastguard Worker } 185*00c7fec1SAndroid Build Coastguard Worker} 186*00c7fec1SAndroid Build Coastguard Worker 187*00c7fec1SAndroid Build Coastguard Worker#define WRITE_MSG(format_begin, format_end, track_name, name, value) { \ 188*00c7fec1SAndroid Build Coastguard Worker char buf[ATRACE_MESSAGE_LENGTH] __attribute__((uninitialized)); \ 189*00c7fec1SAndroid Build Coastguard Worker const char* track_name_sep = track_name[0] != '\0' ? "|" : ""; \ 190*00c7fec1SAndroid Build Coastguard Worker int pid = getpid(); \ 191*00c7fec1SAndroid Build Coastguard Worker int len = snprintf(buf, sizeof(buf), format_begin "%s%s%s" format_end, pid, \ 192*00c7fec1SAndroid Build Coastguard Worker track_name, track_name_sep, name, value); \ 193*00c7fec1SAndroid Build Coastguard Worker if (len >= (int) sizeof(buf)) { \ 194*00c7fec1SAndroid Build Coastguard Worker int name_len = strlen(name) - (len - sizeof(buf)) - 1; \ 195*00c7fec1SAndroid Build Coastguard Worker /* Truncate the name to make the message fit. */ \ 196*00c7fec1SAndroid Build Coastguard Worker if (name_len > 0) { \ 197*00c7fec1SAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), format_begin "%s%s%.*s" format_end, pid, \ 198*00c7fec1SAndroid Build Coastguard Worker track_name, track_name_sep, name_len, name, value); \ 199*00c7fec1SAndroid Build Coastguard Worker } else { \ 200*00c7fec1SAndroid Build Coastguard Worker int track_name_len = 0; \ 201*00c7fec1SAndroid Build Coastguard Worker if (track_name[0] != '\0') { \ 202*00c7fec1SAndroid Build Coastguard Worker track_name_len = strlen(track_name) - (len - strlen(name) - sizeof(buf)) - 2; \ 203*00c7fec1SAndroid Build Coastguard Worker } \ 204*00c7fec1SAndroid Build Coastguard Worker if (track_name_len <= 0) { \ 205*00c7fec1SAndroid Build Coastguard Worker /* Data is still too long. Drop it. */ \ 206*00c7fec1SAndroid Build Coastguard Worker len = 0; \ 207*00c7fec1SAndroid Build Coastguard Worker } else { \ 208*00c7fec1SAndroid Build Coastguard Worker /* Truncate the trackName and name to make the message fit */ \ 209*00c7fec1SAndroid Build Coastguard Worker len = snprintf(buf, sizeof(buf), format_begin "%.*s|%.1s" format_end, pid, \ 210*00c7fec1SAndroid Build Coastguard Worker track_name_len, track_name, name, value); \ 211*00c7fec1SAndroid Build Coastguard Worker } \ 212*00c7fec1SAndroid Build Coastguard Worker } \ 213*00c7fec1SAndroid Build Coastguard Worker } \ 214*00c7fec1SAndroid Build Coastguard Worker if (len > 0) { \ 215*00c7fec1SAndroid Build Coastguard Worker write(atrace_marker_fd, buf, len); \ 216*00c7fec1SAndroid Build Coastguard Worker } \ 217*00c7fec1SAndroid Build Coastguard Worker} 218*00c7fec1SAndroid Build Coastguard Worker 219*00c7fec1SAndroid Build Coastguard Worker#endif // __TRACE_DEV_INC 220