diff options
author | Douglas Raillard <douglas.raillard@arm.com> | 2021-10-19 11:07:24 +0100 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2021-12-07 14:55:16 -0300 |
commit | 005236c3e40eeb64f352dcb710ca6bffabf7f3b2 (patch) | |
tree | 6f6a77e504bbb299d8f225214094a9660ad9cb6f | |
parent | 7c5e35b63bd26f1de0a22acb6319bf2b1a4166c1 (diff) | |
download | pahole-005236c3e40eeb64f352dcb710ca6bffabf7f3b2.tar.gz |
pahole: Add --inner_anon option
Allow making the inner struct/enum/union anonymous. This permits using
the header to inspect pointer values using -E, without having to care
about avoiding duplicate type definitions such as:
struct foo { ... };
struct bar {
struct foo {
....
} a;
};
With --inner_anon, the conflict between the two definitions of struct
foo is gone:
struct foo { ... };
struct bar {
struct {
....
} a;
};
Committer testing:
$ cat inner_anon.c
struct foo {
int a;
char b;
};
struct bar {
struct foo c;
int d;
} bla;
$ gcc -g -c inner_anon.c -o inner_anon.o
No expansion:
$ pahole inner_anon.o
struct foo {
int a; /* 0 4 */
char b; /* 4 1 */
/* size: 8, cachelines: 1, members: 2 */
/* padding: 3 */
/* last cacheline: 8 bytes */
};
struct bar {
struct foo c; /* 0 8 */
/* XXX last struct has 3 bytes of padding */
int d; /* 8 4 */
/* size: 12, cachelines: 1, members: 2 */
/* paddings: 1, sum paddings: 3 */
/* last cacheline: 12 bytes */
};
Expanding types:
$ pahole -E inner_anon.o
struct foo {
int a; /* 0 4 */
char b; /* 4 1 */
/* size: 8, cachelines: 1, members: 2 */
/* padding: 3 */
/* last cacheline: 8 bytes */
};
struct bar {
struct foo {
int a; /* 0 4 */
char b; /* 4 1 */
}c; /* 0 8 */
/* XXX last struct has 3 bytes of padding */
int d; /* 8 4 */
/* size: 12, cachelines: 1, members: 2 */
/* paddings: 1, sum paddings: 3 */
/* last cacheline: 12 bytes */
};
Anonymising the inner struct:
$ pahole -E --inner_anon inner_anon.o
struct foo {
int a; /* 0 4 */
char b; /* 4 1 */
/* size: 8, cachelines: 1, members: 2 */
/* padding: 3 */
/* last cacheline: 8 bytes */
};
struct bar {
struct /* foo */ {
int a; /* 0 4 */
char b; /* 4 1 */
}c; /* 0 8 */
/* XXX last struct has 3 bytes of padding */
int d; /* 8 4 */
/* size: 12, cachelines: 1, members: 2 */
/* paddings: 1, sum paddings: 3 */
/* last cacheline: 12 bytes */
};
Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
[ Added man page entry for --inner_anon, refreshed the patch to cope with the btf_tag series ]
Link: https://lore.kernel.org/all/20211019100724.325570-3-douglas.raillard@arm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | man-pages/pahole.1 | 7 | ||||
-rw-r--r-- | pahole.c | 8 |
2 files changed, 15 insertions, 0 deletions
diff --git a/man-pages/pahole.1 b/man-pages/pahole.1 index c1ec63e4..f81a2965 100644 --- a/man-pages/pahole.1 +++ b/man-pages/pahole.1 @@ -123,6 +123,13 @@ Expand class members. Useful to find in what member of inner structs where an offset from the beginning of a struct is. .TP +.B \-\-inner_anon +Allow making inner structs, enums and unions anonymous, so that when using -E +to expand types we don't end up with multiple definitions for the expanded +inner structs/enums/unions, allowing the resulting expanded struct to be +compilable. + +.TP .B \-F, \-\-format_path Allows specifying a list of debugging formats to try, in order. Right now this includes "ctf" and "dwarf". The default format path used is equivalent to @@ -1127,6 +1127,7 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version; #define ARGP_skip_encoding_btf_decl_tag 331 #define ARGP_skip_missing 332 #define ARGP_skip_encoding_btf_type_tag 333 +#define ARGP_inner_anon 334 static const struct argp_option pahole__options[] = { { @@ -1235,6 +1236,11 @@ static const struct argp_option pahole__options[] = { .doc = "expand class members", }, { + .name = "inner_anon", + .key = ARGP_inner_anon, + .doc = "expanded class members are anonymous", + }, + { .name = "nr_members", .key = 'n', .doc = "show number of members", @@ -1666,6 +1672,8 @@ static error_t pahole__options_parser(int key, char *arg, conf_load.skip_missing = true; break; case ARGP_skip_encoding_btf_type_tag: conf_load.skip_encoding_btf_type_tag = true; break; + case ARGP_inner_anon: + conf.inner_anonymous = true; break; default: return ARGP_ERR_UNKNOWN; } |