xref: /aosp_15_r20/external/bcc/src/cc/bcc_btf.cc (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker  * Copyright (c) 2019 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 
17*387f9dfdSAndroid Build Coastguard Worker #include "bcc_btf.h"
18*387f9dfdSAndroid Build Coastguard Worker #include <stdarg.h>
19*387f9dfdSAndroid Build Coastguard Worker #include <string.h>
20*387f9dfdSAndroid Build Coastguard Worker #include "linux/btf.h"
21*387f9dfdSAndroid Build Coastguard Worker #include "libbpf.h"
22*387f9dfdSAndroid Build Coastguard Worker #include "bcc_libbpf_inc.h"
23*387f9dfdSAndroid Build Coastguard Worker #include <vector>
24*387f9dfdSAndroid Build Coastguard Worker #include <byteswap.h>
25*387f9dfdSAndroid Build Coastguard Worker 
26*387f9dfdSAndroid Build Coastguard Worker #define BCC_MAX_ERRNO       4095
27*387f9dfdSAndroid Build Coastguard Worker #define BCC_IS_ERR_VALUE(x) ((x) >= (unsigned long)-BCC_MAX_ERRNO)
28*387f9dfdSAndroid Build Coastguard Worker #define BCC_IS_ERR(ptr) BCC_IS_ERR_VALUE((unsigned long)ptr)
29*387f9dfdSAndroid Build Coastguard Worker #ifndef offsetofend
30*387f9dfdSAndroid Build Coastguard Worker # define offsetofend(TYPE, FIELD) \
31*387f9dfdSAndroid Build Coastguard Worker 	        (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
32*387f9dfdSAndroid Build Coastguard Worker #endif
33*387f9dfdSAndroid Build Coastguard Worker 
34*387f9dfdSAndroid Build Coastguard Worker namespace btf_ext_vendored {
35*387f9dfdSAndroid Build Coastguard Worker 
36*387f9dfdSAndroid Build Coastguard Worker /* The minimum bpf_func_info checked by the loader */
37*387f9dfdSAndroid Build Coastguard Worker struct bpf_func_info_min {
38*387f9dfdSAndroid Build Coastguard Worker         uint32_t   insn_off;
39*387f9dfdSAndroid Build Coastguard Worker         uint32_t   type_id;
40*387f9dfdSAndroid Build Coastguard Worker };
41*387f9dfdSAndroid Build Coastguard Worker 
42*387f9dfdSAndroid Build Coastguard Worker /* The minimum bpf_line_info checked by the loader */
43*387f9dfdSAndroid Build Coastguard Worker struct bpf_line_info_min {
44*387f9dfdSAndroid Build Coastguard Worker         uint32_t   insn_off;
45*387f9dfdSAndroid Build Coastguard Worker         uint32_t   file_name_off;
46*387f9dfdSAndroid Build Coastguard Worker         uint32_t   line_off;
47*387f9dfdSAndroid Build Coastguard Worker         uint32_t   line_col;
48*387f9dfdSAndroid Build Coastguard Worker };
49*387f9dfdSAndroid Build Coastguard Worker 
50*387f9dfdSAndroid Build Coastguard Worker struct btf_ext_sec_setup_param {
51*387f9dfdSAndroid Build Coastguard Worker         uint32_t off;
52*387f9dfdSAndroid Build Coastguard Worker         uint32_t len;
53*387f9dfdSAndroid Build Coastguard Worker         uint32_t min_rec_size;
54*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext_info *ext_info;
55*387f9dfdSAndroid Build Coastguard Worker         const char *desc;
56*387f9dfdSAndroid Build Coastguard Worker };
57*387f9dfdSAndroid Build Coastguard Worker 
btf_ext_setup_info(struct btf_ext * btf_ext,struct btf_ext_sec_setup_param * ext_sec)58*387f9dfdSAndroid Build Coastguard Worker static int btf_ext_setup_info(struct btf_ext *btf_ext,
59*387f9dfdSAndroid Build Coastguard Worker                               struct btf_ext_sec_setup_param *ext_sec)
60*387f9dfdSAndroid Build Coastguard Worker {
61*387f9dfdSAndroid Build Coastguard Worker         const struct btf_ext_info_sec *sinfo;
62*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext_info *ext_info;
63*387f9dfdSAndroid Build Coastguard Worker         uint32_t info_left, record_size;
64*387f9dfdSAndroid Build Coastguard Worker         /* The start of the info sec (including the __u32 record_size). */
65*387f9dfdSAndroid Build Coastguard Worker         void *info;
66*387f9dfdSAndroid Build Coastguard Worker 
67*387f9dfdSAndroid Build Coastguard Worker         if (ext_sec->len == 0)
68*387f9dfdSAndroid Build Coastguard Worker                 return 0;
69*387f9dfdSAndroid Build Coastguard Worker 
70*387f9dfdSAndroid Build Coastguard Worker         if (ext_sec->off & 0x03) {
71*387f9dfdSAndroid Build Coastguard Worker                 /*pr_debug(".BTF.ext %s section is not aligned to 4 bytes\n",
72*387f9dfdSAndroid Build Coastguard Worker                      ext_sec->desc);*/
73*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
74*387f9dfdSAndroid Build Coastguard Worker         }
75*387f9dfdSAndroid Build Coastguard Worker 
76*387f9dfdSAndroid Build Coastguard Worker         info = (uint8_t*)btf_ext->data + btf_ext->hdr->hdr_len + ext_sec->off;
77*387f9dfdSAndroid Build Coastguard Worker         info_left = ext_sec->len;
78*387f9dfdSAndroid Build Coastguard Worker 
79*387f9dfdSAndroid Build Coastguard Worker         if ((uint8_t*)btf_ext->data + btf_ext->data_size < (uint8_t*)info + ext_sec->len) {
80*387f9dfdSAndroid Build Coastguard Worker                 /*pr_debug("%s section (off:%u len:%u) is beyond the end of the ELF section .BTF.ext\n",
81*387f9dfdSAndroid Build Coastguard Worker                          ext_sec->desc, ext_sec->off, ext_sec->len);*/
82*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
83*387f9dfdSAndroid Build Coastguard Worker         }
84*387f9dfdSAndroid Build Coastguard Worker 
85*387f9dfdSAndroid Build Coastguard Worker         /* At least a record size */
86*387f9dfdSAndroid Build Coastguard Worker         if (info_left < sizeof(uint32_t)) {
87*387f9dfdSAndroid Build Coastguard Worker                 /*pr_debug(".BTF.ext %s record size not found\n", ext_sec->desc);*/
88*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
89*387f9dfdSAndroid Build Coastguard Worker         }
90*387f9dfdSAndroid Build Coastguard Worker 
91*387f9dfdSAndroid Build Coastguard Worker         /* The record size needs to meet the minimum standard */
92*387f9dfdSAndroid Build Coastguard Worker         record_size = *(uint32_t *)info;
93*387f9dfdSAndroid Build Coastguard Worker         if (record_size < ext_sec->min_rec_size ||
94*387f9dfdSAndroid Build Coastguard Worker             record_size & 0x03) {
95*387f9dfdSAndroid Build Coastguard Worker                 /*pr_debug("%s section in .BTF.ext has invalid record size %u\n",
96*387f9dfdSAndroid Build Coastguard Worker                          ext_sec->desc, record_size);*/
97*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
98*387f9dfdSAndroid Build Coastguard Worker         }
99*387f9dfdSAndroid Build Coastguard Worker 
100*387f9dfdSAndroid Build Coastguard Worker         sinfo = (struct btf_ext_info_sec*)((uint8_t*)info + sizeof(uint32_t));
101*387f9dfdSAndroid Build Coastguard Worker         info_left -= sizeof(uint32_t);
102*387f9dfdSAndroid Build Coastguard Worker 
103*387f9dfdSAndroid Build Coastguard Worker         /* If no records, return failure now so .BTF.ext won't be used. */
104*387f9dfdSAndroid Build Coastguard Worker         if (!info_left) {
105*387f9dfdSAndroid Build Coastguard Worker                 /*pr_debug("%s section in .BTF.ext has no records", ext_sec->desc);*/
106*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
107*387f9dfdSAndroid Build Coastguard Worker         }
108*387f9dfdSAndroid Build Coastguard Worker 
109*387f9dfdSAndroid Build Coastguard Worker         while (info_left) {
110*387f9dfdSAndroid Build Coastguard Worker                 unsigned int sec_hdrlen = sizeof(struct btf_ext_info_sec);
111*387f9dfdSAndroid Build Coastguard Worker                 uint64_t total_record_size;
112*387f9dfdSAndroid Build Coastguard Worker                 uint32_t num_records;
113*387f9dfdSAndroid Build Coastguard Worker 
114*387f9dfdSAndroid Build Coastguard Worker                 if (info_left < sec_hdrlen) {
115*387f9dfdSAndroid Build Coastguard Worker                         /*pr_debug("%s section header is not found in .BTF.ext\n",
116*387f9dfdSAndroid Build Coastguard Worker                              ext_sec->desc);*/
117*387f9dfdSAndroid Build Coastguard Worker                         return -EINVAL;
118*387f9dfdSAndroid Build Coastguard Worker                 }
119*387f9dfdSAndroid Build Coastguard Worker 
120*387f9dfdSAndroid Build Coastguard Worker                 num_records = sinfo->num_info;
121*387f9dfdSAndroid Build Coastguard Worker                 if (num_records == 0) {
122*387f9dfdSAndroid Build Coastguard Worker                         /*pr_debug("%s section has incorrect num_records in .BTF.ext\n",
123*387f9dfdSAndroid Build Coastguard Worker                              ext_sec->desc);*/
124*387f9dfdSAndroid Build Coastguard Worker                         return -EINVAL;
125*387f9dfdSAndroid Build Coastguard Worker                 }
126*387f9dfdSAndroid Build Coastguard Worker 
127*387f9dfdSAndroid Build Coastguard Worker                 total_record_size = sec_hdrlen +
128*387f9dfdSAndroid Build Coastguard Worker                                     (uint64_t)num_records * record_size;
129*387f9dfdSAndroid Build Coastguard Worker                 if (info_left < total_record_size) {
130*387f9dfdSAndroid Build Coastguard Worker                         /*pr_debug("%s section has incorrect num_records in .BTF.ext\n",
131*387f9dfdSAndroid Build Coastguard Worker                              ext_sec->desc);*/
132*387f9dfdSAndroid Build Coastguard Worker                         return -EINVAL;
133*387f9dfdSAndroid Build Coastguard Worker                 }
134*387f9dfdSAndroid Build Coastguard Worker 
135*387f9dfdSAndroid Build Coastguard Worker                 info_left -= total_record_size;
136*387f9dfdSAndroid Build Coastguard Worker                 sinfo = (struct btf_ext_info_sec *)((uint8_t*)sinfo + total_record_size);
137*387f9dfdSAndroid Build Coastguard Worker         }
138*387f9dfdSAndroid Build Coastguard Worker 
139*387f9dfdSAndroid Build Coastguard Worker         ext_info = ext_sec->ext_info;
140*387f9dfdSAndroid Build Coastguard Worker         ext_info->len = ext_sec->len - sizeof(uint32_t);
141*387f9dfdSAndroid Build Coastguard Worker         ext_info->rec_size = record_size;
142*387f9dfdSAndroid Build Coastguard Worker         ext_info->info = (uint8_t*)info + sizeof(uint32_t);
143*387f9dfdSAndroid Build Coastguard Worker 
144*387f9dfdSAndroid Build Coastguard Worker         return 0;
145*387f9dfdSAndroid Build Coastguard Worker }
146*387f9dfdSAndroid Build Coastguard Worker 
btf_ext_setup_func_info(struct btf_ext * btf_ext)147*387f9dfdSAndroid Build Coastguard Worker static int btf_ext_setup_func_info(struct btf_ext *btf_ext)
148*387f9dfdSAndroid Build Coastguard Worker {
149*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext_sec_setup_param param = {
150*387f9dfdSAndroid Build Coastguard Worker                 .off = btf_ext->hdr->func_info_off,
151*387f9dfdSAndroid Build Coastguard Worker                 .len = btf_ext->hdr->func_info_len,
152*387f9dfdSAndroid Build Coastguard Worker                 .min_rec_size = sizeof(struct bpf_func_info_min),
153*387f9dfdSAndroid Build Coastguard Worker                 .ext_info = &btf_ext->func_info,
154*387f9dfdSAndroid Build Coastguard Worker                 .desc = "func_info"
155*387f9dfdSAndroid Build Coastguard Worker         };
156*387f9dfdSAndroid Build Coastguard Worker 
157*387f9dfdSAndroid Build Coastguard Worker         return btf_ext_setup_info(btf_ext, &param);
158*387f9dfdSAndroid Build Coastguard Worker }
159*387f9dfdSAndroid Build Coastguard Worker 
btf_ext_setup_line_info(struct btf_ext * btf_ext)160*387f9dfdSAndroid Build Coastguard Worker static int btf_ext_setup_line_info(struct btf_ext *btf_ext)
161*387f9dfdSAndroid Build Coastguard Worker {
162*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext_sec_setup_param param = {
163*387f9dfdSAndroid Build Coastguard Worker                 .off = btf_ext->hdr->line_info_off,
164*387f9dfdSAndroid Build Coastguard Worker                 .len = btf_ext->hdr->line_info_len,
165*387f9dfdSAndroid Build Coastguard Worker                 .min_rec_size = sizeof(struct bpf_line_info_min),
166*387f9dfdSAndroid Build Coastguard Worker                 .ext_info = &btf_ext->line_info,
167*387f9dfdSAndroid Build Coastguard Worker                 .desc = "line_info",
168*387f9dfdSAndroid Build Coastguard Worker         };
169*387f9dfdSAndroid Build Coastguard Worker 
170*387f9dfdSAndroid Build Coastguard Worker         return btf_ext_setup_info(btf_ext, &param);
171*387f9dfdSAndroid Build Coastguard Worker }
172*387f9dfdSAndroid Build Coastguard Worker 
btf_ext_setup_core_relos(struct btf_ext * btf_ext)173*387f9dfdSAndroid Build Coastguard Worker static int btf_ext_setup_core_relos(struct btf_ext *btf_ext)
174*387f9dfdSAndroid Build Coastguard Worker {
175*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext_sec_setup_param param = {
176*387f9dfdSAndroid Build Coastguard Worker                 .off = btf_ext->hdr->core_relo_off,
177*387f9dfdSAndroid Build Coastguard Worker                 .len = btf_ext->hdr->core_relo_len,
178*387f9dfdSAndroid Build Coastguard Worker                 .min_rec_size = sizeof(struct bpf_core_relo),
179*387f9dfdSAndroid Build Coastguard Worker                 .ext_info = &btf_ext->core_relo_info,
180*387f9dfdSAndroid Build Coastguard Worker                 .desc = "core_relo",
181*387f9dfdSAndroid Build Coastguard Worker         };
182*387f9dfdSAndroid Build Coastguard Worker 
183*387f9dfdSAndroid Build Coastguard Worker         return btf_ext_setup_info(btf_ext, &param);
184*387f9dfdSAndroid Build Coastguard Worker }
185*387f9dfdSAndroid Build Coastguard Worker 
btf_ext_parse_hdr(uint8_t * data,uint32_t data_size)186*387f9dfdSAndroid Build Coastguard Worker static int btf_ext_parse_hdr(uint8_t *data, uint32_t data_size)
187*387f9dfdSAndroid Build Coastguard Worker {
188*387f9dfdSAndroid Build Coastguard Worker         const struct btf_ext_header *hdr = (struct btf_ext_header *)data;
189*387f9dfdSAndroid Build Coastguard Worker 
190*387f9dfdSAndroid Build Coastguard Worker         if (data_size < offsetofend(struct btf_ext_header, hdr_len) ||
191*387f9dfdSAndroid Build Coastguard Worker             data_size < hdr->hdr_len) {
192*387f9dfdSAndroid Build Coastguard Worker                 //pr_debug("BTF.ext header not found");
193*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
194*387f9dfdSAndroid Build Coastguard Worker         }
195*387f9dfdSAndroid Build Coastguard Worker 
196*387f9dfdSAndroid Build Coastguard Worker         if (hdr->magic == bswap_16(BTF_MAGIC)) {
197*387f9dfdSAndroid Build Coastguard Worker                 //pr_warn("BTF.ext in non-native endianness is not supported\n");
198*387f9dfdSAndroid Build Coastguard Worker                 return -ENOTSUP;
199*387f9dfdSAndroid Build Coastguard Worker         } else if (hdr->magic != BTF_MAGIC) {
200*387f9dfdSAndroid Build Coastguard Worker                 //pr_debug("Invalid BTF.ext magic:%x\n", hdr->magic);
201*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
202*387f9dfdSAndroid Build Coastguard Worker         }
203*387f9dfdSAndroid Build Coastguard Worker 
204*387f9dfdSAndroid Build Coastguard Worker         if (hdr->version != BTF_VERSION) {
205*387f9dfdSAndroid Build Coastguard Worker                 //pr_debug("Unsupported BTF.ext version:%u\n", hdr->version);
206*387f9dfdSAndroid Build Coastguard Worker                 return -ENOTSUP;
207*387f9dfdSAndroid Build Coastguard Worker         }
208*387f9dfdSAndroid Build Coastguard Worker 
209*387f9dfdSAndroid Build Coastguard Worker         if (hdr->flags) {
210*387f9dfdSAndroid Build Coastguard Worker                 //pr_debug("Unsupported BTF.ext flags:%x\n", hdr->flags);
211*387f9dfdSAndroid Build Coastguard Worker                 return -ENOTSUP;
212*387f9dfdSAndroid Build Coastguard Worker         }
213*387f9dfdSAndroid Build Coastguard Worker 
214*387f9dfdSAndroid Build Coastguard Worker         if (data_size == hdr->hdr_len) {
215*387f9dfdSAndroid Build Coastguard Worker                 //pr_debug("BTF.ext has no data\n");
216*387f9dfdSAndroid Build Coastguard Worker                 return -EINVAL;
217*387f9dfdSAndroid Build Coastguard Worker         }
218*387f9dfdSAndroid Build Coastguard Worker 
219*387f9dfdSAndroid Build Coastguard Worker         return 0;
220*387f9dfdSAndroid Build Coastguard Worker }
221*387f9dfdSAndroid Build Coastguard Worker 
btf_ext__free(struct btf_ext * btf_ext)222*387f9dfdSAndroid Build Coastguard Worker void btf_ext__free(struct btf_ext *btf_ext)
223*387f9dfdSAndroid Build Coastguard Worker {
224*387f9dfdSAndroid Build Coastguard Worker 	if((!btf_ext) || BCC_IS_ERR_VALUE((unsigned long)btf_ext))
225*387f9dfdSAndroid Build Coastguard Worker                 return;
226*387f9dfdSAndroid Build Coastguard Worker         free(btf_ext->data);
227*387f9dfdSAndroid Build Coastguard Worker         free(btf_ext);
228*387f9dfdSAndroid Build Coastguard Worker }
229*387f9dfdSAndroid Build Coastguard Worker 
btf_ext__new(const uint8_t * data,uint32_t size)230*387f9dfdSAndroid Build Coastguard Worker struct btf_ext *btf_ext__new(const uint8_t *data, uint32_t size)
231*387f9dfdSAndroid Build Coastguard Worker {
232*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext *btf_ext;
233*387f9dfdSAndroid Build Coastguard Worker         int err;
234*387f9dfdSAndroid Build Coastguard Worker 
235*387f9dfdSAndroid Build Coastguard Worker         btf_ext = (struct btf_ext*)calloc(1, sizeof(struct btf_ext));
236*387f9dfdSAndroid Build Coastguard Worker         if (!btf_ext)
237*387f9dfdSAndroid Build Coastguard Worker                 return (struct btf_ext*)-ENOMEM;
238*387f9dfdSAndroid Build Coastguard Worker 
239*387f9dfdSAndroid Build Coastguard Worker         btf_ext->data_size = size;
240*387f9dfdSAndroid Build Coastguard Worker         btf_ext->data = malloc(size);
241*387f9dfdSAndroid Build Coastguard Worker         if (!btf_ext->data) {
242*387f9dfdSAndroid Build Coastguard Worker                 err = -ENOMEM;
243*387f9dfdSAndroid Build Coastguard Worker                 goto done;
244*387f9dfdSAndroid Build Coastguard Worker         }
245*387f9dfdSAndroid Build Coastguard Worker         memcpy(btf_ext->data, data, size);
246*387f9dfdSAndroid Build Coastguard Worker 
247*387f9dfdSAndroid Build Coastguard Worker         err = btf_ext_parse_hdr((uint8_t*)btf_ext->data, size);
248*387f9dfdSAndroid Build Coastguard Worker         if (err)
249*387f9dfdSAndroid Build Coastguard Worker                 goto done;
250*387f9dfdSAndroid Build Coastguard Worker 
251*387f9dfdSAndroid Build Coastguard Worker         if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, line_info_len)) {
252*387f9dfdSAndroid Build Coastguard Worker                 err = -EINVAL;
253*387f9dfdSAndroid Build Coastguard Worker                 goto done;
254*387f9dfdSAndroid Build Coastguard Worker         }
255*387f9dfdSAndroid Build Coastguard Worker 
256*387f9dfdSAndroid Build Coastguard Worker         err = btf_ext_setup_func_info(btf_ext);
257*387f9dfdSAndroid Build Coastguard Worker         if (err)
258*387f9dfdSAndroid Build Coastguard Worker                 goto done;
259*387f9dfdSAndroid Build Coastguard Worker 
260*387f9dfdSAndroid Build Coastguard Worker         err = btf_ext_setup_line_info(btf_ext);
261*387f9dfdSAndroid Build Coastguard Worker         if (err)
262*387f9dfdSAndroid Build Coastguard Worker                 goto done;
263*387f9dfdSAndroid Build Coastguard Worker 
264*387f9dfdSAndroid Build Coastguard Worker         if (btf_ext->hdr->hdr_len < offsetofend(struct btf_ext_header, core_relo_len)) {
265*387f9dfdSAndroid Build Coastguard Worker                 err = -EINVAL;
266*387f9dfdSAndroid Build Coastguard Worker                 goto done;
267*387f9dfdSAndroid Build Coastguard Worker         }
268*387f9dfdSAndroid Build Coastguard Worker 
269*387f9dfdSAndroid Build Coastguard Worker         err = btf_ext_setup_core_relos(btf_ext);
270*387f9dfdSAndroid Build Coastguard Worker         if (err)
271*387f9dfdSAndroid Build Coastguard Worker                 goto done;
272*387f9dfdSAndroid Build Coastguard Worker 
273*387f9dfdSAndroid Build Coastguard Worker done:
274*387f9dfdSAndroid Build Coastguard Worker         if (err) {
275*387f9dfdSAndroid Build Coastguard Worker                 btf_ext__free(btf_ext);
276*387f9dfdSAndroid Build Coastguard Worker                 return (struct btf_ext*)(uintptr_t)err;
277*387f9dfdSAndroid Build Coastguard Worker         }
278*387f9dfdSAndroid Build Coastguard Worker 
279*387f9dfdSAndroid Build Coastguard Worker         return btf_ext;
280*387f9dfdSAndroid Build Coastguard Worker }
281*387f9dfdSAndroid Build Coastguard Worker 
btf_ext_reloc_info(const struct btf * btf,const struct btf_ext_info * ext_info,const char * sec_name,uint32_t insns_cnt,void ** info,uint32_t * cnt)282*387f9dfdSAndroid Build Coastguard Worker static int btf_ext_reloc_info(const struct btf *btf,
283*387f9dfdSAndroid Build Coastguard Worker                               const struct btf_ext_info *ext_info,
284*387f9dfdSAndroid Build Coastguard Worker                               const char *sec_name, uint32_t insns_cnt,
285*387f9dfdSAndroid Build Coastguard Worker                               void **info, uint32_t *cnt)
286*387f9dfdSAndroid Build Coastguard Worker {
287*387f9dfdSAndroid Build Coastguard Worker         uint32_t sec_hdrlen = sizeof(struct btf_ext_info_sec);
288*387f9dfdSAndroid Build Coastguard Worker         uint32_t i, record_size, existing_len, records_len;
289*387f9dfdSAndroid Build Coastguard Worker         struct btf_ext_info_sec *sinfo;
290*387f9dfdSAndroid Build Coastguard Worker         const char *info_sec_name;
291*387f9dfdSAndroid Build Coastguard Worker         uint64_t remain_len;
292*387f9dfdSAndroid Build Coastguard Worker         void *data;
293*387f9dfdSAndroid Build Coastguard Worker 
294*387f9dfdSAndroid Build Coastguard Worker         record_size = ext_info->rec_size;
295*387f9dfdSAndroid Build Coastguard Worker         sinfo = (struct btf_ext_info_sec*)ext_info->info;
296*387f9dfdSAndroid Build Coastguard Worker         remain_len = ext_info->len;
297*387f9dfdSAndroid Build Coastguard Worker         while (remain_len > 0) {
298*387f9dfdSAndroid Build Coastguard Worker                 records_len = sinfo->num_info * record_size;
299*387f9dfdSAndroid Build Coastguard Worker                 info_sec_name = btf__name_by_offset(btf, sinfo->sec_name_off);
300*387f9dfdSAndroid Build Coastguard Worker                 if (strcmp(info_sec_name, sec_name)) {
301*387f9dfdSAndroid Build Coastguard Worker                         remain_len -= sec_hdrlen + records_len;
302*387f9dfdSAndroid Build Coastguard Worker                         sinfo = (struct btf_ext_info_sec*)((uint8_t *)sinfo + sec_hdrlen + records_len);
303*387f9dfdSAndroid Build Coastguard Worker                         continue;
304*387f9dfdSAndroid Build Coastguard Worker                 }
305*387f9dfdSAndroid Build Coastguard Worker 
306*387f9dfdSAndroid Build Coastguard Worker                 existing_len = (*cnt) * record_size;
307*387f9dfdSAndroid Build Coastguard Worker                 data = realloc(*info, existing_len + records_len);
308*387f9dfdSAndroid Build Coastguard Worker                 if (!data)
309*387f9dfdSAndroid Build Coastguard Worker                         return -ENOMEM;
310*387f9dfdSAndroid Build Coastguard Worker 
311*387f9dfdSAndroid Build Coastguard Worker                 memcpy((uint8_t*)data + existing_len, sinfo->data, records_len);
312*387f9dfdSAndroid Build Coastguard Worker                 /* adjust insn_off only, the rest data will be passed
313*387f9dfdSAndroid Build Coastguard Worker                  * to the kernel.
314*387f9dfdSAndroid Build Coastguard Worker                  */
315*387f9dfdSAndroid Build Coastguard Worker                 for (i = 0; i < sinfo->num_info; i++) {
316*387f9dfdSAndroid Build Coastguard Worker                         uint32_t *insn_off;
317*387f9dfdSAndroid Build Coastguard Worker 
318*387f9dfdSAndroid Build Coastguard Worker                         insn_off = (uint32_t *)((uint8_t*)data + existing_len + (i * record_size));
319*387f9dfdSAndroid Build Coastguard Worker                         *insn_off = *insn_off / sizeof(struct bpf_insn) + insns_cnt;
320*387f9dfdSAndroid Build Coastguard Worker                 }
321*387f9dfdSAndroid Build Coastguard Worker                 *info = data;
322*387f9dfdSAndroid Build Coastguard Worker                 *cnt += sinfo->num_info;
323*387f9dfdSAndroid Build Coastguard Worker                 return 0;
324*387f9dfdSAndroid Build Coastguard Worker         }
325*387f9dfdSAndroid Build Coastguard Worker 
326*387f9dfdSAndroid Build Coastguard Worker         return -ENOENT;
327*387f9dfdSAndroid Build Coastguard Worker }
328*387f9dfdSAndroid Build Coastguard Worker 
btf_ext__reloc_func_info(const struct btf * btf,const struct btf_ext * btf_ext,const char * sec_name,uint32_t insns_cnt,void ** func_info,uint32_t * cnt)329*387f9dfdSAndroid Build Coastguard Worker int btf_ext__reloc_func_info(const struct btf *btf,
330*387f9dfdSAndroid Build Coastguard Worker                              const struct btf_ext *btf_ext,
331*387f9dfdSAndroid Build Coastguard Worker                              const char *sec_name, uint32_t insns_cnt,
332*387f9dfdSAndroid Build Coastguard Worker                              void **func_info, uint32_t *cnt)
333*387f9dfdSAndroid Build Coastguard Worker {
334*387f9dfdSAndroid Build Coastguard Worker         return btf_ext_vendored::btf_ext_reloc_info(btf, &btf_ext->func_info, sec_name,
335*387f9dfdSAndroid Build Coastguard Worker                                   insns_cnt, func_info, cnt);
336*387f9dfdSAndroid Build Coastguard Worker }
337*387f9dfdSAndroid Build Coastguard Worker 
btf_ext__reloc_line_info(const struct btf * btf,const struct btf_ext * btf_ext,const char * sec_name,uint32_t insns_cnt,void ** line_info,uint32_t * cnt)338*387f9dfdSAndroid Build Coastguard Worker int btf_ext__reloc_line_info(const struct btf *btf,
339*387f9dfdSAndroid Build Coastguard Worker                              const struct btf_ext *btf_ext,
340*387f9dfdSAndroid Build Coastguard Worker                              const char *sec_name, uint32_t insns_cnt,
341*387f9dfdSAndroid Build Coastguard Worker                              void **line_info, uint32_t *cnt)
342*387f9dfdSAndroid Build Coastguard Worker {
343*387f9dfdSAndroid Build Coastguard Worker         return btf_ext_vendored::btf_ext_reloc_info(btf, &btf_ext->line_info, sec_name,
344*387f9dfdSAndroid Build Coastguard Worker                                   insns_cnt, line_info, cnt);
345*387f9dfdSAndroid Build Coastguard Worker }
346*387f9dfdSAndroid Build Coastguard Worker 
347*387f9dfdSAndroid Build Coastguard Worker } // namespace btf_ext_vendored
348*387f9dfdSAndroid Build Coastguard Worker 
349*387f9dfdSAndroid Build Coastguard Worker namespace ebpf {
350*387f9dfdSAndroid Build Coastguard Worker 
addString(std::string S)351*387f9dfdSAndroid Build Coastguard Worker int32_t BTFStringTable::addString(std::string S) {
352*387f9dfdSAndroid Build Coastguard Worker   // Check whether the string already exists.
353*387f9dfdSAndroid Build Coastguard Worker   for (auto &OffsetM : OffsetToIdMap) {
354*387f9dfdSAndroid Build Coastguard Worker     if (Table[OffsetM.second] == S)
355*387f9dfdSAndroid Build Coastguard Worker       return OffsetM.first;
356*387f9dfdSAndroid Build Coastguard Worker   }
357*387f9dfdSAndroid Build Coastguard Worker 
358*387f9dfdSAndroid Build Coastguard Worker   // Make sure we do not overflow the string table.
359*387f9dfdSAndroid Build Coastguard Worker   if (OrigTblLen + Size + S.size() + 1 >= BTF_MAX_NAME_OFFSET)
360*387f9dfdSAndroid Build Coastguard Worker     return -1;
361*387f9dfdSAndroid Build Coastguard Worker 
362*387f9dfdSAndroid Build Coastguard Worker   // Not find, add to the string table.
363*387f9dfdSAndroid Build Coastguard Worker   uint32_t Offset = Size;
364*387f9dfdSAndroid Build Coastguard Worker   OffsetToIdMap[Offset] = Table.size();
365*387f9dfdSAndroid Build Coastguard Worker   Table.push_back(S);
366*387f9dfdSAndroid Build Coastguard Worker   Size += S.size() + 1;
367*387f9dfdSAndroid Build Coastguard Worker   return Offset;
368*387f9dfdSAndroid Build Coastguard Worker }
369*387f9dfdSAndroid Build Coastguard Worker 
BTF(bool debug,sec_map_def & sections)370*387f9dfdSAndroid Build Coastguard Worker BTF::BTF(bool debug, sec_map_def &sections) : debug_(debug),
371*387f9dfdSAndroid Build Coastguard Worker     btf_(nullptr), btf_ext_(nullptr), sections_(sections) {
372*387f9dfdSAndroid Build Coastguard Worker   if (!debug)
373*387f9dfdSAndroid Build Coastguard Worker     libbpf_set_print(NULL);
374*387f9dfdSAndroid Build Coastguard Worker }
375*387f9dfdSAndroid Build Coastguard Worker 
~BTF()376*387f9dfdSAndroid Build Coastguard Worker BTF::~BTF() {
377*387f9dfdSAndroid Build Coastguard Worker   btf__free(btf_);
378*387f9dfdSAndroid Build Coastguard Worker   btf_ext__free(btf_ext_);
379*387f9dfdSAndroid Build Coastguard Worker }
380*387f9dfdSAndroid Build Coastguard Worker 
warning(const char * format,...)381*387f9dfdSAndroid Build Coastguard Worker void BTF::warning(const char *format, ...) {
382*387f9dfdSAndroid Build Coastguard Worker   va_list args;
383*387f9dfdSAndroid Build Coastguard Worker 
384*387f9dfdSAndroid Build Coastguard Worker   if (!debug_)
385*387f9dfdSAndroid Build Coastguard Worker     return;
386*387f9dfdSAndroid Build Coastguard Worker 
387*387f9dfdSAndroid Build Coastguard Worker   va_start(args, format);
388*387f9dfdSAndroid Build Coastguard Worker   vfprintf(stderr, format, args);
389*387f9dfdSAndroid Build Coastguard Worker   va_end(args);
390*387f9dfdSAndroid Build Coastguard Worker }
391*387f9dfdSAndroid Build Coastguard Worker 
fixup_btf(uint8_t * type_sec,uintptr_t type_sec_size,char * strings)392*387f9dfdSAndroid Build Coastguard Worker void BTF::fixup_btf(uint8_t *type_sec, uintptr_t type_sec_size,
393*387f9dfdSAndroid Build Coastguard Worker                     char *strings) {
394*387f9dfdSAndroid Build Coastguard Worker   uint8_t *next_type = type_sec;
395*387f9dfdSAndroid Build Coastguard Worker   uint8_t *end_type = type_sec + type_sec_size;
396*387f9dfdSAndroid Build Coastguard Worker   int base_size = sizeof(struct btf_type);
397*387f9dfdSAndroid Build Coastguard Worker 
398*387f9dfdSAndroid Build Coastguard Worker   while (next_type < end_type) {
399*387f9dfdSAndroid Build Coastguard Worker     struct btf_type *t = (struct btf_type *)next_type;
400*387f9dfdSAndroid Build Coastguard Worker     unsigned short vlen = BTF_INFO_VLEN(t->info);
401*387f9dfdSAndroid Build Coastguard Worker 
402*387f9dfdSAndroid Build Coastguard Worker     next_type += base_size;
403*387f9dfdSAndroid Build Coastguard Worker 
404*387f9dfdSAndroid Build Coastguard Worker     switch(BTF_INFO_KIND(t->info)) {
405*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_FWD:
406*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_CONST:
407*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_VOLATILE:
408*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_RESTRICT:
409*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_PTR:
410*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_TYPEDEF:
411*387f9dfdSAndroid Build Coastguard Worker       break;
412*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_FUNC:
413*387f9dfdSAndroid Build Coastguard Worker       // sanitize vlen to be 0 since bcc does not
414*387f9dfdSAndroid Build Coastguard Worker       // care about func scope (static, global, extern) yet.
415*387f9dfdSAndroid Build Coastguard Worker       t->info &= ~0xffff;
416*387f9dfdSAndroid Build Coastguard Worker       break;
417*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_INT:
418*387f9dfdSAndroid Build Coastguard Worker       next_type += sizeof(uint32_t);
419*387f9dfdSAndroid Build Coastguard Worker       break;
420*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_ENUM:
421*387f9dfdSAndroid Build Coastguard Worker       next_type += vlen * sizeof(struct btf_enum);
422*387f9dfdSAndroid Build Coastguard Worker       break;
423*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_ARRAY:
424*387f9dfdSAndroid Build Coastguard Worker       next_type += sizeof(struct btf_array);
425*387f9dfdSAndroid Build Coastguard Worker       break;
426*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_STRUCT:
427*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_UNION:
428*387f9dfdSAndroid Build Coastguard Worker       next_type += vlen * sizeof(struct btf_member);
429*387f9dfdSAndroid Build Coastguard Worker       break;
430*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_FUNC_PROTO:
431*387f9dfdSAndroid Build Coastguard Worker       next_type += vlen * sizeof(struct btf_param);
432*387f9dfdSAndroid Build Coastguard Worker       break;
433*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_VAR: {
434*387f9dfdSAndroid Build Coastguard Worker       // BTF_KIND_VAR is not used by bcc, so
435*387f9dfdSAndroid Build Coastguard Worker       // a sanitization to convert it to an int.
436*387f9dfdSAndroid Build Coastguard Worker       // One extra __u32 after btf_type.
437*387f9dfdSAndroid Build Coastguard Worker       if (sizeof(struct btf_var) == 4) {
438*387f9dfdSAndroid Build Coastguard Worker         t->name_off = 0;
439*387f9dfdSAndroid Build Coastguard Worker         t->info = BTF_KIND_INT << 24;
440*387f9dfdSAndroid Build Coastguard Worker         t->size = 4;
441*387f9dfdSAndroid Build Coastguard Worker 
442*387f9dfdSAndroid Build Coastguard Worker         unsigned *intp = (unsigned *)next_type;
443*387f9dfdSAndroid Build Coastguard Worker         *intp = BTF_INT_BITS(t->size << 3);
444*387f9dfdSAndroid Build Coastguard Worker       }
445*387f9dfdSAndroid Build Coastguard Worker 
446*387f9dfdSAndroid Build Coastguard Worker       next_type += sizeof(struct btf_var);
447*387f9dfdSAndroid Build Coastguard Worker       break;
448*387f9dfdSAndroid Build Coastguard Worker     }
449*387f9dfdSAndroid Build Coastguard Worker     case BTF_KIND_DATASEC: {
450*387f9dfdSAndroid Build Coastguard Worker       // bcc does not use BTF_KIND_DATASEC, so
451*387f9dfdSAndroid Build Coastguard Worker       // a sanitization here to convert it to a list
452*387f9dfdSAndroid Build Coastguard Worker       // of void pointers.
453*387f9dfdSAndroid Build Coastguard Worker       // btf_var_secinfo is 3 __u32's for each var.
454*387f9dfdSAndroid Build Coastguard Worker       if (sizeof(struct btf_var_secinfo) == 12) {
455*387f9dfdSAndroid Build Coastguard Worker         t->name_off = 0;
456*387f9dfdSAndroid Build Coastguard Worker         t->info = BTF_KIND_PTR << 24;
457*387f9dfdSAndroid Build Coastguard Worker         t->type = 0;
458*387f9dfdSAndroid Build Coastguard Worker 
459*387f9dfdSAndroid Build Coastguard Worker         struct btf_type *typep = (struct btf_type *)next_type;
460*387f9dfdSAndroid Build Coastguard Worker         for (int i = 0; i < vlen; i++) {
461*387f9dfdSAndroid Build Coastguard Worker           typep->name_off = 0;
462*387f9dfdSAndroid Build Coastguard Worker           typep->info = BTF_KIND_PTR << 24;
463*387f9dfdSAndroid Build Coastguard Worker           typep->type = 0;
464*387f9dfdSAndroid Build Coastguard Worker           typep++;
465*387f9dfdSAndroid Build Coastguard Worker         }
466*387f9dfdSAndroid Build Coastguard Worker       }
467*387f9dfdSAndroid Build Coastguard Worker 
468*387f9dfdSAndroid Build Coastguard Worker       next_type += vlen * sizeof(struct btf_var_secinfo);
469*387f9dfdSAndroid Build Coastguard Worker       break;
470*387f9dfdSAndroid Build Coastguard Worker     }
471*387f9dfdSAndroid Build Coastguard Worker     default:
472*387f9dfdSAndroid Build Coastguard Worker       // Something not understood
473*387f9dfdSAndroid Build Coastguard Worker       return;
474*387f9dfdSAndroid Build Coastguard Worker     }
475*387f9dfdSAndroid Build Coastguard Worker   }
476*387f9dfdSAndroid Build Coastguard Worker }
477*387f9dfdSAndroid Build Coastguard Worker 
478*387f9dfdSAndroid Build Coastguard Worker // The compiler doesn't have source code for remapped files.
479*387f9dfdSAndroid Build Coastguard Worker // So we modify .BTF and .BTF.ext sections here to add these
480*387f9dfdSAndroid Build Coastguard Worker // missing line source codes.
481*387f9dfdSAndroid Build Coastguard Worker // The .BTF and .BTF.ext ELF section specification can be
482*387f9dfdSAndroid Build Coastguard Worker // found at linux repo: linux/Documentation/bpf/btf.rst.
adjust(uint8_t * btf_sec,uintptr_t btf_sec_size,uint8_t * btf_ext_sec,uintptr_t btf_ext_sec_size,std::map<std::string,std::string> & remapped_sources,uint8_t ** new_btf_sec,uintptr_t * new_btf_sec_size)483*387f9dfdSAndroid Build Coastguard Worker void BTF::adjust(uint8_t *btf_sec, uintptr_t btf_sec_size,
484*387f9dfdSAndroid Build Coastguard Worker                  uint8_t *btf_ext_sec, uintptr_t btf_ext_sec_size,
485*387f9dfdSAndroid Build Coastguard Worker                  std::map<std::string, std::string> &remapped_sources,
486*387f9dfdSAndroid Build Coastguard Worker                  uint8_t **new_btf_sec, uintptr_t *new_btf_sec_size) {
487*387f9dfdSAndroid Build Coastguard Worker 
488*387f9dfdSAndroid Build Coastguard Worker   // Line cache for remapped files
489*387f9dfdSAndroid Build Coastguard Worker   std::map<std::string, std::vector<std::string>> LineCaches;
490*387f9dfdSAndroid Build Coastguard Worker   for (auto it = remapped_sources.begin(); it != remapped_sources.end(); ++it) {
491*387f9dfdSAndroid Build Coastguard Worker     size_t FileBufSize = it->second.size();
492*387f9dfdSAndroid Build Coastguard Worker     std::vector<std::string> LineCache;
493*387f9dfdSAndroid Build Coastguard Worker 
494*387f9dfdSAndroid Build Coastguard Worker     for (uint32_t start = 0, end = start; end < FileBufSize; end++) {
495*387f9dfdSAndroid Build Coastguard Worker       if (it->second[end] == '\n' || end == FileBufSize - 1 ||
496*387f9dfdSAndroid Build Coastguard Worker           (it->second[end] == '\r' && it->second[end + 1] == '\n')) {
497*387f9dfdSAndroid Build Coastguard Worker         // Not including the endline
498*387f9dfdSAndroid Build Coastguard Worker         LineCache.push_back(std::string(it->second.substr(start, end - start)));
499*387f9dfdSAndroid Build Coastguard Worker         if (it->second[end] == '\r')
500*387f9dfdSAndroid Build Coastguard Worker           end++;
501*387f9dfdSAndroid Build Coastguard Worker         start = end + 1;
502*387f9dfdSAndroid Build Coastguard Worker       }
503*387f9dfdSAndroid Build Coastguard Worker     }
504*387f9dfdSAndroid Build Coastguard Worker     LineCaches[it->first] = std::move(LineCache);
505*387f9dfdSAndroid Build Coastguard Worker   }
506*387f9dfdSAndroid Build Coastguard Worker 
507*387f9dfdSAndroid Build Coastguard Worker   struct btf_header *hdr = (struct btf_header *)btf_sec;
508*387f9dfdSAndroid Build Coastguard Worker   struct btf_ext_vendored::btf_ext_header *ehdr = (struct btf_ext_vendored::btf_ext_header *)btf_ext_sec;
509*387f9dfdSAndroid Build Coastguard Worker 
510*387f9dfdSAndroid Build Coastguard Worker   // Fixup btf for old kernels or kernel requirements.
511*387f9dfdSAndroid Build Coastguard Worker   fixup_btf(btf_sec + hdr->hdr_len + hdr->type_off, hdr->type_len,
512*387f9dfdSAndroid Build Coastguard Worker             (char *)(btf_sec + hdr->hdr_len + hdr->str_off));
513*387f9dfdSAndroid Build Coastguard Worker 
514*387f9dfdSAndroid Build Coastguard Worker   // Check the LineInfo table and add missing lines
515*387f9dfdSAndroid Build Coastguard Worker   char *strings = (char *)(btf_sec + hdr->hdr_len + hdr->str_off);
516*387f9dfdSAndroid Build Coastguard Worker   unsigned orig_strings_len = hdr->str_len;
517*387f9dfdSAndroid Build Coastguard Worker   unsigned *linfo_s = (unsigned *)(btf_ext_sec + ehdr->hdr_len + ehdr->line_info_off);
518*387f9dfdSAndroid Build Coastguard Worker   unsigned lrec_size = *linfo_s;
519*387f9dfdSAndroid Build Coastguard Worker   linfo_s++;
520*387f9dfdSAndroid Build Coastguard Worker   unsigned linfo_len = ehdr->line_info_len - 4;
521*387f9dfdSAndroid Build Coastguard Worker 
522*387f9dfdSAndroid Build Coastguard Worker   // Go through all line info. For any line number whose line is in the LineCaches,
523*387f9dfdSAndroid Build Coastguard Worker   // Correct the line_off and record the corresponding source line in BTFStringTable,
524*387f9dfdSAndroid Build Coastguard Worker   // which later will be merged into .BTF string section.
525*387f9dfdSAndroid Build Coastguard Worker   BTFStringTable new_strings(orig_strings_len);
526*387f9dfdSAndroid Build Coastguard Worker   bool overflow = false;
527*387f9dfdSAndroid Build Coastguard Worker   while (!overflow && linfo_len) {
528*387f9dfdSAndroid Build Coastguard Worker     unsigned num_recs = linfo_s[1];
529*387f9dfdSAndroid Build Coastguard Worker     linfo_s += 2;
530*387f9dfdSAndroid Build Coastguard Worker     for (unsigned i = 0; !overflow && i < num_recs; i++) {
531*387f9dfdSAndroid Build Coastguard Worker       struct bpf_line_info *linfo = (struct bpf_line_info *)linfo_s;
532*387f9dfdSAndroid Build Coastguard Worker       if (linfo->line_off == 0) {
533*387f9dfdSAndroid Build Coastguard Worker         for (auto it = LineCaches.begin(); it != LineCaches.end(); ++it) {
534*387f9dfdSAndroid Build Coastguard Worker           if (strcmp(strings + linfo->file_name_off, it->first.c_str()) == 0) {
535*387f9dfdSAndroid Build Coastguard Worker             unsigned line_num = BPF_LINE_INFO_LINE_NUM(linfo->line_col);
536*387f9dfdSAndroid Build Coastguard Worker             if (line_num > 0 && line_num <= it->second.size()) {
537*387f9dfdSAndroid Build Coastguard Worker                int offset = new_strings.addString(it->second[line_num - 1]);
538*387f9dfdSAndroid Build Coastguard Worker                if (offset < 0) {
539*387f9dfdSAndroid Build Coastguard Worker                  overflow = true;
540*387f9dfdSAndroid Build Coastguard Worker                  warning(".BTF string table overflowed, some lines missing\n");
541*387f9dfdSAndroid Build Coastguard Worker                  break;
542*387f9dfdSAndroid Build Coastguard Worker                }
543*387f9dfdSAndroid Build Coastguard Worker                linfo->line_off = orig_strings_len + offset;
544*387f9dfdSAndroid Build Coastguard Worker             }
545*387f9dfdSAndroid Build Coastguard Worker           }
546*387f9dfdSAndroid Build Coastguard Worker         }
547*387f9dfdSAndroid Build Coastguard Worker       }
548*387f9dfdSAndroid Build Coastguard Worker       linfo_s += lrec_size >> 2;
549*387f9dfdSAndroid Build Coastguard Worker     }
550*387f9dfdSAndroid Build Coastguard Worker     linfo_len -= 8 + num_recs * lrec_size;
551*387f9dfdSAndroid Build Coastguard Worker   }
552*387f9dfdSAndroid Build Coastguard Worker 
553*387f9dfdSAndroid Build Coastguard Worker   // If any new source lines need to be recorded, do not touch the original section,
554*387f9dfdSAndroid Build Coastguard Worker   // allocate a new section. The original section is allocated through llvm infra.
555*387f9dfdSAndroid Build Coastguard Worker   if (new_strings.getSize() > 0) {
556*387f9dfdSAndroid Build Coastguard Worker     // LLVM generated .BTF layout always has type_sec followed by str_sec without holes,
557*387f9dfdSAndroid Build Coastguard Worker     // so we can just append the new strings to the end and adjust str_sec size.
558*387f9dfdSAndroid Build Coastguard Worker     unsigned tmp_sec_size = btf_sec_size + new_strings.getSize();
559*387f9dfdSAndroid Build Coastguard Worker     uint8_t *tmp_sec = new uint8_t[tmp_sec_size];
560*387f9dfdSAndroid Build Coastguard Worker     memcpy(tmp_sec, btf_sec, btf_sec_size);
561*387f9dfdSAndroid Build Coastguard Worker 
562*387f9dfdSAndroid Build Coastguard Worker     struct btf_header *nhdr = (struct btf_header *)tmp_sec;
563*387f9dfdSAndroid Build Coastguard Worker     nhdr->str_len += new_strings.getSize();
564*387f9dfdSAndroid Build Coastguard Worker 
565*387f9dfdSAndroid Build Coastguard Worker     // Populate new strings to the string table.
566*387f9dfdSAndroid Build Coastguard Worker     uint8_t *new_str = tmp_sec + nhdr->hdr_len + nhdr->str_off + orig_strings_len;
567*387f9dfdSAndroid Build Coastguard Worker     std::vector<std::string> &Table = new_strings.getTable();
568*387f9dfdSAndroid Build Coastguard Worker     for (unsigned i = 0; i < Table.size(); i++) {
569*387f9dfdSAndroid Build Coastguard Worker       strcpy((char *)new_str, Table[i].c_str());
570*387f9dfdSAndroid Build Coastguard Worker       new_str += Table[i].size() + 1;
571*387f9dfdSAndroid Build Coastguard Worker     }
572*387f9dfdSAndroid Build Coastguard Worker 
573*387f9dfdSAndroid Build Coastguard Worker     *new_btf_sec = tmp_sec;
574*387f9dfdSAndroid Build Coastguard Worker     *new_btf_sec_size = tmp_sec_size;
575*387f9dfdSAndroid Build Coastguard Worker   }
576*387f9dfdSAndroid Build Coastguard Worker }
577*387f9dfdSAndroid Build Coastguard Worker 
load(uint8_t * btf_sec,uintptr_t btf_sec_size,uint8_t * btf_ext_sec,uintptr_t btf_ext_sec_size,std::map<std::string,std::string> & remapped_sources)578*387f9dfdSAndroid Build Coastguard Worker int BTF::load(uint8_t *btf_sec, uintptr_t btf_sec_size,
579*387f9dfdSAndroid Build Coastguard Worker               uint8_t *btf_ext_sec, uintptr_t btf_ext_sec_size,
580*387f9dfdSAndroid Build Coastguard Worker               std::map<std::string, std::string> &remapped_sources) {
581*387f9dfdSAndroid Build Coastguard Worker   struct btf *btf;
582*387f9dfdSAndroid Build Coastguard Worker   struct btf_ext_vendored::btf_ext *btf_ext;
583*387f9dfdSAndroid Build Coastguard Worker   uint8_t *new_btf_sec = NULL;
584*387f9dfdSAndroid Build Coastguard Worker   uintptr_t new_btf_sec_size = 0;
585*387f9dfdSAndroid Build Coastguard Worker 
586*387f9dfdSAndroid Build Coastguard Worker   adjust(btf_sec, btf_sec_size, btf_ext_sec, btf_ext_sec_size,
587*387f9dfdSAndroid Build Coastguard Worker          remapped_sources, &new_btf_sec, &new_btf_sec_size);
588*387f9dfdSAndroid Build Coastguard Worker 
589*387f9dfdSAndroid Build Coastguard Worker   if (new_btf_sec) {
590*387f9dfdSAndroid Build Coastguard Worker     btf = btf__new(new_btf_sec, new_btf_sec_size);
591*387f9dfdSAndroid Build Coastguard Worker     delete[] new_btf_sec;
592*387f9dfdSAndroid Build Coastguard Worker   } else {
593*387f9dfdSAndroid Build Coastguard Worker     btf = btf__new(btf_sec, btf_sec_size);
594*387f9dfdSAndroid Build Coastguard Worker   }
595*387f9dfdSAndroid Build Coastguard Worker   if (BCC_IS_ERR(btf)) {
596*387f9dfdSAndroid Build Coastguard Worker     warning("Processing .BTF section failed\n");
597*387f9dfdSAndroid Build Coastguard Worker     return -1;
598*387f9dfdSAndroid Build Coastguard Worker   }
599*387f9dfdSAndroid Build Coastguard Worker 
600*387f9dfdSAndroid Build Coastguard Worker   if (btf__load_into_kernel(btf)) {
601*387f9dfdSAndroid Build Coastguard Worker     btf__free(btf);
602*387f9dfdSAndroid Build Coastguard Worker     warning("Loading .BTF section failed\n");
603*387f9dfdSAndroid Build Coastguard Worker     return -1;
604*387f9dfdSAndroid Build Coastguard Worker   }
605*387f9dfdSAndroid Build Coastguard Worker 
606*387f9dfdSAndroid Build Coastguard Worker   btf_ext = btf_ext_vendored::btf_ext__new(btf_ext_sec, btf_ext_sec_size);
607*387f9dfdSAndroid Build Coastguard Worker   if (BCC_IS_ERR(btf_ext)) {
608*387f9dfdSAndroid Build Coastguard Worker     btf__free(btf);
609*387f9dfdSAndroid Build Coastguard Worker     warning("Processing .BTF.ext section failed\n");
610*387f9dfdSAndroid Build Coastguard Worker     return -1;
611*387f9dfdSAndroid Build Coastguard Worker   }
612*387f9dfdSAndroid Build Coastguard Worker 
613*387f9dfdSAndroid Build Coastguard Worker   btf_ = btf;
614*387f9dfdSAndroid Build Coastguard Worker   btf_ext_ = btf_ext;
615*387f9dfdSAndroid Build Coastguard Worker   return 0;
616*387f9dfdSAndroid Build Coastguard Worker }
617*387f9dfdSAndroid Build Coastguard Worker 
get_fd()618*387f9dfdSAndroid Build Coastguard Worker int BTF::get_fd() {
619*387f9dfdSAndroid Build Coastguard Worker   return btf__fd(btf_);
620*387f9dfdSAndroid Build Coastguard Worker }
621*387f9dfdSAndroid Build Coastguard Worker 
get_btf_info(const char * fname,void ** func_info,unsigned * func_info_cnt,unsigned * finfo_rec_size,void ** line_info,unsigned * line_info_cnt,unsigned * linfo_rec_size)622*387f9dfdSAndroid Build Coastguard Worker int BTF::get_btf_info(const char *fname,
623*387f9dfdSAndroid Build Coastguard Worker                       void **func_info, unsigned *func_info_cnt,
624*387f9dfdSAndroid Build Coastguard Worker                       unsigned *finfo_rec_size,
625*387f9dfdSAndroid Build Coastguard Worker                       void **line_info, unsigned *line_info_cnt,
626*387f9dfdSAndroid Build Coastguard Worker                       unsigned *linfo_rec_size) {
627*387f9dfdSAndroid Build Coastguard Worker   int ret;
628*387f9dfdSAndroid Build Coastguard Worker 
629*387f9dfdSAndroid Build Coastguard Worker   *func_info = *line_info = NULL;
630*387f9dfdSAndroid Build Coastguard Worker   *func_info_cnt = *line_info_cnt = 0;
631*387f9dfdSAndroid Build Coastguard Worker 
632*387f9dfdSAndroid Build Coastguard Worker   *finfo_rec_size = btf_ext_->func_info.rec_size;
633*387f9dfdSAndroid Build Coastguard Worker   *linfo_rec_size = btf_ext_->line_info.rec_size;
634*387f9dfdSAndroid Build Coastguard Worker 
635*387f9dfdSAndroid Build Coastguard Worker   ret = btf_ext_vendored::btf_ext__reloc_func_info(btf_, btf_ext_, fname, 0,
636*387f9dfdSAndroid Build Coastguard Worker         func_info, func_info_cnt);
637*387f9dfdSAndroid Build Coastguard Worker   if (ret) {
638*387f9dfdSAndroid Build Coastguard Worker     warning(".BTF.ext reloc func_info failed\n");
639*387f9dfdSAndroid Build Coastguard Worker     return ret;
640*387f9dfdSAndroid Build Coastguard Worker   }
641*387f9dfdSAndroid Build Coastguard Worker 
642*387f9dfdSAndroid Build Coastguard Worker   ret = btf_ext_vendored::btf_ext__reloc_line_info(btf_, btf_ext_, fname, 0,
643*387f9dfdSAndroid Build Coastguard Worker         line_info, line_info_cnt);
644*387f9dfdSAndroid Build Coastguard Worker   if (ret) {
645*387f9dfdSAndroid Build Coastguard Worker     warning(".BTF.ext reloc line_info failed\n");
646*387f9dfdSAndroid Build Coastguard Worker     return ret;
647*387f9dfdSAndroid Build Coastguard Worker   }
648*387f9dfdSAndroid Build Coastguard Worker 
649*387f9dfdSAndroid Build Coastguard Worker   return 0;
650*387f9dfdSAndroid Build Coastguard Worker }
651*387f9dfdSAndroid Build Coastguard Worker 
get_map_tids(std::string map_name,unsigned expected_ksize,unsigned expected_vsize,unsigned * key_tid,unsigned * value_tid)652*387f9dfdSAndroid Build Coastguard Worker int BTF::get_map_tids(std::string map_name,
653*387f9dfdSAndroid Build Coastguard Worker                       unsigned expected_ksize, unsigned expected_vsize,
654*387f9dfdSAndroid Build Coastguard Worker                       unsigned *key_tid, unsigned *value_tid) {
655*387f9dfdSAndroid Build Coastguard Worker   auto struct_name = "____btf_map_" + map_name;
656*387f9dfdSAndroid Build Coastguard Worker   auto type_id = btf__find_by_name_kind(btf_, struct_name.c_str(), BTF_KIND_STRUCT);
657*387f9dfdSAndroid Build Coastguard Worker   if (type_id < 0) {
658*387f9dfdSAndroid Build Coastguard Worker     warning("struct %s not found in BTF\n", struct_name.c_str());
659*387f9dfdSAndroid Build Coastguard Worker     return -1;
660*387f9dfdSAndroid Build Coastguard Worker   }
661*387f9dfdSAndroid Build Coastguard Worker 
662*387f9dfdSAndroid Build Coastguard Worker   auto struct_type = btf__type_by_id(btf_, type_id);
663*387f9dfdSAndroid Build Coastguard Worker   if (!struct_type || btf_vlen(struct_type) < 2) {
664*387f9dfdSAndroid Build Coastguard Worker     warning("struct %s is not a valid map struct\n", struct_name.c_str());
665*387f9dfdSAndroid Build Coastguard Worker     return -1;
666*387f9dfdSAndroid Build Coastguard Worker   }
667*387f9dfdSAndroid Build Coastguard Worker 
668*387f9dfdSAndroid Build Coastguard Worker   auto members = btf_members(struct_type);
669*387f9dfdSAndroid Build Coastguard Worker   auto key = members[0];
670*387f9dfdSAndroid Build Coastguard Worker   auto key_name = btf__name_by_offset(btf_, key.name_off);
671*387f9dfdSAndroid Build Coastguard Worker   if (strcmp(key_name, "key")) {
672*387f9dfdSAndroid Build Coastguard Worker     warning("'key' should be the first member\n");
673*387f9dfdSAndroid Build Coastguard Worker     return -1;
674*387f9dfdSAndroid Build Coastguard Worker   }
675*387f9dfdSAndroid Build Coastguard Worker   auto key_size = btf__resolve_size(btf_, key.type);
676*387f9dfdSAndroid Build Coastguard Worker   if (key_size != expected_ksize) {
677*387f9dfdSAndroid Build Coastguard Worker     warning("expect key size to be %d, got %d\n", expected_ksize, key_size);
678*387f9dfdSAndroid Build Coastguard Worker     return -1;
679*387f9dfdSAndroid Build Coastguard Worker   }
680*387f9dfdSAndroid Build Coastguard Worker   *key_tid = key.type;
681*387f9dfdSAndroid Build Coastguard Worker 
682*387f9dfdSAndroid Build Coastguard Worker   auto value = members[1];
683*387f9dfdSAndroid Build Coastguard Worker   auto value_name = btf__name_by_offset(btf_, value.name_off);
684*387f9dfdSAndroid Build Coastguard Worker   if (strcmp(value_name, "value")) {
685*387f9dfdSAndroid Build Coastguard Worker     warning("'value' should be the second member\n");
686*387f9dfdSAndroid Build Coastguard Worker     return -1;
687*387f9dfdSAndroid Build Coastguard Worker   }
688*387f9dfdSAndroid Build Coastguard Worker   auto value_size = btf__resolve_size(btf_, value.type);
689*387f9dfdSAndroid Build Coastguard Worker   if (value_size != expected_vsize) {
690*387f9dfdSAndroid Build Coastguard Worker     warning("expect value size to be %d, got %d\n", expected_vsize, value_size);
691*387f9dfdSAndroid Build Coastguard Worker     return -1;
692*387f9dfdSAndroid Build Coastguard Worker   }
693*387f9dfdSAndroid Build Coastguard Worker   *value_tid = value.type;
694*387f9dfdSAndroid Build Coastguard Worker 
695*387f9dfdSAndroid Build Coastguard Worker   return 0;
696*387f9dfdSAndroid Build Coastguard Worker }
697*387f9dfdSAndroid Build Coastguard Worker 
698*387f9dfdSAndroid Build Coastguard Worker } // namespace ebpf
699