Skip to content

Commit

Permalink
libbpf: Introduce BTF_KIND_FLOAT
Browse files Browse the repository at this point in the history
Some BPF programs compiled on s390 fail to load, because s390
arch-specific linux headers contain float and double types.

Introduce support for such types to libbpf by representing them using
the new BTF_KIND_FLOAT.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
  • Loading branch information
iii-i committed Feb 15, 2021
1 parent 0d415f6 commit b0f5206
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
@@ -1,3 +1,3 @@
[submodule "lib/bpf"]
path = lib/bpf
url = https://github.com/libbpf/libbpf
url = https://github.com/iii-i/libbpf
21 changes: 19 additions & 2 deletions btf_loader.c
Expand Up @@ -160,7 +160,7 @@ static struct variable *variable__new(strings_t name, uint32_t linkage)
return var;
}

static int create_new_base_type(struct btf_elf *btfe, const struct btf_type *tp, uint32_t id)
static int create_new_int_type(struct btf_elf *btfe, const struct btf_type *tp, uint32_t id)
{
uint32_t attrs = btf_int_encoding(tp);
strings_t name = tp->name_off;
Expand All @@ -175,6 +175,20 @@ static int create_new_base_type(struct btf_elf *btfe, const struct btf_type *tp,
return 0;
}

static int create_new_float_type(struct btf_elf *btfe, const struct btf_type *tp, uint32_t id)
{
strings_t name = tp->name_off;
struct base_type *base = base_type__new(name, 0, BT_FP_SINGLE, tp->size * 8);

if (base == NULL)
return -ENOMEM;

base->tag.tag = DW_TAG_base_type;
cu__add_tag_with_id(btfe->priv, &base->tag, id);

return 0;
}

static int create_new_array(struct btf_elf *btfe, const struct btf_type *tp, uint32_t id)
{
struct btf_array *ap = btf_array(tp);
Expand Down Expand Up @@ -397,7 +411,7 @@ static int btf_elf__load_types(struct btf_elf *btfe)

switch (type) {
case BTF_KIND_INT:
err = create_new_base_type(btfe, type_ptr, type_index);
err = create_new_int_type(btfe, type_ptr, type_index);
break;
case BTF_KIND_ARRAY:
err = create_new_array(btfe, type_ptr, type_index);
Expand Down Expand Up @@ -442,6 +456,9 @@ static int btf_elf__load_types(struct btf_elf *btfe)
// BTF_KIND_FUNC corresponding to a defined subprogram.
err = create_new_function(btfe, type_ptr, type_index);
break;
case BTF_KIND_FLOAT:
err = create_new_float_type(btfe, type_ptr, type_index);
break;
default:
fprintf(stderr, "BTF: idx: %d, Unknown kind %d\n", type_index, type);
fflush(stderr);
Expand Down
11 changes: 11 additions & 0 deletions dwarf_loader.c
Expand Up @@ -461,6 +461,16 @@ static struct ptr_to_member_type *ptr_to_member_type__new(Dwarf_Die *die,
return ptr;
}

static uint8_t encoding_to_float_type(uint64_t encoding)
{
switch (encoding) {
case DW_ATE_complex_float: return BT_FP_CMPLX;
case DW_ATE_float: return BT_FP_SINGLE;
case DW_ATE_imaginary_float: return BT_FP_IMGRY;
default: return 0;
}
}

static struct base_type *base_type__new(Dwarf_Die *die, struct cu *cu)
{
struct base_type *bt = tag__alloc(cu, sizeof(*bt));
Expand All @@ -474,6 +484,7 @@ static struct base_type *base_type__new(Dwarf_Die *die, struct cu *cu)
bt->is_signed = encoding == DW_ATE_signed;
bt->is_varargs = false;
bt->name_has_encoding = true;
bt->float_type = encoding_to_float_type(encoding);
}

return bt;
Expand Down
2 changes: 1 addition & 1 deletion lib/bpf
Submodule bpf updated from 5af3d8 to fd6c01
30 changes: 29 additions & 1 deletion libbtf.c
Expand Up @@ -227,6 +227,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
[BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
[BTF_KIND_VAR] = "VAR",
[BTF_KIND_DATASEC] = "DATASEC",
[BTF_KIND_FLOAT] = "FLOAT",
};

static const char *btf_elf__printable_name(const struct btf_elf *btfe, uint32_t offset)
Expand Down Expand Up @@ -367,6 +368,27 @@ static void btf_log_func_param(const struct btf_elf *btfe,
}
}

static int32_t btf_elf__add_float_type(struct btf_elf *btfe,
const struct base_type *bt,
const char *name)
{
int32_t id;

id = btf__add_float(btfe->btf, name, BITS_ROUNDUP_BYTES(bt->bit_size));
if (id < 0) {
btf_elf__log_err(btfe, BTF_KIND_FLOAT, name, true, "Error emitting BTF type");
} else {
const struct btf_type *t;

t = btf__type_by_id(btfe->btf, id);
btf_elf__log_type(btfe, t, false, true,
"size=%u nr_bits=%u",
t->size, bt->bit_size);
}

return id;
}

int32_t btf_elf__add_base_type(struct btf_elf *btfe, const struct base_type *bt,
const char *name)
{
Expand All @@ -380,7 +402,11 @@ int32_t btf_elf__add_base_type(struct btf_elf *btfe, const struct base_type *bt,
} else if (bt->is_bool) {
encoding = BTF_INT_BOOL;
} else if (bt->float_type) {
fprintf(stderr, "float_type is not supported\n");
if (bt->float_type == BT_FP_SINGLE ||
bt->float_type == BT_FP_DOUBLE ||
bt->float_type == BT_FP_LDBL)
return btf_elf__add_float_type(btfe, bt, name);
fprintf(stderr, "Complex, interval and imaginary float types are not supported\n");
return -1;
}

Expand Down Expand Up @@ -820,6 +846,8 @@ int btf_elf__encode(struct btf_elf *btfe, uint8_t flags)
{
struct btf *btf = btfe->btf;

libbpf_set_print(libbpf_log);

/* Empty file, nothing to do, so... done! */
if (btf__get_nr_types(btf) == 0)
return 0;
Expand Down

0 comments on commit b0f5206

Please sign in to comment.