From e975ff247aa8be98c0ce895febbaff3d94b9daf3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 28 Jul 2018 14:25:30 -0300 Subject: [PATCH] dwarves_fprintf: Print cacheline boundaries in multiple union members In 'struct audit_context' we have an union that have member structs that straddles cacheline boundaries, the existing logic was showing those cacheline boundaries only for the first struct in the union where that straddling took place, all the subsequent structs where straddling also takes place were not showing it, the struct: struct audit_context { union { struct { int nargs; /* 824 4 */ /* XXX 4 bytes hole, try to pack */ /* --- cacheline 13 boundary (832 bytes) --- */ long int args[6]; /* 832 48 */ } socketcall; /* 824 56 */ struct { kuid_t uid; /* 824 4 */ kgid_t gid; /* 828 4 */ umode_t mode; /* 832 2 */ /* XXX 2 bytes hole, try to pack */ u32 osid; /* 836 4 */ int has_perm; /* 840 4 */ uid_t perm_uid; /* 844 4 */ gid_t perm_gid; /* 848 4 */ umode_t perm_mode; /* 852 2 */ /* XXX 2 bytes hole, try to pack */ long unsigned int qbytes; /* 856 8 */ } ipc; /* 824 40 */ struct { mqd_t mqdes; /* 824 4 */ /* XXX 4 bytes hole, try to pack */ struct mq_attr mqstat; /* 832 64 */ } mq_getsetattr; /* 824 72 */ struct { mqd_t mqdes; /* 824 4 */ int sigev_signo; /* 828 4 */ } mq_notify; /* 824 8 */ struct { mqd_t mqdes; /* 824 4 */ /* XXX 4 bytes hole, try to pack */ size_t msg_len; /* 832 8 */ unsigned int msg_prio; /* 840 4 */ /* XXX 4 bytes hole, try to pack */ struct timespec64 abs_timeout; /* 848 16 */ } mq_sendrecv; /* 824 40 */ struct { int oflag; /* 824 4 */ umode_t mode; /* 828 2 */ /* XXX 2 bytes hole, try to pack */ struct mq_attr attr; /* 832 64 */ } mq_open; /* 824 72 */ struct { pid_t pid; /* 824 4 */ struct audit_cap_data cap; /* 828 32 */ } capset; /* 824 36 */ struct { int fd; /* 824 4 */ int flags; /* 828 4 */ } mmap; /* 824 8 */ struct { int argc; /* 824 4 */ } execve; /* 824 4 */ struct { char * name; /* 824 8 */ } module; /* 824 8 */ }; /* 824 72 */ /* --- cacheline 14 boundary (896 bytes) --- */ int fds[2]; /* 896 8 */ struct audit_proctitle proctitle; /* 904 16 */ /* size: 920, cachelines: 15, members: 46 */ /* sum members: 912, holes: 2, sum holes: 8 */ /* last cacheline: 24 bytes */ }; With this fix: struct audit_context { union { struct { int nargs; /* 824 4 */ /* XXX 4 bytes hole, try to pack */ /* --- cacheline 13 boundary (832 bytes) --- */ long int args[6]; /* 832 48 */ } socketcall; /* 824 56 */ struct { kuid_t uid; /* 824 4 */ kgid_t gid; /* 828 4 */ /* --- cacheline 13 boundary (832 bytes) --- */ umode_t mode; /* 832 2 */ /* XXX 2 bytes hole, try to pack */ u32 osid; /* 836 4 */ int has_perm; /* 840 4 */ uid_t perm_uid; /* 844 4 */ gid_t perm_gid; /* 848 4 */ umode_t perm_mode; /* 852 2 */ /* XXX 2 bytes hole, try to pack */ long unsigned int qbytes; /* 856 8 */ } ipc; /* 824 40 */ struct { mqd_t mqdes; /* 824 4 */ /* XXX 4 bytes hole, try to pack */ /* --- cacheline 13 boundary (832 bytes) --- */ struct mq_attr mqstat; /* 832 64 */ } mq_getsetattr; /* 824 72 */ struct { mqd_t mqdes; /* 824 4 */ int sigev_signo; /* 828 4 */ } mq_notify; /* 824 8 */ struct { mqd_t mqdes; /* 824 4 */ /* XXX 4 bytes hole, try to pack */ /* --- cacheline 13 boundary (832 bytes) --- */ size_t msg_len; /* 832 8 */ unsigned int msg_prio; /* 840 4 */ /* XXX 4 bytes hole, try to pack */ struct timespec64 abs_timeout; /* 848 16 */ } mq_sendrecv; /* 824 40 */ struct { int oflag; /* 824 4 */ umode_t mode; /* 828 2 */ /* XXX 2 bytes hole, try to pack */ /* --- cacheline 13 boundary (832 bytes) --- */ struct mq_attr attr; /* 832 64 */ } mq_open; /* 824 72 */ struct { pid_t pid; /* 824 4 */ struct audit_cap_data cap; /* 828 32 */ } capset; /* 824 36 */ struct { int fd; /* 824 4 */ int flags; /* 828 4 */ } mmap; /* 824 8 */ struct { int argc; /* 824 4 */ } execve; /* 824 4 */ struct { char * name; /* 824 8 */ } module; /* 824 8 */ }; /* 824 72 */ /* --- cacheline 14 boundary (896 bytes) --- */ int fds[2]; /* 896 8 */ struct audit_proctitle proctitle; /* 904 16 */ /* size: 920, cachelines: 15, members: 46 */ /* sum members: 912, holes: 2, sum holes: 8 */ /* last cacheline: 24 bytes */ }; Signed-off-by: Arnaldo Carvalho de Melo --- dwarves_fprintf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c index 40d326b..2164c9e 100644 --- a/dwarves_fprintf.c +++ b/dwarves_fprintf.c @@ -827,6 +827,7 @@ static size_t union__fprintf(struct type *type, const struct cu *cu, size_t printed = 0; int indent = conf->indent; struct conf_fprintf uconf; + uint32_t initial_union_cacheline; if (indent >= (int)sizeof(tabs)) indent = sizeof(tabs) - 1; @@ -838,6 +839,12 @@ static size_t union__fprintf(struct type *type, const struct cu *cu, uconf = *conf; uconf.indent = indent + 1; + /* + * Save the cacheline we're in, then, after each union member, get + * back to it. Else we'll end up showing cacheline boundaries in + * just the first of a multi struct union, for instance. + */ + initial_union_cacheline = *uconf.cachelinep; type__for_each_member(type, pos) { struct tag *type = cu__type(cu, pos->tag.type); @@ -851,6 +858,7 @@ static size_t union__fprintf(struct type *type, const struct cu *cu, printed += union_member__fprintf(pos, type, cu, &uconf, fp); fputc('\n', fp); ++printed; + *uconf.cachelinep = initial_union_cacheline; } return printed + fprintf(fp, "%.*s}%s%s", indent, tabs,