@@ -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
}
@@ -1671,7 +1707,7 @@ 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
}
@@ -1764,17 +1800,103 @@ static bool is_preset_supported(const struct btf_type *t)
1764
1800
return btf_is_int (t ) || btf_is_enum (t ) || btf_is_enum64 (t );
1765
1801
}
1766
1802
1803
+ static int find_enum_value (const struct btf * btf , const char * name , long long * value )
1804
+ {
1805
+ const struct btf_type * t ;
1806
+ int cnt , i ;
1807
+ long long lvalue ;
1808
+
1809
+ cnt = btf__type_cnt (btf );
1810
+ for (i = 1 ; i != cnt ; ++ i ) {
1811
+ t = btf__type_by_id (btf , i );
1812
+
1813
+ if (!btf_is_any_enum (t ))
1814
+ continue ;
1815
+
1816
+ if (enum_value_from_name (btf , t , name , & lvalue ) == 0 ) {
1817
+ * value = lvalue ;
1818
+ return 0 ;
1819
+ }
1820
+ }
1821
+ return - ESRCH ;
1822
+ }
1823
+
1824
+ static int resolve_rvalue (struct btf * btf , const struct rvalue * rvalue , long long * result )
1825
+ {
1826
+ int err = 0 ;
1827
+
1828
+ switch (rvalue -> type ) {
1829
+ case INTEGRAL :
1830
+ * result = rvalue -> ivalue ;
1831
+ break ;
1832
+ case ENUMERATOR :
1833
+ err = find_enum_value (btf , rvalue -> svalue , result );
1834
+ if (err )
1835
+ fprintf (stderr , "Can't resolve enum value %s\n" , rvalue -> svalue );
1836
+ break ;
1837
+ }
1838
+ return err ;
1839
+ }
1840
+
1841
+ /* Returns number of consumed atoms from preset, negative error if failed */
1842
+ static int adjust_var_secinfo_array (struct btf * btf , int tid , struct var_preset * preset ,
1843
+ int atom_idx , struct btf_var_secinfo * sinfo )
1844
+ {
1845
+ struct btf_array * barr ;
1846
+ int i = atom_idx , err ;
1847
+ const struct btf_type * t ;
1848
+ long long off = 0 , idx ;
1849
+
1850
+ if (atom_idx < 1 ) /* Array index can't be the first atom */
1851
+ return - EINVAL ;
1852
+
1853
+ tid = btf__resolve_type (btf , tid );
1854
+ t = btf__type_by_id (btf , tid );
1855
+ if (!btf_is_array (t )) {
1856
+ fprintf (stderr , "Array index is not expected for %s\n" ,
1857
+ preset -> atoms [atom_idx - 1 ].name );
1858
+ return - EINVAL ;
1859
+ }
1860
+ do {
1861
+ if (preset -> atoms [i ].type != ARRAY_INDEX ) {
1862
+ fprintf (stderr , "Array index is missing for %s\n" ,
1863
+ preset -> atoms [atom_idx - 1 ].name );
1864
+ return - EINVAL ;
1865
+ }
1866
+ err = resolve_rvalue (btf , & preset -> atoms [i ].index , & idx );
1867
+ if (err )
1868
+ return err ;
1869
+ barr = btf_array (t );
1870
+ if (idx < 0 || idx >= barr -> nelems ) {
1871
+ fprintf (stderr , "Array index %lld is out of bounds [0, %u]: %s\n" ,
1872
+ idx , barr -> nelems , preset -> full_name );
1873
+ return - EINVAL ;
1874
+ }
1875
+ off *= barr -> nelems ;
1876
+ off += idx ;
1877
+ tid = btf__resolve_type (btf , barr -> type );
1878
+ t = btf__type_by_id (btf , tid );
1879
+ i ++ ;
1880
+ } while (btf_is_array (t ));
1881
+
1882
+ sinfo -> size = t -> size ;
1883
+ sinfo -> type = tid ;
1884
+ sinfo -> offset += off * t -> size ;
1885
+ return i - atom_idx ;
1886
+ }
1887
+
1767
1888
const int btf_find_member (const struct btf * btf ,
1768
1889
const struct btf_type * parent_type ,
1769
1890
__u32 parent_offset ,
1770
1891
const char * member_name ,
1771
- int * member_tid ,
1772
- __u32 * member_offset )
1892
+ struct btf_var_secinfo * sinfo )
1773
1893
{
1774
1894
int i ;
1775
1895
1776
- if (!btf_is_composite (parent_type ))
1896
+ if (!btf_is_composite (parent_type )) {
1897
+ fprintf (stderr , "Can't resolve field %s for non-composite type\n" , member_name );
1777
1898
return - EINVAL ;
1899
+ }
1778
1900
1779
1901
for (i = 0 ; i < btf_vlen (parent_type ); ++ i ) {
1780
1902
const struct btf_member * member ;
@@ -1796,15 +1918,16 @@ const int btf_find_member(const struct btf *btf,
1796
1918
name );
1797
1919
return - EINVAL ;
1798
1920
}
1799
- * member_offset = parent_offset + member -> offset ;
1800
- * member_tid = tid ;
1921
+ sinfo -> offset += (parent_offset + member -> offset ) / 8 ;
1922
+ sinfo -> type = tid ;
1923
+ sinfo -> size = member_type -> size ;
1801
1924
return 0 ;
1802
1925
}
1803
1926
} else if (btf_is_composite (member_type )) {
1804
1927
int err ;
1805
1928
1806
1929
err = btf_find_member (btf , member_type , parent_offset + member -> offset ,
1807
- member_name , member_tid , member_offset );
1930
+ member_name , sinfo );
1808
1931
if (!err )
1809
1932
return 0 ;
1810
1933
}
@@ -1816,26 +1939,29 @@ const int btf_find_member(const struct btf *btf,
1816
1939
static int adjust_var_secinfo (struct btf * btf , const struct btf_type * t ,
1817
1940
struct btf_var_secinfo * sinfo , struct var_preset * preset )
1818
1941
{
1819
- const struct btf_type * base_type , * member_type ;
1820
- int err , member_tid , i ;
1821
- __u32 member_offset = 0 ;
1822
-
1823
- base_type = btf__type_by_id (btf , btf__resolve_type (btf , t -> type ));
1824
-
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 );
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 ;
1942
+ const struct btf_type * base_type ;
1943
+ int err , i = 1 , n ;
1944
+ int tid ;
1945
+
1946
+ tid = btf__resolve_type (btf , t -> type );
1947
+ base_type = btf__type_by_id (btf , tid );
1948
+
1949
+ while (i < preset -> atom_count ) {
1950
+ if (preset -> atoms [i ].type == ARRAY_INDEX ) {
1951
+ n = adjust_var_secinfo_array (btf , tid , preset , i , sinfo );
1952
+ if (n < 0 )
1953
+ return n ;
1954
+ i += n ;
1955
+ } else {
1956
+ err = btf_find_member (btf , base_type , 0 , preset -> atoms [i ].name , sinfo );
1957
+ if (err )
1958
+ return err ;
1959
+ i ++ ;
1832
1960
}
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 ;
1961
+ base_type = btf__type_by_id (btf , sinfo -> type );
1962
+ tid = sinfo -> type ;
1838
1963
}
1964
+
1839
1965
return 0 ;
1840
1966
}
1841
1967
@@ -1854,8 +1980,8 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf,
1854
1980
return - EINVAL ;
1855
1981
}
1856
1982
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 ) );
1983
+ fprintf (stderr , "Can't set %s. Only ints and enums are supported\n" ,
1984
+ preset -> full_name );
1859
1985
return - EINVAL ;
1860
1986
}
1861
1987
@@ -1972,6 +2098,7 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
1972
2098
if (!presets [i ].applied ) {
1973
2099
fprintf (stderr , "Global variable preset %s has not been applied\n" ,
1974
2100
presets [i ].full_name );
2101
+ err = - EINVAL ;
1975
2102
}
1976
2103
presets [i ].applied = false;
1977
2104
}
@@ -3165,11 +3292,18 @@ int main(int argc, char **argv)
3165
3292
free (env .deny_filters );
3166
3293
for (i = 0 ; i < env .npresets ; ++ i ) {
3167
3294
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 );
3295
+ for (j = 0 ; j < env .presets [i ].atom_count ; ++ j ) {
3296
+ switch (env .presets [i ].atoms [j ].type ) {
3297
+ case FIELD_NAME :
3298
+ free (env .presets [i ].atoms [j ].name );
3299
+ break ;
3300
+ case ARRAY_INDEX :
3301
+ if (env .presets [i ].atoms [j ].index .type == ENUMERATOR )
3302
+ free (env .presets [i ].atoms [j ].index .svalue );
3303
+ break ;
3304
+ }
3305
+ }
3170
3306
free (env .presets [i ].atoms );
3171
- if (env .presets [i ].value .type == ENUMERATOR )
3172
- free (env .presets [i ].value .svalue );
3173
3307
}
3174
3308
free (env .presets );
3175
3309
return - err ;
0 commit comments