Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Jan 2019 21:15:51 -0800
From:      Mark Millard <marklmi@yahoo.com>
To:        Kyle Evans <kevans@FreeBSD.org>, freebsd-emulation@freebsd.org, ports-list freebsd <freebsd-ports@freebsd.org>
Cc:        Sean Bruno <sbruno@freebsd.org>, freebsd-arm <freebsd-arm@freebsd.org>
Subject:   qemu-arm-static has target_freebsd11_nstat too small vs. arm native's struct nstat
Message-ID:  <62F581E3-EBB6-4980-BD20-4E121D64BBC5@yahoo.com>

next in thread | raw e-mail | index | archive | help
[The context here is FreeBSD head -r341836 based and ports head -r488859 =
based.]

Note: I assume that "struct target_shmd_ds" is meant to match the memory =
layout
of the target's native "struct shmid_ds". Otherwise the reported =
differences
below could be irrelevant.

For armv7 (and likely armv6) the following code:

        printf("sizeof(struct nstat) =3D %lu\n", (unsigned long) =
sizeof(struct nstat));
        printf("st_dev %lu\n", (unsigned long) offsetof(struct nstat, =
st_dev));
        printf("st_ino %lu\n", (unsigned long) offsetof(struct nstat, =
st_ino));
        printf("st_mode %lu\n", (unsigned long) offsetof(struct nstat, =
st_mode));
        printf("st_nlink %lu\n", (unsigned long) offsetof(struct nstat, =
st_nlink));
        printf("st_uid %lu\n", (unsigned long) offsetof(struct nstat, =
st_uid));
        printf("st_gid %lu\n", (unsigned long) offsetof(struct nstat, =
st_gid));
        printf("st_rdev %lu\n", (unsigned long) offsetof(struct nstat, =
st_rdev));
        printf("st_atim %lu\n", (unsigned long) offsetof(struct nstat, =
st_atim));
        printf("st_mtim %lu\n", (unsigned long) offsetof(struct nstat, =
st_mtim));
        printf("st_ctim %lu\n", (unsigned long) offsetof(struct nstat, =
st_ctim));
        printf("st_size %lu\n", (unsigned long) offsetof(struct nstat, =
st_size));
        printf("st_blocks %lu\n", (unsigned long) offsetof(struct nstat, =
st_blocks));
        printf("st_blksize %lu\n", (unsigned long) offsetof(struct =
nstat, st_blksize));
        printf("st_flags %lu\n", (unsigned long) offsetof(struct nstat, =
st_flags));
        printf("st_gen %lu\n", (unsigned long) offsetof(struct nstat, =
st_gen));
        printf("st_birthtim %lu\n", (unsigned long) offsetof(struct =
nstat, st_birthtim));

produces:

sizeof(struct nstat) =3D 128
st_dev 0
st_ino 4
st_mode 8
st_nlink 12
st_uid 16
st_gid 20
st_rdev 24
st_atim 32
st_mtim 48
st_ctim 64
st_size 80
st_blocks 88
st_blksize 96
st_flags 100
st_gen 104
st_birthtim 112

However gdb reports for qemu-arm-static (on amd64):

(gdb) p/d sizeof(struct target_freebsd11_nstat)
$41 =3D 116
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_dev  =20
$42 =3D 0
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_ino
$43 =3D 4
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_mode
$44 =3D 8
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_nlink
$45 =3D 10
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_uid =20
$46 =3D 12
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_gid
$47 =3D 16
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_rdev
$48 =3D 20
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_atim
$49 =3D 24
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_mtim  =20
$50 =3D 40
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_ctim
$51 =3D 56
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_size  =20
$52 =3D 72
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_blocks
$53 =3D 80
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_blksize
$54 =3D 88
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_flags =20
$55 =3D 92
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_gen =20
$56 =3D 96
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_birthtim
$57 =3D 100

So after st_mode the offsets are wrong relative to struct nstat
(native to armv7).

/usr/include/sys/stat.h has:

struct nstat {
        __uint32_t st_dev;              /* inode's device */
        __uint32_t st_ino;              /* inode's number */
        __uint32_t st_mode;             /* inode protection mode */
        __uint32_t st_nlink;            /* number of hard links */
        uid_t     st_uid;               /* user ID of the file's owner =
*/
        gid_t     st_gid;               /* group ID of the file's group =
*/
        __uint32_t st_rdev;             /* device type */
        struct  timespec st_atim;       /* time of last access */
        struct  timespec st_mtim;       /* time of last data =
modification */
        struct  timespec st_ctim;       /* time of last file status =
change */
        off_t     st_size;              /* file size, in bytes */
        blkcnt_t st_blocks;             /* blocks allocated for file */
        blksize_t st_blksize;           /* optimal blocksize for I/O */
        fflags_t  st_flags;             /* user defined flags for file =
*/
        __uint32_t st_gen;              /* file generation number */
        struct timespec st_birthtim;    /* time of file creation */
        /*
         * See comment in the definition of struct freebsd11_stat
         * above about the following padding.
         */
        unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
        unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
};

=
/wrkdirs/usr/ports/emulators/qemu-user-static/work/qemu-bsd-user-4ef7d07/b=
sd-user/syscall_defs.h
has:

struct target_freebsd11_nstat {
    uint32_t  st_dev;       /* inode's device */
    uint32_t  st_ino;       /* inode's number */
    int16_t   st_mode;      /* inode protection mode */
    int16_t   st_nlink;     /* number of hard links */
    uint32_t  st_uid;       /* user ID of the file's owner */
    uint32_t  st_gid;       /* group ID of the file's group */
    uint32_t  st_rdev;      /* device type */
    struct  target_freebsd_timespec st_atim; /* time last accessed */
    struct  target_freebsd_timespec st_mtim; /* time last data =
modification */
    struct  target_freebsd_timespec st_ctim; /* time last file status =
change */
    int64_t    st_size;     /* file size, in bytes */
    int64_t    st_blocks;   /* blocks allocated for file */
    uint32_t   st_blksize;  /* optimal blocksize for I/O */
    uint32_t   st_flags;    /* user defined flags for file */
    __uint32_t st_gen;      /* file generation number */
    /* __int32_t  st_lspare; */
    struct target_freebsd_timespec st_birthtim; /* time of file creation =
*/
    /*
     * Explicitly pad st_birthtim to 16 bytes so that the size of
     * struct stat is backwards compatible.  We use bitfields instead
     * of an array of chars so that this doesn't require a C99 compiler
     * to compile if the size of the padding is 0.  We use 2 bitfields
     * to cover up to 64 bits on 32-bit machines.  We assume that
     * CHAR_BIT is 8...
     */
    unsigned int:(8 / 2) * (16 - (int)sizeof(struct =
target_freebsd_timespec));
    unsigned int:(8 / 2) * (16 - (int)sizeof(struct =
target_freebsd_timespec));
} __packed;

There are multiple issues here, for example: __uint32_t (native nstat) =
vs. int16_t
(target_nstat) for st_mode. Similarly for st_nlink. And there is =
__packed changing
the padding for another example.




=3D=3D=3D
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?62F581E3-EBB6-4980-BD20-4E121D64BBC5>