1 /*
2  * Copyright 2016 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 #ifndef ART_COMPILER_JIT_JIT_LOGGER_H_
18 #define ART_COMPILER_JIT_JIT_LOGGER_H_
19 
20 #include <memory>
21 
22 #include "base/mutex.h"
23 #include "base/os.h"
24 #include "compiled_method.h"
25 
26 namespace art {
27 
28 class ArtMethod;
29 
30 namespace jit {
31 
32 //
33 // JitLogger supports two approaches of perf profiling.
34 //
35 // (1) perf-map:
36 //     The perf-map mechanism generates perf-PID.map file,
37 //     which provides simple "address, size, method_name" information to perf,
38 //     and allows perf to map samples in jit-code-cache to jitted method symbols.
39 //
40 //     Command line Example:
41 //       $ perf record dalvikvm -Xcompiler-option --generate-debug-info -cp <classpath> Test
42 //       $ perf report
43 //     NOTE:
44 //       - Make sure that the perf-PID.map file is available for 'perf report' tool to access,
45 //         so that jitted method can be displayed.
46 //
47 //
48 // (2) perf-inject:
49 //     The perf-inject mechansim generates jit-PID.dump file,
50 //     which provides rich informations about a jitted method.
51 //     It allows perf or other profiling tools to do advanced analysis on jitted code,
52 //     for example instruction level profiling.
53 //
54 //     Command line Example:
55 //       $ perf record -k mono dalvikvm -Xcompiler-option --generate-debug-info -cp <classpath> Test
56 //       $ perf inject -i perf.data -o perf.data.jitted
57 //       $ perf report -i perf.data.jitted
58 //       $ perf annotate -i perf.data.jitted
59 //     NOTE:
60 //       REQUIREMENTS
61 //       - The 'perf record -k mono' option requires 4.1 (or higher) Linux kernel.
62 //       - The 'perf inject' (generating jit ELF files feature) requires perf 4.6 (or higher).
63 //       PERF RECORD
64 //       - The '-k mono' option tells 'perf record' to use CLOCK_MONOTONIC clock during sampling;
65 //         which is required by 'perf inject', to make sure that both perf.data and jit-PID.dump
66 //         have unified clock source for timestamps.
67 //       PERF INJECT
68 //       - The 'perf inject' tool injects information from jit-PID.dump into perf.data file,
69 //         and generates small ELF files (jitted-TID-CODEID.so) for each jitted method.
70 //       - On Android devices, the jit-PID.dump file is generated in /data/misc/trace/ folder, and
71 //         such location is recorded in perf.data file.
72 //         The 'perf inject' tool is going to look for jit-PID.dump and generates small ELF files in
73 //         this /data/misc/trace/ folder.
74 //         Make sure that you have the read/write access to /data/misc/trace/ folder.
75 //       - On non-Android devices, the jit-PID.dump file is generated in /tmp/ folder, and
76 //         'perf inject' tool operates on this folder.
77 //         Make sure that you have the read/write access to /tmp/ folder.
78 //       - If you are executing 'perf inject' on non-Android devices (host), but perf.data and
79 //         jit-PID.dump files are adb-pulled from Android devices, make sure that there is a
80 //         /data/misc/trace/ folder on host, and jit-PID.dump file is copied to this folder.
81 //       - Currently 'perf inject' doesn't provide option to change the path for jit-PID.dump and
82 //         generated ELF files.
83 //       PERF ANNOTATE
84 //       - The 'perf annotate' tool displays assembly level profiling report.
85 //         Source code can also be displayed if the ELF file has debug symbols.
86 //       - Make sure above small ELF files are available for 'perf annotate' tool to access,
87 //         so that jitted code can be displayed in assembly view.
88 //
89 class JitLogger {
90  public:
JitLogger()91     JitLogger() : code_index_(0), marker_address_(nullptr) {}
92 
OpenLog()93     void OpenLog() {
94       OpenPerfMapLog();
95       OpenJitDumpLog();
96     }
97 
WriteLog(const void * ptr,size_t code_size,ArtMethod * method)98     void WriteLog(const void* ptr, size_t code_size, ArtMethod* method)
99         REQUIRES_SHARED(Locks::mutator_lock_) {
100       WritePerfMapLog(ptr, code_size, method);
101       WriteJitDumpLog(ptr, code_size, method);
102     }
103 
CloseLog()104     void CloseLog() {
105       ClosePerfMapLog();
106       CloseJitDumpLog();
107     }
108 
109  private:
110     // For perf-map profiling
111     void OpenPerfMapLog();
112     void WritePerfMapLog(const void* ptr, size_t code_size, ArtMethod* method)
113         REQUIRES_SHARED(Locks::mutator_lock_);
114     void ClosePerfMapLog();
115 
116     // For perf-inject profiling
117     void OpenJitDumpLog();
118     void WriteJitDumpLog(const void* ptr, size_t code_size, ArtMethod* method)
119         REQUIRES_SHARED(Locks::mutator_lock_);
120     void CloseJitDumpLog();
121 
122     void OpenMarkerFile();
123     void CloseMarkerFile();
124     void WriteJitDumpHeader();
125     void WriteJitDumpDebugInfo();
126 
127     std::unique_ptr<File> perf_file_;
128     std::unique_ptr<File> jit_dump_file_;
129     uint64_t code_index_;
130     void* marker_address_;
131 
132     DISALLOW_COPY_AND_ASSIGN(JitLogger);
133 };
134 
135 }  // namespace jit
136 }  // namespace art
137 
138 #endif  // ART_COMPILER_JIT_JIT_LOGGER_H_
139