summaryrefslogblamecommitdiffstats
path: root/tools/testing/selftests/bpf/test_btf.c
blob: 3d617e806054803e332d8530447c6de1ecfbbc95 (plain) (tree)
1
2
3
4
5
6
7
8
9
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791





                                      
                         
                         
                         










                         
                   



                       
                     
                     
 


                           























                                                                         
                                                                           
                                                      
 
                                              

 


                              



                                                       
                           

                              



                                       
                                       
                                    




                           
                           
                        






                                          
                                             

  


                                                             
                                

  



                             
                            
                                        



                                   

                            


                            

                          
                        
                          


                           
                                          

  


                                                   






                                          

                             



















                                                                                 

                                                                          






                                                                          
                                                                         










                                                                                       

                           




















































                                                                                

                           

                         


























                                                                                  

















































































































































































































































































































































































































































































































































































































































































                                                                                             














                                                                                                  
                                                            








                                            

                           

                             
                                                




























                                                                                                 

                           

                             
                                                




























                                                                                                              

                           

                             
                                                




































                                                                                                 

                           

                             
                                                
















                                                                       

                                                         

                                                                                            
                                               








                                                         

                           


























                                                                               

                           

                             
                                    













                                                                       



                                                         







                                                   
                         
                           




















                                                                       

                           

                             
                                  

























                                                              

                           

                             
                                   























                                                                         







                                              

                           

                             
                                   

















                                                                 







                                              

                           

                             
                                   































                                                                 

                           

                             
                                   




































                                                                               

                           

                             
                                   
























                                                                               

                           

                             
                                   






















                                                                                            

                           

                             
                                   






























                                                                                            

                           

                             
                                   


  
                                                         





                                                                     





































                                                                 




                                        

                           

                             
                                   


  
                                                   










                                                                     

                           

                             

                                            


  
                                                             










                                                                     

                           

                             

                                               


  
                                                             










                                                                     

                           

                             

                                               


  
                                                                 










                                                                     

                           

                             

                                           


  
                                                    










                                                                     













































































































































































































































                                                                       

                             



                                   






















                                                                       





































                                                                     

  





















                                                                     
 








































































































































































































































































































































































                                                                                 
















































































                                                                 

























































































































                                                                         
                                                    


                                                                         

                                                                         












                                                     





















































                                                                         
                                                              


































































































































































































































































                                                                                                 









































































































































































































































































































































































































































































































                                                                                                   



























































































                                                                                         























































































                                                                          
 






                                                                   
                                                   


              
                                    










                                                         

                                                      

                                                                  

                                                         

                                         
                                      
                            
                             
 
                                                    
                                                                
                            


                                                                  
                                                                  
                            




                                           
















                                                                             



                                                                    




                                                                  
                         










                                                                          









                                                    
                                          



                                         
                         

                                                                                
 







                                       

















                                                                          
                                                      





                          
                                                               










                                                                  






                                                                       









                                                    

                                                            



                                                       

                                                       


                 
                                      

                                                     
                                                     














                              
                                                                    

                                                    
                                                    






                            
                                        
                           

                                                   

  


                                                    









                                                                 
                            









                                                                 
























                                                                 


  





















                                                                             
                                                      


















































































                                                                             
                                                      
























































                                                                                      

                                          









                                                                   



                                                                                                 












































                                                              




                                                                             


                                      
 
                                                       

                                       


                                                    



                                                    
                                                      






                                        
                                            






                                                            
                                                     



                          
                                                                 




                                                           











                                                                                                                                          





                                                          


                                                                         




                                  
                              


                                                     
                                                     















                                   
                                                                              

                                                         
                                                         









                                            


                                                                

  


                                                                     


                                                              
                                       
                                       
                                      
                                    
                                 



                                 
                            
                            



                                                               







                                                                              
         



                                      

                                           
                                                         


                                      
                                                       
                          

                                            
                                                   





                                                              
                                                        
                          
                                        

                                                           
                                               



                          
                                                                                          
                                         

                                                                                          
                                         
                          
 

                          









                                                                         


                                                         



                                           
                                                           




                                                                              
                                                         
                                                 





                                                                
                              









                                                                         


                                                         









                                                               
                                                  






























                                                                       
     
                              

     
                        









                               
                                                                      

                                                     
                                                     




























                                 

                          
                            

  









                                    

                                                     















                                                                     
                                            




















                                                                       
                                                                                 







                                                                           

                                                                            


                                                                   

                            
                                                                                                                                                                                                                                                                                                       















































                                                                       
                                                                                 







                                                                                           

                                                                                                    


                                                                   

                            
                                                                                                                                                                                                                                                                                                       

                                                 

                                                        
                                  












































                                                                       
                                                                                 







                                                                                           

                                                                                                    
                                                                                           



                                                                                          

                                                                                          

                            
                                                                                                                                                                                                                                                                                                               






                                                        




























                                                                                                                             

  





                                    
                        






                                          
                            







                                         
                            







                                             



























                                                    



  



                                                                     
 




                                                         




                                                              



                                                                 












                                                      



                                                              


                                                           














                                                                       














                                                                               
                                                                         












                                                                      


                                                                          
         
 


















                                                                       
                              



                                                                    
 











                                                               

 
 
                                       
 
                                                                          
                                                            
                                                    

                                                   
                                        
                                     





                                  
                          

                         
 
                                                                

                                                                   
                                                      









                                                            
                                                     
                         








                                                    

                                                            

                                                    
                                                     
                         


                          




                                                                        
                         



                                            
                                                                      
                          
 

                                                            
                                                                          





                                                      
                                                       
                                                                                    
                                                           


                                        
                                                                       
                         







                                                                   
                                                  
                         


                          


                                          

                                       
                                      
                            
                        
 
                                                                    
                                                                                         































                                                                                        



                                                                                           




                                                                       
                                                           

                 




                                                                      


                                                            
                                                                   
 



                                                                          
                         


                          
                                                                           
                         





                          

                           
                 
                                      
                                                     
                                                     











                                 




                            
                                                            
                                                             


















                                                                                         




                   


                                                                                     
                                  

                            

                                        





                                         


                                        
                                        



                             
                      



























                                                                                 
                                     





























                                                                                 
                                     






























                                                                                 
                                     



                                           
                                                                

























                                                                                 



























































                                                                                 


























                                                                                 



















































































































































































































                                                                                          


                                           










































































































































































































































































































































































                                                                                                                











                                                          



                                                            
 



                                                        
 

                                        
 



                              
 


                                        
 











                                                                              

         


                                 
 

                                                                
 

                                       

                                    
                           
                





                                                                         
                          
         

                                                                 

                                                         
                          
         
 
                                           
                                                           

                                                                            

         
                               

                         
                                                         

                                               


                                                                
                                         







                                                                         
                                                    

                                                         


                          
                                                      
                                                               





                                             


                                                    








                                                                   

                
     



                        











                                                                
                         







                                                      
                                                                           















                                                                

                                                         

                                                                  



                                                                                                                                                            





                                                                 

                                                                            



















                                                                                                                          
                                














                                                                             
                                                    














                                                                   
                                             
                                                         
                                                         

                                                                  
                                                                                                                                                                                                                  
                             

                                                     







                                                                



                                                        




                                                           




                                                                      
















































































                                                                                    


                                                                              
                                                             
                                               

                                             
                                 



                                                                                    
                                                               


















                                                                    









                                                                        










                                                           




                                                                          



                                                                           


                                                                       










                                            


                                                                      


                          
     


                                      






                                                     
 


                                    


                   
                              



                       




                                                                              



                   




































































































































                                                                                                  












































                                                                                            














































                                                                                                     
































































































                                                                                                             











































                                                                                        












































                                                                                           




























                                                                    



                                                                         




















                                                                       

                                                                             
                                                        
                                                    



                                                            


                                  



































                                                                               









                                                                          
                                                                          
                                     
                                                                                


                                                                   
                                                     
                                                               
                                                         
                                                                   




                                 
                                                     
                                     
                                                           





















































































                                                                                

                                  



                                                                             

                                                                 
                                                                       

                                                                   



                                            
                                             





















                                                              
                         

                                                              
                              



                                                           



                                       

                                       


























                                                                               







                                                                                    







                                                                            


                 





                                                          








                                     
                                            










                                       
                                     
 

                                       
 


                                    
                                                                    
                                                                      
                          



                               
                               
                            
 

                        

                   
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Facebook */

#include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/filter.h>
#include <linux/unistd.h>
#include <bpf/bpf.h>
#include <sys/resource.h>
#include <libelf.h>
#include <gelf.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <bpf/libbpf.h>
#include <bpf/btf.h>

#include "bpf_rlimit.h"
#include "bpf_util.h"
#include "test_btf.h"

#define MAX_INSNS	512
#define MAX_SUBPROGS	16

static uint32_t pass_cnt;
static uint32_t error_cnt;
static uint32_t skip_cnt;

#define CHECK(condition, format...) ({					\
	int __ret = !!(condition);					\
	if (__ret) {							\
		fprintf(stderr, "%s:%d:FAIL ", __func__, __LINE__);	\
		fprintf(stderr, format);				\
	}								\
	__ret;								\
})

static int count_result(int err)
{
	if (err)
		error_cnt++;
	else
		pass_cnt++;

	fprintf(stderr, "\n");
	return err;
}

static int __base_pr(enum libbpf_print_level level __attribute__((unused)),
		     const char *format, va_list args)
{
	return vfprintf(stderr, format, args);
}

#define BTF_END_RAW 0xdeadbeef
#define NAME_TBD 0xdeadb33f

#define NAME_NTH(N) (0xffff0000 | N)
#define IS_NAME_NTH(X) ((X & 0xffff0000) == 0xffff0000)
#define GET_NAME_NTH_IDX(X) (X & 0x0000ffff)

#define MAX_NR_RAW_U32 1024
#define BTF_LOG_BUF_SIZE 65535

static struct args {
	unsigned int raw_test_num;
	unsigned int file_test_num;
	unsigned int get_info_test_num;
	unsigned int info_raw_test_num;
	unsigned int dedup_test_num;
	bool raw_test;
	bool file_test;
	bool get_info_test;
	bool pprint_test;
	bool always_log;
	bool info_raw_test;
	bool dedup_test;
} args;

static char btf_log_buf[BTF_LOG_BUF_SIZE];

static struct btf_header hdr_tmpl = {
	.magic = BTF_MAGIC,
	.version = BTF_VERSION,
	.hdr_len = sizeof(struct btf_header),
};

/* several different mapv kinds(types) supported by pprint */
enum pprint_mapv_kind_t {
	PPRINT_MAPV_KIND_BASIC = 0,
	PPRINT_MAPV_KIND_INT128,
};

struct btf_raw_test {
	const char *descr;
	const char *str_sec;
	const char *map_name;
	const char *err_str;
	__u32 raw_types[MAX_NR_RAW_U32];
	__u32 str_sec_size;
	enum bpf_map_type map_type;
	__u32 key_size;
	__u32 value_size;
	__u32 key_type_id;
	__u32 value_type_id;
	__u32 max_entries;
	bool btf_load_err;
	bool map_create_err;
	bool ordered_map;
	bool lossless_map;
	bool percpu_map;
	int hdr_len_delta;
	int type_off_delta;
	int str_off_delta;
	int str_len_delta;
	enum pprint_mapv_kind_t mapv_kind;
};

#define BTF_STR_SEC(str) \
	.str_sec = str, .str_sec_size = sizeof(str)

