diff --git a/linux-user/aarch64/syscall_nr.h b/linux-user/aarch64/syscall_nr.h index f00ffd7fb8..c0392f68ac 100644 --- a/linux-user/aarch64/syscall_nr.h +++ b/linux-user/aarch64/syscall_nr.h @@ -277,4 +277,6 @@ #define TARGET_NR_mlock2 284 #define TARGET_NR_copy_file_range 285 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h index 2e5541bbf9..c9c2f4f8e1 100644 --- a/linux-user/alpha/syscall_nr.h +++ b/linux-user/alpha/syscall_nr.h @@ -454,4 +454,6 @@ #define TARGET_NR_memfd_create 512 #define TARGET_NR_execveat 513 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 7be4071751..6cef76c72a 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -333,7 +333,7 @@ void cpu_loop(CPUARMState *env) n -= ARM_SYSCALL_BASE; env->eabi = 0; } - if ( n > ARM_NR_BASE) { + if (n > ARM_NR_BASE && n != TARGET_NR_getdents64_x32) { switch (n) { case ARM_NR_cacheflush: /* nop */ diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h index e7eda0d766..add8414441 100644 --- a/linux-user/arm/syscall_nr.h +++ b/linux-user/arm/syscall_nr.h @@ -400,4 +400,6 @@ #define TARGET_NR_membarrier (389) #define TARGET_NR_mlock2 (390) +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/cris/syscall_nr.h b/linux-user/cris/syscall_nr.h index 4b6cf65c42..162a2d9911 100644 --- a/linux-user/cris/syscall_nr.h +++ b/linux-user/cris/syscall_nr.h @@ -364,4 +364,6 @@ #define TARGET_NR_bpf 358 #define TARGET_NR_execveat 359 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/hppa/syscall_nr.h b/linux-user/hppa/syscall_nr.h index ae41e94321..80fdcdee17 100644 --- a/linux-user/hppa/syscall_nr.h +++ b/linux-user/hppa/syscall_nr.h @@ -355,4 +355,6 @@ #define TARGET_NR_preadv2 347 #define TARGET_NR_pwritev2 348 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h index 3234ec21c6..3f5765e1c5 100644 --- a/linux-user/i386/syscall_nr.h +++ b/linux-user/i386/syscall_nr.h @@ -384,4 +384,6 @@ #define TARGET_NR_mlock2 376 #define TARGET_NR_copy_file_range 377 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/m68k/syscall_nr.h b/linux-user/m68k/syscall_nr.h index d33d8e98a7..38b41ff27a 100644 --- a/linux-user/m68k/syscall_nr.h +++ b/linux-user/m68k/syscall_nr.h @@ -383,4 +383,6 @@ #define TARGET_NR_preadv2 377 #define TARGET_NR_pwritev2 378 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/microblaze/syscall_nr.h b/linux-user/microblaze/syscall_nr.h index aa2eb93881..2dabe4c7c8 100644 --- a/linux-user/microblaze/syscall_nr.h +++ b/linux-user/microblaze/syscall_nr.h @@ -394,4 +394,6 @@ #define TARGET_NR_bpf 387 #define TARGET_NR_execveat 388 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 39915b3fde..e317410141 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -446,14 +446,19 @@ void cpu_loop(CPUMIPSState *env) env->active_tc.PC += 4; # ifdef TARGET_ABI_MIPSO32 syscall_num = env->active_tc.gpr[2] - 4000; - if (syscall_num >= sizeof(mips_syscall_args)) { + if (syscall_num >= sizeof(mips_syscall_args) && env->active_tc.gpr[2] != TARGET_NR_getdents64_x32) { ret = -TARGET_ENOSYS; } else { int nb_args; abi_ulong sp_reg; abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; - nb_args = mips_syscall_args[syscall_num]; + if (env->active_tc.gpr[2] == TARGET_NR_getdents64_x32) { + nb_args = 3; + } else { + nb_args = mips_syscall_args[syscall_num]; + } + sp_reg = env->active_tc.gpr[29]; switch (nb_args) { /* these arguments are taken from the stack */ diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h index 7fa7fa5a86..c0de530f6f 100644 --- a/linux-user/mips/syscall_nr.h +++ b/linux-user/mips/syscall_nr.h @@ -377,4 +377,6 @@ #define TARGET_NR_rseq (TARGET_NR_Linux + 367) #define TARGET_NR_io_pgetevents (TARGET_NR_Linux + 368) +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/mips64/syscall_nr.h b/linux-user/mips64/syscall_nr.h index db40f69ca2..ecaccc81cf 100644 --- a/linux-user/mips64/syscall_nr.h +++ b/linux-user/mips64/syscall_nr.h @@ -676,4 +676,6 @@ #define TARGET_NR_io_pgetevents (TARGET_NR_Linux + 328) #endif +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/nios2/syscall_nr.h b/linux-user/nios2/syscall_nr.h index 8fb87864ca..47b582211f 100644 --- a/linux-user/nios2/syscall_nr.h +++ b/linux-user/nios2/syscall_nr.h @@ -331,4 +331,6 @@ #define TARGET_NR__sysctl 1078 #define TARGET_NR_fork 1079 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/openrisc/syscall_nr.h b/linux-user/openrisc/syscall_nr.h index 7763dbcfd8..0b22f19b1d 100644 --- a/linux-user/openrisc/syscall_nr.h +++ b/linux-user/openrisc/syscall_nr.h @@ -506,4 +506,6 @@ #define TARGET_NR_lstat64 TARGET_NR_3264_lstat #endif +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h index b57a07b931..797ab30b89 100644 --- a/linux-user/ppc/syscall_nr.h +++ b/linux-user/ppc/syscall_nr.h @@ -399,4 +399,6 @@ #define TARGET_NR_shmctl 377 #define TARGET_NR_mlock2 378 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/riscv/syscall_nr.h b/linux-user/riscv/syscall_nr.h index 5c87282209..b3d32dbed3 100644 --- a/linux-user/riscv/syscall_nr.h +++ b/linux-user/riscv/syscall_nr.h @@ -302,4 +302,6 @@ #define TARGET_NR_syscalls (TARGET_NR_kexec_file_load + 1) +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/s390x/syscall_nr.h b/linux-user/s390x/syscall_nr.h index b1553a0810..0475fbb96a 100644 --- a/linux-user/s390x/syscall_nr.h +++ b/linux-user/s390x/syscall_nr.h @@ -395,4 +395,6 @@ #endif +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/sh4/syscall_nr.h b/linux-user/sh4/syscall_nr.h index d53a2a07dd..f6c63baa14 100644 --- a/linux-user/sh4/syscall_nr.h +++ b/linux-user/sh4/syscall_nr.h @@ -390,4 +390,6 @@ #define TARGET_NR_preadv2 381 #define TARGET_NR_pwritev2 382 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h index 162099f9ce..8fc2bf676a 100644 --- a/linux-user/sparc/syscall_nr.h +++ b/linux-user/sparc/syscall_nr.h @@ -360,4 +360,6 @@ #define TARGET_NR_pwritev2 359 #define TARGET_NR_statx 360 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/sparc64/syscall_nr.h b/linux-user/sparc64/syscall_nr.h index 6b088c9862..f5830f9e54 100644 --- a/linux-user/sparc64/syscall_nr.h +++ b/linux-user/sparc64/syscall_nr.h @@ -363,4 +363,6 @@ #define TARGET_NR_pwritev2 359 #define TARGET_NR_statx 360 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/strace.list b/linux-user/strace.list index 1de4319dcf..65bb2e9b16 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1656,3 +1656,6 @@ #ifdef TARGET_NR_statx { TARGET_NR_statx, "statx", NULL, print_statx, NULL }, #endif +#ifdef TARGET_NR_getdents64_x32 +{ TARGET_NR_getdents64_x32, "getdents64_x32" , NULL, NULL, NULL }, +#endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 171c0caef3..957a0e65f6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -230,7 +230,6 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \ } - #define __NR_sys_uname __NR_uname #define __NR_sys_getcwd1 __NR_getcwd #define __NR_sys_getdents __NR_getdents @@ -245,6 +244,10 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch #define __NR_sys_statx __NR_statx +#define __X32_SYSCALL_BIT 0x40000000UL +#define __NR_getdents64_x32 (__X32_SYSCALL_BIT + 217) +#define __NR_sys_getdents64_x32 __NR_getdents64_x32 + #if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__) #define __NR__llseek __NR_lseek #endif @@ -275,6 +278,11 @@ _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count) (defined(TARGET_NR_getdents64) && defined(__NR_getdents64)) _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); #endif +#if (defined(TARGET_NR_getdents) && \ + !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \ + (defined(TARGET_NR_getdents64_x32) && defined(__NR_getdents64_x32)) +_syscall3(int, sys_getdents64_x32, uint, fd, struct linux_dirent64 *, dirp, uint, count); +#endif #if defined(TARGET_NR__llseek) && defined(__NR_llseek) _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); @@ -1062,7 +1070,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong target_rlim) { abi_ulong target_rlim_swap; rlim_t result; - + target_rlim_swap = tswapal(target_rlim); if (target_rlim_swap == TARGET_RLIM_INFINITY) return RLIM_INFINITY; @@ -1070,7 +1078,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong target_rlim) result = target_rlim_swap; if (target_rlim_swap != (rlim_t)result) return RLIM_INFINITY; - + return result; } @@ -1078,13 +1086,13 @@ static inline abi_ulong host_to_target_rlim(rlim_t rlim) { abi_ulong target_rlim_swap; abi_ulong result; - + if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim) target_rlim_swap = TARGET_RLIM_INFINITY; else target_rlim_swap = rlim; result = tswapal(target_rlim_swap); - + return result; } @@ -1526,9 +1534,9 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh, abi_ulong target_cmsg_addr; struct target_cmsghdr *target_cmsg, *target_cmsg_start; socklen_t space = 0; - + msg_controllen = tswapal(target_msgh->msg_controllen); - if (msg_controllen < sizeof (struct target_cmsghdr)) + if (msg_controllen < sizeof (struct target_cmsghdr)) goto the_end; target_cmsg_addr = tswapal(target_msgh->msg_control); target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); @@ -1610,7 +1618,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, socklen_t space = 0; msg_controllen = tswapal(target_msgh->msg_controllen); - if (msg_controllen < sizeof (struct target_cmsghdr)) + if (msg_controllen < sizeof (struct target_cmsghdr)) goto the_end; target_cmsg_addr = tswapal(target_msgh->msg_control); target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0); @@ -5592,7 +5600,7 @@ abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) } unlock_user_struct(target_ldt_info, ptr, 1); - if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN || + if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN || ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX) return -TARGET_EINVAL; seg_32bit = ldt_info.flags & 1; @@ -5670,7 +5678,7 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) lp = (uint32_t *)(gdt_table + idx); entry_1 = tswap32(lp[0]); entry_2 = tswap32(lp[1]); - + read_exec_only = ((entry_2 >> 9) & 1) ^ 1; contents = (entry_2 >> 10) & 3; seg_not_present = ((entry_2 >> 15) & 1) ^ 1; @@ -5686,8 +5694,8 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) (read_exec_only << 3) | (limit_in_pages << 4) | (seg_not_present << 5) | (useable << 6) | (lm << 7); limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000); - base_addr = (entry_1 >> 16) | - (entry_2 & 0xff000000) | + base_addr = (entry_1 >> 16) | + (entry_2 & 0xff000000) | ((entry_2 & 0xff) << 16); target_ldt_info->base_addr = tswapal(base_addr); target_ldt_info->limit = tswap32(limit); @@ -9535,7 +9543,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } #endif #else - /* Implement getdents in terms of getdents64 */ + /* Implement getdents in terms of getdents64_x32 */ { struct linux_dirent64 *dirp; abi_long count = arg3; @@ -9544,7 +9552,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, if (!dirp) { return -TARGET_EFAULT; } - ret = get_errno(sys_getdents64(arg1, dirp, count)); + ret = get_errno(sys_getdents64_x32(arg1, dirp, count)); if (!is_error(ret)) { /* Convert the dirent64 structs to target dirent. We do this * in-place, since we can guarantee that a target_dirent is no @@ -9619,6 +9627,34 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } return ret; #endif /* TARGET_NR_getdents64 */ +#if defined(TARGET_NR_getdents64_x32) && defined(__NR_getdents64_x32) + case TARGET_NR_getdents64_x32: + { + struct linux_dirent64 *dirp; + abi_long count = arg3; + if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) + return -TARGET_EFAULT; + ret = get_errno(sys_getdents64_x32(arg1, dirp, count)); + if (!is_error(ret)) { + struct linux_dirent64 *de; + int len = ret; + int reclen; + de = dirp; + while (len > 0) { + reclen = de->d_reclen; + if (reclen > len) + break; + de->d_reclen = tswap16(reclen); + tswap64s((uint64_t *)&de->d_ino); + tswap64s((uint64_t *)&de->d_off); + de = (struct linux_dirent64 *)((char *)de + reclen); + len -= reclen; + } + } + unlock_user(dirp, arg2, ret); + } + return ret; +#endif /* TARGET_NR_getdents64_x32 */ #if defined(TARGET_NR__newselect) case TARGET_NR__newselect: return do_select(arg1, arg2, arg3, arg4, arg5); @@ -10554,7 +10590,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3))); #if defined(TARGET_NR_fchownat) case TARGET_NR_fchownat: - if (!(p = lock_user_string(arg2))) + if (!(p = lock_user_string(arg2))) return -TARGET_EFAULT; ret = get_errno(fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5)); diff --git a/linux-user/tilegx/syscall_nr.h b/linux-user/tilegx/syscall_nr.h index c104b94230..e8c9ff1f14 100644 --- a/linux-user/tilegx/syscall_nr.h +++ b/linux-user/tilegx/syscall_nr.h @@ -324,4 +324,6 @@ #define TARGET_NR__sysctl 1078 #define TARGET_NR_fork 1079 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/x86_64/syscall_nr.h b/linux-user/x86_64/syscall_nr.h index 9b6981e74c..3e0def88d0 100644 --- a/linux-user/x86_64/syscall_nr.h +++ b/linux-user/x86_64/syscall_nr.h @@ -329,4 +329,6 @@ #define TARGET_NR_mlock2 325 #define TARGET_NR_copy_file_range 326 +#define TARGET_NR_getdents64_x32 0xffff + #endif diff --git a/linux-user/xtensa/syscall_nr.h b/linux-user/xtensa/syscall_nr.h index 27645bea47..ba32d29ebf 100644 --- a/linux-user/xtensa/syscall_nr.h +++ b/linux-user/xtensa/syscall_nr.h @@ -434,4 +434,6 @@ #define TARGET_NR_syscall_count 352 +#define TARGET_NR_getdents64_x32 0xffff + #endif /* XTENSA_SYSCALL_NR_H */