@@ -1457,40 +1457,83 @@ kernel_module_set_build_id(struct drgn_module *module,
14571457 _cleanup_free_ void * buf = NULL ;
14581458 size_t capacity = 0 ;
14591459
1460- // n = mod->notes_attrs->notes
1461- uint64_t n ;
14621460 err = drgn_object_member (& attrs , module_obj , "notes_attrs" );
1463- if (err )
1464- return err ;
1465- err = drgn_object_member_dereference (& tmp , & attrs , "notes" );
1466- if (err )
1467- return err ;
1468- err = drgn_object_read_unsigned (& tmp , & n );
14691461 if (err )
14701462 return err ;
14711463
1472- // attrs = mod->notes_attrs->attrs
1473- err = drgn_object_member_dereference (& attrs , & attrs , "attrs" );
1474- if (err )
1464+ bool group = true;
1465+ uint64_t n ;
1466+ err = drgn_object_member_dereference (& attrs , & attrs , "grp" );
1467+ if (!err ) {
1468+ // Since Linux kernel commit 4723f16de64e ("module: sysfs: Add
1469+ // notes attributes through attribute_group") (in v6.14), we
1470+ // have to iterate over struct attribute_group::bin_attrs, a
1471+ // null-terminated array of struct bin_attribute pointers.
1472+
1473+ // attr = mod->notes_attrs->grp.bin_attrs
1474+ err = drgn_object_member (& attrs , & attrs , "bin_attrs" );
1475+ if (err )
1476+ return err ;
1477+ } else if (drgn_error_catch (& err , DRGN_ERROR_LOOKUP )) {
1478+ // Before that, there was no struct attribute_group for notes,
1479+ // so we iterate over struct module_notes_attrs::attrs, an array
1480+ // of struct bin_attribute with a length given by struct
1481+ // module_notes_attrs::notes.
1482+ group = false;
1483+ // n = mod->notes_attrs->notes
1484+ err = drgn_object_member_dereference (& tmp , & attrs , "notes" );
1485+ if (err )
1486+ return err ;
1487+ err = drgn_object_read_unsigned (& tmp , & n );
1488+ if (err )
1489+ return err ;
1490+
1491+ // attrs = mod->notes_attrs->attrs
1492+ err = drgn_object_member_dereference (& attrs , & attrs , "attrs" );
1493+ if (err )
1494+ return err ;
1495+ } else {
14751496 return err ;
1497+ }
14761498
1477- for (uint64_t i = 0 ; i < n ; i ++ ) {
1499+ // If we're not using struct attribute_group, we know how many
1500+ // attributes there are.
1501+ for (uint64_t i = 0 ; group || i < n ; i ++ ) {
14781502 // attr = attrs[i]
14791503 err = drgn_object_subscript (& attr , & attrs , i );
14801504 if (err )
14811505 return err ;
14821506
1483- // address = attr.private
1484- err = drgn_object_member (& tmp , & attr , "private" );
1507+ if (group ) {
1508+ // If we're using struct attribute_group, we stop when
1509+ // we hit a NULL pointer.
1510+ err = drgn_object_read (& attr , & attr );
1511+ if (err )
1512+ return err ;
1513+ bool truthy ;
1514+ err = drgn_object_bool (& attr , & truthy );
1515+ if (err )
1516+ return err ;
1517+ if (!truthy )
1518+ break ;
1519+ } else {
1520+ // attr = &attrs[i]
1521+ err = drgn_object_address_of (& attr , & attr );
1522+ if (err )
1523+ return err ;
1524+ }
1525+
1526+ // address = attr->private
1527+ err = drgn_object_member_dereference (& tmp , & attr , "private" );
14851528 if (err )
14861529 return err ;
14871530 uint64_t address ;
14881531 err = drgn_object_read_unsigned (& tmp , & address );
14891532 if (err )
14901533 return err ;
14911534
1492- // size = attr. size
1493- err = drgn_object_member (& tmp , & attr , "size" );
1535+ // size = attr-> size
1536+ err = drgn_object_member_dereference (& tmp , & attr , "size" );
14941537 if (err )
14951538 return err ;
14961539 uint64_t size ;
@@ -1633,50 +1676,107 @@ kernel_module_set_section_addresses(struct drgn_module *module,
16331676 if (err )
16341677 return err ;
16351678
1636- // i = mod->sect_attrs->nsections
1679+ bool group = true;
1680+ uint64_t nsections ;
16371681 err = drgn_object_member_dereference (& tmp , & attrs , "nsections" );
1638- if (err )
1639- return err ;
1640- uint64_t i ;
1641- err = drgn_object_read_unsigned (& tmp , & i );
1642- if (err )
1643- return err ;
1682+ if (drgn_error_catch (& err , DRGN_ERROR_LOOKUP )) {
1683+ // Since Linux kernel commit d8959b947a8d ("module: sysfs: Drop
1684+ // member 'module_sect_attrs::nsections'") (in v6.14), we have
1685+ // to iterate over struct attribute_group::bin_attrs, a
1686+ // null-terminated array of struct bin_attribute pointers.
1687+
1688+ // attrs = mod->sect_attrs->grp.bin_attrs
1689+ err = drgn_object_member_dereference (& attrs , & attrs , "grp" );
1690+ if (err )
1691+ return err ;
1692+ err = drgn_object_member (& attrs , & attrs , "bin_attrs" );
1693+ if (err )
1694+ return err ;
1695+ } else if (!err ) {
1696+ // Before that, struct module_sect_attrs::grp still exists.
1697+ // However, since Linux kernel commit ed66f991bb19 ("module:
1698+ // Refactor section attr into bin attribute") (in v5.8), the
1699+ // sections are in struct attribute_group::bin_attrs, and before
1700+ // that, they're in struct attribute_group::attrs. Additionally,
1701+ // we'd then have to get the containing struct module_sect_attr
1702+ // to get the section address.
1703+ //
1704+ // Instead, it's easier to iterate over struct
1705+ // module_sect_attrs::attrs, an array of struct module_sect_attr
1706+ // with a length given by struct module_sect_attrs::nsections.
1707+ group = false;
1708+ // nsections = mod->sect_attrs->nsections
1709+ err = drgn_object_read_unsigned (& tmp , & nsections );
1710+ if (err )
1711+ return err ;
16441712
1645- // attrs = mod->sect_attrs->attrs
1646- err = drgn_object_member_dereference (& attrs , & attrs , "attrs" );
1647- if (err )
1713+ // attrs = mod->sect_attrs->attrs
1714+ err = drgn_object_member_dereference (& attrs , & attrs , "attrs" );
1715+ if (err )
1716+ return err ;
1717+ } else {
16481718 return err ;
1719+ }
16491720
1650- while (i -- > 0 ) {
1721+ // If we're not using struct attribute_group, we know how many
1722+ // attributes there are.
1723+ for (uint64_t i = 0 ; group || i < nsections ; i ++ ) {
16511724 // attr = attrs[i]
16521725 err = drgn_object_subscript (& attr , & attrs , i );
16531726 if (err )
16541727 return err ;
16551728
1656- // address = attr.address
1657- err = drgn_object_member (& tmp , & attr , "address" );
1658- if (err )
1659- return err ;
1729+ if (group ) {
1730+ // If we're using struct attribute_group, we stop when
1731+ // we hit a NULL pointer.
1732+ err = drgn_object_read (& attr , & attr );
1733+ if (err )
1734+ return err ;
1735+ bool truthy ;
1736+ err = drgn_object_bool (& attr , & truthy );
1737+ if (err )
1738+ return err ;
1739+ if (!truthy )
1740+ break ;
1741+ // Since Linux kernel commit 4b2c11e4aaf7 ("module:
1742+ // sysfs: Drop member 'module_sect_attr::address'") (in
1743+ // v6.14), the section address is in struct
1744+ // bin_attribute::private.
1745+ err = drgn_object_member_dereference (& tmp , & attr ,
1746+ "private" );
1747+ } else {
1748+ // Before that, the section address is in struct
1749+ // module_sect_attr::address.
1750+ err = drgn_object_member (& tmp , & attr , "address" );
1751+ if (err )
1752+ return err ;
1753+ }
16601754 uint64_t address ;
16611755 err = drgn_object_read_unsigned (& tmp , & address );
16621756 if (err )
16631757 return err ;
16641758
1665- // Since Linux kernel commit ed66f991bb19 ("module: Refactor
1666- // section attr into bin attribute") (in v5.8), the section name
1667- // is module_sect_attr.battr.attr.name. Before that, it is
1668- // simply module_sect_attr.name.
1669-
1670- // attr = attr.battr.attr
1671- err = drgn_object_member (& attr , & attr , "battr" );
1672- if (!err ) {
1673- err = drgn_object_member (& attr , & attr , "attr" );
1759+ if (group ) {
1760+ // attr = attr->attr
1761+ err = drgn_object_member_dereference (& attr , & attr ,
1762+ "attr" );
16741763 if (err )
16751764 return err ;
16761765 } else {
1677- if (err -> code != DRGN_ERROR_LOOKUP )
1766+ // Since Linux kernel commit ed66f991bb19 ("module:
1767+ // Refactor section attr into bin attribute") (in v5.8),
1768+ // the section name is module_sect_attr.battr.attr.name.
1769+ // Before that, it is simply module_sect_attr.name.
1770+
1771+ // attr = attr.battr.attr
1772+ err = drgn_object_member (& attr , & attr , "battr" );
1773+ if (!err ) {
1774+ err = drgn_object_member (& attr , & attr , "attr" );
1775+ if (err )
1776+ return err ;
1777+ } else if (!drgn_error_catch (& err , DRGN_ERROR_LOOKUP )) {
16781778 return err ;
1679- drgn_error_destroy ( err );
1779+ }
16801780 }
16811781 err = drgn_object_member (& tmp , & attr , "name" );
16821782 if (err )
0 commit comments