static struct btf_raw_test raw_tests[] = {
/* enum E {
 *     E0,
 *     E1,
 * };
 *
 * struct A {
 *	unsigned long long m;
 *	int n;
 *	char o;
 *	[3 bytes hole]
 *	int p[8];
 *	int q[4][8];
 *	enum E r;
 * };
 */
{
	.descr = "struct test #1",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 6), 180),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		BTF_MEMBER_ENC(NAME_TBD, 6, 384),/* int q[4][8]		*/
		BTF_MEMBER_ENC(NAME_TBD, 7, 1408), /* enum E r		*/
		/* } */
		/* int[4][8] */
		BTF_TYPE_ARRAY_ENC(4, 1, 4),			/* [6] */
		/* enum E */					/* [7] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)),
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_ENUM_ENC(NAME_TBD, 1),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_test1_map",
	.key_size = sizeof(int),
	.value_size = 180,
	.key_type_id = 1,
	.value_type_id = 5,
	.max_entries = 4,
},

/* typedef struct b Struct_B;
 *
 * struct A {
 *     int m;
 *     struct b n[4];
 *     const Struct_B o[4];
 * };
 *
 * struct B {
 *     int m;
 *     int n;
 * };
 */
{
	.descr = "struct test #2",
	.raw_types = {
		/* int */					/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* struct b [4] */				/* [2] */
		BTF_TYPE_ARRAY_ENC(4, 1, 4),

		/* struct A { */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 3), 68),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m;		*/
		BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct B n[4]	*/
		BTF_MEMBER_ENC(NAME_TBD, 8, 288),/* const Struct_B o[4];*/
		/* } */

		/* struct B { */				/* [4] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m; */
		BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */
		/* } */

		/* const int */					/* [5] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),
		/* typedef struct b Struct_B */	/* [6] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 4),
		/* const Struct_B */				/* [7] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 6),
		/* const Struct_B [4] */			/* [8] */
		BTF_TYPE_ARRAY_ENC(7, 1, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0B\0m\0n\0Struct_B",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0B\0m\0n\0Struct_B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_test2_map",
	.key_size = sizeof(int),
	.value_size = 68,
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
},
{
	.descr = "struct test #3 Invalid member offset",
	.raw_types = {
		/* int */					/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int64 */					/* [2] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),

		/* struct A { */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 16),
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),	/* int m;		*/
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),		/* int64 n; */
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0",
	.str_sec_size = sizeof("\0A\0m\0n\0"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_test3_map",
	.key_size = sizeof(int),
	.value_size = 16,
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid member bits_offset",
},
/*
 * struct A {
 *	unsigned long long m;
 *	int n;
 *	char o;
 *	[3 bytes hole]
 *	int p[8];
 * };
 */
{
	.descr = "global data test #1",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_test1_map",
	.key_size = sizeof(int),
	.value_size = 48,
	.key_type_id = 1,
	.value_type_id = 5,
	.max_entries = 4,
},
/*
 * struct A {
 *	unsigned long long m;
 *	int n;
 *	char o;
 *	[3 bytes hole]
 *	int p[8];
 * };
 * static struct A t; <- in .bss
 */
{
	.descr = "global data test #2",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* .bss section */				/* [7] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 48),
		BTF_VAR_SECINFO_ENC(6, 0, 48),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 48,
	.key_type_id = 0,
	.value_type_id = 7,
	.max_entries = 1,
},
{
	.descr = "global data test #3",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* static int t */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [2] */
		/* .bss section */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(2, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0t\0.bss",
	.str_sec_size = sizeof("\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 3,
	.max_entries = 1,
},
{
	.descr = "global data test #4, unsupported linkage",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* static int t */
		BTF_VAR_ENC(NAME_TBD, 1, 2),			/* [2] */
		/* .bss section */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(2, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0t\0.bss",
	.str_sec_size = sizeof("\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 3,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Linkage not supported",
},
{
	.descr = "global data test #5, invalid var type",
	.raw_types = {
		/* static void t */
		BTF_VAR_ENC(NAME_TBD, 0, 0),			/* [1] */
		/* .bss section */				/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(1, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0t\0.bss",
	.str_sec_size = sizeof("\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 2,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},
{
	.descr = "global data test #6, invalid var type (fwd type)",
	.raw_types = {
		/* union A */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_FWD, 1, 0), 0), /* [1] */
		/* static union A t */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [2] */
		/* .bss section */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(2, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0.bss",
	.str_sec_size = sizeof("\0A\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 2,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type",
},
{
	.descr = "global data test #7, invalid var type (fwd type)",
	.raw_types = {
		/* union A */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_FWD, 1, 0), 0), /* [1] */
		/* static union A t */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [2] */
		/* .bss section */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(1, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0.bss",
	.str_sec_size = sizeof("\0A\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 2,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type",
},
{
	.descr = "global data test #8, invalid var size",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* .bss section */				/* [7] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 48),
		BTF_VAR_SECINFO_ENC(6, 0, 47),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 48,
	.key_type_id = 0,
	.value_type_id = 7,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid size",
},
{
	.descr = "global data test #9, invalid var size",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* .bss section */				/* [7] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 46),
		BTF_VAR_SECINFO_ENC(6, 0, 48),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 48,
	.key_type_id = 0,
	.value_type_id = 7,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid size",
},
{
	.descr = "global data test #10, invalid var size",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* .bss section */				/* [7] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 46),
		BTF_VAR_SECINFO_ENC(6, 0, 46),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 48,
	.key_type_id = 0,
	.value_type_id = 7,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid size",
},
{
	.descr = "global data test #11, multiple section members",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* static int u */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [7] */
		/* .bss section */				/* [8] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62),
		BTF_VAR_SECINFO_ENC(6, 10, 48),
		BTF_VAR_SECINFO_ENC(7, 58, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 62,
	.key_type_id = 0,
	.value_type_id = 8,
	.max_entries = 1,
},
{
	.descr = "global data test #12, invalid offset",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* static int u */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [7] */
		/* .bss section */				/* [8] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62),
		BTF_VAR_SECINFO_ENC(6, 10, 48),
		BTF_VAR_SECINFO_ENC(7, 60, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 62,
	.key_type_id = 0,
	.value_type_id = 8,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid offset+size",
},
{
	.descr = "global data test #13, invalid offset",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* static int u */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [7] */
		/* .bss section */				/* [8] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62),
		BTF_VAR_SECINFO_ENC(6, 10, 48),
		BTF_VAR_SECINFO_ENC(7, 12, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 62,
	.key_type_id = 0,
	.value_type_id = 8,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid offset",
},
{
	.descr = "global data test #14, invalid offset",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* unsigned long long */
		BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),		/* [2] */
		/* char */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),	/* [3] */
		/* int[8] */
		BTF_TYPE_ARRAY_ENC(1, 1, 8),			/* [4] */
		/* struct A { */				/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 4), 48),
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),	/* unsigned long long m;*/
		BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;		*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;		*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]		*/
		/* } */
		/* static struct A t */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [6] */
		/* static int u */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [7] */
		/* .bss section */				/* [8] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 2), 62),
		BTF_VAR_SECINFO_ENC(7, 58, 4),
		BTF_VAR_SECINFO_ENC(6, 10, 48),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n\0o\0p\0t\0u\0.bss",
	.str_sec_size = sizeof("\0A\0m\0n\0o\0p\0t\0u\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 62,
	.key_type_id = 0,
	.value_type_id = 8,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid offset",
},
{
	.descr = "global data test #15, not var kind",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [2] */
		/* .bss section */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(1, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0.bss",
	.str_sec_size = sizeof("\0A\0t\0.bss"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 3,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Not a VAR kind member",
},
{
	.descr = "global data test #16, invalid var referencing sec",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_VAR_ENC(NAME_TBD, 5, 0),			/* [2] */
		BTF_VAR_ENC(NAME_TBD, 2, 0),			/* [3] */
		/* a section */					/* [4] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(3, 0, 4),
		/* a section */					/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(6, 0, 4),
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [6] */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0s\0a\0a",
	.str_sec_size = sizeof("\0A\0t\0s\0a\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},
{
	.descr = "global data test #17, invalid var referencing var",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [2] */
		BTF_VAR_ENC(NAME_TBD, 2, 0),			/* [3] */
		/* a section */					/* [4] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(3, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0s\0a\0a",
	.str_sec_size = sizeof("\0A\0t\0s\0a\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},
{
	.descr = "global data test #18, invalid var loop",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_VAR_ENC(NAME_TBD, 2, 0),			/* [2] */
		/* .bss section */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
		BTF_VAR_SECINFO_ENC(2, 0, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0aaa",
	.str_sec_size = sizeof("\0A\0t\0aaa"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},
{
	.descr = "global data test #19, invalid var referencing var",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_VAR_ENC(NAME_TBD, 3, 0),			/* [2] */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [3] */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0s\0a\0a",
	.str_sec_size = sizeof("\0A\0t\0s\0a\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},
{
	.descr = "global data test #20, invalid ptr referencing var",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* PTR type_id=3	*/			/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [3] */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0s\0a\0a",
	.str_sec_size = sizeof("\0A\0t\0s\0a\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},
{
	.descr = "global data test #21, var included in struct",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* struct A { */				/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m; */
		BTF_MEMBER_ENC(NAME_TBD, 3, 32),/* VAR type_id=3; */
		/* } */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [3] */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0s\0a\0a",
	.str_sec_size = sizeof("\0A\0t\0s\0a\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid member",
},
{
	.descr = "global data test #22, array of var",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_ARRAY_ENC(3, 1, 4),			/* [2] */
		BTF_VAR_ENC(NAME_TBD, 1, 0),			/* [3] */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0t\0s\0a\0a",
	.str_sec_size = sizeof("\0A\0t\0s\0a\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = ".bss",
	.key_size = sizeof(int),
	.value_size = 4,
	.key_type_id = 0,
	.value_type_id = 4,
	.max_entries = 1,
	.btf_load_err = true,
	.err_str = "Invalid elem",
},
/* Test member exceeds the size of struct.
 *
 * struct A {
 *     int m;
 *     int n;
 * };
 */
{
	.descr = "size check test #1",
	.raw_types = {
		/* int */					/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* struct A { */				/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 -  1),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m; */
		BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n",
	.str_sec_size = sizeof("\0A\0m\0n"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "size_check1_map",
	.key_size = sizeof(int),
	.value_size = 1,
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Member exceeds struct_size",
},

/* Test member exeeds the size of struct
 *
 * struct A {
 *     int m;
 *     int n[2];
 * };
 */
{
	.descr = "size check test #2",
	.raw_types = {
		/* int */					/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
		/* int[2] */					/* [2] */
		BTF_TYPE_ARRAY_ENC(1, 1, 2),
		/* struct A { */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 3 - 1),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m; */
		BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* int n[2]; */
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n",
	.str_sec_size = sizeof("\0A\0m\0n"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "size_check2_map",
	.key_size = sizeof(int),
	.value_size = 1,
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Member exceeds struct_size",
},

/* Test member exeeds the size of struct
 *
 * struct A {
 *     int m;
 *     void *n;
 * };
 */
{
	.descr = "size check test #3",
	.raw_types = {
		/* int */					/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
		/* void* */					/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
		/* struct A { */				/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) + sizeof(void *) - 1),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m; */
		BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* void *n; */
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0n",
	.str_sec_size = sizeof("\0A\0m\0n"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "size_check3_map",
	.key_size = sizeof(int),
	.value_size = 1,
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Member exceeds struct_size",
},

/* Test member exceeds the size of struct
 *
 * enum E {
 *     E0,
 *     E1,
 * };
 *
 * struct A {
 *     int m;
 *     enum E n;
 * };
 */
{
	.descr = "size check test #4",
	.raw_types = {
		/* int */			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
		/* enum E { */			/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)),
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_ENUM_ENC(NAME_TBD, 1),
		/* } */
		/* struct A { */		/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 - 1),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int m; */
		BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* enum E n; */
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0E\0E0\0E1\0A\0m\0n",
	.str_sec_size = sizeof("\0E\0E0\0E1\0A\0m\0n"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "size_check4_map",
	.key_size = sizeof(int),
	.value_size = 1,
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Member exceeds struct_size",
},

/* typedef const void * const_void_ptr;
 * struct A {
 *	const_void_ptr m;
 * };
 */
{
	.descr = "void test #1",
	.raw_types = {
		/* int */		/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* const void */	/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
		/* const void* */	/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
		/* typedef const void * const_void_ptr */
		BTF_TYPEDEF_ENC(NAME_TBD, 3),	/* [4] */
		/* struct A { */	/* [5] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
		/* const_void_ptr m; */
		BTF_MEMBER_ENC(NAME_TBD, 4, 0),
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0const_void_ptr\0A\0m",
	.str_sec_size = sizeof("\0const_void_ptr\0A\0m"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "void_test1_map",
	.key_size = sizeof(int),
	.value_size = sizeof(void *),
	.key_type_id = 1,
	.value_type_id = 4,
	.max_entries = 4,
},

/* struct A {
 *     const void m;
 * };
 */
{
	.descr = "void test #2",
	.raw_types = {
		/* int */		/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* const void */	/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
		/* struct A { */	/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 8),
		/* const void m; */
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),
		/* } */
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m",
	.str_sec_size = sizeof("\0A\0m"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "void_test2_map",
	.key_size = sizeof(int),
	.value_size = sizeof(void *),
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid member",
},

/* typedef const void * const_void_ptr;
 * const_void_ptr[4]
 */
{
	.descr = "void test #3",
	.raw_types = {
		/* int */		/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* const void */	/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
		/* const void* */	/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
		/* typedef const void * const_void_ptr */
		BTF_TYPEDEF_ENC(NAME_TBD, 3),	/* [4] */
		/* const_void_ptr[4] */
		BTF_TYPE_ARRAY_ENC(4, 1, 4),	/* [5] */
		BTF_END_RAW,
	},
	.str_sec = "\0const_void_ptr",
	.str_sec_size = sizeof("\0const_void_ptr"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "void_test3_map",
	.key_size = sizeof(int),
	.value_size = sizeof(void *) * 4,
	.key_type_id = 1,
	.value_type_id = 5,
	.max_entries = 4,
},

/* const void[4]  */
{
	.descr = "void test #4",
	.raw_types = {
		/* int */		/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* const void */	/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
		/* const void[4] */	/* [3] */
		BTF_TYPE_ARRAY_ENC(2, 1, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m",
	.str_sec_size = sizeof("\0A\0m"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "void_test4_map",
	.key_size = sizeof(int),
	.value_size = sizeof(void *) * 4,
	.key_type_id = 1,
	.value_type_id = 3,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid elem",
},

/* Array_A  <------------------+
 *     elem_type == Array_B    |
 *                    |        |
 *                    |        |
 * Array_B  <-------- +        |
 *      elem_type == Array A --+
 */
{
	.descr = "loop test #1",
	.raw_types = {
		/* int */			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* Array_A */			/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 1, 8),
		/* Array_B */			/* [3] */
		BTF_TYPE_ARRAY_ENC(2, 1, 8),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test1_map",
	.key_size = sizeof(int),
	.value_size = sizeof(sizeof(int) * 8),
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

/* typedef is _before_ the BTF type of Array_A and Array_B
 *
 * typedef Array_B int_array;
 *
 * Array_A  <------------------+
 *     elem_type == int_array  |
 *                    |        |
 *                    |        |
 * Array_B  <-------- +        |
 *      elem_type == Array_A --+
 */
{
	.descr = "loop test #2",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* typedef Array_B int_array */
		BTF_TYPEDEF_ENC(1, 4),				/* [2] */
		/* Array_A */
		BTF_TYPE_ARRAY_ENC(2, 1, 8),			/* [3] */
		/* Array_B */
		BTF_TYPE_ARRAY_ENC(3, 1, 8),			/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "\0int_array\0",
	.str_sec_size = sizeof("\0int_array"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test2_map",
	.key_size = sizeof(int),
	.value_size = sizeof(sizeof(int) * 8),
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

/* Array_A  <------------------+
 *     elem_type == Array_B    |
 *                    |        |
 *                    |        |
 * Array_B  <-------- +        |
 *      elem_type == Array_A --+
 */
{
	.descr = "loop test #3",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* Array_A */				/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 1, 8),
		/* Array_B */				/* [3] */
		BTF_TYPE_ARRAY_ENC(2, 1, 8),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test3_map",
	.key_size = sizeof(int),
	.value_size = sizeof(sizeof(int) * 8),
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

/* typedef is _between_ the BTF type of Array_A and Array_B
 *
 * typedef Array_B int_array;
 *
 * Array_A  <------------------+
 *     elem_type == int_array  |
 *                    |        |
 *                    |        |
 * Array_B  <-------- +        |
 *      elem_type == Array_A --+
 */
{
	.descr = "loop test #4",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* Array_A */				/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 1, 8),
		/* typedef Array_B int_array */		/* [3] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),
		/* Array_B */				/* [4] */
		BTF_TYPE_ARRAY_ENC(2, 1, 8),
		BTF_END_RAW,
	},
	.str_sec = "\0int_array\0",
	.str_sec_size = sizeof("\0int_array"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test4_map",
	.key_size = sizeof(int),
	.value_size = sizeof(sizeof(int) * 8),
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

/* typedef struct B Struct_B
 *
 * struct A {
 *     int x;
 *     Struct_B y;
 * };
 *
 * struct B {
 *     int x;
 *     struct A y;
 * };
 */
{
	.descr = "loop test #5",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* struct A */					/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int x;	*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 32),/* Struct_B y;	*/
		/* typedef struct B Struct_B */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),			/* [3] */
		/* struct B */					/* [4] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int x;	*/
		BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A y;	*/
		BTF_END_RAW,
	},
	.str_sec = "\0A\0x\0y\0Struct_B\0B\0x\0y",
	.str_sec_size = sizeof("\0A\0x\0y\0Struct_B\0B\0x\0y"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test5_map",
	.key_size = sizeof(int),
	.value_size = 8,
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

/* struct A {
 *     int x;
 *     struct A array_a[4];
 * };
 */
{
	.descr = "loop test #6",
	.raw_types = {
		/* int */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_ARRAY_ENC(3, 1, 4),			/* [2] */
		/* struct A */					/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),	/* int x;		*/
		BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A array_a[4];	*/
		BTF_END_RAW,
	},
	.str_sec = "\0A\0x\0y",
	.str_sec_size = sizeof("\0A\0x\0y"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test6_map",
	.key_size = sizeof(int),
	.value_size = 8,
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

{
	.descr = "loop test #7",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* struct A { */			/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
		/*     const void *m;	*/
		BTF_MEMBER_ENC(NAME_TBD, 3, 0),
		/* CONST type_id=3	*/		/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
		/* PTR type_id=2	*/		/* [4] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m",
	.str_sec_size = sizeof("\0A\0m"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test7_map",
	.key_size = sizeof(int),
	.value_size = sizeof(void *),
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

{
	.descr = "loop test #8",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* struct A { */			/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
		/*     const void *m;	*/
		BTF_MEMBER_ENC(NAME_TBD, 4, 0),
		/* struct B { */			/* [3] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
		/*     const void *n;	*/
		BTF_MEMBER_ENC(NAME_TBD, 6, 0),
		/* CONST type_id=5	*/		/* [4] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 5),
		/* PTR type_id=6	*/		/* [5] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),
		/* CONST type_id=7	*/		/* [6] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 7),
		/* PTR type_id=4	*/		/* [7] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 4),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0m\0B\0n",
	.str_sec_size = sizeof("\0A\0m\0B\0n"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "loop_test8_map",
	.key_size = sizeof(int),
	.value_size = sizeof(void *),
	.key_type_id = 1,
	.value_type_id = 2,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Loop detected",
},

{
	.descr = "string section does not end with null",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int") - 1,
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid string section",
},

{
	.descr = "empty string section",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = 0,
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid string section",
},

{
	.descr = "empty type section",
	.raw_types = {
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "No type found",
},

{
	.descr = "btf_header test. Longer hdr_len",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.hdr_len_delta = 4,
	.err_str = "Unsupported btf_header",
},

{
	.descr = "btf_header test. Gap between hdr and type",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.type_off_delta = 4,
	.err_str = "Unsupported section found",
},

{
	.descr = "btf_header test. Gap between type and str",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.str_off_delta = 4,
	.err_str = "Unsupported section found",
},

{
	.descr = "btf_header test. Overlap between type and str",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.str_off_delta = -4,
	.err_str = "Section overlap found",
},

{
	.descr = "btf_header test. Larger BTF size",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.str_len_delta = -4,
	.err_str = "Unsupported section found",
},

{
	.descr = "btf_header test. Smaller BTF size",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0int",
	.str_sec_size = sizeof("\0int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "hdr_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.str_len_delta = 4,
	.err_str = "Total section length too long",
},

{
	.descr = "array test. index_type/elem_type \"int\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int[16] */				/* [2] */
		BTF_TYPE_ARRAY_ENC(1, 1, 16),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "array test. index_type/elem_type \"const int\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int[16] */				/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 3, 16),
		/* CONST type_id=1 */			/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "array test. index_type \"const int:31\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int:31 */				/* [2] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 31, 4),
		/* int[16] */				/* [3] */
		BTF_TYPE_ARRAY_ENC(1, 4, 16),
		/* CONST type_id=2 */			/* [4] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid index",
},

{
	.descr = "array test. elem_type \"const int:31\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int:31 */				/* [2] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 31, 4),
		/* int[16] */				/* [3] */
		BTF_TYPE_ARRAY_ENC(4, 1, 16),
		/* CONST type_id=2 */			/* [4] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid array of int",
},

{
	.descr = "array test. index_type \"void\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int[16] */				/* [2] */
		BTF_TYPE_ARRAY_ENC(1, 0, 16),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid index",
},

{
	.descr = "array test. index_type \"const void\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int[16] */				/* [2] */
		BTF_TYPE_ARRAY_ENC(1, 3, 16),
		/* CONST type_id=0 (void) */		/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid index",
},

{
	.descr = "array test. elem_type \"const void\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int[16] */				/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 1, 16),
		/* CONST type_id=0 (void) */		/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid elem",
},

{
	.descr = "array test. elem_type \"const void *\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* const void *[16] */			/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 1, 16),
		/* CONST type_id=4 */			/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
		/* void* */				/* [4] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "array test. index_type \"const void *\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* const void *[16] */			/* [2] */
		BTF_TYPE_ARRAY_ENC(3, 3, 16),
		/* CONST type_id=4 */			/* [3] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
		/* void* */				/* [4] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid index",
},

{
	.descr = "array test. t->size != 0\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* int[16] */				/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 1),
		BTF_ARRAY_ENC(1, 1, 16),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "size != 0",
},

{
	.descr = "int test. invalid int_data",
	.raw_types = {
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), 4),
		0x10000000,
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid int_data",
},

{
	.descr = "invalid BTF_INFO",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_TYPE_ENC(0, 0x10000000, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info",
},

{
	.descr = "fwd test. t->type != 0\"",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* fwd type */				/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FWD, 0, 0), 1),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "fwd_test_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "type != 0",
},

{
	.descr = "typedef (invalid name, name_off = 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPEDEF_ENC(0, 1),				/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__int",
	.str_sec_size = sizeof("\0__int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "typedef_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "typedef (invalid name, invalid identifier)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPEDEF_ENC(NAME_TBD, 1),			/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__!int",
	.str_sec_size = sizeof("\0__!int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "typedef_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "ptr type (invalid name, name_off <> 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__int",
	.str_sec_size = sizeof("\0__int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "ptr_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "volatile type (invalid name, name_off <> 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__int",
	.str_sec_size = sizeof("\0__int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "volatile_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "const type (invalid name, name_off <> 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__int",
	.str_sec_size = sizeof("\0__int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "const_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "restrict type (invalid name, name_off <> 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 1),	/* [2] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_RESTRICT, 0, 0), 2),	/* [3] */
		BTF_END_RAW,
	},
	.str_sec = "\0__int",
	.str_sec_size = sizeof("\0__int"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "restrict_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "fwd type (invalid name, name_off = 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FWD, 0, 0), 0),	/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__skb",
	.str_sec_size = sizeof("\0__skb"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "fwd_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "fwd type (invalid name, invalid identifier)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_FWD, 0, 0), 0),	/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0__!skb",
	.str_sec_size = sizeof("\0__!skb"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "fwd_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "array type (invalid name, name_off <> 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 0),	/* [2] */
		BTF_ARRAY_ENC(1, 1, 4),
		BTF_END_RAW,
	},
	.str_sec = "\0__skb",
	.str_sec_size = sizeof("\0__skb"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "struct type (name_off = 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0,
			     BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A",
	.str_sec_size = sizeof("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "struct type (invalid name, invalid identifier)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A!\0B",
	.str_sec_size = sizeof("\0A!\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "struct member (name_off = 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0,
			     BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A",
	.str_sec_size = sizeof("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "struct member (invalid name, invalid identifier)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0B*",
	.str_sec_size = sizeof("\0A\0B*"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "enum type (name_off = 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0,
			     BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1),
			     sizeof(int)),				/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A\0B",
	.str_sec_size = sizeof("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "enum_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "enum type (invalid name, invalid identifier)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1),
			     sizeof(int)),				/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A!\0B",
	.str_sec_size = sizeof("\0A!\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "enum_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "enum member (invalid name, name_off = 0)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0,
			     BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1),
			     sizeof(int)),				/* [2] */
		BTF_ENUM_ENC(0, 0),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "enum_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "enum member (invalid name, invalid identifier)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0,
			     BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1),
			     sizeof(int)),				/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0A!",
	.str_sec_size = sizeof("\0A!"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "enum_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},
{
	.descr = "arraymap invalid btf key (a bit field)",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* 32 bit int with 32 bit offset */	/* [2] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 32, 32, 8),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_map_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 2,
	.value_type_id = 1,
	.max_entries = 4,
	.map_create_err = true,
},

{
	.descr = "arraymap invalid btf key (!= 32 bits)",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* 16 bit int with 0 bit offset */	/* [2] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 16, 2),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_map_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 2,
	.value_type_id = 1,
	.max_entries = 4,
	.map_create_err = true,
},

{
	.descr = "arraymap invalid btf value (too small)",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_map_check_btf",
	.key_size = sizeof(int),
	/* btf_value_size < map->value_size */
	.value_size = sizeof(__u64),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.map_create_err = true,
},

{
	.descr = "arraymap invalid btf value (too big)",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_map_check_btf",
	.key_size = sizeof(int),
	/* btf_value_size > map->value_size */
	.value_size = sizeof(__u16),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.map_create_err = true,
},

{
	.descr = "func proto (int (*)(int, unsigned int))",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* int (*)(int, unsigned int) */
		BTF_FUNC_PROTO_ENC(1, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func proto (vararg)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int, unsigned int, ...) */
		BTF_FUNC_PROTO_ENC(0, 3),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
			BTF_FUNC_PROTO_ARG_ENC(0, 0),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func proto (vararg with name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int b, ... c) */
		BTF_FUNC_PROTO_ENC(0, 3),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 0),
		BTF_END_RAW,
	},
	.str_sec = "\0a\0b\0c",
	.str_sec_size = sizeof("\0a\0b\0c"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid arg#3",
},

{
	.descr = "func proto (arg after vararg)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, ..., unsigned int b) */
		BTF_FUNC_PROTO_ENC(0, 3),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 0),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0a\0b",
	.str_sec_size = sizeof("\0a\0b"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid arg#2",
},

{
	.descr = "func proto (CONST=>TYPEDEF=>PTR=>FUNC_PROTO)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* typedef void (*func_ptr)(int, unsigned int) */
		BTF_TYPEDEF_ENC(NAME_TBD, 5),			/* [3] */
		/* const func_ptr */
		BTF_CONST_ENC(3),				/* [4] */
		BTF_PTR_ENC(6),					/* [5] */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [6] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0func_ptr",
	.str_sec_size = sizeof("\0func_ptr"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func proto (TYPEDEF=>FUNC_PROTO)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),			/* [3] */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [4] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0func_typedef",
	.str_sec_size = sizeof("\0func_typedef"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func proto (btf_resolve(arg))",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		/* void (*)(const void *) */
		BTF_FUNC_PROTO_ENC(0, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(0, 3),
		BTF_CONST_ENC(4),				/* [3] */
		BTF_PTR_ENC(0),					/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func proto (Not all arg has name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int, unsigned int b) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0b",
	.str_sec_size = sizeof("\0b"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func proto (Bad arg name_off)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int <bad_name_off>) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(0x0fffffff, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0a",
	.str_sec_size = sizeof("\0a"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid arg#2",
},

{
	.descr = "func proto (Bad arg name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int !!!) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0a\0!!!",
	.str_sec_size = sizeof("\0a\0!!!"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid arg#2",
},

{
	.descr = "func proto (Invalid return type)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* <bad_ret_type> (*)(int, unsigned int) */
		BTF_FUNC_PROTO_ENC(100, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid return type",
},

{
	.descr = "func proto (with func name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void func_proto(int, unsigned int) */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 0),	/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(0, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
		BTF_END_RAW,
	},
	.str_sec = "\0func_proto",
	.str_sec_size = sizeof("\0func_proto"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "func proto (const void arg)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(const void) */
		BTF_FUNC_PROTO_ENC(0, 1),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(0, 4),
		BTF_CONST_ENC(0),				/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid arg#1",
},

{
	.descr = "func (void func(int a, unsigned int b))",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int b) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		/* void func(int a, unsigned int b) */
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "\0a\0b\0func",
	.str_sec_size = sizeof("\0a\0b\0func"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "func (No func name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int b) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		/* void <no_name>(int a, unsigned int b) */
		BTF_FUNC_ENC(0, 3),				/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "\0a\0b",
	.str_sec_size = sizeof("\0a\0b"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "func (Invalid func name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int b) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		/* void !!!(int a, unsigned int b) */
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "\0a\0b\0!!!",
	.str_sec_size = sizeof("\0a\0b\0!!!"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid name",
},

{
	.descr = "func (Some arg has no name)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(0, 2),
		/* void func(int a, unsigned int) */
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "\0a\0func",
	.str_sec_size = sizeof("\0a\0func"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid arg#2",
},

{
	.descr = "func (Non zero vlen)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),		/* [2] */
		/* void (*)(int a, unsigned int b) */
		BTF_FUNC_PROTO_ENC(0, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		/* void func(int a, unsigned int b) */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 3), 	/* [4] */
		BTF_END_RAW,
	},
	.str_sec = "\0a\0b\0func",
	.str_sec_size = sizeof("\0a\0b\0func"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "vlen != 0",
},

{
	.descr = "func (Not referring to FUNC_PROTO)",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_ENC(NAME_TBD, 1),			/* [2] */
		BTF_END_RAW,
	},
	.str_sec = "\0func",
	.str_sec_size = sizeof("\0func"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid type_id",
},

{
	.descr = "invalid int kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_INT, 1, 0), 4),	/* [2] */
		BTF_INT_ENC(0, 0, 32),
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "int_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid ptr kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 1, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "ptr_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid array kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 1, 0), 0),	/* [2] */
		BTF_ARRAY_ENC(1, 1, 1),
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "array_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid enum kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 1, 1), 4),	/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "enum_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "valid fwd kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_FWD, 1, 0), 0),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "fwd_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "invalid typedef kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(NAME_TBD,
			     BTF_INFO_ENC(BTF_KIND_TYPEDEF, 1, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "typedef_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid volatile kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 1, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "volatile_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid const kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 1, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "const_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid restrict kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_RESTRICT, 1, 0), 1),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "restrict_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid func kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 0), 0),	/* [2] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 1, 0), 2),	/* [3] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "invalid func_proto kind_flag",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 1, 0), 0),	/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC(""),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "func_proto_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid btf_info kind_flag",
},

{
	.descr = "valid struct, kind_flag, bitfield_size = 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 8),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(0, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(0, 32)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "valid struct, kind_flag, int member, bitfield_size != 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(4, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(4, 4)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "valid union, kind_flag, int member, bitfield_size != 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 1, 2), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(4, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(4, 0)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "union_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "valid struct, kind_flag, enum member, bitfield_size != 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),	/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 4),/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(4, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(4, 4)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B\0C"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "valid union, kind_flag, enum member, bitfield_size != 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),	/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 1, 2), 4),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(4, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(4, 0)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B\0C"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "union_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "valid struct, kind_flag, typedef member, bitfield_size != 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),	/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 4),/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 4, BTF_MEMBER_OFFSET(4, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 5, BTF_MEMBER_OFFSET(4, 4)),
		BTF_TYPEDEF_ENC(NAME_TBD, 1),				/* [4] */
		BTF_TYPEDEF_ENC(NAME_TBD, 2),				/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B\0C\0D\0E"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "valid union, kind_flag, typedef member, bitfield_size != 0",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),	/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 1, 2), 4),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 4, BTF_MEMBER_OFFSET(4, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 5, BTF_MEMBER_OFFSET(4, 0)),
		BTF_TYPEDEF_ENC(NAME_TBD, 1),				/* [4] */
		BTF_TYPEDEF_ENC(NAME_TBD, 2),				/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B\0C\0D\0E"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "union_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "invalid struct, kind_flag, bitfield_size greater than struct size",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 4),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(20, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(20, 20)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Member exceeds struct_size",
},

{
	.descr = "invalid struct, kind_flag, bitfield base_type int not regular",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 20, 4),			/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 4),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(20, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(20, 20)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid member base type",
},

{
	.descr = "invalid struct, kind_flag, base_type int not regular",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 12, 4),			/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 4),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(8, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(8, 8)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid member base type",
},

{
	.descr = "invalid union, kind_flag, bitfield_size greater than struct size",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),		/* [1] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 1, 2), 2),	/* [2] */
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(8, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 1, BTF_MEMBER_OFFSET(20, 0)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "union_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Member exceeds struct_size",
},

{
	.descr = "invalid struct, kind_flag, int member, bitfield_size = 0, wrong byte alignment",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 12),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 36)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid member offset",
},

{
	.descr = "invalid struct, kind_flag, enum member, bitfield_size = 0, wrong byte alignment",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),	/* [2] */
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 2), 12),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 0)),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 36)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A\0B\0C"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
	.btf_load_err = true,
	.err_str = "Invalid member offset",
},

{
	.descr = "128-bit int",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 128, 16),		/* [2] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "int_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "struct, 128-bit int member",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 128, 16),		/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 16),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "struct, 120-bit int member bitfield",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 120, 16),		/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 16),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "struct, kind_flag, 128-bit int member",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 128, 16),		/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 1), 16),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 0)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},

{
	.descr = "struct, kind_flag, 120-bit int member bitfield",
	.raw_types = {
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),			/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 128, 16),		/* [2] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 1), 16),	/* [3] */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(120, 0)),
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0A"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "struct_type_check_btf",
	.key_size = sizeof(int),
	.value_size = sizeof(int),
	.key_type_id = 1,
	.value_type_id = 1,
	.max_entries = 4,
},
/*
 * typedef int arr_t[16];
 * struct s {
 *	arr_t *a;
 * };
 */
{
	.descr = "struct->ptr->typedef->array->int size resolution",
	.raw_types = {
		BTF_STRUCT_ENC(NAME_TBD, 1, 8),			/* [1] */
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),
		BTF_PTR_ENC(3),					/* [2] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),			/* [3] */
		BTF_TYPE_ARRAY_ENC(5, 5, 16),			/* [4] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0s\0a\0arr_t"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "ptr_mod_chain_size_resolve_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int) * 16,
	.key_type_id = 5 /* int */,
	.value_type_id = 3 /* arr_t */,
	.max_entries = 4,
},
/*
 * typedef int arr_t[16][8][4];
 * struct s {
 *	arr_t *a;
 * };
 */
{
	.descr = "struct->ptr->typedef->multi-array->int size resolution",
	.raw_types = {
		BTF_STRUCT_ENC(NAME_TBD, 1, 8),			/* [1] */
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),
		BTF_PTR_ENC(3),					/* [2] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),			/* [3] */
		BTF_TYPE_ARRAY_ENC(5, 7, 16),			/* [4] */
		BTF_TYPE_ARRAY_ENC(6, 7, 8),			/* [5] */
		BTF_TYPE_ARRAY_ENC(7, 7, 4),			/* [6] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [7] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0s\0a\0arr_t"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "multi_arr_size_resolve_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int) * 16 * 8 * 4,
	.key_type_id = 7 /* int */,
	.value_type_id = 3 /* arr_t */,
	.max_entries = 4,
},
/*
 * typedef int int_t;
 * typedef int_t arr3_t[4];
 * typedef arr3_t arr2_t[8];
 * typedef arr2_t arr1_t[16];
 * struct s {
 *	arr1_t *a;
 * };
 */
{
	.descr = "typedef/multi-arr mix size resolution",
	.raw_types = {
		BTF_STRUCT_ENC(NAME_TBD, 1, 8),			/* [1] */
		BTF_MEMBER_ENC(NAME_TBD, 2, 0),
		BTF_PTR_ENC(3),					/* [2] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),			/* [3] */
		BTF_TYPE_ARRAY_ENC(5, 10, 16),			/* [4] */
		BTF_TYPEDEF_ENC(NAME_TBD, 6),			/* [5] */
		BTF_TYPE_ARRAY_ENC(7, 10, 8),			/* [6] */
		BTF_TYPEDEF_ENC(NAME_TBD, 8),			/* [7] */
		BTF_TYPE_ARRAY_ENC(9, 10, 4),			/* [8] */
		BTF_TYPEDEF_ENC(NAME_TBD, 10),			/* [9] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [10] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0s\0a\0arr1_t\0arr2_t\0arr3_t\0int_t"),
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "typedef_arra_mix_size_resolve_map",
	.key_size = sizeof(int),
	.value_size = sizeof(int) * 16 * 8 * 4,
	.key_type_id = 10 /* int */,
	.value_type_id = 3 /* arr_t */,
	.max_entries = 4,
},

}; /* struct btf_raw_test raw_tests[] */

static const char *get_next_str(const char *start, const char *end)
{
	return start < end - 1 ? start + 1 : NULL;
}

static int get_raw_sec_size(const __u32 *raw_types)
{
	int i;

	for (i = MAX_NR_RAW_U32 - 1;
	     i >= 0 && raw_types[i] != BTF_END_RAW;
	     i--)
		;

	return i < 0 ? i : i * sizeof(raw_types[0]);
}

static void *btf_raw_create(const struct btf_header *hdr,
			    const __u32 *raw_types,
			    const char *str,
			    unsigned int str_sec_size,
			    unsigned int *btf_size,
			    const char **ret_next_str)
{
	const char *next_str = str, *end_str = str + str_sec_size;
	const char **strs_idx = NULL, **tmp_strs_idx;
	int strs_cap = 0, strs_cnt = 0, next_str_idx = 0;
	unsigned int size_needed, offset;
	struct btf_header *ret_hdr;
	int i, type_sec_size, err = 0;
	uint32_t *ret_types;
	void *raw_btf = NULL;

	type_sec_size = get_raw_sec_size(raw_types);
	if (CHECK(type_sec_size < 0, "Cannot get nr_raw_types"))
		return NULL;

	size_needed = sizeof(*hdr) + type_sec_size + str_sec_size;
	raw_btf = malloc(size_needed);
	if (CHECK(!raw_btf, "Cannot allocate memory for raw_btf"))
		return NULL;

	/* Copy header */
	memcpy(raw_btf, hdr, sizeof(*hdr));
	offset = sizeof(*hdr);

	/* Index strings */
	while ((next_str = get_next_str(next_str, end_str))) {
		if (strs_cnt == strs_cap) {
			strs_cap += max(16, strs_cap / 2);
			tmp_strs_idx = realloc(strs_idx,
					       sizeof(*strs_idx) * strs_cap);
			if (CHECK(!tmp_strs_idx,
				  "Cannot allocate memory for strs_idx")) {
				err = -1;
				goto done;
			}
			strs_idx = tmp_strs_idx;
		}
		strs_idx[strs_cnt++] = next_str;
		next_str += strlen(next_str);
	}

	/* Copy type section */
	ret_types = raw_btf + offset;
	for (i = 0; i < type_sec_size / sizeof(raw_types[0]); i++) {
		if (raw_types[i] == NAME_TBD) {
			if (CHECK(next_str_idx == strs_cnt,
				  "Error in getting next_str #%d",
				  next_str_idx)) {
				err = -1;
				goto done;
			}
			ret_types[i] = strs_idx[next_str_idx++] - str;
		} else if (IS_NAME_NTH(raw_types[i])) {
			int idx = GET_NAME_NTH_IDX(raw_types[i]);

			if (CHECK(idx <= 0 || idx > strs_cnt,
				  "Error getting string #%d, strs_cnt:%d",
				  idx, strs_cnt)) {
				err = -1;
				goto done;
			}
			ret_types[i] = strs_idx[idx-1] - str;
		} else {
			ret_types[i] = raw_types[i];
		}
	}
	offset += type_sec_size;

	/* Copy string section */
	memcpy(raw_btf + offset, str, str_sec_size);

	ret_hdr = (struct btf_header *)raw_btf;
	ret_hdr->type_len = type_sec_size;
	ret_hdr->str_off = type_sec_size;
	ret_hdr->str_len = str_sec_size;

	*btf_size = size_needed;
	if (ret_next_str)
		*ret_next_str =
			next_str_idx < strs_cnt ? strs_idx[next_str_idx] : NULL;

done:
	if (err) {
		if (raw_btf)
			free(raw_btf);
		if (strs_idx)
			free(strs_idx);
		return NULL;
	}
	return raw_btf;
}

static int do_test_raw(unsigned int test_num)
{
	struct btf_raw_test *test = &raw_tests[test_num - 1];
	struct bpf_create_map_attr create_attr = {};
	int map_fd = -1, btf_fd = -1;
	unsigned int raw_btf_size;
	struct btf_header *hdr;
	void *raw_btf;
	int err;

	fprintf(stderr, "BTF raw test[%u] (%s): ", test_num, test->descr);
	raw_btf = btf_raw_create(&hdr_tmpl,
				 test->raw_types,
				 test->str_sec,
				 test->str_sec_size,
				 &raw_btf_size, NULL);

	if (!raw_btf)
		return -1;

	hdr = raw_btf;

	hdr->hdr_len = (int)hdr->hdr_len + test->hdr_len_delta;
	hdr->type_off = (int)hdr->type_off + test->type_off_delta;
	hdr->str_off = (int)hdr->str_off + test->str_off_delta;
	hdr->str_len = (int)hdr->str_len + test->str_len_delta;

	*btf_log_buf = '\0';
	btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
			      btf_log_buf, BTF_LOG_BUF_SIZE,
			      args.always_log);
	free(raw_btf);

	err = ((btf_fd == -1) != test->btf_load_err);
	if (CHECK(err, "btf_fd:%d test->btf_load_err:%u",
		  btf_fd, test->btf_load_err) ||
	    CHECK(test->err_str && !strstr(btf_log_buf, test->err_str),
		  "expected err_str:%s", test->err_str)) {
		err = -1;
		goto done;
	}

	if (err || btf_fd == -1)
		goto done;

	create_attr.name = test->map_name;
	create_attr.map_type = test->map_type;
	create_attr.key_size = test->key_size;
	create_attr.value_size = test->value_size;
	create_attr.max_entries = test->max_entries;
	create_attr.btf_fd = btf_fd;
	create_attr.btf_key_type_id = test->key_type_id;
	create_attr.btf_value_type_id = test->value_type_id;

	map_fd = bpf_create_map_xattr(&create_attr);

	err = ((map_fd == -1) != test->map_create_err);
	CHECK(err, "map_fd:%d test->map_create_err:%u",
	      map_fd, test->map_create_err);

done:
	if (!err)
		fprintf(stderr, "OK");

	if (*btf_log_buf && (err || args.always_log))
		fprintf(stderr, "\n%s", btf_log_buf);

	if (btf_fd != -1)
		close(btf_fd);
	if (map_fd != -1)
		close(map_fd);

	return err;
}

static int test_raw(void)
{
	unsigned int i;
	int err = 0;

	if (args.raw_test_num)
		return count_result(do_test_raw(args.raw_test_num));

	for (i = 1; i <= ARRAY_SIZE(raw_tests); i++)
		err |= count_result(do_test_raw(i));

	return err;
}

struct btf_get_info_test {
	const char *descr;
	const char *str_sec;
	__u32 raw_types[MAX_NR_RAW_U32];
	__u32 str_sec_size;
	int btf_size_delta;
	int (*special_test)(unsigned int test_num);
};

static int test_big_btf_info(unsigned int test_num);
static int test_btf_id(unsigned int test_num);

const struct btf_get_info_test get_info_tests[] = {
{
	.descr = "== raw_btf_size+1",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.btf_size_delta = 1,
},
{
	.descr = "== raw_btf_size-3",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.btf_size_delta = -3,
},
{
	.descr = "Large bpf_btf_info",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.special_test = test_big_btf_info,
},
{
	.descr = "BTF ID",
	.raw_types = {
		/* int */				/* [1] */
		BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
		/* unsigned int */			/* [2] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),
		BTF_END_RAW,
	},
	.str_sec = "",
	.str_sec_size = sizeof(""),
	.special_test = test_btf_id,
},
};

static inline __u64 ptr_to_u64(const void *ptr)
{
	return (__u64)(unsigned long)ptr;
}

static int test_big_btf_info(unsigned int test_num)
{
	const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
	uint8_t *raw_btf = NULL, *user_btf = NULL;
	unsigned int raw_btf_size;
	struct {
		struct bpf_btf_info info;
		uint64_t garbage;
	} info_garbage;
	struct bpf_btf_info *info;
	int btf_fd = -1, err;
	uint32_t info_len;

	raw_btf = btf_raw_create(&hdr_tmpl,
				 test->raw_types,
				 test->str_sec,
				 test->str_sec_size,
				 &raw_btf_size, NULL);

	if (!raw_btf)
		return -1;

	*btf_log_buf = '\0';

	user_btf = malloc(raw_btf_size);
	if (CHECK(!user_btf, "!user_btf")) {
		err = -1;
		goto done;
	}

	btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
			      btf_log_buf, BTF_LOG_BUF_SIZE,
			      args.always_log);
	if (CHECK(btf_fd == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	/*
	 * GET_INFO should error out if the userspace info
	 * has non zero tailing bytes.
	 */
	info = &info_garbage.info;
	memset(info, 0, sizeof(*info));
	info_garbage.garbage = 0xdeadbeef;
	info_len = sizeof(info_garbage);
	info->btf = ptr_to_u64(user_btf);
	info->btf_size = raw_btf_size;

	err = bpf_obj_get_info_by_fd(btf_fd, info, &info_len);
	if (CHECK(!err, "!err")) {
		err = -1;
		goto done;
	}

	/*
	 * GET_INFO should succeed even info_len is larger than
	 * the kernel supported as long as tailing bytes are zero.
	 * The kernel supported info len should also be returned
	 * to userspace.
	 */
	info_garbage.garbage = 0;
	err = bpf_obj_get_info_by_fd(btf_fd, info, &info_len);
	if (CHECK(err || info_len != sizeof(*info),
		  "err:%d errno:%d info_len:%u sizeof(*info):%lu",
		  err, errno, info_len, sizeof(*info))) {
		err = -1;
		goto done;
	}

	fprintf(stderr, "OK");

done:
	if (*btf_log_buf && (err || args.always_log))
		fprintf(stderr, "\n%s", btf_log_buf);

	free(raw_btf);
	free(user_btf);

	if (btf_fd != -1)
		close(btf_fd);

	return err;
}

static int test_btf_id(unsigned int test_num)
{
	const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
	struct bpf_create_map_attr create_attr = {};
	uint8_t *raw_btf = NULL, *user_btf[2] = {};
	int btf_fd[2] = {-1, -1}, map_fd = -1;
	struct bpf_map_info map_info = {};
	struct bpf_btf_info info[2] = {};
	unsigned int raw_btf_size;
	uint32_t info_len;
	int err, i, ret;

	raw_btf = btf_raw_create(&hdr_tmpl,
				 test->raw_types,
				 test->str_sec,
				 test->str_sec_size,
				 &raw_btf_size, NULL);

	if (!raw_btf)
		return -1;

	*btf_log_buf = '\0';

	for (i = 0; i < 2; i++) {
		user_btf[i] = malloc(raw_btf_size);
		if (CHECK(!user_btf[i], "!user_btf[%d]", i)) {
			err = -1;
			goto done;
		}
		info[i].btf = ptr_to_u64(user_btf[i]);
		info[i].btf_size = raw_btf_size;
	}

	btf_fd[0] = bpf_load_btf(raw_btf, raw_btf_size,
				 btf_log_buf, BTF_LOG_BUF_SIZE,
				 args.always_log);
	if (CHECK(btf_fd[0] == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	/* Test BPF_OBJ_GET_INFO_BY_ID on btf_id */
	info_len = sizeof(info[0]);
	err = bpf_obj_get_info_by_fd(btf_fd[0], &info[0], &info_len);
	if (CHECK(err, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	btf_fd[1] = bpf_btf_get_fd_by_id(info[0].id);
	if (CHECK(btf_fd[1] == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	ret = 0;
	err = bpf_obj_get_info_by_fd(btf_fd[1], &info[1], &info_len);
	if (CHECK(err || info[0].id != info[1].id ||
		  info[0].btf_size != info[1].btf_size ||
		  (ret = memcmp(user_btf[0], user_btf[1], info[0].btf_size)),
		  "err:%d errno:%d id0:%u id1:%u btf_size0:%u btf_size1:%u memcmp:%d",
		  err, errno, info[0].id, info[1].id,
		  info[0].btf_size, info[1].btf_size, ret)) {
		err = -1;
		goto done;
	}

	/* Test btf members in struct bpf_map_info */
	create_attr.name = "test_btf_id";
	create_attr.map_type = BPF_MAP_TYPE_ARRAY;
	create_attr.key_size = sizeof(int);
	create_attr.value_size = sizeof(unsigned int);
	create_attr.max_entries = 4;
	create_attr.btf_fd = btf_fd[0];
	create_attr.btf_key_type_id = 1;
	create_attr.btf_value_type_id = 2;

	map_fd = bpf_create_map_xattr(&create_attr);
	if (CHECK(map_fd == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	info_len = sizeof(map_info);
	err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
	if (CHECK(err || map_info.btf_id != info[0].id ||
		  map_info.btf_key_type_id != 1 || map_info.btf_value_type_id != 2,
		  "err:%d errno:%d info.id:%u btf_id:%u btf_key_type_id:%u btf_value_type_id:%u",
		  err, errno, info[0].id, map_info.btf_id, map_info.btf_key_type_id,
		  map_info.btf_value_type_id)) {
		err = -1;
		goto done;
	}

	for (i = 0; i < 2; i++) {
		close(btf_fd[i]);
		btf_fd[i] = -1;
	}

	/* Test BTF ID is removed from the kernel */
	btf_fd[0] = bpf_btf_get_fd_by_id(map_info.btf_id);
	if (CHECK(btf_fd[0] == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}
	close(btf_fd[0]);
	btf_fd[0] = -1;

	/* The map holds the last ref to BTF and its btf_id */
	close(map_fd);
	map_fd = -1;
	btf_fd[0] = bpf_btf_get_fd_by_id(map_info.btf_id);
	if (CHECK(btf_fd[0] != -1, "BTF lingers")) {
		err = -1;
		goto done;
	}

	fprintf(stderr, "OK");

done:
	if (*btf_log_buf && (err || args.always_log))
		fprintf(stderr, "\n%s", btf_log_buf);

	free(raw_btf);
	if (map_fd != -1)
		close(map_fd);
	for (i = 0; i < 2; i++) {
		free(user_btf[i]);
		if (btf_fd[i] != -1)
			close(btf_fd[i]);
	}

	return err;
}

static int do_test_get_info(unsigned int test_num)
{
	const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
	unsigned int raw_btf_size, user_btf_size, expected_nbytes;
	uint8_t *raw_btf = NULL, *user_btf = NULL;
	struct bpf_btf_info info = {};
	int btf_fd = -1, err, ret;
	uint32_t info_len;

	fprintf(stderr, "BTF GET_INFO test[%u] (%s): ",
		test_num, test->descr);

	if (test->special_test)
		return test->special_test(test_num);

	raw_btf = btf_raw_create(&hdr_tmpl,
				 test->raw_types,
				 test->str_sec,
				 test->str_sec_size,
				 &raw_btf_size, NULL);

	if (!raw_btf)
		return -1;

	*btf_log_buf = '\0';

	user_btf = malloc(raw_btf_size);
	if (CHECK(!user_btf, "!user_btf")) {
		err = -1;
		goto done;
	}

	btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
			      btf_log_buf, BTF_LOG_BUF_SIZE,
			      args.always_log);
	if (CHECK(btf_fd == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	user_btf_size = (int)raw_btf_size + test->btf_size_delta;
	expected_nbytes = min(raw_btf_size, user_btf_size);
	if (raw_btf_size > expected_nbytes)
		memset(user_btf + expected_nbytes, 0xff,
		       raw_btf_size - expected_nbytes);

	info_len = sizeof(info);
	info.btf = ptr_to_u64(user_btf);
	info.btf_size = user_btf_size;

	ret = 0;
	err = bpf_obj_get_info_by_fd(btf_fd, &info, &info_len);
	if (CHECK(err || !info.id || info_len != sizeof(info) ||
		  info.btf_size != raw_btf_size ||
		  (ret = memcmp(raw_btf, user_btf, expected_nbytes)),
		  "err:%d errno:%d info.id:%u info_len:%u sizeof(info):%lu raw_btf_size:%u info.btf_size:%u expected_nbytes:%u memcmp:%d",
		  err, errno, info.id, info_len, sizeof(info),
		  raw_btf_size, info.btf_size, expected_nbytes, ret)) {
		err = -1;
		goto done;
	}

	while (expected_nbytes < raw_btf_size) {
		fprintf(stderr, "%u...", expected_nbytes);
		if (CHECK(user_btf[expected_nbytes++] != 0xff,
			  "user_btf[%u]:%x != 0xff", expected_nbytes - 1,
			  user_btf[expected_nbytes - 1])) {
			err = -1;
			goto done;
		}
	}

	fprintf(stderr, "OK");

done:
	if (*btf_log_buf && (err || args.always_log))
		fprintf(stderr, "\n%s", btf_log_buf);

	free(raw_btf);
	free(user_btf);

	if (btf_fd != -1)
		close(btf_fd);

	return err;
}

static int test_get_info(void)
{
	unsigned int i;
	int err = 0;

	if (args.get_info_test_num)
		return count_result(do_test_get_info(args.get_info_test_num));

	for (i = 1; i <= ARRAY_SIZE(get_info_tests); i++)
		err |= count_result(do_test_get_info(i));

	return err;
}

struct btf_file_test {
	const char *file;
	bool btf_kv_notfound;
};

static struct btf_file_test file_tests[] = {
	{ .file = "test_btf_haskv.o", },
	{ .file = "test_btf_newkv.o", },
	{ .file = "test_btf_nokv.o", .btf_kv_notfound = true, },
};

static int do_test_file(unsigned int test_num)
{
	const struct btf_file_test *test = &file_tests[test_num - 1];
	const char *expected_fnames[] = {"_dummy_tracepoint",
					 "test_long_fname_1",
					 "test_long_fname_2"};
	struct btf_ext *btf_ext = NULL;
	struct bpf_prog_info info = {};
	struct bpf_object *obj = NULL;
	struct bpf_func_info *finfo;
	struct bpf_program *prog;
	__u32 info_len, rec_size;
	bool has_btf_ext = false;
	struct btf *btf = NULL;
	void *func_info = NULL;
	struct bpf_map *map;
	int i, err, prog_fd;

	fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
		test->file);

	btf = btf__parse_elf(test->file, &btf_ext);
	if (IS_ERR(btf)) {
		if (PTR_ERR(btf) == -ENOENT) {
			fprintf(stderr, "SKIP. No ELF %s found", BTF_ELF_SEC);
			skip_cnt++;
			return 0;
		}
		return PTR_ERR(btf);
	}
	btf__free(btf);

	has_btf_ext = btf_ext != NULL;
	btf_ext__free(btf_ext);

	obj = bpf_object__open(test->file);
	if (CHECK(IS_ERR(obj), "obj: %ld", PTR_ERR(obj)))
		return PTR_ERR(obj);

	err = bpf_object__btf_fd(obj);
	if (CHECK(err == -1, "bpf_object__btf_fd: -1"))
		goto done;

	prog = bpf_program__next(NULL, obj);
	if (CHECK(!prog, "Cannot find bpf_prog")) {
		err = -1;
		goto done;
	}

	bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
	err = bpf_object__load(obj);
	if (CHECK(err < 0, "bpf_object__load: %d", err))
		goto done;
	prog_fd = bpf_program__fd(prog);

	map = bpf_object__find_map_by_name(obj, "btf_map");
	if (CHECK(!map, "btf_map not found")) {
		err = -1;
		goto done;
	}

	err = (bpf_map__btf_key_type_id(map) == 0 || bpf_map__btf_value_type_id(map) == 0)
		!= test->btf_kv_notfound;
	if (CHECK(err, "btf_key_type_id:%u btf_value_type_id:%u test->btf_kv_notfound:%u",
		  bpf_map__btf_key_type_id(map), bpf_map__btf_value_type_id(map),
		  test->btf_kv_notfound))
		goto done;

	if (!has_btf_ext)
		goto skip;

	/* get necessary program info */
	info_len = sizeof(struct bpf_prog_info);
	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);

	if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
		fprintf(stderr, "%s\n", btf_log_buf);
		err = -1;
		goto done;
	}
	if (CHECK(info.nr_func_info != 3,
		  "incorrect info.nr_func_info (1st) %d",
		  info.nr_func_info)) {
		err = -1;
		goto done;
	}
	rec_size = info.func_info_rec_size;
	if (CHECK(rec_size != sizeof(struct bpf_func_info),
		  "incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {
		err = -1;
		goto done;
	}

	func_info = malloc(info.nr_func_info * rec_size);
	if (CHECK(!func_info, "out of memory")) {
		err = -1;
		goto done;
	}

	/* reset info to only retrieve func_info related data */
	memset(&info, 0, sizeof(info));
	info.nr_func_info = 3;
	info.func_info_rec_size = rec_size;
	info.func_info = ptr_to_u64(func_info);

	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);

	if (CHECK(err == -1, "invalid get info (2nd) errno:%d", errno)) {
		fprintf(stderr, "%s\n", btf_log_buf);
		err = -1;
		goto done;
	}
	if (CHECK(info.nr_func_info != 3,
		  "incorrect info.nr_func_info (2nd) %d",
		  info.nr_func_info)) {
		err = -1;
		goto done;
	}
	if (CHECK(info.func_info_rec_size != rec_size,
		  "incorrect info.func_info_rec_size (2nd) %d",
		  info.func_info_rec_size)) {
		err = -1;
		goto done;
	}

	err = btf__get_from_id(info.btf_id, &btf);
	if (CHECK(err, "cannot get btf from kernel, err: %d", err))
		goto done;

	/* check three functions */
	finfo = func_info;
	for (i = 0; i < 3; i++) {
		const struct btf_type *t;
		const char *fname;

		t = btf__type_by_id(btf, finfo->type_id);
		if (CHECK(!t, "btf__type_by_id failure: id %u",
			  finfo->type_id)) {
			err = -1;
			goto done;
		}

		fname = btf__name_by_offset(btf, t->name_off);
		err = strcmp(fname, expected_fnames[i]);
		/* for the second and third functions in .text section,
		 * the compiler may order them either way.
		 */
		if (i && err)
			err = strcmp(fname, expected_fnames[3 - i]);
		if (CHECK(err, "incorrect fname %s", fname ? : "")) {
			err = -1;
			goto done;
		}

		finfo = (void *)finfo + rec_size;
	}

skip:
	fprintf(stderr, "OK");

done:
	free(func_info);
	bpf_object__close(obj);
	return err;
}

static int test_file(void)
{
	unsigned int i;
	int err = 0;

	if (args.file_test_num)
		return count_result(do_test_file(args.file_test_num));

	for (i = 1; i <= ARRAY_SIZE(file_tests); i++)
		err |= count_result(do_test_file(i));

	return err;
}

const char *pprint_enum_str[] = {
	"ENUM_ZERO",
	"ENUM_ONE",
	"ENUM_TWO",
	"ENUM_THREE",
};

struct pprint_mapv {
	uint32_t ui32;
	uint16_t ui16;
	/* 2 bytes hole */
	int32_t si32;
	uint32_t unused_bits2a:2,
		bits28:28,
		unused_bits2b:2;
	union {
		uint64_t ui64;
		uint8_t ui8a[8];
	};
	enum {
		ENUM_ZERO,
		ENUM_ONE,
		ENUM_TWO,
		ENUM_THREE,
	} aenum;
	uint32_t ui32b;
	uint32_t bits2c:2;
	uint8_t si8_4[2][2];
};

#ifdef __SIZEOF_INT128__
struct pprint_mapv_int128 {
	__int128 si128a;
	__int128 si128b;
	unsigned __int128 bits3:3;
	unsigned __int128 bits80:80;
	unsigned __int128 ui128;
};
#endif

static struct btf_raw_test pprint_test_template[] = {
{
	.raw_types = {
		/* unsighed char */			/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
		/* unsigned short */			/* [2] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2),
		/* unsigned int */			/* [3] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),
		/* int */				/* [4] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		/* unsigned long long */		/* [5] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8),
		/* 2 bits */				/* [6] */
		BTF_TYPE_INT_ENC(0, 0, 0, 2, 2),
		/* 28 bits */				/* [7] */
		BTF_TYPE_INT_ENC(0, 0, 0, 28, 4),
		/* uint8_t[8] */			/* [8] */
		BTF_TYPE_ARRAY_ENC(9, 1, 8),
		/* typedef unsigned char uint8_t */	/* [9] */
		BTF_TYPEDEF_ENC(NAME_TBD, 1),
		/* typedef unsigned short uint16_t */	/* [10] */
		BTF_TYPEDEF_ENC(NAME_TBD, 2),
		/* typedef unsigned int uint32_t */	/* [11] */
		BTF_TYPEDEF_ENC(NAME_TBD, 3),
		/* typedef int int32_t */		/* [12] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),
		/* typedef unsigned long long uint64_t *//* [13] */
		BTF_TYPEDEF_ENC(NAME_TBD, 5),
		/* union (anon) */			/* [14] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 13, 0),/* uint64_t ui64; */
		BTF_MEMBER_ENC(NAME_TBD, 8, 0),	/* uint8_t ui8a[8]; */
		/* enum (anon) */			/* [15] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 4), 4),
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_ENUM_ENC(NAME_TBD, 1),
		BTF_ENUM_ENC(NAME_TBD, 2),
		BTF_ENUM_ENC(NAME_TBD, 3),
		/* struct pprint_mapv */		/* [16] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 11), 40),
		BTF_MEMBER_ENC(NAME_TBD, 11, 0),	/* uint32_t ui32 */
		BTF_MEMBER_ENC(NAME_TBD, 10, 32),	/* uint16_t ui16 */
		BTF_MEMBER_ENC(NAME_TBD, 12, 64),	/* int32_t si32 */
		BTF_MEMBER_ENC(NAME_TBD, 6, 96),	/* unused_bits2a */
		BTF_MEMBER_ENC(NAME_TBD, 7, 98),	/* bits28 */
		BTF_MEMBER_ENC(NAME_TBD, 6, 126),	/* unused_bits2b */
		BTF_MEMBER_ENC(0, 14, 128),		/* union (anon) */
		BTF_MEMBER_ENC(NAME_TBD, 15, 192),	/* aenum */
		BTF_MEMBER_ENC(NAME_TBD, 11, 224),	/* uint32_t ui32b */
		BTF_MEMBER_ENC(NAME_TBD, 6, 256),	/* bits2c */
		BTF_MEMBER_ENC(NAME_TBD, 17, 264),	/* si8_4 */
		BTF_TYPE_ARRAY_ENC(18, 1, 2),		/* [17] */
		BTF_TYPE_ARRAY_ENC(1, 1, 2),		/* [18] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0si8_4"),
	.key_size = sizeof(unsigned int),
	.value_size = sizeof(struct pprint_mapv),
	.key_type_id = 3,	/* unsigned int */
	.value_type_id = 16,	/* struct pprint_mapv */
	.max_entries = 128 * 1024,
},

{
	/* this type will have the same type as the
	 * first .raw_types definition, but struct type will
	 * be encoded with kind_flag set.
	 */
	.raw_types = {
		/* unsighed char */			/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
		/* unsigned short */			/* [2] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2),
		/* unsigned int */			/* [3] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),
		/* int */				/* [4] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		/* unsigned long long */		/* [5] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8),
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),	/* [6] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),	/* [7] */
		/* uint8_t[8] */			/* [8] */
		BTF_TYPE_ARRAY_ENC(9, 1, 8),
		/* typedef unsigned char uint8_t */	/* [9] */
		BTF_TYPEDEF_ENC(NAME_TBD, 1),
		/* typedef unsigned short uint16_t */	/* [10] */
		BTF_TYPEDEF_ENC(NAME_TBD, 2),
		/* typedef unsigned int uint32_t */	/* [11] */
		BTF_TYPEDEF_ENC(NAME_TBD, 3),
		/* typedef int int32_t */		/* [12] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),
		/* typedef unsigned long long uint64_t *//* [13] */
		BTF_TYPEDEF_ENC(NAME_TBD, 5),
		/* union (anon) */			/* [14] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 13, 0),/* uint64_t ui64; */
		BTF_MEMBER_ENC(NAME_TBD, 8, 0),	/* uint8_t ui8a[8]; */
		/* enum (anon) */			/* [15] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 4), 4),
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_ENUM_ENC(NAME_TBD, 1),
		BTF_ENUM_ENC(NAME_TBD, 2),
		BTF_ENUM_ENC(NAME_TBD, 3),
		/* struct pprint_mapv */		/* [16] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 11), 40),
		BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),	/* uint32_t ui32 */
		BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)),	/* uint16_t ui16 */
		BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)),	/* int32_t si32 */
		BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 96)),	/* unused_bits2a */
		BTF_MEMBER_ENC(NAME_TBD, 7, BTF_MEMBER_OFFSET(28, 98)),	/* bits28 */
		BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 126)),	/* unused_bits2b */
		BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),	/* union (anon) */
		BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),	/* aenum */
		BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),	/* uint32_t ui32b */
		BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 256)),	/* bits2c */
		BTF_MEMBER_ENC(NAME_TBD, 17, 264),	/* si8_4 */
		BTF_TYPE_ARRAY_ENC(18, 1, 2),		/* [17] */
		BTF_TYPE_ARRAY_ENC(1, 1, 2),		/* [18] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0si8_4"),
	.key_size = sizeof(unsigned int),
	.value_size = sizeof(struct pprint_mapv),
	.key_type_id = 3,	/* unsigned int */
	.value_type_id = 16,	/* struct pprint_mapv */
	.max_entries = 128 * 1024,
},

{
	/* this type will have the same layout as the
	 * first .raw_types definition. The struct type will
	 * be encoded with kind_flag set, bitfield members
	 * are added typedef/const/volatile, and bitfield members
	 * will have both int and enum types.
	 */
	.raw_types = {
		/* unsighed char */			/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
		/* unsigned short */			/* [2] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2),
		/* unsigned int */			/* [3] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),
		/* int */				/* [4] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
		/* unsigned long long */		/* [5] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8),
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),	/* [6] */
		BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),	/* [7] */
		/* uint8_t[8] */			/* [8] */
		BTF_TYPE_ARRAY_ENC(9, 1, 8),
		/* typedef unsigned char uint8_t */	/* [9] */
		BTF_TYPEDEF_ENC(NAME_TBD, 1),
		/* typedef unsigned short uint16_t */	/* [10] */
		BTF_TYPEDEF_ENC(NAME_TBD, 2),
		/* typedef unsigned int uint32_t */	/* [11] */
		BTF_TYPEDEF_ENC(NAME_TBD, 3),
		/* typedef int int32_t */		/* [12] */
		BTF_TYPEDEF_ENC(NAME_TBD, 4),
		/* typedef unsigned long long uint64_t *//* [13] */
		BTF_TYPEDEF_ENC(NAME_TBD, 5),
		/* union (anon) */			/* [14] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 0, 2), 8),
		BTF_MEMBER_ENC(NAME_TBD, 13, 0),/* uint64_t ui64; */
		BTF_MEMBER_ENC(NAME_TBD, 8, 0),	/* uint8_t ui8a[8]; */
		/* enum (anon) */			/* [15] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 4), 4),
		BTF_ENUM_ENC(NAME_TBD, 0),
		BTF_ENUM_ENC(NAME_TBD, 1),
		BTF_ENUM_ENC(NAME_TBD, 2),
		BTF_ENUM_ENC(NAME_TBD, 3),
		/* struct pprint_mapv */		/* [16] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 11), 40),
		BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),	/* uint32_t ui32 */
		BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)),	/* uint16_t ui16 */
		BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)),	/* int32_t si32 */
		BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 96)),	/* unused_bits2a */
		BTF_MEMBER_ENC(NAME_TBD, 7, BTF_MEMBER_OFFSET(28, 98)),	/* bits28 */
		BTF_MEMBER_ENC(NAME_TBD, 19, BTF_MEMBER_OFFSET(2, 126)),/* unused_bits2b */
		BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),	/* union (anon) */
		BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),	/* aenum */
		BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),	/* uint32_t ui32b */
		BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 256)),	/* bits2c */
		BTF_MEMBER_ENC(NAME_TBD, 20, BTF_MEMBER_OFFSET(0, 264)),	/* si8_4 */
		/* typedef unsigned int ___int */	/* [17] */
		BTF_TYPEDEF_ENC(NAME_TBD, 18),
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6),	/* [18] */
		BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15),	/* [19] */
		BTF_TYPE_ARRAY_ENC(21, 1, 2),					/* [20] */
		BTF_TYPE_ARRAY_ENC(1, 1, 2),					/* [21] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int\0si8_4"),
	.key_size = sizeof(unsigned int),
	.value_size = sizeof(struct pprint_mapv),
	.key_type_id = 3,	/* unsigned int */
	.value_type_id = 16,	/* struct pprint_mapv */
	.max_entries = 128 * 1024,
},

#ifdef __SIZEOF_INT128__
{
	/* test int128 */
	.raw_types = {
		/* unsigned int */				/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),
		/* __int128 */					/* [2] */
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 128, 16),
		/* unsigned __int128 */				/* [3] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 128, 16),
		/* struct pprint_mapv_int128 */			/* [4] */
		BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 5), 64),
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 0)),		/* si128a */
		BTF_MEMBER_ENC(NAME_TBD, 2, BTF_MEMBER_OFFSET(0, 128)),		/* si128b */
		BTF_MEMBER_ENC(NAME_TBD, 3, BTF_MEMBER_OFFSET(3, 256)),		/* bits3 */
		BTF_MEMBER_ENC(NAME_TBD, 3, BTF_MEMBER_OFFSET(80, 259)),	/* bits80 */
		BTF_MEMBER_ENC(NAME_TBD, 3, BTF_MEMBER_OFFSET(0, 384)),		/* ui128 */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0unsigned int\0__int128\0unsigned __int128\0pprint_mapv_int128\0si128a\0si128b\0bits3\0bits80\0ui128"),
	.key_size = sizeof(unsigned int),
	.value_size = sizeof(struct pprint_mapv_int128),
	.key_type_id = 1,
	.value_type_id = 4,
	.max_entries = 128 * 1024,
	.mapv_kind = PPRINT_MAPV_KIND_INT128,
},
#endif

};

static struct btf_pprint_test_meta {
	const char *descr;
	enum bpf_map_type map_type;
	const char *map_name;
	bool ordered_map;
	bool lossless_map;
	bool percpu_map;
} pprint_tests_meta[] = {
{
	.descr = "BTF pretty print array",
	.map_type = BPF_MAP_TYPE_ARRAY,
	.map_name = "pprint_test_array",
	.ordered_map = true,
	.lossless_map = true,
	.percpu_map = false,
},

{
	.descr = "BTF pretty print hash",
	.map_type = BPF_MAP_TYPE_HASH,
	.map_name = "pprint_test_hash",
	.ordered_map = false,
	.lossless_map = true,
	.percpu_map = false,
},

{
	.descr = "BTF pretty print lru hash",
	.map_type = BPF_MAP_TYPE_LRU_HASH,
	.map_name = "pprint_test_lru_hash",
	.ordered_map = false,
	.lossless_map = false,
	.percpu_map = false,
},

{
	.descr = "BTF pretty print percpu array",
	.map_type = BPF_MAP_TYPE_PERCPU_ARRAY,
	.map_name = "pprint_test_percpu_array",
	.ordered_map = true,
	.lossless_map = true,
	.percpu_map = true,
},

{
	.descr = "BTF pretty print percpu hash",
	.map_type = BPF_MAP_TYPE_PERCPU_HASH,
	.map_name = "pprint_test_percpu_hash",
	.ordered_map = false,
	.lossless_map = true,
	.percpu_map = true,
},

{
	.descr = "BTF pretty print lru percpu hash",
	.map_type = BPF_MAP_TYPE_LRU_PERCPU_HASH,
	.map_name = "pprint_test_lru_percpu_hash",
	.ordered_map = false,
	.lossless_map = false,
	.percpu_map = true,
},

};

static size_t get_pprint_mapv_size(enum pprint_mapv_kind_t mapv_kind)
{
	if (mapv_kind == PPRINT_MAPV_KIND_BASIC)
		return sizeof(struct pprint_mapv);

#ifdef __SIZEOF_INT128__
	if (mapv_kind == PPRINT_MAPV_KIND_INT128)
		return sizeof(struct pprint_mapv_int128);
#endif

	assert(0);
}

static void set_pprint_mapv(enum pprint_mapv_kind_t mapv_kind,
			    void *mapv, uint32_t i,
			    int num_cpus, int rounded_value_size)
{
	int cpu;

	if (mapv_kind == PPRINT_MAPV_KIND_BASIC) {
		struct pprint_mapv *v = mapv;

		for (cpu = 0; cpu < num_cpus; cpu++) {
			v->ui32 = i + cpu;
			v->si32 = -i;
			v->unused_bits2a = 3;
			v->bits28 = i;
			v->unused_bits2b = 3;
			v->ui64 = i;
			v->aenum = i & 0x03;
			v->ui32b = 4;
			v->bits2c = 1;
			v->si8_4[0][0] = (cpu + i) & 0xff;
			v->si8_4[0][1] = (cpu + i + 1) & 0xff;
			v->si8_4[1][0] = (cpu + i + 2) & 0xff;
			v->si8_4[1][1] = (cpu + i + 3) & 0xff;
			v = (void *)v + rounded_value_size;
		}
	}

#ifdef __SIZEOF_INT128__
	if (mapv_kind == PPRINT_MAPV_KIND_INT128) {
		struct pprint_mapv_int128 *v = mapv;

		for (cpu = 0; cpu < num_cpus; cpu++) {
			v->si128a = i;
			v->si128b = -i;
			v->bits3 = i & 0x07;
			v->bits80 = (((unsigned __int128)1) << 64) + i;
			v->ui128 = (((unsigned __int128)2) << 64) + i;
			v = (void *)v + rounded_value_size;
		}
	}
#endif
}

ssize_t get_pprint_expected_line(enum pprint_mapv_kind_t mapv_kind,
				 char *expected_line, ssize_t line_size,
				 bool percpu_map, unsigned int next_key,
				 int cpu, void *mapv)
{
	ssize_t nexpected_line = -1;

	if (mapv_kind == PPRINT_MAPV_KIND_BASIC) {
		struct pprint_mapv *v = mapv;

		nexpected_line = snprintf(expected_line, line_size,
					  "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
					  "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s,"
					  "%u,0x%x,[[%d,%d],[%d,%d]]}\n",
					  percpu_map ? "\tcpu" : "",
					  percpu_map ? cpu : next_key,
					  v->ui32, v->si32,
					  v->unused_bits2a,
					  v->bits28,
					  v->unused_bits2b,
					  v->ui64,
					  v->ui8a[0], v->ui8a[1],
					  v->ui8a[2], v->ui8a[3],
					  v->ui8a[4], v->ui8a[5],
					  v->ui8a[6], v->ui8a[7],
					  pprint_enum_str[v->aenum],
					  v->ui32b,
					  v->bits2c,
					  v->si8_4[0][0], v->si8_4[0][1],
					  v->si8_4[1][0], v->si8_4[1][1]);
	}

#ifdef __SIZEOF_INT128__
	if (mapv_kind == PPRINT_MAPV_KIND_INT128) {
		struct pprint_mapv_int128 *v = mapv;

		nexpected_line = snprintf(expected_line, line_size,
					  "%s%u: {0x%lx,0x%lx,0x%lx,"
					  "0x%lx%016lx,0x%lx%016lx}\n",
					  percpu_map ? "\tcpu" : "",
					  percpu_map ? cpu : next_key,
					  (uint64_t)v->si128a,
					  (uint64_t)v->si128b,
					  (uint64_t)v->bits3,
					  (uint64_t)(v->bits80 >> 64),
					  (uint64_t)v->bits80,
					  (uint64_t)(v->ui128 >> 64),
					  (uint64_t)v->ui128);
	}
#endif

	return nexpected_line;
}

static int check_line(const char *expected_line, int nexpected_line,
		      int expected_line_len, const char *line)
{
	if (CHECK(nexpected_line == expected_line_len,
		  "expected_line is too long"))
		return -1;

	if (strcmp(expected_line, line)) {
		fprintf(stderr, "unexpected pprint output\n");
		fprintf(stderr, "expected: %s", expected_line);
		fprintf(stderr, "    read: %s", line);
		return -1;
	}

	return 0;
}


static int do_test_pprint(int test_num)
{
	const struct btf_raw_test *test = &pprint_test_template[test_num];
	enum pprint_mapv_kind_t mapv_kind = test->mapv_kind;
	struct bpf_create_map_attr create_attr = {};
	bool ordered_map, lossless_map, percpu_map;
	int err, ret, num_cpus, rounded_value_size;
	unsigned int key, nr_read_elems;
	int map_fd = -1, btf_fd = -1;
	unsigned int raw_btf_size;
	char expected_line[255];
	FILE *pin_file = NULL;
	char pin_path[255];
	size_t line_len = 0;
	char *line = NULL;
	void *mapv = NULL;
	uint8_t *raw_btf;
	ssize_t nread;

	fprintf(stderr, "%s(#%d)......", test->descr, test_num);
	raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
				 test->str_sec, test->str_sec_size,
				 &raw_btf_size, NULL);

	if (!raw_btf)
		return -1;

	*btf_log_buf = '\0';
	btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
			      btf_log_buf, BTF_LOG_BUF_SIZE,
			      args.always_log);
	free(raw_btf);

	if (CHECK(btf_fd == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	create_attr.name = test->map_name;
	create_attr.map_type = test->map_type;
	create_attr.key_size = test->key_size;
	create_attr.value_size = test->value_size;
	create_attr.max_entries = test->max_entries;
	create_attr.btf_fd = btf_fd;
	create_attr.btf_key_type_id = test->key_type_id;
	create_attr.btf_value_type_id = test->value_type_id;

	map_fd = bpf_create_map_xattr(&create_attr);
	if (CHECK(map_fd == -1, "errno:%d", errno)) {
		err = -1;
		goto done;
	}

	ret = snprintf(pin_path, sizeof(pin_path), "%s/%s",
		       "/sys/fs/bpf", test->map_name);

	if (CHECK(ret == sizeof(pin_path), "pin_path %s/%s is too long",
		  "/sys/fs/bpf", test->map_name)) {
		err = -1;
		goto done;
	}

	err = bpf_obj_pin(map_fd, pin_path);
	if (CHECK(err, "bpf_obj_pin(%s): errno:%d.", pin_path, errno))
		goto done;

	percpu_map = test->percpu_map;
	num_cpus = percpu_map ? bpf_num_possible_cpus() : 1;
	rounded_value_size = round_up(get_pprint_mapv_size(mapv_kind), 8);
	mapv = calloc(num_cpus, rounded_value_size);
	if (CHECK(!mapv, "mapv allocation failure")) {
		err = -1;
		goto done;
	}

	for (key = 0; key < test->max_entries; key++) {
		set_pprint_mapv(mapv_kind, mapv, key, num_cpus, rounded_value_size);
		bpf_map_update_elem(map_fd, &key, mapv, 0);
	}

	pin_file = fopen(pin_path, "r");
	if (CHECK(!pin_file, "fopen(%s): errno:%d", pin_path, errno)) {
		err = -1;
		goto done;
	}

	/* Skip lines start with '#' */
	while ((nread = getline(&line, &line_len, pin_file)) > 0 &&
	       *line == '#')
		;

	if (CHECK(nread <= 0, "Unexpected EOF")) {
		err = -1;
		goto done;
	}

	nr_read_elems = 0;
	ordered_map = test->ordered_map;
	lossless_map = test->lossless_map;
	do {
		ssize_t nexpected_line;
		unsigned int next_key;
		void *cmapv;
		int cpu;

		next_key = ordered_map ? nr_read_elems : atoi(line);
		set_pprint_mapv(mapv_kind, mapv, next_key, num_cpus, rounded_value_size);
		cmapv = mapv;

		for (cpu = 0; cpu < num_cpus; cpu++) {
			if (percpu_map) {
				/* for percpu map, the format looks like:
				 * <key>: {
				 *	cpu0: <value_on_cpu0>
				 *	cpu1: <value_on_cpu1>
				 *	...
				 *	cpun: <value_on_cpun>
				 * }
				 *
				 * let us verify the line containing the key here.
				 */
				if (cpu == 0) {
					nexpected_line = snprintf(expected_line,
								  sizeof(expected_line),
								  "%u: {\n",
								  next_key);

					err = check_line(expected_line, nexpected_line,
							 sizeof(expected_line), line);
					if (err == -1)
						goto done;
				}

				/* read value@cpu */
				nread = getline(&line, &line_len, pin_file);
				if (nread < 0)
					break;
			}

			nexpected_line = get_pprint_expected_line(mapv_kind, expected_line,
								  sizeof(expected_line),
								  percpu_map, next_key,
								  cpu, cmapv);
			err = check_line(expected_line, nexpected_line,
					 sizeof(expected_line), line);
			if (err == -1)
				goto done;

			cmapv = cmapv + rounded_value_size;
		}

		if (percpu_map) {
			/* skip the last bracket for the percpu map */
			nread = getline(&line, &line_len, pin_file);
			if (nread < 0)
				break;
		}

		nread = getline(&line, &line_len, pin_file);
	} while (++nr_read_elems < test->max_entries && nread > 0);

	if (lossless_map &&
	    CHECK(nr_read_elems < test->max_entries,
		  "Unexpected EOF. nr_read_elems:%u test->max_entries:%u",
		  nr_read_elems, test->max_entries)) {
		err = -1;
		goto done;
	}

	if (CHECK(nread > 0, "Unexpected extra pprint output: %s", line)) {
		err = -1;
		goto done;
	}

	err = 0;

done:
	if (mapv)
		free(mapv);
	if (!err)
		fprintf(stderr, "OK");
	if (*btf_log_buf && (err || args.always_log))
		fprintf(stderr, "\n%s", btf_log_buf);
	if (btf_fd != -1)
		close(btf_fd);
	if (map_fd != -1)
		close(map_fd);
	if (pin_file)
		fclose(pin_file);
	unlink(pin_path);
	free(line);

	return err;
}

static int test_pprint(void)
{
	unsigned int i;
	int err = 0;

	/* test various maps with the first test template */
	for (i = 0; i < ARRAY_SIZE(pprint_tests_meta); i++) {
		pprint_test_template[0].descr = pprint_tests_meta[i].descr;
		pprint_test_template[0].map_type = pprint_tests_meta[i].map_type;
		pprint_test_template[0].map_name = pprint_tests_meta[i].map_name;
		pprint_test_template[0].ordered_map = pprint_tests_meta[i].ordered_map;
		pprint_test_template[0].lossless_map = pprint_tests_meta[i].lossless_map;
		pprint_test_template[0].percpu_map = pprint_tests_meta[i].percpu_map;

		err |= count_result(do_test_pprint(0));
	}

	/* test rest test templates with the first map */
	for (i = 1; i < ARRAY_SIZE(pprint_test_template); i++) {
		pprint_test_template[i].descr = pprint_tests_meta[0].descr;
		pprint_test_template[i].map_type = pprint_tests_meta[0].map_type;
		pprint_test_template[i].map_name = pprint_tests_meta[0].map_name;
		pprint_test_template[i].ordered_map = pprint_tests_meta[0].ordered_map;
		pprint_test_template[i].lossless_map = pprint_tests_meta[0].lossless_map;
		pprint_test_template[i].percpu_map = pprint_tests_meta[0].percpu_map;
		err |= count_result(do_test_pprint(i));
	}

	return err;
}

#define BPF_LINE_INFO_ENC(insn_off, file_off, line_off, line_num, line_col) \
	(insn_off), (file_off), (line_off), ((line_num) << 10 | ((line_col) & 0x3ff))

static struct prog_info_raw_test {
	const char *descr;
	const char *str_sec;
	const char *err_str;
	__u32 raw_types[MAX_NR_RAW_U32];
	__u32 str_sec_size;
	struct bpf_insn insns[MAX_INSNS];
	__u32 prog_type;
	__u32 func_info[MAX_SUBPROGS][2];
	__u32 func_info_rec_size;
	__u32 func_info_cnt;
	__u32 line_info[MAX_NR_RAW_U32];
	__u32 line_info_rec_size;
	__u32 nr_jited_ksyms;
	bool expected_prog_load_failure;
	__u32 dead_code_cnt;
	__u32 dead_code_mask;
	__u32 dead_func_cnt;
	__u32 dead_func_mask;
} info_raw_tests[] = {
{
	.descr = "func_type (main func + one sub)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),	/* [2] */
		BTF_FUNC_PROTO_ENC(1, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_FUNC_PROTO_ENC(1, 2),			/* [4] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [5] */
		BTF_FUNC_ENC(NAME_TBD, 4),			/* [6] */
		BTF_END_RAW,
	},
	.str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
	.str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
	.insns = {
		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 2),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info = { {0, 5}, {3, 6} },
	.func_info_rec_size = 8,
	.func_info_cnt = 2,
	.line_info = { BTF_END_RAW },
},

{
	.descr = "func_type (Incorrect func_info_rec_size)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),	/* [2] */
		BTF_FUNC_PROTO_ENC(1, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_FUNC_PROTO_ENC(1, 2),			/* [4] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [5] */
		BTF_FUNC_ENC(NAME_TBD, 4),			/* [6] */
		BTF_END_RAW,
	},
	.str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
	.str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
	.insns = {
		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 2),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info = { {0, 5}, {3, 6} },
	.func_info_rec_size = 4,
	.func_info_cnt = 2,
	.line_info = { BTF_END_RAW },
	.expected_prog_load_failure = true,
},

{
	.descr = "func_type (Incorrect func_info_cnt)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),	/* [2] */
		BTF_FUNC_PROTO_ENC(1, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_FUNC_PROTO_ENC(1, 2),			/* [4] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [5] */
		BTF_FUNC_ENC(NAME_TBD, 4),			/* [6] */
		BTF_END_RAW,
	},
	.str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
	.str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
	.insns = {
		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 2),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info = { {0, 5}, {3, 6} },
	.func_info_rec_size = 8,
	.func_info_cnt = 1,
	.line_info = { BTF_END_RAW },
	.expected_prog_load_failure = true,
},

{
	.descr = "func_type (Incorrect bpf_func_info.insn_off)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),	/* [2] */
		BTF_FUNC_PROTO_ENC(1, 2),			/* [3] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
		BTF_FUNC_PROTO_ENC(1, 2),			/* [4] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 3),			/* [5] */
		BTF_FUNC_ENC(NAME_TBD, 4),			/* [6] */
		BTF_END_RAW,
	},
	.str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
	.str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
	.insns = {
		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 2),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info = { {0, 5}, {2, 6} },
	.func_info_rec_size = 8,
	.func_info_cnt = 2,
	.line_info = { BTF_END_RAW },
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (No subprog)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_MOV64_IMM(BPF_REG_1, 2),
		BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 1,
},

{
	.descr = "line_info (No subprog. insn_off >= prog->len)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_MOV64_IMM(BPF_REG_1, 2),
		BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7),
		BPF_LINE_INFO_ENC(4, 0, 0, 5, 6),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 1,
	.err_str = "line_info[4].insn_off",
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (Zero bpf insn code)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8),	/* [2] */
		BTF_TYPEDEF_ENC(NAME_TBD, 2),			/* [3] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0unsigned long\0u64\0u64 a=1;\0return a;"),
	.insns = {
		BPF_LD_IMM64(BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(1, 0, 0, 2, 9),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 1,
	.err_str = "Invalid insn code at line_info[1]",
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (No subprog. zero tailing line_info",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_MOV64_IMM(BPF_REG_1, 2),
		BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 0,
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 0,
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 0,
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 0,
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info) + sizeof(__u32),
	.nr_jited_ksyms = 1,
},

{
	.descr = "line_info (No subprog. nonzero tailing line_info)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_MOV64_IMM(BPF_REG_1, 2),
		BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10), 0,
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9), 0,
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8), 0,
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7), 1,
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info) + sizeof(__u32),
	.nr_jited_ksyms = 1,
	.err_str = "nonzero tailing record in line_info",
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (subprog)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
},

{
	.descr = "line_info (subprog + func_info)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [4] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0sub\0main\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 2,
	.func_info_rec_size = 8,
	.func_info = { {0, 4}, {5, 3} },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
},

{
	.descr = "line_info (subprog. missing 1st func line info)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.err_str = "missing bpf_line_info for func#0",
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (subprog. missing 2nd func line info)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.err_str = "missing bpf_line_info for func#1",
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (subprog. unordered insn offset)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1+1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.err_str = "Invalid line_info[2].insn_off",
	.expected_prog_load_failure = true,
},

{
	.descr = "line_info (dead start)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0/* dead jmp */\0int a=1;\0int b=2;\0return a + b;\0return a + b;"),
	.insns = {
		BPF_JMP_IMM(BPF_JA, 0, 0, 0),
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_MOV64_IMM(BPF_REG_1, 2),
		BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 7),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 5, 6),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 1,
	.dead_code_cnt = 1,
	.dead_code_mask = 0x01,
},

{
	.descr = "line_info (dead end)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0int a=1;\0int b=2;\0return a + b;\0/* dead jmp */\0return a + b;\0/* dead exit */"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_MOV64_IMM(BPF_REG_1, 2),
		BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 10, 1),
		BPF_EXIT_INSN(),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 0,
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 12),
		BPF_LINE_INFO_ENC(1, 0, NAME_TBD, 2, 11),
		BPF_LINE_INFO_ENC(2, 0, NAME_TBD, 3, 10),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 4, 9),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 5, 8),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 6, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 1,
	.dead_code_cnt = 2,
	.dead_code_mask = 0x28,
},

