Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libbpf: Support layout section handling in BTF

Support reading in layout fixing endian issues on reading;
also support writing layout section to raw BTF object.
There is not yet an API to populate the layout with meaningful
information.

As part of this, we need to consider multiple valid BTF header
sizes; the original or the layout-extended headers.
So to support this, the "struct btf" representation is modified
to contain a "struct btf_header" and we copy the valid
portion from the raw data to it; this means we can always safely
check fields like btf->hdr.layout_len .

Note if parsed-in BTF has extra header information beyond
sizeof(struct btf_header) - if so we make that BTF ineligible
for modification by setting btf->has_hdr_extra .

Ensure that we handle endianness issues for BTF layout section,
though currently only field that needs this (flags) is unused.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20260326145444.2076244-3-alan.maguire@oracle.com

authored by

Alan Maguire and committed by
Andrii Nakryiko
087f3964 222edc84

+321 -154
+321 -154
tools/lib/bpf/btf.c
··· 40 40 41 41 /* 42 42 * When BTF is loaded from an ELF or raw memory it is stored 43 - * in a contiguous memory block. The hdr, type_data, and, strs_data 43 + * in a contiguous memory block. The type_data, layout and strs_data 44 44 * point inside that memory region to their respective parts of BTF 45 45 * representation: 46 46 * 47 - * +--------------------------------+ 48 - * | Header | Types | Strings | 49 - * +--------------------------------+ 50 - * ^ ^ ^ 51 - * | | | 52 - * hdr | | 53 - * types_data-+ | 54 - * strs_data------------+ 47 + * +----------------------------------------+---------------+ 48 + * | Header | Types | Optional layout | Strings | 49 + * +--------------------------------------------------------+ 50 + * ^ ^ ^ ^ 51 + * | | | | 52 + * raw_data | | | 53 + * types_data-+ | | 54 + * layout---------------+ | 55 + * strs_data--------------------------------+ 56 + * 57 + * A separate struct btf_header is embedded as btf->hdr, 58 + * and header information is copied into it. This allows us 59 + * to handle header data for various header formats; the original, 60 + * the extended header with layout info, etc. 55 61 * 56 62 * If BTF data is later modified, e.g., due to types added or 57 63 * removed, BTF deduplication performed, etc, this contiguous 58 - * representation is broken up into three independently allocated 59 - * memory regions to be able to modify them independently. 64 + * representation is broken up into four independent memory 65 + * regions. 66 + * 60 67 * raw_data is nulled out at that point, but can be later allocated 61 68 * and cached again if user calls btf__raw_data(), at which point 62 - * raw_data will contain a contiguous copy of header, types, and 63 - * strings: 69 + * raw_data will contain a contiguous copy of header, types, optional 70 + * layout and strings. layout optionally points to a 71 + * btf_layout array - this allows us to encode information about 72 + * the kinds known at encoding time. If layout is NULL no 73 + * layout information is encoded. 64 74 * 65 - * +----------+ +---------+ +-----------+ 66 - * | Header | | Types | | Strings | 67 - * +----------+ +---------+ +-----------+ 68 - * ^ ^ ^ 69 - * | | | 70 - * hdr | | 71 - * types_data----+ | 72 - * strset__data(strs_set)-----+ 75 + * +----------+ +---------+ +-----------+ +-----------+ 76 + * | Header | | Types | | Layout | | Strings | 77 + * +----------+ +---------+ +-----------+ +-----------+ 78 + * ^ ^ ^ ^ 79 + * | | | | 80 + * hdr | | | 81 + * types_data----+ | | 82 + * layout---------------------+ | 83 + * strset__data(strs_set)---------------------+ 73 84 * 74 - * +----------+---------+-----------+ 75 - * | Header | Types | Strings | 76 - * raw_data----->+----------+---------+-----------+ 85 + * +----------+---------+-------------------+-----------+ 86 + * | Header | Types | Optional Layout | Strings | 87 + * raw_data----->+----------+---------+-------------------+-----------+ 77 88 */ 78 - struct btf_header *hdr; 89 + struct btf_header hdr; 79 90 80 91 void *types_data; 81 92 size_t types_data_cap; /* used size stored in hdr->type_len */ ··· 135 124 136 125 /* whether raw_data is a (read-only) mmap */ 137 126 bool raw_data_is_mmap; 127 + 128 + /* is BTF modifiable? i.e. is it split into separate sections as described above? */ 129 + bool modifiable; 130 + /* does BTF have header information we do not support? If so, disallow 131 + * modification. 132 + */ 133 + bool has_hdr_extra; 134 + /* Points either at raw kind layout data in parsed BTF (if present), or 135 + * at an allocated kind layout array when BTF is modifiable. 136 + */ 137 + void *layout; 138 138 139 139 /* BTF object FD, if loaded into kernel */ 140 140 int fd; ··· 238 216 return 0; 239 217 } 240 218 241 - static void btf_bswap_hdr(struct btf_header *h) 219 + static void btf_bswap_hdr(struct btf_header *h, __u32 hdr_len) 242 220 { 243 221 h->magic = bswap_16(h->magic); 244 222 h->hdr_len = bswap_32(h->hdr_len); ··· 246 224 h->type_len = bswap_32(h->type_len); 247 225 h->str_off = bswap_32(h->str_off); 248 226 h->str_len = bswap_32(h->str_len); 227 + /* May be operating on raw data with hdr_len that does not include below fields */ 228 + if (hdr_len >= sizeof(struct btf_header)) { 229 + h->layout_off = bswap_32(h->layout_off); 230 + h->layout_len = bswap_32(h->layout_len); 231 + } 249 232 } 250 233 251 234 static int btf_parse_hdr(struct btf *btf) 252 235 { 253 - struct btf_header *hdr = btf->hdr; 254 - __u32 meta_left; 236 + struct btf_header *hdr = btf->raw_data; 237 + __u32 hdr_len, meta_left; 255 238 256 - if (btf->raw_size < sizeof(struct btf_header)) { 239 + if (btf->raw_size < offsetofend(struct btf_header, str_len)) { 257 240 pr_debug("BTF header not found\n"); 258 241 return -EINVAL; 259 242 } 260 243 244 + hdr_len = hdr->hdr_len; 245 + 261 246 if (hdr->magic == bswap_16(BTF_MAGIC)) { 262 247 btf->swapped_endian = true; 263 - if (bswap_32(hdr->hdr_len) != sizeof(struct btf_header)) { 248 + hdr_len = bswap_32(hdr->hdr_len); 249 + if (hdr_len < offsetofend(struct btf_header, str_len)) { 264 250 pr_warn("Can't load BTF with non-native endianness due to unsupported header length %u\n", 265 - bswap_32(hdr->hdr_len)); 251 + hdr_len); 266 252 return -ENOTSUP; 267 253 } 268 - btf_bswap_hdr(hdr); 269 254 } else if (hdr->magic != BTF_MAGIC) { 270 255 pr_debug("Invalid BTF magic: %x\n", hdr->magic); 271 256 return -EINVAL; 272 257 } 273 258 274 - if (btf->raw_size < hdr->hdr_len) { 259 + if (btf->raw_size < hdr_len) { 275 260 pr_debug("BTF header len %u larger than data size %u\n", 276 - hdr->hdr_len, btf->raw_size); 261 + hdr_len, btf->raw_size); 277 262 return -EINVAL; 278 263 } 279 264 280 - meta_left = btf->raw_size - hdr->hdr_len; 281 - if (meta_left < (long long)hdr->str_off + hdr->str_len) { 265 + if (btf->swapped_endian) 266 + btf_bswap_hdr(hdr, hdr_len); 267 + 268 + memcpy(&btf->hdr, hdr, min((size_t)hdr_len, sizeof(struct btf_header))); 269 + 270 + /* If unknown header data is found, modification is prohibited in 271 + * btf_ensure_modifiable(). 272 + */ 273 + if (hdr_len > sizeof(struct btf_header)) { 274 + __u8 *h = (__u8 *)hdr; 275 + __u32 i; 276 + 277 + for (i = sizeof(struct btf_header); i < hdr_len; i++) { 278 + if (!h[i]) 279 + continue; 280 + btf->has_hdr_extra = true; 281 + pr_debug("Unknown BTF header data at offset %u; modification is disallowed\n", 282 + i); 283 + break; 284 + } 285 + } 286 + 287 + meta_left = btf->raw_size - hdr_len; 288 + if (meta_left < (long long)btf->hdr.str_off + btf->hdr.str_len) { 282 289 pr_debug("Invalid BTF total size: %u\n", btf->raw_size); 283 290 return -EINVAL; 284 291 } 285 292 286 - if ((long long)hdr->type_off + hdr->type_len > hdr->str_off) { 293 + if ((long long)btf->hdr.type_off + btf->hdr.type_len > btf->hdr.str_off) { 287 294 pr_debug("Invalid BTF data sections layout: type data at %u + %u, strings data at %u + %u\n", 288 - hdr->type_off, hdr->type_len, hdr->str_off, hdr->str_len); 295 + btf->hdr.type_off, btf->hdr.type_len, btf->hdr.str_off, 296 + btf->hdr.str_len); 289 297 return -EINVAL; 290 298 } 291 299 292 - if (hdr->type_off % 4) { 300 + if (btf->hdr.type_off % 4) { 293 301 pr_debug("BTF type section is not aligned to 4 bytes\n"); 294 302 return -EINVAL; 295 303 } 296 304 305 + if (btf->hdr.layout_len == 0) 306 + return 0; 307 + 308 + /* optional layout section sits between types and strings */ 309 + if (btf->hdr.layout_off % 4) { 310 + pr_debug("BTF layout section is not aligned to 4 bytes\n"); 311 + return -EINVAL; 312 + } 313 + if (btf->hdr.layout_off < (long long)btf->hdr.type_off + btf->hdr.type_len) { 314 + pr_debug("Invalid BTF data sections layout: type data at %u + %u, layout data at %u + %u\n", 315 + btf->hdr.type_off, btf->hdr.type_len, 316 + btf->hdr.layout_off, btf->hdr.layout_len); 317 + return -EINVAL; 318 + } 319 + if ((long long)btf->hdr.layout_off + btf->hdr.layout_len > btf->hdr.str_off || 320 + btf->hdr.layout_off > btf->hdr.str_off) { 321 + pr_debug("Invalid BTF data sections layout: layout data at %u + %u, strings data at %u\n", 322 + btf->hdr.layout_off, btf->hdr.layout_len, btf->hdr.str_off); 323 + return -EINVAL; 324 + } 297 325 return 0; 298 326 } 299 327 300 328 static int btf_parse_str_sec(struct btf *btf) 301 329 { 302 - const struct btf_header *hdr = btf->hdr; 303 330 const char *start = btf->strs_data; 304 - const char *end = start + btf->hdr->str_len; 331 + const char *end = start + btf->hdr.str_len; 305 332 306 - if (btf->base_btf && hdr->str_len == 0) 333 + if (btf->base_btf && btf->hdr.str_len == 0) 307 334 return 0; 308 - if (!hdr->str_len || hdr->str_len - 1 > BTF_MAX_STR_OFFSET || end[-1]) { 335 + if (!btf->hdr.str_len || btf->hdr.str_len - 1 > BTF_MAX_STR_OFFSET || end[-1]) { 309 336 pr_debug("Invalid BTF string section\n"); 310 337 return -EINVAL; 311 338 } ··· 362 291 pr_debug("Malformed BTF string section, did you forget to provide base BTF?\n"); 363 292 return -EINVAL; 364 293 } 294 + return 0; 295 + } 296 + 297 + static int btf_parse_layout_sec(struct btf *btf) 298 + { 299 + if (!btf->hdr.layout_len) 300 + return 0; 301 + 302 + if (btf->hdr.layout_len % sizeof(struct btf_layout) != 0) { 303 + pr_debug("Invalid BTF kind layout section\n"); 304 + return -EINVAL; 305 + } 306 + btf->layout = btf->raw_data + btf->hdr.hdr_len + btf->hdr.layout_off; 307 + 308 + if (btf->swapped_endian) { 309 + struct btf_layout *l, *end = btf->layout + btf->hdr.layout_len; 310 + 311 + for (l = btf->layout; l < end; l++) 312 + l->flags = bswap_16(l->flags); 313 + } 314 + 365 315 return 0; 366 316 } 367 317 ··· 513 421 514 422 static int btf_parse_type_sec(struct btf *btf) 515 423 { 516 - struct btf_header *hdr = btf->hdr; 517 424 void *next_type = btf->types_data; 518 - void *end_type = next_type + hdr->type_len; 425 + void *end_type = next_type + btf->hdr.type_len; 519 426 int err, type_size; 520 427 521 428 while (next_type + sizeof(struct btf_type) <= end_type) { ··· 1103 1012 1104 1013 static bool btf_is_modifiable(const struct btf *btf) 1105 1014 { 1106 - return (void *)btf->hdr != btf->raw_data; 1015 + /* BTF is modifiable if split into multiple sections */ 1016 + return btf->modifiable; 1107 1017 } 1108 1018 1109 1019 static void btf_free_raw_data(struct btf *btf) ··· 1128 1036 1129 1037 if (btf_is_modifiable(btf)) { 1130 1038 /* if BTF was modified after loading, it will have a split 1131 - * in-memory representation for header, types, and strings 1039 + * in-memory representation for types, strings and layout 1132 1040 * sections, so we need to free all of them individually. It 1133 1041 * might still have a cached contiguous raw data present, 1134 1042 * which will be unconditionally freed below. 1135 1043 */ 1136 - free(btf->hdr); 1137 1044 free(btf->types_data); 1138 1045 strset__free(btf->strs_set); 1046 + free(btf->layout); 1139 1047 } 1140 1048 btf_free_raw_data(btf); 1141 1049 free(btf->raw_data_swapped); ··· 1147 1055 1148 1056 static struct btf *btf_new_empty(struct btf *base_btf) 1149 1057 { 1058 + struct btf_header *hdr; 1150 1059 struct btf *btf; 1151 1060 1152 1061 btf = calloc(1, sizeof(*btf)); ··· 1165 1072 if (base_btf) { 1166 1073 btf->base_btf = base_btf; 1167 1074 btf->start_id = btf__type_cnt(base_btf); 1168 - btf->start_str_off = base_btf->hdr->str_len + base_btf->start_str_off; 1075 + btf->start_str_off = base_btf->hdr.str_len + base_btf->start_str_off; 1169 1076 btf->swapped_endian = base_btf->swapped_endian; 1170 1077 } 1171 1078 ··· 1177 1084 return ERR_PTR(-ENOMEM); 1178 1085 } 1179 1086 1180 - btf->hdr = btf->raw_data; 1181 - btf->hdr->hdr_len = sizeof(struct btf_header); 1182 - btf->hdr->magic = BTF_MAGIC; 1183 - btf->hdr->version = BTF_VERSION; 1087 + hdr = btf->raw_data; 1088 + hdr->hdr_len = sizeof(struct btf_header); 1089 + hdr->magic = BTF_MAGIC; 1090 + hdr->version = BTF_VERSION; 1184 1091 1185 - btf->types_data = btf->raw_data + btf->hdr->hdr_len; 1186 - btf->strs_data = btf->raw_data + btf->hdr->hdr_len; 1187 - btf->hdr->str_len = base_btf ? 0 : 1; /* empty string at offset 0 */ 1092 + btf->types_data = btf->raw_data + hdr->hdr_len; 1093 + btf->strs_data = btf->raw_data + hdr->hdr_len; 1094 + hdr->str_len = base_btf ? 0 : 1; /* empty string at offset 0 */ 1095 + memcpy(&btf->hdr, hdr, sizeof(*hdr)); 1188 1096 1189 1097 return btf; 1190 1098 } ··· 1218 1124 if (base_btf) { 1219 1125 btf->base_btf = base_btf; 1220 1126 btf->start_id = btf__type_cnt(base_btf); 1221 - btf->start_str_off = base_btf->hdr->str_len + base_btf->start_str_off; 1127 + btf->start_str_off = base_btf->hdr.str_len + base_btf->start_str_off; 1222 1128 } 1223 1129 1224 1130 if (is_mmap) { ··· 1235 1141 1236 1142 btf->raw_size = size; 1237 1143 1238 - btf->hdr = btf->raw_data; 1239 1144 err = btf_parse_hdr(btf); 1240 1145 if (err) 1241 1146 goto done; 1242 1147 1243 - btf->strs_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->str_off; 1244 - btf->types_data = btf->raw_data + btf->hdr->hdr_len + btf->hdr->type_off; 1148 + btf->strs_data = btf->raw_data + btf->hdr.hdr_len + btf->hdr.str_off; 1149 + btf->types_data = btf->raw_data + btf->hdr.hdr_len + btf->hdr.type_off; 1245 1150 1246 1151 err = btf_parse_str_sec(btf); 1152 + err = err ?: btf_parse_layout_sec(btf); 1247 1153 err = err ?: btf_parse_type_sec(btf); 1248 1154 err = err ?: btf_sanity_check(btf); 1249 1155 if (err) ··· 1695 1601 1696 1602 static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian) 1697 1603 { 1698 - struct btf_header *hdr = btf->hdr; 1604 + const struct btf_header *hdr = &btf->hdr; 1699 1605 struct btf_type *t; 1700 1606 void *data, *p; 1701 1607 __u32 data_sz; ··· 1708 1614 } 1709 1615 1710 1616 data_sz = hdr->hdr_len + hdr->type_len + hdr->str_len; 1617 + if (btf->layout) 1618 + data_sz += hdr->layout_len; 1619 + 1711 1620 data = calloc(1, data_sz); 1712 1621 if (!data) 1713 1622 return NULL; 1714 1623 p = data; 1715 1624 1716 - memcpy(p, hdr, hdr->hdr_len); 1625 + memcpy(p, hdr, min((__u32)sizeof(struct btf_header), hdr->hdr_len)); 1717 1626 if (swap_endian) 1718 - btf_bswap_hdr(p); 1627 + btf_bswap_hdr(p, hdr->hdr_len); 1719 1628 p += hdr->hdr_len; 1720 1629 1721 1630 memcpy(p, btf->types_data, hdr->type_len); ··· 1736 1639 } 1737 1640 p += hdr->type_len; 1738 1641 1642 + if (btf->layout) { 1643 + memcpy(p, btf->layout, hdr->layout_len); 1644 + if (swap_endian) { 1645 + struct btf_layout *l, *end = p + hdr->layout_len; 1646 + 1647 + for (l = p; l < end ; l++) 1648 + l->flags = bswap_16(l->flags); 1649 + } 1650 + p += hdr->layout_len; 1651 + } 1652 + 1739 1653 memcpy(p, btf_strs_data(btf), hdr->str_len); 1740 - p += hdr->str_len; 1741 1654 1742 1655 *size = data_sz; 1743 1656 return data; ··· 1782 1675 { 1783 1676 if (offset < btf->start_str_off) 1784 1677 return btf__str_by_offset(btf->base_btf, offset); 1785 - else if (offset - btf->start_str_off < btf->hdr->str_len) 1678 + else if (offset - btf->start_str_off < btf->hdr.str_len) 1786 1679 return btf_strs_data(btf) + (offset - btf->start_str_off); 1787 1680 else 1788 1681 return errno = EINVAL, NULL; ··· 1890 1783 } 1891 1784 1892 1785 /* Ensure BTF is ready to be modified (by splitting into a three memory 1893 - * regions for header, types, and strings). Also invalidate cached 1786 + * regions for types, strings and layout. Also invalidate cached 1894 1787 * raw_data, if any. 1895 1788 */ 1896 1789 static int btf_ensure_modifiable(struct btf *btf) 1897 1790 { 1898 - void *hdr, *types; 1791 + void *types, *layout = NULL; 1899 1792 struct strset *set = NULL; 1900 1793 int err = -ENOMEM; 1901 1794 ··· 1905 1798 return 0; 1906 1799 } 1907 1800 1908 - /* split raw data into three memory regions */ 1909 - hdr = malloc(btf->hdr->hdr_len); 1910 - types = malloc(btf->hdr->type_len); 1911 - if (!hdr || !types) 1912 - goto err_out; 1801 + if (btf->has_hdr_extra) { 1802 + /* Additional BTF header data was found; not safe to modify. */ 1803 + return -EOPNOTSUPP; 1804 + } 1913 1805 1914 - memcpy(hdr, btf->hdr, btf->hdr->hdr_len); 1915 - memcpy(types, btf->types_data, btf->hdr->type_len); 1806 + /* split raw data into memory regions; btf->hdr is done already. */ 1807 + types = malloc(btf->hdr.type_len); 1808 + if (!types) 1809 + goto err_out; 1810 + memcpy(types, btf->types_data, btf->hdr.type_len); 1811 + 1812 + if (btf->hdr.layout_len) { 1813 + layout = malloc(btf->hdr.layout_len); 1814 + if (!layout) 1815 + goto err_out; 1816 + memcpy(layout, btf->raw_data + btf->hdr.hdr_len + btf->hdr.layout_off, 1817 + btf->hdr.layout_len); 1818 + } 1916 1819 1917 1820 /* build lookup index for all strings */ 1918 - set = strset__new(BTF_MAX_STR_OFFSET, btf->strs_data, btf->hdr->str_len); 1821 + set = strset__new(BTF_MAX_STR_OFFSET, btf->strs_data, btf->hdr.str_len); 1919 1822 if (IS_ERR(set)) { 1920 1823 err = PTR_ERR(set); 1921 1824 goto err_out; 1922 1825 } 1923 1826 1924 1827 /* only when everything was successful, update internal state */ 1925 - btf->hdr = hdr; 1926 1828 btf->types_data = types; 1927 - btf->types_data_cap = btf->hdr->type_len; 1829 + btf->types_data_cap = btf->hdr.type_len; 1928 1830 btf->strs_data = NULL; 1929 1831 btf->strs_set = set; 1832 + if (layout) 1833 + btf->layout = layout; 1930 1834 /* if BTF was created from scratch, all strings are guaranteed to be 1931 1835 * unique and deduplicated 1932 1836 */ 1933 - if (btf->hdr->str_len == 0) 1837 + if (btf->hdr.str_len == 0) 1934 1838 btf->strs_deduped = true; 1935 - if (!btf->base_btf && btf->hdr->str_len == 1) 1839 + if (!btf->base_btf && btf->hdr.str_len == 1) 1936 1840 btf->strs_deduped = true; 1937 1841 1938 1842 /* invalidate raw_data representation */ 1939 1843 btf_invalidate_raw_data(btf); 1940 1844 1845 + btf->modifiable = true; 1846 + 1941 1847 return 0; 1942 1848 1943 1849 err_out: 1944 1850 strset__free(set); 1945 - free(hdr); 1946 1851 free(types); 1852 + free(layout); 1947 1853 return err; 1948 1854 } 1949 1855 ··· 1969 1849 int btf__find_str(struct btf *btf, const char *s) 1970 1850 { 1971 1851 int off; 1852 + int err; 1972 1853 1973 1854 if (btf->base_btf) { 1974 1855 off = btf__find_str(btf->base_btf, s); ··· 1978 1857 } 1979 1858 1980 1859 /* BTF needs to be in a modifiable state to build string lookup index */ 1981 - if (btf_ensure_modifiable(btf)) 1982 - return libbpf_err(-ENOMEM); 1860 + err = btf_ensure_modifiable(btf); 1861 + if (err) 1862 + return libbpf_err(err); 1983 1863 1984 1864 off = strset__find_str(btf->strs_set, s); 1985 1865 if (off < 0) ··· 1997 1875 int btf__add_str(struct btf *btf, const char *s) 1998 1876 { 1999 1877 int off; 1878 + int err; 2000 1879 2001 1880 if (btf->base_btf) { 2002 1881 off = btf__find_str(btf->base_btf, s); ··· 2005 1882 return off; 2006 1883 } 2007 1884 2008 - if (btf_ensure_modifiable(btf)) 2009 - return libbpf_err(-ENOMEM); 1885 + err = btf_ensure_modifiable(btf); 1886 + if (err) 1887 + return libbpf_err(err); 2010 1888 2011 1889 off = strset__add_str(btf->strs_set, s); 2012 1890 if (off < 0) 2013 1891 return libbpf_err(off); 2014 1892 2015 - btf->hdr->str_len = strset__data_size(btf->strs_set); 1893 + btf->hdr.str_len = strset__data_size(btf->strs_set); 2016 1894 2017 1895 return btf->start_str_off + off; 2018 1896 } ··· 2021 1897 static void *btf_add_type_mem(struct btf *btf, size_t add_sz) 2022 1898 { 2023 1899 return libbpf_add_mem(&btf->types_data, &btf->types_data_cap, 1, 2024 - btf->hdr->type_len, UINT_MAX, add_sz); 1900 + btf->hdr.type_len, UINT_MAX, add_sz); 2025 1901 } 2026 1902 2027 1903 static void btf_type_inc_vlen(struct btf_type *t) ··· 2029 1905 t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t)); 2030 1906 } 2031 1907 1908 + static void btf_hdr_update_type_len(struct btf *btf, int new_len) 1909 + { 1910 + btf->hdr.type_len = new_len; 1911 + if (btf->layout) { 1912 + btf->hdr.layout_off = btf->hdr.type_off + new_len; 1913 + btf->hdr.str_off = btf->hdr.layout_off + btf->hdr.layout_len; 1914 + } else { 1915 + btf->hdr.str_off = btf->hdr.type_off + new_len; 1916 + } 1917 + } 1918 + 1919 + static void btf_hdr_update_str_len(struct btf *btf, int new_len) 1920 + { 1921 + btf->hdr.str_len = new_len; 1922 + } 1923 + 2032 1924 static int btf_commit_type(struct btf *btf, int data_sz) 2033 1925 { 2034 1926 int err; 2035 1927 2036 - err = btf_add_type_idx_entry(btf, btf->hdr->type_len); 1928 + err = btf_add_type_idx_entry(btf, btf->hdr.type_len); 2037 1929 if (err) 2038 1930 return libbpf_err(err); 2039 1931 2040 - btf->hdr->type_len += data_sz; 2041 - btf->hdr->str_off += data_sz; 1932 + btf_hdr_update_type_len(btf, btf->hdr.type_len + data_sz); 2042 1933 btf->nr_types++; 2043 1934 return btf->start_id + btf->nr_types - 1; 2044 1935 } ··· 2107 1968 return libbpf_err(sz); 2108 1969 2109 1970 /* deconstruct BTF, if necessary, and invalidate raw_data */ 2110 - if (btf_ensure_modifiable(p->dst)) 2111 - return libbpf_err(-ENOMEM); 1971 + err = btf_ensure_modifiable(p->dst); 1972 + if (err) 1973 + return libbpf_err(err); 2112 1974 2113 1975 t = btf_add_type_mem(p->dst, sz); 2114 1976 if (!t) ··· 2158 2018 src_start_id = src_btf->base_btf ? btf__type_cnt(src_btf->base_btf) : 1; 2159 2019 2160 2020 /* deconstruct BTF, if necessary, and invalidate raw_data */ 2161 - if (btf_ensure_modifiable(btf)) 2162 - return libbpf_err(-ENOMEM); 2021 + err = btf_ensure_modifiable(btf); 2022 + if (err) 2023 + return libbpf_err(err); 2163 2024 2164 2025 /* remember original strings section size if we have to roll back 2165 2026 * partial strings section changes 2166 2027 */ 2167 - old_strs_len = btf->hdr->str_len; 2028 + old_strs_len = btf->hdr.str_len; 2168 2029 2169 - data_sz = src_btf->hdr->type_len; 2030 + data_sz = src_btf->hdr.type_len; 2170 2031 cnt = src_btf->nr_types; 2171 2032 2172 2033 /* pre-allocate enough memory for new types */ ··· 2244 2103 * update type count and various internal offsets and sizes to 2245 2104 * "commit" the changes and made them visible to the outside world. 2246 2105 */ 2247 - btf->hdr->type_len += data_sz; 2248 - btf->hdr->str_off += data_sz; 2106 + btf_hdr_update_type_len(btf, btf->hdr.type_len + data_sz); 2249 2107 btf->nr_types += cnt; 2250 2108 2251 2109 hashmap__free(p.str_off_map); ··· 2255 2115 /* zero out preallocated memory as if it was just allocated with 2256 2116 * libbpf_add_mem() 2257 2117 */ 2258 - memset(btf->types_data + btf->hdr->type_len, 0, data_sz); 2259 - memset(btf->strs_data + old_strs_len, 0, btf->hdr->str_len - old_strs_len); 2118 + memset(btf->types_data + btf->hdr.type_len, 0, data_sz); 2119 + if (btf->strs_data) 2120 + memset(btf->strs_data + old_strs_len, 0, btf->hdr.str_len - old_strs_len); 2260 2121 2261 2122 /* and now restore original strings section size; types data size 2262 2123 * wasn't modified, so doesn't need restoring, see big comment above 2263 2124 */ 2264 - btf->hdr->str_len = old_strs_len; 2125 + btf_hdr_update_str_len(btf, old_strs_len); 2265 2126 2266 2127 hashmap__free(p.str_off_map); 2267 2128 ··· 2282 2141 { 2283 2142 struct btf_type *t; 2284 2143 int sz, name_off; 2144 + int err; 2285 2145 2286 2146 /* non-empty name */ 2287 2147 if (str_is_empty(name)) ··· 2294 2152 return libbpf_err(-EINVAL); 2295 2153 2296 2154 /* deconstruct BTF, if necessary, and invalidate raw_data */ 2297 - if (btf_ensure_modifiable(btf)) 2298 - return libbpf_err(-ENOMEM); 2155 + err = btf_ensure_modifiable(btf); 2156 + if (err) 2157 + return libbpf_err(err); 2299 2158 2300 2159 sz = sizeof(struct btf_type) + sizeof(int); 2301 2160 t = btf_add_type_mem(btf, sz); ··· 2332 2189 { 2333 2190 struct btf_type *t; 2334 2191 int sz, name_off; 2192 + int err; 2335 2193 2336 2194 /* non-empty name */ 2337 2195 if (str_is_empty(name)) ··· 2343 2199 byte_sz != 16) 2344 2200 return libbpf_err(-EINVAL); 2345 2201 2346 - if (btf_ensure_modifiable(btf)) 2347 - return libbpf_err(-ENOMEM); 2202 + err = btf_ensure_modifiable(btf); 2203 + if (err) 2204 + return libbpf_err(err); 2348 2205 2349 2206 sz = sizeof(struct btf_type); 2350 2207 t = btf_add_type_mem(btf, sz); ··· 2379 2234 { 2380 2235 struct btf_type *t; 2381 2236 int sz, name_off = 0; 2237 + int err; 2382 2238 2383 2239 if (validate_type_id(ref_type_id)) 2384 2240 return libbpf_err(-EINVAL); 2385 2241 2386 - if (btf_ensure_modifiable(btf)) 2387 - return libbpf_err(-ENOMEM); 2242 + err = btf_ensure_modifiable(btf); 2243 + if (err) 2244 + return libbpf_err(err); 2388 2245 2389 2246 sz = sizeof(struct btf_type); 2390 2247 t = btf_add_type_mem(btf, sz); ··· 2431 2284 { 2432 2285 struct btf_type *t; 2433 2286 struct btf_array *a; 2287 + int err; 2434 2288 int sz; 2435 2289 2436 2290 if (validate_type_id(index_type_id) || validate_type_id(elem_type_id)) 2437 2291 return libbpf_err(-EINVAL); 2438 2292 2439 - if (btf_ensure_modifiable(btf)) 2440 - return libbpf_err(-ENOMEM); 2293 + err = btf_ensure_modifiable(btf); 2294 + if (err) 2295 + return libbpf_err(err); 2441 2296 2442 2297 sz = sizeof(struct btf_type) + sizeof(struct btf_array); 2443 2298 t = btf_add_type_mem(btf, sz); ··· 2463 2314 { 2464 2315 struct btf_type *t; 2465 2316 int sz, name_off = 0; 2317 + int err; 2466 2318 2467 - if (btf_ensure_modifiable(btf)) 2468 - return libbpf_err(-ENOMEM); 2319 + err = btf_ensure_modifiable(btf); 2320 + if (err) 2321 + return libbpf_err(err); 2469 2322 2470 2323 sz = sizeof(struct btf_type); 2471 2324 t = btf_add_type_mem(btf, sz); ··· 2547 2396 struct btf_member *m; 2548 2397 bool is_bitfield; 2549 2398 int sz, name_off = 0; 2399 + int err; 2550 2400 2551 2401 /* last type should be union/struct */ 2552 2402 if (btf->nr_types == 0) ··· 2568 2416 return libbpf_err(-EINVAL); 2569 2417 2570 2418 /* decompose and invalidate raw data */ 2571 - if (btf_ensure_modifiable(btf)) 2572 - return libbpf_err(-ENOMEM); 2419 + err = btf_ensure_modifiable(btf); 2420 + if (err) 2421 + return libbpf_err(err); 2573 2422 2574 2423 sz = sizeof(struct btf_member); 2575 2424 m = btf_add_type_mem(btf, sz); ··· 2592 2439 /* update parent type's vlen and kflag */ 2593 2440 t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, is_bitfield || btf_kflag(t)); 2594 2441 2595 - btf->hdr->type_len += sz; 2596 - btf->hdr->str_off += sz; 2442 + btf_hdr_update_type_len(btf, btf->hdr.type_len + sz); 2597 2443 return 0; 2598 2444 } 2599 2445 ··· 2601 2449 { 2602 2450 struct btf_type *t; 2603 2451 int sz, name_off = 0; 2452 + int err; 2604 2453 2605 2454 /* byte_sz must be power of 2 */ 2606 2455 if (!byte_sz || (byte_sz & (byte_sz - 1)) || byte_sz > 8) 2607 2456 return libbpf_err(-EINVAL); 2608 2457 2609 - if (btf_ensure_modifiable(btf)) 2610 - return libbpf_err(-ENOMEM); 2458 + err = btf_ensure_modifiable(btf); 2459 + if (err) 2460 + return libbpf_err(err); 2611 2461 2612 2462 sz = sizeof(struct btf_type); 2613 2463 t = btf_add_type_mem(btf, sz); ··· 2665 2511 struct btf_type *t; 2666 2512 struct btf_enum *v; 2667 2513 int sz, name_off; 2514 + int err; 2668 2515 2669 2516 /* last type should be BTF_KIND_ENUM */ 2670 2517 if (btf->nr_types == 0) ··· 2681 2526 return libbpf_err(-E2BIG); 2682 2527 2683 2528 /* decompose and invalidate raw data */ 2684 - if (btf_ensure_modifiable(btf)) 2685 - return libbpf_err(-ENOMEM); 2529 + err = btf_ensure_modifiable(btf); 2530 + if (err) 2531 + return libbpf_err(err); 2686 2532 2687 2533 sz = sizeof(struct btf_enum); 2688 2534 v = btf_add_type_mem(btf, sz); ··· 2705 2549 if (value < 0) 2706 2550 t->info = btf_type_info(btf_kind(t), btf_vlen(t), true); 2707 2551 2708 - btf->hdr->type_len += sz; 2709 - btf->hdr->str_off += sz; 2552 + btf_hdr_update_type_len(btf, btf->hdr.type_len + sz); 2710 2553 return 0; 2711 2554 } 2712 2555 ··· 2743 2588 struct btf_enum64 *v; 2744 2589 struct btf_type *t; 2745 2590 int sz, name_off; 2591 + int err; 2746 2592 2747 2593 /* last type should be BTF_KIND_ENUM64 */ 2748 2594 if (btf->nr_types == 0) ··· 2757 2601 return libbpf_err(-EINVAL); 2758 2602 2759 2603 /* decompose and invalidate raw data */ 2760 - if (btf_ensure_modifiable(btf)) 2761 - return libbpf_err(-ENOMEM); 2604 + err = btf_ensure_modifiable(btf); 2605 + if (err) 2606 + return libbpf_err(err); 2762 2607 2763 2608 sz = sizeof(struct btf_enum64); 2764 2609 v = btf_add_type_mem(btf, sz); ··· 2778 2621 t = btf_last_type(btf); 2779 2622 btf_type_inc_vlen(t); 2780 2623 2781 - btf->hdr->type_len += sz; 2782 - btf->hdr->str_off += sz; 2624 + btf_hdr_update_type_len(btf, btf->hdr.type_len + sz); 2783 2625 return 0; 2784 2626 } 2785 2627 ··· 2947 2791 int btf__add_func_proto(struct btf *btf, int ret_type_id) 2948 2792 { 2949 2793 struct btf_type *t; 2794 + int err; 2950 2795 int sz; 2951 2796 2952 2797 if (validate_type_id(ret_type_id)) 2953 2798 return libbpf_err(-EINVAL); 2954 2799 2955 - if (btf_ensure_modifiable(btf)) 2956 - return libbpf_err(-ENOMEM); 2800 + err = btf_ensure_modifiable(btf); 2801 + if (err) 2802 + return libbpf_err(err); 2957 2803 2958 2804 sz = sizeof(struct btf_type); 2959 2805 t = btf_add_type_mem(btf, sz); ··· 2985 2827 struct btf_type *t; 2986 2828 struct btf_param *p; 2987 2829 int sz, name_off = 0; 2830 + int err; 2988 2831 2989 2832 if (validate_type_id(type_id)) 2990 2833 return libbpf_err(-EINVAL); ··· 2998 2839 return libbpf_err(-EINVAL); 2999 2840 3000 2841 /* decompose and invalidate raw data */ 3001 - if (btf_ensure_modifiable(btf)) 3002 - return libbpf_err(-ENOMEM); 2842 + err = btf_ensure_modifiable(btf); 2843 + if (err) 2844 + return libbpf_err(err); 3003 2845 3004 2846 sz = sizeof(struct btf_param); 3005 2847 p = btf_add_type_mem(btf, sz); ··· 3020 2860 t = btf_last_type(btf); 3021 2861 btf_type_inc_vlen(t); 3022 2862 3023 - btf->hdr->type_len += sz; 3024 - btf->hdr->str_off += sz; 2863 + btf_hdr_update_type_len(btf, btf->hdr.type_len + sz); 3025 2864 return 0; 3026 2865 } 3027 2866 ··· 3039 2880 struct btf_type *t; 3040 2881 struct btf_var *v; 3041 2882 int sz, name_off; 2883 + int err; 3042 2884 3043 2885 /* non-empty name */ 3044 2886 if (str_is_empty(name)) ··· 3051 2891 return libbpf_err(-EINVAL); 3052 2892 3053 2893 /* deconstruct BTF, if necessary, and invalidate raw_data */ 3054 - if (btf_ensure_modifiable(btf)) 3055 - return libbpf_err(-ENOMEM); 2894 + err = btf_ensure_modifiable(btf); 2895 + if (err) 2896 + return libbpf_err(err); 3056 2897 3057 2898 sz = sizeof(struct btf_type) + sizeof(struct btf_var); 3058 2899 t = btf_add_type_mem(btf, sz); ··· 3090 2929 { 3091 2930 struct btf_type *t; 3092 2931 int sz, name_off; 2932 + int err; 3093 2933 3094 2934 /* non-empty name */ 3095 2935 if (str_is_empty(name)) 3096 2936 return libbpf_err(-EINVAL); 3097 2937 3098 - if (btf_ensure_modifiable(btf)) 3099 - return libbpf_err(-ENOMEM); 2938 + err = btf_ensure_modifiable(btf); 2939 + if (err) 2940 + return libbpf_err(err); 3100 2941 3101 2942 sz = sizeof(struct btf_type); 3102 2943 t = btf_add_type_mem(btf, sz); ··· 3131 2968 { 3132 2969 struct btf_type *t; 3133 2970 struct btf_var_secinfo *v; 2971 + int err; 3134 2972 int sz; 3135 2973 3136 2974 /* last type should be BTF_KIND_DATASEC */ ··· 3145 2981 return libbpf_err(-EINVAL); 3146 2982 3147 2983 /* decompose and invalidate raw data */ 3148 - if (btf_ensure_modifiable(btf)) 3149 - return libbpf_err(-ENOMEM); 2984 + err = btf_ensure_modifiable(btf); 2985 + if (err) 2986 + return libbpf_err(err); 3150 2987 3151 2988 sz = sizeof(struct btf_var_secinfo); 3152 2989 v = btf_add_type_mem(btf, sz); ··· 3162 2997 t = btf_last_type(btf); 3163 2998 btf_type_inc_vlen(t); 3164 2999 3165 - btf->hdr->type_len += sz; 3166 - btf->hdr->str_off += sz; 3000 + btf_hdr_update_type_len(btf, btf->hdr.type_len + sz); 3167 3001 return 0; 3168 3002 } 3169 3003 ··· 3171 3007 { 3172 3008 struct btf_type *t; 3173 3009 int sz, value_off; 3010 + int err; 3174 3011 3175 3012 if (str_is_empty(value) || component_idx < -1) 3176 3013 return libbpf_err(-EINVAL); ··· 3179 3014 if (validate_type_id(ref_type_id)) 3180 3015 return libbpf_err(-EINVAL); 3181 3016 3182 - if (btf_ensure_modifiable(btf)) 3183 - return libbpf_err(-ENOMEM); 3017 + err = btf_ensure_modifiable(btf); 3018 + if (err) 3019 + return libbpf_err(err); 3184 3020 3185 3021 sz = sizeof(struct btf_type) + sizeof(struct btf_decl_tag); 3186 3022 t = btf_add_type_mem(btf, sz); ··· 3805 3639 return libbpf_err(-EINVAL); 3806 3640 } 3807 3641 3808 - if (btf_ensure_modifiable(btf)) { 3809 - err = -ENOMEM; 3642 + err = btf_ensure_modifiable(btf); 3643 + if (err) 3810 3644 goto done; 3811 - } 3812 3645 3813 3646 err = btf_dedup_prep(d); 3814 3647 if (err) { ··· 4127 3962 4128 3963 /* replace BTF string data and hash with deduped ones */ 4129 3964 strset__free(d->btf->strs_set); 4130 - d->btf->hdr->str_len = strset__data_size(d->strs_set); 3965 + btf_hdr_update_str_len(d->btf, strset__data_size(d->strs_set)); 4131 3966 d->btf->strs_set = d->strs_set; 4132 3967 d->strs_set = NULL; 4133 3968 d->btf->strs_deduped = true; ··· 5574 5409 /* shrink struct btf's internal types index and update btf_header */ 5575 5410 d->btf->nr_types = next_type_id - d->btf->start_id; 5576 5411 d->btf->type_offs_cap = d->btf->nr_types; 5577 - d->btf->hdr->type_len = p - d->btf->types_data; 5412 + d->btf->hdr.type_len = p - d->btf->types_data; 5578 5413 new_offs = libbpf_reallocarray(d->btf->type_offs, d->btf->type_offs_cap, 5579 5414 sizeof(*new_offs)); 5580 5415 if (d->btf->type_offs_cap && !new_offs) 5581 5416 return -ENOMEM; 5582 5417 d->btf->type_offs = new_offs; 5583 - d->btf->hdr->str_off = d->btf->hdr->type_len; 5584 - d->btf->raw_size = d->btf->hdr->hdr_len + d->btf->hdr->type_len + d->btf->hdr->str_len; 5418 + if (d->btf->layout) 5419 + d->btf->hdr.layout_off = d->btf->hdr.type_off + d->btf->hdr.type_len; 5420 + d->btf->hdr.str_off = d->btf->hdr.type_off + d->btf->hdr.type_len + d->btf->hdr.layout_len; 5421 + d->btf->raw_size = d->btf->hdr.hdr_len + d->btf->hdr.type_off + d->btf->hdr.type_len + 5422 + d->btf->hdr.layout_len + d->btf->hdr.str_len; 5585 5423 return 0; 5586 5424 } 5587 5425 ··· 6042 5874 goto done; 6043 5875 } 6044 5876 dist.split_start_id = btf__type_cnt(old_base); 6045 - dist.split_start_str = old_base->hdr->str_len; 5877 + dist.split_start_str = old_base->hdr.str_len; 6046 5878 6047 5879 /* Pass over src split BTF; generate the list of base BTF type ids it 6048 5880 * references; these will constitute our distilled BTF set to be ··· 6111 5943 6112 5944 const struct btf_header *btf_header(const struct btf *btf) 6113 5945 { 6114 - return btf->hdr; 5946 + return &btf->hdr; 6115 5947 } 6116 5948 6117 5949 void btf_set_base_btf(struct btf *btf, const struct btf *base_btf) 6118 5950 { 6119 5951 btf->base_btf = (struct btf *)base_btf; 6120 5952 btf->start_id = btf__type_cnt(base_btf); 6121 - btf->start_str_off = base_btf->hdr->str_len + base_btf->start_str_off; 5953 + btf->start_str_off = base_btf->hdr.str_len + base_btf->start_str_off; 6122 5954 } 6123 5955 6124 5956 int btf__relocate(struct btf *btf, const struct btf *base_btf) ··· 6185 6017 goto done; 6186 6018 } 6187 6019 6188 - new_types = calloc(btf->hdr->type_len, 1); 6020 + new_types = calloc(btf->hdr.type_len, 1); 6189 6021 if (!new_types) { 6190 6022 err = -ENOMEM; 6191 6023 goto done; 6192 6024 } 6193 6025 6194 - if (btf_ensure_modifiable(btf)) { 6195 - err = -ENOMEM; 6026 + err = btf_ensure_modifiable(btf); 6027 + if (err) 6196 6028 goto done; 6197 - } 6198 6029 6199 6030 for (i = start_offs; i < id_map_cnt; i++) { 6200 6031 id = id_map[i];