qemu-arm-static has target_freebsd11_nstat too small vs. arm native's struct nstat

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

qemu-arm-static has target_freebsd11_nstat too small vs. arm native's struct nstat

freebsd-emulation mailing list
[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) = %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) = 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 = 116
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_dev  
$42 = 0
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_ino
$43 = 4
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_mode
$44 = 8
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_nlink
$45 = 10
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_uid  
$46 = 12
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_gid
$47 = 16
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_rdev
$48 = 20
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_atim
$49 = 24
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_mtim  
$50 = 40
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_ctim
$51 = 56
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_size  
$52 = 72
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_blocks
$53 = 80
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_blksize
$54 = 88
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_flags  
$55 = 92
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_gen  
$56 = 96
(gdb) p/d &((struct target_freebsd11_nstat *)0)->st_birthtim
$57 = 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/bsd-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.




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

_______________________________________________
[hidden email] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-emulation
To unsubscribe, send any mail to "[hidden email]"