{
	.descr = "line_info (dead code + subprog + func_info)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [4] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0sub\0main\0int a=1+1;\0/* dead jmp */"
		    "\0/* dead */\0/* dead */\0/* dead */\0/* dead */"
		    "\0/* dead */\0/* dead */\0/* dead */\0/* dead */"
		    "\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
		BPF_MOV64_REG(BPF_REG_1, BPF_REG_2),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 8),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 2,
	.func_info_rec_size = 8,
	.func_info = { {0, 4}, {14, 3} },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(8, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(9, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(10, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(11, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(12, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(14, 0, NAME_TBD, 3, 8),
		BPF_LINE_INFO_ENC(16, 0, NAME_TBD, 4, 7),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.dead_code_cnt = 9,
	.dead_code_mask = 0x3fe,
},

{
	.descr = "line_info (dead subprog)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [4] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0dead\0main\0func\0int a=1+1;\0/* live call */"
		    "\0return 0;\0return 0;\0/* dead */\0/* dead */"
		    "\0/* dead */\0return bla + 1;\0return bla + 1;"
		    "\0return bla + 1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
		BPF_CALL_REL(3),
		BPF_CALL_REL(5),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_MOV64_REG(BPF_REG_0, 2),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 3,
	.func_info_rec_size = 8,
		.func_info = { {0, 4}, {6, 3}, {9, 5} },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(8, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(9, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(10, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(11, 0, NAME_TBD, 2, 9),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.dead_code_cnt = 3,
	.dead_code_mask = 0x70,
	.dead_func_cnt = 1,
	.dead_func_mask = 0x2,
},

{
	.descr = "line_info (dead last subprog)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0dead\0main\0int a=1+1;\0/* live call */"
		    "\0return 0;\0/* dead */\0/* dead */"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
		BPF_CALL_REL(2),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 2,
	.func_info_rec_size = 8,
		.func_info = { {0, 4}, {5, 3} },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 1, 10),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 1,
	.dead_code_cnt = 2,
	.dead_code_mask = 0x18,
	.dead_func_cnt = 1,
	.dead_func_mask = 0x2,
},

{
	.descr = "line_info (dead subprog + dead start)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [4] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0dead\0main\0func\0int a=1+1;\0/* dead */"
		    "\0return 0;\0return 0;\0return 0;"
		    "\0/* dead */\0/* dead */\0/* dead */\0/* dead */"
		    "\0return b + 1;\0return b + 1;\0return b + 1;"),
	.insns = {
		BPF_JMP_IMM(BPF_JA, 0, 0, 0),
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
		BPF_CALL_REL(3),
		BPF_CALL_REL(5),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_JMP_IMM(BPF_JA, 0, 0, 0),
		BPF_MOV64_REG(BPF_REG_0, 2),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 3,
	.func_info_rec_size = 8,
		.func_info = { {0, 4}, {7, 3}, {10, 5} },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(8, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(9, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(10, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(11, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(12, 0, NAME_TBD, 2, 9),
		BPF_LINE_INFO_ENC(13, 0, NAME_TBD, 2, 9),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.dead_code_cnt = 5,
	.dead_code_mask = 0x1e2,
	.dead_func_cnt = 1,
	.dead_func_mask = 0x2,
},

{
	.descr = "line_info (dead subprog + dead start w/ move)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [4] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [5] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0dead\0main\0func\0int a=1+1;\0/* live call */"
		    "\0return 0;\0return 0;\0/* dead */\0/* dead */"
		    "\0/* dead */\0return bla + 1;\0return bla + 1;"
		    "\0return bla + 1;\0return func(a);\0b+=1;\0return b;"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_2, 1),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_2, 0, 1),
		BPF_CALL_REL(3),
		BPF_CALL_REL(5),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_CALL_REL(1),
		BPF_EXIT_INSN(),
		BPF_JMP_IMM(BPF_JA, 0, 0, 0),
		BPF_MOV64_REG(BPF_REG_0, 2),
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 3,
	.func_info_rec_size = 8,
		.func_info = { {0, 4}, {6, 3}, {9, 5} },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(3, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(4, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(5, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(7, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(8, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(9, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(11, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(12, 0, NAME_TBD, 2, 9),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
	.dead_code_cnt = 3,
	.dead_code_mask = 0x70,
	.dead_func_cnt = 1,
	.dead_func_mask = 0x2,
},

{
	.descr = "line_info (dead end + subprog start w/ no linfo)",
	.raw_types = {
		BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
		BTF_FUNC_PROTO_ENC(1, 1),			/* [2] */
			BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [3] */
		BTF_FUNC_ENC(NAME_TBD, 2),			/* [4] */
		BTF_END_RAW,
	},
	BTF_STR_SEC("\0int\0x\0main\0func\0/* main linfo */\0/* func linfo */"),
	.insns = {
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 1, 3),
		BPF_CALL_REL(3),
		BPF_MOV64_IMM(BPF_REG_0, 0),
		BPF_EXIT_INSN(),
		BPF_EXIT_INSN(),
		BPF_JMP_IMM(BPF_JA, 0, 0, 0),
		BPF_EXIT_INSN(),
	},
	.prog_type = BPF_PROG_TYPE_TRACEPOINT,
	.func_info_cnt = 2,
	.func_info_rec_size = 8,
	.func_info = { {0, 3}, {6, 4}, },
	.line_info = {
		BPF_LINE_INFO_ENC(0, 0, NAME_TBD, 1, 10),
		BPF_LINE_INFO_ENC(6, 0, NAME_TBD, 1, 10),
		BTF_END_RAW,
	},
	.line_info_rec_size = sizeof(struct bpf_line_info),
	.nr_jited_ksyms = 2,
},

};

static size_t probe_prog_length(const struct bpf_insn *fp)
{
	size_t len;

	for (len = MAX_INSNS - 1; len > 0; --len)
		if (fp[len].code != 0 || fp[len].imm != 0)
			break;
	return len + 1;
}

static __u32 *patch_name_tbd(const __u32 *raw_u32,
			     const char *str, __u32 str_off,
			     unsigned int str_sec_size,
			     unsigned int *ret_size)
{
	int i, raw_u32_size = get_raw_sec_size(raw_u32);
	const char *end_str = str + str_sec_size;
	const char *next_str = str + str_off;
	__u32 *new_u32 = NULL;

	if (raw_u32_size == -1)
		return ERR_PTR(-EINVAL);

	if (!raw_u32_size) {
		*ret_size = 0;
		return NULL;
	}

	new_u32 = malloc(raw_u32_size);
	if (!new_u32)
		return ERR_PTR(-ENOMEM);

	for (i = 0; i < raw_u32_size / sizeof(raw_u32[0]); i++) {
		if (raw_u32[i] == NAME_TBD) {
			next_str = get_next_str(next_str, end_str);
			if (CHECK(!next_str, "Error in getting next_str\n")) {
				free(new_u32);
				return ERR_PTR(-EINVAL);
			}
			new_u32[i] = next_str - str;
			next_str += strlen(next_str);
		} else {
			new_u32[i] = raw_u32[i];
		}
	}

	*ret_size = raw_u32_size;
	return new_u32;
}

static int test_get_finfo(const struct prog_info_raw_test *test,
			  int prog_fd)
{
	struct bpf_prog_info info = {};
	struct bpf_func_info *finfo;
	__u32 info_len, rec_size, i;
	void *func_info = NULL;
	__u32 nr_func_info;
	int err;

	/* get necessary lens */
	info_len = sizeof(struct bpf_prog_info);
	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
		fprintf(stderr, "%s\n", btf_log_buf);
		return -1;
	}
	nr_func_info = test->func_info_cnt - test->dead_func_cnt;
	if (CHECK(info.nr_func_info != nr_func_info,
		  "incorrect info.nr_func_info (1st) %d",
		  info.nr_func_info)) {
		return -1;
	}

	rec_size = info.func_info_rec_size;
	if (CHECK(rec_size != sizeof(struct bpf_func_info),
		  "incorrect info.func_info_rec_size (1st) %d", rec_size)) {
		return -1;
	}

	if (!info.nr_func_info)
		return 0;

	func_info = malloc(info.nr_func_info * rec_size);
	if (CHECK(!func_info, "out of memory"))
		return -1;

	/* reset info to only retrieve func_info related data */
	memset(&info, 0, sizeof(info));
	info.nr_func_info = nr_func_info;
	info.func_info_rec_size = rec_size;
	info.func_info = ptr_to_u64(func_info);
	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (CHECK(err == -1, "invalid get info (2nd) errno:%d", errno)) {
		fprintf(stderr, "%s\n", btf_log_buf);
		err = -1;
		goto done;
	}
	if (CHECK(info.nr_func_info != nr_func_info,
		  "incorrect info.nr_func_info (2nd) %d",
		  info.nr_func_info)) {
		err = -1;
		goto done;
	}
	if (CHECK(info.func_info_rec_size != rec_size,
		  "incorrect info.func_info_rec_size (2nd) %d",
		  info.func_info_rec_size)) {
		err = -1;
		goto done;
	}

	finfo = func_info;
	for (i = 0; i < nr_func_info; i++) {
		if (test->dead_func_mask & (1 << i))
			continue;
		if (CHECK(finfo->type_id != test->func_info[i][1],
			  "incorrect func_type %u expected %u",
			  finfo->type_id, test->func_info[i][1])) {
			err = -1;
			goto done;
		}
		finfo = (void *)finfo + rec_size;
	}

	err = 0;

done:
	free(func_info);
	return err;
}

static int test_get_linfo(const struct prog_info_raw_test *test,
			  const void *patched_linfo,
			  __u32 cnt, int prog_fd)
{
	__u32 i, info_len, nr_jited_ksyms, nr_jited_func_lens;
	__u64 *jited_linfo = NULL, *jited_ksyms = NULL;
	__u32 rec_size, jited_rec_size, jited_cnt;
	struct bpf_line_info *linfo = NULL;
	__u32 cur_func_len, ksyms_found;
	struct bpf_prog_info info = {};
	__u32 *jited_func_lens = NULL;
	__u64 cur_func_ksyms;
	__u32 dead_insns;
	int err;

	jited_cnt = cnt;
	rec_size = sizeof(*linfo);
	jited_rec_size = sizeof(*jited_linfo);
	if (test->nr_jited_ksyms)
		nr_jited_ksyms = test->nr_jited_ksyms;
	else
		nr_jited_ksyms = test->func_info_cnt - test->dead_func_cnt;
	nr_jited_func_lens = nr_jited_ksyms;

	info_len = sizeof(struct bpf_prog_info);
	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
	if (CHECK(err == -1, "err:%d errno:%d", err, errno)) {
		err = -1;
		goto done;
	}

	if (!info.jited_prog_len) {
		/* prog is not jited */
		jited_cnt = 0;
		nr_jited_ksyms = 1;
		nr_jited_func_lens = 1;
	}

	if (CHECK(info.nr_line_info != cnt ||
		  info.nr_jited_line_info != jited_cnt ||
		  info.nr_jited_ksyms != nr_jited_ksyms ||
		  info.nr_jited_func_lens != nr_jited_func_lens ||
		  (!info.nr_line_info && info.nr_jited_line_info),
		  "info: nr_line_info:%u(expected:%u) nr_jited_line_info:%u(expected:%u) nr_jited_ksyms:%u(expected:%u) nr_jited_func_lens:%u(expected:%u)",
		  info.nr_line_info, cnt,
		  info.nr_jited_line_info, jited_cnt,
		  info.nr_jited_ksyms, nr_jited_ksyms,
		  info.nr_jited_func_lens, nr_jited_func_lens)) {
		err = -1;
		goto done;
	}

	if (CHECK(info.line_info_rec_size != sizeof(struct bpf_line_info) ||
		  info.jited_line_info_rec_size != sizeof(__u64),
		  "info: line_info_rec_size:%u(userspace expected:%u) jited_line_info_rec_size:%u(userspace expected:%u)",
		  info.line_info_rec_size, rec_size,
		  info.jited_line_info_rec_size, jited_rec_size)) {
		err = -1;
		goto done;
	}

	if (!cnt)
		return 0;

	rec_size = info.line_info_rec_size;
	jited_rec_size = info.jited_line_info_rec_size;

	memset(&info, 0, sizeof(info));

	linfo = calloc(cnt, rec_size);
	if (CHECK(!linfo, "!linfo")) {
		err = -1;
		goto done;
	}
	info.nr_line_info = cnt;
	info.line_info_rec_size = rec_size;
	info.line_info = ptr_to_u64(linfo);

	if (jited_cnt) {
		jited_linfo = calloc(jited_cnt, jited_rec_size);
		jited_ksyms = calloc(nr_jited_ksyms, sizeof(*jited_ksyms));
		jited_func_lens = calloc(nr_jited_func_lens,
					 sizeof(*jited_func_lens));
		if (CHECK(!jited_linfo || !jited_ksyms || !jited_func_lens,
			  "jited_linfo:%p jited_ksyms:%p jited_func_lens:%p",
			  jited_linfo, jited_ksyms, jited_func_lens)) {
			err = -1;
			goto done;
		}

		info.nr_jited_line_info = jited_cnt;
		info.jited_line_info_rec_size = jited_rec_size;
		info.jited_line_info = ptr_to_u64(jited_linfo);
		info.nr_jited_ksyms = nr_jited_ksyms;
		info.jited_ksyms = ptr_to_u64(jited_ksyms);
		info.nr_jited_func_lens = nr_jited_func_lens;
		info.jited_func_lens = ptr_to_u64(jited_func_lens);
	}

	err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);

	/*
	 * Only recheck the info.*line_info* fields.
	 * Other fields are not the concern of this test.
	 */
	if (CHECK(err == -1 ||
		  info.nr_line_info != cnt ||
		  (jited_cnt && !info.jited_line_info) ||
		  info.nr_jited_line_info != jited_cnt ||
		  info.line_info_rec_size != rec_size ||
		  info.jited_line_info_rec_size != jited_rec_size,
		  "err:%d errno:%d info: nr_line_info:%u(expected:%u) nr_jited_line_info:%u(expected:%u) line_info_rec_size:%u(expected:%u) jited_linfo_rec_size:%u(expected:%u) line_info:%p jited_line_info:%p",
		  err, errno,
		  info.nr_line_info, cnt,
		  info.nr_jited_line_info, jited_cnt,
		  info.line_info_rec_size, rec_size,
		  info.jited_line_info_rec_size, jited_rec_size,
		  (void *)(long)info.line_info,
		  (void *)(long)info.jited_line_info)) {
		err = -1;
		goto done;
	}

	dead_insns = 0;
	while (test->dead_code_mask & (1 << dead_insns))
		dead_insns++;

	CHECK(linfo[0].insn_off, "linfo[0].insn_off:%u",
	      linfo[0].insn_off);
	for (i = 1; i < cnt; i++) {
		const struct bpf_line_info *expected_linfo;

		while (test->dead_code_mask & (1 << (i + dead_insns)))
			dead_insns++;

		expected_linfo = patched_linfo +
			((i + dead_insns) * test->line_info_rec_size);
		if (CHECK(linfo[i].insn_off <= linfo[i - 1].insn_off,
			  "linfo[%u].insn_off:%u <= linfo[%u].insn_off:%u",
			  i, linfo[i].insn_off,
			  i - 1, linfo[i - 1].insn_off)) {
			err = -1;
			goto done;
		}
		if (CHECK(linfo[i].file_name_off != expected_linfo->file_name_off ||
			  linfo[i].line_off != expected_linfo->line_off ||
			  linfo[i].line_col != expected_linfo->line_col,
			  "linfo[%u] (%u, %u, %u) != (%u, %u, %u)", i,
			  linfo[i].file_name_off,
			  linfo[i].line_off,
			  linfo[i].line_col,
			  expected_linfo->file_name_off,
			  expected_linfo->line_off,
			  expected_linfo->line_col)) {
			err = -1;
			goto done;
		}
	}

	if (!jited_cnt) {
		fprintf(stderr, "not jited. skipping jited_line_info check. ");
		err = 0;
		goto done;
	}

	if (CHECK(jited_linfo[0] != jited_ksyms[0],
		  "jited_linfo[0]:%lx != jited_ksyms[0]:%lx",
		  (long)(jited_linfo[0]), (long)(jited_ksyms[0]))) {
		err = -1;
		goto done;
	}

	ksyms_found = 1;
	cur_func_len = jited_func_lens[0];
	cur_func_ksyms = jited_ksyms[0];
	for (i = 1; i < jited_cnt; i++) {
		if (ksyms_found < nr_jited_ksyms &&
		    jited_linfo[i] == jited_ksyms[ksyms_found]) {
			cur_func_ksyms = jited_ksyms[ksyms_found];
			cur_func_len = jited_ksyms[ksyms_found];
			ksyms_found++;
			continue;
		}

		if (CHECK(jited_linfo[i] <= jited_linfo[i - 1],
			  "jited_linfo[%u]:%lx <= jited_linfo[%u]:%lx",
			  i, (long)jited_linfo[i],
			  i - 1, (long)(jited_linfo[i - 1]))) {
			err = -1;
			goto done;
		}

		if (CHECK(jited_linfo[i] - cur_func_ksyms > cur_func_len,
			  "jited_linfo[%u]:%lx - %lx > %u",
			  i, (long)jited_linfo[i], (long)cur_func_ksyms,
			  cur_func_len)) {
			err = -1;
			goto done;
		}
	}

	if (CHECK(ksyms_found != nr_jited_ksyms,
		  "ksyms_found:%u != nr_jited_ksyms:%u",
		  ksyms_found, nr_jited_ksyms)) {
		err = -1;
		goto done;
	}

	err = 0;

done:
	free(linfo);
	free(jited_linfo);
	free(jited_ksyms);
	free(jited_func_lens);
	return err;
}

static int do_test_info_raw(unsigned int test_num)
{
	const struct prog_info_raw_test *test = &info_raw_tests[test_num - 1];
	unsigned int raw_btf_size, linfo_str_off, linfo_size;
	int btf_fd = -1, prog_fd = -1, err = 0;
	void *raw_btf, *patched_linfo = NULL;
	const char *ret_next_str;
	union bpf_attr attr = {};

	fprintf(stderr, "BTF prog info raw test[%u] (%s): ", test_num, test->descr);
	raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
				 test->str_sec, test->str_sec_size,
				 &raw_btf_size, &ret_next_str);

	if (!raw_btf)
		return -1;

	*btf_log_buf = '\0';
	btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
			      btf_log_buf, BTF_LOG_BUF_SIZE,
			      args.always_log);
	free(raw_btf);

	if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {
		err = -1;
		goto done;
	}

	if (*btf_log_buf && args.always_log)
		fprintf(stderr, "\n%s", btf_log_buf);
	*btf_log_buf = '\0';

	linfo_str_off = ret_next_str - test->str_sec;
	patched_linfo = patch_name_tbd(test->line_info,
				       test->str_sec, linfo_str_off,
				       test->str_sec_size, &linfo_size);
	if (IS_ERR(patched_linfo)) {
		fprintf(stderr, "error in creating raw bpf_line_info");
		err = -1;
		goto done;
	}

	attr.prog_type = test->prog_type;
	attr.insns = ptr_to_u64(test->insns);
	attr.insn_cnt = probe_prog_length(test->insns);
	attr.license = ptr_to_u64("GPL");
	attr.prog_btf_fd = btf_fd;
	attr.func_info_rec_size = test->func_info_rec_size;
	attr.func_info_cnt = test->func_info_cnt;
	attr.func_info = ptr_to_u64(test->func_info);
	attr.log_buf = ptr_to_u64(btf_log_buf);
	attr.log_size = BTF_LOG_BUF_SIZE;
	attr.log_level = 1;
	if (linfo_size) {
		attr.line_info_rec_size = test->line_info_rec_size;
		attr.line_info = ptr_to_u64(patched_linfo);
		attr.line_info_cnt = linfo_size / attr.line_info_rec_size;
	}

	prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
	err = ((prog_fd == -1) != test->expected_prog_load_failure);
	if (CHECK(err, "prog_fd:%d expected_prog_load_failure:%u errno:%d",
		  prog_fd, test->expected_prog_load_failure, errno) ||
	    CHECK(test->err_str && !strstr(btf_log_buf, test->err_str),
		  "expected err_str:%s", test->err_str)) {
		err = -1;
		goto done;
	}

	if (prog_fd == -1)
		goto done;

	err = test_get_finfo(test, prog_fd);
	if (err)
		goto done;

	err = test_get_linfo(test, patched_linfo,
			     attr.line_info_cnt - test->dead_code_cnt,
			     prog_fd);
	if (err)
		goto done;

done:
	if (!err)
		fprintf(stderr, "OK");

	if (*btf_log_buf && (err || args.always_log))
		fprintf(stderr, "\n%s", btf_log_buf);

	if (btf_fd != -1)
		close(btf_fd);
	if (prog_fd != -1)
		close(prog_fd);

	if (!IS_ERR(patched_linfo))
		free(patched_linfo);

	return err;
}

static int test_info_raw(void)
{
	unsigned int i;
	int err = 0;

	if (args.info_raw_test_num)
		return count_result(do_test_info_raw(args.info_raw_test_num));

	for (i = 1; i <= ARRAY_SIZE(info_raw_tests); i++)
		err |= count_result(do_test_info_raw(i));

	return err;
}

struct btf_raw_data {
	__u32 raw_types[MAX_NR_RAW_U32];
	const char *str_sec;
	__u32 str_sec_size;
};

struct btf_dedup_test {
	const char *descr;
	struct btf_raw_data input;
	struct btf_raw_data expect;
	struct btf_dedup_opts opts;
};

const struct btf_dedup_test dedup_tests[] = {

{
	.descr = "dedup: unused strings filtering",
	.input = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_NTH(2), BTF_INT_SIGNED, 0, 32, 4),
			BTF_TYPE_INT_ENC(NAME_NTH(5), BTF_INT_SIGNED, 0, 64, 8),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0unused\0int\0foo\0bar\0long"),
	},
	.expect = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),
			BTF_TYPE_INT_ENC(NAME_NTH(2), BTF_INT_SIGNED, 0, 64, 8),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0int\0long"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: strings deduplication",
	.input = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),
			BTF_TYPE_INT_ENC(NAME_NTH(2), BTF_INT_SIGNED, 0, 64, 8),
			BTF_TYPE_INT_ENC(NAME_NTH(3), BTF_INT_SIGNED, 0, 32, 4),
			BTF_TYPE_INT_ENC(NAME_NTH(4), BTF_INT_SIGNED, 0, 64, 8),
			BTF_TYPE_INT_ENC(NAME_NTH(5), BTF_INT_SIGNED, 0, 32, 4),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0int\0long int\0int\0long int\0int"),
	},
	.expect = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),
			BTF_TYPE_INT_ENC(NAME_NTH(2), BTF_INT_SIGNED, 0, 64, 8),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0int\0long int"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: struct example #1",
	/*
	 * struct s {
	 *	struct s *next;
	 *	const int *a;
	 *	int b[16];
	 *	int c;
	 * }
	 */
	.input = {
		.raw_types = {
			/* int */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
			/* int[16] */
			BTF_TYPE_ARRAY_ENC(1, 1, 16),					/* [2] */
			/* struct s { */
			BTF_STRUCT_ENC(NAME_NTH(2), 4, 84),				/* [3] */
				BTF_MEMBER_ENC(NAME_NTH(3), 4, 0),	/* struct s *next;	*/
				BTF_MEMBER_ENC(NAME_NTH(4), 5, 64),	/* const int *a;	*/
				BTF_MEMBER_ENC(NAME_NTH(5), 2, 128),	/* int b[16];		*/
				BTF_MEMBER_ENC(NAME_NTH(6), 1, 640),	/* int c;		*/
			/* ptr -> [3] struct s */
			BTF_PTR_ENC(3),							/* [4] */
			/* ptr -> [6] const int */
			BTF_PTR_ENC(6),							/* [5] */
			/* const -> [1] int */
			BTF_CONST_ENC(1),						/* [6] */

			/* full copy of the above */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),	/* [7] */
			BTF_TYPE_ARRAY_ENC(7, 7, 16),					/* [8] */
			BTF_STRUCT_ENC(NAME_NTH(2), 4, 84),				/* [9] */
				BTF_MEMBER_ENC(NAME_NTH(3), 10, 0),
				BTF_MEMBER_ENC(NAME_NTH(4), 11, 64),
				BTF_MEMBER_ENC(NAME_NTH(5), 8, 128),
				BTF_MEMBER_ENC(NAME_NTH(6), 7, 640),
			BTF_PTR_ENC(9),							/* [10] */
			BTF_PTR_ENC(12),						/* [11] */
			BTF_CONST_ENC(7),						/* [12] */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0int\0s\0next\0a\0b\0c\0"),
	},
	.expect = {
		.raw_types = {
			/* int */
			BTF_TYPE_INT_ENC(NAME_NTH(4), BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
			/* int[16] */
			BTF_TYPE_ARRAY_ENC(1, 1, 16),					/* [2] */
			/* struct s { */
			BTF_STRUCT_ENC(NAME_NTH(6), 4, 84),				/* [3] */
				BTF_MEMBER_ENC(NAME_NTH(5), 4, 0),	/* struct s *next;	*/
				BTF_MEMBER_ENC(NAME_NTH(1), 5, 64),	/* const int *a;	*/
				BTF_MEMBER_ENC(NAME_NTH(2), 2, 128),	/* int b[16];		*/
				BTF_MEMBER_ENC(NAME_NTH(3), 1, 640),	/* int c;		*/
			/* ptr -> [3] struct s */
			BTF_PTR_ENC(3),							/* [4] */
			/* ptr -> [6] const int */
			BTF_PTR_ENC(6),							/* [5] */
			/* const -> [1] int */
			BTF_CONST_ENC(1),						/* [6] */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0a\0b\0c\0int\0next\0s"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: struct <-> fwd resolution w/ hash collision",
	/*
	 * // CU 1:
	 * struct x;
	 * struct s {
	 *	struct x *x;
	 * };
	 * // CU 2:
	 * struct x {};
	 * struct s {
	 *	struct x *x;
	 * };
	 */
	.input = {
		.raw_types = {
			/* CU 1 */
			BTF_FWD_ENC(NAME_TBD, 0 /* struct fwd */),	/* [1] fwd x      */
			BTF_PTR_ENC(1),					/* [2] ptr -> [1] */
			BTF_STRUCT_ENC(NAME_TBD, 1, 8),			/* [3] struct s   */
				BTF_MEMBER_ENC(NAME_TBD, 2, 0),
			/* CU 2 */
			BTF_STRUCT_ENC(NAME_TBD, 0, 0),			/* [4] struct x   */
			BTF_PTR_ENC(4),					/* [5] ptr -> [4] */
			BTF_STRUCT_ENC(NAME_TBD, 1, 8),			/* [6] struct s   */
				BTF_MEMBER_ENC(NAME_TBD, 5, 0),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0x\0s\0x\0x\0s\0x\0"),
	},
	.expect = {
		.raw_types = {
			BTF_PTR_ENC(3),					/* [1] ptr -> [3] */
			BTF_STRUCT_ENC(NAME_TBD, 1, 8),			/* [2] struct s   */
				BTF_MEMBER_ENC(NAME_TBD, 1, 0),
			BTF_STRUCT_ENC(NAME_NTH(2), 0, 0),		/* [3] struct x   */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0s\0x"),
	},
	.opts = {
		.dont_resolve_fwds = false,
		.dedup_table_size = 1, /* force hash collisions */
	},
},
{
	.descr = "dedup: void equiv check",
	/*
	 * // CU 1:
	 * struct s {
	 *	struct {} *x;
	 * };
	 * // CU 2:
	 * struct s {
	 *	int *x;
	 * };
	 */
	.input = {
		.raw_types = {
			/* CU 1 */
			BTF_STRUCT_ENC(0, 0, 1),				/* [1] struct {}  */
			BTF_PTR_ENC(1),						/* [2] ptr -> [1] */
			BTF_STRUCT_ENC(NAME_NTH(1), 1, 8),			/* [3] struct s   */
				BTF_MEMBER_ENC(NAME_NTH(2), 2, 0),
			/* CU 2 */
			BTF_PTR_ENC(0),						/* [4] ptr -> void */
			BTF_STRUCT_ENC(NAME_NTH(1), 1, 8),			/* [5] struct s   */
				BTF_MEMBER_ENC(NAME_NTH(2), 4, 0),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0s\0x"),
	},
	.expect = {
		.raw_types = {
			/* CU 1 */
			BTF_STRUCT_ENC(0, 0, 1),				/* [1] struct {}  */
			BTF_PTR_ENC(1),						/* [2] ptr -> [1] */
			BTF_STRUCT_ENC(NAME_NTH(1), 1, 8),			/* [3] struct s   */
				BTF_MEMBER_ENC(NAME_NTH(2), 2, 0),
			/* CU 2 */
			BTF_PTR_ENC(0),						/* [4] ptr -> void */
			BTF_STRUCT_ENC(NAME_NTH(1), 1, 8),			/* [5] struct s   */
				BTF_MEMBER_ENC(NAME_NTH(2), 4, 0),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0s\0x"),
	},
	.opts = {
		.dont_resolve_fwds = false,
		.dedup_table_size = 1, /* force hash collisions */
	},
},
{
	.descr = "dedup: all possible kinds (no duplicates)",
	.input = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 8),		/* [1] int */
			BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), 4),	/* [2] enum */
				BTF_ENUM_ENC(NAME_TBD, 0),
				BTF_ENUM_ENC(NAME_TBD, 1),
			BTF_FWD_ENC(NAME_TBD, 1 /* union kind_flag */),			/* [3] fwd */
			BTF_TYPE_ARRAY_ENC(2, 1, 7),					/* [4] array */
			BTF_STRUCT_ENC(NAME_TBD, 1, 4),					/* [5] struct */
				BTF_MEMBER_ENC(NAME_TBD, 1, 0),
			BTF_UNION_ENC(NAME_TBD, 1, 4),					/* [6] union */
				BTF_MEMBER_ENC(NAME_TBD, 1, 0),
			BTF_TYPEDEF_ENC(NAME_TBD, 1),					/* [7] typedef */
			BTF_PTR_ENC(0),							/* [8] ptr */
			BTF_CONST_ENC(8),						/* [9] const */
			BTF_VOLATILE_ENC(8),						/* [10] volatile */
			BTF_RESTRICT_ENC(8),						/* [11] restrict */
			BTF_FUNC_PROTO_ENC(1, 2),					/* [12] func_proto */
				BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
				BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 8),
			BTF_FUNC_ENC(NAME_TBD, 12),					/* [13] func */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M"),
	},
	.expect = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 8),		/* [1] int */
			BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), 4),	/* [2] enum */
				BTF_ENUM_ENC(NAME_TBD, 0),
				BTF_ENUM_ENC(NAME_TBD, 1),
			BTF_FWD_ENC(NAME_TBD, 1 /* union kind_flag */),			/* [3] fwd */
			BTF_TYPE_ARRAY_ENC(2, 1, 7),					/* [4] array */
			BTF_STRUCT_ENC(NAME_TBD, 1, 4),					/* [5] struct */
				BTF_MEMBER_ENC(NAME_TBD, 1, 0),
			BTF_UNION_ENC(NAME_TBD, 1, 4),					/* [6] union */
				BTF_MEMBER_ENC(NAME_TBD, 1, 0),
			BTF_TYPEDEF_ENC(NAME_TBD, 1),					/* [7] typedef */
			BTF_PTR_ENC(0),							/* [8] ptr */
			BTF_CONST_ENC(8),						/* [9] const */
			BTF_VOLATILE_ENC(8),						/* [10] volatile */
			BTF_RESTRICT_ENC(8),						/* [11] restrict */
			BTF_FUNC_PROTO_ENC(1, 2),					/* [12] func_proto */
				BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
				BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 8),
			BTF_FUNC_ENC(NAME_TBD, 12),					/* [13] func */
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0K\0L\0M"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: no int duplicates",
	.input = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 8),
			/* different name */
			BTF_TYPE_INT_ENC(NAME_NTH(2), BTF_INT_SIGNED, 0, 32, 8),
			/* different encoding */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_CHAR, 0, 32, 8),
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_BOOL, 0, 32, 8),
			/* different bit offset */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 8, 32, 8),
			/* different bit size */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 27, 8),
			/* different byte size */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0int\0some other int"),
	},
	.expect = {
		.raw_types = {
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 8),
			/* different name */
			BTF_TYPE_INT_ENC(NAME_NTH(2), BTF_INT_SIGNED, 0, 32, 8),
			/* different encoding */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_CHAR, 0, 32, 8),
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_BOOL, 0, 32, 8),
			/* different bit offset */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 8, 32, 8),
			/* different bit size */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 27, 8),
			/* different byte size */
			BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0int\0some other int"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: enum fwd resolution",
	.input = {
		.raw_types = {
			/* [1] fwd enum 'e1' before full enum */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 4),
			/* [2] full enum 'e1' after fwd */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
				BTF_ENUM_ENC(NAME_NTH(2), 123),
			/* [3] full enum 'e2' before fwd */
			BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
				BTF_ENUM_ENC(NAME_NTH(4), 456),
			/* [4] fwd enum 'e2' after full enum */
			BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 4),
			/* [5] incompatible fwd enum with different size */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 1),
			/* [6] incompatible full enum with different value */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
				BTF_ENUM_ENC(NAME_NTH(2), 321),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0e1\0e1_val\0e2\0e2_val"),
	},
	.expect = {
		.raw_types = {
			/* [1] full enum 'e1' */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
				BTF_ENUM_ENC(NAME_NTH(2), 123),
			/* [2] full enum 'e2' */
			BTF_TYPE_ENC(NAME_NTH(3), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
				BTF_ENUM_ENC(NAME_NTH(4), 456),
			/* [3] incompatible fwd enum with different size */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 0), 1),
			/* [4] incompatible full enum with different value */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_ENUM, 0, 1), 4),
				BTF_ENUM_ENC(NAME_NTH(2), 321),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0e1\0e1_val\0e2\0e2_val"),
	},
	.opts = {
		.dont_resolve_fwds = false,
	},
},
{
	.descr = "dedup: datasec and vars pass-through",
	.input = {
		.raw_types = {
			/* int */
			BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
			/* static int t */
			BTF_VAR_ENC(NAME_NTH(2), 1, 0),			/* [2] */
			/* .bss section */				/* [3] */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
			BTF_VAR_SECINFO_ENC(2, 0, 4),
			/* int, referenced from [5] */
			BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [4] */
			/* another static int t */
			BTF_VAR_ENC(NAME_NTH(2), 4, 0),			/* [5] */
			/* another .bss section */			/* [6] */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
			BTF_VAR_SECINFO_ENC(5, 0, 4),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0.bss\0t"),
	},
	.expect = {
		.raw_types = {
			/* int */
			BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),	/* [1] */
			/* static int t */
			BTF_VAR_ENC(NAME_NTH(2), 1, 0),			/* [2] */
			/* .bss section */				/* [3] */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
			BTF_VAR_SECINFO_ENC(2, 0, 4),
			/* another static int t */
			BTF_VAR_ENC(NAME_NTH(2), 1, 0),			/* [4] */
			/* another .bss section */			/* [5] */
			BTF_TYPE_ENC(NAME_NTH(1), BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1), 4),
			BTF_VAR_SECINFO_ENC(4, 0, 4),
			BTF_END_RAW,
		},
		BTF_STR_SEC("\0.bss\0t"),
	},
	.opts = {
		.dont_resolve_fwds = false,
		.dedup_table_size = 1
	},
},

};

