xref: /aosp_15_r20/external/bcc/src/cc/bcc_perf_map.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) 2016 Facebook, Inc.
3*387f9dfdSAndroid Build Coastguard Worker  *
4*387f9dfdSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker  *
8*387f9dfdSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker  *
10*387f9dfdSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker  * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker  */
16*387f9dfdSAndroid Build Coastguard Worker #include <ctype.h>
17*387f9dfdSAndroid Build Coastguard Worker #include <errno.h>
18*387f9dfdSAndroid Build Coastguard Worker #include <limits.h>
19*387f9dfdSAndroid Build Coastguard Worker #include <stdio.h>
20*387f9dfdSAndroid Build Coastguard Worker #include <stdlib.h>
21*387f9dfdSAndroid Build Coastguard Worker #include <string.h>
22*387f9dfdSAndroid Build Coastguard Worker 
23*387f9dfdSAndroid Build Coastguard Worker #include "bcc_perf_map.h"
24*387f9dfdSAndroid Build Coastguard Worker 
bcc_is_perf_map(const char * path)25*387f9dfdSAndroid Build Coastguard Worker bool bcc_is_perf_map(const char *path) {
26*387f9dfdSAndroid Build Coastguard Worker   char* pos = strstr(path, ".map");
27*387f9dfdSAndroid Build Coastguard Worker   // Path ends with ".map"
28*387f9dfdSAndroid Build Coastguard Worker   return (pos != NULL) && (*(pos + 4)== 0);
29*387f9dfdSAndroid Build Coastguard Worker }
30*387f9dfdSAndroid Build Coastguard Worker 
bcc_is_valid_perf_map(const char * path)31*387f9dfdSAndroid Build Coastguard Worker bool bcc_is_valid_perf_map(const char *path) {
32*387f9dfdSAndroid Build Coastguard Worker   return bcc_is_perf_map(path) && (access(path, R_OK) == 0);
33*387f9dfdSAndroid Build Coastguard Worker }
34*387f9dfdSAndroid Build Coastguard Worker 
bcc_perf_map_nstgid(int pid)35*387f9dfdSAndroid Build Coastguard Worker int bcc_perf_map_nstgid(int pid) {
36*387f9dfdSAndroid Build Coastguard Worker   char status_path[64];
37*387f9dfdSAndroid Build Coastguard Worker   FILE *status;
38*387f9dfdSAndroid Build Coastguard Worker 
39*387f9dfdSAndroid Build Coastguard Worker   snprintf(status_path, sizeof(status_path), "/proc/%d/status", pid);
40*387f9dfdSAndroid Build Coastguard Worker   status = fopen(status_path, "r");
41*387f9dfdSAndroid Build Coastguard Worker 
42*387f9dfdSAndroid Build Coastguard Worker   if (!status)
43*387f9dfdSAndroid Build Coastguard Worker     return -1;
44*387f9dfdSAndroid Build Coastguard Worker 
45*387f9dfdSAndroid Build Coastguard Worker   // return the original PID if we fail to work out the TGID
46*387f9dfdSAndroid Build Coastguard Worker   int nstgid = pid;
47*387f9dfdSAndroid Build Coastguard Worker 
48*387f9dfdSAndroid Build Coastguard Worker   size_t size = 0;
49*387f9dfdSAndroid Build Coastguard Worker   char *line = NULL;
50*387f9dfdSAndroid Build Coastguard Worker   while (getline(&line, &size, status) != -1) {
51*387f9dfdSAndroid Build Coastguard Worker     // check Tgid line first in case CONFIG_PID_NS is off
52*387f9dfdSAndroid Build Coastguard Worker     if (strstr(line, "Tgid:") != NULL)
53*387f9dfdSAndroid Build Coastguard Worker       nstgid = (int)strtol(strrchr(line, '\t'), NULL, 10);
54*387f9dfdSAndroid Build Coastguard Worker     if (strstr(line, "NStgid:") != NULL)
55*387f9dfdSAndroid Build Coastguard Worker       // PID namespaces can be nested -- last number is innermost PID
56*387f9dfdSAndroid Build Coastguard Worker       nstgid = (int)strtol(strrchr(line, '\t'), NULL, 10);
57*387f9dfdSAndroid Build Coastguard Worker   }
58*387f9dfdSAndroid Build Coastguard Worker   free(line);
59*387f9dfdSAndroid Build Coastguard Worker   fclose(status);
60*387f9dfdSAndroid Build Coastguard Worker 
61*387f9dfdSAndroid Build Coastguard Worker   return nstgid;
62*387f9dfdSAndroid Build Coastguard Worker }
63*387f9dfdSAndroid Build Coastguard Worker 
bcc_perf_map_path(char * map_path,size_t map_len,int pid)64*387f9dfdSAndroid Build Coastguard Worker bool bcc_perf_map_path(char *map_path, size_t map_len, int pid) {
65*387f9dfdSAndroid Build Coastguard Worker   char source[64];
66*387f9dfdSAndroid Build Coastguard Worker   snprintf(source, sizeof(source), "/proc/%d/root", pid);
67*387f9dfdSAndroid Build Coastguard Worker 
68*387f9dfdSAndroid Build Coastguard Worker   char target[4096];
69*387f9dfdSAndroid Build Coastguard Worker   ssize_t target_len = readlink(source, target, sizeof(target) - 1);
70*387f9dfdSAndroid Build Coastguard Worker   if (target_len == -1)
71*387f9dfdSAndroid Build Coastguard Worker     return false;
72*387f9dfdSAndroid Build Coastguard Worker 
73*387f9dfdSAndroid Build Coastguard Worker   target[target_len] = '\0';
74*387f9dfdSAndroid Build Coastguard Worker   if (strcmp(target, "/") == 0)
75*387f9dfdSAndroid Build Coastguard Worker     target[0] = '\0';
76*387f9dfdSAndroid Build Coastguard Worker 
77*387f9dfdSAndroid Build Coastguard Worker   int nstgid = bcc_perf_map_nstgid(pid);
78*387f9dfdSAndroid Build Coastguard Worker 
79*387f9dfdSAndroid Build Coastguard Worker   snprintf(map_path, map_len, "%s/tmp/perf-%d.map", target, nstgid);
80*387f9dfdSAndroid Build Coastguard Worker   return true;
81*387f9dfdSAndroid Build Coastguard Worker }
82*387f9dfdSAndroid Build Coastguard Worker 
bcc_perf_map_foreach_sym(const char * path,bcc_perf_map_symcb callback,void * payload)83*387f9dfdSAndroid Build Coastguard Worker int bcc_perf_map_foreach_sym(const char *path, bcc_perf_map_symcb callback,
84*387f9dfdSAndroid Build Coastguard Worker                              void* payload) {
85*387f9dfdSAndroid Build Coastguard Worker   FILE* file = fopen(path, "r");
86*387f9dfdSAndroid Build Coastguard Worker   if (!file)
87*387f9dfdSAndroid Build Coastguard Worker     return -1;
88*387f9dfdSAndroid Build Coastguard Worker 
89*387f9dfdSAndroid Build Coastguard Worker   char *line = NULL;
90*387f9dfdSAndroid Build Coastguard Worker   size_t size = 0;
91*387f9dfdSAndroid Build Coastguard Worker   long long begin, len;
92*387f9dfdSAndroid Build Coastguard Worker   while (getline(&line, &size, file) != -1) {
93*387f9dfdSAndroid Build Coastguard Worker     char *cursor = line;
94*387f9dfdSAndroid Build Coastguard Worker     char *newline, *sep;
95*387f9dfdSAndroid Build Coastguard Worker 
96*387f9dfdSAndroid Build Coastguard Worker     begin = strtoull(cursor, &sep, 16);
97*387f9dfdSAndroid Build Coastguard Worker     if (begin == 0 || *sep != ' ' || (begin == ULLONG_MAX && errno == ERANGE))
98*387f9dfdSAndroid Build Coastguard Worker       continue;
99*387f9dfdSAndroid Build Coastguard Worker     cursor = sep;
100*387f9dfdSAndroid Build Coastguard Worker     while (*cursor && isspace(*cursor)) cursor++;
101*387f9dfdSAndroid Build Coastguard Worker 
102*387f9dfdSAndroid Build Coastguard Worker     len = strtoull(cursor, &sep, 16);
103*387f9dfdSAndroid Build Coastguard Worker     if (*sep != ' ' ||
104*387f9dfdSAndroid Build Coastguard Worker         (sep == cursor && len == 0) ||
105*387f9dfdSAndroid Build Coastguard Worker         (len == ULLONG_MAX && errno == ERANGE))
106*387f9dfdSAndroid Build Coastguard Worker       continue;
107*387f9dfdSAndroid Build Coastguard Worker     cursor = sep;
108*387f9dfdSAndroid Build Coastguard Worker     while (*cursor && isspace(*cursor)) cursor++;
109*387f9dfdSAndroid Build Coastguard Worker 
110*387f9dfdSAndroid Build Coastguard Worker     newline = strchr(cursor, '\n');
111*387f9dfdSAndroid Build Coastguard Worker     if (newline)
112*387f9dfdSAndroid Build Coastguard Worker         newline[0] = '\0';
113*387f9dfdSAndroid Build Coastguard Worker 
114*387f9dfdSAndroid Build Coastguard Worker     callback(cursor, begin, len, payload);
115*387f9dfdSAndroid Build Coastguard Worker   }
116*387f9dfdSAndroid Build Coastguard Worker 
117*387f9dfdSAndroid Build Coastguard Worker   free(line);
118*387f9dfdSAndroid Build Coastguard Worker   fclose(file);
119*387f9dfdSAndroid Build Coastguard Worker 
120*387f9dfdSAndroid Build Coastguard Worker   return 0;
121*387f9dfdSAndroid Build Coastguard Worker }
122