Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Add unit tests for bpf_line_info

Add unit tests for bpf_line_info for both BPF_PROG_LOAD and
BPF_OBJ_GET_INFO_BY_FD.

jit enabled:
[root@arch-fb-vm1 bpf]# ./test_btf -k 0
BTF prog info raw test[5] (line_info (No subprog)): OK
BTF prog info raw test[6] (line_info (No subprog. insn_off >= prog->len)): OK
BTF prog info raw test[7] (line_info (No subprog. zero tailing line_info): OK
BTF prog info raw test[8] (line_info (No subprog. nonzero tailing line_info)): OK
BTF prog info raw test[9] (line_info (subprog)): OK
BTF prog info raw test[10] (line_info (subprog + func_info)): OK
BTF prog info raw test[11] (line_info (subprog. missing 1st func line info)): OK
BTF prog info raw test[12] (line_info (subprog. missing 2nd func line info)): OK
BTF prog info raw test[13] (line_info (subprog. unordered insn offset)): OK

jit disabled:
BTF prog info raw test[5] (line_info (No subprog)): not jited. skipping jited_line_info check. OK
BTF prog info raw test[6] (line_info (No subprog. insn_off >= prog->len)): OK
BTF prog info raw test[7] (line_info (No subprog. zero tailing line_info): not jited. skipping jited_line_info check. OK
BTF prog info raw test[8] (line_info (No subprog. nonzero tailing line_info)): OK
BTF prog info raw test[9] (line_info (subprog)): not jited. skipping jited_line_info check. OK
BTF prog info raw test[10] (line_info (subprog + func_info)): not jited. skipping jited_line_info check. OK
BTF prog info raw test[11] (line_info (subprog. missing 1st func line info)): OK
BTF prog info raw test[12] (line_info (subprog. missing 2nd func line info)): OK
BTF prog info raw test[13] (line_info (subprog. unordered insn offset)): OK

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Martin KaFai Lau and committed by
Alexei Starovoitov
4d6304c7 05687352

+580 -17
+580 -17
tools/testing/selftests/bpf/test_btf.c
··· 108 108 #define BTF_END_RAW 0xdeadbeef 109 109 #define NAME_TBD 0xdeadb33f 110 110 111 - #define MAX_NR_RAW_TYPES 1024 111 + #define MAX_NR_RAW_U32 1024 112 112 #define BTF_LOG_BUF_SIZE 65535 113 113 114 114 static struct args { ··· 137 137 const char *str_sec; 138 138 const char *map_name; 139 139 const char *err_str; 140 - __u32 raw_types[MAX_NR_RAW_TYPES]; 140 + __u32 raw_types[MAX_NR_RAW_U32]; 141 141 __u32 str_sec_size; 142 142 enum bpf_map_type map_type; 143 143 __u32 key_size; ··· 155 155 int str_off_delta; 156 156 int str_len_delta; 157 157 }; 158 + 159 + #define BTF_STR_SEC(str) \ 160 + .str_sec = str, .str_sec_size = sizeof(str) 158 161 159 162 static struct btf_raw_test raw_tests[] = { 160 163 /* enum E { ··· 1861 1858 return start < end - 1 ? start + 1 : NULL; 1862 1859 } 1863 1860 1864 - static int get_type_sec_size(const __u32 *raw_types) 1861 + static int get_raw_sec_size(const __u32 *raw_types) 1865 1862 { 1866 1863 int i; 1867 1864 1868 - for (i = MAX_NR_RAW_TYPES - 1; 1865 + for (i = MAX_NR_RAW_U32 - 1; 1869 1866 i >= 0 && raw_types[i] != BTF_END_RAW; 1870 1867 i--) 1871 1868 ; ··· 1877 1874 const __u32 *raw_types, 1878 1875 const char *str, 1879 1876 unsigned int str_sec_size, 1880 - unsigned int *btf_size) 1877 + unsigned int *btf_size, 1878 + const char **ret_next_str) 1881 1879 { 1882 1880 const char *next_str = str, *end_str = str + str_sec_size; 1883 1881 unsigned int size_needed, offset; ··· 1887 1883 uint32_t *ret_types; 1888 1884 void *raw_btf; 1889 1885 1890 - type_sec_size = get_type_sec_size(raw_types); 1886 + type_sec_size = get_raw_sec_size(raw_types); 1891 1887 if (CHECK(type_sec_size < 0, "Cannot get nr_raw_types")) 1892 1888 return NULL; 1893 1889 ··· 1926 1922 ret_hdr->str_len = str_sec_size; 1927 1923 1928 1924 *btf_size = size_needed; 1925 + if (ret_next_str) 1926 + *ret_next_str = next_str; 1929 1927 1930 1928 return raw_btf; 1931 1929 } ··· 1947 1941 test->raw_types, 1948 1942 test->str_sec, 1949 1943 test->str_sec_size, 1950 - &raw_btf_size); 1944 + &raw_btf_size, NULL); 1951 1945 1952 1946 if (!raw_btf) 1953 1947 return -1; ··· 2024 2018 struct btf_get_info_test { 2025 2019 const char *descr; 2026 2020 const char *str_sec; 2027 - __u32 raw_types[MAX_NR_RAW_TYPES]; 2021 + __u32 raw_types[MAX_NR_RAW_U32]; 2028 2022 __u32 str_sec_size; 2029 2023 int btf_size_delta; 2030 2024 int (*special_test)(unsigned int test_num); ··· 2104 2098 test->raw_types, 2105 2099 test->str_sec, 2106 2100 test->str_sec_size, 2107 - &raw_btf_size); 2101 + &raw_btf_size, NULL); 2108 2102 2109 2103 if (!raw_btf) 2110 2104 return -1; ··· 2188 2182 test->raw_types, 2189 2183 test->str_sec, 2190 2184 test->str_sec_size, 2191 - &raw_btf_size); 2185 + &raw_btf_size, NULL); 2192 2186 2193 2187 if (!raw_btf) 2194 2188 return -1; ··· 2326 2320 test->raw_types, 2327 2321 test->str_sec, 2328 2322 test->str_sec_size, 2329 - &raw_btf_size); 2323 + &raw_btf_size, NULL); 2330 2324 2331 2325 if (!raw_btf) 2332 2326 return -1; ··· 2855 2849 fprintf(stderr, "%s......", test->descr); 2856 2850 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types, 2857 2851 test->str_sec, test->str_sec_size, 2858 - &raw_btf_size); 2852 + &raw_btf_size, NULL); 2859 2853 2860 2854 if (!raw_btf) 2861 2855 return -1; ··· 3059 3053 return err; 3060 3054 } 3061 3055 3056 + #define BPF_LINE_INFO_ENC(insn_off, file_off, line_off, line_num, line_col) \ 3057 + (insn_off), (file_off), (line_off), ((line_num) << 10 | ((line_col) & 0x3ff)) 3058 + 3062 3059 static struct prog_info_raw_test { 3063 3060 const char *descr; 3064 3061 const char *str_sec; 3065 - __u32 raw_types[MAX_NR_RAW_TYPES]; 3062 + const char *err_str; 3063 + __u32 raw_types[MAX_NR_RAW_U32]; 3066 3064 __u32 str_sec_size; 3067 3065 struct bpf_insn insns[MAX_INSNS]; 3068 3066 __u32 prog_type; 3069 3067 __u32 func_info[MAX_SUBPROGS][2]; 3070 3068 __u32 func_info_rec_size; 3071 3069 __u32 func_info_cnt; 3070 + __u32 line_info[MAX_NR_RAW_U32]; 3071 + __u32 line_info_rec_size; 3072 + __u32 nr_jited_ksyms; 3072 3073 bool expected_prog_load_failure; 3073 3074 } info_raw_tests[] = { 3074 3075 { ··· 3106 3093 .func_info = { {0, 5}, {3, 6} }, 3107 3094 .func_info_rec_size = 8, 3108 3095 .func_info_cnt = 2, 3096 + .line_info = { BTF_END_RAW }, 3109 3097 }, 3110 3098 3111 3099 { ··· 3137 3123 .func_info = { {0, 5}, {3, 6} }, 3138 3124 .func_info_rec_size = 4, 3139 3125 .func_info_cnt = 2, 3126 + .line_info = { BTF_END_RAW }, 3140 3127 .expected_prog_load_failure = true, 3141 3128 }, 3142 3129 ··· 3169 3154 .func_info = { {0, 5}, {3, 6} }, 3170 3155 .func_info_rec_size = 8, 3171 3156 .func_info_cnt = 1, 3157 + .line_info = { BTF_END_RAW }, 3172 3158 .expected_prog_load_failure = true, 3173 3159 }, 3174 3160 ··· 3201 3185 .func_info = { {0, 5}, {2, 6} }, 3202 3186 .func_info_rec_size = 8, 3203 3187 .func_info_cnt = 2, 3188 + .line_info = { BTF_END_RAW }, 3189 + .expected_prog_load_failure = true, 3190 + }, 3191 + 3192 + { 3193 + .descr = "line_info (No subprog)", 3194 + .raw_types = { 3195 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3196 + BTF_END_RAW, 3197 + }, 3198 + BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"), 3199 + .insns = { 3200 + BPF_MOV64_IMM(BPF_REG_0, 1), 3201 + BPF_MOV64_IMM(BPF_REG_1, 2), 3202 + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 3203 + BPF_EXIT_INSN(), 3204 + }, 3205 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3206 + .func_info_cnt = 0, 3207 + .line_info = { 3208 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 3209 + BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 3210 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 3211 + BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 3212 + BTF_END_RAW, 3213 + }, 3214 + .line_info_rec_size = sizeof(struct bpf_line_info), 3215 + .nr_jited_ksyms = 1, 3216 + }, 3217 + 3218 + { 3219 + .descr = "line_info (No subprog. insn_off >= prog->len)", 3220 + .raw_types = { 3221 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3222 + BTF_END_RAW, 3223 + }, 3224 + BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"), 3225 + .insns = { 3226 + BPF_MOV64_IMM(BPF_REG_0, 1), 3227 + BPF_MOV64_IMM(BPF_REG_1, 2), 3228 + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 3229 + BPF_EXIT_INSN(), 3230 + }, 3231 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3232 + .func_info_cnt = 0, 3233 + .line_info = { 3234 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 3235 + BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 3236 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 3237 + BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 3238 + BPF_LINE_INFO_ENC(4, 0, 0, 5, 6), 3239 + BTF_END_RAW, 3240 + }, 3241 + .line_info_rec_size = sizeof(struct bpf_line_info), 3242 + .nr_jited_ksyms = 1, 3243 + .err_str = "line_info[4].insn_off", 3244 + .expected_prog_load_failure = true, 3245 + }, 3246 + 3247 + { 3248 + .descr = "line_info (No subprog. zero tailing line_info", 3249 + .raw_types = { 3250 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3251 + BTF_END_RAW, 3252 + }, 3253 + BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"), 3254 + .insns = { 3255 + BPF_MOV64_IMM(BPF_REG_0, 1), 3256 + BPF_MOV64_IMM(BPF_REG_1, 2), 3257 + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 3258 + BPF_EXIT_INSN(), 3259 + }, 3260 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3261 + .func_info_cnt = 0, 3262 + .line_info = { 3263 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 0, 3264 + BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 0, 3265 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 0, 3266 + BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 0, 3267 + BTF_END_RAW, 3268 + }, 3269 + .line_info_rec_size = sizeof(struct bpf_line_info) + sizeof(__u32), 3270 + .nr_jited_ksyms = 1, 3271 + }, 3272 + 3273 + { 3274 + .descr = "line_info (No subprog. nonzero tailing line_info)", 3275 + .raw_types = { 3276 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3277 + BTF_END_RAW, 3278 + }, 3279 + BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"), 3280 + .insns = { 3281 + BPF_MOV64_IMM(BPF_REG_0, 1), 3282 + BPF_MOV64_IMM(BPF_REG_1, 2), 3283 + BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), 3284 + BPF_EXIT_INSN(), 3285 + }, 3286 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3287 + .func_info_cnt = 0, 3288 + .line_info = { 3289 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 0, 3290 + BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 0, 3291 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 0, 3292 + BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 1, 3293 + BTF_END_RAW, 3294 + }, 3295 + .line_info_rec_size = sizeof(struct bpf_line_info) + sizeof(__u32), 3296 + .nr_jited_ksyms = 1, 3297 + .err_str = "nonzero tailing record in line_info", 3298 + .expected_prog_load_failure = true, 3299 + }, 3300 + 3301 + { 3302 + .descr = "line_info (subprog)", 3303 + .raw_types = { 3304 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3305 + BTF_END_RAW, 3306 + }, 3307 + BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"), 3308 + .insns = { 3309 + BPF_MOV64_IMM(BPF_REG_2, 1), 3310 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1), 3311 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), 3312 + BPF_CALL_REL(1), 3313 + BPF_EXIT_INSN(), 3314 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 3315 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 3316 + BPF_EXIT_INSN(), 3317 + }, 3318 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3319 + .func_info_cnt = 0, 3320 + .line_info = { 3321 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 3322 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9), 3323 + BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8), 3324 + BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7), 3325 + BTF_END_RAW, 3326 + }, 3327 + .line_info_rec_size = sizeof(struct bpf_line_info), 3328 + .nr_jited_ksyms = 2, 3329 + }, 3330 + 3331 + { 3332 + .descr = "line_info (subprog + func_info)", 3333 + .raw_types = { 3334 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3335 + BTF_FUNC_PROTO_ENC(1, 1), /* [2] */ 3336 + BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1), 3337 + BTF_FUNC_ENC(NAME_TBD, 2), /* [3] */ 3338 + BTF_FUNC_ENC(NAME_TBD, 2), /* [4] */ 3339 + BTF_END_RAW, 3340 + }, 3341 + BTF_STR_SEC("\0int\0x\0sub\0main\0int a=1+1;\0return func(a);\0b+=1;\0return b;"), 3342 + .insns = { 3343 + BPF_MOV64_IMM(BPF_REG_2, 1), 3344 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1), 3345 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), 3346 + BPF_CALL_REL(1), 3347 + BPF_EXIT_INSN(), 3348 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 3349 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 3350 + BPF_EXIT_INSN(), 3351 + }, 3352 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3353 + .func_info_cnt = 2, 3354 + .func_info_rec_size = 8, 3355 + .func_info = { {0, 4}, {5, 3} }, 3356 + .line_info = { 3357 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 3358 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9), 3359 + BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8), 3360 + BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7), 3361 + BTF_END_RAW, 3362 + }, 3363 + .line_info_rec_size = sizeof(struct bpf_line_info), 3364 + .nr_jited_ksyms = 2, 3365 + }, 3366 + 3367 + { 3368 + .descr = "line_info (subprog. missing 1st func line info)", 3369 + .raw_types = { 3370 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3371 + BTF_END_RAW, 3372 + }, 3373 + BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"), 3374 + .insns = { 3375 + BPF_MOV64_IMM(BPF_REG_2, 1), 3376 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1), 3377 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), 3378 + BPF_CALL_REL(1), 3379 + BPF_EXIT_INSN(), 3380 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 3381 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 3382 + BPF_EXIT_INSN(), 3383 + }, 3384 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3385 + .func_info_cnt = 0, 3386 + .line_info = { 3387 + BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 1, 10), 3388 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9), 3389 + BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8), 3390 + BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7), 3391 + BTF_END_RAW, 3392 + }, 3393 + .line_info_rec_size = sizeof(struct bpf_line_info), 3394 + .nr_jited_ksyms = 2, 3395 + .err_str = "missing bpf_line_info for func#0", 3396 + .expected_prog_load_failure = true, 3397 + }, 3398 + 3399 + { 3400 + .descr = "line_info (subprog. missing 2nd func line info)", 3401 + .raw_types = { 3402 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3403 + BTF_END_RAW, 3404 + }, 3405 + BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"), 3406 + .insns = { 3407 + BPF_MOV64_IMM(BPF_REG_2, 1), 3408 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1), 3409 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), 3410 + BPF_CALL_REL(1), 3411 + BPF_EXIT_INSN(), 3412 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 3413 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 3414 + BPF_EXIT_INSN(), 3415 + }, 3416 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3417 + .func_info_cnt = 0, 3418 + .line_info = { 3419 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 3420 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9), 3421 + BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 3, 8), 3422 + BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7), 3423 + BTF_END_RAW, 3424 + }, 3425 + .line_info_rec_size = sizeof(struct bpf_line_info), 3426 + .nr_jited_ksyms = 2, 3427 + .err_str = "missing bpf_line_info for func#1", 3428 + .expected_prog_load_failure = true, 3429 + }, 3430 + 3431 + { 3432 + .descr = "line_info (subprog. unordered insn offset)", 3433 + .raw_types = { 3434 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 3435 + BTF_END_RAW, 3436 + }, 3437 + BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"), 3438 + .insns = { 3439 + BPF_MOV64_IMM(BPF_REG_2, 1), 3440 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1), 3441 + BPF_MOV64_REG(BPF_REG_1, BPF_REG_2), 3442 + BPF_CALL_REL(1), 3443 + BPF_EXIT_INSN(), 3444 + BPF_MOV64_REG(BPF_REG_0, BPF_REG_1), 3445 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1), 3446 + BPF_EXIT_INSN(), 3447 + }, 3448 + .prog_type = BPF_PROG_TYPE_TRACEPOINT, 3449 + .func_info_cnt = 0, 3450 + .line_info = { 3451 + BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 3452 + BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 2, 9), 3453 + BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 3454 + BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7), 3455 + BTF_END_RAW, 3456 + }, 3457 + .line_info_rec_size = sizeof(struct bpf_line_info), 3458 + .nr_jited_ksyms = 2, 3459 + .err_str = "Invalid line_info[2].insn_off", 3204 3460 .expected_prog_load_failure = true, 3205 3461 }, 3206 3462 ··· 3486 3198 if (fp[len].code != 0 || fp[len].imm != 0) 3487 3199 break; 3488 3200 return len + 1; 3201 + } 3202 + 3203 + static __u32 *patch_name_tbd(const __u32 *raw_u32, 3204 + const char *str, __u32 str_off, 3205 + unsigned int str_sec_size, 3206 + unsigned int *ret_size) 3207 + { 3208 + int i, raw_u32_size = get_raw_sec_size(raw_u32); 3209 + const char *end_str = str + str_sec_size; 3210 + const char *next_str = str + str_off; 3211 + __u32 *new_u32 = NULL; 3212 + 3213 + if (raw_u32_size == -1) 3214 + return ERR_PTR(-EINVAL); 3215 + 3216 + if (!raw_u32_size) { 3217 + *ret_size = 0; 3218 + return NULL; 3219 + } 3220 + 3221 + new_u32 = malloc(raw_u32_size); 3222 + if (!new_u32) 3223 + return ERR_PTR(-ENOMEM); 3224 + 3225 + for (i = 0; i < raw_u32_size / sizeof(raw_u32[0]); i++) { 3226 + if (raw_u32[i] == NAME_TBD) { 3227 + next_str = get_next_str(next_str, end_str); 3228 + if (CHECK(!next_str, "Error in getting next_str\n")) { 3229 + free(new_u32); 3230 + return ERR_PTR(-EINVAL); 3231 + } 3232 + new_u32[i] = next_str - str; 3233 + next_str += strlen(next_str); 3234 + } else { 3235 + new_u32[i] = raw_u32[i]; 3236 + } 3237 + } 3238 + 3239 + *ret_size = raw_u32_size; 3240 + return new_u32; 3489 3241 } 3490 3242 3491 3243 static int test_get_finfo(const struct prog_info_raw_test *test, ··· 3611 3283 return err; 3612 3284 } 3613 3285 3286 + static int test_get_linfo(const struct prog_info_raw_test *test, 3287 + const void *patched_linfo, 3288 + __u32 cnt, int prog_fd) 3289 + { 3290 + __u32 i, info_len, nr_jited_ksyms, nr_jited_func_lens; 3291 + __u64 *jited_linfo = NULL, *jited_ksyms = NULL; 3292 + __u32 rec_size, jited_rec_size, jited_cnt; 3293 + struct bpf_line_info *linfo = NULL; 3294 + __u32 cur_func_len, ksyms_found; 3295 + struct bpf_prog_info info = {}; 3296 + __u32 *jited_func_lens = NULL; 3297 + __u64 cur_func_ksyms; 3298 + int err; 3299 + 3300 + jited_cnt = cnt; 3301 + rec_size = sizeof(*linfo); 3302 + jited_rec_size = sizeof(*jited_linfo); 3303 + if (test->nr_jited_ksyms) 3304 + nr_jited_ksyms = test->nr_jited_ksyms; 3305 + else 3306 + nr_jited_ksyms = test->func_info_cnt; 3307 + nr_jited_func_lens = nr_jited_ksyms; 3308 + 3309 + info_len = sizeof(struct bpf_prog_info); 3310 + err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); 3311 + if (CHECK(err == -1, "err:%d errno:%d", err, errno)) { 3312 + err = -1; 3313 + goto done; 3314 + } 3315 + 3316 + if (!info.jited_prog_len) { 3317 + /* prog is not jited */ 3318 + jited_cnt = 0; 3319 + nr_jited_ksyms = 1; 3320 + nr_jited_func_lens = 1; 3321 + } 3322 + 3323 + if (CHECK(info.line_info_cnt != cnt || 3324 + info.jited_line_info_cnt != jited_cnt || 3325 + info.nr_jited_ksyms != nr_jited_ksyms || 3326 + info.nr_jited_func_lens != nr_jited_func_lens || 3327 + (!info.line_info_cnt && info.jited_line_info_cnt), 3328 + "info: line_info_cnt:%u(expected:%u) jited_line_info_cnt:%u(expected:%u) nr_jited_ksyms:%u(expected:%u) nr_jited_func_lens:%u(expected:%u)", 3329 + info.line_info_cnt, cnt, 3330 + info.jited_line_info_cnt, jited_cnt, 3331 + info.nr_jited_ksyms, nr_jited_ksyms, 3332 + info.nr_jited_func_lens, nr_jited_func_lens)) { 3333 + err = -1; 3334 + goto done; 3335 + } 3336 + 3337 + if (CHECK(info.line_info_rec_size < 16 || 3338 + info.jited_line_info_rec_size < 8, 3339 + "info: line_info_rec_size:%u(userspace expected:%u) jited_line_info_rec_size:%u(userspace expected:%u)", 3340 + info.line_info_rec_size, rec_size, 3341 + info.jited_line_info_rec_size, jited_rec_size)) { 3342 + err = -1; 3343 + goto done; 3344 + } 3345 + 3346 + if (!cnt) 3347 + return 0; 3348 + 3349 + rec_size = info.line_info_rec_size; 3350 + jited_rec_size = info.jited_line_info_rec_size; 3351 + 3352 + memset(&info, 0, sizeof(info)); 3353 + 3354 + linfo = calloc(cnt, rec_size); 3355 + if (CHECK(!linfo, "!linfo")) { 3356 + err = -1; 3357 + goto done; 3358 + } 3359 + info.line_info_cnt = cnt; 3360 + info.line_info_rec_size = rec_size; 3361 + info.line_info = ptr_to_u64(linfo); 3362 + 3363 + if (jited_cnt) { 3364 + jited_linfo = calloc(jited_cnt, jited_rec_size); 3365 + jited_ksyms = calloc(nr_jited_ksyms, sizeof(*jited_ksyms)); 3366 + jited_func_lens = calloc(nr_jited_func_lens, 3367 + sizeof(*jited_func_lens)); 3368 + if (CHECK(!jited_linfo || !jited_ksyms || !jited_func_lens, 3369 + "jited_linfo:%p jited_ksyms:%p jited_func_lens:%p", 3370 + jited_linfo, jited_ksyms, jited_func_lens)) { 3371 + err = -1; 3372 + goto done; 3373 + } 3374 + 3375 + info.jited_line_info_cnt = jited_cnt; 3376 + info.jited_line_info_rec_size = jited_rec_size; 3377 + info.jited_line_info = ptr_to_u64(jited_linfo); 3378 + info.nr_jited_ksyms = nr_jited_ksyms; 3379 + info.jited_ksyms = ptr_to_u64(jited_ksyms); 3380 + info.nr_jited_func_lens = nr_jited_func_lens; 3381 + info.jited_func_lens = ptr_to_u64(jited_func_lens); 3382 + } 3383 + 3384 + err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len); 3385 + 3386 + /* 3387 + * Only recheck the info.*line_info* fields. 3388 + * Other fields are not the concern of this test. 3389 + */ 3390 + if (CHECK(err == -1 || 3391 + !info.line_info || 3392 + info.line_info_cnt != cnt || 3393 + (jited_cnt && !info.jited_line_info) || 3394 + info.jited_line_info_cnt != jited_cnt || 3395 + info.line_info_rec_size != rec_size || 3396 + info.jited_line_info_rec_size != jited_rec_size, 3397 + "err:%d errno:%d info: line_info_cnt:%u(expected:%u) jited_line_info_cnt:%u(expected:%u) line_info_rec_size:%u(expected:%u) jited_linfo_rec_size:%u(expected:%u) line_info:%p jited_line_info:%p", 3398 + err, errno, 3399 + info.line_info_cnt, cnt, 3400 + info.jited_line_info_cnt, jited_cnt, 3401 + info.line_info_rec_size, rec_size, 3402 + info.jited_line_info_rec_size, jited_rec_size, 3403 + (void *)(long)info.line_info, 3404 + (void *)(long)info.jited_line_info)) { 3405 + err = -1; 3406 + goto done; 3407 + } 3408 + 3409 + CHECK(linfo[0].insn_off, "linfo[0].insn_off:%u", 3410 + linfo[0].insn_off); 3411 + for (i = 1; i < cnt; i++) { 3412 + const struct bpf_line_info *expected_linfo; 3413 + 3414 + expected_linfo = patched_linfo + (i * test->line_info_rec_size); 3415 + if (CHECK(linfo[i].insn_off <= linfo[i - 1].insn_off, 3416 + "linfo[%u].insn_off:%u <= linfo[%u].insn_off:%u", 3417 + i, linfo[i].insn_off, 3418 + i - 1, linfo[i - 1].insn_off)) { 3419 + err = -1; 3420 + goto done; 3421 + } 3422 + if (CHECK(linfo[i].file_name_off != expected_linfo->file_name_off || 3423 + linfo[i].line_off != expected_linfo->line_off || 3424 + linfo[i].line_col != expected_linfo->line_col, 3425 + "linfo[%u] (%u, %u, %u) != (%u, %u, %u)", i, 3426 + linfo[i].file_name_off, 3427 + linfo[i].line_off, 3428 + linfo[i].line_col, 3429 + expected_linfo->file_name_off, 3430 + expected_linfo->line_off, 3431 + expected_linfo->line_col)) { 3432 + err = -1; 3433 + goto done; 3434 + } 3435 + } 3436 + 3437 + if (!jited_cnt) { 3438 + fprintf(stderr, "not jited. skipping jited_line_info check. "); 3439 + err = 0; 3440 + goto done; 3441 + } 3442 + 3443 + if (CHECK(jited_linfo[0] != jited_ksyms[0], 3444 + "jited_linfo[0]:%lx != jited_ksyms[0]:%lx", 3445 + (long)(jited_linfo[0]), (long)(jited_ksyms[0]))) { 3446 + err = -1; 3447 + goto done; 3448 + } 3449 + 3450 + ksyms_found = 1; 3451 + cur_func_len = jited_func_lens[0]; 3452 + cur_func_ksyms = jited_ksyms[0]; 3453 + for (i = 1; i < jited_cnt; i++) { 3454 + if (ksyms_found < nr_jited_ksyms && 3455 + jited_linfo[i] == jited_ksyms[ksyms_found]) { 3456 + cur_func_ksyms = jited_ksyms[ksyms_found]; 3457 + cur_func_len = jited_ksyms[ksyms_found]; 3458 + ksyms_found++; 3459 + continue; 3460 + } 3461 + 3462 + if (CHECK(jited_linfo[i] <= jited_linfo[i - 1], 3463 + "jited_linfo[%u]:%lx <= jited_linfo[%u]:%lx", 3464 + i, (long)jited_linfo[i], 3465 + i - 1, (long)(jited_linfo[i - 1]))) { 3466 + err = -1; 3467 + goto done; 3468 + } 3469 + 3470 + if (CHECK(jited_linfo[i] - cur_func_ksyms > cur_func_len, 3471 + "jited_linfo[%u]:%lx - %lx > %u", 3472 + i, (long)jited_linfo[i], (long)cur_func_ksyms, 3473 + cur_func_len)) { 3474 + err = -1; 3475 + goto done; 3476 + } 3477 + } 3478 + 3479 + if (CHECK(ksyms_found != nr_jited_ksyms, 3480 + "ksyms_found:%u != nr_jited_ksyms:%u", 3481 + ksyms_found, nr_jited_ksyms)) { 3482 + err = -1; 3483 + goto done; 3484 + } 3485 + 3486 + err = 0; 3487 + 3488 + done: 3489 + free(linfo); 3490 + free(jited_linfo); 3491 + free(jited_ksyms); 3492 + free(jited_func_lens); 3493 + return err; 3494 + } 3495 + 3614 3496 static int do_test_info_raw(unsigned int test_num) 3615 3497 { 3616 3498 const struct prog_info_raw_test *test = &info_raw_tests[test_num - 1]; 3499 + unsigned int raw_btf_size, linfo_str_off, linfo_size; 3617 3500 int btf_fd = -1, prog_fd = -1, err = 0; 3618 - unsigned int raw_btf_size; 3501 + void *raw_btf, *patched_linfo = NULL; 3502 + const char *ret_next_str; 3619 3503 union bpf_attr attr = {}; 3620 - void *raw_btf; 3621 3504 3622 3505 fprintf(stderr, "BTF prog info raw test[%u] (%s): ", test_num, test->descr); 3623 3506 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types, 3624 3507 test->str_sec, test->str_sec_size, 3625 - &raw_btf_size); 3508 + &raw_btf_size, &ret_next_str); 3626 3509 3627 3510 if (!raw_btf) 3628 3511 return -1; ··· 3853 3314 fprintf(stderr, "\n%s", btf_log_buf); 3854 3315 *btf_log_buf = '\0'; 3855 3316 3317 + linfo_str_off = ret_next_str - test->str_sec; 3318 + patched_linfo = patch_name_tbd(test->line_info, 3319 + test->str_sec, linfo_str_off, 3320 + test->str_sec_size, &linfo_size); 3321 + if (IS_ERR(patched_linfo)) { 3322 + fprintf(stderr, "error in creating raw bpf_line_info"); 3323 + err = -1; 3324 + goto done; 3325 + } 3326 + 3856 3327 attr.prog_type = test->prog_type; 3857 3328 attr.insns = ptr_to_u64(test->insns); 3858 3329 attr.insn_cnt = probe_prog_length(test->insns); ··· 3874 3325 attr.log_buf = ptr_to_u64(btf_log_buf); 3875 3326 attr.log_size = BTF_LOG_BUF_SIZE; 3876 3327 attr.log_level = 1; 3328 + if (linfo_size) { 3329 + attr.line_info_rec_size = test->line_info_rec_size; 3330 + attr.line_info = ptr_to_u64(patched_linfo); 3331 + attr.line_info_cnt = linfo_size / attr.line_info_rec_size; 3332 + } 3877 3333 3878 3334 prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); 3879 3335 err = ((prog_fd == -1) != test->expected_prog_load_failure); 3880 3336 if (CHECK(err, "prog_fd:%d expected_prog_load_failure:%u errno:%d", 3881 - prog_fd, test->expected_prog_load_failure, errno)) { 3337 + prog_fd, test->expected_prog_load_failure, errno) || 3338 + CHECK(test->err_str && !strstr(btf_log_buf, test->err_str), 3339 + "expected err_str:%s", test->err_str)) { 3882 3340 err = -1; 3883 3341 goto done; 3884 3342 } ··· 3894 3338 goto done; 3895 3339 3896 3340 err = test_get_finfo(test, prog_fd); 3341 + if (err) 3342 + goto done; 3343 + 3344 + err = test_get_linfo(test, patched_linfo, attr.line_info_cnt, prog_fd); 3897 3345 if (err) 3898 3346 goto done; 3899 3347 ··· 3912 3352 close(btf_fd); 3913 3353 if (prog_fd != -1) 3914 3354 close(prog_fd); 3355 + 3356 + if (!IS_ERR(patched_linfo)) 3357 + free(patched_linfo); 3915 3358 3916 3359 return err; 3917 3360 }