1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 /* Copyright (c) 2018 Facebook */
9 #include "libbpf_internal.h"
11 /* make sure libbpf doesn't use kernel-only integer typedefs */
12 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
14 struct bpf_prog_linfo
{
16 void *raw_jited_linfo
;
17 __u32
*nr_jited_linfo_per_func
;
18 __u32
*jited_linfo_func_idx
;
25 static int dissect_jited_func(struct bpf_prog_linfo
*prog_linfo
,
26 const __u64
*ksym_func
, const __u32
*ksym_len
)
28 __u32 nr_jited_func
, nr_linfo
;
29 const void *raw_jited_linfo
;
30 const __u64
*jited_linfo
;
31 __u64 last_jited_linfo
;
33 * Index to raw_jited_linfo:
34 * i: Index for searching the next ksym_func
35 * prev_i: Index to the last found ksym_func
38 __u32 f
; /* Index to ksym_func */
40 raw_jited_linfo
= prog_linfo
->raw_jited_linfo
;
41 jited_linfo
= raw_jited_linfo
;
42 if (ksym_func
[0] != *jited_linfo
)
45 prog_linfo
->jited_linfo_func_idx
[0] = 0;
46 nr_jited_func
= prog_linfo
->nr_jited_func
;
47 nr_linfo
= prog_linfo
->nr_linfo
;
49 for (prev_i
= 0, i
= 1, f
= 1;
50 i
< nr_linfo
&& f
< nr_jited_func
;
52 raw_jited_linfo
+= prog_linfo
->jited_rec_size
;
53 last_jited_linfo
= *jited_linfo
;
54 jited_linfo
= raw_jited_linfo
;
56 if (ksym_func
[f
] == *jited_linfo
) {
57 prog_linfo
->jited_linfo_func_idx
[f
] = i
;
60 if (last_jited_linfo
- ksym_func
[f
- 1] + 1 >
64 prog_linfo
->nr_jited_linfo_per_func
[f
- 1] =
69 * The ksym_func[f] is found in jited_linfo.
70 * Look for the next one.
73 } else if (*jited_linfo
<= last_jited_linfo
) {
74 /* Ensure the addr is increasing _within_ a func */
79 if (f
!= nr_jited_func
)
82 prog_linfo
->nr_jited_linfo_per_func
[nr_jited_func
- 1] =
91 void bpf_prog_linfo__free(struct bpf_prog_linfo
*prog_linfo
)
96 free(prog_linfo
->raw_linfo
);
97 free(prog_linfo
->raw_jited_linfo
);
98 free(prog_linfo
->nr_jited_linfo_per_func
);
99 free(prog_linfo
->jited_linfo_func_idx
);
103 struct bpf_prog_linfo
*bpf_prog_linfo__new(const struct bpf_prog_info
*info
)
105 struct bpf_prog_linfo
*prog_linfo
;
106 __u32 nr_linfo
, nr_jited_func
;
109 nr_linfo
= info
->nr_line_info
;
115 * The min size that bpf_prog_linfo has to access for
118 if (info
->line_info_rec_size
<
119 offsetof(struct bpf_line_info
, file_name_off
))
122 prog_linfo
= calloc(1, sizeof(*prog_linfo
));
126 /* Copy xlated line_info */
127 prog_linfo
->nr_linfo
= nr_linfo
;
128 prog_linfo
->rec_size
= info
->line_info_rec_size
;
129 data_sz
= (__u64
)nr_linfo
* prog_linfo
->rec_size
;
130 prog_linfo
->raw_linfo
= malloc(data_sz
);
131 if (!prog_linfo
->raw_linfo
)
133 memcpy(prog_linfo
->raw_linfo
, (void *)(long)info
->line_info
, data_sz
);
135 nr_jited_func
= info
->nr_jited_ksyms
;
136 if (!nr_jited_func
||
137 !info
->jited_line_info
||
138 info
->nr_jited_line_info
!= nr_linfo
||
139 info
->jited_line_info_rec_size
< sizeof(__u64
) ||
140 info
->nr_jited_func_lens
!= nr_jited_func
||
141 !info
->jited_ksyms
||
142 !info
->jited_func_lens
)
143 /* Not enough info to provide jited_line_info */
146 /* Copy jited_line_info */
147 prog_linfo
->nr_jited_func
= nr_jited_func
;
148 prog_linfo
->jited_rec_size
= info
->jited_line_info_rec_size
;
149 data_sz
= (__u64
)nr_linfo
* prog_linfo
->jited_rec_size
;
150 prog_linfo
->raw_jited_linfo
= malloc(data_sz
);
151 if (!prog_linfo
->raw_jited_linfo
)
153 memcpy(prog_linfo
->raw_jited_linfo
,
154 (void *)(long)info
->jited_line_info
, data_sz
);
156 /* Number of jited_line_info per jited func */
157 prog_linfo
->nr_jited_linfo_per_func
= malloc(nr_jited_func
*
159 if (!prog_linfo
->nr_jited_linfo_per_func
)
163 * For each jited func,
164 * the start idx to the "linfo" and "jited_linfo" array,
166 prog_linfo
->jited_linfo_func_idx
= malloc(nr_jited_func
*
168 if (!prog_linfo
->jited_linfo_func_idx
)
171 if (dissect_jited_func(prog_linfo
,
172 (__u64
*)(long)info
->jited_ksyms
,
173 (__u32
*)(long)info
->jited_func_lens
))
179 bpf_prog_linfo__free(prog_linfo
);
183 const struct bpf_line_info
*
184 bpf_prog_linfo__lfind_addr_func(const struct bpf_prog_linfo
*prog_linfo
,
185 __u64 addr
, __u32 func_idx
, __u32 nr_skip
)
187 __u32 jited_rec_size
, rec_size
, nr_linfo
, start
, i
;
188 const void *raw_jited_linfo
, *raw_linfo
;
189 const __u64
*jited_linfo
;
191 if (func_idx
>= prog_linfo
->nr_jited_func
)
194 nr_linfo
= prog_linfo
->nr_jited_linfo_per_func
[func_idx
];
195 if (nr_skip
>= nr_linfo
)
198 start
= prog_linfo
->jited_linfo_func_idx
[func_idx
] + nr_skip
;
199 jited_rec_size
= prog_linfo
->jited_rec_size
;
200 raw_jited_linfo
= prog_linfo
->raw_jited_linfo
+
201 (start
* jited_rec_size
);
202 jited_linfo
= raw_jited_linfo
;
203 if (addr
< *jited_linfo
)
207 rec_size
= prog_linfo
->rec_size
;
208 raw_linfo
= prog_linfo
->raw_linfo
+ (start
* rec_size
);
209 for (i
= 0; i
< nr_linfo
; i
++) {
210 if (addr
< *jited_linfo
)
213 raw_linfo
+= rec_size
;
214 raw_jited_linfo
+= jited_rec_size
;
215 jited_linfo
= raw_jited_linfo
;
218 return raw_linfo
- rec_size
;
221 const struct bpf_line_info
*
222 bpf_prog_linfo__lfind(const struct bpf_prog_linfo
*prog_linfo
,
223 __u32 insn_off
, __u32 nr_skip
)
225 const struct bpf_line_info
*linfo
;
226 __u32 rec_size
, nr_linfo
, i
;
227 const void *raw_linfo
;
229 nr_linfo
= prog_linfo
->nr_linfo
;
230 if (nr_skip
>= nr_linfo
)
233 rec_size
= prog_linfo
->rec_size
;
234 raw_linfo
= prog_linfo
->raw_linfo
+ (nr_skip
* rec_size
);
236 if (insn_off
< linfo
->insn_off
)
240 for (i
= 0; i
< nr_linfo
; i
++) {
241 if (insn_off
< linfo
->insn_off
)
244 raw_linfo
+= rec_size
;
248 return raw_linfo
- rec_size
;