Re: [PATCH pahole] btf: add kind_flag support for btf_loader

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 12/20/18 3:44 PM, Yonghong Song wrote:
> For struct/union members, the struct/union type info kind_flag is
> needed to calculate correct bitfield_size and bit_offset.
>    if (kind_flag) {
>      bitfield_size = BTF_MEMBER_BITFIELD_SIZE(member->offset);
>      bit_offset = BTF_MEMBER_BIT_OFFSET(member->offset);
>    } else {
>      bitfield_size = 0;
>      bit_offset = member->offset;
>    }
> Note that bitfield_size and bit_offset will not depend on the
> member type. The member type will help calculate correct
> bitfield_offset, byte_size, byte_offset, bit_size.
> 
> For example, with the fix, we will be able to display
> bit offset and bitfield size properly.
> 
>    -bash-4.4$ cat t.c
>    struct t {
>      int a:2;
>      int b:3;
>      int c:2;
>    } g;
>    -bash-4.4$ gcc -c -O2 -g t.c
>    -bash-4.4$ pahole -JV t.o
>    File t.o:
>    [1] STRUCT t kind_flag=1 size=4 vlen=3
>            a type_id=2 bitfield_size=2 bits_offset=0
>            b type_id=2 bitfield_size=3 bits_offset=2
>            c type_id=2 bitfield_size=2 bits_offset=5
>    [2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
>    -bash-4.4$ pahole -F btf t.o
>    struct t {
>            int                        a:2;                  /*     0: 0  4 */
>            int                        b:3;                  /*     0: 2  4 */
>            int                        c:2;                  /*     0: 5  4 */
> 
>            /* size: 4, cachelines: 1, members: 3 */
>            /* bit_padding: 25 bits */
>            /* last cacheline: 4 bytes */
>    };
> 
> Note that the above offset showing is different from the below dwarf as
> BTF bitfield_offset is always the offset from the start of structure,
> kindly like big endian encoding. This may need adjustment to be
> conforming to the dwarf dump format.
> 
>    -bash-4.4$ pahole -F dwarf t.o
>    struct t {
>            int                        a:2;                  /*     0:30  4 */
>            int                        b:3;                  /*     0:27  4 */
>            int                        c:2;                  /*     0:25  4 */
> 
>            /* size: 4, cachelines: 1, members: 3 */
>            /* bit_padding: 25 bits */
>            /* last cacheline: 4 bytes */
>    };
> 
> Signed-off-by: Yonghong Song <yhs@xxxxxx>
> ---
>   btf_loader.c | 61 +++++++++++++++++++++++++++++++---------------------
>   dwarves.h    |  1 +
>   2 files changed, 37 insertions(+), 25 deletions(-)
> 
> diff --git a/btf_loader.c b/btf_loader.c
> index dae21d5..eeb0c8b 100644
> --- a/btf_loader.c
> +++ b/btf_loader.c
> @@ -1,4 +1,4 @@
> -/*
> +/*
>    * btf_loader.c
>    *
>    * Copyright (C) 2018 Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
> @@ -101,7 +101,7 @@ static struct base_type *base_type__new(strings_t name, uint32_t attrs,
>   }
>   
>   static void type__init(struct type *type, uint16_t tag,
> -		       strings_t name, size_t size)
> +		       strings_t name, size_t size, bool kflag)
>   {
>   	INIT_LIST_HEAD(&type->node);
>   	INIT_LIST_HEAD(&type->namespace.tags);
> @@ -109,24 +109,26 @@ static void type__init(struct type *type, uint16_t tag,
>   	type->namespace.tag.tag = tag;
>   	type->namespace.name = name;
>   	type->namespace.sname = 0;
> +	type->flag = kflag;

Found one problem related to this.
This is not needed since type->flag is not used later.

>   }
>   
> -static struct type *type__new(uint16_t tag, strings_t name, size_t size)
> +static struct type *type__new(uint16_t tag, strings_t name, size_t size,
> +			      bool kflag)
>   {
>           struct type *type = tag__alloc(sizeof(*type));
>   
>   	if (type != NULL)
> -		type__init(type, tag, name, size);
> +		type__init(type, tag, name, size, kflag);
>   
>   	return type;
>   }
>   
> -static struct class *class__new(strings_t name, size_t size)
> +static struct class *class__new(strings_t name, size_t size, bool kflag)
>   {
>   	struct class *class = tag__alloc(sizeof(*class));
>   
>   	if (class != NULL) {
> -		type__init(&class->type, DW_TAG_structure_type, name, size);
> +		type__init(&class->type, DW_TAG_structure_type, name, size, kflag);
>   		INIT_LIST_HEAD(&class->vtable);
>   	}
>   
> @@ -177,7 +179,8 @@ static int create_new_array(struct btf *btf, void *ptr, long id)
>   	return sizeof(*ap);
>   }
>   
> -static int create_members(struct btf *btf, void *ptr, int vlen, struct type *class)
> +static int create_members(struct btf *btf, void *ptr, int vlen, struct type *class,
> +			  bool kflag)
>   {
>   	struct btf_member *mp = ptr;
>   	int i;
> @@ -193,8 +196,13 @@ static int create_members(struct btf *btf, void *ptr, int vlen, struct type *cla
>   		member->tag.type   = btf__get32(btf, &mp[i].type);
>   		member->name	   = btf__get32(btf, &mp[i].name_off);
>   		offset = btf__get32(btf, &mp[i].offset);
> -		member->bit_offset = BTF_MEMBER_BIT_OFFSET(offset);
> -		member->bitfield_size = BTF_MEMBER_BITFIELD_SIZE(offset);
> +		if (kflag) {
> +			member->bit_offset = BTF_MEMBER_BIT_OFFSET(offset);
> +			member->bitfield_size = BTF_MEMBER_BITFIELD_SIZE(offset);
> +		} else {
> +			member->bit_offset = offset;
> +			member->bitfield_size = 0;
> +		}
>   		/* sizes and offsets will be corrected at class__fixup_btf_bitfields */
>   		type__add_member(class, member);
>   	}
> @@ -202,11 +210,13 @@ static int create_members(struct btf *btf, void *ptr, int vlen, struct type *cla
>   	return sizeof(*mp);
>   }
>   
> -static int create_new_class(struct btf *btf, void *ptr, int vlen, struct btf_type *tp, uint64_t size, long id)
> +static int create_new_class(struct btf *btf, void *ptr, int vlen,
> +			    struct btf_type *tp, uint64_t size, long id,
> +			    bool kflag)
>   {
>   	strings_t name = btf__get32(btf, &tp->name_off);
> -	struct class *class = class__new(name, size);
> -	int member_size = create_members(btf, ptr, vlen, &class->type);
> +	struct class *class = class__new(name, size, kflag);
> +	int member_size = create_members(btf, ptr, vlen, &class->type, kflag);
>   
>   	if (member_size < 0)
>   		goto out_free;
> @@ -221,11 +231,12 @@ out_free:
>   
>   static int create_new_union(struct btf *btf, void *ptr,
>   			    int vlen, struct btf_type *tp,
> -			    uint64_t size, long id)
> +			    uint64_t size, long id,
> +			    bool kflag)
>   {
>   	strings_t name = btf__get32(btf, &tp->name_off);
> -	struct type *un = type__new(DW_TAG_union_type, name, size);
> -	int member_size = create_members(btf, ptr, vlen, un);
> +	struct type *un = type__new(DW_TAG_union_type, name, size, kflag);
> +	int member_size = create_members(btf, ptr, vlen, un, kflag);
>   
>   	if (member_size < 0)
>   		goto out_free;
> @@ -259,7 +270,7 @@ static int create_new_enumeration(struct btf *btf, void *ptr,
>   	uint16_t i;
>   	struct type *enumeration = type__new(DW_TAG_enumeration_type,
>   					     btf__get32(btf, &tp->name_off),
> -					     size ?: (sizeof(int) * 8));
> +					     size ?: (sizeof(int) * 8), false);
>   
>   	if (enumeration == NULL)
>   		return -ENOMEM;
> @@ -299,10 +310,11 @@ static int create_new_subroutine_type(struct btf *btf, void *ptr,
>   	return vlen < 0 ? -ENOMEM : vlen;
>   }
>   
> -static int create_new_forward_decl(struct btf *btf, struct btf_type *tp, uint64_t size, long id)
> +static int create_new_forward_decl(struct btf *btf, struct btf_type *tp,
> +				   uint64_t size, long id, bool kflag)
>   {
>   	strings_t name = btf__get32(btf, &tp->name_off);
> -	struct class *fwd = class__new(name, size);
> +	struct class *fwd = class__new(name, size, kflag);
>   
>   	if (fwd == NULL)
>   		return -ENOMEM;
> @@ -315,7 +327,7 @@ static int create_new_typedef(struct btf *btf, struct btf_type *tp, uint64_t siz
>   {
>   	strings_t name = btf__get32(btf, &tp->name_off);
>   	unsigned int type_id = btf__get32(btf, &tp->type);
> -	struct type *type = type__new(DW_TAG_typedef, name, size);
> +	struct type *type = type__new(DW_TAG_typedef, name, size, false);
>   
>   	if (type == NULL)
>   		return -ENOMEM;
> @@ -377,6 +389,7 @@ static int btf__load_types(struct btf *btf)
>   		int	 vlen = BTF_INFO_VLEN(val);
>   		void	 *ptr = type_ptr;
>   		uint32_t size = btf__get32(btf, &type_ptr->size);
> +		bool     kflag = BTF_INFO_KFLAG(val);
>   
>   		ptr += sizeof(struct btf_type);
>   
> @@ -385,13 +398,13 @@ static int btf__load_types(struct btf *btf)
>   		} else if (type == BTF_KIND_ARRAY) {
>   			vlen = create_new_array(btf, ptr, type_index);
>   		} else if (type == BTF_KIND_STRUCT) {
> -			vlen = create_new_class(btf, ptr, vlen, type_ptr, size, type_index);
> +			vlen = create_new_class(btf, ptr, vlen, type_ptr, size, type_index, kflag);
>   		} else if (type == BTF_KIND_UNION) {
> -			vlen = create_new_union(btf, ptr, vlen, type_ptr, size, type_index);
> +			vlen = create_new_union(btf, ptr, vlen, type_ptr, size, type_index, kflag);
>   		} else if (type == BTF_KIND_ENUM) {
>   			vlen = create_new_enumeration(btf, ptr, vlen, type_ptr, size, type_index);
>   		} else if (type == BTF_KIND_FWD) {
> -			vlen = create_new_forward_decl(btf, type_ptr, size, type_index);
> +			vlen = create_new_forward_decl(btf, type_ptr, size, type_index, kflag);
>   		} else if (type == BTF_KIND_TYPEDEF) {
>   			vlen = create_new_typedef(btf, type_ptr, size, type_index);
>   		} else if (type == BTF_KIND_VOLATILE ||
> @@ -442,7 +455,6 @@ static int class__fixup_btf_bitfields(struct tag *tag, struct cu *cu)
>   			continue;
>   
>   		pos->bitfield_offset = 0;
> -		pos->bitfield_size = 0;
>   		pos->byte_offset = pos->bit_offset / 8;
>   
>   		uint16_t type_bit_size;
> @@ -484,13 +496,12 @@ static int class__fixup_btf_bitfields(struct tag *tag, struct cu *cu)
>   		 */
>   		pos->byte_size = integral_bit_size / 8;
>   
> -		if (integral_bit_size == 0 || type_bit_size == integral_bit_size) {
> +		if (integral_bit_size == 0) {
>   			pos->bit_size = integral_bit_size;
>   			continue;
>   		}
>   
>   		pos->bitfield_offset = pos->bit_offset % integral_bit_size;
> -		pos->bitfield_size = type_bit_size;
>   		pos->bit_size = type_bit_size;
>   		pos->byte_offset = (((pos->bit_offset / integral_bit_size) *
>   				     integral_bit_size) / 8);
> diff --git a/dwarves.h b/dwarves.h
> index 156fa58..f800518 100644
> --- a/dwarves.h
> +++ b/dwarves.h
> @@ -879,6 +879,7 @@ struct type {
>   	uint8_t		 definition_emitted:1;
>   	uint8_t		 fwd_decl_emitted:1;
>   	uint8_t		 resized:1;
> +	uint8_t		 flag:1;
>   };
>   
>   static inline struct class *type__class(const struct type *type)
> 




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux