@@ -1486,7 +1486,84 @@ static bool is_preset_supported(const struct btf_type *t)
1486
1486
return btf_is_int (t ) || btf_is_enum (t ) || btf_is_enum64 (t );
1487
1487
}
1488
1488
1489
- static int set_global_var (struct bpf_object * obj , struct btf * btf , const struct btf_type * t ,
1489
+ const int btf_find_member (const struct btf * btf ,
1490
+ const struct btf_type * parent_type ,
1491
+ __u32 parent_offset ,
1492
+ const char * member_name ,
1493
+ int * member_tid ,
1494
+ __u32 * member_offset )
1495
+ {
1496
+ int i ;
1497
+
1498
+ if (!btf_is_composite (parent_type ))
1499
+ return - EINVAL ;
1500
+
1501
+ for (i = 0 ; i < btf_vlen (parent_type ); ++ i ) {
1502
+ const struct btf_member * member ;
1503
+ const struct btf_type * member_type ;
1504
+ int tid ;
1505
+
1506
+ member = btf_members (parent_type ) + i ;
1507
+ tid = btf__resolve_type (btf , member -> type );
1508
+ if (tid < 0 )
1509
+ return - EINVAL ;
1510
+
1511
+ member_type = btf__type_by_id (btf , tid );
1512
+ if (member -> name_off ) {
1513
+ const char * name = btf__name_by_offset (btf , member -> name_off );
1514
+
1515
+ if (strcmp (member_name , name ) == 0 ) {
1516
+ if (btf_member_bitfield_size (parent_type , i ) != 0 ) {
1517
+ fprintf (stderr , "Bitfield presets are not supported %s\n" ,
1518
+ name );
1519
+ return - EINVAL ;
1520
+ }
1521
+ * member_offset = parent_offset + member -> offset ;
1522
+ * member_tid = tid ;
1523
+ return 0 ;
1524
+ }
1525
+ } else if (btf_is_composite (member_type )) {
1526
+ int err ;
1527
+
1528
+ err = btf_find_member (btf , member_type , parent_offset + member -> offset ,
1529
+ member_name , member_tid , member_offset );
1530
+ if (!err )
1531
+ return 0 ;
1532
+ }
1533
+ }
1534
+
1535
+ return - EINVAL ;
1536
+ }
1537
+
1538
+ static int adjust_var_secinfo (struct btf * btf , const struct btf_type * t ,
1539
+ struct btf_var_secinfo * sinfo , const char * var )
1540
+ {
1541
+ char expr [256 ], * saveptr ;
1542
+ const struct btf_type * base_type , * member_type ;
1543
+ int err , member_tid ;
1544
+ char * name ;
1545
+ __u32 member_offset = 0 ;
1546
+
1547
+ base_type = btf__type_by_id (btf , btf__resolve_type (btf , t -> type ));
1548
+ snprintf (expr , sizeof (expr ), "%s" , var );
1549
+ strtok_r (expr , "." , & saveptr );
1550
+
1551
+ while ((name = strtok_r (NULL , "." , & saveptr ))) {
1552
+ err = btf_find_member (btf , base_type , 0 , name , & member_tid , & member_offset );
1553
+ if (err ) {
1554
+ fprintf (stderr , "Could not find member %s for variable %s\n" , name , var );
1555
+ return err ;
1556
+ }
1557
+ member_type = btf__type_by_id (btf , member_tid );
1558
+ sinfo -> offset += member_offset / 8 ;
1559
+ sinfo -> size = member_type -> size ;
1560
+ sinfo -> type = member_tid ;
1561
+ base_type = member_type ;
1562
+ }
1563
+ return 0 ;
1564
+ }
1565
+
1566
+ static int set_global_var (struct bpf_object * obj , struct btf * btf ,
1490
1567
struct bpf_map * map , struct btf_var_secinfo * sinfo ,
1491
1568
struct var_preset * preset )
1492
1569
{
@@ -1495,9 +1572,9 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf, const struct
1495
1572
long long value = preset -> ivalue ;
1496
1573
size_t size ;
1497
1574
1498
- base_type = btf__type_by_id (btf , btf__resolve_type (btf , t -> type ));
1575
+ base_type = btf__type_by_id (btf , btf__resolve_type (btf , sinfo -> type ));
1499
1576
if (!base_type ) {
1500
- fprintf (stderr , "Failed to resolve type %d\n" , t -> type );
1577
+ fprintf (stderr , "Failed to resolve type %d\n" , sinfo -> type );
1501
1578
return - EINVAL ;
1502
1579
}
1503
1580
if (!is_preset_supported (base_type )) {
@@ -1530,7 +1607,7 @@ static int set_global_var(struct bpf_object *obj, struct btf *btf, const struct
1530
1607
if (value >= max_val || value < - max_val ) {
1531
1608
fprintf (stderr ,
1532
1609
"Variable %s value %lld is out of range [%lld; %lld]\n" ,
1533
- btf__name_by_offset (btf , t -> name_off ), value ,
1610
+ btf__name_by_offset (btf , base_type -> name_off ), value ,
1534
1611
is_signed ? - max_val : 0 , max_val - 1 );
1535
1612
return - EINVAL ;
1536
1613
}
@@ -1583,28 +1660,38 @@ static int set_global_vars(struct bpf_object *obj, struct var_preset *presets, i
1583
1660
for (j = 0 ; j < n ; ++ j , ++ sinfo ) {
1584
1661
const struct btf_type * var_type = btf__type_by_id (btf , sinfo -> type );
1585
1662
const char * var_name ;
1663
+ int var_len ;
1586
1664
1587
1665
if (!btf_is_var (var_type ))
1588
1666
continue ;
1589
1667
1590
1668
var_name = btf__name_by_offset (btf , var_type -> name_off );
1669
+ var_len = strlen (var_name );
1591
1670
1592
1671
for (k = 0 ; k < npresets ; ++ k ) {
1593
- if (strcmp (var_name , presets [k ].name ) != 0 )
1672
+ struct btf_var_secinfo tmp_sinfo ;
1673
+
1674
+ if (strncmp (var_name , presets [k ].name , var_len ) != 0 ||
1675
+ (presets [k ].name [var_len ] != '\0' &&
1676
+ presets [k ].name [var_len ] != '.' ))
1594
1677
continue ;
1595
1678
1596
1679
if (presets [k ].applied ) {
1597
1680
fprintf (stderr , "Variable %s is set more than once" ,
1598
1681
var_name );
1599
1682
return - EINVAL ;
1600
1683
}
1684
+ tmp_sinfo = * sinfo ;
1685
+ err = adjust_var_secinfo (btf , var_type ,
1686
+ & tmp_sinfo , presets [k ].name );
1687
+ if (err )
1688
+ return err ;
1601
1689
1602
- err = set_global_var (obj , btf , var_type , map , sinfo , presets + k );
1690
+ err = set_global_var (obj , btf , map , & tmp_sinfo , presets + k );
1603
1691
if (err )
1604
1692
return err ;
1605
1693
1606
1694
presets [k ].applied = true;
1607
- break ;
1608
1695
}
1609
1696
}
1610
1697
}
0 commit comments