Needed to find the right 'struct ftype' to iterate function arguments
on. This is due to how BTF works with this and how we implemented it, at
some point this can get improved to avoid the need for checking if it is
BTF, doing it in a more format abstracted way, but for now, abstract
this away in the for_each_parameter helpers.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
If we have:
inline void process_adjtimex_modes(const struct __kernel_timex * txc, s32 * time_tai)
{
}
And any other struct receiving as a parameter pointers to 'struct
__kerne_timex', then the source file with the above inline, since it
doesn't have any inline expansion, i.e. 'pfunct --compile' generates
just empty function bodies, the types won't be included in the resulting
.o.
Since the original file has the expansions, type types will be there and
thus we will not be able to compare those types, so ask for any 'inline'
to be stripped, so that we keep those types and 'fullcircle' can do its
work.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
/home/acme/git/build/v5.1-rc4+/fs/proc/kcore.o
/tmp/fullcircle.Vnd2oz.c:788:29: error: flexible array member in a struct with no named members
char x[]; /* 0 0 */
Original:
include/linux/mmzone.h, line 109:
/*
* zone->lock and the zone lru_lock are two of the hottest locks in the kernel.
* So add a wild amount of padding here to ensure that they fall into separate
* cachelines. There are very few zone structures in the machine, so space
* consumption is not a concern here.
*/
#if defined(CONFIG_SMP)
struct zone_padding {
char x[0];
} ____cacheline_internodealigned_in_smp;
#define ZONE_PADDING(name) struct zone_padding name;
#else
#define ZONE_PADDING(name)
#endif
B0rken:
struct zone_padding {
char x[]; /* 0 0 */
/* size: 0, cachelines: 0, members: 1 */
} __attribute__((__aligned__(64)));
Fixed:
struct zone_padding {
char x[0]; /* 0 0 */
/* size: 0, cachelines: 0, members: 1 */
} __attribute__((__aligned__(64)));
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Consider:
struct ipc64_perm {
__kernel_key_t key;
__kernel_uid32_t uid;
__kernel_gid32_t gid;
__kernel_uid32_t cuid;
__kernel_gid32_t cgid;
__kernel_mode_t mode;
/* pad if mode_t is u16: */
unsigned char __pad1[4 - sizeof(__kernel_mode_t)];
unsigned short seq;
unsigned short __pad2;
__kernel_ulong_t __unused1;
__kernel_ulong_t __unused2;
};
That is a roundabout way of using __attribute__(__aligned__(4)), but
should work nonetheless.
We were not putting the [0] in that zero sized array which ended up
making gcc complain with:
$ gcc -g -c shm.c
shm.c:199:29: error: flexible array member not at end of struct
unsigned char __pad1[]; /* 24 0 */
^~~~~~
$
Now this works, i.e. generates compilable source code out of the
type tags, be it from BTF or from DWARF, i.e. this is all from the
internal representation of such types, agnostic wrt the original type
format.
So, the full circle:
$ pahole -C ipc64_perm /home/acme/git/build/v5.1-rc4+/ipc/shm.o
struct ipc64_perm {
__kernel_key_t key; /* 0 4 */
__kernel_uid32_t uid; /* 4 4 */
__kernel_gid32_t gid; /* 8 4 */
__kernel_uid32_t cuid; /* 12 4 */
__kernel_gid32_t cgid; /* 16 4 */
__kernel_mode_t mode; /* 20 4 */
unsigned char __pad1[0]; /* 24 0 */
short unsigned int seq; /* 24 2 */
short unsigned int __pad2; /* 26 2 */
/* XXX 4 bytes hole, try to pack */
__kernel_ulong_t __unused1; /* 32 8 */
__kernel_ulong_t __unused2; /* 40 8 */
/* size: 48, cachelines: 1, members: 11 */
/* sum members: 44, holes: 1, sum holes: 4 */
/* last cacheline: 48 bytes */
};
$ pfunct --compile /home/acme/git/build/v5.1-rc4+/ipc/shm.o > shm.c
$ gcc -g -c shm.c
$ pahole -C ipc64_perm shm.o
struct ipc64_perm {
__kernel_key_t key; /* 0 4 */
__kernel_uid32_t uid; /* 4 4 */
__kernel_gid32_t gid; /* 8 4 */
__kernel_uid32_t cuid; /* 12 4 */
__kernel_gid32_t cgid; /* 16 4 */
__kernel_mode_t mode; /* 20 4 */
unsigned char __pad1[0]; /* 24 0 */
short unsigned int seq; /* 24 2 */
short unsigned int __pad2; /* 26 2 */
/* XXX 4 bytes hole, try to pack */
__kernel_ulong_t __unused1; /* 32 8 */
__kernel_ulong_t __unused2; /* 40 8 */
/* size: 48, cachelines: 1, members: 11 */
/* sum members: 44, holes: 1, sum holes: 4 */
/* last cacheline: 48 bytes */
};
$
And for a chuckle, the original source code with a bit of history about
struct layout worries:
include/uapi/asm-generic/ipcbuf.h:
/*
* The generic ipc64_perm structure:
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
* ipc64_perm was originally meant to be architecture specific, but
* everyone just ended up making identical copies without specific
* optimizations, so we may just as well all use the same one.
*
* Pad space is left for:
* - 32-bit mode_t on architectures that only had 16 bit
* - 32-bit seq
* - 2 miscellaneous 32-bit values
*/
struct ipc64_perm {
__kernel_key_t key;
__kernel_uid32_t uid;
__kernel_gid32_t gid;
__kernel_uid32_t cuid;
__kernel_gid32_t cgid;
__kernel_mode_t mode;
/* pad if mode_t is u16: */
unsigned char __pad1[4 - sizeof(__kernel_mode_t)];
unsigned short seq;
unsigned short __pad2;
__kernel_ulong_t __unused1;
__kernel_ulong_t __unused2;
};
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Since we don't have something like DW_AT_alignment for
__attribute__((__packed__)), we need to use whatever hints that are
there in the alignments to figure out if a naturally packed struct has
the __attribute__((packed)) in the original sources, because that is
needed to waiver its natural alignment requisites.
For instance,
/* Used at: btrfs.c */
/* <1e7b> /home/acme/git/pahole/btrfs.c:199 */
struct btrfs_block_group_cache {
struct btrfs_key key; /* 0 17 */
struct btrfs_block_group_item item; /* 17 24 */
/* XXX 7 bytes hole, try to pack */
struct btrfs_fs_info * fs_info; /* 48 8 */
struct inode * inode; /* 56 8 */
In the original source code, btrfs_block_group_item is marked
__packed__, and being so, even seemingly unnecessarily, makes it, when
embedded in another struct, like the above, forfeit its natural
alingment, that would be 8 bytes, and instead appear right at the 17th
byte offset...
struct btrfs_block_group_item {
__le64 used; /* 0 8 */
__le64 chunk_objectid; /* 8 8 */
__le64 flags; /* 16 8 */
/* size: 24, cachelines: 1, members: 3 */
/* last cacheline: 24 bytes */
} __attribute__((__packed__));
So we need to, seeing its use at a unnatural offset, go backwards to the
btrfs_block_group_item pahole internal data structure, 'struct type' and
mark is_packed field as 'true', despite it not looking like a packed
struct.
Same thing with:
struct ieee80211_mcs_info {
u8 rx_mask[10]; /* 0 10 */
__le16 rx_highest; /* 10 2 */
u8 tx_params; /* 12 1 */
u8 reserved[3]; /* 13 3 */
/* size: 16, cachelines: 1, members: 4 */
/* last cacheline: 16 bytes */
};
That is naturally aligned and as 16 bytes, a power of two, then when it appears at the end of:
$ pahole -IC ieee80211_sta_ht_cap vht.o
/* Used at: vht.c */
/* <31ea> /home/acme/git/pahole/vht.c:1769 */
struct ieee80211_sta_ht_cap {
u16 cap; /* 0 2 */
bool ht_supported; /* 2 1 */
u8 ampdu_factor; /* 3 1 */
u8 ampdu_density; /* 4 1 */
/* XXX 1 byte hole, try to pack */
struct ieee80211_mcs_info mcs; /* 6 16 */
/* size: 22, cachelines: 1, members: 5 */
/* sum members: 21, holes: 1, sum holes: 1 */
/* last cacheline: 22 bytes */
};
$
We get that one byte hole if ieee80211_mcs_info isn't marked __packed__, as soon as we mark it:
$ pahole -IC ieee80211_sta_ht_cap vht.o
/* Used at: vht.c */
/* <31ea> /home/acme/git/pahole/vht.c:1769 */
struct ieee80211_sta_ht_cap {
u16 cap; /* 0 2 */
bool ht_supported; /* 2 1 */
u8 ampdu_factor; /* 3 1 */
u8 ampdu_density; /* 4 1 */
struct ieee80211_mcs_info mcs; /* 5 16 */
/* size: 22, cachelines: 1, members: 5 */
/* padding: 1 */
/* last cacheline: 22 bytes */
};
[acme@quaco pahole]$
It works, so __packed__ in this case just says: trow away the natural
alignment, make it 1 in whatever container structs.
So, before emitting the types for some struct, we go back looking at
each of its members and checking for such unnatural offsets, marking the
types as __packed__. Now:
$ pfunct --compile /home/acme/git/build/v5.1-rc4+/net/mac80211/vht.o | grep "^struct ieee80211_mcs_info" -A8
struct ieee80211_mcs_info {
u8 rx_mask[10]; /* 0 10 */
__le16 rx_highest; /* 10 2 */
u8 tx_params; /* 12 1 */
u8 reserved[3]; /* 13 3 */
/* size: 16, cachelines: 1, members: 4 */
/* last cacheline: 16 bytes */
} __attribute__((__packed__));
$
$ pfunct --compile /home/acme/git/build/v5.1-rc4+/fs/btrfs/free-space-tree.o | grep "^struct btrfs_block_group_item" -A7
struct btrfs_block_group_item {
__le64 used; /* 0 8 */
__le64 chunk_objectid; /* 8 8 */
__le64 flags; /* 16 8 */
/* size: 24, cachelines: 1, members: 3 */
/* last cacheline: 24 bytes */
} __attribute__((__packed__));
$
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
We use things like DW_AT_alignment, so not all of those attributes are
inferred by formats like BTF that lack that info, allow suppressing the
output and make btfdiff ask for both DWARF and BTF output to have this
suppressed.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For instance, DWARF has DW_AT_alignment, and some output features
require that, so let loaders advertise such things, next patch will use
this info.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Will be used when considering comparing multiple CU entries in a struct
cus to the sole compile unit in a second file, like when comparing the
types in a multi-CU DWARF file like vmlinux against the combined,
deduplicated entries in that vmlinux .BTF section.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
For the usual idiom to ask if a tag is a pointer, removing a bit of
DWARFism and shortening the operation.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
So that we can use it in things like btfdiff.
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Wielaard <mark@klomp.org>
Cc: Yonghong Song <yhs@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
pahole --reorganize heavily depends on member's bit_hole and hole fields
to denote bit/byte holes *after* member. Previous commit "dwarves: use
bit sizes and bit/byte hole info in __class__fprintf" changed its
meaning to bit/byte hole *before* member to accomodate possible bit/byte
holes at the beginning of a struct. This change broke reorganization
algorithm, though, which is quite involved and isn't trivially
modifiable to accomodate new semantics.
This patch reverts the meaning of bit_hole and hole, but also introduces
per class pre_bit_hole/pre_hole to record initial bit/byte hole of a
struct. This allows to fix reorg code more easily and still handle
initial holes cases, if at the expense of being not as elegant.
Committer testing:
$ time pahole -F btf --packable vmlinux | sort -nr -k4 | head
bts_ctx 12288 8192 4096
swsusp_info 4096 432 3664
vc_data 792 496 296
pci_dev 2488 2320 168
rcu_state 3392 3240 152
ptr_ring 192 40 152
xdp_sock 960 840 120
zone 1664 1552 112
rcu_data 576 472 104
rcu_node 576 480 96
real 0m0.038s
user 0m0.029s
sys 0m0.017s
$
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This patch records for each CU whether it's in little-endian or
big-endian data format. This flag will be used in subsequent commits to
adjust bit offsets where necessary, to make them uniform across
endianness. This patch doesn't have any effect on pahole's output.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Mark Wielaard <mark@klomp.org>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
With BTF dedup we end up with a CU with all the types, and with
something like an allmodconfig vmlinux image it ends up with more than
65535 types, so use uint32_t for the type IDs to accomodate that.
Reported-by: Andrii Nakryiko <andriin@fb.com>
Tested-by:Andrii Nakryiko <andrii.nakryiko@gmail.com>
Link: https://lore.kernel.org/bpf/CAEf4Bzb0SpvXdDKMMnUof==kp4Y0AP54bKFjeCzX_AsmDm7k7g@mail.gmail.com/
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
the CTF and BTF loaders come already with the id to use, while the DWARF
loader comes with a Dwarf_Off that needs to be converted into the
ptr_table index.
So keep the cu__add_tag(cu, tag, &id) method to ask ask for the index to
be allocated in the ptr_table and the result to come back via the 'id'
parameter, now a uint32_t and introduce a cu__add_tag_with_id(cu, tag, id)
method to indicate that the 'uint32_t id' is the one to use.
With this we can use a uint32_t for the id both on 32-bit and 64-bit
arches.
Reported-by: Andrii Nakryiko <andriin@fb.com>
Tested-by:Andrii Nakryiko <andrii.nakryiko@gmail.com>
Link: https://lore.kernel.org/bpf/CAEf4Bzb0SpvXdDKMMnUof==kp4Y0AP54bKFjeCzX_AsmDm7k7g@mail.gmail.com/
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The dwarves class_member field bitfield_offset represents the dwarf tag
DW_AT_bit_offset. For dwarf2, this field can be negative for little
endian for bitfields in packed data structures which cross type
boundary.
-bash-4.4$ cat bitfield.c
struct packed {
char x1: 1;
char x2: 3;
char x3: 3;
int y1: 7;
int y2: 20;
} __attribute__((packed));
struct packed g;
-bash-4.4$ gcc -O2 -c -g bitfield.c
-bash-4.4$ pahole -JV bitfield.o
File bitfield.o:
[1] STRUCT packed kind_flag=1 size=5 vlen=5
x1 type_id=2 bitfield_size=1 bits_offset=0
x2 type_id=2 bitfield_size=3 bits_offset=1
x3 type_id=2 bitfield_size=3 bits_offset=4
y1 type_id=3 bitfield_size=7 bits_offset=7
y2 type_id=3 bitfield_size=255 bits_offset=16776974
[2] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
[3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
-bash-4.4$
The above large negative bits_offset and bitfield_size=255 results from
negative bitfield_offset which is interpreted as positive value in btf
encoding.
With this fix, the pahole works properly for BTF:
-bash-4.4$ pahole -JV bitfield.o
File bitfield.o:
[1] STRUCT packed kind_flag=1 size=5 vlen=5
x1 type_id=2 bitfield_size=1 bits_offset=0
x2 type_id=2 bitfield_size=3 bits_offset=1
x3 type_id=2 bitfield_size=3 bits_offset=4
y1 type_id=3 bitfield_size=7 bits_offset=7
y2 type_id=3 bitfield_size=20 bits_offset=14
[2] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
[3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
-bash-4.4$
Note that change bitfield_offset from uint8_t to int8_t is safe as the
maximum int type we support is __int128 and maximum bitfield_offset is
127.
Signed-off-by: Yonghong Song <yhs@fb.com>
Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: dwarves@vger.kernel.org
Link: https://www.spinics.net/lists/dwarves/msg00199.html
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Commit 2a82d593be ("btf: Add kind_flag support for btf_loader") added
kind_flag supported in btf_loader to get correct bitfield_size and
bit_offset for struct/union members. The commit unnecessarily stored
the bit in the structure type which is not used later.
So let us remove the kind_flag from the struct type and any other
changes whose purpose is to set this bit.
Signed-off-by: Yonghong Song <yhs@fb.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Fixes: 2a82d593be ("btf: Add kind_flag support for btf_loader")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Martin KaFai Lau <kafai@fb.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This patch fixed two issues with BTF. One is related to struct/union
bitfield encoding and the other is related to forward type.
Issue #1 and solution:
======================
Current btf encoding of bitfield follows what pahole generates.
For each bitfield, pahole will duplicate the type chain and
put the bitfield size at the final int or enum type.
Since the BTF enum type cannot encode bit size,
commit b18354f64c ("btf: Generate correct struct bitfield
member types") workarounds the issue by generating
an int type whenever the enum bit size is not 32.
The above workaround is not ideal as we lost original type
in BTF. Another undesiable fact is the type duplication
as the pahole duplicates the type chain.
To fix this issue, this patch implemented a compatible
change for BTF struct type encoding:
. the bit 31 of type->info, previously reserved,
now is used to indicate whether bitfield_size is
encoded in btf_member or not.
. if bit 31 of struct_type->info is set,
btf_member->offset will encode like:
bit 0 - 23: bit offset
bit 24 - 31: bitfield size
if bit 31 is not set, the old behavior is preserved:
bit 0 - 31: bit offset
So if the struct contains a bit field, the maximum bit offset
will be reduced to (2^24 - 1) instead of MAX_UINT. The maximum
bitfield size will be 255 which is enough for today as maximum
bitfield in compiler can be 128 where int128 type is supported.
A new global, no_bitfield_type_recode, is introduced and which
will be set to true if BTF encoding is enabled. This global
will prevent pahole duplicating the bitfield types to avoid
type duplication in BTF.
Issue #2 and solution:
======================
Current forward type in BTF does not specify whether the original
type is struct or union. This will not work for type pretty print
and BTF-to-header-file conversion as struct/union must be specified.
To fix this issue, similar to issue #1, type->info bit 31
is used. If the bit is set, it is union type. Otherwise, it is
a struct type.
Examples:
=========
-bash-4.4$ cat t.c
struct s;
union u;
typedef int ___int;
enum A { A1, A2, A3 };
struct t {
int a[5];
___int b:4;
volatile enum A c:4;
struct s *p1;
union u *p2;
} g;
-bash-4.4$ gcc -c -O2 -g t.c
Without this patch:
$ pahole -JV t.o
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t size=40 vlen=5
a type_id=5 bits_offset=0
b type_id=13 bits_offset=160
c type_id=15 bits_offset=164
p1 type_id=9 bits_offset=192
p2 type_id=11 bits_offset=256
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
[8] FWD s type_id=0
[9] PTR (anon) type_id=8
[10] FWD u type_id=0
[11] PTR (anon) type_id=10
[12] INT int size=1 bit_offset=0 nr_bits=4 encoding=(none)
[13] TYPEDEF ___int type_id=12
[14] INT (anon) size=1 bit_offset=0 nr_bits=4 encoding=SIGNED
[15] VOLATILE (anon) type_id=14
With this patch:
$ pahole -JV t.o
File t.o:
[1] TYPEDEF ___int type_id=2
[2] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED
[3] ENUM A size=4 vlen=3
A1 val=0
A2 val=1
A3 val=2
[4] STRUCT t kind_flag=1 size=40 vlen=5
a type_id=5 bitfield_size=0 bits_offset=0
b type_id=1 bitfield_size=4 bits_offset=160
c type_id=7 bitfield_size=4 bits_offset=164
p1 type_id=9 bitfield_size=0 bits_offset=192
p2 type_id=11 bitfield_size=0 bits_offset=256
[5] ARRAY (anon) type_id=2 index_type_id=2 nr_elems=5
[6] INT sizetype size=8 bit_offset=0 nr_bits=64 encoding=(none)
[7] VOLATILE (anon) type_id=3
[8] FWD s struct
[9] PTR (anon) type_id=8
[10] FWD u union
[11] PTR (anon) type_id=10
The fix removed the type duplication, preserved the enum type for the
bitfield, and have correct struct/union information for the forward
type.
Signed-off-by: Yonghong Song <yhs@fb.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Since tools like 'pahole' now shows unions in addition to structs.
Cc: Matthew Wilcox <willy@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
The pahole tool initial goal was to show struct holes, which can't
happen with a first level of a tagged union (a union with a name),
so those only were displayed when part of a higher level struct.
Show the first level tagged enums as well, as this is useful when just
wanting to see its members.
E.g.:
$ pahole ../build/v4.20-rc5/net/core/sock.o | grep ^union
union fpregs_state {
union irq_stack_union {
union sigval {
union __sifields {
union thread_union {
union kernfs_node_id {
union flowi_uli {
union ethtool_flow_union {
union key_payload {
union bpf_attr {
union tcp_md5_addr {
$
Suggested-by: Matthew Wilcox <willy@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This is DWARF specific, we don't have in CTF, AFAIK, info about where a
variable is put, i.e. in a register? in the stack? etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
We'll use location in the DWARF sense, i.e. location lists, etc, i.e.
where is this variable? In a register? The stack? etc.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Take 'struct task_struct' in the Linux kernel, these fields:
/* --- cacheline 2 boundary (128 bytes) --- */
struct sched_entity se; /* 128 448 */
/* XXX last struct has 24 bytes of padding */
/* --- cacheline 9 boundary (576 bytes) --- */
struct sched_rt_entity rt; /* 576 48 */
The sched_entity struct has 24 bytes of padding, and that info would
only appear when printing 'struct task_struct' if class__find_holes()
had previously been run on 'struct sched_entity' which wasn't always the
case, make sure that happens.
This results in this extra stat being printed for 'struct task_struct':
/* paddings: 4, sum paddings: 38 */
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
A diff for 'pahole -EC task_struct vmlinux' should clarify what this fixes:
[acme@jouet linux]$ diff -u /tmp/before.c /tmp/after.c | head -30
--- /tmp/before.c 2016-06-29 17:00:38.082647281 -0300
+++ /tmp/a.c 2016-06-29 17:03:36.913124779 -0300
@@ -43,8 +43,8 @@
struct list_head * prev; /* 176 8 */
} group_node; /* 168 16 */
unsigned int on_rq; /* 184 4 */
+ /* --- cacheline 3 boundary (192 bytes) --- */
/* typedef u64 */ long long unsigned int exec_start; /* 192 8 */
- /* --- cacheline 1 boundary (64 bytes) was 4 bytes ago --- */
/* typedef u64 */ long long unsigned int sum_exec_runtime; /* 200 8 */
/* typedef u64 */ long long unsigned int vruntime; /* 208 8 */
/* typedef u64 */ long long unsigned int prev_sum_exec_runtime; /* 216 8 */
@@ -53,40 +53,40 @@
/* typedef u64 */ long long unsigned int wait_start; /* 232 8 */
/* typedef u64 */ long long unsigned int wait_max; /* 240 8 */
/* typedef u64 */ long long unsigned int wait_count; /* 248 8 */
+ /* --- cacheline 4 boundary (256 bytes) --- */
/* typedef u64 */ long long unsigned int wait_sum; /* 256 8 */
/* typedef u64 */ long long unsigned int iowait_count; /* 264 8 */
/* typedef u64 */ long long unsigned int iowait_sum; /* 272 8 */
/* typedef u64 */ long long unsigned int sleep_start; /* 280 8 */
/* typedef u64 */ long long unsigned int sleep_max; /* 288 8 */
- /* --- cacheline 1 boundary (64 bytes) --- */
/* typedef s64 */ long long int sum_sleep_runtime; /* 296 8 */
/* typedef u64 */ long long unsigned int block_start; /* 304 8 */
/* typedef u64 */ long long unsigned int block_max; /* 312 8 */
+ /* --- cacheline 5 boundary (320 bytes) --- */
/* typedef u64 */ long long unsigned int exec_max; /* 320 8 */
/* typedef u64 */ long long unsigned int slice_max; /* 328 8 */
/* typedef u64 */ long long unsigned int nr_migrations_cold; /* 336 8 */
[acme@jouet linux]$
I.e. the boundary detection was being reset at each expanded struct, do the math globally,
using the member offset, that was already done globally and correctly.
Reported-and-Tested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
That conf_fprintf can be elided as it is always NULL for the root call,
i.e. only when expanding types is that it will be called recursively.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>