forked from mirrors/linux
		
	libbpf: Expose btf__align_of() API
Expose BTF API that calculates type alignment requirements. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20191214014341.3442258-7-andriin@fb.com
This commit is contained in:
		
							parent
							
								
									544402d4b4
								
							
						
					
					
						commit
						3d208f4ca1
					
				
					 4 changed files with 47 additions and 41 deletions
				
			
		| 
						 | 
					@ -278,6 +278,45 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
 | 
				
			||||||
	return nelems * size;
 | 
						return nelems * size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btf__align_of(const struct btf *btf, __u32 id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct btf_type *t = btf__type_by_id(btf, id);
 | 
				
			||||||
 | 
						__u16 kind = btf_kind(t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (kind) {
 | 
				
			||||||
 | 
						case BTF_KIND_INT:
 | 
				
			||||||
 | 
						case BTF_KIND_ENUM:
 | 
				
			||||||
 | 
							return min(sizeof(void *), t->size);
 | 
				
			||||||
 | 
						case BTF_KIND_PTR:
 | 
				
			||||||
 | 
							return sizeof(void *);
 | 
				
			||||||
 | 
						case BTF_KIND_TYPEDEF:
 | 
				
			||||||
 | 
						case BTF_KIND_VOLATILE:
 | 
				
			||||||
 | 
						case BTF_KIND_CONST:
 | 
				
			||||||
 | 
						case BTF_KIND_RESTRICT:
 | 
				
			||||||
 | 
							return btf__align_of(btf, t->type);
 | 
				
			||||||
 | 
						case BTF_KIND_ARRAY:
 | 
				
			||||||
 | 
							return btf__align_of(btf, btf_array(t)->type);
 | 
				
			||||||
 | 
						case BTF_KIND_STRUCT:
 | 
				
			||||||
 | 
						case BTF_KIND_UNION: {
 | 
				
			||||||
 | 
							const struct btf_member *m = btf_members(t);
 | 
				
			||||||
 | 
							__u16 vlen = btf_vlen(t);
 | 
				
			||||||
 | 
							int i, align = 1, t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for (i = 0; i < vlen; i++, m++) {
 | 
				
			||||||
 | 
								t = btf__align_of(btf, m->type);
 | 
				
			||||||
 | 
								if (t <= 0)
 | 
				
			||||||
 | 
									return t;
 | 
				
			||||||
 | 
								align = max(align, t);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return align;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int btf__resolve_type(const struct btf *btf, __u32 type_id)
 | 
					int btf__resolve_type(const struct btf *btf, __u32 type_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct btf_type *t;
 | 
						const struct btf_type *t;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,7 @@ LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
 | 
				
			||||||
						  __u32 id);
 | 
											  __u32 id);
 | 
				
			||||||
LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
 | 
					LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
 | 
				
			||||||
LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
 | 
					LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
 | 
				
			||||||
 | 
					LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
 | 
				
			||||||
LIBBPF_API int btf__fd(const struct btf *btf);
 | 
					LIBBPF_API int btf__fd(const struct btf *btf);
 | 
				
			||||||
LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
 | 
					LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
 | 
				
			||||||
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
 | 
					LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -752,41 +752,6 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int btf_align_of(const struct btf *btf, __u32 id)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	const struct btf_type *t = btf__type_by_id(btf, id);
 | 
					 | 
				
			||||||
	__u16 kind = btf_kind(t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch (kind) {
 | 
					 | 
				
			||||||
	case BTF_KIND_INT:
 | 
					 | 
				
			||||||
	case BTF_KIND_ENUM:
 | 
					 | 
				
			||||||
		return min(sizeof(void *), t->size);
 | 
					 | 
				
			||||||
	case BTF_KIND_PTR:
 | 
					 | 
				
			||||||
		return sizeof(void *);
 | 
					 | 
				
			||||||
	case BTF_KIND_TYPEDEF:
 | 
					 | 
				
			||||||
	case BTF_KIND_VOLATILE:
 | 
					 | 
				
			||||||
	case BTF_KIND_CONST:
 | 
					 | 
				
			||||||
	case BTF_KIND_RESTRICT:
 | 
					 | 
				
			||||||
		return btf_align_of(btf, t->type);
 | 
					 | 
				
			||||||
	case BTF_KIND_ARRAY:
 | 
					 | 
				
			||||||
		return btf_align_of(btf, btf_array(t)->type);
 | 
					 | 
				
			||||||
	case BTF_KIND_STRUCT:
 | 
					 | 
				
			||||||
	case BTF_KIND_UNION: {
 | 
					 | 
				
			||||||
		const struct btf_member *m = btf_members(t);
 | 
					 | 
				
			||||||
		__u16 vlen = btf_vlen(t);
 | 
					 | 
				
			||||||
		int i, align = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < vlen; i++, m++)
 | 
					 | 
				
			||||||
			align = max(align, btf_align_of(btf, m->type));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return align;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
 | 
					static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
 | 
				
			||||||
				 const struct btf_type *t)
 | 
									 const struct btf_type *t)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -794,18 +759,18 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
 | 
				
			||||||
	int align, i, bit_sz;
 | 
						int align, i, bit_sz;
 | 
				
			||||||
	__u16 vlen;
 | 
						__u16 vlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	align = btf_align_of(btf, id);
 | 
						align = btf__align_of(btf, id);
 | 
				
			||||||
	/* size of a non-packed struct has to be a multiple of its alignment*/
 | 
						/* size of a non-packed struct has to be a multiple of its alignment*/
 | 
				
			||||||
	if (t->size % align)
 | 
						if (align && t->size % align)
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m = btf_members(t);
 | 
						m = btf_members(t);
 | 
				
			||||||
	vlen = btf_vlen(t);
 | 
						vlen = btf_vlen(t);
 | 
				
			||||||
	/* all non-bitfield fields have to be naturally aligned */
 | 
						/* all non-bitfield fields have to be naturally aligned */
 | 
				
			||||||
	for (i = 0; i < vlen; i++, m++) {
 | 
						for (i = 0; i < vlen; i++, m++) {
 | 
				
			||||||
		align = btf_align_of(btf, m->type);
 | 
							align = btf__align_of(btf, m->type);
 | 
				
			||||||
		bit_sz = btf_member_bitfield_size(t, i);
 | 
							bit_sz = btf_member_bitfield_size(t, i);
 | 
				
			||||||
		if (bit_sz == 0 && m->offset % (8 * align) != 0)
 | 
							if (align && bit_sz == 0 && m->offset % (8 * align) != 0)
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -889,7 +854,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
 | 
				
			||||||
		fname = btf_name_of(d, m->name_off);
 | 
							fname = btf_name_of(d, m->name_off);
 | 
				
			||||||
		m_sz = btf_member_bitfield_size(t, i);
 | 
							m_sz = btf_member_bitfield_size(t, i);
 | 
				
			||||||
		m_off = btf_member_bit_offset(t, i);
 | 
							m_off = btf_member_bit_offset(t, i);
 | 
				
			||||||
		align = packed ? 1 : btf_align_of(d->btf, m->type);
 | 
							align = packed ? 1 : btf__align_of(d->btf, m->type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1);
 | 
							btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1);
 | 
				
			||||||
		btf_dump_printf(d, "\n%s", pfx(lvl + 1));
 | 
							btf_dump_printf(d, "\n%s", pfx(lvl + 1));
 | 
				
			||||||
| 
						 | 
					@ -907,7 +872,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* pad at the end, if necessary */
 | 
						/* pad at the end, if necessary */
 | 
				
			||||||
	if (is_struct) {
 | 
						if (is_struct) {
 | 
				
			||||||
		align = packed ? 1 : btf_align_of(d->btf, id);
 | 
							align = packed ? 1 : btf__align_of(d->btf, id);
 | 
				
			||||||
		btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
 | 
							btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
 | 
				
			||||||
					  lvl + 1);
 | 
										  lvl + 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,4 +212,5 @@ LIBBPF_0.0.6 {
 | 
				
			||||||
LIBBPF_0.0.7 {
 | 
					LIBBPF_0.0.7 {
 | 
				
			||||||
	global:
 | 
						global:
 | 
				
			||||||
		bpf_program__attach;
 | 
							bpf_program__attach;
 | 
				
			||||||
 | 
							btf__align_of;
 | 
				
			||||||
} LIBBPF_0.0.6;
 | 
					} LIBBPF_0.0.6;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue