core: The padding in ancestor classes may be used in descendants
commit47e83035c12c153b579db2e5fabd306a0d6f2d29
authorArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 7 Mar 2024 19:50:43 +0000 (7 16:50 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 7 Mar 2024 20:00:52 +0000 (7 17:00 -0300)
tree828ec2dda45fb29ee2359556793362fbe8dc8416
parent9442420a8c2044601b95f0f36447c79cf07bfacd
core: The padding in ancestor classes may be used in descendants

This appeared on the radar, in an expanded type:

class Spell_AdjustVital : public SpellActionType {
public:

        /* class SpellActionType {
        public:

                void SpellActionType(class SpellActionType *, const class SpellActionType  &);

                int ()(void) * *   _vptr.SpellActionType;              /*   0  8 */
           void SpellActionType(class SpellActionType *, int);

                virtual void ~SpellActionType(class SpellActionType *, int);

                virtual int Cast(class SpellActionType *, class CUnit &, const class SpellType  &, class CUnit * &, const Vec2i  &);

                virtual void Parse(class SpellActionType *, struct lua_State *, int, int);

              const int          ModifyManaCaster;                   /*   8   4 */
                /* vtable has 2 entries: {
                   [2] = Cast((null)),
                   [3] = Parse((null)),
                } */    } <ancestor>; */ /*     0    16 */

        /* XXX last struct has 4 bytes of padding */
        /* XXX 65532 bytes hole, try to pack */
        void Spell_AdjustVital(class Spell_AdjustVital *);

        virtual int Cast(class Spell_AdjustVital *, class CUnit &, const class SpellType  &, class CUnit * &, const Vec2i  &);

        virtual void Parse(class Spell_AdjustVital *, lua_State *, int, int);

        int                        HP;                  /*    12   4 */
        int                        Mana;                /*    16   4 */
        int                        Shield;              /*    20   4 */
        int                        MaxMultiCast;        /*    24   4 */
     virtual void ~Spell_AdjustVital(class Spell_AdjustVital *, int);

        /* vtable has 2 entries: {
           [2] = Cast((null)),
           [3] = Parse((null)),
        } */
/* size: 32, cachelines: 1, members: 5 */
        /* sum members: 32, holes: 1, sum holes: 65532 */
        /* padding: 4 */
        /* paddings: 1, sum paddings: 4 */
        /* last cacheline: 32 bytes */

        /* BRAIN FART ALERT! 32 bytes != 32 (member bytes) + 0 (member bits) + 65532 (byte holes) + 0 (bit holes), diff = -524288 bits */
};

So the ancestor class (DW_TAG_inheritance) 'class SpellActionType' has 4
bytes of padding (the sum of its members is 12 bytes but its sizeof is
16) and then the first DW_TAG_member in the descendant, 'class Spell_AdjustVital'
is at offset 12, meaning it is using the padding from the ancestor.

Take that into account, with it now we have, unexpanded:

  $ pahole -C Spell_AdjustVital objects/spell_adjustvital.cpp.o
  class Spell_AdjustVital : public SpellActionType {
  public:

          /* class SpellActionType     <ancestor>; */      /*     0    16 */

          /* XXX last struct has 4 bytes of padding */
          void Spell_AdjustVital(class Spell_AdjustVital *);

          virtual int Cast(class Spell_AdjustVital *, class CUnit &, const class SpellType  &, class CUnit * &, const Vec2i  &);

          virtual void Parse(class Spell_AdjustVital *, lua_State *, int, int);

          /* Bitfield combined with next fields */

          int                        HP;                   /*    12     4 */
          int                        Mana;                 /*    16     4 */
          int                        Shield;               /*    20     4 */
          int                        MaxMultiCast;         /*    24     4 */
          virtual void ~Spell_AdjustVital(class Spell_AdjustVital *, int);

          /* vtable has 2 entries: {
             [2] = Cast((null)),
             [3] = Parse((null)),
          } */
          /* size: 32, cachelines: 1, members: 5 */
          /* padding: 4 */
          /* paddings: 1, sum paddings: 4 */
          /* last cacheline: 32 bytes */
  };

  $

Reported-by: Matthias Schwarzott <zzam@gentoo.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
dwarves.c
dwarves.h
dwarves_fprintf.c