[PATCH v2 pahole 1/2] btf_loader: simplify fixup code by relying on BTF data more

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

 



btf_loader relies on guessing base integral type size for enums and
integers, which is unreliable. There doesn't seem to be a need for
that, as all this information could be extracted from BTF information.

Before:
$ PAHOLE=~/local/pahole/build/pahole ./btfdiff ~/local/btf/libc-2.28.so.debug
base_type__name_to_size: base_type _Float128
class__fixup_btf_bitfields: unknown base type name "_Float128"!
base_type__name_to_size: base_type _Float128
class__fixup_btf_bitfields: unknown base type name "_Float128"!
base_type__name_to_size: base_type _Float128
class__fixup_btf_bitfields: unknown base type name "_Float128"!
base_type__name_to_size: base_type _Float128
class__fixup_btf_bitfields: unknown base type name "_Float128"!
base_type__name_to_size: base_type _Float128
class__fixup_btf_bitfields: unknown base type name "_Float128"!
base_type__name_to_size: base_type _Float128
class__fixup_btf_bitfields: unknown base type name "_Float128"!
--- /tmp/btfdiff.dwarf.aV4wSL   2019-02-25 13:31:54.787923673 -0800
+++ /tmp/btfdiff.btf.22NQmJ     2019-02-25 13:31:54.802923668 -0800
@@ -461,9 +461,15 @@ struct La_x86_64_retval {
        uint64_t                   lrv_rdx;              /*     8     8 */
        La_x86_64_xmm              lrv_xmm0;             /*    16    16 */
        La_x86_64_xmm              lrv_xmm1;             /*    32    16 */
-       long double                lrv_st0;              /*    48    16 */
+       long double                lrv_st0;              /*    48     8 */
+
+       /* XXX 8 bytes hole, try to pack */
+
        /* --- cacheline 1 boundary (64 bytes) --- */
-       long double                lrv_st1;              /*    64    16 */
+       long double                lrv_st1;              /*    64     8 */
+
+       /* XXX 8 bytes hole, try to pack */
+
        La_x86_64_vector           lrv_vector0;          /*    80    64 */
        /* --- cacheline 2 boundary (128 bytes) was 16 bytes ago --- */
        La_x86_64_vector           lrv_vector1;          /*   144    64 */
@@ -472,6 +478,7 @@ struct La_x86_64_retval {
        __int128                   lrv_bnd1;             /*   224    16 */

        /* size: 240, cachelines: 4, members: 10 */
+       /* sum members: 224, holes: 2, sum holes: 16 */
        /* last cacheline: 48 bytes */
 };
 struct r_debug {
@@ -2044,7 +2051,7 @@ union ieee754_float {
        } ieee_nan;                                    /*     0     4 */
 };
 union ieee854_long_double {
-       long double                d;                  /*     0    16 */
+       long double                d;                  /*     0     8 */
        struct {
                unsigned int       mantissa1:32;       /*     0: 0  4 */
                unsigned int       mantissa0:32;       /*     4: 0  4 */
@@ -2141,7 +2148,7 @@ struct ucontext_t {
        /* last cacheline: 8 bytes */
 };
 union ieee854_float128 {
-       _Float128                  d;                  /*     0    16 */
+       _Float128                  d;                  /*     0     0 */
        struct {
                unsigned int       mantissa3:32;       /*     0: 0  4 */
                unsigned int       mantissa2:32;       /*     4: 0  4 */
@@ -2219,7 +2226,7 @@ union printf_arg {
        long unsigned int          pa_u_long_int;      /*     0     8 */
        long long unsigned int     pa_u_long_long_int; /*     0     8 */
        double                     pa_double;          /*     0     8 */
-       long double                pa_long_double;     /*     0    16 */
+       long double                pa_long_double;     /*     0     8 */
        const char  *              pa_string;          /*     0     8 */
        const wchar_t  *           pa_wstring;         /*     0     8 */
        void *                     pa_pointer;         /*     0     8 */

$ PAHOLE=~/local/pahole/build/pahole ./btfdiff ~/local/btf/libc-2.28.so.debug
<empty output>

Still good for kernel image:
$ PAHOLE=~/local/pahole/build/pahole ./btfdiff ~/local/btf/vmlinux4
<empty output>

Signed-off-by: Andrii Nakryiko <andriin@xxxxxx>
---
 btf_loader.c | 59 ++++++++++------------------------------------------
 1 file changed, 11 insertions(+), 48 deletions(-)

diff --git a/btf_loader.c b/btf_loader.c
index 62e7e30..3b4fb40 100644
--- a/btf_loader.c
+++ b/btf_loader.c
@@ -463,64 +463,27 @@ static int class__fixup_btf_bitfields(struct tag *tag, struct cu *cu, struct btf
 			continue;
 
 		pos->bitfield_offset = 0;
+		pos->byte_size = tag__size(type, cu);
+		pos->bit_size = pos->byte_size * 8;
 
-		uint16_t type_bit_size;
-		size_t integral_bit_size;
-
-		switch (type->tag) {
-		case DW_TAG_enumeration_type:
-			type_bit_size = tag__type(type)->size;
-			/* Best we can do to check if this is a packed enum */
-			if (is_power_of_2(type_bit_size))
-				integral_bit_size = roundup(type_bit_size, 8);
-			else
-				integral_bit_size = sizeof(int) * 8;
-			break;
-		case DW_TAG_base_type: {
-			struct base_type *bt = tag__base_type(type);
-			char name[256];
-			type_bit_size = bt->bit_size;
-			integral_bit_size = base_type__name_to_size(bt, cu);
-			if (integral_bit_size == 0) {
-				fprintf(stderr, "%s: unknown base type name \"%s\"!\n",
-					__func__, base_type__name(bt, cu, name,
-								  sizeof(name)));
-			}
-		}
-			break;
-		default:
-			pos->byte_size = tag__size(type, cu);
-			pos->bit_size = pos->byte_size * 8;
+		/* bitfield fixup is needed for enums and base types only */
+		if (type->tag != DW_TAG_base_type && type->tag != DW_TAG_enumeration_type)
 			continue;
-		}
 
-		/*
-		 * XXX: integral_bit_size can be zero if base_type__name_to_size doesn't
-		 * know about the base_type name, so one has to add there when
-		 * such base_type isn't found. pahole will put zero on the
-		 * struct output so it should be easy to spot the name when
-		 * such unlikely thing happens.
-		 */
-		pos->byte_size = integral_bit_size / 8;
-		pos->bit_size = type_bit_size;
-
-		if (integral_bit_size == 0) {
-			pos->bit_size = 0;
+		/* if BTF data is incorrect and has size == 0, skip field, 
+		 * instead of crashing */
+		if (pos->byte_size == 0) {
 			continue;
 		}
 
 		if (pos->bitfield_size) {
 			/* bitfields seem to be always aligned, no matter the packing */
-			pos->byte_offset = pos->bit_offset / integral_bit_size * integral_bit_size / 8;
-		} else {
-			pos->byte_offset = pos->bit_offset / 8;
-		}
-
-
-		if (pos->bitfield_size) {
+			pos->byte_offset = pos->bit_offset / pos->bit_size * pos->bit_size / 8;
 			pos->bitfield_offset = pos->bit_offset - pos->byte_offset * 8;
 			if (!btfe->is_big_endian)
-				pos->bitfield_offset = integral_bit_size - pos->bitfield_offset - pos->bitfield_size;
+				pos->bitfield_offset = pos->bit_size - pos->bitfield_offset - pos->bitfield_size;
+		} else {
+			pos->byte_offset = pos->bit_offset / 8;
 		}
 	}
 
-- 
2.17.1




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

  Powered by Linux