2020-07-11 23:53:29 +02:00
// SPDX-License-Identifier: GPL-2.0
# include <linux/err.h>
# include <string.h>
# include <bpf/btf.h>
# include <bpf/libbpf.h>
# include <linux/btf.h>
# include <linux/kernel.h>
2020-07-20 09:33:59 -07:00
# define CONFIG_DEBUG_INFO_BTF
2020-07-11 23:53:29 +02:00
# include <linux/btf_ids.h>
# include "test_progs.h"
static int duration ;
struct symbol {
const char * name ;
int type ;
int id ;
} ;
struct symbol test_symbols [ ] = {
{ " unused " , BTF_KIND_UNKN , 0 } ,
{ " S " , BTF_KIND_TYPEDEF , - 1 } ,
{ " T " , BTF_KIND_TYPEDEF , - 1 } ,
{ " U " , BTF_KIND_TYPEDEF , - 1 } ,
{ " S " , BTF_KIND_STRUCT , - 1 } ,
{ " U " , BTF_KIND_UNION , - 1 } ,
{ " func " , BTF_KIND_FUNC , - 1 } ,
} ;
2020-09-30 11:36:01 +02:00
/* Align the .BTF_ids section to 4 bytes */
asm (
" .pushsection " BTF_IDS_SECTION " , \" a \" ; \n "
" .balign 4, 0; \n "
" .popsection; \n " ) ;
2020-07-20 09:34:01 -07:00
BTF_ID_LIST ( test_list_local )
BTF_ID_UNUSED
BTF_ID ( typedef , S )
BTF_ID ( typedef , T )
BTF_ID ( typedef , U )
BTF_ID ( struct , S )
BTF_ID ( union , U )
BTF_ID ( func , func )
extern __u32 test_list_global [ ] ;
2022-06-28 10:43:10 -07:00
BTF_ID_LIST_GLOBAL ( test_list_global , 1 )
2020-07-11 23:53:29 +02:00
BTF_ID_UNUSED
BTF_ID ( typedef , S )
BTF_ID ( typedef , T )
BTF_ID ( typedef , U )
BTF_ID ( struct , S )
BTF_ID ( union , U )
BTF_ID ( func , func )
2020-08-25 21:21:24 +02:00
BTF_SET_START ( test_set )
BTF_ID ( typedef , S )
BTF_ID ( typedef , T )
BTF_ID ( typedef , U )
BTF_ID ( struct , S )
BTF_ID ( union , U )
BTF_ID ( func , func )
BTF_SET_END ( test_set )
2020-07-11 23:53:29 +02:00
static int
__resolve_symbol ( struct btf * btf , int type_id )
{
const struct btf_type * type ;
const char * str ;
unsigned int i ;
type = btf__type_by_id ( btf , type_id ) ;
if ( ! type ) {
PRINT_FAIL ( " Failed to get type for ID %d \n " , type_id ) ;
return - 1 ;
}
for ( i = 0 ; i < ARRAY_SIZE ( test_symbols ) ; i + + ) {
2021-05-24 20:59:32 -07:00
if ( test_symbols [ i ] . id > = 0 )
2020-07-11 23:53:29 +02:00
continue ;
if ( BTF_INFO_KIND ( type - > info ) ! = test_symbols [ i ] . type )
continue ;
str = btf__name_by_offset ( btf , type - > name_off ) ;
if ( ! str ) {
PRINT_FAIL ( " Failed to get name for BTF ID %d \n " , type_id ) ;
return - 1 ;
}
if ( ! strcmp ( str , test_symbols [ i ] . name ) )
test_symbols [ i ] . id = type_id ;
}
return 0 ;
}
static int resolve_symbols ( void )
{
struct btf * btf ;
int type_id ;
__u32 nr ;
2022-09-01 22:22:53 +00:00
btf = btf__parse_elf ( " btf_data.bpf.o " , NULL ) ;
2020-07-11 23:53:29 +02:00
if ( CHECK ( libbpf_get_error ( btf ) , " resolve " ,
" Failed to load BTF from btf_data.o \n " ) )
return - 1 ;
2021-10-22 21:06:23 +08:00
nr = btf__type_cnt ( btf ) ;
2020-07-11 23:53:29 +02:00
2021-10-22 21:06:23 +08:00
for ( type_id = 1 ; type_id < nr ; type_id + + ) {
2020-07-11 23:53:29 +02:00
if ( __resolve_symbol ( btf , type_id ) )
break ;
}
btf__free ( btf ) ;
return 0 ;
}
2021-10-22 15:32:25 -07:00
void test_resolve_btfids ( void )
2020-07-11 23:53:29 +02:00
{
2020-07-20 09:34:01 -07:00
__u32 * test_list , * test_lists [ ] = { test_list_local , test_list_global } ;
unsigned int i , j ;
2020-07-11 23:53:29 +02:00
int ret = 0 ;
if ( resolve_symbols ( ) )
2021-10-22 15:32:25 -07:00
return ;
2020-07-11 23:53:29 +02:00
2020-07-20 09:34:01 -07:00
/* Check BTF_ID_LIST(test_list_local) and
* BTF_ID_LIST_GLOBAL ( test_list_global ) IDs
*/
for ( j = 0 ; j < ARRAY_SIZE ( test_lists ) ; j + + ) {
test_list = test_lists [ j ] ;
2020-08-25 21:21:24 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( test_symbols ) ; i + + ) {
2020-07-20 09:34:01 -07:00
ret = CHECK ( test_list [ i ] ! = test_symbols [ i ] . id ,
" id_check " ,
" wrong ID for %s (%d != %d) \n " ,
test_symbols [ i ] . name ,
test_list [ i ] , test_symbols [ i ] . id ) ;
2020-08-25 21:21:24 +02:00
if ( ret )
2021-10-22 15:32:25 -07:00
return ;
2020-08-25 21:21:24 +02:00
}
}
/* Check BTF_SET_START(test_set) IDs */
for ( i = 0 ; i < test_set . cnt ; i + + ) {
bool found = false ;
for ( j = 0 ; j < ARRAY_SIZE ( test_symbols ) ; j + + ) {
if ( test_symbols [ j ] . id ! = test_set . ids [ i ] )
continue ;
found = true ;
break ;
}
ret = CHECK ( ! found , " id_check " ,
" ID %d not found in test_symbols \n " ,
test_set . ids [ i ] ) ;
if ( ret )
break ;
if ( i > 0 ) {
2021-04-26 12:29:45 -07:00
if ( ! ASSERT_LE ( test_set . ids [ i - 1 ] , test_set . ids [ i ] , " sort_check " ) )
2021-10-22 15:32:25 -07:00
return ;
2020-07-20 09:34:01 -07:00
}
2020-07-11 23:53:29 +02:00
}
}