Commit Graph

1325 Commits

Author SHA1 Message Date
Arnaldo Carvalho de Melo f95fd85f7b pfunct: type->type == 0 is void, fix --compile for that
We were using the fall back for that, i.e. 'return 0;' was being emitted
for a function returning void, noticed with using BTF as the format.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 12:04:17 -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
Andrii Nakryiko 3c5f2a224a btf_encoder: Preserve and encode exported functions as BTF_KIND_FUNC
Add encoding of DWARF's DW_TAG_subprogram_type into BTF's BTF_KIND_FUNC
(plus corresponding BTF_KIND_FUNC_PROTO). Only exported functions are
converted for now. This allows to capture all the exported kernel
functions, same subset that's exposed through /proc/kallsyms.

Committer testing:

Before:

  $ readelf -SW vmlinux  | grep BTF
    [78] .BTF              PROGBITS        0000000000000000 26a27da9 1e5543 00      0   0  1
  $

After:

  $ pahole -J vmlinux
  $ readelf -SW vmlinux  | grep BTF
    [78] .BTF              PROGBITS        0000000000000000 26a27da9 2d5f47 00      0   0  1
  $

  >>> 0x2d5f47 - 0x1e5543
  985604

The kernel has a lot of functions! :-)

  $ pahole -VJ vmlinux > /tmp/pahole-btf-encoding-verbose-output.txt

  $ grep -w FUNC /tmp/pahole-btf-encoding-verbose-output.txt | wc -l
  22871
  [acme@quaco pahole]$ grep -w FUNC /tmp/pahole-btf-encoding-verbose-output.txt | tail
  [4511543] FUNC copy_from_user_nmi type_id=4511542
  [4512934] FUNC memcpy_page_flushcache type_id=4512933
  [4512936] FUNC __memcpy_flushcache type_id=4512935
  [4512938] FUNC __copy_user_flushcache type_id=4512937
  [4512940] FUNC arch_wb_cache_pmem type_id=4512939
  [4512942] FUNC mcsafe_handle_tail type_id=4512941
  [4512944] FUNC copy_user_handle_tail type_id=4512943
  [4512946] FUNC clear_user type_id=4512945
  [4512948] FUNC __clear_user type_id=4512947
  [4512950] FUNC memcpy type_id=4512949
  $ grep -w FUNC_PROTO /tmp/pahole-btf-encoding-verbose-output.txt | tail
  [4512902] FUNC_PROTO (anon) return=4511725 args=(4512097 (anon), 4511544 (anon))
  [4512933] FUNC_PROTO (anon) return=0 args=(4511598 to, 4511725 page, 4511610 offset, 4511610 len)
  [4512935] FUNC_PROTO (anon) return=0 args=(4511638 _dst, 4511759 _src, 4511610 size)
  [4512937] FUNC_PROTO (anon) return=4511585 args=(4511638 dst, 4511759 src, 4511552 size)
  [4512939] FUNC_PROTO (anon) return=0 args=(4511638 addr, 4511610 size)
  [4512941] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
  [4512943] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)
  [4512945] FUNC_PROTO (anon) return=4511544 args=(4511638 to, 4511544 n)
  [4512947] FUNC_PROTO (anon) return=4511544 args=(4511638 addr, 4511544 size)
  [4512949] FUNC_PROTO (anon) return=4511638 args=(4511638 p, 4511759 q, 4511591 size)
  $ grep -w FUNC_PROTO /tmp/pahole-btf-encoding-verbose-output.txt |grep 4511542
  [4511542] FUNC_PROTO (anon) return=4510159 args=(4510254 to, 4510374 from, 4510159 n)
  $

With a little change to pdwtags to see DW_TAG_subroutine_type, which is
what BTF's KIND_FUNC_PROTO maps to, we see some of those last
prototypes:

[acme@quaco pahole]$ pdwtags -F btf vmlinux  | grep '()(' | tail
void ()(struct insn * insn); /* size: 45404744 */
int ()(struct insn * insn); /* size: 4 */
void ()(struct insn * insn, const void  * kaddr, int buf_len, int x86_64); /* size: 45405032 */
long unsigned int ()(const char  * purpose); /* size: 8 */
void ()(char * to, struct page * page, size_t offset, size_t len); /* size: 45405864 */
void ()(void * _dst, const void  * _src, size_t size); /* size: 45406200 */
long int ()(void * dst, const void  * src, unsigned int size); /* size: 8 */
long unsigned int ()(char * to, char * from, unsigned int len); /* size: 8 */
long unsigned int ()(void * to, long unsigned int n); /* size: 8 */
long unsigned int ()(void * addr, long unsigned int size); /* size: 8 */
[acme@quaco pahole]$

I.e.:

  [4512941] FUNC_PROTO (anon) return=4511544 args=(4511598 to, 4511598 from, 4511552 len)

gets decoded by pdwtags as:

  long unsigned int ()(char * to, char * from, unsigned int len); /* size: 8 */

  $ grep '\[\(4511544\|4511598\|4511550\|4511552\)\]' /tmp/pahole-btf-encoding-verbose-output.txt
  [4511544] INT long unsigned int size=8 bit_offset=0 nr_bits=64 encoding=(none)
  [4511550] INT char size=1 bit_offset=0 nr_bits=8 encoding=(none)
  [4511552] INT unsigned int size=4 bit_offset=0 nr_bits=32 encoding=(none)
  [4511598] PTR (anon) type_id=4511550
  $

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: dwarves@vger.kernel.org
Cc: kernel-team@fb.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-11-05 09:27:58 -03:00
Arnaldo Carvalho de Melo 910e060b5c btf_loader: Skip BTF_KIND_DATASEC entries
Just skip them, we have no use for them so far, skipping them will allow
us to process the other kinds we have use for.

Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Daniel Bristot de Oliveira <bristot@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 21:02:33 -03:00
Arnaldo Carvalho de Melo 96235a74a3 btf_loader: Replace if/else series with a proper switch {}
A switch is the right thing here, use it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 20:56:31 -03:00
Arnaldo Carvalho de Melo a4ba2234ff btf_loader: Support BTF_KIND_VAR
Now the output for DWARF and BTF match, modulo warnings about some
BTF_KIND_ still not supported:

  [root@quaco tracebuffer]# pglobal -F dwarf -v bristot.o
  struct ____btf_map_tracebuffer__bristot ____btf_map_tracebuffer__bristot;; /* 0 */

  char                       _license[4];; /* 0 */

  int                        _version;; /* 0 */

  struct bpf_map     tracebuffer__bristot;; /* 0 */

  [root@quaco tracebuffer]# pglobal -F btf -v bristot.o
  BTF: idx: 17, off: 352, Unknown kind 15
  BTF: idx: 18, off: 364, Unknown kind 0
  BTF: idx: 19, off: 376, Unknown kind 15
  BTF: idx: 20, off: 388, Unknown kind 0
  BTF: idx: 21, off: 400, Unknown kind 15
  BTF: idx: 22, off: 412, Unknown kind 0
  BTF: idx: 23, off: 424, Unknown kind 15
  BTF: idx: 24, off: 436, Unknown kind 0
  struct ____btf_map_tracebuffer__bristot ____btf_map_tracebuffer__bristot;; /* 0 */

  char                       _license[4];; /* 0 */

  int                        _version;; /* 0 */

  struct bpf_map     tracebuffer__bristot;; /* 0 */

  [root@quaco tracebuffer]#

Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Daniel Bristot de Oliveira <bristot@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 17:14:00 -03:00
Arnaldo Carvalho de Melo 5965ce015e dwarves: Fix ptr_table__add_with_id() handling of pt->nr_entries
To agree with what ptr_table__add() does, i.e. the number of entries
(pt->nr_entries) is in fact the max id number in the table + 1, we can't
allow to add an id that is not contiguous and simply increment
nr_entries, as cu__for_each_variable(cu, id, pos) will iterate based on
nr_entries, skipping NULL buckets.

Detected when adding support for BTF variables, that share the id space
with types, but end up in different ptr_tables, so we end up with:

    cu__table_add_tag(BTF_KIND_VAR)
	ptr_table__add_with_id(cu->tags_table)

but:

     cu__table_add_tag()
	ptr_table__add_with_id(cu->types_table)

for all the other BTF_KIND_s, fix it so that ptr->nr_entries copes with
not receiving strictly monotonically incremented by one ids.

We'll have to fix this more properly by defining which tags are
supported by some debugging format and this what should go to a
ptr_table so that we have all its entries monononically incremented by
one and avoid tag__check_id_drift() returning true in the per debugging
format encoders (e.g.: btf_encoder.c).

This patch allows us to move forward and apply the BTF_KIND_VAR patch
where we'll at least produce, for global variables and a simple BPF
program with both DWARF and BTF tags the same results:

  [root@quaco tracebuffer]# pglobal -F dwarf -v bristot.o
  struct ____btf_map_tracebuffer__bristot ____btf_map_tracebuffer__bristot;; /* 0 */

  char                       _license[4];; /* 0 */

  int                        _version;; /* 0 */

  struct bpf_map     tracebuffer__bristot;; /* 0 */

  [root@quaco tracebuffer]# pglobal -F btf -v bristot.o
  BTF: idx: 17, off: 352, Unknown kind 15
  BTF: idx: 18, off: 364, Unknown kind 0
  BTF: idx: 19, off: 376, Unknown kind 15
  BTF: idx: 20, off: 388, Unknown kind 0
  BTF: idx: 21, off: 400, Unknown kind 15
  BTF: idx: 22, off: 412, Unknown kind 0
  BTF: idx: 23, off: 424, Unknown kind 15
  BTF: idx: 24, off: 436, Unknown kind 0
  struct ____btf_map_tracebuffer__bristot ____btf_map_tracebuffer__bristot;; /* 0 */

  char                       _license[4];; /* 0 */

  int                        _version;; /* 0 */

  struct bpf_map     tracebuffer__bristot;; /* 0 */

  [root@quaco tracebuffer]#

Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Daniel Bristot de Oliveira <bristot@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 16:56:40 -03:00
Arnaldo Carvalho de Melo 173911ac38 btf_loader: Show the unknown kind numbers
Instead of just telling that some unknown BTF_KIND_ was found in a file,
show the number to help in debugging.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 16:45:00 -03:00
Arnaldo Carvalho de Melo 0d8e11e856 pglobal: Allow passing the format path specifier, to use with BTF
I.e. now we can, just like with pahole, use:

  pglobal -F btf --variable foo.o

To get the global variables.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-24 08:17:16 -03:00
Arnaldo Carvalho de Melo ba27df9f2f CMakeLists: Use lib/bpf/include/uapi when building libdwarves
To avoid using /usr/include/linux/btf.h, as it has:

  [acme@quaco pahole]$ grep ^# /usr/include/linux/btf.h | head -2
  #ifndef __LINUX_BTF_H__
  #define __LINUX_BTF_H__
  [acme@quaco pahole]$

While:

  [acme@quaco pahole]$ grep ^# lib/bpf/include/uapi/linux/btf.h | head -2
  #ifndef _UAPI__LINUX_BTF_H__
  #define _UAPI__LINUX_BTF_H__
  [acme@quaco pahole]$

Then when both get included we get duplicate definitions, to avoid that
put lib/bpf/include/uapi/ first in the include path for libbdwarves.

Cc: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-21 18:25:41 -03:00
Arnaldo Carvalho de Melo 95517e1d99 libbpf: Get latest libbpf
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-10-21 17:31:15 -03:00
Arnaldo Carvalho de Melo ca294eebfc MANIFEST: Add missing files
Domenico reported that the README.DEBUG and changes-v1.13 files were not
in MANIFEST, so were not making into the release tarballs, fix that.

