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

libbpf: BTF relocation followup fixing naming, loop logic

Use less verbose names in BTF relocation code and fix off-by-one error
and typo in btf_relocate.c. Simplify loop over matching distilled
types, moving from assigning a _next value in loop body to moving
match check conditions into the guard.

Suggested-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/bpf/20240620091733.1967885-2-alan.maguire@oracle.com

authored by

Alan Maguire and committed by
Andrii Nakryiko
d1cf8408 cd387ce5

+31 -41
+31 -41
tools/lib/bpf/btf_relocate.c
··· 160 160 */ 161 161 static int btf_relocate_map_distilled_base(struct btf_relocate *r) 162 162 { 163 - struct btf_name_info *dist_base_info_sorted, *dist_base_info_sorted_end; 163 + struct btf_name_info *info, *info_end; 164 164 struct btf_type *base_t, *dist_t; 165 165 __u8 *base_name_cnt = NULL; 166 166 int err = 0; ··· 169 169 /* generate a sort index array of name/type ids sorted by name for 170 170 * distilled base BTF to speed name-based lookups. 171 171 */ 172 - dist_base_info_sorted = calloc(r->nr_dist_base_types, sizeof(*dist_base_info_sorted)); 173 - if (!dist_base_info_sorted) { 172 + info = calloc(r->nr_dist_base_types, sizeof(*info)); 173 + if (!info) { 174 174 err = -ENOMEM; 175 175 goto done; 176 176 } 177 - dist_base_info_sorted_end = dist_base_info_sorted + r->nr_dist_base_types; 177 + info_end = info + r->nr_dist_base_types; 178 178 for (id = 0; id < r->nr_dist_base_types; id++) { 179 179 dist_t = btf_type_by_id(r->dist_base_btf, id); 180 - dist_base_info_sorted[id].name = btf__name_by_offset(r->dist_base_btf, 181 - dist_t->name_off); 182 - dist_base_info_sorted[id].id = id; 183 - dist_base_info_sorted[id].size = dist_t->size; 184 - dist_base_info_sorted[id].needs_size = true; 180 + info[id].name = btf__name_by_offset(r->dist_base_btf, dist_t->name_off); 181 + info[id].id = id; 182 + info[id].size = dist_t->size; 183 + info[id].needs_size = true; 185 184 } 186 - qsort(dist_base_info_sorted, r->nr_dist_base_types, sizeof(*dist_base_info_sorted), 187 - cmp_btf_name_size); 185 + qsort(info, r->nr_dist_base_types, sizeof(*info), cmp_btf_name_size); 188 186 189 187 /* Mark distilled base struct/union members of split BTF structs/unions 190 188 * in id_map with BTF_IS_EMBEDDED; this signals that these types 191 - * need to match both name and size, otherwise embeddding the base 189 + * need to match both name and size, otherwise embedding the base 192 190 * struct/union in the split type is invalid. 193 191 */ 194 192 for (id = r->nr_dist_base_types; id < r->nr_split_types; id++) { ··· 214 216 215 217 /* Now search base BTF for matching distilled base BTF types. */ 216 218 for (id = 1; id < r->nr_base_types; id++) { 217 - struct btf_name_info *dist_name_info, *dist_name_info_next = NULL; 218 - struct btf_name_info base_name_info = {}; 219 + struct btf_name_info *dist_info, base_info = {}; 219 220 int dist_kind, base_kind; 220 221 221 222 base_t = btf_type_by_id(r->base_btf, id); ··· 222 225 if (!base_t->name_off) 223 226 continue; 224 227 base_kind = btf_kind(base_t); 225 - base_name_info.id = id; 226 - base_name_info.name = btf__name_by_offset(r->base_btf, base_t->name_off); 228 + base_info.id = id; 229 + base_info.name = btf__name_by_offset(r->base_btf, base_t->name_off); 227 230 switch (base_kind) { 228 231 case BTF_KIND_INT: 229 232 case BTF_KIND_FLOAT: 230 233 case BTF_KIND_ENUM: 231 234 case BTF_KIND_ENUM64: 232 235 /* These types should match both name and size */ 233 - base_name_info.needs_size = true; 234 - base_name_info.size = base_t->size; 236 + base_info.needs_size = true; 237 + base_info.size = base_t->size; 235 238 break; 236 239 case BTF_KIND_FWD: 237 240 /* No size considerations for fwds. */ ··· 245 248 * unless corresponding _base_ types to match them are 246 249 * missing. 247 250 */ 248 - base_name_info.needs_size = base_name_cnt[base_t->name_off] > 1; 249 - base_name_info.size = base_t->size; 251 + base_info.needs_size = base_name_cnt[base_t->name_off] > 1; 252 + base_info.size = base_t->size; 250 253 break; 251 254 default: 252 255 continue; 253 256 } 254 257 /* iterate over all matching distilled base types */ 255 - for (dist_name_info = search_btf_name_size(&base_name_info, dist_base_info_sorted, 256 - r->nr_dist_base_types); 257 - dist_name_info != NULL; dist_name_info = dist_name_info_next) { 258 - /* Are there more distilled matches to process after 259 - * this one? 260 - */ 261 - dist_name_info_next = dist_name_info + 1; 262 - if (dist_name_info_next >= dist_base_info_sorted_end || 263 - cmp_btf_name_size(&base_name_info, dist_name_info_next)) 264 - dist_name_info_next = NULL; 265 - 266 - if (!dist_name_info->id || dist_name_info->id > r->nr_dist_base_types) { 258 + for (dist_info = search_btf_name_size(&base_info, info, r->nr_dist_base_types); 259 + dist_info != NULL && dist_info < info_end && 260 + cmp_btf_name_size(&base_info, dist_info) == 0; 261 + dist_info++) { 262 + if (!dist_info->id || dist_info->id >= r->nr_dist_base_types) { 267 263 pr_warn("base BTF id [%d] maps to invalid distilled base BTF id [%d]\n", 268 - id, dist_name_info->id); 264 + id, dist_info->id); 269 265 err = -EINVAL; 270 266 goto done; 271 267 } 272 - dist_t = btf_type_by_id(r->dist_base_btf, dist_name_info->id); 268 + dist_t = btf_type_by_id(r->dist_base_btf, dist_info->id); 273 269 dist_kind = btf_kind(dist_t); 274 270 275 271 /* Validate that the found distilled type is compatible. ··· 309 319 /* size verification is required for embedded 310 320 * struct/unions. 311 321 */ 312 - if (r->id_map[dist_name_info->id] == BTF_IS_EMBEDDED && 322 + if (r->id_map[dist_info->id] == BTF_IS_EMBEDDED && 313 323 base_t->size != dist_t->size) 314 324 continue; 315 325 break; 316 326 default: 317 327 continue; 318 328 } 319 - if (r->id_map[dist_name_info->id] && 320 - r->id_map[dist_name_info->id] != BTF_IS_EMBEDDED) { 329 + if (r->id_map[dist_info->id] && 330 + r->id_map[dist_info->id] != BTF_IS_EMBEDDED) { 321 331 /* we already have a match; this tells us that 322 332 * multiple base types of the same name 323 333 * have the same size, since for cases where ··· 327 337 * to in base BTF, so error out. 328 338 */ 329 339 pr_warn("distilled base BTF type '%s' [%u], size %u has multiple candidates of the same size (ids [%u, %u]) in base BTF\n", 330 - base_name_info.name, dist_name_info->id, 331 - base_t->size, id, r->id_map[dist_name_info->id]); 340 + base_info.name, dist_info->id, 341 + base_t->size, id, r->id_map[dist_info->id]); 332 342 err = -EINVAL; 333 343 goto done; 334 344 } 335 345 /* map id and name */ 336 - r->id_map[dist_name_info->id] = id; 346 + r->id_map[dist_info->id] = id; 337 347 r->str_map[dist_t->name_off] = base_t->name_off; 338 348 } 339 349 } ··· 352 362 } 353 363 done: 354 364 free(base_name_cnt); 355 - free(dist_base_info_sorted); 365 + free(info); 356 366 return err; 357 367 } 358 368