@@ -167,7 +167,8 @@ enum bpf_enum_value_kind {
* Convenience macro to get BTF type ID of a target kernel's type that matches
* specified local type.
* Returns:
- * - valid 32-bit unsigned type ID in kernel BTF;
+ * - valid 64-bit unsigned integer: the upper 32 bits is the BTF ID
+ * and the lower 32 bits is the type ID within the BTF.
* - 0, if no matching type was found in a target kernel BTF.
*/
#define bpf_core_type_id_kernel(type) \
@@ -884,6 +884,7 @@ static int bpf_core_calc_relo(const char *prog_name,
res->fail_memsz_adjust = false;
res->orig_sz = res->new_sz = 0;
res->orig_type_id = res->new_type_id = 0;
+ res->btf_obj_id = 0;
if (core_relo_is_field_based(relo->kind)) {
err = bpf_core_calc_field_relo(prog_name, relo, local_spec,
@@ -934,6 +935,8 @@ static int bpf_core_calc_relo(const char *prog_name,
} else if (core_relo_is_type_based(relo->kind)) {
err = bpf_core_calc_type_relo(relo, local_spec, &res->orig_val, &res->validate);
err = err ?: bpf_core_calc_type_relo(relo, targ_spec, &res->new_val, NULL);
+ if (!err && relo->kind == BPF_CORE_TYPE_ID_TARGET)
+ res->btf_obj_id = btf_obj_id(targ_spec->btf);
} else if (core_relo_is_enumval_based(relo->kind)) {
err = bpf_core_calc_enumval_relo(relo, local_spec, &res->orig_val);
err = err ?: bpf_core_calc_enumval_relo(relo, targ_spec, &res->new_val);
@@ -1125,7 +1128,10 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
}
insn[0].imm = new_val;
- insn[1].imm = new_val >> 32;
+ /* For type IDs, upper 32 bits are used for BTF ID */
+ insn[1].imm = relo->kind == BPF_CORE_TYPE_ID_TARGET ?
+ res->btf_obj_id :
+ (new_val >> 32);
pr_debug("prog '%s': relo #%d: patched insn #%d (LDIMM64) imm64 %llu -> %llu\n",
prog_name, relo_idx, insn_idx,
(unsigned long long)imm, (unsigned long long)new_val);
@@ -66,6 +66,7 @@ struct bpf_core_relo_res {
__u32 orig_type_id;
__u32 new_sz;
__u32 new_type_id;
+ __u32 btf_obj_id;
};
int __bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,