From 4de596cb5092fbe125beb5e0b684cf0da7359624 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 15 Feb 2011 21:10:43 +0100 Subject: [PATCH 1/5] linux-user: add rmdir() strace Signed-off-by: Laurent Vivier Signed-off-by: Riku Voipio --- linux-user/strace.c | 12 ++++++++++++ linux-user/strace.list | 3 +++ 2 files changed, 15 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 18366661cd..05277c0183 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -876,6 +876,18 @@ print_mkdirat(const struct syscallname *name, } #endif +#ifdef TARGET_NR_rmdir +static void +print_rmdir(const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_string(arg0, 0); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_mknod static void print_mknod(const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index d7be0e7a68..563a67f0a2 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -495,6 +495,9 @@ #ifdef TARGET_NR_mkdirat { TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL }, #endif +#ifdef TARGET_NR_rmdir +{ TARGET_NR_rmdir, "rmdir" , NULL, print_rmdir, NULL }, +#endif #ifdef TARGET_NR_mknod { TARGET_NR_mknod, "mknod" , NULL, print_mknod, NULL }, #endif From d2ee72a5b17d95fe0e57e496f1b2ddb2464b5c08 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 15 Feb 2011 21:10:44 +0100 Subject: [PATCH 2/5] linux-user: in linux-user/strace.c, tswap() is useless Syscall parameters are already swapped by the caller. This patch removes useless tswap() from strace.c $ QEMU_STRACE=1 chroot /m68k mknod myramdisk b 1 1 with tswap() ... 29944 mknod("myramdisk",026630200000) = 0 ... without tswap() ... 30042 mknod("myramdisk",S_IFBLK|0666,makedev(1,1)) = 0 ... natively: $ strace touch mytouch ... open("mytouch", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3 ... $ QEMU_STRACE=1 chroot /m68k touch mytouch with tswap() ... 30368 open("/usr/share/locale/locale.alias",O_RDONLY) = 3 30368 fstat64(50331648,0x4080032c) = 0 ... 30368 open("mytouch",O_RDONLY|O_CREAT|O_LARGEFILE|O_NOCTTY|O_NONBLOCK|0x1) = 0 ... without tswap() ... 30572 open("/usr/share/locale/locale.alias",O_RDONLY) = 3 30572 fstat64(3,0x4080032c) = 0 ... 30572 open("mytouch",O_WRONLY|O_CREAT|O_LARGEFILE|O_NOCTTY|O_NONBLOCK,0666) = 0 Signed-off-by: Laurent Vivier Fixes by Riku Voipio: add casts Signed-off-by: Riku Voipio --- linux-user/strace.c | 79 +++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 05277c0183..8dd398b9f2 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -441,14 +441,11 @@ get_comma(int last) } static void -print_flags(const struct flags *f, abi_long tflags, int last) +print_flags(const struct flags *f, abi_long flags, int last) { const char *sep = ""; - int flags; int n; - flags = (int)tswap32(tflags); - if ((flags == 0) && (f->f_value == 0)) { gemu_log("%s%s", f->f_string, get_comma(last)); return; @@ -465,36 +462,33 @@ print_flags(const struct flags *f, abi_long tflags, int last) if (n > 0) { /* print rest of the flags as numeric */ if (flags != 0) { - gemu_log("%s%#x%s", sep, flags, get_comma(last)); + gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last)); } else { gemu_log("%s", get_comma(last)); } } else { /* no string version of flags found, print them in hex then */ - gemu_log("%#x%s", flags, get_comma(last)); + gemu_log("%#x%s", (unsigned int)flags, get_comma(last)); } } static void -print_at_dirfd(abi_long tdirfd, int last) +print_at_dirfd(abi_long dirfd, int last) { - int dirfd = tswap32(tdirfd); - #ifdef AT_FDCWD if (dirfd == AT_FDCWD) { gemu_log("AT_FDCWD%s", get_comma(last)); return; } #endif - gemu_log("%d%s", dirfd, get_comma(last)); + gemu_log("%d%s", (int)dirfd, get_comma(last)); } static void -print_file_mode(abi_long tmode, int last) +print_file_mode(abi_long mode, int last) { const char *sep = ""; const struct flags *m; - mode_t mode = (mode_t)tswap32(tmode); for (m = &mode_flags[0]; m->f_string != NULL; m++) { if ((m->f_value & mode) == m->f_value) { @@ -508,16 +502,14 @@ print_file_mode(abi_long tmode, int last) mode &= ~S_IFMT; /* print rest of the mode as octal */ if (mode != 0) - gemu_log("%s%#o", sep, mode); + gemu_log("%s%#o", sep, (unsigned int)mode); gemu_log("%s", get_comma(last)); } static void -print_open_flags(abi_long tflags, int last) +print_open_flags(abi_long flags, int last) { - int flags = tswap32(tflags); - print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1); flags &= ~TARGET_O_ACCMODE; if (flags == 0) { @@ -620,7 +612,7 @@ print_accept(const struct syscallname *name, abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); - print_raw_param("%d", tswap32(arg0), 0); + print_raw_param("%d", arg0, 0); print_pointer(arg1, 0); print_number(arg2, 1); print_syscall_epilogue(name); @@ -698,7 +690,7 @@ print_execv(const struct syscallname *name, { print_syscall_prologue(name); print_string(arg0, 0); - print_raw_param("0x" TARGET_ABI_FMT_lx, tswapl(arg1), 1); + print_raw_param("0x" TARGET_ABI_FMT_lx, arg1, 1); print_syscall_epilogue(name); } #endif @@ -742,13 +734,8 @@ print_fchownat(const struct syscallname *name, print_syscall_prologue(name); print_at_dirfd(arg0, 0); print_string(arg1, 0); -#ifdef USE_UID16 - print_raw_param("%d", tswap16(arg2), 0); - print_raw_param("%d", tswap16(arg3), 0); -#else - print_raw_param("%d", tswap32(arg2), 0); - print_raw_param("%d", tswap32(arg3), 0); -#endif + print_raw_param("%d", arg2, 0); + print_raw_param("%d", arg3, 0); print_flags(at_file_flags, arg4, 1); print_syscall_epilogue(name); } @@ -761,7 +748,7 @@ print_fcntl(const struct syscallname *name, abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); - print_raw_param("%d", tswap32(arg0), 0); + print_raw_param("%d", arg0, 0); print_flags(fcntl_flags, arg1, 0); /* * TODO: check flags and print following argument only @@ -842,7 +829,7 @@ print_fstat(const struct syscallname *name, abi_long arg3, abi_long arg4, abi_long arg5) { print_syscall_prologue(name); - print_raw_param("%d", tswap32(arg0), 0); + print_raw_param("%d", arg0, 0); print_pointer(arg1, 1); print_syscall_epilogue(name); } @@ -894,14 +881,14 @@ print_mknod(const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - int hasdev = (tswapl(arg1) & (S_IFCHR|S_IFBLK)); + int hasdev = (arg1 & (S_IFCHR|S_IFBLK)); print_syscall_prologue(name); print_string(arg0, 0); print_file_mode(arg1, (hasdev == 0)); if (hasdev) { - print_raw_param("makedev(%d", major(tswapl(arg2)), 0); - print_raw_param("%d)", minor(tswapl(arg2)), 1); + print_raw_param("makedev(%d", major(arg2), 0); + print_raw_param("%d)", minor(arg2), 1); } print_syscall_epilogue(name); } @@ -913,15 +900,15 @@ print_mknodat(const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - int hasdev = (tswapl(arg2) & (S_IFCHR|S_IFBLK)); + int hasdev = (arg2 & (S_IFCHR|S_IFBLK)); print_syscall_prologue(name); print_at_dirfd(arg0, 0); print_string(arg1, 0); print_file_mode(arg2, (hasdev == 0)); if (hasdev) { - print_raw_param("makedev(%d", major(tswapl(arg3)), 0); - print_raw_param("%d)", minor(tswapl(arg3)), 1); + print_raw_param("makedev(%d", major(arg3), 0); + print_raw_param("%d)", minor(arg3), 1); } print_syscall_epilogue(name); } @@ -933,7 +920,7 @@ print_mq_open(const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - int is_creat = (tswapl(arg1) & TARGET_O_CREAT); + int is_creat = (arg1 & TARGET_O_CREAT); print_syscall_prologue(name); print_string(arg0, 0); @@ -952,7 +939,7 @@ print_open(const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - int is_creat = (tswap32(arg1) & TARGET_O_CREAT); + int is_creat = (arg1 & TARGET_O_CREAT); print_syscall_prologue(name); print_string(arg0, 0); @@ -969,7 +956,7 @@ print_openat(const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { - int is_creat = (tswap32(arg2) & TARGET_O_CREAT); + int is_creat = (arg2 & TARGET_O_CREAT); print_syscall_prologue(name); print_at_dirfd(arg0, 0); @@ -1018,7 +1005,7 @@ print_readlink(const struct syscallname *name, print_syscall_prologue(name); print_string(arg0, 0); print_pointer(arg1, 0); - print_raw_param("%u", tswapl(arg2), 1); + print_raw_param("%u", arg2, 1); print_syscall_epilogue(name); } #endif @@ -1033,7 +1020,7 @@ print_readlinkat(const struct syscallname *name, print_at_dirfd(arg0, 0); print_string(arg1, 0); print_pointer(arg2, 0); - print_raw_param("%u", tswapl(arg3), 1); + print_raw_param("%u", arg3, 1); print_syscall_epilogue(name); } #endif @@ -1223,11 +1210,11 @@ print_mmap(const struct syscallname *name, { print_syscall_prologue(name); print_pointer(arg0, 0); - print_raw_param("%d", tswapl(arg1), 0); + print_raw_param("%d", arg1, 0); print_flags(mmap_prot_flags, arg2, 0); print_flags(mmap_flags, arg3, 0); - print_raw_param("%d", tswapl(arg4), 0); - print_raw_param("%#x", tswapl(arg5), 1); + print_raw_param("%d", arg4, 0); + print_raw_param("%#x", arg5, 1); print_syscall_epilogue(name); } #define print_mmap2 print_mmap @@ -1241,7 +1228,7 @@ print_mprotect(const struct syscallname *name, { print_syscall_prologue(name); print_pointer(arg0, 0); - print_raw_param("%d", tswapl(arg1), 0); + print_raw_param("%d", arg1, 0); print_flags(mmap_prot_flags, arg2, 1); print_syscall_epilogue(name); } @@ -1255,7 +1242,7 @@ print_munmap(const struct syscallname *name, { print_syscall_prologue(name); print_pointer(arg0, 0); - print_raw_param("%d", tswapl(arg1), 1); + print_raw_param("%d", arg1, 1); print_syscall_epilogue(name); } #endif @@ -1269,7 +1256,7 @@ if( cmd == val ) { \ return; \ } - int cmd = (int)tswap32(tflag); + int cmd = (int)tflag; #ifdef FUTEX_PRIVATE_FLAG if (cmd & FUTEX_PRIVATE_FLAG) { gemu_log("FUTEX_PRIVATE_FLAG|"); @@ -1303,10 +1290,10 @@ print_futex(const struct syscallname *name, print_syscall_prologue(name); print_pointer(arg0, 0); print_futex_op(arg1, 0); - print_raw_param(",%d", tswapl(arg2), 0); + print_raw_param(",%d", arg2, 0); print_pointer(arg3, 0); /* struct timespec */ print_pointer(arg4, 0); - print_raw_param("%d", tswapl(arg4), 1); + print_raw_param("%d", arg4, 1); print_syscall_epilogue(name); } #endif From 3b6edd1611e25099a1df20771ce3f88939a0e93a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 15 Feb 2011 18:35:05 +0000 Subject: [PATCH 3/5] linux-user: Support the epoll syscalls Support the epoll family of syscalls: epoll_create(), epoll_create1(), epoll_ctl(), epoll_wait() and epoll_pwait(). Note that epoll_create1() and epoll_pwait() are later additions, so we have to test separately in configure for their presence. Signed-off-by: Peter Maydell Signed-off-by: Riku Voipio --- configure | 54 +++++++++++++++++++ linux-user/syscall.c | 107 ++++++++++++++++++++++++++++++++++++++ linux-user/syscall_defs.h | 13 +++++ 3 files changed, 174 insertions(+) diff --git a/configure b/configure index a3f53456f4..cb72ced129 100755 --- a/configure +++ b/configure @@ -2142,6 +2142,51 @@ if compile_prog "" "" ; then dup3=yes fi +# check for epoll support +epoll=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_create(0); + return 0; +} +EOF +if compile_prog "$ARCH_CFLAGS" "" ; then + epoll=yes +fi + +# epoll_create1 and epoll_pwait are later additions +# so we must check separately for their presence +epoll_create1=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_create1(0); + return 0; +} +EOF +if compile_prog "$ARCH_CFLAGS" "" ; then + epoll_create1=yes +fi + +epoll_pwait=no +cat > $TMPC << EOF +#include + +int main(void) +{ + epoll_pwait(0, 0, 0, 0, 0); + return 0; +} +EOF +if compile_prog "$ARCH_CFLAGS" "" ; then + epoll_pwait=yes +fi + # Check if tools are available to build documentation. if test "$docs" != "no" ; then if has makeinfo && has pod2man; then @@ -2674,6 +2719,15 @@ fi if test "$dup3" = "yes" ; then echo "CONFIG_DUP3=y" >> $config_host_mak fi +if test "$epoll" = "yes" ; then + echo "CONFIG_EPOLL=y" >> $config_host_mak +fi +if test "$epoll_create1" = "yes" ; then + echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak +fi +if test "$epoll_pwait" = "yes" ; then + echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak +fi if test "$inotify" = "yes" ; then echo "CONFIG_INOTIFY=y" >> $config_host_mak fi diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4412a9b143..cf8a4c3876 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -66,6 +66,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #ifdef CONFIG_EVENTFD #include #endif +#ifdef CONFIG_EPOLL +#include +#endif #define termios host_termios #define winsize host_winsize @@ -7611,6 +7614,110 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif break; #endif +#endif +#if defined(CONFIG_EPOLL) +#if defined(TARGET_NR_epoll_create) + case TARGET_NR_epoll_create: + ret = get_errno(epoll_create(arg1)); + break; +#endif +#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1) + case TARGET_NR_epoll_create1: + ret = get_errno(epoll_create1(arg1)); + break; +#endif +#if defined(TARGET_NR_epoll_ctl) + case TARGET_NR_epoll_ctl: + { + struct epoll_event ep; + struct epoll_event *epp = 0; + if (arg4) { + struct target_epoll_event *target_ep; + if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { + goto efault; + } + ep.events = tswap32(target_ep->events); + /* The epoll_data_t union is just opaque data to the kernel, + * so we transfer all 64 bits across and need not worry what + * actual data type it is. + */ + ep.data.u64 = tswap64(target_ep->data.u64); + unlock_user_struct(target_ep, arg4, 0); + epp = &ep; + } + ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp)); + break; + } +#endif + +#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT) +#define IMPLEMENT_EPOLL_PWAIT +#endif +#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT) +#if defined(TARGET_NR_epoll_wait) + case TARGET_NR_epoll_wait: +#endif +#if defined(IMPLEMENT_EPOLL_PWAIT) + case TARGET_NR_epoll_pwait: +#endif + { + struct target_epoll_event *target_ep; + struct epoll_event *ep; + int epfd = arg1; + int maxevents = arg3; + int timeout = arg4; + + target_ep = lock_user(VERIFY_WRITE, arg2, + maxevents * sizeof(struct target_epoll_event), 1); + if (!target_ep) { + goto efault; + } + + ep = alloca(maxevents * sizeof(struct epoll_event)); + + switch (num) { +#if defined(IMPLEMENT_EPOLL_PWAIT) + case TARGET_NR_epoll_pwait: + { + target_sigset_t *target_set; + sigset_t _set, *set = &_set; + + if (arg5) { + target_set = lock_user(VERIFY_READ, arg5, + sizeof(target_sigset_t), 1); + if (!target_set) { + unlock_user(target_ep, arg2, 0); + goto efault; + } + target_to_host_sigset(set, target_set); + unlock_user(target_set, arg5, 0); + } else { + set = NULL; + } + + ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set)); + break; + } +#endif +#if defined(TARGET_NR_epoll_wait) + case TARGET_NR_epoll_wait: + ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout)); + break; +#endif + default: + ret = -TARGET_ENOSYS; + } + if (!is_error(ret)) { + int i; + for (i = 0; i < ret; i++) { + target_ep[i].events = tswap32(ep[i].events); + target_ep[i].data.u64 = tswap64(ep[i].data.u64); + } + } + unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event)); + break; + } +#endif #endif default: unimplemented: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 4742ac0272..702652cb9e 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2206,3 +2206,16 @@ struct target_mq_attr { #define FUTEX_CLOCK_REALTIME 256 #define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) +#ifdef CONFIG_EPOLL +typedef union target_epoll_data { + abi_ulong ptr; + abi_ulong fd; + uint32_t u32; + uint64_t u64; +} target_epoll_data_t; + +struct target_epoll_event { + uint32_t events; + target_epoll_data_t data; +}; +#endif From c2e3dee6e03527baf8698698cce76b1a3174969a Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sun, 13 Feb 2011 23:37:34 +0100 Subject: [PATCH 4/5] linux-user: Define target alignment size Datatype alignment can be found using following application: int main(void) { printf("alignof(short) %ld\n", __alignof__(short)); printf("alignof(int) %ld\n", __alignof__(int)); printf("alignof(long) %ld\n", __alignof__(long)); printf("alignof(long long) %ld\n", __alignof__(long long)); } This patch includes following alignments: i386 alignof(short) 2 alignof(int) 4 alignof(long) 4 alignof(long long) 8 x86_64 alignof(short) 2 alignof(int) 4 alignof(long) 8 alignof(long long) 8 arm alignof(short) 2 alignof(int) 4 alignof(long) 4 alignof(long long) 4 m68k (680x0) alignof(short) 2 alignof(int) 2 alignof(long) 2 alignof(long long) 2 mips alignof(short) 2 alignof(int) 4 alignof(long) 4 alignof(long long) 8 ppc alignof(short) 2 alignof(int) 4 alignof(long) 4 alignof(long long) 8 for other targets, use by default (2,4,4,8). Please, update for your favorite target... Signed-off-by: Laurent Vivier Signed-off-by: Riku Voipio --- configure | 17 +++++++++++++++++ cpu-defs.h | 14 ++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/configure b/configure index cb72ced129..fe00036dbd 100755 --- a/configure +++ b/configure @@ -2962,6 +2962,10 @@ target_nptl="no" interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"` echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak gdb_xml_files="" +target_short_alignment=2 +target_int_alignment=4 +target_long_alignment=4 +target_llong_alignment=8 TARGET_ARCH="$target_arch2" TARGET_BASE_ARCH="" @@ -2974,9 +2978,11 @@ case "$target_arch2" in x86_64) TARGET_BASE_ARCH=i386 target_phys_bits=64 + target_long_alignment=8 ;; alpha) target_phys_bits=64 + target_long_alignment=8 target_nptl="yes" ;; arm|armeb) @@ -2985,6 +2991,7 @@ case "$target_arch2" in target_nptl="yes" gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml" target_phys_bits=32 + target_llong_alignment=4 ;; cris) target_nptl="yes" @@ -2994,6 +3001,9 @@ case "$target_arch2" in bflt="yes" gdb_xml_files="cf-core.xml cf-fp.xml" target_phys_bits=32 + target_int_alignment=2 + target_long_alignment=2 + target_llong_alignment=2 ;; microblaze) bflt="yes" @@ -3017,6 +3027,7 @@ case "$target_arch2" in TARGET_BASE_ARCH=mips echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak target_phys_bits=64 + target_long_alignment=8 ;; ppc) gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml" @@ -3035,6 +3046,7 @@ case "$target_arch2" in TARGET_ABI_DIR=ppc gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml" target_phys_bits=64 + target_long_alignment=8 ;; ppc64abi32) TARGET_ARCH=ppc64 @@ -3056,6 +3068,7 @@ case "$target_arch2" in sparc64) TARGET_BASE_ARCH=sparc target_phys_bits=64 + target_long_alignment=8 ;; sparc32plus) TARGET_ARCH=sparc64 @@ -3072,6 +3085,10 @@ case "$target_arch2" in exit 1 ;; esac +echo "TARGET_SHORT_ALIGNMENT=$target_short_alignment" >> $config_target_mak +echo "TARGET_INT_ALIGNMENT=$target_int_alignment" >> $config_target_mak +echo "TARGET_LONG_ALIGNMENT=$target_long_alignment" >> $config_target_mak +echo "TARGET_LLONG_ALIGNMENT=$target_llong_alignment" >> $config_target_mak echo "TARGET_ARCH=$TARGET_ARCH" >> $config_target_mak target_arch_name="`echo $TARGET_ARCH | tr '[:lower:]' '[:upper:]'`" echo "TARGET_$target_arch_name=y" >> $config_target_mak diff --git a/cpu-defs.h b/cpu-defs.h index db809ed465..2b59fa6fb0 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -37,16 +37,22 @@ #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) +typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT))); +typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT))); +typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT))); +typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT))); +typedef int64_t target_llong __attribute__((aligned(TARGET_LLONG_ALIGNMENT))); +typedef uint64_t target_ullong __attribute__((aligned(TARGET_LLONG_ALIGNMENT))); /* target_ulong is the type of a virtual address */ #if TARGET_LONG_SIZE == 4 -typedef int32_t target_long; -typedef uint32_t target_ulong; +typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT))); +typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT))); #define TARGET_FMT_lx "%08x" #define TARGET_FMT_ld "%d" #define TARGET_FMT_lu "%u" #elif TARGET_LONG_SIZE == 8 -typedef int64_t target_long; -typedef uint64_t target_ulong; +typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT))); +typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT))); #define TARGET_FMT_lx "%016" PRIx64 #define TARGET_FMT_ld "%" PRId64 #define TARGET_FMT_lu "%" PRIu64 From 80f5ce758ac277e76c016dd7c0b246e40d4fca2d Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sun, 13 Feb 2011 23:37:35 +0100 Subject: [PATCH 5/5] linux-user: correct core dump format This patch allows to really use the core dumped by qemu with guest architecture tools. - it adds a missing bswap_phdr() for the program headers of memory regions. "objdump -x" sample: BEFORE: 0x1000000 off 0x00200000 vaddr 0x00000400 paddr 0x00000000 align 2**21 filesz 0x00000000 memsz 0x00100000 flags --- 0x1000000 off 0x00200000 vaddr 0x00100400 paddr 0x00000000 align 2**21 filesz 0x00000000 memsz 0x00080000 flags --- 6000000 AFTER: LOAD off 0x00002000 vaddr 0x00040000 paddr 0x00000000 align 2**13 filesz 0x00000000 memsz 0x00001000 flags --- LOAD off 0x00002000 vaddr 0x00041000 paddr 0x00000000 align 2**13 filesz 0x00000000 memsz 0x00000800 flags rw- - it doesn't pad the note size to sizeof(int32_t). On m68k the NT_PRSTATUS note size is 154 and must not be rounded up to 156, because this value is checked by objdump and gdb. "gdb" symptoms: "warning: Couldn't find general-purpose registers in core file." "objdump -x" sample: BEFORE: Sections: Idx Name Size VMA LMA File off Algn 0 note0 000001c4 00000000 00000000 000003b4 2**0 CONTENTS, READONLY 1 .auxv 00000070 00000000 00000000 00000508 2**2 CONTENTS 2 proc1 00100000 00000400 00000000 00200000 2**10 READONLY AFTER: Sections: Idx Name Size VMA LMA File off Algn 0 note0 000001c4 00000000 00000000 000003b4 2**0 CONTENTS, READONLY 1 .reg/19022 00000050 00000000 00000000 0000040e 2**2 CONTENTS 2 .reg 00000050 00000000 00000000 0000040e 2**2 CONTENTS 3 .auxv 00000070 00000000 00000000 00000508 2**2 CONTENTS 4 load1 00000000 00040000 00000000 00002000 2**13 ALLOC, READONLY Signed-off-by: Laurent Vivier Signed-off-by: Riku Voipio --- linux-user/elfload.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 2de83e4bfb..fe5410e6f9 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -103,13 +103,13 @@ enum { typedef target_ulong target_elf_greg_t; #ifdef USE_UID16 -typedef uint16_t target_uid_t; -typedef uint16_t target_gid_t; +typedef target_ushort target_uid_t; +typedef target_ushort target_gid_t; #else -typedef uint32_t target_uid_t; -typedef uint32_t target_gid_t; +typedef target_uint target_uid_t; +typedef target_uint target_gid_t; #endif -typedef int32_t target_pid_t; +typedef target_int target_pid_t; #ifdef TARGET_I386 @@ -1761,19 +1761,20 @@ struct memelfnote { size_t namesz_rounded; int type; size_t datasz; + size_t datasz_rounded; void *data; size_t notesz; }; struct target_elf_siginfo { - int si_signo; /* signal number */ - int si_code; /* extra code */ - int si_errno; /* errno */ + target_int si_signo; /* signal number */ + target_int si_code; /* extra code */ + target_int si_errno; /* errno */ }; struct target_elf_prstatus { struct target_elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ + target_short pr_cursig; /* Current signal */ target_ulong pr_sigpend; /* XXX */ target_ulong pr_sighold; /* XXX */ target_pid_t pr_pid; @@ -1785,7 +1786,7 @@ struct target_elf_prstatus { struct target_timeval pr_cutime; /* XXX Cumulative user time */ struct target_timeval pr_cstime; /* XXX Cumulative system time */ target_elf_gregset_t pr_reg; /* GP registers */ - int pr_fpvalid; /* XXX */ + target_int pr_fpvalid; /* XXX */ }; #define ELF_PRARGSZ (80) /* Number of chars for args */ @@ -2036,7 +2037,9 @@ static void fill_note(struct memelfnote *note, const char *name, int type, note->namesz = namesz; note->namesz_rounded = roundup(namesz, sizeof (int32_t)); note->type = type; - note->datasz = roundup(sz, sizeof (int32_t));; + note->datasz = sz; + note->datasz_rounded = roundup(sz, sizeof (int32_t)); + note->data = data; /* @@ -2044,7 +2047,7 @@ static void fill_note(struct memelfnote *note, const char *name, int type, * ELF document. */ note->notesz = sizeof (struct elf_note) + - note->namesz_rounded + note->datasz; + note->namesz_rounded + note->datasz_rounded; } static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, @@ -2264,7 +2267,7 @@ static int write_note(struct memelfnote *men, int fd) return (-1); if (dump_write(fd, men->name, men->namesz_rounded) != 0) return (-1); - if (dump_write(fd, men->data, men->datasz) != 0) + if (dump_write(fd, men->data, men->datasz_rounded) != 0) return (-1); return (0); @@ -2480,7 +2483,7 @@ static int elf_core_dump(int signr, const CPUState *env) * ELF specification wants data to start at page boundary so * we align it here. */ - offset = roundup(offset, ELF_EXEC_PAGESIZE); + data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE); /* * Write program headers for memory regions mapped in @@ -2503,6 +2506,7 @@ static int elf_core_dump(int signr, const CPUState *env) phdr.p_flags |= PF_X; phdr.p_align = ELF_EXEC_PAGESIZE; + bswap_phdr(&phdr, 1); dump_write(fd, &phdr, sizeof (phdr)); } @@ -2514,8 +2518,6 @@ static int elf_core_dump(int signr, const CPUState *env) goto out; /* align data to page boundary */ - data_offset = lseek(fd, 0, SEEK_CUR); - data_offset = TARGET_PAGE_ALIGN(data_offset); if (lseek(fd, data_offset, SEEK_SET) != data_offset) goto out;