• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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