static int btf_type_size(const struct btf_type *t)
{
	int base_size = sizeof(struct btf_type);
	__u16 vlen = BTF_INFO_VLEN(t->info);
	__u16 kind = BTF_INFO_KIND(t->info);

	switch (kind) {
	case BTF_KIND_FWD:
	case BTF_KIND_CONST:
	case BTF_KIND_VOLATILE:
	case BTF_KIND_RESTRICT:
	case BTF_KIND_PTR:
	case BTF_KIND_TYPEDEF:
	case BTF_KIND_FUNC:
		return base_size;
	case BTF_KIND_INT:
		return base_size + sizeof(__u32);
	case BTF_KIND_ENUM:
		return base_size + vlen * sizeof(struct btf_enum);
	case BTF_KIND_ARRAY:
		return base_size + sizeof(struct btf_array);
	case BTF_KIND_STRUCT:
	case BTF_KIND_UNION:
		return base_size + vlen * sizeof(struct btf_member);
	case BTF_KIND_FUNC_PROTO:
		return base_size + vlen * sizeof(struct btf_param);
	case BTF_KIND_VAR:
		return base_size + sizeof(struct btf_var);
	case BTF_KIND_DATASEC:
		return base_size + vlen * sizeof(struct btf_var_secinfo);
	default:
		fprintf(stderr, "Unsupported BTF_KIND:%u\n", kind);
		return -EINVAL;
	}
}

