| @@ -68,33 +68,6 @@ enum libbpf_print_level { · 67 unmodified lines |
| 68 | 68 | #include "libbpf_internal.h" |
| 69 | 69 | #endif |
| 70 | 70 | |
| 71 | | −#define BPF_CORE_SPEC_MAX_LEN 32 |
| 72 | | − |
| 73 | | −/* represents BPF CO-RE field or array element accessor */ |
| 74 | | −struct bpf_core_accessor { |
| 75 | | − __u32 type_id; /* struct/union type or array element type */ |
| 76 | | − __u32 idx; /* field index or array index */ |
| 77 | | − const char *name; /* field name or NULL for array accessor */ |
| 78 | | −}; |
| 79 | | − |
| 80 | | −struct bpf_core_spec { |
| 81 | | − const struct btf *btf; |
| 82 | | − /* high-level spec: named fields and array indices only */ |
| 83 | | − struct bpf_core_accessor spec[BPF_CORE_SPEC_MAX_LEN]; |
| 84 | | − /* original unresolved (no skip_mods_or_typedefs) root type ID */ |
| 85 | | − __u32 root_type_id; |
| 86 | | − /* CO-RE relocation kind */ |
| 87 | | − enum bpf_core_relo_kind relo_kind; |
| 88 | | − /* high-level spec length */ |
| 89 | | − int len; |
| 90 | | − /* raw, low-level spec: 1-to-1 with accessor spec string */ |
| 91 | | − int raw_spec[BPF_CORE_SPEC_MAX_LEN]; |
| 92 | | − /* raw spec length */ |
| 93 | | − int raw_len; |
| 94 | | − /* field bit offset represented by spec */ |
| 95 | | − __u32 bit_offset; |
| 96 | | −}; |
| 97 | | − |
| 98 | 71 | static bool is_flex_arr(const struct btf *btf, |
| 99 | 72 | const struct bpf_core_accessor *acc, |
| 100 | 73 | const struct btf_array *arr) |
| @@ -1200,9 +1173,12 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 1099 unmodified lines |
| 1200 | 1173 | const struct bpf_core_relo *relo, |
| 1201 | 1174 | int relo_idx, |
| 1202 | 1175 | const struct btf *local_btf, |
| 1203 | | − struct bpf_core_cand_list *cands) |
| 1176 | + struct bpf_core_cand_list *cands, |
| 1177 | + struct bpf_core_spec *specs_scratch) |
| 1204 | 1178 | { |
| 1205 | | − struct bpf_core_spec local_spec, cand_spec, targ_spec = {}; |
| 1179 | + struct bpf_core_spec *local_spec = &specs_scratch[0]; |
| 1180 | + struct bpf_core_spec *cand_spec = &specs_scratch[1]; |
| 1181 | + struct bpf_core_spec *targ_spec = &specs_scratch[2]; |
| 1206 | 1182 | struct bpf_core_relo_res cand_res, targ_res; |
| 1207 | 1183 | const struct btf_type *local_type; |
| 1208 | 1184 | const char *local_name; |
| @@ -1221,7 +1197,7 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 12 unmodified lines |
| 1221 | 1197 | return -EINVAL; |
| 1222 | 1198 | |
| 1223 | 1199 | err = bpf_core_parse_spec(prog_name, local_btf, local_id, spec_str, |
| 1224 | | − relo->kind, &local_spec); |
| 1200 | + relo->kind, local_spec); |
| 1225 | 1201 | if (err) { |
| 1226 | 1202 | pr_warn("prog '%s': relo #%d: parsing [%d] %s %s + %s failed: %d\n", |
| 1227 | 1203 | prog_name, relo_idx, local_id, btf_kind_str(local_type), |
| @@ -1232,15 +1208,15 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 4 unmodified lines |
| 1232 | 1208 | |
| 1233 | 1209 | pr_debug("prog '%s': relo #%d: kind <%s> (%d), spec is ", prog_name, |
| 1234 | 1210 | relo_idx, core_relo_kind_str(relo->kind), relo->kind); |
| 1235 | | − bpf_core_dump_spec(prog_name, LIBBPF_DEBUG, &local_spec); |
| 1211 | + bpf_core_dump_spec(prog_name, LIBBPF_DEBUG, local_spec); |
| 1236 | 1212 | libbpf_print(LIBBPF_DEBUG, "\n"); |
| 1237 | 1213 | |
| 1238 | 1214 | /* TYPE_ID_LOCAL relo is special and doesn't need candidate search */ |
| 1239 | 1215 | if (relo->kind == BPF_CORE_TYPE_ID_LOCAL) { |
| 1240 | 1216 | targ_res.validate = true; |
| 1241 | 1217 | targ_res.poison = false; |
| 1242 | | − targ_res.orig_val = local_spec.root_type_id; |
| 1243 | | − targ_res.new_val = local_spec.root_type_id; |
| 1218 | + targ_res.orig_val = local_spec->root_type_id; |
| 1219 | + targ_res.new_val = local_spec->root_type_id; |
| 1244 | 1220 | goto patch_insn; |
| 1245 | 1221 | } |
| 1246 | 1222 | |
| @@ -1253,38 +1229,38 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 6 unmodified lines |
| 1253 | 1229 | |
| 1254 | 1230 | |
| 1255 | 1231 | for (i = 0, j = 0; i < cands->len; i++) { |
| 1256 | | − err = bpf_core_spec_match(&local_spec, cands->cands[i].btf, |
| 1257 | | − cands->cands[i].id, &cand_spec); |
| 1232 | + err = bpf_core_spec_match(local_spec, cands->cands[i].btf, |
| 1233 | + cands->cands[i].id, cand_spec); |
| 1258 | 1234 | if (err < 0) { |
| 1259 | 1235 | pr_warn("prog '%s': relo #%d: error matching candidate #%d ", |
| 1260 | 1236 | prog_name, relo_idx, i); |
| 1261 | | − bpf_core_dump_spec(prog_name, LIBBPF_WARN, &cand_spec); |
| 1237 | + bpf_core_dump_spec(prog_name, LIBBPF_WARN, cand_spec); |
| 1262 | 1238 | libbpf_print(LIBBPF_WARN, ": %d\n", err); |
| 1263 | 1239 | return err; |
| 1264 | 1240 | } |
| 1265 | 1241 | |
| 1266 | 1242 | pr_debug("prog '%s': relo #%d: %s candidate #%d ", prog_name, |
| 1267 | 1243 | relo_idx, err == 0 ? "non-matching" : "matching", i); |
| 1268 | | − bpf_core_dump_spec(prog_name, LIBBPF_DEBUG, &cand_spec); |
| 1244 | + bpf_core_dump_spec(prog_name, LIBBPF_DEBUG, cand_spec); |
| 1269 | 1245 | libbpf_print(LIBBPF_DEBUG, "\n"); |
| 1270 | 1246 | |
| 1271 | 1247 | if (err == 0) |
| 1272 | 1248 | continue; |
| 1273 | 1249 | |
| 1274 | | − err = bpf_core_calc_relo(prog_name, relo, relo_idx, &local_spec, &cand_spec, &cand_res); |
| 1250 | + err = bpf_core_calc_relo(prog_name, relo, relo_idx, local_spec, cand_spec, &cand_res); |
| 1275 | 1251 | if (err) |
| 1276 | 1252 | return err; |
| 1277 | 1253 | |
| 1278 | 1254 | if (j == 0) { |
| 1279 | 1255 | targ_res = cand_res; |
| 1280 | | − targ_spec = cand_spec; |
| 1281 | | − } else if (cand_spec.bit_offset != targ_spec.bit_offset) { |
| 1256 | + *targ_spec = *cand_spec; |
| 1257 | + } else if (cand_spec->bit_offset != targ_spec->bit_offset) { |
| 1282 | 1258 | /* if there are many field relo candidates, they |
| 1283 | 1259 | * should all resolve to the same bit offset |
| 1284 | 1260 | */ |
| 1285 | 1261 | pr_warn("prog '%s': relo #%d: field offset ambiguity: %u != %u\n", |
| 1286 | | − prog_name, relo_idx, cand_spec.bit_offset, |
| 1287 | | − targ_spec.bit_offset); |
| 1262 | + prog_name, relo_idx, cand_spec->bit_offset, |
| 1263 | + targ_spec->bit_offset); |
| 1288 | 1264 | return -EINVAL; |
| 1289 | 1265 | } else if (cand_res.poison != targ_res.poison || cand_res.new_val != targ_res.new_val) { |
| 1290 | 1266 | /* all candidates should result in the same relocation |
| @@ -1328,7 +1304,7 @@ int bpf_core_apply_relo_insn(const char *prog_name, struct bpf_insn *insn, · 37 unmodified lines |
| 1328 | 1304 | prog_name, relo_idx); |
| 1329 | 1305 | |
| 1330 | 1306 | /* calculate single target relo result explicitly */ |
| 1331 | | − err = bpf_core_calc_relo(prog_name, relo, relo_idx, &local_spec, NULL, &targ_res); |
| 1307 | + err = bpf_core_calc_relo(prog_name, relo, relo_idx, local_spec, NULL, &targ_res); |
| 1332 | 1308 | if (err) |
| 1333 | 1309 | return err; |
| 1334 | 1310 | } |