qemu-arm-static has target_freebsd11_nstat too small vs. arm native's struct nstat
Mark Millard
marklmi at yahoo.com
Sun Jan 6 05:16:02 UTC 2019
[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)
More information about the freebsd-emulation
mailing list