• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 #include <time.h>
18 
19 #include <android-base/file.h>
20 #include <android-base/stringprintf.h>
21 
22 #include <wakelock/wakelock.h>
23 #include <include/simpleperf_profcollect.hpp>
24 
25 #include "ETMRecorder.h"
26 #include "command.h"
27 #include "event_attr.h"
28 #include "event_fd.h"
29 #include "event_type.h"
30 
31 using namespace simpleperf;
32 
HasDriverSupport()33 bool HasDriverSupport() {
34   bool result = ETMRecorder::GetInstance().IsETMDriverAvailable();
35   LOG(INFO) << "HasDriverSupport result " << result;
36   return result;
37 }
38 
HasDeviceSupport()39 bool HasDeviceSupport() {
40   auto result = ETMRecorder::GetInstance().CheckEtmSupport();
41   if (!result.ok()) {
42     LOG(INFO) << "HasDeviceSupport check failed: " << result.error();
43     return false;
44   }
45   const EventType* type = FindEventTypeByName("cs-etm", false);
46   if (type == nullptr) {
47     LOG(INFO) << "HasDeviceSupport check failed: no etm event";
48     return false;
49   }
50   bool ret = IsEventAttrSupported(CreateDefaultPerfEventAttr(*type), type->name);
51   LOG(INFO) << "HasDeviceSupport result " << ret;
52   return ret;
53 }
54 
Record(const char * event_name,const char * output,float duration,const char * binary_filter)55 bool Record(const char* event_name, const char* output, float duration, const char* binary_filter) {
56   LOG(INFO) << "Record " << event_name << ", duration " << duration << ", output " << output
57             << ", binary_filter " << binary_filter;
58   // The kernel may panic when trying to hibernate or hotplug CPUs while collecting
59   // ETM data. So get wakelock to keep the CPUs on.
60   auto wakelock = android::wakelock::WakeLock::tryGet("profcollectd");
61   if (!wakelock) {
62     LOG(ERROR) << "Record failed: Failed to request wakelock.";
63     return false;
64   }
65   auto recordCmd = CreateCommandInstance("record");
66   std::vector<std::string> args = {"-a",
67                                    "-e",
68                                    event_name,
69                                    "--duration",
70                                    std::to_string(duration),
71                                    "--decode-etm",
72                                    "--exclude-perf",
73                                    "--binary",
74                                    binary_filter,
75                                    "-o",
76                                    output};
77   bool result = recordCmd->Run(args);
78   LOG(INFO) << "Record result " << result;
79   return result;
80 }
81 
Inject(const char * traceInput,const char * profileOutput,const char * binary_filter)82 bool Inject(const char* traceInput, const char* profileOutput, const char* binary_filter) {
83   LOG(INFO) << "Inject traceInput " << traceInput << ", profileOutput " << profileOutput
84             << ", binary_filter " << binary_filter;
85   auto injectCmd = CreateCommandInstance("inject");
86   std::vector<std::string> args = {"-i",       traceInput,    "-o",       profileOutput,
87                                    "--output", "branch-list", "--binary", binary_filter};
88   bool result = injectCmd->Run(args);
89   LOG(INFO) << "Inject result " << result;
90   return result;
91 }
92 
93 static android::base::unique_fd log_fd;
94 static android::base::LogFunction saved_log_func;
95 
FileLogger(android::base::LogId id,android::base::LogSeverity severity,const char * tag,const char * file,unsigned int line,const char * message)96 static void FileLogger(android::base::LogId id, android::base::LogSeverity severity,
97                        const char* tag, const char* file, unsigned int line, const char* message) {
98   if (log_fd.ok()) {
99     static const char log_characters[] = "VDIWEFF";
100     char severity_char = log_characters[severity];
101     struct tm now;
102     time_t t = time(nullptr);
103     localtime_r(&t, &now);
104     char timestamp[32];
105     strftime(timestamp, sizeof(timestamp), "%m-%d %H:%M:%S", &now);
106     std::string s = android::base::StringPrintf("%s %c %s %s:%u] %s\n", tag, severity_char,
107                                                 timestamp, file, line, message);
108     WriteStringToFd(s, log_fd);
109   }
110   saved_log_func(id, severity, tag, file, line, message);
111 }
112 
SetLogFile(const char * filename)113 void SetLogFile(const char* filename) {
114   int fd = TEMP_FAILURE_RETRY(open(filename, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, 0600));
115   if (fd == -1) {
116     PLOG(ERROR) << "failed to open " << filename;
117     return;
118   }
119   log_fd.reset(fd);
120   saved_log_func = SetLogger(FileLogger);
121 }
122 
ResetLogFile()123 void ResetLogFile() {
124   log_fd.reset();
125   SetLogger(std::move(saved_log_func));
126 }
127