1 /* 2 * Copyright 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 <bpf_helpers.h> 18 #include <linux/bpf.h> 19 #include <stdbool.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 // TODO: import this struct from generic header, access registers via generic 25 // function 26 struct pt_regs { 27 unsigned long regs[16]; 28 unsigned long pc; 29 unsigned long pr; 30 unsigned long sr; 31 unsigned long gbr; 32 unsigned long mach; 33 unsigned long macl; 34 long tra; 35 }; 36 37 // TODO: share this struct between bpf and uprobestats 38 struct CallResult { 39 unsigned long pc; 40 unsigned long regs[10]; 41 }; 42 43 struct CallTimestamp { 44 unsigned int event; 45 unsigned long timestampNs; 46 }; 47 48 DEFINE_BPF_RINGBUF_EXT(call_detail_buf, struct CallResult, 4096, 49 AID_UPROBESTATS, AID_UPROBESTATS, 0600, "", "", PRIVATE, 50 BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, LOAD_ON_ENG, 51 LOAD_ON_USER, LOAD_ON_USERDEBUG); 52 53 DEFINE_BPF_RINGBUF_EXT(call_timestamp_buf, struct CallTimestamp, 4096, 54 AID_UPROBESTATS, AID_UPROBESTATS, 0600, "", "", PRIVATE, 55 BPFLOADER_MIN_VER, BPFLOADER_MAX_VER, LOAD_ON_ENG, 56 LOAD_ON_USER, LOAD_ON_USERDEBUG); 57 58 DEFINE_BPF_PROG("uprobe/call_detail", AID_UPROBESTATS, AID_UPROBESTATS, 59 BPF_KPROBE11) 60 (struct pt_regs *ctx) { 61 struct CallResult result; 62 // for whatever reason, reading past register 10 causes bpf verifier to fail 63 for (int i = 0; i < 11; i++) { 64 result.regs[i] = ctx->regs[i]; 65 } 66 result.pc = ctx->pc; 67 struct CallResult *output = bpf_call_detail_buf_reserve(); 68 if (output == NULL) 69 return 1; 70 (*output) = result; 71 bpf_call_detail_buf_submit(output); 72 return 0; 73 } 74 75 DEFINE_BPF_PROG("uprobe/call_timestamp_1", AID_UPROBESTATS, AID_UPROBESTATS, 76 BPF_KPROBE1) 77 () { 78 struct CallTimestamp result; 79 result.event = 1; 80 result.timestampNs = bpf_ktime_get_ns(); 81 struct CallTimestamp *output = bpf_call_timestamp_buf_reserve(); 82 if (output == NULL) { 83 return 1; 84 } 85 (*output) = result; 86 bpf_call_timestamp_buf_submit(output); 87 return 0; 88 } 89 90 DEFINE_BPF_PROG("uprobe/call_timestamp_2", AID_UPROBESTATS, AID_UPROBESTATS, 91 BPF_KPROBE2) 92 () { 93 struct CallTimestamp result; 94 result.event = 2; 95 result.timestampNs = bpf_ktime_get_ns(); 96 struct CallTimestamp *output = bpf_call_timestamp_buf_reserve(); 97 if (output == NULL) { 98 return 1; 99 } 100 (*output) = result; 101 bpf_call_timestamp_buf_submit(output); 102 return 0; 103 } 104 105 DEFINE_BPF_PROG("uprobe/call_timestamp_3", AID_UPROBESTATS, AID_UPROBESTATS, 106 BPF_KPROBE3) 107 () { 108 struct CallTimestamp result; 109 result.event = 3; 110 result.timestampNs = bpf_ktime_get_ns(); 111 struct CallTimestamp *output = bpf_call_timestamp_buf_reserve(); 112 if (output == NULL) { 113 return 1; 114 } 115 (*output) = result; 116 bpf_call_timestamp_buf_submit(output); 117 return 0; 118 } 119 120 DEFINE_BPF_PROG("uprobe/call_timestamp_4", AID_UPROBESTATS, AID_UPROBESTATS, 121 BPF_KPROBE4) 122 () { 123 struct CallTimestamp result; 124 result.event = 4; 125 result.timestampNs = bpf_ktime_get_ns(); 126 struct CallTimestamp *output = bpf_call_timestamp_buf_reserve(); 127 if (output == NULL) { 128 return 1; 129 } 130 (*output) = result; 131 bpf_call_timestamp_buf_submit(output); 132 return 0; 133 } 134 135 DEFINE_BPF_PROG("uprobe/call_timestamp_5", AID_UPROBESTATS, AID_UPROBESTATS, 136 BPF_KPROBE5) 137 () { 138 struct CallTimestamp result; 139 result.event = 5; 140 result.timestampNs = bpf_ktime_get_ns(); 141 struct CallTimestamp *output = bpf_call_timestamp_buf_reserve(); 142 if (output == NULL) { 143 return 1; 144 } 145 (*output) = result; 146 bpf_call_timestamp_buf_submit(output); 147 return 0; 148 } 149 150 LICENSE("GPL"); 151