Commit Graph

135 Commits

Author SHA1 Message Date
Alibek Omarov 0c09533dfc fprintf: preserve conf_fprintf pointer in tag__ptr_name
This fixes the use of classes_as_structs and probably other options, when
fprintf meets a pointer/reference type.

Signed-off-by: Alibek Omarov <a1ba.omarov@gmail.com>
2022-04-18 21:49:39 +03:00
Arnaldo Carvalho de Melo 32cc148172 fprintf: Consider enumerations without members as forward declarations
To avoid emitting:

  enum x86_intercept_stage {
  };

Which isn't compilable.

The DWARF info for this enum in the Linux kernel has the declaration
flag set, but somehow this is not being available when loading from BTF.

So do the best we can at this enumeration__fprintf() time, that is to
just print zero members enumerations as a forward declaration.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2022-02-03 11:30:34 -03:00
Arnaldo Carvalho de Melo 49a2dd6577 fprintf: Check if conf->conf_fprintf is not NULL in when resolving cacheline_size
There are tools that don't set conf_load->conf_fprintf, like codiff, so
check for that in dwarves__resolve_cacheline_size().

Cc: Douglas Raillard <douglas.raillard@arm.com>
Fixes: 772725a77d ("dwarves_fprintf: Move cacheline_size into struct conf_fprintf")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2022-02-02 17:20:00 -03:00
Arnaldo Carvalho de Melo 46cec35ff0 fprintf: Fix division by zero for uninitialized conf_fprintf->cacheline_size field
tldr;

  gdb pfunct
  (gdb) run --compile tcp.o
  Program received signal SIGFPE, Arithmetic exception.
  0x00007ffff7f18551 in class__fprintf_cacheline_boundary (conf=0x7fffffffda10, offset=0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1319
  1319		uint32_t cacheline = offset / conf->cacheline_size;
  (gdb) bt
  #0  0x00007ffff7f18551 in class__fprintf_cacheline_boundary (conf=0x7fffffffda10, offset=0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1319
  #1  0x00007ffff7f16af2 in class_member__fprintf (member=0x45de10, union_member=false, type=0x45dfb0, cu=0x435a40, conf=0x7fffffffda10, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:869
  #2  0x00007ffff7f1717b in struct_member__fprintf (member=0x45de10, type=0x45dfb0, cu=0x435a40, conf=0x7fffffffda10, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:983
  #3  0x00007ffff7f1945c in __class__fprintf (class=0x45dcc0, cu=0x435a40, conf=0x7fffffffdbb0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1583
  #4  0x00007ffff7f1a6bd in tag__fprintf (tag=0x45dcc0, cu=0x435a40, conf=0x7fffffffdc70, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_fprintf.c:1906
  #5  0x00007ffff7fbf022 in type__emit (tag=0x45dcc0, cu=0x435a40, prefix=0x0, suffix=0x0, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:333
  #6  0x00007ffff7fbed3d in tag__emit_definitions (tag=0x6b21e0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:265
  #7  0x00007ffff7fbef45 in type__emit_definitions (tag=0x6b20c0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:315
  #8  0x00007ffff7fbed15 in tag__emit_definitions (tag=0x6b3b40, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:264
  #9  0x00007ffff7fbef45 in type__emit_definitions (tag=0x6b31d0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:315
  #10 0x00007ffff7fbed15 in tag__emit_definitions (tag=0x4cb920, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:264
  #11 0x00007ffff7fbef45 in type__emit_definitions (tag=0x4cb7d0, cu=0x435a40, emissions=0x408300 <emissions>, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/dwarves_emit.c:315
  #12 0x0000000000403592 in function__emit_type_definitions (func=0x738ad0, cu=0x435a40, fp=0x7ffff7e17520 <_IO_2_1_stdout_>) at /var/home/acme/git/pahole/pfunct.c:353
  #13 0x0000000000403670 in function__show (func=0x738ad0, cu=0x435a40) at /var/home/acme/git/pahole/pfunct.c:371
  #14 0x00000000004038e9 in cu_function_iterator (cu=0x435a40, cookie=0x0) at /var/home/acme/git/pahole/pfunct.c:404
  #15 0x00007ffff7f1296b in cus__for_each_cu (cus=0x4369e0, iterator=0x403869 <cu_function_iterator>, cookie=0x0, filter=0x0) at /var/home/acme/git/pahole/dwarves.c:1919
  #16 0x000000000040432a in main (argc=3, argv=0x7fffffffe1f8) at /var/home/acme/git/pahole/pfunct.c:776
  (gdb) p conf->cacheline_size
  $2 = 0

We need to pass a conf_fprintf pointer to the chain starting with
function__emit_type_definitions(), i.e. dwarves_emit.c needs to receive
the printing configuration instead of, right at type__emit() synthesize
a conf_fprintf without initializing conf_fprintf->cacheline_size which
ends up in a division by zero.

But to fix this quicker just add a helper that checks if it is zero and
uses the conf_fprintf__defaults.cacheline_size field that is being
initialized by all tools via:

  dwarves__resolve_cacheline_size(&conf_load, 0);

Fixes: 772725a77d ("dwarves_fprintf: Move cacheline_size into struct conf_fprintf")
Cc: Douglas Raillard <douglas.raillard@arm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2022-01-28 17:24:30 -03:00
Douglas RAILLARD 54ae2f7f5e Revert "fprintf: Allow making struct/enum/union anonymous"
This reverts commit 7c5e35b63b.

Dropped since it could not cope with recursive types. A new attempt will
be made on 1.24.

Signed-off-by: Douglas RAILLARD <douglas.raillard@arm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-12-08 08:52:51 -03:00
Douglas Raillard 7c5e35b63b fprintf: Allow making struct/enum/union anonymous
Allow making inner struct enums and union anonymous, so that when using
-E to expand types we don't end up with multiple definitions for
expanded inner structs, allowing the resulting expanded struct to be
compilable.

Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
[ Applied it manually to cover some fuzz due to other patches ]
Link: https://lore.kernel.org/all/20211019100724.325570-2-douglas.raillard@arm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-11-26 15:36:44 -03:00
Arnaldo Carvalho de Melo 433dc780ca fprintf: Add DWARF5 tags added in elfutils 0.170
Now we know what that 0x4a thing is:

  $ pahole ~/c/split/foo.o
  die__process: DW_TAG_compile_unit, DW_TAG_type_unit or DW_TAG_partial_unit expected got skeleton_unit (0x4a)!
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-11-12 15:16:51 -03:00
Douglas Raillard 772725a77d dwarves_fprintf: Move cacheline_size into struct conf_fprintf
Remove the global variable and turn it into a member in struct
conf_fprintf, so that it can be used by other parts of the code.

Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-10-28 10:17:59 -03:00
Arnaldo Carvalho de Melo 43e8216c25 fprintf: Fix __attribute__((__aligned__(N)) handling for struct members
We just need to record if we printed it for a member and if so, deduce
that from the number of spaces left to print before the end of line
comment (offset, size).

Fixes: a59459bb80 ("fprintf: Account inline type __aligned__ member types for spacing")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-10-27 15:44:10 -03:00
Douglas Raillard 6931e393f8 fprintf: Fix nested struct printing wrt attributes
This code:

    struct X {
       struct {
       } __attribute__((foo)) x __attribute__((bar));
    }

Was wrongly printed as:

    struct X {
       struct {
       } x __attribute__((foo)) __attribute__((bar));
    }

This unfortunately matters a lot, since "bar" is suppose to apply to
"x", but "foo" to typeof(x). In the wrong form, both apply to "x",
leading to e.g. incorrect layout for __aligned__ attribute.

Signed-off-by: Douglas Raillard <douglas.raillard@arm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-10-26 11:29:55 -03:00
Arnaldo Carvalho de Melo 9f9588dc2b fprintf: Add alternative method for reading the data cacheline size
Systems such as Alpine Linux don't have support for obtaining _SC_LEVEL1_DCACHE_LINESIZE
via sysconf(), provide altenative method reading it from sysfs.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-20 16:40:27 -03:00
Arnaldo Carvalho de Melo 0c5bf70cc1 fprintf: class__vtable_fprintf() doesn't need a 'cu' arg
Another simplification made possible by using a plain char string
instead of string_t, that was only needed in the core as prep work
for CTF encoding.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:41:13 -03:00
Arnaldo Carvalho de Melo 38ff86b149 fprintf: string_type__fprintf() doesn't need a 'cu' arg
Another simplification made possible by using a plain char string
instead of string_t, that was only needed in the core as prep work
for CTF encoding.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:41:13 -03:00
Arnaldo Carvalho de Melo 80fe32fd29 core: variable__name() doesn't need a 'cu' arg
Another simplification made possible by using a plain char string
instead of string_t, that was only needed in the core as prep work
for CTF encoding.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:41:13 -03:00
Arnaldo Carvalho de Melo caa219dffc core: base_type__name() doesn't need a 'cu' arg
Another simplification made possible by using a plain char string
instead of string_t, that was only needed in the core as prep work
for CTF encoding.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:41:13 -03:00
Arnaldo Carvalho de Melo 9d0e3ab9a2 pahole: function__name() doesn't need a 'struct cu *' argument
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo b5694280ec core: Make label->name a real string
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.

The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo 0947d6e795 core: enumeration__fprintf() doesn't need a 'cu' argument
With the conversion of ->name members to plain char strings, no need
to use 'cu' to get the old string_t index and find the per-cu string
table.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo bb22f5bb0a core: Make enumeration__max_entry_name_len() static
As it is not used outside where it is defined.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo dc83336171 core: enumeration__max_entry_name_len() doesn't need a 'cu' argument
With the conversion of ->name members to plain char strings, no need
to use 'cu' to get the old string_t index and find the per-cu string
table.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo 96243fdd79 core: enumerator__name() doesn't need a 'cu' argument, ditch it
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo c127d25daf core: class__name() doesn't need a cu arg
Now that namespace->name is a real char string.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo 00e8c5fe21 core: type__name() doesn't need a cu arg
Now that namespace->name is a real char string.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo b99c4008ac core: Make namespace->name a real string
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.

The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.

For the namespace->name case we get the bonus of removing another
user of dwarves__active_loader.

This covers unions, enums, structs and classes.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo 379a73c6eb core: Make class_member->name a real string
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.

The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.

For the class_member->name case we get the bonus of removing another
user of dwarves__active_loader.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo 3280cb4176 core: Make parameter->name a real string
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.

The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.

For the parameter->name case we get the bonus of removing a user of
dwarves__active_loader.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-08-12 09:39:46 -03:00
Arnaldo Carvalho de Melo 4f73cac853 core: Make function->linkage_name a real string
For the threaded code we want to access strings in tags at the same time
that the string table may grow in another thread making the previous
pointer invalid, so, to avoid excessive locking, use plain strings.

The way the tools work will either consume the just produced CU straight
away or keep just one copy of each data structure when we keep all CUs
in memory, so lets try stopping using strings_t for strings.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-07-28 15:18:16 -03:00
Arnaldo Carvalho de Melo bf74fc1fcf core: Introduce helper to return if there is no cu entries in a 'struct cus'
Provide a helper so that we can make 'struct cus' opaque.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-07-28 15:18:16 -03:00
Arnaldo Carvalho de Melo 5b0fb9745e codiff: Fix usage of negative errno values with strerror(), reported by covscan
Error: NEGATIVE_RETURNS (CWE-394):
  dwarves-1.21/codiff.c:816: negative_return_fn: Function "cus__load_file(old_cus, &conf_load, old_filename)" returns a negative number.
  dwarves-1.21/codiff.c:816: assign: Assigning: "err" = "cus__load_file(old_cus, &conf_load, old_filename)".
  dwarves-1.21/codiff.c:818: negative_returns: "err" is passed to a parameter that cannot be negative.
  #  816|                 err = cus__load_file(old_cus, &conf_load, old_filename);
  #  817|                 if (err != 0) {
  #  818|->                       cus__print_error_msg("codiff", old_cus, old_filename, err);
  #  819|                         goto out_cus_delete_priv;
  #  820|                 }

  Error: NEGATIVE_RETURNS (CWE-394):
  dwarves-1.21/codiff.c:830: negative_return_fn: Function "cus__load_file(new_cus, &conf_load, new_filename)" returns a negative number.
  dwarves-1.21/codiff.c:830: assign: Assigning: "err" = "cus__load_file(new_cus, &conf_load, new_filename)".
  dwarves-1.21/codiff.c:832: negative_returns: "err" is passed to a parameter that cannot be negative.
  #  830|                 err = cus__load_file(new_cus, &conf_load, new_filename);
  #  831|                 if (err != 0) {
  #  832|->                       cus__print_error_msg("codiff", new_cus, new_filename, err);
  #  833|                         goto out_cus_delete_priv;
  #  834|                 }

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-05-27 11:00:18 -03:00
Arnaldo Carvalho de Melo 4b7f8c04d0 fprintf: Honour conf_fprintf.hex when printing enumerations
Now this works:

  $ pahole --hex perf_event_type
  enum perf_event_type {
  	PERF_RECORD_MMAP            = 0x1,
  	PERF_RECORD_LOST            = 0x2,
  	PERF_RECORD_COMM            = 0x3,
  	PERF_RECORD_EXIT            = 0x4,
  	PERF_RECORD_THROTTLE        = 0x5,
  	PERF_RECORD_UNTHROTTLE      = 0x6,
  	PERF_RECORD_FORK            = 0x7,
  	PERF_RECORD_READ            = 0x8,
  	PERF_RECORD_SAMPLE          = 0x9,
  	PERF_RECORD_MMAP2           = 0xa,
  	PERF_RECORD_AUX             = 0xb,
  	PERF_RECORD_ITRACE_START    = 0xc,
  	PERF_RECORD_LOST_SAMPLES    = 0xd,
  	PERF_RECORD_SWITCH          = 0xe,
  	PERF_RECORD_SWITCH_CPU_WIDE = 0xf,
  	PERF_RECORD_NAMESPACES      = 0x10,
  	PERF_RECORD_KSYMBOL         = 0x11,
  	PERF_RECORD_BPF_EVENT       = 0x12,
  	PERF_RECORD_CGROUP          = 0x13,
  	PERF_RECORD_TEXT_POKE       = 0x14,
  	PERF_RECORD_MAX             = 0x15,
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2021-02-20 08:41:11 -03:00
Arnaldo Carvalho de Melo bf21da4075 fprintf: Make typedef__fprintf print anonymous enums
In all the examples the kernel BTF info is being used (/sys/kernel/btf/vmlinux).

Before:

  $ pahole ZSTD_strategy
  typedef enum  ZSTD_strategy;
  $

After:

  $ pahole ZSTD_strategy
  typedef enum {
  	ZSTD_fast    = 0,
  	ZSTD_dfast   = 1,
  	ZSTD_greedy  = 2,
  	ZSTD_lazy    = 3,
  	ZSTD_lazy2   = 4,
  	ZSTD_btlazy2 = 5,
  	ZSTD_btopt   = 6,
  	ZSTD_btopt2  = 7,
  } ZSTD_strategy;
  $

Named ones continue to work as before:

  $ pahole timespec_type
  enum timespec_type {
  	TT_NONE   = 0,
  	TT_NATIVE = 1,
  	TT_COMPAT = 2,
  };
  $

And the ones inside structs, when expanded, as well:

  $ pahole ZSTD_parameters
  typedef struct {
  	ZSTD_compressionParameters cParams;              /*     0    28 */
  	ZSTD_frameParameters       fParams;              /*    28    12 */

  	/* size: 40, cachelines: 1, members: 2 */
  	/* last cacheline: 40 bytes */
  } ZSTD_parameters;
  $ pahole -E ZSTD_parameters
  typedef struct {
  	/* typedef ZSTD_compressionParameters */ struct {
  		unsigned int       windowLog;                                            /*     0     4 */
  		unsigned int       chainLog;                                             /*     4     4 */
  		unsigned int       hashLog;                                              /*     8     4 */
  		unsigned int       searchLog;                                            /*    12     4 */
  		unsigned int       searchLength;                                         /*    16     4 */
  		unsigned int       targetLength;                                         /*    20     4 */
  		/* typedef ZSTD_strategy */ enum {
  			ZSTD_fast    = 0,
  			ZSTD_dfast   = 1,
  			ZSTD_greedy  = 2,
  			ZSTD_lazy    = 3,
  			ZSTD_lazy2   = 4,
  			ZSTD_btlazy2 = 5,
  			ZSTD_btopt   = 6,
  			ZSTD_btopt2  = 7,
  		} strategy; /*    24     4 */
  	} cParams; /*     0    28 */
  	/* typedef ZSTD_frameParameters */ struct {
  		unsigned int       contentSizeFlag;                                      /*    28     4 */
  		unsigned int       checksumFlag;                                         /*    32     4 */
  		unsigned int       noDictIDFlag;                                         /*    36     4 */
  	} fParams; /*    28    12 */

  	/* size: 40, cachelines: 1, members: 2 */
  	/* last cacheline: 40 bytes */
  } ZSTD_parameters;
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 11:41:18 -03:00
Arnaldo Carvalho de Melo 9c4bdf9331 fprintf: Align enumerators
$ pahole timespec_type
  enum timespec_type {
  	TT_NONE   = 0,
  	TT_NATIVE = 1,
  	TT_COMPAT = 2,
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 11:36:20 -03:00
Arnaldo Carvalho de Melo 89cf28228a fprintf: Add enumeration__max_entry_name_len()
Cache the results, will be used when pretty printing enumerations, to
align the entries.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 11:25:47 -03:00
Arnaldo Carvalho de Melo 932b84eb45 fprintf: Make typedef__fprintf print anonymous structs
For instance, the Dwarf_Op typedef was found but since it is an
anonymous struct we get:

  $ pahole -C Dwarf_Op build/pahole
  typedef struct  Dwarf_Op;
  $

Which is not useful, fix it:

  $ pahole -C Dwarf_Op build/pahole
  typedef struct {
  	uint8_t                    atom;                 /*     0     1 */

  	/* XXX 7 bytes hole, try to pack */

  	Dwarf_Word                 number;               /*     8     8 */
  	Dwarf_Word                 number2;              /*    16     8 */
  	Dwarf_Word                 offset;               /*    24     8 */

  	/* size: 32, cachelines: 1, members: 4 */
  	/* sum members: 25, holes: 1, sum holes: 7 */
  	/* last cacheline: 32 bytes */
  } Dwarf_Op;
  $

Reported-by: Matthias Schwarzott <zzam@gentoo.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-11-19 10:32:00 -03:00
Arnaldo Carvalho de Melo f5847773d9 fprintf: Support DW_TAG_string_type
We don't really reconstruct source code for FORTRAN, we just print it as
if it was C:

  $ pahole examples/fortran95/derived-type.debug
  struct bar {
  	integer(kind=4)            c;                    /*     0     4 */
  	real(kind=4)               d;                    /*     4     4 */

  	/* size: 8, cachelines: 1, members: 2 */
  	/* last cacheline: 8 bytes */
  };
  struct foo {
  	real(kind=4)               a;                    /*     0     4 */
  	struct bar                 x;                    /*     4     8 */
  	string                     b[7];                 /*    12     7 */

  	/* size: 20, cachelines: 1, members: 3 */
  	/* padding: 1 */
  	/* last cacheline: 20 bytes */
  };
  $

This comes from GCC build tests:

  $ readelf -wi examples/fortran95/derived-type.debug | grep Fortran -A2
      <9c>   DW_AT_producer    : (indirect string, offset: 0x1fb): GNU Fortran2008 10.2.1 20200728 [revision c0438ced53bcf57e4ebb1c38c226e41571aca892] -mtune=generic -march=x86-64 -g -fno-stack-protector -J /home/vries/gdb_versions/devel/build/gdb/testsuite/outputs/gdb.fortran/derived-type -fintrinsic-modules-path /usr/lib64/gcc/x86_64-suse-linux/10/finclude -fpre-include=/usr/include/finclude/math-vector-fortran.h
      <a0>   DW_AT_language    : 14     (Fortran 95)
      <a1>   DW_AT_identifier_case: 2   (down_case)
      <a2>   DW_AT_name        : (indirect string, offset: 0x365): /home/vries/gdb_versions/devel/src/gdb/testsuite/gdb.fortran/derived-type.f90
  [acme@five pahole]$ readelf -wi examples/fortran95/derived-type.debug | grep DW_TAG_string_type -A2
   <1><122>: Abbrev Number: 6 (DW_TAG_string_type)
      <123>   DW_AT_byte_size   : 7
  $

Now lets see whats more that is there segfaulting pahole, but for now I
think I don't have any segfaults, so just wait a bit for Hao to submit
the patch to selectively encode the per-cpu variables in BTF and then
cut v1.18.

Reported-by: Tom de Vries
Bugtracker: https://github.com/acmel/dwarves/issues/9
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-09-18 18:19:22 -03:00
Arnaldo Carvalho de Melo ae43029363 dwarves_fprintf: Export the 'tabs' variable
Will be used by pahole's pretty printer to handle nested structs.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2020-08-05 15:16:19 -03:00
Arnaldo Carvalho de Melo 1bc63a4cff fprintf: Fixup truncation possibility pointed out by gcc -O2
Addresses this warning:

  [ 26%] Building C object CMakeFiles/dwarves.dir/dwarves_fprintf.c.o
  /home/acme/git/pahole/dwarves_fprintf.c: In function ‘type__fprintf’:
  /home/acme/git/pahole/dwarves_fprintf.c:709:47: error: ‘%s’ directive output may be truncated writing up to 257 bytes into a region of size 256 [-Werror=format-truncation=]
    709 |     snprintf(namebfptr, sizeof(namebfptr), "* %s", name);
        |                                               ^~
  /home/acme/git/pahole/dwarves_fprintf.c:709:5: note: ‘snprintf’ output between 3 and 260 bytes into a destination of size 258
    709 |     snprintf(namebfptr, sizeof(namebfptr), "* %s", name);
        |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-16 11:19:47 -03:00
Arnaldo Carvalho de Melo 644466dce7 fprintf: Remove extraneous sizeof operator
That was affecting --suppress_aligned_attribute, detected using the
'btfdiff' utility, that uses pahole with DWARF and BTF and compares
their outputs, and since we don't have this in BTF, we use
--suppress_aligned_attribute with '-F dwarf'.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-12-13 11:35:13 -03:00
Arnaldo Carvalho de Melo a59459bb80 fprintf: Account inline type __aligned__ member types for spacing
Fixing things like that anonymous union offset/size comment
misalignment:

          union {
                  refcount_t         rcu_users;            /*  2568     4 */
                  struct callback_head rcu __attribute__((__aligned__(8))); /*  2568    16 */
  -       } __attribute__((__aligned__(8)));                                               /*  2568    16 */
  +       } __attribute__((__aligned__(8)));               /*  2568    16 */
          struct pipe_inode_info *   splice_pipe;          /*  2584     8 */
          struct page_frag           task_frag;            /*  2592    16 */
          struct task_delay_info *   delays;               /*  2608     8 */

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-19 12:23:00 -03:00
Arnaldo Carvalho de Melo 56547f133a fprintf: Fix alignment of class members that are structs/enums/unions
E.g. look at that 'completion' member in this struct:

   struct cpu_stop_done {
          atomic_t                   nr_todo;              /*     0     4 */
          int                        ret;                  /*     4     4 */
  -       struct completion  completion;                   /*     8    32 */
  +       struct completion          completion;           /*     8    32 */

          /* size: 40, cachelines: 1, members: 3 */
          /* last cacheline: 40 bytes */

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-19 11:48:36 -03:00
Arnaldo Carvalho de Melo ccf3eebfcd btf_loader: Add support for BTF_KIND_FUNC
Some changes to the fprintf routines were needed, as BTF has as the
function type just a BTF_KIND_FUNC_PROTO, while DWARF has as the type
for a function its return value type. With a function->btf flag this was
overcome and all the other goodies in pfunct are present, for instance:

  $ pahole -JV examples/tcp.o | grep -w FUNC | head
  [4068] FUNC tcp_init type_id=4067
  [4070] FUNC tcp_abort type_id=4069
  [4072] FUNC tcp_done type_id=4071
  [4074] FUNC tcp_md5_hash_key type_id=4073
  [4076] FUNC tcp_md5_hash_skb_data type_id=4075
  [4078] FUNC tcp_get_md5sig_pool type_id=4077
  [4080] FUNC tcp_alloc_md5sig_pool type_id=4079
  [4082] FUNC compat_tcp_getsockopt type_id=4081
  [4084] FUNC tcp_getsockopt type_id=4083
  [4086] FUNC tcp_get_timestamping_opt_stats type_id=4085
  $

  $ pfunct -F btf examples/tcp.o  | head
  memset
  memcpy
  tcp_enter_memory_pressure
  tcp_leave_memory_pressure
  tcp_init_sock
  tcp_init_transfer
  tcp_poll
  tcp_ioctl
  tcp_splice_read
  sk_stream_alloc_skb
  $

  $ pfunct --prototype -F btf examples/tcp.o | head
  void * memset(void * p, int c, __kernel_size_t size);
  void * memcpy(void * p, const void  * q, __kernel_size_t size);
  void tcp_enter_memory_pressure(struct sock * sk);
  void tcp_leave_memory_pressure(struct sock * sk);
  void tcp_init_sock(struct sock * sk);
  void tcp_init_transfer(struct sock * sk, int bpf_op);
  __poll_t tcp_poll(struct file * file, struct socket * sock, poll_table * wait);
  int tcp_ioctl(struct sock * sk, int cmd, long unsigned int arg);
  ssize_t tcp_splice_read(struct socket * sock, loff_t * ppos, struct pipe_inode_info * pipe, size_t len, unsigned int flags);
  struct sk_buff * sk_stream_alloc_skb(struct sock * sk, int size, gfp_t gfp, bool force_schedule);
  $

Now to ask just for the 'struct sock' 'methods', i.e. functions that
have as one of its arguments a pointer to the given 'class' name:

  $ pfunct --class sock -F btf examples/tcp.o | head
  tcp_abort
  tcp_done
  compat_tcp_getsockopt
  tcp_getsockopt
  tcp_get_info
  compat_tcp_setsockopt
  tcp_setsockopt
  tcp_disconnect
  tcp_write_queue_purge
  tcp_close
  $

Then ask for the prototypes, which requires -V, should have that fixed:

  $ pfunct -V --prototypes --class sock -F btf examples/tcp.o | head
  int tcp_abort(struct sock * sk, int err);
  void tcp_done(struct sock * sk);
  int compat_tcp_getsockopt(struct sock * sk, int level, int optname, char * optval, int * optlen);
  int tcp_getsockopt(struct sock * sk, int level, int optname, char * optval, int * optlen);
  void tcp_get_info(struct sock * sk, struct tcp_info * info);
  int compat_tcp_setsockopt(struct sock * sk, int level, int optname, char * optval, unsigned int optlen);
  int tcp_setsockopt(struct sock * sk, int level, int optname, char * optval, unsigned int optlen);
  int tcp_disconnect(struct sock * sk, int flags);
  void tcp_write_queue_purge(struct sock * sk);
  void tcp_close(struct sock * sk, long int timeout);
  $

Don't like prototypes with parm names, got you covered:

  $ pfunct --no_parm_names -V --prototypes --class sock -F btf examples/tcp.o | head
  int tcp_abort(struct sock *, int);
  void tcp_done(struct sock *);
  int compat_tcp_getsockopt(struct sock *, int, int, char *, int *);
  int tcp_getsockopt(struct sock *, int, int, char *, int *);
  void tcp_get_info(struct sock *, struct tcp_info *);
  int compat_tcp_setsockopt(struct sock *, int, int, char *, unsigned int);
  int tcp_setsockopt(struct sock *, int, int, char *, unsigned int);
  int tcp_disconnect(struct sock *, int);
  void tcp_write_queue_purge(struct sock *);
  void tcp_close(struct sock *, long int);
  $

Don't like long options and want just one function?

  $ pfunct -f tcp_setsockopt -F btf examples/tcp.o
  int tcp_setsockopt(struct sock * sk, int level, int optname, char * optval, unsigned int optlen);
  $

Want to generate compileable code for all of those functions, full with
the necessary types, etc?

  $ pfunct -F btf --compile examples/tcp.o  > a.c
  $ gcc -c -o a.o a.c
  $ pfunct -F dwarf --prototypes --class sock a.o | head
  pfunct: a.o: No debugging information found
  $ gcc -g -c -o a.o a.c
  $ pfunct -V -F dwarf --prototypes --class sock a.o | head
  void tcp_enter_memory_pressure(struct sock * sk);
  void tcp_leave_memory_pressure(struct sock * sk);
  void tcp_init_sock(struct sock * sk);
  void tcp_init_transfer(struct sock * sk, int bpf_op);
  int tcp_ioctl(struct sock * sk, int cmd, long unsigned int arg);
  struct sk_buff * sk_stream_alloc_skb(struct sock * sk, int size, gfp_t gfp, bool force_schedule);
  ssize_t do_tcp_sendpages(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage_locked(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendmsg_locked(struct sock * sk, struct msghdr * msg, size_t size);
  $

Now lets go full circle and encode BTF for this a.o generated from
source code generated from the original BTF info in that examples/tcp.o
file:

  $ pahole -JV a.o | tail
  [465] FUNC_PROTO (anon) return=35 args=(392 hp, 393 skb, 5 header_len)
  [466] FUNC tcp_md5_hash_skb_data type_id=465
  [467] FUNC_PROTO (anon) return=35 args=(392 hp, 394 key)
  [468] FUNC tcp_md5_hash_key type_id=467
  [469] FUNC_PROTO (anon) return=0 args=(49 sk)
  [470] FUNC tcp_done type_id=469
  [471] FUNC_PROTO (anon) return=35 args=(49 sk, 35 err)
  [472] FUNC tcp_abort type_id=471
  [473] FUNC_PROTO (anon) return=0 args=(void)
  [474] FUNC tcp_init type_id=473
  $

  $ pfunct -F btf -V --prototypes --class=sock a.o | head
  void tcp_enter_memory_pressure(struct sock * sk);
  void tcp_leave_memory_pressure(struct sock * sk);
  void tcp_init_sock(struct sock * sk);
  void tcp_init_transfer(struct sock * sk, int bpf_op);
  int tcp_ioctl(struct sock * sk, int cmd, long unsigned int arg);
  struct sk_buff * sk_stream_alloc_skb(struct sock * sk, int size, gfp_t gfp, bool force_schedule);
  ssize_t do_tcp_sendpages(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage_locked(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendpage(struct sock * sk, struct page * page, int offset, size_t size, int flags);
  int tcp_sendmsg_locked(struct sock * sk, struct msghdr * msg, size_t size);
  $

Curious about the code generated by 'pfunct -F btf --compile examples/tcp.o?

  http://vger.kernel.org/~acme/pahole/pfunct-F-BTF--compile-examples-tcp.o.txt

Cc: Alexei Starovoitov <ast@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.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>
2019-11-05 12:04:23 -03:00
Arnaldo Carvalho de Melo 3e8f09e304 pdwtags: Print DW_TAG_subroutine_type as well
So that we can see at least via pdwtags those tags, be it from DWARF of
BTF.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 10:16:25 -03:00
Arnaldo Carvalho de Melo d5e01d10e5 fprintf: Set tconf.type_spacing earlier
As there are cases where we jump to the type not found label without
having done the full copy of *conf to tconf, so at least the
type_spacing needs to have been set.

This addresses this coverity report entry:

  Error: UNINIT (CWE-457): [#def23]
  dwarves-1.13/dwarves_fprintf.c:600: var_decl: Declaring variable "tconf" without initializer.
  dwarves-1.13/dwarves_fprintf.c:779: uninit_use_in_call: Using uninitialized value "tconf.type_spacing" when calling "fprintf".
  #  777|   	return printed;
  #  778|   out_type_not_found:
  #  779|-> 	printed = fprintf(fp, "%-*s %s", tconf.type_spacing, "<ERROR>", name);
  #  780|   	goto out;
  #  781|   }

Reported-by: William Cohen <wcohen@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 16:28:50 -03:00
Arnaldo Carvalho de Melo c6a9a0eb6a fprintf: Fix up decrementing recursivity level in type__fprintf()
In some exit paths we were accessing tconf before we had copied it from
conf, and we also were losing track of the original type that could have
been expanded and where we bumped the recursivity level member, so just
store that original type and if it is set, decrement its recursivity
level.

This addresses these coverity report entries:

  Error: UNINIT (CWE-457): [#def21]
  dwarves-1.13/dwarves_fprintf.c:600: var_decl: Declaring variable "tconf" without initializer.
  dwarves-1.13/dwarves_fprintf.c:774: uninit_use: Using uninitialized value "tconf.expand_types".
  #  772|   	}
  #  773|   out:
  #  774|-> 	if (tconf.expand_types)
  #  775|   		--type->recursivity_level;
  #  776|

  Error: FORWARD_NULL (CWE-476): [#def22]
  dwarves-1.13/dwarves_fprintf.c:605: var_compare_op: Comparing "type" to null implies that "type" might be null.
  dwarves-1.13/dwarves_fprintf.c:775: var_deref_op: Dereferencing null pointer "type".
  #  773|   out:
  #  774|   	if (tconf.expand_types)
  #  775|-> 		--type->recursivity_level;
  #  776|
  #  777|   	return printed;

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: f84bf73d54 ("dwarves: Move the fprintf code to a new source file.")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 16:22:49 -03:00
Arnaldo Carvalho de Melo f67c281f98 fprintf: Correct the type for the 'cacheline' variable, it should be uint32_t
[ 22%] Building C object CMakeFiles/dwarves.dir/dwarves_fprintf.c.o
  /home/acme/git/pahole/dwarves_fprintf.c: In function ‘union__fprintf’:
  /home/acme/git/pahole/dwarves_fprintf.c:963:34: error: pointer targets in assignment from ‘int *’ to ‘uint32_t *’ {aka ‘unsigned int *’} differ in signedness [-Werror=pointer-sign]
                   uconf.cachelinep = &cacheline;
                                    ^
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:11:27 -03:00
Arnaldo Carvalho de Melo 7b36fab5a8 fprintf: Add guard against unlikely overlapping copy
In cf459ca16f ("fprintf: Pretty print struct members that are pointers
to nameless structs") I added some recursive logic that theoretically
may end up doing an overlapping copy as reported by coverity:

  Error: OVERLAPPING_COPY: [#def19]
  dwarves-1.13/dwarves_fprintf.c:707: assign: Assigning: "name" = "namebfptr".
  dwarves-1.13/dwarves_fprintf.c:705: equal: "name" is equal to the address of "namebfptr".
  dwarves-1.13/dwarves_fprintf.c:705: overlapping_copy: In the call to function "snprintf", the arguments "name" and "namebfptr" may point to the same object.
  #  703|   			if (tag__is_struct(ptype) || tag__is_union(ptype) ||
  #  704|   			    tag__is_enumeration(ptype)) {
  #  705|-> 				snprintf(namebfptr, sizeof(namebfptr), "* %s", name);
  #  706|   				tconf.rel_offset = 1;
  #  707|

Look at cf459ca16f to see what this is about, but for now I'm just
checking if this is the case and adding a guard, at some point I'll
address this properly to allow for pointers to pointers to nameless
struct/union/enums.

Reported-by: William Cohen <wcohen@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:09:45 -03:00
Arnaldo Carvalho de Melo e737976c09 fprintf: Do not scrub type when looking up its type
As we end up goto'ing to a place where we need that original type and
were having just a NULL pointer, oops, fix it.

Related to:

  Error: NULL_RETURNS (CWE-476): [#def18]
  dwarves-1.13/dwarves_fprintf.c:727: returned_null: "cu__type" returns "NULL" (checked 54 out of 62 times).
  dwarves-1.13/dwarves_fprintf.c:727: var_assigned: Assigning: "type" = "NULL" return value from "cu__type".
  dwarves-1.13/dwarves_fprintf.c:686: dereference: Dereferencing "type", which is known to be "NULL".
  dwarves-1.13/codiff.c:137: example_assign: Example 1: Assigning: "old_type" = return value from "cu__type(old_cu, old->tag.type)".
  dwarves-1.13/codiff.c:141: example_checked: Example 1 (cont.): "old_type" has its value checked in "old_type == NULL".
  dwarves-1.13/ctracer.c:356: example_assign: Example 2: Assigning: "type" = return value from "cu__type(cu, tag->type)".
  dwarves-1.13/ctracer.c:358: example_checked: Example 2 (cont.): "type" has its value checked in "type == NULL".
  dwarves-1.13/dwarves.c:914: example_assign: Example 3: Assigning: "type" = return value from "cu__type(cu, tag->type)".
  dwarves-1.13/dwarves.c:916: example_checked: Example 3 (cont.): "type" has its value checked in "type == NULL".
  dwarves-1.13/dwarves.c:941: example_assign: Example 4: Assigning: "tag" = return value from "cu__type(cu, var->ip.tag.type)".
  dwarves-1.13/dwarves.c:942: example_checked: Example 4 (cont.): "tag" has its value checked in "tag != NULL".
  dwarves-1.13/dwarves_emit.c:139: example_assign: Example 5: Assigning: "ptr_type" = return value from "cu__type(cu, type->type)".
  dwarves-1.13/dwarves_emit.c:141: example_checked: Example 5 (cont.): "ptr_type" has its value checked in "ptr_type == NULL".
  #  684|
  #  685|   next_type:
  #  686|-> 	switch (type->tag) {
  #  687|   	case DW_TAG_pointer_type:
  #  688|

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 568dae4bd4 ("printf: Fixup printing "const" early with "const void"")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 10:42:52 -03:00
Arnaldo Carvalho de Melo e95dacb704 fprintf: Remove unused printf arg when printing enumerations
A cut'n'paste error, noticed by coverity:

  Error: PRINTF_ARGS: [#def16]
  dwarves-1.13/dwarves_fprintf.c:369: extra_argument: This argument was not used by the format string: "conf->suffix". [Note: The source code implementation of the function has been overridden by a builtin model.]
  #  367|   	 */
  #  368|   	if (type->size / 8 != sizeof(int))
  #  369|-> 		printed += fprintf(fp, " __attribute__((__packed__))", conf->suffix);
  #  370|
  #  371|   	if (conf->suffix)

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 28a3bc7add ("fprintf: Support packed enums")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 10:29:49 -03:00
Arnaldo Carvalho de Melo b1412a88bb fprintf: Fixup handling classes with no members
Will Cohen reported this NULL pointer dereference while processing some
object linking with cuda:

  #0  0x00007ffff7f91453 in __class__fprintf (class=0x522560, cu=0x40ff80, conf=0x7fffffffa930, fp=0x7ffff7ece780 <_IO_2_1_stdout_>)
      at /home/acme/git/pahole/dwarves_fprintf.c:1624
  #1  0x00007ffff7f92195 in tag__fprintf (tag=0x522560, cu=0x40ff80, conf=0x7fffffffa930, fp=0x7ffff7ece780 <_IO_2_1_stdout_>)
      at /home/acme/git/pahole/dwarves_fprintf.c:1835
  #2  0x00007ffff7f90b57 in __class__fprintf (class=0x5224c0, cu=0x40ff80, conf=0x7fffffffaaa0, fp=0x7ffff7ece780 <_IO_2_1_stdout_>)
      at /home/acme/git/pahole/dwarves_fprintf.c:1406
  #3  0x00007ffff7f92195 in tag__fprintf (tag=0x5224c0, cu=0x40ff80, conf=0x40a200 <conf>, fp=0x7ffff7ece780 <_IO_2_1_stdout_>)
      at /home/acme/git/pahole/dwarves_fprintf.c:1835
  #4  0x0000000000402d03 in class_formatter (class=0x5224c0, cu=0x40ff80, id=1257) at /home/acme/git/pahole/pahole.c:224
  #5  0x0000000000403074 in print_classes (cu=0x40ff80) at /home/acme/git/pahole/pahole.c:319
  #6  0x0000000000404bb2 in pahole_stealer (cu=0x40ff80, conf_load=0x40a240 <conf_load>) at /home/acme/git/pahole/pahole.c:1174
  #7  0x00007ffff7f9ff73 in finalize_cu (cus=0x40b2b0, cu=0x40ff80, dcu=0x7fffffffacf0, conf=0x40a240 <conf_load>)
      at /home/acme/git/pahole/dwarf_loader.c:2227
  #8  0x00007ffff7f9ffac in finalize_cu_immediately (cus=0x40b2b0, cu=0x40ff80, dcu=0x7fffffffacf0, conf=0x40a240 <conf_load>)
      at /home/acme/git/pahole/dwarf_loader.c:2236
  #9  0x00007ffff7fa064c in cus__load_module (cus=0x40b2b0, conf=0x40a240 <conf_load>, mod=0x40d760, dw=0x40e980, elf=0x40b360,
      filename=0x7fffffffd5e3 "examples/wcohen/02_Exercise.cuda") at /home/acme/git/pahole/dwarf_loader.c:2389
  #10 0x00007ffff7fa0760 in cus__process_dwflmod (dwflmod=0x40d760, userdata=0x40d770, name=0x40d910 "examples/wcohen/02_Exercise.cuda",
      base=4194304, arg=0x7fffffffcf10) at /home/acme/git/pahole/dwarf_loader.c:2434
  #11 0x00007ffff7f32be1 in dwfl_getmodules () from /lib64/libdw.so.1
  #12 0x00007ffff7fa0820 in cus__process_file (cus=0x40b2b0, conf=0x40a240 <conf_load>, fd=3,
      filename=0x7fffffffd5e3 "examples/wcohen/02_Exercise.cuda") at /home/acme/git/pahole/dwarf_loader.c:2487
  #13 0x00007ffff7fa089c in dwarf__load_file (cus=0x40b2b0, conf=0x40a240 <conf_load>, filename=0x7fffffffd5e3 "examples/wcohen/02_Exercise.cuda")
      at /home/acme/git/pahole/dwarf_loader.c:2504
  #14 0x00007ffff7f8b0dd in cus__load_file (cus=0x40b2b0, conf=0x40a240 <conf_load>, filename=0x7fffffffd5e3 "examples/wcohen/02_Exercise.cuda")
      at /home/acme/git/pahole/dwarves.c:1745
  #15 0x00007ffff7f8bc2a in cus__load_files (cus=0x40b2b0, conf=0x40a240 <conf_load>, filenames=0x7fffffffd150)
      at /home/acme/git/pahole/dwarves.c:2109
  #16 0x0000000000404ff0 in main (argc=2, argv=0x7fffffffd148) at /home/acme/git/pahole/pahole.c:1294
  (gdb)

  (gdb) p class__name(class, cu)
  $6 = 0x5cbb85 "__nv_hdl_helper_trait<__nv_dl_tag<int (*)(int, char**), main, 1u>, void (main(int, char**)::__lambda0::*)(int, double&)const>"
  (gdb) p class->type.nr_members
  $7 = 0
  (gdb) p last
  $8 = (struct class_member *) 0x0
  (gdb)

So, before checking for bitfield details, first check if there were
members.

Now, if we show all structs/classes in that object file and look for the
above data structure, we find it inside another:

  $ pahole examples/wcohen/02_Exercise.cuda
  <SNIP>
  struct __nv_hdl_helper_trait_outer<false, false, int, Kokkos::View<double**>, Kokkos::View<double*>, Kokkos::View<double*> > {
          struct __nv_hdl_helper_trait<__nv_dl_tag<int (*)(int, char**), main, 1u>, void (main(int, char**)::__lambda0::*)(int, double&)const> {
                  class __nv_hdl_wrapper_t<false, false, __nv_dl_tag<int (*)(int, char**), main, 1u>, void(int, double&), int, Kokkos::View<doubl get<main(int, char**)::__lambda0>(class __lambda0, int, class View<double**>, class View<double*>, class View<double*>);

                  /* size: 1, cachelines: 0, members: 0 */
                  /* padding: 1 */
                  /* last cacheline: 1 bytes */
          };

          /* size: 1, cachelines: 0, members: 0 */
          /* padding: 1 */
          /* last cacheline: 1 bytes */
  };
  <SNIP>
  $

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 13e5b9fc00 ("fprintf: Add unnamed bitfield padding at the end to rebuild original type")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-01 11:37:40 -03:00
Timo Paulssen 3ed9a67967 fprintf: Avoid null dereference with NULL configs
Adding support for suppress_packed and leaving out bitfield paddings at the end
of classes when no alignment info is available accidentally used conf instead
of cconf, where conf can be NULL, which causes cconf to have the default
fprintf config.

Fixes: 986a3b58a8 ("fprintf: Only add bitfield forced paddings when alignment info available")
Fixes: 9a4d719304 ("fprintf: Allow suppressing the inferred __attribute__((__packed__))")
Signed-off-by: Timo Paulssen <timonator@perpetuum-immobile.de>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-05-14 11:19:00 -03:00