@@ -165,7 +165,11 @@ struct rvalue {
165
165
};
166
166
167
167
struct field_access {
168
- char * name ;
168
+ enum { FIELD_NAME , ARRAY_INDEX } type ;
169
+ union {
170
+ char * name ;
171
+ struct rvalue index ;
172
+ };
169
173
};
170
174
171
175
struct var_preset {
@@ -1630,28 +1634,60 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
1630
1634
free (buf );
1631
1635
1632
1636
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
+ }
1634
1665
1635
1666
static int parse_var_atoms (const char * full_var , struct var_preset * preset )
1636
1667
{
1637
- char expr [256 ], * name , * saveptr ;
1668
+ char expr [256 ], var [256 ], * name , * saveptr ;
1669
+ int n , len , off ;
1638
1670
1639
1671
snprintf (expr , sizeof (expr ), "%s" , full_var );
1640
1672
preset -> atom_count = 0 ;
1641
1673
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);
1651
1681
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
+ }
1655
1691
}
1656
1692
return 0 ;
1657
1693
}
@@ -1661,7 +1697,7 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
1661
1697
void * tmp ;
1662
1698
struct var_preset * cur ;
1663
1699
char var [256 ], val [256 ];
1664
- int n , err ;
1700
+ int n , err , i ;
1665
1701
1666
1702
tmp = realloc (* presets , (* cnt + 1 ) * sizeof (* * presets ));
1667
1703
if (!tmp )
@@ -1671,10 +1707,16 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
1671
1707
memset (cur , 0 , sizeof (* cur ));
1672
1708
(* cnt )++ ;
1673
1709
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 )) {
1675
1711
fprintf (stderr , "Failed to parse expression '%s'\n" , expr );
1676
1712
return - EINVAL ;
1677
1713
}
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
+ }
1678
1720
1679
1721
err = parse_rvalue (val , & cur -> value );
1680
1722
if (err )
@@ -1764,29 +1806,104 @@ static bool is_preset_supported(const struct btf_type *t)
1764
1806
return btf_is_int (t ) || btf_is_enum (t ) || btf_is_enum64 (t );
1765
1807
}
1766
1808
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 )
1773
1887
{
1774
1888
int i ;
1775
1889
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 );
1777
1892
return - EINVAL ;
1893
+ }
1778
1894
1779
1895
for (i = 0 ; i < btf_vlen (parent_type ); ++ i ) {
1780
1896
const struct btf_member * member ;
1781
1897
const struct btf_type * member_type ;
1782
- int tid ;
1898
+ int tid , off ;
1783
1899
1784
1900
member = btf_members (parent_type ) + i ;
1785
1901
tid = btf__resolve_type (btf , member -> type );
1786
1902
if (tid < 0 )
1787
1903
return - EINVAL ;
1788
1904
1789
1905
member_type = btf__type_by_id (btf , tid );
1906
+ off = parent_offset + member -> offset ;
1790
1907
if (member -> name_off ) {
1791
1908
const char * name = btf__name_by_offset (btf , member -> name_off );
1792
1909
@@ -1796,15 +1913,16 @@ const int btf_find_member(const struct btf *btf,
1796
1913
name );
1797
1914
return - EINVAL ;
1798
1915
}
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 ;
1801
1919
return 0 ;
1802
1920
}
1803
1921
} else if (btf_is_composite (member_type )) {
1804
1922
int err ;
1805
1923
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 );
1808
1926
if (!err )
1809
1927
return 0 ;
1810
1928
}
@@ -1816,26 +1934,39 @@ const int btf_find_member(const struct btf *btf,
1816
1934
static int adjust_var_secinfo (struct btf * btf , const struct btf_type * t ,
1817
1935
struct btf_var_secinfo * sinfo , struct var_preset * preset )
1818
1936
{
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 );
1822
1944
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 ;
1824
1948
1825
1949
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 ;
1832
1963
}
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 ;
1838
1968
}
1969
+
1839
1970
return 0 ;
1840
1971
}
1841
1972
@@ -1854,8 +1985,8 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
1854
1985
return - EINVAL ;
1855
1986
}
1856
1987
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 );
1859
1990
return - EINVAL ;
1860
1991
}
1861
1992
@@ -1972,6 +2103,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
1972
2103
if (!presets [i ].applied ) {
1973
2104
fprintf (stderr , "Global variable preset %s has not been applied\n" ,
1974
2105
presets [i ].full_name );
2106
+ err = - EINVAL ;
1975
2107
}
1976
2108
presets [i ].applied = false;
1977
2109
}
@@ -3165,11 +3297,18 @@ int main(int argc, char **argv)
3165
3297
free (env .deny_filters );
3166
3298
for (i = 0 ; i < env .npresets ; ++ i ) {
3167
3299
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
+ }
3170
3311
free (env .presets [i ].atoms );
3171
- if (env .presets [i ].value .type == ENUMERATOR )
3172
- free (env .presets [i ].value .svalue );
3173
3312
}
3174
3313
free (env .presets );
3175
3314
return - err ;
0 commit comments