@@ -165,6 +165,7 @@ struct variant {
165165
166166struct var_preset_atom {
167167 char * name ;
168+ struct variant index ;
168169};
169170
170171struct var_preset {
@@ -1375,8 +1376,8 @@ static int process_prog(const char *filename, struct bpf_object *obj, struct bpf
13751376
13761377static int parse_var_atoms (const char * full_var , struct var_preset * preset )
13771378{
1378- char expr [256 ], * name , * saveptr ;
1379- int i = 0 ;
1379+ char expr [256 ], var [ 256 ], idx [ 256 ], * name , * saveptr ;
1380+ int i = 0 , n ;
13801381
13811382 snprintf (expr , sizeof (expr ), "%s" , full_var );
13821383
@@ -1385,7 +1386,27 @@ static int parse_var_atoms(const char *full_var, struct var_preset *preset)
13851386 if (!preset -> atoms )
13861387 return - ENOMEM ;
13871388
1388- preset -> atoms [i ].name = strdup (name );
1389+ if (sscanf (name , "%[a-zA-Z0-9_][%[a-zA-Z0-9]] %n" , var , idx , & n ) == 2 &&
1390+ strlen (name ) == n ) {
1391+ /* current atom is an array, parse index */
1392+ preset -> atoms [i ].name = strdup (var );
1393+ if (sscanf (idx , "%d" , & n ) == 1 ) {
1394+ preset -> atoms [i ].index .type = INTEGRAL ;
1395+ preset -> atoms [i ].index .ivalue = n ;
1396+ } else {
1397+ /* index is not a number, assume it's an enum */
1398+ preset -> atoms [i ].index .type = ENUMERATOR ;
1399+ preset -> atoms [i ].index .svalue = strdup (idx );
1400+ }
1401+ } else if (sscanf (name , "%[a-zA-Z0-9_] %n" , var , & n ) == 1 &&
1402+ strlen (name ) == n ) {
1403+ preset -> atoms [i ].name = strdup (name );
1404+ preset -> atoms [i ].index .type = NONE ;
1405+ } else {
1406+ fprintf (stderr , "Could not parse '%s'" , name );
1407+ return - EINVAL ;
1408+ }
1409+
13891410 if (!preset -> atoms [i ].name )
13901411 return - ENOMEM ;
13911412 ++ i ;
@@ -1410,7 +1431,7 @@ static int append_var_preset(struct var_preset **presets, int *cnt, const char *
14101431 memset (cur , 0 , sizeof (* cur ));
14111432 (* cnt )++ ;
14121433
1413- if (sscanf (expr , "%s = %s %n" , var , val , & n ) != 2 || n != strlen (expr )) {
1434+ if (sscanf (expr , "%[][a-zA-Z0-9_.] = %s %n" , var , val , & n ) != 2 || n != strlen (expr )) {
14141435 fprintf (stderr , "Failed to parse expression '%s'\n" , expr );
14151436 return - EINVAL ;
14161437 }
@@ -1521,14 +1542,82 @@ static bool is_preset_supported(const struct btf_type *t)
15211542 return btf_is_int (t ) || btf_is_enum (t ) || btf_is_enum64 (t );
15221543}
15231544
1545+ static int find_enum_value (const struct btf * btf , const char * name , int * value )
1546+ {
1547+ const struct btf_type * t ;
1548+ int cnt , i ;
1549+ long long lvalue ;
1550+
1551+ cnt = btf__type_cnt (btf );
1552+ for (i = 1 ; i != cnt ; ++ i ) {
1553+ t = btf__type_by_id (btf , i );
1554+
1555+ if (!btf_is_any_enum (t ))
1556+ continue ;
1557+
1558+ if (enum_value_from_name (btf , t , name , & lvalue ) == 0 ) {
1559+ * value = (int )lvalue ;
1560+ return 0 ;
1561+ }
1562+ }
1563+ return - ESRCH ;
1564+ }
1565+
1566+ static int adjust_array_secinfo (const struct btf * btf , const struct btf_type * t ,
1567+ const struct var_preset_atom * var_atom ,
1568+ struct btf_var_secinfo * sinfo )
1569+ {
1570+ struct btf_array * barr ;
1571+ const struct btf_type * type ;
1572+ int tid , index ;
1573+
1574+ if (!btf_is_array (t ))
1575+ return - EINVAL ;
1576+
1577+ barr = btf_array (t );
1578+ tid = btf__resolve_type (btf , barr -> type );
1579+ type = btf__type_by_id (btf , tid );
1580+ if (!btf_is_int (type ) && !btf_is_any_enum (type ) && !btf_is_composite (type )) {
1581+ fprintf (stderr ,
1582+ "Unsupported array type for variable %s. Only int, enum, struct, union are supported\n" ,
1583+ var_atom -> name );
1584+ return - EINVAL ;
1585+ }
1586+ switch (var_atom -> index .type ) {
1587+ case INTEGRAL :
1588+ index = var_atom -> index .ivalue ;
1589+ break ;
1590+ case ENUMERATOR :
1591+ if (find_enum_value (btf , var_atom -> index .svalue , & index ) != 0 ) {
1592+ fprintf (stderr , "Could not find array index as enum value %s" ,
1593+ var_atom -> index .svalue );
1594+ return - EINVAL ;
1595+ }
1596+ break ;
1597+ case NONE :
1598+ fprintf (stderr , "Array index is expected for %s\n" , var_atom -> name );
1599+ return - EINVAL ;
1600+ }
1601+
1602+ if (index < 0 || index >= barr -> nelems ) {
1603+ fprintf (stderr , "Preset index %d is invalid or out of bounds [0, %d]\n" ,
1604+ index , barr -> nelems );
1605+ return - EINVAL ;
1606+ }
1607+ sinfo -> size = type -> size ;
1608+ sinfo -> type = tid ;
1609+ sinfo -> offset += index * type -> size ;
1610+ return 0 ;
1611+ }
1612+
15241613const int btf_find_member (const struct btf * btf ,
15251614 const struct btf_type * parent_type ,
15261615 __u32 parent_offset ,
15271616 struct var_preset_atom * var_atom ,
15281617 int * member_tid ,
15291618 __u32 * member_offset )
15301619{
1531- int i ;
1620+ int i , err ;
15321621
15331622 if (!btf_is_composite (parent_type ))
15341623 return - EINVAL ;
@@ -1547,16 +1636,27 @@ const int btf_find_member(const struct btf *btf,
15471636 if (member -> name_off ) {
15481637 const char * name = btf__name_by_offset (btf , member -> name_off );
15491638
1550- if (strcmp (var_atom -> name , name ) == 0 ) {
1551- if (btf_member_bitfield_size (parent_type , i ) != 0 ) {
1552- fprintf (stderr , "Bitfield presets are not supported %s\n" ,
1553- name );
1554- return - EINVAL ;
1555- }
1556- * member_offset = parent_offset + member -> offset ;
1557- * member_tid = tid ;
1558- return 0 ;
1639+ if (strcmp (var_atom -> name , name ) != 0 )
1640+ continue ;
1641+
1642+ if (btf_member_bitfield_size (parent_type , i ) != 0 ) {
1643+ fprintf (stderr , "Bitfield presets are not supported %s\n" ,
1644+ name );
1645+ return - EINVAL ;
15591646 }
1647+ * member_offset = parent_offset + member -> offset ;
1648+ * member_tid = tid ;
1649+ if (btf_is_array (member_type )) {
1650+ struct btf_var_secinfo sinfo = {.offset = 0 };
1651+
1652+ err = adjust_array_secinfo (btf , member_type ,
1653+ var_atom , & sinfo );
1654+ if (err )
1655+ return err ;
1656+ * member_tid = sinfo .type ;
1657+ * member_offset += sinfo .offset * 8 ;
1658+ }
1659+ return 0 ;
15601660 } else if (btf_is_composite (member_type )) {
15611661 int err ;
15621662
@@ -1567,7 +1667,7 @@ const int btf_find_member(const struct btf *btf,
15671667 }
15681668 }
15691669
1570- return - EINVAL ;
1670+ return - ESRCH ;
15711671}
15721672
15731673static int adjust_var_secinfo (struct btf * btf , const struct btf_type * t ,
@@ -1578,6 +1678,12 @@ static int adjust_var_secinfo(struct btf *btf, const struct btf_type *t,
15781678 __u32 member_offset = 0 ;
15791679
15801680 base_type = btf__type_by_id (btf , btf__resolve_type (btf , t -> type ));
1681+ if (btf_is_array (base_type )) {
1682+ err = adjust_array_secinfo (btf , base_type , & preset -> atoms [0 ], sinfo );
1683+ if (err )
1684+ return err ;
1685+ base_type = btf__type_by_id (btf , sinfo -> type );
1686+ }
15811687
15821688 for (i = 1 ; i < preset -> atom_count ; ++ i ) {
15831689 err = btf_find_member (btf , base_type , 0 , & preset -> atoms [i ],
@@ -1727,8 +1833,9 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
17271833 }
17281834 for (i = 0 ; i < npresets ; ++ i ) {
17291835 if (!presets [i ].applied ) {
1730- fprintf (stderr , "Global variable preset %s has not been applied\n" ,
1731- presets [i ].full_name );
1836+ fprintf (stderr , "Global variable preset %s has not been applied %s\n" ,
1837+ presets [i ].full_name , presets [i ].atoms [0 ].name );
1838+ err = - EINVAL ;
17321839 }
17331840 presets [i ].applied = false;
17341841 }
@@ -2916,8 +3023,11 @@ int main(int argc, char **argv)
29163023 free (env .deny_filters );
29173024 for (i = 0 ; i < env .npresets ; ++ i ) {
29183025 free (env .presets [i ].full_name );
2919- for (j = 0 ; j < env .presets [i ].atom_count ; ++ j )
3026+ for (j = 0 ; j < env .presets [i ].atom_count ; ++ j ) {
29203027 free (env .presets [i ].atoms [j ].name );
3028+ if (env .presets [i ].atoms [j ].index .type == ENUMERATOR )
3029+ free (env .presets [i ].atoms [j ].index .svalue );
3030+ }
29213031 free (env .presets [i ].atoms );
29223032 if (env .presets [i ].value .type == ENUMERATOR )
29233033 free (env .presets [i ].value .svalue );
0 commit comments