static void dump_btf_strings(const char *strs, __u32 len)
{
	const char *cur = strs;
	int i = 0;

	while (cur < strs + len) {
		fprintf(stderr, "string #%d: '%s'\n", i, cur);
		cur += strlen(cur) + 1;
		i++;
	}
}

static int do_test_dedup(unsigned int test_num)
{
	const struct btf_dedup_test *test = &dedup_tests[test_num - 1];
	__u32 test_nr_types, expect_nr_types, test_btf_size, expect_btf_size;
	const struct btf_header *test_hdr, *expect_hdr;
	struct btf *test_btf = NULL, *expect_btf = NULL;
	const void *test_btf_data, *expect_btf_data;
	const char *ret_test_next_str, *ret_expect_next_str;
	const char *test_strs, *expect_strs;
	const char *test_str_cur, *test_str_end;
	const char *expect_str_cur, *expect_str_end;
	unsigned int raw_btf_size;
	void *raw_btf;
	int err = 0, i;

	fprintf(stderr, "BTF dedup test[%u] (%s):", test_num, test->descr);

	raw_btf = btf_raw_create(&hdr_tmpl, test->input.raw_types,
				 test->input.str_sec, test->input.str_sec_size,
				 &raw_btf_size, &ret_test_next_str);
	if (!raw_btf)
		return -1;
	test_btf = btf__new((__u8 *)raw_btf, raw_btf_size);
	free(raw_btf);
	if (CHECK(IS_ERR(test_btf), "invalid test_btf errno:%ld",
		  PTR_ERR(test_btf))) {
		err = -1;
		goto done;
	}

	raw_btf = btf_raw_create(&hdr_tmpl, test->expect.raw_types,
				 test->expect.str_sec,
				 test->expect.str_sec_size,
				 &raw_btf_size, &ret_expect_next_str);
	if (!raw_btf)
		return -1;
	expect_btf = btf__new((__u8 *)raw_btf, raw_btf_size);
	free(raw_btf);
	if (CHECK(IS_ERR(expect_btf), "invalid expect_btf errno:%ld",
		  PTR_ERR(expect_btf))) {
		err = -1;
		goto done;
	}

	err = btf__dedup(test_btf, NULL, &test->opts);
	if (CHECK(err, "btf_dedup failed errno:%d", err)) {
		err = -1;
		goto done;
	}

	test_btf_data = btf__get_raw_data(test_btf, &test_btf_size);
	expect_btf_data = btf__get_raw_data(expect_btf, &expect_btf_size);
	if (CHECK(test_btf_size != expect_btf_size,
		  "test_btf_size:%u != expect_btf_size:%u",
		  test_btf_size, expect_btf_size)) {
		err = -1;
		goto done;
	}

	test_hdr = test_btf_data;
	test_strs = test_btf_data + sizeof(*test_hdr) + test_hdr->str_off;
	expect_hdr = expect_btf_data;
	expect_strs = expect_btf_data + sizeof(*test_hdr) + expect_hdr->str_off;
	if (CHECK(test_hdr->str_len != expect_hdr->str_len,
		  "test_hdr->str_len:%u != expect_hdr->str_len:%u",
		  test_hdr->str_len, expect_hdr->str_len)) {
		fprintf(stderr, "\ntest strings:\n");
		dump_btf_strings(test_strs, test_hdr->str_len);
		fprintf(stderr, "\nexpected strings:\n");
		dump_btf_strings(expect_strs, expect_hdr->str_len);
		err = -1;
		goto done;
	}

	test_str_cur = test_strs;
	test_str_end = test_strs + test_hdr->str_len;
	expect_str_cur = expect_strs;
	expect_str_end = expect_strs + expect_hdr->str_len;
	while (test_str_cur < test_str_end && expect_str_cur < expect_str_end) {
		size_t test_len, expect_len;

		test_len = strlen(test_str_cur);
		expect_len = strlen(expect_str_cur);
		if (CHECK(test_len != expect_len,
			  "test_len:%zu != expect_len:%zu "
			  "(test_str:%s, expect_str:%s)",
			  test_len, expect_len, test_str_cur, expect_str_cur)) {
			err = -1;
			goto done;
		}
		if (CHECK(strcmp(test_str_cur, expect_str_cur),
			  "test_str:%s != expect_str:%s",
			  test_str_cur, expect_str_cur)) {
			err = -1;
			goto done;
		}
		test_str_cur += test_len + 1;
		expect_str_cur += expect_len + 1;
	}
	if (CHECK(test_str_cur != test_str_end,
		  "test_str_cur:%p != test_str_end:%p",
		  test_str_cur, test_str_end)) {
		err = -1;
		goto done;
	}

	test_nr_types = btf__get_nr_types(test_btf);
	expect_nr_types = btf__get_nr_types(expect_btf);
	if (CHECK(test_nr_types != expect_nr_types,
		  "test_nr_types:%u != expect_nr_types:%u",
		  test_nr_types, expect_nr_types)) {
		err = -1;
		goto done;
	}

	for (i = 1; i <= test_nr_types; i++) {
		const struct btf_type *test_type, *expect_type;
		int test_size, expect_size;

		test_type = btf__type_by_id(test_btf, i);
		expect_type = btf__type_by_id(expect_btf, i);
		test_size = btf_type_size(test_type);
		expect_size = btf_type_size(expect_type);

		if (CHECK(test_size != expect_size,
			  "type #%d: test_size:%d != expect_size:%u",
			  i, test_size, expect_size)) {
			err = -1;
			goto done;
		}
		if (CHECK(memcmp((void *)test_type,
				 (void *)expect_type,
				 test_size),
			  "type #%d: contents differ", i)) {
			err = -1;
			goto done;
		}
	}

done:
	if (!err)
		fprintf(stderr, "OK");
	if (!IS_ERR(test_btf))
		btf__free(test_btf);
	if (!IS_ERR(expect_btf))
		btf__free(expect_btf);

	return err;
}

