1 /*
2 * Copyright (C) 2023 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 "berberis/runtime_primitives/profiler_interface.h"
18
19 #include <fcntl.h>
20
21 #include "berberis/base/config_globals.h"
22 #include "berberis/base/format_buffer.h"
23 #include "berberis/base/gettid.h"
24 #include "berberis/base/scoped_errno.h"
25 #include "berberis/base/tracing.h"
26
27 namespace berberis {
28
29 namespace {
30
ProfilerOpenLogFile()31 int ProfilerOpenLogFile() {
32 auto env = GetProfilingConfig();
33 if (!env) {
34 TRACE("Profiling: None");
35 return -1;
36 }
37
38 auto app = GetAppPackageName();
39
40 if (strcmp(env, "1") == 0) {
41 // Special case - profile everything.
42 } else if (app) {
43 // Running an app - must match package name.
44 if (strcmp(app, env) != 0) {
45 TRACE("Profiling: Skipping: app %s doesn't match filter %s", app, env);
46 return -1;
47 }
48 } else if (auto exe = GetMainExecutableRealPath()) {
49 // Running a standalone program - must somehow match main executable path.
50 if (!strstr(exe, env)) {
51 TRACE("Profiling: Skipping: executable %s doesn't match filter %s", exe, env);
52 return -1;
53 }
54 } else {
55 // Running a unit test, or some other non-app, non-executable case.
56 return -1;
57 }
58
59 ScopedErrno scoped_errno;
60
61 char buf[160];
62
63 int pid = GetpidSyscall();
64 if (app) {
65 FormatBuffer(buf, sizeof(buf), "/data/data/%s/perf-%u.map", app, pid);
66 } else {
67 FormatBuffer(buf, sizeof(buf), "/data/local/tmp/perf-%u.map", pid);
68 }
69
70 int fd = open(buf, O_WRONLY | O_CREAT | O_CLOEXEC, S_IWUSR);
71 if (fd == -1) {
72 TRACE("Profiling Error: Failed to open map file %s", buf);
73 } else {
74 TRACE("Probfiling to %s", buf);
75 }
76 return fd;
77 }
78
79 } // namespace
80
ProfilerLogGeneratedCode(const void * start,size_t size,GuestAddr guest_start,size_t guest_size,const char * prefix)81 void ProfilerLogGeneratedCode(const void* start,
82 size_t size,
83 GuestAddr guest_start,
84 size_t guest_size,
85 const char* prefix) {
86 static int fd = ProfilerOpenLogFile();
87 if (fd == -1) {
88 return;
89 }
90
91 char buf[80];
92 // start size name
93 // TODO(b232598137): make name useful
94 size_t n = FormatBuffer(buf,
95 sizeof(buf),
96 "%p 0x%zx %s_jit_0x%lx+%zu\n",
97 start,
98 size,
99 prefix,
100 guest_start,
101 guest_size);
102 UNUSED(write(fd, buf, n));
103 }
104
105 } // namespace berberis
106