Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get size for (void*) in struct #1

Closed
twinshadow opened this issue Oct 1, 2014 · 8 comments
Closed

Can't get size for (void*) in struct #1

twinshadow opened this issue Oct 1, 2014 · 8 comments

Comments

@twinshadow
Copy link

Running structhole on the FreeBSD kernel, I run into some struct attributes that dwarf can't calculate the size of in this structure:
http://fxr.watson.org/fxr/source/netinet/in_pcb.h#L163

# ./structhole inpcb kernel.debug
struct inpcb {
        struct (null)              inp_hash;             /*     0    16 */
        struct (null)              inp_pcbgrouphash;     /*    16    16 */
        struct (null)              inp_list;             /*    32    16 */
structhole.c:191: structprobe: dwarf_aggregate_size: no error(0)
@twinshadow
Copy link
Author

I should add this is with elfutils 0.159 from https://fedorahosted.org/elfutils/

@cemeyer
Copy link
Owner

cemeyer commented Oct 1, 2014

I can reproduce the problem (elfutils 0.160), thanks. Will fix soon.

@cemeyer
Copy link
Owner

cemeyer commented Oct 1, 2014

So, the (null)s are anonymous structures from LIST_ENTRY() macros. pahole(1) correctly dumps them out, so we should be able to do so too.

The error / early exit is a void*.

@cemeyer
Copy link
Owner

cemeyer commented Oct 1, 2014

Progress! I now get this:

struct inpcb {
        struct (null)              inp_hash;             /*     0    16 */
        struct (null)              inp_pcbgrouphash;     /*    16    16 */
        struct (null)              inp_list;             /*    32    16 */
        (null)                     inp_ppcb;             /*    48    16 */
        /* --- cacheline 1 boundary (64 bytes) --- */

        /* XXX -8 bytes hole, try to pack */

        (null)                     inp_pcbinfo;          /*    56    16 */

        /* XXX -8 bytes hole, try to pack */

        (null)                     inp_pcbgroup;         /*    64    16 */

        /* XXX -8 bytes hole, try to pack */

        struct (null)              inp_pcbgroup_wild;    /*    72    16 */
        (null)                     inp_socket;           /*    88    16 */

        /* XXX -8 bytes hole, try to pack */

        (null)                     inp_cred;             /*    96    16 */

        /* XXX -8 bytes hole, try to pack */

        u_int32_t                  inp_flow;             /*   104     4 */
        int                        inp_flags;            /*   108     4 */
        int                        inp_flags2;           /*   112     4 */
        u_char                     inp_vflag;            /*   116     1 */
        u_char                     inp_ip_ttl;           /*   117     1 */
        u_char                     inp_ip_p;             /*   118     1 */
        u_char                     inp_ip_minttl;        /*   119     1 */
        uint32_t                   inp_flowid;           /*   120     4 */
        u_int                      inp_refcount;         /*   124     4 */
        /* --- cacheline 2 boundary (128 bytes) --- */
structhole.c:166: get_member_size: dwarf_aggregate_size: (null)(0)

@cemeyer
Copy link
Owner

cemeyer commented Oct 1, 2014

The next member is void *inp_pspare[5];. Maybe dwarf_aggregate_size is busted on Clang's output for void *, if not all pointers?

Dang. libdw errors with "invalid DWARF" just trying to read efs.ko. But I confirmed that dwarf_aggregate_size also doesn't work on a struct l3_drive *l3m_drives[...]. Sigh.

@cemeyer
Copy link
Owner

cemeyer commented Oct 1, 2014

@cemeyer
Copy link
Owner

cemeyer commented Oct 2, 2014

With the modified patch from upstream elfutils, I get:

struct inpcb {
        struct (null)              inp_hash;             /*     0    16 */
        struct (null)              inp_pcbgrouphash;     /*    16    16 */
        struct (null)              inp_list;             /*    32    16 */
        (null)                     inp_ppcb;             /*    48     8 */
        (null)                     inp_pcbinfo;          /*    56     8 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        (null)                     inp_pcbgroup;         /*    64     8 */
        struct (null)              inp_pcbgroup_wild;    /*    72    16 */
        (null)                     inp_socket;           /*    88     8 */
        (null)                     inp_cred;             /*    96     8 */
        u_int32_t                  inp_flow;             /*   104     4 */
        int                        inp_flags;            /*   108     4 */
        int                        inp_flags2;           /*   112     4 */
        u_char                     inp_vflag;            /*   116     1 */
        u_char                     inp_ip_ttl;           /*   117     1 */
        u_char                     inp_ip_p;             /*   118     1 */
        u_char                     inp_ip_minttl;        /*   119     1 */
        uint32_t                   inp_flowid;           /*   120     4 */
        u_int                      inp_refcount;         /*   124     4 */
        /* --- cacheline 2 boundary (128 bytes) --- */
        (null)                     inp_pspare;           /*   128    40 */
        (null)                     inp_ispare;           /*   168    24 */
        /* --- cacheline 3 boundary (192 bytes) --- */
        struct in_conninfo         inp_inc;              /*   192    40 */
        (null)                     inp_label;            /*   232     8 */
        (null)                     inp_sp;               /*   240     8 */
        struct (null)              inp_depend4;          /*   248    24 */
        /* --- cacheline 4 boundary (256 bytes) was 16 bytes ago --- */
        struct (null)              inp_depend6;          /*   272    40 */
        struct (null)              inp_portlist;         /*   312    16 */
        /* --- cacheline 5 boundary (320 bytes) was 8 bytes ago --- */
        (null)                     inp_phd;              /*   328     8 */
        inp_gen_t                  inp_gencnt;           /*   336     8 */
        (null)                     inp_lle;              /*   344     8 */
        (null)                     inp_rt;               /*   352     8 */
        struct rwlock              inp_lock;             /*   360    32 */
        /* --- cacheline 6 boundary (384 bytes) was 8 bytes ago --- */