Reported-by: Domenico Andreoli <domenico.andreoli@linux.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-09-20 16:23:44 -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 93c3cdf897 cmake: Add -Wall to CFLAGS
And also -Werror for CMAKE_BUILD_TYPE=DEBUG, which is the default.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:33:29 -03:00
Arnaldo Carvalho de Melo 7360f0528f elfcreator: Remove unused 'machine' variable
Addresses:

  [ 84%] Building C object CMakeFiles/scncopy.dir/elfcreator.c.o
  /home/acme/git/pahole/elfcreator.c: In function ‘elfcreator_begin’:
  /home/acme/git/pahole/elfcreator.c:57:12: error: variable ‘machine’ set but not used [-Werror=unused-but-set-variable]
    GElf_Half machine;
              ^~~~~~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:33:05 -03:00
Arnaldo Carvalho de Melo 0f52b11f91 prefcnt: Avoid ambiguous else with for_each macro
Addresses:

  [ 80%] Building C object CMakeFiles/prefcnt.dir/prefcnt.c.o
  /home/acme/git/pahole/prefcnt.c: In function ‘refcnt_tag’:
  /home/acme/git/pahole/prefcnt.c:67:5: error: suggest explicit braces to avoid ambiguous ‘else’ [-Werror=dangling-else]
    if (tag__is_struct(tag) || tag__is_union(tag))
       ^
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:31:57 -03:00
Arnaldo Carvalho de Melo 608813d0af pglobal: Avoid ambiguous else
Addresses this warning:

  [ 68%] Building C object CMakeFiles/pglobal.dir/pglobal.c.o
  /home/acme/git/pahole/pglobal.c: In function ‘extvar__add’:
  /home/acme/git/pahole/pglobal.c:92:11: error: suggest explicit braces to avoid ambiguous ‘else’ [-Werror=dangling-else]
     else if (*nodep != gvar)
             ^
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:30:50 -03:00
Arnaldo Carvalho de Melo 77d06c2d30 reorganize: Enclose bitfield routines under ifdef
As they are temporarily disabled till we go thru them fixing up problems
with the BTF changes.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:28:50 -03:00
Arnaldo Carvalho de Melo 2221ae30bc reorganize: Ditch unused variable
Addressing this compiler warning:

  [ 56%] Building C object CMakeFiles/dwarves_reorganize.dir/dwarves_reorganize.c.o
  /home/acme/git/pahole/dwarves_reorganize.c: In function ‘class__move_bit_member’:
  /home/acme/git/pahole/dwarves_reorganize.c:356:16: error: unused variable ‘is_last_member’ [-Werror=unused-variable]
    const uint8_t is_last_member = (from->tag.node.next ==

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:24:46 -03:00
Arnaldo Carvalho de Melo c419c513ea libbtf: Enlarge the 'cmd' buffer to not possibly truncate the pathname
Addressing this compiler warning:

  /home/acme/git/pahole/libbtf.c: In function ‘btf_elf__write’:
  /home/acme/git/pahole/libbtf.c:655:53: error: ‘%s’ directive output may be truncated writing up to 4095 bytes into a region of size 4076 [-Werror=format-truncation=]
     snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
                                                       ^~
       llvm_objcopy, tmp_fn, filename);
                     ~~~~~~
  /home/acme/git/pahole/libbtf.c:655:3: note: ‘snprintf’ output 22 or more bytes (assuming 4117) into a destination of size 4096
     snprintf(cmd, sizeof(cmd), "%s --add-section .BTF=%s %s",
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       llvm_objcopy, tmp_fn, filename);
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:23:30 -03:00
Arnaldo Carvalho de Melo 092fffe567 btf_loader: Enum values are s32, cast before calling btf_elf__get32()
Addressing this compiler warning:

  /home/acme/git/pahole/btf_loader.c:279:41: error: pointer targets in passing argument 2 of ‘btf_elf__get32’ differ in signedness [-Werror=pointer-sign]
     uint32_t value = btf_elf__get32(btfe, &ep[i].val);
                                           ^~~~~~~~~~
  In file included from /home/acme/git/pahole/btf_loader.c:27:
  /home/acme/git/pahole/libbtf.h:63:10: note: expected ‘uint32_t *’ {aka ‘unsigned int *’} but argument is of type ‘__s32 *’ {aka ‘int *’}
   uint32_t btf_elf__get32(struct btf_elf *btf, uint32_t *p);
            ^~~~~~~~~~~~~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:21:59 -03:00
