@@ -165,7 +165,11 @@ struct rvalue {
165165};
166166
167167struct field_access {
168- char * name ;
168+ enum { FIELD_NAME , ARRAY_INDEX } type ;
169+ union {
170+ char * name ;
171+ struct rvalue index ;
172+ };
169173};
170174
171175struct var_preset {
@@ -1630,28 +1634,60 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
16301634 free (buf );
16311635
16321636 return 0 ;
1633- };
1637+ }
1638+
1639+ static int append_preset_atom (struct var_preset * preset , char * value , bool is_index )
1640+ {
1641+ struct field_access * tmp ;
1642+ int i = preset -> atom_count ;
1643+ int err ;
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+ if (is_index ) {
1653+ preset -> atoms [i ].type = ARRAY_INDEX ;
1654+ err = parse_rvalue (value , & preset -> atoms [i ].index );
1655+ if (err )
1656+ return err ;
1657+ } else {
1658+ preset -> atoms [i ].type = FIELD_NAME ;
1659+ preset -> atoms [i ].name = strdup (value );
1660+ if (!preset -> atoms [i ].name )
1661+ return - ENOMEM ;
1662+ }
1663+ return 0 ;
1664+ }
16341665
16351666static int parse_var_atoms (const char * full_var , struct var_preset * preset )
16361667{
1637- char expr [256 ], * name , * saveptr ;
1668+ char expr [256 ], var [256 ], * name , * saveptr ;
1669+ int n , len , off ;
16381670
16391671 snprintf (expr , sizeof (expr ), "%s" , full_var );
16401672 preset -> atom_count = 0 ;
16411673 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 ++ ;
1674+ len = strlen (name );
1675+ /* parse variable name */
1676+ if (sscanf (name , "%[a-zA-Z0-9_] %n" , var , & off ) != 1 ) {
1677+ fprintf (stderr , "Can't parse %s\n" , name );
1678+ return - EINVAL ;
1679+ }
1680+ append_preset_atom (preset , var , false);
16511681
1652- preset -> atoms [i ].name = strdup (name );
1653- if (!preset -> atoms [i ].name )
1654- return - ENOMEM ;
1682+ /* parse optional array indexes */
1683+ while (off < len ) {
1684+ if (sscanf (name + off , " [ %[a-zA-Z0-9_] ] %n" , var , & n ) != 1 ) {
1685+ fprintf (stderr , "Can't parse %s as index\n" , name + off );
1686+ return - EINVAL ;
1687+ }
1688+ append_preset_atom (preset , var , true);
1689+ off += n ;
1690+ }
16551691 }
16561692 return 0 ;
16571693}
@@ -1661,7 +1697,7 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
16611697 void * tmp ;
16621698 struct var_preset * cur ;
16631699 char var [256 ], val [256 ];
1664- int n , err ;
1700+ int n , err , i ;
16651701
16661702 tmp = realloc (* presets , (* cnt + 1 ) * sizeof (* * presets ));
16671703 if (!tmp )
@@ -1671,10 +1707,16 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
16711707 memset (cur , 0 , sizeof (* cur ));
16721708 (* cnt )++ ;
16731709
1674- if (sscanf (expr , "%s = %s %n" , var , val , & n ) != 2 || n != strlen (expr )) {
1710+ if (sscanf (expr , " %[][a-zA-Z0-9_. ] = %s %n" , var , val , & n ) != 2 || n != strlen (expr )) {
16751711 fprintf (stderr , "Failed to parse expression '%s'\n" , expr );
16761712 return - EINVAL ;
16771713 }
1714+ /* Remove trailing spaces from var, as scanf may add those */
1715+ for (i = strlen (var ) - 1 ; i > 0 ; -- i ) {
1716+ if (!isspace (var [i ]))
1717+ break ;
1718+ var [i ] = '\0' ;
1719+ }
16781720
16791721 err = parse_rvalue (val , & cur -> value );
16801722 if (err )
@@ -1764,29 +1806,104 @@ static bool is_preset_supported(const struct btf_type *t)
17641806 return btf_is_int (t ) || btf_is_enum (t ) || btf_is_enum64 (t );
17651807}
17661808
1767- const int btf_find_member (const struct btf * btf ,
1768- const struct btf_type * parent_type ,
1769- __u32 parent_offset ,
1770- const char * member_name ,
1771- int * member_tid ,
1772- __u32 * member_offset )
1809+ static int find_enum_value (const struct btf * btf , const char * name , long long * value )
1810+ {
1811+ const struct btf_type * t ;
1812+ int cnt , i ;
1813+ long long lvalue ;
1814+
1815+ cnt = btf__type_cnt (btf );
1816+ for (i = 1 ; i != cnt ; ++ i ) {
1817+ t = btf__type_by_id (btf , i );
1818+
1819+ if (!btf_is_any_enum (t ))
1820+ continue ;
1821+
1822+ if (enum_value_from_name (btf , t , name , & lvalue ) == 0 ) {
1823+ * value = lvalue ;
1824+ return 0 ;
1825+ }
1826+ }
1827+ return - ESRCH ;
1828+ }
1829+
1830+ static int resolve_rvalue (struct btf * btf , const struct rvalue * rvalue , long long * result )
1831+ {
1832+ int err = 0 ;
1833+
1834+ switch (rvalue -> type ) {
1835+ case INTEGRAL :
1836+ * result = rvalue -> ivalue ;
1837+ return 0 ;
1838+ case ENUMERATOR :
1839+ err = find_enum_value (btf , rvalue -> svalue , result );
1840+ if (err ) {
1841+ fprintf (stderr , "Can't resolve enum value %s\n" , rvalue -> svalue );
1842+ return err ;
1843+ }
1844+ return 0 ;
1845+ default :
1846+ fprintf (stderr , "Unknown rvalue type\n" );
1847+ return - EOPNOTSUPP ;
1848+ }
1849+ return 0 ;
1850+ }
1851+
1852+ static int adjust_var_secinfo_array (struct btf * btf , int tid , struct field_access * atom ,
1853+ const char * array_name , struct btf_var_secinfo * sinfo )
1854+ {
1855+ const struct btf_type * t ;
1856+ struct btf_array * barr ;
1857+ long long idx ;
1858+ int err ;
1859+
1860+ tid = btf__resolve_type (btf , tid );
1861+ t = btf__type_by_id (btf , tid );
1862+ if (!btf_is_array (t )) {
1863+ fprintf (stderr , "Array index is not expected for %s\n" ,
1864+ array_name );
1865+ return - EINVAL ;
1866+ }
1867+ barr = btf_array (t );
1868+ err = resolve_rvalue (btf , & atom -> index , & idx );
1869+ if (err )
1870+ return err ;
1871+ if (idx < 0 || idx >= barr -> nelems ) {
1872+ fprintf (stderr , "Array index %lld is out of bounds [0, %u]: %s\n" ,
1873+ idx , barr -> nelems , array_name );
1874+ return - EINVAL ;
1875+ }
1876+ sinfo -> size = btf__resolve_size (btf , barr -> type );
1877+ sinfo -> offset += sinfo -> size * idx ;
1878+ sinfo -> type = btf__resolve_type (btf , barr -> type );
1879+ return 0 ;
1880+ }
1881+
1882+ static int adjust_var_secinfo_member (const struct btf * btf ,
1883+ const struct btf_type * parent_type ,
1884+ __u32 parent_offset ,
1885+ const char * member_name ,
1886+ struct btf_var_secinfo * sinfo )
17731887{
17741888 int i ;
17751889
1776- if (!btf_is_composite (parent_type ))
1890+ if (!btf_is_composite (parent_type )) {
1891+ fprintf (stderr , "Can't resolve field %s for non-composite type\n" , member_name );
17771892 return - EINVAL ;
1893+ }
17781894
17791895 for (i = 0 ; i < btf_vlen (parent_type ); ++ i ) {
17801896 const struct btf_member * member ;
17811897 const struct btf_type * member_type ;
1782- int tid ;
1898+ int tid , off ;
17831899
17841900 member = btf_members (parent_type ) + i ;
17851901 tid = btf__resolve_type (btf , member -> type );
17861902 if (tid < 0 )
17871903 return - EINVAL ;
17881904
17891905 member_type = btf__type_by_id (btf , tid );
1906+ off = parent_offset + member -> offset ;
17901907 if (member -> name_off ) {
17911908 const char * name = btf__name_by_offset (btf , member -> name_off );
17921909
@@ -1796,15 +1913,16 @@ const int btf_find_member(const struct btf *btf,
17961913 name );
17971914 return - EINVAL ;
17981915 }
1799- * member_offset = parent_offset + member -> offset ;
1800- * member_tid = tid ;
1916+ sinfo -> offset += off / 8 ;
1917+ sinfo -> type = tid ;
1918+ sinfo -> size = member_type -> size ;
18011919 return 0 ;
18021920 }
18031921 } else if (btf_is_composite (member_type )) {
18041922 int err ;
18051923
1806- err = btf_find_member (btf , member_type , parent_offset + member -> offset ,
1807- member_name , member_tid , member_offset );
1924+ err = adjust_var_secinfo_member (btf , member_type , off ,
1925+ member_name , sinfo );
18081926 if (!err )
18091927 return 0 ;
18101928 }
@@ -1816,26 +1934,39 @@ const int btf_find_member(const struct btf *btf,
18161934static int adjust_var_secinfo (struct btf * btf , const struct btf_type * t ,
18171935 struct btf_var_secinfo * sinfo , struct var_preset * preset )
18181936{
1819- const struct btf_type * base_type , * member_type ;
1820- int err , member_tid , i ;
1821- __u32 member_offset = 0 ;
1937+ const struct btf_type * base_type ;
1938+ const char * prev_name ;
1939+ int err , i ;
1940+ int tid ;
1941+
1942+ assert (preset -> atom_count > 0 );
1943+ assert (preset -> atoms [0 ].type == FIELD_NAME );
18221944
1823- base_type = btf__type_by_id (btf , btf__resolve_type (btf , t -> type ));
1945+ tid = btf__resolve_type (btf , t -> type );
1946+ base_type = btf__type_by_id (btf , tid );
1947+ prev_name = preset -> atoms [0 ].name ;
18241948
18251949 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 );
1828- if (err ) {
1829- fprintf (stderr , "Could not find member %s for variable %s\n" ,
1830- preset -> atoms [i ].name , preset -> atoms [i - 1 ].name );
1831- return err ;
1950+ struct field_access * atom = preset -> atoms + i ;
1951+
1952+ switch (atom -> type ) {
1953+ case ARRAY_INDEX :
1954+ err = adjust_var_secinfo_array (btf , tid , atom , prev_name , sinfo );
1955+ break ;
1956+ case FIELD_NAME :
1957+ err = adjust_var_secinfo_member (btf , base_type , 0 , atom -> name , sinfo );
1958+ prev_name = atom -> name ;
1959+ break ;
1960+ default :
1961+ fprintf (stderr , "Unknown field_access type\n" );
1962+ return - EOPNOTSUPP ;
18321963 }
1833- member_type = btf__type_by_id (btf , member_tid );
1834- sinfo -> offset += member_offset / 8 ;
1835- sinfo -> size = member_type -> size ;
1836- sinfo -> type = member_tid ;
1837- base_type = member_type ;
1964+ if (err )
1965+ return err ;
1966+ base_type = btf__type_by_id (btf , sinfo -> type );
1967+ tid = sinfo -> type ;
18381968 }
1969+
18391970 return 0 ;
18401971}
18411972
@@ -1854,8 +1985,8 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
18541985 return - EINVAL ;
18551986 }
18561987 if (!is_preset_supported (base_type )) {
1857- fprintf (stderr , "Setting value for type %s is not supported\n" ,
1858- btf__name_by_offset ( btf , base_type -> name_off ) );
1988+ fprintf (stderr , "Can't set %s. Only ints and enums are supported\n" ,
1989+ preset -> full_name );
18591990 return - EINVAL ;
18601991 }
18611992
@@ -1972,6 +2103,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
19722103 if (!presets [i ].applied ) {
19732104 fprintf (stderr , "Global variable preset %s has not been applied\n" ,
19742105 presets [i ].full_name );
2106+ err = - EINVAL ;
19752107 }
19762108 presets [i ].applied = false;
19772109 }
@@ -3165,11 +3297,18 @@ int main(int argc, char **argv)
31653297 free (env .deny_filters );
31663298 for (i = 0 ; i < env .npresets ; ++ i ) {
31673299 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 );
3300+ for (j = 0 ; j < env .presets [i ].atom_count ; ++ j ) {
3301+ switch (env .presets [i ].atoms [j ].type ) {
3302+ case FIELD_NAME :
3303+ free (env .presets [i ].atoms [j ].name );
3304+ break ;
3305+ case ARRAY_INDEX :
3306+ if (env .presets [i ].atoms [j ].index .type == ENUMERATOR )
3307+ free (env .presets [i ].atoms [j ].index .svalue );
3308+ break ;
3309+ }
3310+ }
31703311 free (env .presets [i ].atoms );
3171- if (env .presets [i ].value .type == ENUMERATOR )
3172- free (env .presets [i ].value .svalue );
31733312 }
31743313 free (env .presets );
31753314 return - err ;
0 commit comments