static int test_dedup(void)
{
	unsigned int i;
	int err = 0;

	if (args.dedup_test_num)
		return count_result(do_test_dedup(args.dedup_test_num));

	for (i = 1; i <= ARRAY_SIZE(dedup_tests); i++)
		err |= count_result(do_test_dedup(i));

	return err;
}

static void usage(const char *cmd)
{
	fprintf(stderr, "Usage: %s [-l] [[-r btf_raw_test_num (1 - %zu)] |\n"
			"\t[-g btf_get_info_test_num (1 - %zu)] |\n"
			"\t[-f btf_file_test_num (1 - %zu)] |\n"
			"\t[-k btf_prog_info_raw_test_num (1 - %zu)] |\n"
			"\t[-p (pretty print test)] |\n"
			"\t[-d btf_dedup_test_num (1 - %zu)]]\n",
		cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),
		ARRAY_SIZE(file_tests), ARRAY_SIZE(info_raw_tests),
		ARRAY_SIZE(dedup_tests));
}

static int parse_args(int argc, char **argv)
{
	const char *optstr = "hlpk:f:r:g:d:";
	int opt;

	while ((opt = getopt(argc, argv, optstr)) != -1) {
		switch (opt) {
		case 'l':
			args.always_log = true;
			break;
		case 'f':
			args.file_test_num = atoi(optarg);
			args.file_test = true;
			break;
		case 'r':
			args.raw_test_num = atoi(optarg);
			args.raw_test = true;
			break;
		case 'g':
			args.get_info_test_num = atoi(optarg);
			args.get_info_test = true;
			break;
		case 'p':
			args.pprint_test = true;
			break;
		case 'k':
			args.info_raw_test_num = atoi(optarg);
			args.info_raw_test = true;
			break;
		case 'd':
			args.dedup_test_num = atoi(optarg);
			args.dedup_test = true;
			break;
		case 'h':
			usage(argv[0]);
			exit(0);
		default:
			usage(argv[0]);
			return -1;
		}
	}

	if (args.raw_test_num &&
	    (args.raw_test_num < 1 ||
	     args.raw_test_num > ARRAY_SIZE(raw_tests))) {
		fprintf(stderr, "BTF raw test number must be [1 - %zu]\n",
			ARRAY_SIZE(raw_tests));
		return -1;
	}

	if (args.file_test_num &&
	    (args.file_test_num < 1 ||
	     args.file_test_num > ARRAY_SIZE(file_tests))) {
		fprintf(stderr, "BTF file test number must be [1 - %zu]\n",
			ARRAY_SIZE(file_tests));
		return -1;
	}

	if (args.get_info_test_num &&
	    (args.get_info_test_num < 1 ||
	     args.get_info_test_num > ARRAY_SIZE(get_info_tests))) {
		fprintf(stderr, "BTF get info test number must be [1 - %zu]\n",
			ARRAY_SIZE(get_info_tests));
		return -1;
	}

	if (args.info_raw_test_num &&
	    (args.info_raw_test_num < 1 ||
	     args.info_raw_test_num > ARRAY_SIZE(info_raw_tests))) {
		fprintf(stderr, "BTF prog info raw test number must be [1 - %zu]\n",
			ARRAY_SIZE(info_raw_tests));
		return -1;
	}

	if (args.dedup_test_num &&
	    (args.dedup_test_num < 1 ||
	     args.dedup_test_num > ARRAY_SIZE(dedup_tests))) {
		fprintf(stderr, "BTF dedup test number must be [1 - %zu]\n",
			ARRAY_SIZE(dedup_tests));
		return -1;
	}

	return 0;
}

static void print_summary(void)
{
	fprintf(stderr, "PASS:%u SKIP:%u FAIL:%u\n",
		pass_cnt - skip_cnt, skip_cnt, error_cnt);
}

int main(int argc, char **argv)
{
	int err = 0;

	err = parse_args(argc, argv);
	if (err)
		return err;

	if (args.always_log)
		libbpf_set_print(__base_pr);

	if (args.raw_test)
		err |= test_raw();

	if (args.get_info_test)
		err |= test_get_info();

	if (args.file_test)
		err |= test_file();

	if (args.pprint_test)
		err |= test_pprint();

	if (args.info_raw_test)
		err |= test_info_raw();

	if (args.dedup_test)
		err |= test_dedup();

	if (args.raw_test || args.get_info_test || args.file_test ||
	    args.pprint_test || args.info_raw_test || args.dedup_test)
		goto done;

	err |= test_raw();
	err |= test_get_info();
	err |= test_file();
	err |= test_info_raw();
	err |= test_dedup();

done:
	print_summary();
	return err;
}