• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 #define LOG_TAG "uprobestats"
18 
19 #include "bpf.h"
20 
21 #include <BpfSyscallWrappers.h>
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <linux/perf_event.h>
25 
26 #include <string>
27 
28 #include "bpf/BpfRingbuf.h"
29 
pollRingBuf(const char * mapPath,int timeoutMs,size_t valueSize,void (* callback)(const void *,void *),void * cookie)30 int pollRingBuf(const char *mapPath, int timeoutMs, size_t valueSize,
31                 void (*callback)(const void *, void *), void *cookie) {
32   auto result = android::bpf::BpfRingbufSized::Create(mapPath, valueSize);
33   if (!result.ok()) {
34     return -1;
35   }
36   if (!result.value()->wait(timeoutMs)) {
37     return 0;
38   }
39   auto count = result.value()->ConsumeAll(
40       [&](const void *value) { callback(value, cookie); });
41   if (!count.ok()) {
42     LOG(ERROR) << "Failed to consume events from ring buffer. Error: "
43                << count.error().message();
44     return -2;
45   }
46   return count.value();
47 }
48 
49 const char *PMU_TYPE_FILE = "/sys/bus/event_source/devices/uprobe/type";
50 
bpfPerfEventOpen(const char * filename,int offset,int pid,const char * bpfProgramPath)51 int bpfPerfEventOpen(const char *filename, int offset, int pid,
52                      const char *bpfProgramPath) {
53   android::base::unique_fd bpfProgramFd(
54       android::bpf::retrieveProgram(bpfProgramPath));
55   if (bpfProgramFd < 0) {
56     LOG(ERROR) << "retrieveProgram failed";
57     return -1;
58   }
59   std::string typeStr;
60   if (!android::base::ReadFileToString(PMU_TYPE_FILE, &typeStr)) {
61     LOG(ERROR) << "Failed to open pmu type file";
62     return -1;
63   }
64   int pmu_type = (int)strtol(typeStr.c_str(), NULL, 10);
65   struct perf_event_attr attr = {};
66   attr.sample_period = 1;
67   attr.wakeup_events = 1;
68   attr.config2 = offset;
69   attr.size = sizeof(attr);
70   attr.type = pmu_type;
71   attr.config1 = android::bpf::ptr_to_u64((void *)filename);
72   attr.exclude_kernel = true;
73   int perfEventFd = syscall(__NR_perf_event_open, &attr, pid, /*cpu=*/-1,
74                             /* group_fd=*/-1, PERF_FLAG_FD_CLOEXEC);
75   if (perfEventFd < 0) {
76     LOG(ERROR) << "syscall(__NR_perf_event_open) failed. "
77                << "perfEventFd: " << perfEventFd << " "
78                << "error: " << strerror(errno);
79     return -1;
80   }
81   if (ioctl(perfEventFd, PERF_EVENT_IOC_SET_BPF, int(bpfProgramFd)) < 0) {
82     LOG(ERROR) << "PERF_EVENT_IOC_SET_BPF failed. " << strerror(errno);
83     return -1;
84   }
85   if (ioctl(perfEventFd, PERF_EVENT_IOC_ENABLE, 0) < 0) {
86     LOG(ERROR) << "PERF_EVENT_IOC_ENABLE failed. " << strerror(errno);
87     return -1;
88   }
89   return 0;
90 }
91