fprintf: Notice explicit bitfield alignment modifications
I.e. when we find that the last member has a bit_hole, i.e. it is part of a bitfield, and the current field has a bitfield_size, i.e. it _also_ is part of a bitfield, the only explanation is that they were artificially put in different base types, i.e. like in these fields in the linux kernel 'struct task_struct', here reconstructed by pahole: $ pahole -C task_struct ~/git/build/v5.1-rc2+/kernel/sched/core.o | grep :0 -B9 -A12 unsigned int personality; /* 1128 4 */ unsigned int sched_reset_on_fork:1; /* 1132: 0 4 */ unsigned int sched_contributes_to_load:1; /* 1132: 1 4 */ unsigned int sched_migrated:1; /* 1132: 2 4 */ unsigned int sched_remote_wakeup:1; /* 1132: 3 4 */ /* XXX 28 bits hole, try to pack */ /* Force alignment to the next boundary: */ unsigned int :0; unsigned int in_execve:1; /* 1136: 0 4 */ unsigned int in_iowait:1; /* 1136: 1 4 */ unsigned int restore_sigmask:1; /* 1136: 2 4 */ unsigned int in_user_fault:1; /* 1136: 3 4 */ unsigned int no_cgroup_migration:1; /* 1136: 4 4 */ unsigned int use_memdelay:1; /* 1136: 5 4 */ /* XXX 26 bits hole, try to pack */ /* XXX 4 bytes hole, try to pack */ long unsigned int atomic_flags; /* 1144 8 */ $ This matches the original definition in the original kernel sources, and further more, the following sequence proves that with this and DW_AT_alignment, we can go full circle, i.e.: 1. from an object file reconstruct the source code for all the types that appears in function signatures, if pointers, them they will be fully defined, not just forward declared: $ pfunct --compile=sched_change_group ~/git/build/v5.1-rc2+/kernel/sched/core.o | egrep -w 'sched_change_group|task_struct {' -B10 -A5 /* --- cacheline 3 boundary (192 bytes) --- */ struct fpu fpu __attribute__((__aligned__(64))); /* 192 4160 */ /* size: 4352, cachelines: 68, members: 21 */ /* sum members: 4316, holes: 2, sum holes: 32 */ /* sum bitfield members: 2 bits, bit holes: 1, sum bit holes: 30 bits */ /* forced alignments: 1, forced holes: 1, sum forced holes: 28 */ }; struct task_struct { struct thread_info thread_info; /* 0 16 */ /* XXX last struct has 4 bytes of padding */ volatile long int state; /* 16 8 */ -- /* --- cacheline 104 boundary (6656 bytes) --- */ struct thread_struct thread __attribute__((__aligned__(64))); /* 6656 4352 */ /* size: 11008, cachelines: 172, members: 207 */ /* sum members: 10902, holes: 16, sum holes: 98 */ /* sum bitfield members: 10 bits, bit holes: 2, sum bit holes: 54 bits */ /* paddings: 3, sum paddings: 14 */ /* forced alignments: 6, forced holes: 1, sum forced holes: 40 */ }; void sched_change_group(struct task_struct * tsk, int type) { } $ 2. Build the regenerated skeleton function + its types: $ pfunct --compile=sched_change_group ~/git/build/v5.1-rc2+/kernel/sched/core.o > sched_change_group.c $ gcc -g -c sched_change_group.c $ file sched_change_group.o sched_change_group.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), with debug_info, not stripped $ 3. Now lets see if the original 'struct task_struct' printed by pahole, matches the the output printed by pahole for the DWARF info generated for the regenerated 'struct task_struct' source code in sched_change_group.c: $ pahole -C task_struct sched_change_group.o | tail /* --- cacheline 104 boundary (6656 bytes) --- */ struct thread_struct thread __attribute__((__aligned__(64))); /* 6656 4352 */ /* size: 11008, cachelines: 172, members: 207 */ /* sum members: 10902, holes: 16, sum holes: 98 */ /* sum bitfield members: 10 bits, bit holes: 2, sum bit holes: 54 bits */ /* paddings: 3, sum paddings: 14 */ /* forced alignments: 6, forced holes: 1, sum forced holes: 40 */ }; $ pahole -C task_struct ~/git/build/v5.1-rc2+/kernel/sched/core.o | tail /* --- cacheline 104 boundary (6656 bytes) --- */ struct thread_struct thread __attribute__((__aligned__(64))); /* 6656 4352 */ /* size: 11008, cachelines: 172, members: 207 */ /* sum members: 10902, holes: 16, sum holes: 98 */ /* sum bitfield members: 10 bits, bit holes: 2, sum bit holes: 54 bits */ /* paddings: 3, sum paddings: 14 */ /* forced alignments: 6, forced holes: 1, sum forced holes: 40 */ }; $ Furthermore: $ pahole -C task_struct ~/git/build/v5.1-rc2+/kernel/sched/core.o > /tmp/original $ pahole -C task_struct sched_change_group.o > /tmp/regenerated $ diff -u /tmp/original /tmp/regenerated $ So one of the most complex data structures in the Linux kernel seems to be under control, and it uses zero sized unnamed bitfields and __attribute__((aligned(N))), a DWARF5 goodie, time to go tag v1.13! Cc: Alexei Starovoitov <ast@fb.com> Cc: Andrii Nakryiko <andriin@fb.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Yonghong Song <yhs@fb.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
75f32a24c7
commit
a104eb1ea1
|
@ -1361,6 +1361,19 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
|
|||
* all over the place.
|
||||
*/
|
||||
last_size != 0) {
|
||||
if (last->bit_hole != 0 && pos->bitfield_size) {
|
||||
type = cu__type(cu, pos->tag.type);
|
||||
if (type == NULL) {
|
||||
printed += fprintf(fp, "%.*s", cconf.indent, tabs);
|
||||
printed += tag__id_not_found_fprintf(fp, pos->tag.type);
|
||||
continue;
|
||||
}
|
||||
printed += fprintf(fp, "\n%.*s/* Force alignment to the next boundary: */\n", cconf.indent, tabs);
|
||||
printed += fprintf(fp, "%.*s", cconf.indent, tabs);
|
||||
printed += type__fprintf(type, cu, "", &cconf, fp);
|
||||
printed += fprintf(fp, ":0;\n");
|
||||
}
|
||||
|
||||
if (pos->byte_offset < last->byte_offset ||
|
||||
(pos->byte_offset == last->byte_offset &&
|
||||
last->bitfield_size == 0 &&
|
||||
|
|
Loading…
Reference in New Issue