Go to file
Arnaldo Carvalho de Melo dc6b9437a3 emit: Handle structs with DW_AT_alignment=1 meaning __packed__
In the following struct the ceph_entity_addr entries all appear marked with a
__attribute__((__aligned__(8)), which, for the first two members of this type,
'peer_addr' and 'peer_addr_for_me', don't cause the regenerated struct to
differ in layout from the original layout put in place by the compiler as per
the original source code.

But the third member of this type, 'actual_peer_addr' ends up in a different
offset, even in a different cacheline, here is how it looks like in the code generated
from the original source code, at offset 568.

          char                       in_banner[30];        /*   472    30 */
          struct ceph_msg_connect out_connect;             /*   502    33 */
          /* --- cacheline 8 boundary (512 bytes) was 23 bytes ago --- */
          struct ceph_msg_connect_reply in_reply;          /*   535    26 */
          struct ceph_entity_addr actual_peer_addr __attribute__((__aligned__(1))); /*   561   136 */
          /* --- cacheline 10 boundary (640 bytes) was 57 bytes ago --- */
          struct ceph_msg_header out_hdr;                  /*   697    53 */

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

          /* --- cacheline 11 boundary (704 bytes) was 48 bytes ago --- */

And here is how it looks like when built from the regenerated source code, at
offset 568:

  $ pfunct --compile /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o > ceph.c
  $ gcc -g -c  ceph.c
  $ pahole -C ceph_connection ceph.o | head -46
  struct ceph_connection {
          void *                     private;              /*     0     8 */
          const struct ceph_connection_operations  * ops;  /*     8     8 */
          struct ceph_messenger *    msgr;                 /*    16     8 */
          atomic_t                   sock_state;           /*    24     4 */

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

          struct socket *            sock;                 /*    32     8 */
          struct ceph_entity_addr peer_addr __attribute__((__aligned__(8))); /*    40   136 */
          /* --- cacheline 2 boundary (128 bytes) was 48 bytes ago --- */
          struct ceph_entity_addr peer_addr_for_me __attribute__((__aligned__(8))); /*   176   136 */
          /* --- cacheline 4 boundary (256 bytes) was 56 bytes ago --- */
          long unsigned int          flags;                /*   312     8 */
          /* --- cacheline 5 boundary (320 bytes) --- */
          long unsigned int          state;                /*   320     8 */
          const char  *              error_msg;            /*   328     8 */
          struct ceph_entity_name peer_name;               /*   336     9 */

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

          u64                        peer_features;        /*   352     8 */
          u32                        connect_seq;          /*   360     4 */
          u32                        peer_global_seq;      /*   364     4 */
          struct ceph_auth_handshake * auth;               /*   368     8 */
          int                        auth_retry;           /*   376     4 */

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

          /* --- cacheline 6 boundary (384 bytes) --- */
          struct mutex       mutex;                        /*   384    32 */
          struct list_head   out_queue;                    /*   416    16 */
          struct list_head   out_sent;                     /*   432    16 */
          /* --- cacheline 7 boundary (448 bytes) --- */
          u64                        out_seq;              /*   448     8 */
          u64                        in_seq;               /*   456     8 */
          u64                        in_seq_acked;         /*   464     8 */
          char                       in_banner[30];        /*   472    30 */
          struct ceph_msg_connect out_connect;             /*   502    33 */
          /* --- cacheline 8 boundary (512 bytes) was 23 bytes ago --- */
          struct ceph_msg_connect_reply in_reply;          /*   535    26 */

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

          struct ceph_entity_addr actual_peer_addr __attribute__((__aligned__(8))); /*   568   136 */
          /* --- cacheline 11 boundary (704 bytes) --- */
    $

That happens because 'struct ceph_entity_addr' has that __attribute__
((__aligned__(8)) in the regenerated source code, above, now look at how it
gets regenerated:

  $ pahole -C ceph_entity_addr ceph.o
  struct ceph_entity_addr {
          __le32                     type;                 /*     0     4 */
          __le32                     nonce;                /*     4     4 */
          struct __kernel_sockaddr_storage in_addr __attribute__((__aligned__(8))); /*     8   128 */

          /* size: 136, cachelines: 3, members: 3 */
          /* forced alignments: 1 */
          /* last cacheline: 8 bytes */
  } __attribute__((__aligned__(8)));
  $

While when looking at the original DWARF:

  $ pahole -C ceph_entity_addr /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o
  struct ceph_entity_addr {
          __le32                     type;                 /*     0     4 */
          __le32                     nonce;                /*     4     4 */
          struct __kernel_sockaddr_storage in_addr __attribute__((__aligned__(1))); /*     8   128 */

          /* size: 136, cachelines: 3, members: 3 */
          /* forced alignments: 1 */
          /* last cacheline: 8 bytes */
  } __attribute__((__aligned__(1)));
  $

The confusion may further come from the fact that 'struct __kernel_sockaddr_storage' has,
in the regenerated source code, the __attribute__((__aligned__8)))

  $ pahole -C __kernel_sockaddr_storage ceph.o
  struct __kernel_sockaddr_storage {
          __kernel_sa_family_t       ss_family;            /*     0     2 */
          char                       __data[126];          /*     2   126 */

          /* size: 128, cachelines: 2, members: 2 */
  } __attribute__((__aligned__(8)));
  $

Which is the same as in the original DWARF:

  $ pahole -C __kernel_sockaddr_storage /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o
  struct __kernel_sockaddr_storage {
          __kernel_sa_family_t       ss_family;            /*     0     2 */
          char                       __data[126];          /*     2   126 */

          /* size: 128, cachelines: 2, members: 2 */
  } __attribute__((__aligned__(8)));
  $

Looking at the original original source code for 'struct ceph_entity_addr'
helps here, as it reads:

  include/linux/ceph/msgr.h, line 63:

  /*
   * entity_addr -- network address
   */
  struct ceph_entity_addr {
          __le32 type;
          __le32 nonce;  /* unique id for process (e.g. pid) */
          struct sockaddr_storage in_addr;
  } __attribute__ ((packed));

So the original code has no __attribute__((__aligned__(1))), so, lets look at
what the compiler generates for 'struct ceph_entity_addr':

  $ readelf -wi /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o | grep ceph_entity_addr -A7
      <193a6>   DW_AT_name        : (indirect string, offset: 0x1586): ceph_entity_addr
      <193aa>   DW_AT_byte_size   : 136
      <193ab>   DW_AT_alignment   : 1
      <193ac>   DW_AT_decl_file   : 296
      <193ae>   DW_AT_decl_line   : 63
      <193af>   DW_AT_decl_column : 8
      <193b0>   DW_AT_sibling     : <0x193e0>
   <2><193b4>: Abbrev Number: 5 (DW_TAG_member)
  $

So the natural alignment for 'struct ceph_entity_addr' ends up being the
natural alignment for 'struct __kernel_sockaddr_storage', which is 8, but
since 'struct ceph_entity_addr' was marked in the original source code as __packed__,
the compiler added the DW_AT_alignment: 1 to override that.

The heuristic in pahole, so far, took that __attribute__((__aligned__(1)))
literally:

  $ pahole -C ceph_entity_addr /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o
  struct ceph_entity_addr {
          __le32                     type;                 /*     0     4 */
          __le32                     nonce;                /*     4     4 */
          struct __kernel_sockaddr_storage in_addr __attribute__((__aligned__(1))); /*     8   128 */

          /* size: 136, cachelines: 3, members: 3 */
          /* forced alignments: 1 */
          /* last cacheline: 8 bytes */
  } __attribute__((__aligned__(1)));
  $

which ends up making the regenerated source code (with the __aligned__((1))),
generate a different layout, the __aligned__((8)) in one of its members
overrode that __aligned__((1)).

Take this into account and when faced with a structure which natural alignment
is not one and that has a DW_AT_alignment:1 to mean it really is __packed__.

Doing that makes the regenerated source code match the original structure
layouts, i.e. after the patch we get:

  $ pahole -C ceph_entity_addr /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o
  struct ceph_entity_addr {
          __le32                     type;                 /*     0     4 */
          __le32                     nonce;                /*     4     4 */
          struct __kernel_sockaddr_storage in_addr __attribute__((__aligned__(1))); /*     8   128 */

          /* size: 136, cachelines: 3, members: 3 */
          /* forced alignments: 1 */
          /* last cacheline: 8 bytes */
  } __attribute__((__packed__));
  $

And that member in 'struct ceph_connection', in the original, continues to read:

  $ pahole -C ceph_connection /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o | grep -w actual_peer_addr -B4 -A6
          char                       in_banner[30];        /*   472    30 */
          struct ceph_msg_connect out_connect;             /*   502    33 */
          /* --- cacheline 8 boundary (512 bytes) was 23 bytes ago --- */
          struct ceph_msg_connect_reply in_reply;          /*   535    26 */
          struct ceph_entity_addr actual_peer_addr __attribute__((__aligned__(1))); /*   561   136 */
          /* --- cacheline 10 boundary (640 bytes) was 57 bytes ago --- */
          struct ceph_msg_header out_hdr;                  /*   697    53 */

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

          /* --- cacheline 11 boundary (704 bytes) was 48 bytes ago --- */
  $

While in the regenerated DWARF from the regenerated source code reads:

  $ pfunct --compile /home/acme/git/build/v5.1-rc4+/fs/ceph/super.o > ceph.c
  $ gcc -g -c  ceph.c
  $ pahole -C ceph_connection ceph.o | grep -w actual_peer_addr -B4 -A6
          char                       in_banner[30];        /*   472    30 */
          struct ceph_msg_connect out_connect;             /*   502    33 */
          /* --- cacheline 8 boundary (512 bytes) was 23 bytes ago --- */
          struct ceph_msg_connect_reply in_reply;          /*   535    26 */
          struct ceph_entity_addr actual_peer_addr __attribute__((__aligned__(1))); /*   561   136 */
          /* --- cacheline 10 boundary (640 bytes) was 57 bytes ago --- */
          struct ceph_msg_header out_hdr;                  /*   697    53 */

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

          /* --- cacheline 11 boundary (704 bytes) was 48 bytes ago --- */
  $

I.e. it now matches.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2019-04-15 13:25:48 -03:00
cmake/modules cmake: Add comments explaining build_id and fedora/rh detection 2009-06-27 13:32:20 -03:00
lib libbpf: Sync in latest libbpf sources 2019-03-29 15:53:13 -03:00
man-pages dwarves_fprintf: Allow suppressing the __attribute__((__aligned__(N)) 2019-04-03 18:10:16 -03:00
ostra [OSTRA]: Change ostra-cg license to GPLv2 2007-12-24 12:25:17 -02:00
rpm/SPECS v1.12 - New Release 2018-08-16 16:15:27 -03:00
.gitignore pahole: Add build dir, config.h to .gitignore 2019-02-11 12:55:46 -03:00
.gitmodules pahole: add libbpf as submodule under lib/bpf 2019-02-11 12:56:40 -03:00
CMakeLists.txt libbpf: Build as PIC and statically link into libdwarves 2019-02-19 10:21:29 -03:00
COPYING [LICENSE]: Add COPYING file and add missing license info on some files 2007-12-17 14:15:42 -02:00
MANIFEST MANIFEST: Add missing COPYING file 2018-09-11 11:22:41 -03:00
NEWS v1.12 - New Release 2018-08-16 16:15:27 -03:00
README [CMAKE]: Make the default install prefix be /usr/local 2007-04-19 18:01:47 -03:00
README.DEBUG README.DEBUG: Add an extra step to make the instructions cut'n'exec 2017-12-14 14:15:54 -03:00
README.btf README.btf: Add section on validating the .BTF section via the kernel 2018-08-16 12:05:29 -03:00
README.ctracer ctracer: update README.ctracer, f9 has the dwarves 2008-10-29 08:54:53 -02:00
btf_encoder.c dwarf_loader: Use DWARF recommended uniform bit offset scheme 2019-03-29 15:55:37 -03:00
btf_encoder.h Fixup copyright notices for BTF files authored by Facebook engineers 2019-01-18 20:34:05 -03:00
btf_loader.c dwarf_loader: Use DWARF recommended uniform bit offset scheme 2019-03-29 15:55:37 -03:00
btfdiff btfdiff: Use --suppress_aligned_attribute with -F dwarf 2019-04-03 18:10:16 -03:00
codiff.c codiff: Fix comparision of multi-cu against single-cu files 2019-04-11 16:38:51 -03:00
config.h.cmake [DWARVES] Fixes a FIXME relating to a missing elf (libdw) symbol check. 2008-02-12 21:08:49 -02:00
ctf.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
ctf_encoder.c libctf: The type_ids returned are uint32_t fixup where it was uint16_t 2019-03-11 11:44:53 -03:00
ctf_encoder.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
ctf_loader.c loaders: Record CU's endianness in dwarf/btf/ctf loaders 2019-03-29 15:55:37 -03:00
ctfdwdiff ctfdwdiff: Don't ask for variables and inline expansions in pfunct 2009-03-31 19:21:46 -03:00
ctracer.c tag: Introduce tag__is_pointer_to() 2019-04-05 15:28:55 -03:00
dtagnames.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
dutil.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
dutil.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
dwarf_loader.c dwarf_loader: Store DW_AT_alignment if available in DW_TAG_{structure,union,class}_type 2019-04-09 16:57:52 -03:00
dwarves.c emit: Handle structs with DW_AT_alignment=1 meaning __packed__ 2019-04-15 13:25:48 -03:00
dwarves.h core: Infer __packed__ for union struct members 2019-04-12 17:08:41 -03:00
dwarves_emit.c emit: Cover void ** as a function parameter 2019-04-11 11:19:32 -03:00
dwarves_emit.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
dwarves_fprintf.c emit: Handle structs with DW_AT_alignment=1 meaning __packed__ 2019-04-15 13:25:48 -03:00
dwarves_reorganize.c reorganize: Introduce class__for_each_member_from_safe() 2019-04-05 16:16:16 -03:00
dwarves_reorganize.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
elf_symtab.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
elf_symtab.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
elfcreator.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
elfcreator.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
gobuffer.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
gobuffer.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
hash.h [DWARVES]: Use a hash table for the tags in a CU 2008-02-11 11:47:17 -02:00
libbtf.c btf_encoder: run BTF deduplication before writing out to ELF 2019-02-18 11:00:03 -03:00
libbtf.h btf_elf: Rename btf_elf__free() to btf_elf__delete() 2019-02-14 17:06:40 -03:00
libctf.c libctf: The type_ids returned are uint32_t fixup where it was uint16_t 2019-03-11 11:44:53 -03:00
libctf.h libctf: The type_ids returned are uint32_t fixup where it was uint16_t 2019-03-11 11:44:53 -03:00
list.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
pahole.c tag: Introduce tag__is_pointer_to() 2019-04-05 15:28:55 -03:00
pdwtags.c tag: Introduce tag__is_pointer() 2019-04-05 15:21:55 -03:00
pfunct.c pfunct: Generate a valid return type for the --compile bodies 2019-04-05 16:33:43 -03:00
pglobal.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
prefcnt.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
rbtree.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
rbtree.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
regtest regtest: Accept --diff instad of plain 'diff' as long option 2012-05-14 19:36:58 -03:00
scncopy.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
strings.c Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
strings.h Adopt SPDX-License-Identifier 2019-01-18 15:41:48 -03:00
syscse.c dwarves: Introduce type_id_t for use with the type IDs 2019-03-11 11:44:53 -03:00

README

Build instructions:

1. install cmake
2. mkdir build
3. cd build
4. cmake -D__LIB=lib ..
5. make install

Default is to be installed on /usr/local, see rpm spec file for
installing on other places.

Known to work scenarios:

Mandriva Cooker:

cmake 2.4.5-1mdv2007.1
libelfutils1-devel 0.123-1mdv2007.1

Debian Unstable:

cmake 2.4.5-1
libdw-dev 0.123-2

Fedora Core 6:

cmake 2.4.5-2.fc6
elfutils-devel 0.126-1.fc6