Arnaldo Carvalho de Melo 7bfb1aa80f libctf: Enlarge the 'cmd' buffer to not possibly truncate the pathname
Addressing this compiler warning:

  [ 22%] Building C object CMakeFiles/dwarves.dir/libctf.c.o
  /home/acme/git/pahole/libctf.h: In function ‘ctf__encode’:
  /home/acme/git/pahole/libctf.c:744:62: error: ‘%s’ directive output may be truncated writing up to 4095 bytes into a region of size 4064 [-Werror=format-truncation=]
    snprintf(cmd, sizeof(cmd), "objcopy --add-section .SUNW_ctf=%s %s",
                                                                ^~
      pathname, ctf->filename);
      ~~~~~~~~
  /home/acme/git/pahole/libctf.c:744:2: note: ‘snprintf’ output 34 or more bytes (assuming 4129) into a destination of size 4096
    snprintf(cmd, sizeof(cmd), "objcopy --add-section .SUNW_ctf=%s %s",
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      pathname, ctf->filename);
      ~~~~~~~~~~~~~~~~~~~~~~~~
  cc1: all warnings being treated as errors

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 12:14:02 -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 71c4f83f28 emit: Remove unused 'is_pointer' variable
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 10:27:16 -03:00
Arnaldo Carvalho de Melo fe87354c31 dwarves: Ditch unused asprintf() function
Not used at all, brought when adding vmlinux searching, but ended up not
being used, ditch it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 10:25:43 -03:00
Arnaldo Carvalho de Melo 60c73a7698 dwarves: We need to consistently check if 'conf was specified
Addresses this coverity report entry:

  Error: FORWARD_NULL (CWE-476): [#def12]
  dwarves-1.13/dwarves.c:1708: var_compare_op: Comparing "conf" to null implies that "conf" might be null.
  dwarves-1.13/dwarves.c:1743: var_deref_op: Dereferencing null pointer "conf".
  # 1741|
  # 1742|   	while (debug_fmt_table[i] != NULL) {
  # 1743|-> 		if (conf->conf_fprintf)
  # 1744|   			conf->conf_fprintf->has_alignment_info = debug_fmt_table[i]->has_alignment_info;
  # 1745|   		if (debug_fmt_table[i]->load_file(cus, conf, filename) == 0)

The first check setting added by 49c27bdd66 ("core: Allow the loaders
to advertise features they have") was inside a block where conf was
already checked, the second wasn't, fix it.

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 49c27bdd66 ("core: Allow the loaders to advertise features they have")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 10:18:58 -03:00
Arnaldo Carvalho de Melo 5fdfd09a6b dwarves: Fix check in type__find_first_biggest_size_base_type_member()
We stopped scrubbing type when looking for type->type by assigning the
result of cu__type(cu, type->type) to a temporary 'tag' variable but
continued to check the result of cu__type() looking at type... Check
'tag' instead.

Addresses these coverity report entries:

  Error: NULL_RETURNS (CWE-476): [#def9]
  dwarves-1.13/dwarves.c:333: returned_null: "cu__type" returns "NULL" (checked 54 out of 62 times).
  dwarves-1.13/dwarves.c:333: var_assigned: Assigning: "tag" = "NULL" return value from "cu__type".
  dwarves-1.13/dwarves.c:338: alias: Assigning: "type" = "tag". Both pointers are now "NULL".
  dwarves-1.13/dwarves.c:312: 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".
  #  310|   		}
  #  311|   reevaluate:
  #  312|-> 		switch (type->tag) {
  #  313|   		case DW_TAG_base_type:
  #  314|

  Error: REVERSE_INULL (CWE-476): [#def10]
  dwarves-1.13/dwarves.c:312: deref_ptr: Directly dereferencing pointer "type".
  dwarves-1.13/dwarves.c:334: check_after_deref: Null-checking "type" suggests that it may be null, but it has already been dereferenced on all paths leading to the check.
  #  332|   		case DW_TAG_volatile_type: {
  #  333|   			struct tag *tag = cu__type(cu, type->type);
  #  334|-> 			if (type == NULL) {
  #  335|   				tag__id_not_found_fprintf(stderr, type->type);
  #  336|   				continue;

Looking at this last one shows the problem in detail, check for NULL to
then deref it, phew.

This is just used in 'pahole --show_first_biggest_size_base_type_member'
and when fixing up alignment in the --reorganize code tho.

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 7fc7148be7 ("core: Fix thinko in type__find_first_biggest_size_base_type_member")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-02 10:16:40 -03:00
Arnaldo Carvalho de Melo 24ced5be8a dwarf_loader: Fix array overrun access
Fixing this coverity report:

  Error: OVERRUN (CWE-119): [#def7]
  dwarves-1.13/dwarf_loader.c:54: cond_at_most: Checking "tag < DW_TAG_MIPS_loop" implies that "tag" may be up to 16512 on the true branch.
  dwarves-1.13/dwarf_loader.c:55: overrun-local: Overrunning array "dwarf_tags_warned" of 66 bytes at byte offset 16512 using index "tag" (which evaluates to 16512).
  #   53|
  #   54|   	if (tag < DW_TAG_MIPS_loop) {
  #   55|-> 		if (dwarf_tags_warned[tag])
  #   56|   			return;
  #   57|   		dwarf_tags_warned[tag] = true;

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: c7fa6a9a40 ("dwarf loader: Catch some more template tags")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-01 22:20:14 -03:00
Arnaldo Carvalho de Melo 33e2d7aa35 ctf_loader: Plug leak when bailing out due to unknown tag
Fixes this coverity report:

  Error: RESOURCE_LEAK (CWE-772): [#def6]
  dwarves-1.13/ctf_loader.c:458: alloc_fn: Storage is returned from allocation function "zalloc".
  dwarves-1.13/ctf_loader.c:458: var_assign: Assigning: "tag" = storage returned from "zalloc(40UL)".
  dwarves-1.13/ctf_loader.c:470: leaked_storage: Variable "tag" going out of scope leaks the storage it points to.
  #  468|   	default:
  #  469|   		printf("%s: FOO %d\n\n", __func__, type);
  #  470|-> 		return 0;
  #  471|   	}
  #  472|

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 2dfa5fe6ea ("[DWARVES]: Initial CTF support")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-01 21:43:46 -03:00
Arnaldo Carvalho de Melo aefa930381 codiff: Remove unused filenames variable
I changed the logic at some point stopping the use of that variable, but
then forgot to remove it, do it now.

Addresses this coverity report entry:

  Error: COMPILER_WARNING: [#def3]
  dwarves-1.13/codiff.c: scope_hint: In function 'main'
  dwarves-1.13/codiff.c:776:8: warning: variable 'filenames' set but not used [-Wunused-but-set-variable]
  #  776 |  char *filenames[2];
  #      |        ^~~~~~~~~
  #  774|   	int remaining, err, rc = EXIT_FAILURE;
  #  775|   	char *old_filename, *new_filename;
  #  776|-> 	char *filenames[2];
  #  777|   	struct stat st;
  #  778|

Need to find how to make cmake show these warnings...

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 991c6a3ebb ("dwarves: Rename cus__loadfl with cus__load_files")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-01 16:41:02 -03:00
Arnaldo Carvalho de Melo de5e72bc15 btf_loader: Plug leak when bailing out due to unknown tag
Fixes this coverity report:

  Error: RESOURCE_LEAK (CWE-772): [#def2]
  dwarves-1.13/btf_loader.c:342: alloc_fn: Storage is returned from allocation function "zalloc".
  dwarves-1.13/btf_loader.c:342: var_assign: Assigning: "tag" = storage returned from "zalloc(40UL)".
  dwarves-1.13/btf_loader.c:354: leaked_storage: Variable "tag" going out of scope leaks the storage it points to.
  #  352|   	default:
  #  353|   		printf("%s: FOO %d\n\n", __func__, type);
  #  354|-> 		return 0;
  #  355|   	}
  #  356|

Reported-by: William Cohen <wcohen@redhat.com>
Fixes: 472256d3c5 ("btf_loader: Introduce a loader for the BTF format")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-01 16:30:43 -03:00
Arnaldo Carvalho de Melo 511a791294 dwarves: Remove unused variable
The 'last' variable is not being used at all, ditch it.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-07-01 16:24:31 -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
Arnaldo Carvalho de Melo 5299035710 v1.15: New release
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-06-27 07:20:37 -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
Arnaldo Carvalho de Melo 568dae4bd4 printf: Fixup printing "const" early with "const void"
When printing const more early we're not considering "const void *", fix
it.

Fixes: ccd67bdb20 ("fprintf: Print "const" for class members more early, in type__fprintf()")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-05-01 14:56:33 -04:00
Arnaldo Carvalho de Melo 68f261d8df fprintf: Fix recursively printing named structs in --expand_types
In cf459ca16f ("fprintf: Pretty print struct members that are pointers
to nameless structs") we end up breaking 'pahole --expand_types/-E.

All we need there is to print nameless structs when they are referenced
by a pointer member in a struct, i.e. it is defined only there, inline.

Check if that struct is unnamed before emitting it, keeping that fix
while fixing the regression it caused for --expand_types.

Fixes: cf459ca16f ("fprintf: Pretty print struct members that are pointers to nameless structs")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-05-01 12:04:53 -04:00
Arnaldo Carvalho de Melo 139a3b3373 ostra: Initial python3 conversion
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-23 12:02:22 -03:00
Arnaldo Carvalho de Melo 01276a7e89 spec: Sync spec with fedora's
Removing some needless defattr, using new ldconfig scriptlets, etc.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-23 11:37:53 -03:00
Arnaldo Carvalho de Melo 9f1f0628b9 rpm: Add missing devel headers
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-23 11:25:41 -03:00
Arnaldo Carvalho de Melo 989dc3f1ba cmake: Install missing devel headers
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-23 11:25:41 -03:00
Arnaldo Carvalho de Melo 8288d88423 MANIFEST: Add missing files to generate the tarball
btf_loader.c and the libbpf obtained via the git module are needed to
be able to build from the tarball generated via:

  tar cvfj rpm/SOURCES/dwarves-1.13.tar.bz2 `cat MANIFEST`

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-16 20:55:59 -03:00
Arnaldo Carvalho de Melo 92a4118812 v1.13: New release
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-16 16:13:19 -03:00
Arnaldo Carvalho de Melo 0fb727166a pfunct: Strip inlines in the code generated for --compile
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>
2019-04-16 15:00:44 -03:00
Arnaldo Carvalho de Melo 7b967744db emit: Emit the types for inline structs defined in pointer members
I.e. before:

  $ pfunct --compile /home/acme/git/build/v5.1-rc4+/block/partitions/sgi.o > a.c
    $ gcc -g -c a.c
  a.c:9:3: error: unknown type name ‘sector_t’
     sector_t           from;                 /*     0     8 */
     ^~~~~~~~
  a.c:10:3: error: unknown type name ‘sector_t’
     sector_t           size;                 /*     8     8 */
     ^~~~~~~~
  a.c:13:30: error: field ‘info’ has incomplete type
     struct partition_meta_info info;         /*    21   101 */
                                ^~~~
  $

After:

  $ pfunct --compile /home/acme/git/build/v5.1-rc4+/block/partitions/sgi.o > a.c
  $ gcc -g -c a.c
  $ head -40 a.c
  struct block_device;

  typedef long unsigned int sector_t;

  typedef _Bool bool;

  typedef unsigned char __u8;
  typedef __u8 u8;

  struct partition_meta_info {
  	char                       uuid[37];             /*     0    37 */
  	u8                         volname[64];          /*    37    64 */

  	/* size: 101, cachelines: 2, members: 2 */
  	/* last cacheline: 37 bytes */
  };

  struct parsed_partitions {
  	struct block_device * bdev;                      /*     0     8 */
  	char                       name[32];             /*     8    32 */
  	struct {
  		sector_t           from;                 /*     0     8 */
  		sector_t           size;                 /*     8     8 */
  		int                flags;                /*    16     4 */
  		bool               has_info;             /*    20     1 */
  		struct partition_meta_info info;         /*    21   101 */
  	} * parts; /*    40     8 */
  	int                        next;                 /*    48     4 */
  	int                        limit;                /*    52     4 */
  	bool                       access_beyond_eod;    /*    56     1 */

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

  	/* --- cacheline 1 boundary (64 bytes) --- */
  	char *                     pp_buf;               /*    64     8 */

  	/* size: 72, cachelines: 2, members: 7 */
  	/* sum members: 65, holes: 1, sum holes: 7 */
  	/* last cacheline: 8 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-16 14:47:53 -03:00
Arnaldo Carvalho de Melo 30526e2848 fprintf: Print relative offsets for inner pointer structs
I.e. before:

      $ pahole -C parsed_partitions /home/acme/git/build/v5.1-rc4+/block/partitions/check.o > a.c ; head -29 a.c
      struct parsed_partitions {
            struct block_device * bdev;                      /*     0     8 */
            char                       name[32];             /*     8    32 */
            struct {
                    sector_t           from;                 /*    40     8 */
                    sector_t           size;                 /*    48     8 */
                    int                flags;                /*    56     4 */
                    bool               has_info;             /*    60     1 */
                    struct partition_meta_info info;         /*    61   101 */
            } * parts; /*    40     8 */
            int                        next;                 /*    48     4 */
            int                        limit;                /*    52     4 */
            bool                       access_beyond_eod;    /*    56     1 */

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

            /* --- cacheline 1 boundary (64 bytes) --- */
            char *                     pp_buf;               /*    64     8 */

            /* size: 72, cachelines: 2, members: 7 */
            /* sum members: 65, holes: 1, sum holes: 7 */
            /* last cacheline: 8 bytes */
      };
      $

Now:

  $ pahole -C parsed_partitions /home/acme/git/build/v5.1-rc4+/block/partitions/check.o
  struct parsed_partitions {
  	struct block_device * bdev;                      /*     0     8 */
  	char                       name[32];             /*     8    32 */
  	struct {
  		sector_t           from;                 /*     0     8 */
  		sector_t           size;                 /*     8     8 */
  		int                flags;                /*    16     4 */
  		bool               has_info;             /*    20     1 */
  		struct partition_meta_info info;         /*    21   101 */
  	} * parts; /*    40     8 */
  	int                        next;                 /*    48     4 */
  	int                        limit;                /*    52     4 */
  	bool                       access_beyond_eod;    /*    56     1 */

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

  	/* --- cacheline 1 boundary (64 bytes) --- */
  	char *                     pp_buf;               /*    64     8 */

  	/* size: 72, cachelines: 2, members: 7 */
  	/* sum members: 65, holes: 1, sum holes: 7 */
  	/* last cacheline: 8 bytes */
  };
  $

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-16 14:39:51 -03:00