@@ -156,13 +156,23 @@ struct filter {
156156 bool abs ;
157157};
158158
159- struct var_preset {
160- char * name ;
159+ struct rvalue {
161160 enum { INTEGRAL , ENUMERATOR } type ;
162161 union {
163162 long long ivalue ;
164163 char * svalue ;
165164 };
165+ };
166+
167+ struct field_access {
168+ char * name ;
169+ };
170+
171+ struct var_preset {
172+ struct field_access * atoms ;
173+ int atom_count ;
174+ char * full_name ;
175+ struct rvalue value ;
166176 bool applied ;
167177};
168178
@@ -1498,6 +1508,35 @@ static int reset_stat_cgroup(void)
14981508 return 0 ;
14991509}
15001510
1511+ static int parse_rvalue (const char * val , struct rvalue * rvalue )
1512+ {
1513+ long long value ;
1514+ char * val_end ;
1515+
1516+ if (val [0 ] == '-' || isdigit (val [0 ])) {
1517+ /* must be a number */
1518+ errno = 0 ;
1519+ value = strtoll (val , & val_end , 0 );
1520+ if (errno == ERANGE ) {
1521+ errno = 0 ;
1522+ value = strtoull (val , & val_end , 0 );
1523+ }
1524+ if (errno || * val_end != '\0' ) {
1525+ fprintf (stderr , "Failed to parse value '%s'\n" , val );
1526+ return - EINVAL ;
1527+ }
1528+ rvalue -> ivalue = value ;
1529+ rvalue -> type = INTEGRAL ;
1530+ } else {
1531+ /* if not a number, consider it enum value */
1532+ rvalue -> svalue = strdup (val );
1533+ if (!rvalue -> svalue )
1534+ return - ENOMEM ;
1535+ rvalue -> type = ENUMERATOR ;
1536+ }
1537+ return 0 ;
1538+ }
1539+
15011540static int process_prog (const char * filename , struct bpf_object * obj , struct bpf_program * prog )
15021541{
15031542 const char * base_filename = basename (strdupa (filename ));
@@ -1593,13 +1632,36 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
15931632 return 0 ;
15941633};
15951634
1635+ static int parse_var_atoms (const char * full_var , struct var_preset * preset )
1636+ {
1637+ char expr [256 ], * name , * saveptr ;
1638+
1639+ snprintf (expr , sizeof (expr ), "%s" , full_var );
1640+ preset -> atom_count = 0 ;
1641+ while ((name = strtok_r (preset -> atom_count ? NULL : expr , "." , & saveptr ))) {
1642+ struct field_access * tmp ;
1643+ int i = preset -> atom_count ;
1644+
1645+ tmp = reallocarray (preset -> atoms , i + 1 , sizeof (* preset -> atoms ));
1646+ if (!tmp )
1647+ return - ENOMEM ;
1648+
1649+ preset -> atoms = tmp ;
1650+ preset -> atom_count ++ ;
1651+
1652+ preset -> atoms [i ].name = strdup (name );
1653+ if (!preset -> atoms [i ].name )
1654+ return - ENOMEM ;
1655+ }
1656+ return 0 ;
1657+ }
1658+
15961659static int append_var_preset (struct var_preset * * presets , int * cnt , const char * expr )
15971660{
15981661 void * tmp ;
15991662 struct var_preset * cur ;
1600- char var [256 ], val [256 ], * val_end ;
1601- long long value ;
1602- int n ;
1663+ char var [256 ], val [256 ];
1664+ int n , err ;
16031665
16041666 tmp = realloc (* presets , (* cnt + 1 ) * sizeof (* * presets ));
16051667 if (!tmp )
@@ -1614,32 +1676,18 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
16141676 return - EINVAL ;
16151677 }
16161678
1617- if (val [0 ] == '-' || isdigit (val [0 ])) {
1618- /* must be a number */
1619- errno = 0 ;
1620- value = strtoll (val , & val_end , 0 );
1621- if (errno == ERANGE ) {
1622- errno = 0 ;
1623- value = strtoull (val , & val_end , 0 );
1624- }
1625- if (errno || * val_end != '\0' ) {
1626- fprintf (stderr , "Failed to parse value '%s'\n" , val );
1627- return - EINVAL ;
1628- }
1629- cur -> ivalue = value ;
1630- cur -> type = INTEGRAL ;
1631- } else {
1632- /* if not a number, consider it enum value */
1633- cur -> svalue = strdup (val );
1634- if (!cur -> svalue )
1635- return - ENOMEM ;
1636- cur -> type = ENUMERATOR ;
1637- }
1679+ err = parse_rvalue (val , & cur -> value );
1680+ if (err )
1681+ return err ;
16381682
1639- cur -> name = strdup (var );
1640- if (!cur -> name )
1683+ cur -> full_name = strdup (var );
1684+ if (!cur -> full_name )
16411685 return - ENOMEM ;
16421686
1687+ err = parse_var_atoms (var , cur );
1688+ if (err )
1689+ return err ;
1690+
16431691 return 0 ;
16441692}
16451693
@@ -1766,22 +1814,20 @@ const int btf_find_member(const struct btf *btf,
17661814}
17671815
17681816static int adjust_var_secinfo (struct btf * btf , const struct btf_type * t ,
1769- struct btf_var_secinfo * sinfo , const char * var )
1817+ struct btf_var_secinfo * sinfo , struct var_preset * preset )
17701818{
1771- char expr [256 ], * saveptr ;
17721819 const struct btf_type * base_type , * member_type ;
1773- int err , member_tid ;
1774- char * name ;
1820+ int err , member_tid , i ;
17751821 __u32 member_offset = 0 ;
17761822
17771823 base_type = btf__type_by_id (btf , btf__resolve_type (btf , t -> type ));
1778- snprintf (expr , sizeof (expr ), "%s" , var );
1779- strtok_r (expr , "." , & saveptr );
17801824
1781- while ((name = strtok_r (NULL , "." , & saveptr ))) {
1782- err = btf_find_member (btf , base_type , 0 , name , & member_tid , & member_offset );
1825+ for (i = 1 ; i < preset -> atom_count ; ++ i ) {
1826+ err = btf_find_member (btf , base_type , 0 , preset -> atoms [i ].name ,
1827+ & member_tid , & member_offset );
17831828 if (err ) {
1784- fprintf (stderr , "Could not find member %s for variable %s\n" , name , var );
1829+ fprintf (stderr , "Could not find member %s for variable %s\n" ,
1830+ preset -> atoms [i ].name , preset -> atoms [i - 1 ].name );
17851831 return err ;
17861832 }
17871833 member_type = btf__type_by_id (btf , member_tid );
@@ -1799,7 +1845,7 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
17991845{
18001846 const struct btf_type * base_type ;
18011847 void * ptr ;
1802- long long value = preset -> ivalue ;
1848+ long long value = preset -> value . ivalue ;
18031849 size_t size ;
18041850
18051851 base_type = btf__type_by_id (btf , btf__resolve_type (btf , sinfo -> type ));
@@ -1813,17 +1859,18 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
18131859 return - EINVAL ;
18141860 }
18151861
1816- if (preset -> type == ENUMERATOR ) {
1862+ if (preset -> value . type == ENUMERATOR ) {
18171863 if (btf_is_any_enum (base_type )) {
1818- if (enum_value_from_name (btf , base_type , preset -> svalue , & value )) {
1864+ if (enum_value_from_name (btf , base_type , preset -> value . svalue , & value )) {
18191865 fprintf (stderr ,
18201866 "Failed to find integer value for enum element %s\n" ,
1821- preset -> svalue );
1867+ preset -> value . svalue );
18221868 return - EINVAL ;
18231869 }
18241870 } else {
18251871 fprintf (stderr , "Value %s is not supported for type %s\n" ,
1826- preset -> svalue , btf__name_by_offset (btf , base_type -> name_off ));
1872+ preset -> value .svalue ,
1873+ btf__name_by_offset (btf , base_type -> name_off ));
18271874 return - EINVAL ;
18281875 }
18291876 }
@@ -1890,20 +1937,16 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
18901937 for (j = 0 ; j < n ; ++ j , ++ sinfo ) {
18911938 const struct btf_type * var_type = btf__type_by_id (btf , sinfo -> type );
18921939 const char * var_name ;
1893- int var_len ;
18941940
18951941 if (!btf_is_var (var_type ))
18961942 continue ;
18971943
18981944 var_name = btf__name_by_offset (btf , var_type -> name_off );
1899- var_len = strlen (var_name );
19001945
19011946 for (k = 0 ; k < npresets ; ++ k ) {
19021947 struct btf_var_secinfo tmp_sinfo ;
19031948
1904- if (strncmp (var_name , presets [k ].name , var_len ) != 0 ||
1905- (presets [k ].name [var_len ] != '\0' &&
1906- presets [k ].name [var_len ] != '.' ))
1949+ if (strcmp (var_name , presets [k ].atoms [0 ].name ) != 0 )
19071950 continue ;
19081951
19091952 if (presets [k ].applied ) {
@@ -1913,7 +1956,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
19131956 }
19141957 tmp_sinfo = * sinfo ;
19151958 err = adjust_var_secinfo (btf , var_type ,
1916- & tmp_sinfo , presets [ k ]. name );
1959+ & tmp_sinfo , presets + k );
19171960 if (err )
19181961 return err ;
19191962
@@ -1928,7 +1971,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
19281971 for (i = 0 ; i < npresets ; ++ i ) {
19291972 if (!presets [i ].applied ) {
19301973 fprintf (stderr , "Global variable preset %s has not been applied\n" ,
1931- presets [i ].name );
1974+ presets [i ].full_name );
19321975 }
19331976 presets [i ].applied = false;
19341977 }
@@ -3062,7 +3105,7 @@ static int handle_replay_mode(void)
30623105
30633106int main (int argc , char * * argv )
30643107{
3065- int err = 0 , i ;
3108+ int err = 0 , i , j ;
30663109
30673110 if (argp_parse (& argp , argc , argv , 0 , NULL , NULL ))
30683111 return 1 ;
@@ -3121,9 +3164,12 @@ int main(int argc, char **argv)
31213164 }
31223165 free (env .deny_filters );
31233166 for (i = 0 ; i < env .npresets ; ++ i ) {
3124- free (env .presets [i ].name );
3125- if (env .presets [i ].type == ENUMERATOR )
3126- free (env .presets [i ].svalue );
3167+ free (env .presets [i ].full_name );
3168+ for (j = 0 ; j < env .presets [i ].atom_count ; ++ j )
3169+ free (env .presets [i ].atoms [j ].name );
3170+ free (env .presets [i ].atoms );
3171+ if (env .presets [i ].value .type == ENUMERATOR )
3172+ free (env .presets [i ].value .svalue );
31273173 }
31283174 free (env .presets );
31293175 return - err ;
0 commit comments