        /* size: 392, cachelines: 7, members: 31 */
        /* sum members: 392, holes: 0, sum holes: 0 */
        /* last cacheline: 8 bytes */
};

More progress! Adding support for formatting pointer and array type names is clearly needed. Pahole(1) manages to dump out sub struct definitions as well, we should probably be able to do that eventually.

@cemeyer cemeyer closed this as completed in fffc31a Oct 2, 2014
@cemeyer
Copy link
Owner

cemeyer commented Oct 2, 2014

You can now get size for void*. Issue fixed! (What, you want the type name too? Hah.) (You will need an elfutils fix that isn't present in 0.160, something like "libdw: dwarf_aggregate_size return CU address_size for sizeless pointer/refs.")

struct inpcb {
        struct <anonymous>         inp_hash;             /*     0    16 */
        struct <anonymous>         inp_pcbgrouphash;     /*    16    16 */
        struct <anonymous>         inp_list;             /*    32    16 */
        <anonymous> *              inp_ppcb;             /*    48     8 */
        struct inpcbinfo *         inp_pcbinfo;          /*    56     8 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        struct inpcbgroup *        inp_pcbgroup;         /*    64     8 */
        struct <anonymous>         inp_pcbgroup_wild;    /*    72    16 */
        struct socket *            inp_socket;           /*    88     8 */
        struct ucred *             inp_cred;             /*    96     8 */
        u_int32_t                  inp_flow;             /*   104     4 */
        int                        inp_flags;            /*   108     4 */
        int                        inp_flags2;           /*   112     4 */
        u_char                     inp_vflag;            /*   116     1 */
        u_char                     inp_ip_ttl;           /*   117     1 */
        u_char                     inp_ip_p;             /*   118     1 */
        u_char                     inp_ip_minttl;        /*   119     1 */
        uint32_t                   inp_flowid;           /*   120     4 */
        u_int                      inp_refcount;         /*   124     4 */
        /* --- cacheline 2 boundary (128 bytes) --- */
        <anonymous>                inp_pspare;           /*   128    40 */
        <anonymous>                inp_ispare;           /*   168    24 */
        /* --- cacheline 3 boundary (192 bytes) --- */
        struct in_conninfo         inp_inc;              /*   192    40 */
        struct label *             inp_label;            /*   232     8 */
        struct inpcbpolicy *       inp_sp;               /*   240     8 */
        struct <anonymous>         inp_depend4;          /*   248    24 */
        /* --- cacheline 4 boundary (256 bytes) was 16 bytes ago --- */
        struct <anonymous>         inp_depend6;          /*   272    40 */
        struct <anonymous>         inp_portlist;         /*   312    16 */
        /* --- cacheline 5 boundary (320 bytes) was 8 bytes ago --- */
        struct inpcbport *         inp_phd;              /*   328     8 */
        inp_gen_t                  inp_gencnt;           /*   336     8 */
        struct llentry *           inp_lle;              /*   344     8 */
        struct rtentry *           inp_rt;               /*   352     8 */
        struct rwlock              inp_lock;             /*   360    32 */
        /* --- cacheline 6 boundary (384 bytes) was 8 bytes ago --- */

        /* size: 392, cachelines: 7, members: 31 */
        /* sum members: 392, holes: 0, sum holes: 0 */
        /* last cacheline: 8 bytes */
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants