Commit 53a5960aadd542dd27b8705ac30df154557d5ffc
1 parent
26f69dc0
Avoid accessing guest memory directly in usermode emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1790 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
15 changed files
with
1194 additions
and
772 deletions
cpu-all.h
@@ -584,22 +584,41 @@ static inline void stfq_be_p(void *ptr, float64 v) | @@ -584,22 +584,41 @@ static inline void stfq_be_p(void *ptr, float64 v) | ||
584 | 584 | ||
585 | /* MMU memory access macros */ | 585 | /* MMU memory access macros */ |
586 | 586 | ||
587 | +#if defined(CONFIG_USER_ONLY) | ||
588 | +/* On some host systems the guest address space is reserved on the host. | ||
589 | + * This allows the guest address space to be offset to a convenient location. | ||
590 | + */ | ||
591 | +//#define GUEST_BASE 0x20000000 | ||
592 | +#define GUEST_BASE 0 | ||
593 | + | ||
594 | +/* All direct uses of g2h and h2g need to go away for usermode softmmu. */ | ||
595 | +#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) | ||
596 | +#define h2g(x) ((target_ulong)(x - GUEST_BASE)) | ||
597 | + | ||
598 | +#define saddr(x) g2h(x) | ||
599 | +#define laddr(x) g2h(x) | ||
600 | + | ||
601 | +#else /* !CONFIG_USER_ONLY */ | ||
587 | /* NOTE: we use double casts if pointers and target_ulong have | 602 | /* NOTE: we use double casts if pointers and target_ulong have |
588 | different sizes */ | 603 | different sizes */ |
589 | -#define ldub_raw(p) ldub_p((uint8_t *)(long)(p)) | ||
590 | -#define ldsb_raw(p) ldsb_p((uint8_t *)(long)(p)) | ||
591 | -#define lduw_raw(p) lduw_p((uint8_t *)(long)(p)) | ||
592 | -#define ldsw_raw(p) ldsw_p((uint8_t *)(long)(p)) | ||
593 | -#define ldl_raw(p) ldl_p((uint8_t *)(long)(p)) | ||
594 | -#define ldq_raw(p) ldq_p((uint8_t *)(long)(p)) | ||
595 | -#define ldfl_raw(p) ldfl_p((uint8_t *)(long)(p)) | ||
596 | -#define ldfq_raw(p) ldfq_p((uint8_t *)(long)(p)) | ||
597 | -#define stb_raw(p, v) stb_p((uint8_t *)(long)(p), v) | ||
598 | -#define stw_raw(p, v) stw_p((uint8_t *)(long)(p), v) | ||
599 | -#define stl_raw(p, v) stl_p((uint8_t *)(long)(p), v) | ||
600 | -#define stq_raw(p, v) stq_p((uint8_t *)(long)(p), v) | ||
601 | -#define stfl_raw(p, v) stfl_p((uint8_t *)(long)(p), v) | ||
602 | -#define stfq_raw(p, v) stfq_p((uint8_t *)(long)(p), v) | 604 | +#define saddr(x) (uint8_t *)(long)(x) |
605 | +#define laddr(x) (uint8_t *)(long)(x) | ||
606 | +#endif | ||
607 | + | ||
608 | +#define ldub_raw(p) ldub_p(laddr((p))) | ||
609 | +#define ldsb_raw(p) ldsb_p(laddr((p))) | ||
610 | +#define lduw_raw(p) lduw_p(laddr((p))) | ||
611 | +#define ldsw_raw(p) ldsw_p(laddr((p))) | ||
612 | +#define ldl_raw(p) ldl_p(laddr((p))) | ||
613 | +#define ldq_raw(p) ldq_p(laddr((p))) | ||
614 | +#define ldfl_raw(p) ldfl_p(laddr((p))) | ||
615 | +#define ldfq_raw(p) ldfq_p(laddr((p))) | ||
616 | +#define stb_raw(p, v) stb_p(saddr((p)), v) | ||
617 | +#define stw_raw(p, v) stw_p(saddr((p)), v) | ||
618 | +#define stl_raw(p, v) stl_p(saddr((p)), v) | ||
619 | +#define stq_raw(p, v) stq_p(saddr((p)), v) | ||
620 | +#define stfl_raw(p, v) stfl_p(saddr((p)), v) | ||
621 | +#define stfq_raw(p, v) stfq_p(saddr((p)), v) | ||
603 | 622 | ||
604 | 623 | ||
605 | #if defined(CONFIG_USER_ONLY) | 624 | #if defined(CONFIG_USER_ONLY) |
@@ -648,6 +667,7 @@ static inline void stfq_be_p(void *ptr, float64 v) | @@ -648,6 +667,7 @@ static inline void stfq_be_p(void *ptr, float64 v) | ||
648 | #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) | 667 | #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) |
649 | #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) | 668 | #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) |
650 | 669 | ||
670 | +/* ??? These should be the larger of unsigned long and target_ulong. */ | ||
651 | extern unsigned long qemu_real_host_page_size; | 671 | extern unsigned long qemu_real_host_page_size; |
652 | extern unsigned long qemu_host_page_bits; | 672 | extern unsigned long qemu_host_page_bits; |
653 | extern unsigned long qemu_host_page_size; | 673 | extern unsigned long qemu_host_page_size; |
@@ -666,9 +686,9 @@ extern unsigned long qemu_host_page_mask; | @@ -666,9 +686,9 @@ extern unsigned long qemu_host_page_mask; | ||
666 | #define PAGE_WRITE_ORG 0x0010 | 686 | #define PAGE_WRITE_ORG 0x0010 |
667 | 687 | ||
668 | void page_dump(FILE *f); | 688 | void page_dump(FILE *f); |
669 | -int page_get_flags(unsigned long address); | ||
670 | -void page_set_flags(unsigned long start, unsigned long end, int flags); | ||
671 | -void page_unprotect_range(uint8_t *data, unsigned long data_size); | 689 | +int page_get_flags(target_ulong address); |
690 | +void page_set_flags(target_ulong start, target_ulong end, int flags); | ||
691 | +void page_unprotect_range(target_ulong data, target_ulong data_size); | ||
672 | 692 | ||
673 | #define SINGLE_CPU_DEFINES | 693 | #define SINGLE_CPU_DEFINES |
674 | #ifdef SINGLE_CPU_DEFINES | 694 | #ifdef SINGLE_CPU_DEFINES |
cpu-exec.c
@@ -913,7 +913,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -913,7 +913,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
913 | pc, address, is_write, *(unsigned long *)old_set); | 913 | pc, address, is_write, *(unsigned long *)old_set); |
914 | #endif | 914 | #endif |
915 | /* XXX: locking issue */ | 915 | /* XXX: locking issue */ |
916 | - if (is_write && page_unprotect(address, pc, puc)) { | 916 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { |
917 | return 1; | 917 | return 1; |
918 | } | 918 | } |
919 | 919 | ||
@@ -964,7 +964,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -964,7 +964,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
964 | pc, address, is_write, *(unsigned long *)old_set); | 964 | pc, address, is_write, *(unsigned long *)old_set); |
965 | #endif | 965 | #endif |
966 | /* XXX: locking issue */ | 966 | /* XXX: locking issue */ |
967 | - if (is_write && page_unprotect(address, pc, puc)) { | 967 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { |
968 | return 1; | 968 | return 1; |
969 | } | 969 | } |
970 | /* see if it is an MMU fault */ | 970 | /* see if it is an MMU fault */ |
@@ -1000,7 +1000,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -1000,7 +1000,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
1000 | pc, address, is_write, *(unsigned long *)old_set); | 1000 | pc, address, is_write, *(unsigned long *)old_set); |
1001 | #endif | 1001 | #endif |
1002 | /* XXX: locking issue */ | 1002 | /* XXX: locking issue */ |
1003 | - if (is_write && page_unprotect(address, pc, puc)) { | 1003 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { |
1004 | return 1; | 1004 | return 1; |
1005 | } | 1005 | } |
1006 | /* see if it is an MMU fault */ | 1006 | /* see if it is an MMU fault */ |
@@ -1036,7 +1036,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -1036,7 +1036,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
1036 | pc, address, is_write, *(unsigned long *)old_set); | 1036 | pc, address, is_write, *(unsigned long *)old_set); |
1037 | #endif | 1037 | #endif |
1038 | /* XXX: locking issue */ | 1038 | /* XXX: locking issue */ |
1039 | - if (is_write && page_unprotect(address, pc, puc)) { | 1039 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { |
1040 | return 1; | 1040 | return 1; |
1041 | } | 1041 | } |
1042 | 1042 | ||
@@ -1086,7 +1086,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -1086,7 +1086,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
1086 | pc, address, is_write, *(unsigned long *)old_set); | 1086 | pc, address, is_write, *(unsigned long *)old_set); |
1087 | #endif | 1087 | #endif |
1088 | /* XXX: locking issue */ | 1088 | /* XXX: locking issue */ |
1089 | - if (is_write && page_unprotect(address, pc, puc)) { | 1089 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { |
1090 | return 1; | 1090 | return 1; |
1091 | } | 1091 | } |
1092 | 1092 |
exec-all.h
@@ -93,7 +93,7 @@ int cpu_restore_state_copy(struct TranslationBlock *tb, | @@ -93,7 +93,7 @@ int cpu_restore_state_copy(struct TranslationBlock *tb, | ||
93 | void *puc); | 93 | void *puc); |
94 | void cpu_resume_from_signal(CPUState *env1, void *puc); | 94 | void cpu_resume_from_signal(CPUState *env1, void *puc); |
95 | void cpu_exec_init(CPUState *env); | 95 | void cpu_exec_init(CPUState *env); |
96 | -int page_unprotect(unsigned long address, unsigned long pc, void *puc); | 96 | +int page_unprotect(target_ulong address, unsigned long pc, void *puc); |
97 | void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, | 97 | void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, |
98 | int is_cpu_write_access); | 98 | int is_cpu_write_access); |
99 | void tb_invalidate_page_range(target_ulong start, target_ulong end); | 99 | void tb_invalidate_page_range(target_ulong start, target_ulong end); |
exec.c
@@ -34,6 +34,9 @@ | @@ -34,6 +34,9 @@ | ||
34 | 34 | ||
35 | #include "cpu.h" | 35 | #include "cpu.h" |
36 | #include "exec-all.h" | 36 | #include "exec-all.h" |
37 | +#if defined(CONFIG_USER_ONLY) | ||
38 | +#include <qemu.h> | ||
39 | +#endif | ||
37 | 40 | ||
38 | //#define DEBUG_TB_INVALIDATE | 41 | //#define DEBUG_TB_INVALIDATE |
39 | //#define DEBUG_FLUSH | 42 | //#define DEBUG_FLUSH |
@@ -810,7 +813,7 @@ static void tb_invalidate_phys_page(target_ulong addr, | @@ -810,7 +813,7 @@ static void tb_invalidate_phys_page(target_ulong addr, | ||
810 | 813 | ||
811 | /* add the tb in the target page and protect it if necessary */ | 814 | /* add the tb in the target page and protect it if necessary */ |
812 | static inline void tb_alloc_page(TranslationBlock *tb, | 815 | static inline void tb_alloc_page(TranslationBlock *tb, |
813 | - unsigned int n, unsigned int page_addr) | 816 | + unsigned int n, target_ulong page_addr) |
814 | { | 817 | { |
815 | PageDesc *p; | 818 | PageDesc *p; |
816 | TranslationBlock *last_first_tb; | 819 | TranslationBlock *last_first_tb; |
@@ -826,23 +829,30 @@ static inline void tb_alloc_page(TranslationBlock *tb, | @@ -826,23 +829,30 @@ static inline void tb_alloc_page(TranslationBlock *tb, | ||
826 | 829 | ||
827 | #if defined(CONFIG_USER_ONLY) | 830 | #if defined(CONFIG_USER_ONLY) |
828 | if (p->flags & PAGE_WRITE) { | 831 | if (p->flags & PAGE_WRITE) { |
829 | - unsigned long host_start, host_end, addr; | 832 | + target_ulong addr; |
833 | + PageDesc *p2; | ||
830 | int prot; | 834 | int prot; |
831 | 835 | ||
832 | /* force the host page as non writable (writes will have a | 836 | /* force the host page as non writable (writes will have a |
833 | page fault + mprotect overhead) */ | 837 | page fault + mprotect overhead) */ |
834 | - host_start = page_addr & qemu_host_page_mask; | ||
835 | - host_end = host_start + qemu_host_page_size; | 838 | + page_addr &= qemu_host_page_mask; |
836 | prot = 0; | 839 | prot = 0; |
837 | - for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE) | ||
838 | - prot |= page_get_flags(addr); | ||
839 | - mprotect((void *)host_start, qemu_host_page_size, | 840 | + for(addr = page_addr; addr < page_addr + qemu_host_page_size; |
841 | + addr += TARGET_PAGE_SIZE) { | ||
842 | + | ||
843 | + p2 = page_find (addr >> TARGET_PAGE_BITS); | ||
844 | + if (!p2) | ||
845 | + continue; | ||
846 | + prot |= p2->flags; | ||
847 | + p2->flags &= ~PAGE_WRITE; | ||
848 | + page_get_flags(addr); | ||
849 | + } | ||
850 | + mprotect(g2h(page_addr), qemu_host_page_size, | ||
840 | (prot & PAGE_BITS) & ~PAGE_WRITE); | 851 | (prot & PAGE_BITS) & ~PAGE_WRITE); |
841 | #ifdef DEBUG_TB_INVALIDATE | 852 | #ifdef DEBUG_TB_INVALIDATE |
842 | printf("protecting code page: 0x%08lx\n", | 853 | printf("protecting code page: 0x%08lx\n", |
843 | - host_start); | 854 | + page_addr); |
844 | #endif | 855 | #endif |
845 | - p->flags &= ~PAGE_WRITE; | ||
846 | } | 856 | } |
847 | #else | 857 | #else |
848 | /* if some code is already present, then the pages are already | 858 | /* if some code is already present, then the pages are already |
@@ -1546,7 +1556,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, | @@ -1546,7 +1556,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, | ||
1546 | 1556 | ||
1547 | /* called from signal handler: invalidate the code and unprotect the | 1557 | /* called from signal handler: invalidate the code and unprotect the |
1548 | page. Return TRUE if the fault was succesfully handled. */ | 1558 | page. Return TRUE if the fault was succesfully handled. */ |
1549 | -int page_unprotect(unsigned long addr, unsigned long pc, void *puc) | 1559 | +int page_unprotect(target_ulong addr, unsigned long pc, void *puc) |
1550 | { | 1560 | { |
1551 | #if !defined(CONFIG_SOFTMMU) | 1561 | #if !defined(CONFIG_SOFTMMU) |
1552 | VirtPageDesc *vp; | 1562 | VirtPageDesc *vp; |
@@ -1645,7 +1655,7 @@ void page_dump(FILE *f) | @@ -1645,7 +1655,7 @@ void page_dump(FILE *f) | ||
1645 | } | 1655 | } |
1646 | } | 1656 | } |
1647 | 1657 | ||
1648 | -int page_get_flags(unsigned long address) | 1658 | +int page_get_flags(target_ulong address) |
1649 | { | 1659 | { |
1650 | PageDesc *p; | 1660 | PageDesc *p; |
1651 | 1661 | ||
@@ -1658,10 +1668,10 @@ int page_get_flags(unsigned long address) | @@ -1658,10 +1668,10 @@ int page_get_flags(unsigned long address) | ||
1658 | /* modify the flags of a page and invalidate the code if | 1668 | /* modify the flags of a page and invalidate the code if |
1659 | necessary. The flag PAGE_WRITE_ORG is positionned automatically | 1669 | necessary. The flag PAGE_WRITE_ORG is positionned automatically |
1660 | depending on PAGE_WRITE */ | 1670 | depending on PAGE_WRITE */ |
1661 | -void page_set_flags(unsigned long start, unsigned long end, int flags) | 1671 | +void page_set_flags(target_ulong start, target_ulong end, int flags) |
1662 | { | 1672 | { |
1663 | PageDesc *p; | 1673 | PageDesc *p; |
1664 | - unsigned long addr; | 1674 | + target_ulong addr; |
1665 | 1675 | ||
1666 | start = start & TARGET_PAGE_MASK; | 1676 | start = start & TARGET_PAGE_MASK; |
1667 | end = TARGET_PAGE_ALIGN(end); | 1677 | end = TARGET_PAGE_ALIGN(end); |
@@ -1684,11 +1694,11 @@ void page_set_flags(unsigned long start, unsigned long end, int flags) | @@ -1684,11 +1694,11 @@ void page_set_flags(unsigned long start, unsigned long end, int flags) | ||
1684 | 1694 | ||
1685 | /* called from signal handler: invalidate the code and unprotect the | 1695 | /* called from signal handler: invalidate the code and unprotect the |
1686 | page. Return TRUE if the fault was succesfully handled. */ | 1696 | page. Return TRUE if the fault was succesfully handled. */ |
1687 | -int page_unprotect(unsigned long address, unsigned long pc, void *puc) | 1697 | +int page_unprotect(target_ulong address, unsigned long pc, void *puc) |
1688 | { | 1698 | { |
1689 | unsigned int page_index, prot, pindex; | 1699 | unsigned int page_index, prot, pindex; |
1690 | PageDesc *p, *p1; | 1700 | PageDesc *p, *p1; |
1691 | - unsigned long host_start, host_end, addr; | 1701 | + target_ulong host_start, host_end, addr; |
1692 | 1702 | ||
1693 | host_start = address & qemu_host_page_mask; | 1703 | host_start = address & qemu_host_page_mask; |
1694 | page_index = host_start >> TARGET_PAGE_BITS; | 1704 | page_index = host_start >> TARGET_PAGE_BITS; |
@@ -1707,7 +1717,7 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc) | @@ -1707,7 +1717,7 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc) | ||
1707 | if (prot & PAGE_WRITE_ORG) { | 1717 | if (prot & PAGE_WRITE_ORG) { |
1708 | pindex = (address - host_start) >> TARGET_PAGE_BITS; | 1718 | pindex = (address - host_start) >> TARGET_PAGE_BITS; |
1709 | if (!(p1[pindex].flags & PAGE_WRITE)) { | 1719 | if (!(p1[pindex].flags & PAGE_WRITE)) { |
1710 | - mprotect((void *)host_start, qemu_host_page_size, | 1720 | + mprotect((void *)g2h(host_start), qemu_host_page_size, |
1711 | (prot & PAGE_BITS) | PAGE_WRITE); | 1721 | (prot & PAGE_BITS) | PAGE_WRITE); |
1712 | p1[pindex].flags |= PAGE_WRITE; | 1722 | p1[pindex].flags |= PAGE_WRITE; |
1713 | /* and since the content will be modified, we must invalidate | 1723 | /* and since the content will be modified, we must invalidate |
@@ -1723,11 +1733,12 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc) | @@ -1723,11 +1733,12 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc) | ||
1723 | } | 1733 | } |
1724 | 1734 | ||
1725 | /* call this function when system calls directly modify a memory area */ | 1735 | /* call this function when system calls directly modify a memory area */ |
1726 | -void page_unprotect_range(uint8_t *data, unsigned long data_size) | 1736 | +/* ??? This should be redundant now we have lock_user. */ |
1737 | +void page_unprotect_range(target_ulong data, target_ulong data_size) | ||
1727 | { | 1738 | { |
1728 | - unsigned long start, end, addr; | 1739 | + target_ulong start, end, addr; |
1729 | 1740 | ||
1730 | - start = (unsigned long)data; | 1741 | + start = data; |
1731 | end = start + data_size; | 1742 | end = start + data_size; |
1732 | start &= TARGET_PAGE_MASK; | 1743 | start &= TARGET_PAGE_MASK; |
1733 | end = TARGET_PAGE_ALIGN(end); | 1744 | end = TARGET_PAGE_ALIGN(end); |
@@ -1932,6 +1943,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | @@ -1932,6 +1943,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | ||
1932 | { | 1943 | { |
1933 | int l, flags; | 1944 | int l, flags; |
1934 | target_ulong page; | 1945 | target_ulong page; |
1946 | + void * p; | ||
1935 | 1947 | ||
1936 | while (len > 0) { | 1948 | while (len > 0) { |
1937 | page = addr & TARGET_PAGE_MASK; | 1949 | page = addr & TARGET_PAGE_MASK; |
@@ -1944,11 +1956,15 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | @@ -1944,11 +1956,15 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, | ||
1944 | if (is_write) { | 1956 | if (is_write) { |
1945 | if (!(flags & PAGE_WRITE)) | 1957 | if (!(flags & PAGE_WRITE)) |
1946 | return; | 1958 | return; |
1947 | - memcpy((uint8_t *)addr, buf, len); | 1959 | + p = lock_user(addr, len, 0); |
1960 | + memcpy(p, buf, len); | ||
1961 | + unlock_user(p, addr, len); | ||
1948 | } else { | 1962 | } else { |
1949 | if (!(flags & PAGE_READ)) | 1963 | if (!(flags & PAGE_READ)) |
1950 | return; | 1964 | return; |
1951 | - memcpy(buf, (uint8_t *)addr, len); | 1965 | + p = lock_user(addr, len, 1); |
1966 | + memcpy(buf, p, len); | ||
1967 | + unlock_user(p, addr, 0); | ||
1952 | } | 1968 | } |
1953 | len -= l; | 1969 | len -= l; |
1954 | buf += l; | 1970 | buf += l; |
linux-user/arm-semi.c
@@ -77,20 +77,20 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) | @@ -77,20 +77,20 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) | ||
77 | return code; | 77 | return code; |
78 | } | 78 | } |
79 | 79 | ||
80 | -#define ARG(x) tswap32(args[x]) | 80 | +#define ARG(n) tget32(args + n * 4) |
81 | uint32_t do_arm_semihosting(CPUState *env) | 81 | uint32_t do_arm_semihosting(CPUState *env) |
82 | { | 82 | { |
83 | - uint32_t *args; | 83 | + target_ulong args; |
84 | char * s; | 84 | char * s; |
85 | int nr; | 85 | int nr; |
86 | uint32_t ret; | 86 | uint32_t ret; |
87 | TaskState *ts = env->opaque; | 87 | TaskState *ts = env->opaque; |
88 | 88 | ||
89 | nr = env->regs[0]; | 89 | nr = env->regs[0]; |
90 | - args = (uint32_t *)env->regs[1]; | 90 | + args = env->regs[1]; |
91 | switch (nr) { | 91 | switch (nr) { |
92 | case SYS_OPEN: | 92 | case SYS_OPEN: |
93 | - s = (char *)ARG(0); | 93 | + s = (char *)g2h(ARG(0)); |
94 | if (ARG(1) >= 12) | 94 | if (ARG(1) >= 12) |
95 | return (uint32_t)-1; | 95 | return (uint32_t)-1; |
96 | if (strcmp(s, ":tt") == 0) { | 96 | if (strcmp(s, ":tt") == 0) { |
@@ -103,18 +103,23 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -103,18 +103,23 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
103 | case SYS_CLOSE: | 103 | case SYS_CLOSE: |
104 | return set_swi_errno(ts, close(ARG(0))); | 104 | return set_swi_errno(ts, close(ARG(0))); |
105 | case SYS_WRITEC: | 105 | case SYS_WRITEC: |
106 | - /* Write to debug console. stderr is near enough. */ | ||
107 | - return write(STDERR_FILENO, args, 1); | 106 | + { |
107 | + char c = tget8(args); | ||
108 | + /* Write to debug console. stderr is near enough. */ | ||
109 | + return write(STDERR_FILENO, &c, 1); | ||
110 | + } | ||
108 | case SYS_WRITE0: | 111 | case SYS_WRITE0: |
109 | - s = (char *)args; | ||
110 | - return write(STDERR_FILENO, s, strlen(s)); | 112 | + s = lock_user_string(args); |
113 | + ret = write(STDERR_FILENO, s, strlen(s)); | ||
114 | + unlock_user(s, args, 0); | ||
115 | + return ret; | ||
111 | case SYS_WRITE: | 116 | case SYS_WRITE: |
112 | - ret = set_swi_errno(ts, write(ARG(0), (void *)ARG(1), ARG(2))); | 117 | + ret = set_swi_errno(ts, write(ARG(0), g2h(ARG(1)), ARG(2))); |
113 | if (ret == (uint32_t)-1) | 118 | if (ret == (uint32_t)-1) |
114 | return -1; | 119 | return -1; |
115 | return ARG(2) - ret; | 120 | return ARG(2) - ret; |
116 | case SYS_READ: | 121 | case SYS_READ: |
117 | - ret = set_swi_errno(ts, read(ARG(0), (void *)ARG(1), ARG(2))); | 122 | + ret = set_swi_errno(ts, read(ARG(0), g2h(ARG(1)), ARG(2))); |
118 | if (ret == (uint32_t)-1) | 123 | if (ret == (uint32_t)-1) |
119 | return -1; | 124 | return -1; |
120 | return ARG(2) - ret; | 125 | return ARG(2) - ret; |
@@ -140,20 +145,21 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -140,20 +145,21 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
140 | /* XXX: Not implemented. */ | 145 | /* XXX: Not implemented. */ |
141 | return -1; | 146 | return -1; |
142 | case SYS_REMOVE: | 147 | case SYS_REMOVE: |
143 | - return set_swi_errno(ts, remove((char *)ARG(0))); | 148 | + return set_swi_errno(ts, remove((char *)g2h(ARG(0)))); |
144 | case SYS_RENAME: | 149 | case SYS_RENAME: |
145 | - return set_swi_errno(ts, rename((char *)ARG(0), (char *)ARG(2))); | 150 | + return set_swi_errno(ts, rename((char *)g2h(ARG(0)), |
151 | + (char *)g2h(ARG(2)))); | ||
146 | case SYS_CLOCK: | 152 | case SYS_CLOCK: |
147 | return clock() / (CLOCKS_PER_SEC / 100); | 153 | return clock() / (CLOCKS_PER_SEC / 100); |
148 | case SYS_TIME: | 154 | case SYS_TIME: |
149 | return set_swi_errno(ts, time(NULL)); | 155 | return set_swi_errno(ts, time(NULL)); |
150 | case SYS_SYSTEM: | 156 | case SYS_SYSTEM: |
151 | - return set_swi_errno(ts, system((char *)ARG(0))); | 157 | + return set_swi_errno(ts, system((char *)g2h(ARG(0)))); |
152 | case SYS_ERRNO: | 158 | case SYS_ERRNO: |
153 | return ts->swi_errno; | 159 | return ts->swi_errno; |
154 | case SYS_GET_CMDLINE: | 160 | case SYS_GET_CMDLINE: |
155 | /* XXX: Not implemented. */ | 161 | /* XXX: Not implemented. */ |
156 | - s = (char *)ARG(0); | 162 | + s = (char *)g2h(ARG(0)); |
157 | *s = 0; | 163 | *s = 0; |
158 | return -1; | 164 | return -1; |
159 | case SYS_HEAPINFO: | 165 | case SYS_HEAPINFO: |
@@ -166,11 +172,11 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -166,11 +172,11 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
166 | if (!ts->heap_limit) { | 172 | if (!ts->heap_limit) { |
167 | long ret; | 173 | long ret; |
168 | 174 | ||
169 | - ts->heap_base = do_brk(NULL); | 175 | + ts->heap_base = do_brk(0); |
170 | limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE; | 176 | limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE; |
171 | /* Try a big heap, and reduce the size if that fails. */ | 177 | /* Try a big heap, and reduce the size if that fails. */ |
172 | for (;;) { | 178 | for (;;) { |
173 | - ret = do_brk((char *)limit); | 179 | + ret = do_brk(limit); |
174 | if (ret != -1) | 180 | if (ret != -1) |
175 | break; | 181 | break; |
176 | limit = (ts->heap_base >> 1) + (limit >> 1); | 182 | limit = (ts->heap_base >> 1) + (limit >> 1); |
@@ -178,7 +184,8 @@ uint32_t do_arm_semihosting(CPUState *env) | @@ -178,7 +184,8 @@ uint32_t do_arm_semihosting(CPUState *env) | ||
178 | ts->heap_limit = limit; | 184 | ts->heap_limit = limit; |
179 | } | 185 | } |
180 | 186 | ||
181 | - ptr = (uint32_t *)ARG(0); | 187 | + page_unprotect_range (ARG(0), 32); |
188 | + ptr = (uint32_t *)g2h(ARG(0)); | ||
182 | ptr[0] = tswap32(ts->heap_base); | 189 | ptr[0] = tswap32(ts->heap_base); |
183 | ptr[1] = tswap32(ts->heap_limit); | 190 | ptr[1] = tswap32(ts->heap_limit); |
184 | ptr[2] = tswap32(ts->stack_base); | 191 | ptr[2] = tswap32(ts->stack_base); |
linux-user/elfload.c
@@ -97,17 +97,17 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i | @@ -97,17 +97,17 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i | ||
97 | 97 | ||
98 | static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) | 98 | static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) |
99 | { | 99 | { |
100 | - target_long *stack = (void *)infop->start_stack; | 100 | + target_long stack = infop->start_stack; |
101 | memset(regs, 0, sizeof(*regs)); | 101 | memset(regs, 0, sizeof(*regs)); |
102 | regs->ARM_cpsr = 0x10; | 102 | regs->ARM_cpsr = 0x10; |
103 | if (infop->entry & 1) | 103 | if (infop->entry & 1) |
104 | regs->ARM_cpsr |= CPSR_T; | 104 | regs->ARM_cpsr |= CPSR_T; |
105 | regs->ARM_pc = infop->entry & 0xfffffffe; | 105 | regs->ARM_pc = infop->entry & 0xfffffffe; |
106 | regs->ARM_sp = infop->start_stack; | 106 | regs->ARM_sp = infop->start_stack; |
107 | - regs->ARM_r2 = tswapl(stack[2]); /* envp */ | ||
108 | - regs->ARM_r1 = tswapl(stack[1]); /* argv */ | 107 | + regs->ARM_r2 = tgetl(stack + 8); /* envp */ |
108 | + regs->ARM_r1 = tgetl(stack + 4); /* envp */ | ||
109 | /* XXX: it seems that r0 is zeroed after ! */ | 109 | /* XXX: it seems that r0 is zeroed after ! */ |
110 | - // regs->ARM_r0 = tswapl(stack[0]); /* argc */ | 110 | + // regs->ARM_r0 = tgetl(stack); /* argc */ |
111 | } | 111 | } |
112 | 112 | ||
113 | #define USE_ELF_CORE_DUMP | 113 | #define USE_ELF_CORE_DUMP |
@@ -202,7 +202,7 @@ do { \ | @@ -202,7 +202,7 @@ do { \ | ||
202 | _r->gpr[3] = bprm->argc; \ | 202 | _r->gpr[3] = bprm->argc; \ |
203 | _r->gpr[4] = (unsigned long)++pos; \ | 203 | _r->gpr[4] = (unsigned long)++pos; \ |
204 | for (; tmp != 0; pos++) \ | 204 | for (; tmp != 0; pos++) \ |
205 | - tmp = *pos; \ | 205 | + tmp = ldl(pos); \ |
206 | _r->gpr[5] = (unsigned long)pos; \ | 206 | _r->gpr[5] = (unsigned long)pos; \ |
207 | } while (0) | 207 | } while (0) |
208 | 208 | ||
@@ -297,7 +297,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i | @@ -297,7 +297,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i | ||
297 | */ | 297 | */ |
298 | struct linux_binprm { | 298 | struct linux_binprm { |
299 | char buf[128]; | 299 | char buf[128]; |
300 | - unsigned long page[MAX_ARG_PAGES]; | 300 | + void *page[MAX_ARG_PAGES]; |
301 | unsigned long p; | 301 | unsigned long p; |
302 | int sh_bang; | 302 | int sh_bang; |
303 | int fd; | 303 | int fd; |
@@ -427,37 +427,13 @@ static void bswap_sym(Elf32_Sym *sym) | @@ -427,37 +427,13 @@ static void bswap_sym(Elf32_Sym *sym) | ||
427 | } | 427 | } |
428 | #endif | 428 | #endif |
429 | 429 | ||
430 | -static void * get_free_page(void) | ||
431 | -{ | ||
432 | - void * retval; | ||
433 | - | ||
434 | - /* User-space version of kernel get_free_page. Returns a page-aligned | ||
435 | - * page-sized chunk of memory. | ||
436 | - */ | ||
437 | - retval = (void *)target_mmap(0, qemu_host_page_size, PROT_READ|PROT_WRITE, | ||
438 | - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | ||
439 | - | ||
440 | - if((long)retval == -1) { | ||
441 | - perror("get_free_page"); | ||
442 | - exit(-1); | ||
443 | - } | ||
444 | - else { | ||
445 | - return(retval); | ||
446 | - } | ||
447 | -} | ||
448 | - | ||
449 | -static void free_page(void * pageaddr) | ||
450 | -{ | ||
451 | - target_munmap((unsigned long)pageaddr, qemu_host_page_size); | ||
452 | -} | ||
453 | - | ||
454 | /* | 430 | /* |
455 | * 'copy_string()' copies argument/envelope strings from user | 431 | * 'copy_string()' copies argument/envelope strings from user |
456 | * memory to free pages in kernel mem. These are in a format ready | 432 | * memory to free pages in kernel mem. These are in a format ready |
457 | * to be put directly into the top of new user memory. | 433 | * to be put directly into the top of new user memory. |
458 | * | 434 | * |
459 | */ | 435 | */ |
460 | -static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, | 436 | +static unsigned long copy_strings(int argc,char ** argv, void **page, |
461 | unsigned long p) | 437 | unsigned long p) |
462 | { | 438 | { |
463 | char *tmp, *tmp1, *pag = NULL; | 439 | char *tmp, *tmp1, *pag = NULL; |
@@ -482,10 +458,10 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, | @@ -482,10 +458,10 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, | ||
482 | --p; --tmp; --len; | 458 | --p; --tmp; --len; |
483 | if (--offset < 0) { | 459 | if (--offset < 0) { |
484 | offset = p % TARGET_PAGE_SIZE; | 460 | offset = p % TARGET_PAGE_SIZE; |
485 | - pag = (char *) page[p/TARGET_PAGE_SIZE]; | 461 | + pag = (char *)page[p/TARGET_PAGE_SIZE]; |
486 | if (!pag) { | 462 | if (!pag) { |
487 | - pag = (char *)get_free_page(); | ||
488 | - page[p/TARGET_PAGE_SIZE] = (unsigned long)pag; | 463 | + pag = (char *)malloc(TARGET_PAGE_SIZE); |
464 | + page[p/TARGET_PAGE_SIZE] = pag; | ||
489 | if (!pag) | 465 | if (!pag) |
490 | return 0; | 466 | return 0; |
491 | } | 467 | } |
@@ -591,10 +567,20 @@ static int prepare_binprm(struct linux_binprm *bprm) | @@ -591,10 +567,20 @@ static int prepare_binprm(struct linux_binprm *bprm) | ||
591 | } | 567 | } |
592 | } | 568 | } |
593 | 569 | ||
594 | -unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, | ||
595 | - struct image_info * info) | 570 | +static inline void memcpy_to_target(target_ulong dest, const void *src, |
571 | + unsigned long len) | ||
596 | { | 572 | { |
597 | - unsigned long stack_base, size, error; | 573 | + void *host_ptr; |
574 | + | ||
575 | + host_ptr = lock_user(dest, len, 0); | ||
576 | + memcpy(host_ptr, src, len); | ||
577 | + unlock_user(host_ptr, dest, 1); | ||
578 | +} | ||
579 | + | ||
580 | +unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm, | ||
581 | + struct image_info * info) | ||
582 | +{ | ||
583 | + target_ulong stack_base, size, error; | ||
598 | int i; | 584 | int i; |
599 | 585 | ||
600 | /* Create enough stack to hold everything. If we don't use | 586 | /* Create enough stack to hold everything. If we don't use |
@@ -627,10 +613,10 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, | @@ -627,10 +613,10 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, | ||
627 | if (bprm->page[i]) { | 613 | if (bprm->page[i]) { |
628 | info->rss++; | 614 | info->rss++; |
629 | 615 | ||
630 | - memcpy((void *)stack_base, (void *)bprm->page[i], TARGET_PAGE_SIZE); | ||
631 | - free_page((void *)bprm->page[i]); | 616 | + memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); |
617 | + free(bprm->page[i]); | ||
632 | } | 618 | } |
633 | - stack_base += TARGET_PAGE_SIZE; | 619 | + stack_base += TARGET_PAGE_SIZE; |
634 | } | 620 | } |
635 | return p; | 621 | return p; |
636 | } | 622 | } |
@@ -657,7 +643,6 @@ static void set_brk(unsigned long start, unsigned long end) | @@ -657,7 +643,6 @@ static void set_brk(unsigned long start, unsigned long end) | ||
657 | static void padzero(unsigned long elf_bss) | 643 | static void padzero(unsigned long elf_bss) |
658 | { | 644 | { |
659 | unsigned long nbyte; | 645 | unsigned long nbyte; |
660 | - char * fpnt; | ||
661 | 646 | ||
662 | /* XXX: this is really a hack : if the real host page size is | 647 | /* XXX: this is really a hack : if the real host page size is |
663 | smaller than the target page size, some pages after the end | 648 | smaller than the target page size, some pages after the end |
@@ -679,55 +664,57 @@ static void padzero(unsigned long elf_bss) | @@ -679,55 +664,57 @@ static void padzero(unsigned long elf_bss) | ||
679 | nbyte = elf_bss & (qemu_host_page_size-1); | 664 | nbyte = elf_bss & (qemu_host_page_size-1); |
680 | if (nbyte) { | 665 | if (nbyte) { |
681 | nbyte = qemu_host_page_size - nbyte; | 666 | nbyte = qemu_host_page_size - nbyte; |
682 | - fpnt = (char *) elf_bss; | ||
683 | do { | 667 | do { |
684 | - *fpnt++ = 0; | 668 | + tput8(elf_bss, 0); |
669 | + elf_bss++; | ||
685 | } while (--nbyte); | 670 | } while (--nbyte); |
686 | } | 671 | } |
687 | } | 672 | } |
688 | 673 | ||
689 | -static unsigned int * create_elf_tables(char *p, int argc, int envc, | ||
690 | - struct elfhdr * exec, | ||
691 | - unsigned long load_addr, | ||
692 | - unsigned long load_bias, | ||
693 | - unsigned long interp_load_addr, int ibcs, | ||
694 | - struct image_info *info) | 674 | + |
675 | +static unsigned long create_elf_tables(target_ulong p, int argc, int envc, | ||
676 | + struct elfhdr * exec, | ||
677 | + unsigned long load_addr, | ||
678 | + unsigned long load_bias, | ||
679 | + unsigned long interp_load_addr, int ibcs, | ||
680 | + struct image_info *info) | ||
695 | { | 681 | { |
696 | - target_ulong *argv, *envp; | ||
697 | - target_ulong *sp, *csp; | ||
698 | - target_ulong *u_platform; | 682 | + target_ulong argv, envp; |
683 | + target_ulong sp; | ||
684 | + int size; | ||
685 | + target_ulong u_platform; | ||
699 | const char *k_platform; | 686 | const char *k_platform; |
700 | - int v; | 687 | + const int n = sizeof(target_ulong); |
701 | 688 | ||
702 | - /* | ||
703 | - * Force 16 byte _final_ alignment here for generality. | ||
704 | - */ | ||
705 | - sp = (unsigned int *) (~15UL & (unsigned long) p); | ||
706 | - u_platform = NULL; | 689 | + sp = p; |
690 | + u_platform = 0; | ||
707 | k_platform = ELF_PLATFORM; | 691 | k_platform = ELF_PLATFORM; |
708 | if (k_platform) { | 692 | if (k_platform) { |
709 | size_t len = strlen(k_platform) + 1; | 693 | size_t len = strlen(k_platform) + 1; |
710 | - sp -= (len + sizeof(target_ulong) - 1) / sizeof(target_ulong); | ||
711 | - u_platform = (target_ulong *)sp; | ||
712 | - __copy_to_user(u_platform, k_platform, len); | 694 | + sp -= (len + n - 1) & ~(n - 1); |
695 | + u_platform = sp; | ||
696 | + memcpy_to_target(sp, k_platform, len); | ||
713 | } | 697 | } |
714 | - csp = sp; | ||
715 | - csp -= (DLINFO_ITEMS + 1) * 2; | 698 | + /* |
699 | + * Force 16 byte _final_ alignment here for generality. | ||
700 | + */ | ||
701 | + sp = sp &~ (target_ulong)15; | ||
702 | + size = (DLINFO_ITEMS + 1) * 2; | ||
716 | if (k_platform) | 703 | if (k_platform) |
717 | - csp -= 2; | 704 | + size += 2; |
718 | #ifdef DLINFO_ARCH_ITEMS | 705 | #ifdef DLINFO_ARCH_ITEMS |
719 | - csp -= DLINFO_ARCH_ITEMS*2; | 706 | + size += DLINFO_ARCH_ITEMS * 2; |
720 | #endif | 707 | #endif |
721 | - csp -= envc+1; | ||
722 | - csp -= argc+1; | ||
723 | - csp -= (!ibcs ? 3 : 1); /* argc itself */ | ||
724 | - if ((unsigned long)csp & 15UL) | ||
725 | - sp -= ((unsigned long)csp & 15UL) / sizeof(*sp); | 708 | + size += envc + argc + 2; |
709 | + size += (!ibcs ? 3 : 1); /* argc itself */ | ||
710 | + size *= n; | ||
711 | + if (size & 15) | ||
712 | + sp -= 16 - (size & 15); | ||
726 | 713 | ||
727 | -#define NEW_AUX_ENT(id, val) \ | ||
728 | - sp -= 2; \ | ||
729 | - put_user (id, sp); \ | ||
730 | - put_user (val, sp + 1) | 714 | +#define NEW_AUX_ENT(id, val) do { \ |
715 | + sp -= n; tputl(sp, val); \ | ||
716 | + sp -= n; tputl(sp, id); \ | ||
717 | + } while(0) | ||
731 | NEW_AUX_ENT (AT_NULL, 0); | 718 | NEW_AUX_ENT (AT_NULL, 0); |
732 | 719 | ||
733 | /* There must be exactly DLINFO_ITEMS entries here. */ | 720 | /* There must be exactly DLINFO_ITEMS entries here. */ |
@@ -744,7 +731,7 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, | @@ -744,7 +731,7 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, | ||
744 | NEW_AUX_ENT(AT_EGID, (target_ulong) getegid()); | 731 | NEW_AUX_ENT(AT_EGID, (target_ulong) getegid()); |
745 | NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP); | 732 | NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP); |
746 | if (k_platform) | 733 | if (k_platform) |
747 | - NEW_AUX_ENT(AT_PLATFORM, (target_ulong) u_platform); | 734 | + NEW_AUX_ENT(AT_PLATFORM, u_platform); |
748 | #ifdef ARCH_DLINFO | 735 | #ifdef ARCH_DLINFO |
749 | /* | 736 | /* |
750 | * ARCH_DLINFO must come last so platform specific code can enforce | 737 | * ARCH_DLINFO must come last so platform specific code can enforce |
@@ -754,39 +741,32 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, | @@ -754,39 +741,32 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, | ||
754 | #endif | 741 | #endif |
755 | #undef NEW_AUX_ENT | 742 | #undef NEW_AUX_ENT |
756 | 743 | ||
757 | - sp -= envc+1; | 744 | + sp -= (envc + 1) * n; |
758 | envp = sp; | 745 | envp = sp; |
759 | - sp -= argc+1; | 746 | + sp -= (argc + 1) * n; |
760 | argv = sp; | 747 | argv = sp; |
761 | if (!ibcs) { | 748 | if (!ibcs) { |
762 | - put_user((target_ulong)envp,--sp); | ||
763 | - put_user((target_ulong)argv,--sp); | 749 | + sp -= n; tputl(sp, envp); |
750 | + sp -= n; tputl(sp, argv); | ||
764 | } | 751 | } |
765 | - put_user(argc,--sp); | ||
766 | - info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff); | 752 | + sp -= n; tputl(sp, argc); |
753 | + info->arg_start = p; | ||
767 | while (argc-->0) { | 754 | while (argc-->0) { |
768 | - put_user((target_ulong)p,argv++); | ||
769 | - do { | ||
770 | - get_user(v, p); | ||
771 | - p++; | ||
772 | - } while (v != 0); | 755 | + tputl(argv, p); argv += n; |
756 | + p += target_strlen(p) + 1; | ||
773 | } | 757 | } |
774 | - put_user(0,argv); | ||
775 | - info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff); | 758 | + tputl(argv, 0); |
759 | + info->arg_end = info->env_start = p; | ||
776 | while (envc-->0) { | 760 | while (envc-->0) { |
777 | - put_user((target_ulong)p,envp++); | ||
778 | - do { | ||
779 | - get_user(v, p); | ||
780 | - p++; | ||
781 | - } while (v != 0); | 761 | + tputl(envp, p); envp += n; |
762 | + p += target_strlen(p) + 1; | ||
782 | } | 763 | } |
783 | - put_user(0,envp); | ||
784 | - info->env_end = (unsigned int)((unsigned long)p & 0xffffffff); | 764 | + tputl(envp, 0); |
765 | + info->env_end = p; | ||
785 | return sp; | 766 | return sp; |
786 | } | 767 | } |
787 | 768 | ||
788 | 769 | ||
789 | - | ||
790 | static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | 770 | static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
791 | int interpreter_fd, | 771 | int interpreter_fd, |
792 | unsigned long *interp_load_addr) | 772 | unsigned long *interp_load_addr) |
@@ -1335,8 +1315,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | @@ -1335,8 +1315,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
1335 | #ifdef LOW_ELF_STACK | 1315 | #ifdef LOW_ELF_STACK |
1336 | info->start_stack = bprm->p = elf_stack - 4; | 1316 | info->start_stack = bprm->p = elf_stack - 4; |
1337 | #endif | 1317 | #endif |
1338 | - bprm->p = (unsigned long) | ||
1339 | - create_elf_tables((char *)bprm->p, | 1318 | + bprm->p = create_elf_tables(bprm->p, |
1340 | bprm->argc, | 1319 | bprm->argc, |
1341 | bprm->envc, | 1320 | bprm->envc, |
1342 | &elf_ex, | 1321 | &elf_ex, |
@@ -1432,6 +1411,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, | @@ -1432,6 +1411,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, | ||
1432 | if(retval>=0) { | 1411 | if(retval>=0) { |
1433 | retval = load_elf_binary(&bprm,regs,infop); | 1412 | retval = load_elf_binary(&bprm,regs,infop); |
1434 | } | 1413 | } |
1414 | + | ||
1435 | if(retval>=0) { | 1415 | if(retval>=0) { |
1436 | /* success. Initialize important registers */ | 1416 | /* success. Initialize important registers */ |
1437 | init_thread(regs, infop); | 1417 | init_thread(regs, infop); |
@@ -1440,7 +1420,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, | @@ -1440,7 +1420,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, | ||
1440 | 1420 | ||
1441 | /* Something went wrong, return the inode and free the argument pages*/ | 1421 | /* Something went wrong, return the inode and free the argument pages*/ |
1442 | for (i=0 ; i<MAX_ARG_PAGES ; i++) { | 1422 | for (i=0 ; i<MAX_ARG_PAGES ; i++) { |
1443 | - free_page((void *)bprm.page[i]); | 1423 | + free(bprm.page[i]); |
1444 | } | 1424 | } |
1445 | return(retval); | 1425 | return(retval); |
1446 | } | 1426 | } |
linux-user/ioctls.h
@@ -55,7 +55,7 @@ | @@ -55,7 +55,7 @@ | ||
55 | IOCTL(KDMKTONE, 0, TYPE_INT) | 55 | IOCTL(KDMKTONE, 0, TYPE_INT) |
56 | IOCTL(KDGKBTYPE, IOC_R, MK_PTR(TYPE_CHAR)) | 56 | IOCTL(KDGKBTYPE, IOC_R, MK_PTR(TYPE_CHAR)) |
57 | IOCTL(KDGKBENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbentry))) | 57 | IOCTL(KDGKBENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbentry))) |
58 | - IOCTL(KDGKBSENT, IOC_RW, TYPE_PTRVOID) | 58 | + IOCTL(KDGKBSENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbsentry))) |
59 | 59 | ||
60 | IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT)) | 60 | IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT)) |
61 | IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT)) | 61 | IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT)) |
linux-user/main.c
@@ -152,21 +152,25 @@ static void write_dt(void *ptr, unsigned long addr, unsigned long limit, | @@ -152,21 +152,25 @@ static void write_dt(void *ptr, unsigned long addr, unsigned long limit, | ||
152 | int flags) | 152 | int flags) |
153 | { | 153 | { |
154 | unsigned int e1, e2; | 154 | unsigned int e1, e2; |
155 | + uint32_t *p; | ||
155 | e1 = (addr << 16) | (limit & 0xffff); | 156 | e1 = (addr << 16) | (limit & 0xffff); |
156 | e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); | 157 | e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); |
157 | e2 |= flags; | 158 | e2 |= flags; |
158 | - stl((uint8_t *)ptr, e1); | ||
159 | - stl((uint8_t *)ptr + 4, e2); | 159 | + p = ptr; |
160 | + p[0] = tswapl(e1); | ||
161 | + p[1] = tswapl(e2); | ||
160 | } | 162 | } |
161 | 163 | ||
162 | static void set_gate(void *ptr, unsigned int type, unsigned int dpl, | 164 | static void set_gate(void *ptr, unsigned int type, unsigned int dpl, |
163 | unsigned long addr, unsigned int sel) | 165 | unsigned long addr, unsigned int sel) |
164 | { | 166 | { |
165 | unsigned int e1, e2; | 167 | unsigned int e1, e2; |
168 | + uint32_t *p; | ||
166 | e1 = (addr & 0xffff) | (sel << 16); | 169 | e1 = (addr & 0xffff) | (sel << 16); |
167 | e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); | 170 | e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); |
168 | - stl((uint8_t *)ptr, e1); | ||
169 | - stl((uint8_t *)ptr + 4, e2); | 171 | + p = ptr; |
172 | + p[0] = tswapl(e1); | ||
173 | + p[1] = tswapl(e2); | ||
170 | } | 174 | } |
171 | 175 | ||
172 | uint64_t gdt_table[6]; | 176 | uint64_t gdt_table[6]; |
@@ -343,7 +347,7 @@ void cpu_loop(CPUARMState *env) | @@ -343,7 +347,7 @@ void cpu_loop(CPUARMState *env) | ||
343 | 347 | ||
344 | /* we handle the FPU emulation here, as Linux */ | 348 | /* we handle the FPU emulation here, as Linux */ |
345 | /* we get the opcode */ | 349 | /* we get the opcode */ |
346 | - opcode = ldl_raw((uint8_t *)env->regs[15]); | 350 | + opcode = tget32(env->regs[15]); |
347 | 351 | ||
348 | if (EmulateAll(opcode, &ts->fpa, env) == 0) { | 352 | if (EmulateAll(opcode, &ts->fpa, env) == 0) { |
349 | info.si_signo = SIGILL; | 353 | info.si_signo = SIGILL; |
@@ -364,20 +368,20 @@ void cpu_loop(CPUARMState *env) | @@ -364,20 +368,20 @@ void cpu_loop(CPUARMState *env) | ||
364 | /* system call */ | 368 | /* system call */ |
365 | if (trapnr == EXCP_BKPT) { | 369 | if (trapnr == EXCP_BKPT) { |
366 | if (env->thumb) { | 370 | if (env->thumb) { |
367 | - insn = lduw((void *)(env->regs[15])); | 371 | + insn = tget16(env->regs[15]); |
368 | n = insn & 0xff; | 372 | n = insn & 0xff; |
369 | env->regs[15] += 2; | 373 | env->regs[15] += 2; |
370 | } else { | 374 | } else { |
371 | - insn = ldl((void *)(env->regs[15])); | 375 | + insn = tget32(env->regs[15]); |
372 | n = (insn & 0xf) | ((insn >> 4) & 0xff0); | 376 | n = (insn & 0xf) | ((insn >> 4) & 0xff0); |
373 | env->regs[15] += 4; | 377 | env->regs[15] += 4; |
374 | } | 378 | } |
375 | } else { | 379 | } else { |
376 | if (env->thumb) { | 380 | if (env->thumb) { |
377 | - insn = lduw((void *)(env->regs[15] - 2)); | 381 | + insn = tget16(env->regs[15] - 2); |
378 | n = insn & 0xff; | 382 | n = insn & 0xff; |
379 | } else { | 383 | } else { |
380 | - insn = ldl((void *)(env->regs[15] - 4)); | 384 | + insn = tget32(env->regs[15] - 4); |
381 | n = insn & 0xffffff; | 385 | n = insn & 0xffffff; |
382 | } | 386 | } |
383 | } | 387 | } |
@@ -475,16 +479,16 @@ static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) | @@ -475,16 +479,16 @@ static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) | ||
475 | static inline void save_window_offset(CPUSPARCState *env, int cwp1) | 479 | static inline void save_window_offset(CPUSPARCState *env, int cwp1) |
476 | { | 480 | { |
477 | unsigned int i; | 481 | unsigned int i; |
478 | - uint32_t *sp_ptr; | 482 | + target_ulong sp_ptr; |
479 | 483 | ||
480 | - sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]); | 484 | + sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; |
481 | #if defined(DEBUG_WIN) | 485 | #if defined(DEBUG_WIN) |
482 | printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n", | 486 | printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n", |
483 | (int)sp_ptr, cwp1); | 487 | (int)sp_ptr, cwp1); |
484 | #endif | 488 | #endif |
485 | for(i = 0; i < 16; i++) { | 489 | for(i = 0; i < 16; i++) { |
486 | - put_user(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); | ||
487 | - sp_ptr++; | 490 | + tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]); |
491 | + sp_ptr += sizeof(target_ulong); | ||
488 | } | 492 | } |
489 | } | 493 | } |
490 | 494 | ||
@@ -500,22 +504,21 @@ static void save_window(CPUSPARCState *env) | @@ -500,22 +504,21 @@ static void save_window(CPUSPARCState *env) | ||
500 | static void restore_window(CPUSPARCState *env) | 504 | static void restore_window(CPUSPARCState *env) |
501 | { | 505 | { |
502 | unsigned int new_wim, i, cwp1; | 506 | unsigned int new_wim, i, cwp1; |
503 | - uint32_t *sp_ptr, reg; | 507 | + target_ulong sp_ptr; |
504 | 508 | ||
505 | new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) & | 509 | new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) & |
506 | ((1LL << NWINDOWS) - 1); | 510 | ((1LL << NWINDOWS) - 1); |
507 | 511 | ||
508 | /* restore the invalid window */ | 512 | /* restore the invalid window */ |
509 | cwp1 = (env->cwp + 1) & (NWINDOWS - 1); | 513 | cwp1 = (env->cwp + 1) & (NWINDOWS - 1); |
510 | - sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]); | 514 | + sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; |
511 | #if defined(DEBUG_WIN) | 515 | #if defined(DEBUG_WIN) |
512 | printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n", | 516 | printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n", |
513 | (int)sp_ptr, cwp1); | 517 | (int)sp_ptr, cwp1); |
514 | #endif | 518 | #endif |
515 | for(i = 0; i < 16; i++) { | 519 | for(i = 0; i < 16; i++) { |
516 | - get_user(reg, sp_ptr); | ||
517 | - env->regbase[get_reg_index(env, cwp1, 8 + i)] = reg; | ||
518 | - sp_ptr++; | 520 | + env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr); |
521 | + sp_ptr += sizeof(target_ulong); | ||
519 | } | 522 | } |
520 | env->wim = new_wim; | 523 | env->wim = new_wim; |
521 | } | 524 | } |
@@ -1304,15 +1307,9 @@ void cpu_loop(CPUMIPSState *env) | @@ -1304,15 +1307,9 @@ void cpu_loop(CPUMIPSState *env) | ||
1304 | if (nb_args >= 5) { | 1307 | if (nb_args >= 5) { |
1305 | sp_reg = env->gpr[29]; | 1308 | sp_reg = env->gpr[29]; |
1306 | /* these arguments are taken from the stack */ | 1309 | /* these arguments are taken from the stack */ |
1307 | - if (get_user(arg5, (target_ulong *)(sp_reg + 16))) { | ||
1308 | - ret = -EFAULT; | ||
1309 | - goto fail; | ||
1310 | - } | 1310 | + arg5 = tgetl(sp_reg + 16); |
1311 | if (nb_args >= 6) { | 1311 | if (nb_args >= 6) { |
1312 | - if (get_user(arg6, (target_ulong *)(sp_reg + 20))) { | ||
1313 | - ret = -EFAULT; | ||
1314 | - goto fail; | ||
1315 | - } | 1312 | + arg6 = tgetl(sp_reg + 20); |
1316 | } else { | 1313 | } else { |
1317 | arg6 = 0; | 1314 | arg6 = 0; |
1318 | } | 1315 | } |
@@ -1347,8 +1344,7 @@ void cpu_loop(CPUMIPSState *env) | @@ -1347,8 +1344,7 @@ void cpu_loop(CPUMIPSState *env) | ||
1347 | { | 1344 | { |
1348 | uint32_t insn, op; | 1345 | uint32_t insn, op; |
1349 | 1346 | ||
1350 | - if (get_user(insn, (uint32_t *)env->PC) < 0) | ||
1351 | - goto sigill; | 1347 | + insn = tget32(env->PC); |
1352 | op = insn >> 26; | 1348 | op = insn >> 26; |
1353 | // printf("insn=%08x op=%02x\n", insn, op); | 1349 | // printf("insn=%08x op=%02x\n", insn, op); |
1354 | /* XXX: totally dummy FP ops just to be able to launch | 1350 | /* XXX: totally dummy FP ops just to be able to launch |
@@ -1531,7 +1527,7 @@ int main(int argc, char **argv) | @@ -1531,7 +1527,7 @@ int main(int argc, char **argv) | ||
1531 | fprintf(logfile, "entry 0x%08lx\n" , info->entry); | 1527 | fprintf(logfile, "entry 0x%08lx\n" , info->entry); |
1532 | } | 1528 | } |
1533 | 1529 | ||
1534 | - target_set_brk((char *)info->brk); | 1530 | + target_set_brk(info->brk); |
1535 | syscall_init(); | 1531 | syscall_init(); |
1536 | signal_init(); | 1532 | signal_init(); |
1537 | 1533 | ||
@@ -1566,7 +1562,7 @@ int main(int argc, char **argv) | @@ -1566,7 +1562,7 @@ int main(int argc, char **argv) | ||
1566 | env->eip = regs->eip; | 1562 | env->eip = regs->eip; |
1567 | 1563 | ||
1568 | /* linux interrupt setup */ | 1564 | /* linux interrupt setup */ |
1569 | - env->idt.base = (long)idt_table; | 1565 | + env->idt.base = h2g(idt_table); |
1570 | env->idt.limit = sizeof(idt_table) - 1; | 1566 | env->idt.limit = sizeof(idt_table) - 1; |
1571 | set_idt(0, 0); | 1567 | set_idt(0, 0); |
1572 | set_idt(1, 0); | 1568 | set_idt(1, 0); |
@@ -1591,7 +1587,7 @@ int main(int argc, char **argv) | @@ -1591,7 +1587,7 @@ int main(int argc, char **argv) | ||
1591 | set_idt(0x80, 3); | 1587 | set_idt(0x80, 3); |
1592 | 1588 | ||
1593 | /* linux segment setup */ | 1589 | /* linux segment setup */ |
1594 | - env->gdt.base = (long)gdt_table; | 1590 | + env->gdt.base = h2g(gdt_table); |
1595 | env->gdt.limit = sizeof(gdt_table) - 1; | 1591 | env->gdt.limit = sizeof(gdt_table) - 1; |
1596 | write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, | 1592 | write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, |
1597 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | | 1593 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | |
linux-user/mmap.c
@@ -29,10 +29,10 @@ | @@ -29,10 +29,10 @@ | ||
29 | 29 | ||
30 | //#define DEBUG_MMAP | 30 | //#define DEBUG_MMAP |
31 | 31 | ||
32 | -/* NOTE: all the constants are the HOST ones */ | ||
33 | -int target_mprotect(unsigned long start, unsigned long len, int prot) | 32 | +/* NOTE: all the constants are the HOST ones, but addresses are target. */ |
33 | +int target_mprotect(target_ulong start, target_ulong len, int prot) | ||
34 | { | 34 | { |
35 | - unsigned long end, host_start, host_end, addr; | 35 | + target_ulong end, host_start, host_end, addr; |
36 | int prot1, ret; | 36 | int prot1, ret; |
37 | 37 | ||
38 | #ifdef DEBUG_MMAP | 38 | #ifdef DEBUG_MMAP |
@@ -67,7 +67,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | @@ -67,7 +67,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | ||
67 | } | 67 | } |
68 | end = host_end; | 68 | end = host_end; |
69 | } | 69 | } |
70 | - ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS); | 70 | + ret = mprotect(g2h(host_start), qemu_host_page_size, prot1 & PAGE_BITS); |
71 | if (ret != 0) | 71 | if (ret != 0) |
72 | return ret; | 72 | return ret; |
73 | host_start += qemu_host_page_size; | 73 | host_start += qemu_host_page_size; |
@@ -77,7 +77,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | @@ -77,7 +77,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | ||
77 | for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { | 77 | for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { |
78 | prot1 |= page_get_flags(addr); | 78 | prot1 |= page_get_flags(addr); |
79 | } | 79 | } |
80 | - ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size, | 80 | + ret = mprotect(g2h(host_end - qemu_host_page_size), qemu_host_page_size, |
81 | prot1 & PAGE_BITS); | 81 | prot1 & PAGE_BITS); |
82 | if (ret != 0) | 82 | if (ret != 0) |
83 | return ret; | 83 | return ret; |
@@ -86,7 +86,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | @@ -86,7 +86,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | ||
86 | 86 | ||
87 | /* handle the pages in the middle */ | 87 | /* handle the pages in the middle */ |
88 | if (host_start < host_end) { | 88 | if (host_start < host_end) { |
89 | - ret = mprotect((void *)host_start, host_end - host_start, prot); | 89 | + ret = mprotect(g2h(host_start), host_end - host_start, prot); |
90 | if (ret != 0) | 90 | if (ret != 0) |
91 | return ret; | 91 | return ret; |
92 | } | 92 | } |
@@ -95,28 +95,31 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | @@ -95,28 +95,31 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) | ||
95 | } | 95 | } |
96 | 96 | ||
97 | /* map an incomplete host page */ | 97 | /* map an incomplete host page */ |
98 | -int mmap_frag(unsigned long host_start, | ||
99 | - unsigned long start, unsigned long end, | ||
100 | - int prot, int flags, int fd, unsigned long offset) | 98 | +static int mmap_frag(target_ulong real_start, |
99 | + target_ulong start, target_ulong end, | ||
100 | + int prot, int flags, int fd, target_ulong offset) | ||
101 | { | 101 | { |
102 | - unsigned long host_end, ret, addr; | 102 | + target_ulong real_end, ret, addr; |
103 | + void *host_start; | ||
103 | int prot1, prot_new; | 104 | int prot1, prot_new; |
104 | 105 | ||
105 | - host_end = host_start + qemu_host_page_size; | 106 | + real_end = real_start + qemu_host_page_size; |
107 | + host_start = g2h(real_start); | ||
106 | 108 | ||
107 | /* get the protection of the target pages outside the mapping */ | 109 | /* get the protection of the target pages outside the mapping */ |
108 | prot1 = 0; | 110 | prot1 = 0; |
109 | - for(addr = host_start; addr < host_end; addr++) { | 111 | + for(addr = real_start; addr < real_end; addr++) { |
110 | if (addr < start || addr >= end) | 112 | if (addr < start || addr >= end) |
111 | prot1 |= page_get_flags(addr); | 113 | prot1 |= page_get_flags(addr); |
112 | } | 114 | } |
113 | 115 | ||
114 | if (prot1 == 0) { | 116 | if (prot1 == 0) { |
115 | /* no page was there, so we allocate one */ | 117 | /* no page was there, so we allocate one */ |
116 | - ret = (long)mmap((void *)host_start, qemu_host_page_size, prot, | 118 | + ret = (long)mmap(host_start, qemu_host_page_size, prot, |
117 | flags | MAP_ANONYMOUS, -1, 0); | 119 | flags | MAP_ANONYMOUS, -1, 0); |
118 | if (ret == -1) | 120 | if (ret == -1) |
119 | return ret; | 121 | return ret; |
122 | + prot1 = prot; | ||
120 | } | 123 | } |
121 | prot1 &= PAGE_BITS; | 124 | prot1 &= PAGE_BITS; |
122 | 125 | ||
@@ -130,31 +133,35 @@ int mmap_frag(unsigned long host_start, | @@ -130,31 +133,35 @@ int mmap_frag(unsigned long host_start, | ||
130 | 133 | ||
131 | /* adjust protection to be able to read */ | 134 | /* adjust protection to be able to read */ |
132 | if (!(prot1 & PROT_WRITE)) | 135 | if (!(prot1 & PROT_WRITE)) |
133 | - mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE); | 136 | + mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE); |
134 | 137 | ||
135 | /* read the corresponding file data */ | 138 | /* read the corresponding file data */ |
136 | - pread(fd, (void *)start, end - start, offset); | 139 | + pread(fd, g2h(start), end - start, offset); |
137 | 140 | ||
138 | /* put final protection */ | 141 | /* put final protection */ |
139 | if (prot_new != (prot1 | PROT_WRITE)) | 142 | if (prot_new != (prot1 | PROT_WRITE)) |
140 | - mprotect((void *)host_start, qemu_host_page_size, prot_new); | 143 | + mprotect(host_start, qemu_host_page_size, prot_new); |
141 | } else { | 144 | } else { |
142 | /* just update the protection */ | 145 | /* just update the protection */ |
143 | if (prot_new != prot1) { | 146 | if (prot_new != prot1) { |
144 | - mprotect((void *)host_start, qemu_host_page_size, prot_new); | 147 | + mprotect(host_start, qemu_host_page_size, prot_new); |
145 | } | 148 | } |
146 | } | 149 | } |
147 | return 0; | 150 | return 0; |
148 | } | 151 | } |
149 | 152 | ||
150 | /* NOTE: all the constants are the HOST ones */ | 153 | /* NOTE: all the constants are the HOST ones */ |
151 | -long target_mmap(unsigned long start, unsigned long len, int prot, | ||
152 | - int flags, int fd, unsigned long offset) | 154 | +long target_mmap(target_ulong start, target_ulong len, int prot, |
155 | + int flags, int fd, target_ulong offset) | ||
153 | { | 156 | { |
154 | - unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len; | 157 | + target_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; |
158 | + long host_start; | ||
155 | #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \ | 159 | #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \ |
156 | defined(__ia64) | 160 | defined(__ia64) |
157 | - static unsigned long last_start = 0x40000000; | 161 | + static target_ulong last_start = 0x40000000; |
162 | +#elif defined(__CYGWIN__) | ||
163 | + /* Cygwin doesn't have a whole lot of address space. */ | ||
164 | + static target_ulong last_start = 0x18000000; | ||
158 | #endif | 165 | #endif |
159 | 166 | ||
160 | #ifdef DEBUG_MMAP | 167 | #ifdef DEBUG_MMAP |
@@ -191,45 +198,49 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | @@ -191,45 +198,49 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | ||
191 | len = TARGET_PAGE_ALIGN(len); | 198 | len = TARGET_PAGE_ALIGN(len); |
192 | if (len == 0) | 199 | if (len == 0) |
193 | return start; | 200 | return start; |
194 | - host_start = start & qemu_host_page_mask; | 201 | + real_start = start & qemu_host_page_mask; |
195 | 202 | ||
196 | if (!(flags & MAP_FIXED)) { | 203 | if (!(flags & MAP_FIXED)) { |
197 | #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \ | 204 | #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \ |
198 | - defined(__ia64) | 205 | + defined(__ia64) || defined(__CYGWIN__) |
199 | /* tell the kenel to search at the same place as i386 */ | 206 | /* tell the kenel to search at the same place as i386 */ |
200 | - if (host_start == 0) { | ||
201 | - host_start = last_start; | 207 | + if (real_start == 0) { |
208 | + real_start = last_start; | ||
202 | last_start += HOST_PAGE_ALIGN(len); | 209 | last_start += HOST_PAGE_ALIGN(len); |
203 | } | 210 | } |
204 | #endif | 211 | #endif |
205 | if (qemu_host_page_size != qemu_real_host_page_size) { | 212 | if (qemu_host_page_size != qemu_real_host_page_size) { |
206 | /* NOTE: this code is only for debugging with '-p' option */ | 213 | /* NOTE: this code is only for debugging with '-p' option */ |
214 | + /* ??? Can also occur when TARGET_PAGE_SIZE > host page size. */ | ||
207 | /* reserve a memory area */ | 215 | /* reserve a memory area */ |
216 | + /* ??? This needs fixing for remapping. */ | ||
217 | +abort(); | ||
208 | host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE; | 218 | host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE; |
209 | - host_start = (long)mmap((void *)host_start, host_len, PROT_NONE, | 219 | + real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE, |
210 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 220 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
211 | - if (host_start == -1) | ||
212 | - return host_start; | ||
213 | - host_end = host_start + host_len; | ||
214 | - start = HOST_PAGE_ALIGN(host_start); | 221 | + if (real_start == -1) |
222 | + return real_start; | ||
223 | + real_end = real_start + host_len; | ||
224 | + start = HOST_PAGE_ALIGN(real_start); | ||
215 | end = start + HOST_PAGE_ALIGN(len); | 225 | end = start + HOST_PAGE_ALIGN(len); |
216 | - if (start > host_start) | ||
217 | - munmap((void *)host_start, start - host_start); | ||
218 | - if (end < host_end) | ||
219 | - munmap((void *)end, host_end - end); | 226 | + if (start > real_start) |
227 | + munmap((void *)real_start, start - real_start); | ||
228 | + if (end < real_end) | ||
229 | + munmap((void *)end, real_end - end); | ||
220 | /* use it as a fixed mapping */ | 230 | /* use it as a fixed mapping */ |
221 | flags |= MAP_FIXED; | 231 | flags |= MAP_FIXED; |
222 | } else { | 232 | } else { |
223 | /* if not fixed, no need to do anything */ | 233 | /* if not fixed, no need to do anything */ |
224 | host_offset = offset & qemu_host_page_mask; | 234 | host_offset = offset & qemu_host_page_mask; |
225 | host_len = len + offset - host_offset; | 235 | host_len = len + offset - host_offset; |
226 | - start = (long)mmap((void *)host_start, host_len, | ||
227 | - prot, flags, fd, host_offset); | ||
228 | - if (start == -1) | ||
229 | - return start; | 236 | + host_start = (long)mmap(real_start ? g2h(real_start) : NULL, |
237 | + host_len, prot, flags, fd, host_offset); | ||
238 | + if (host_start == -1) | ||
239 | + return host_start; | ||
230 | /* update start so that it points to the file position at 'offset' */ | 240 | /* update start so that it points to the file position at 'offset' */ |
231 | if (!(flags & MAP_ANONYMOUS)) | 241 | if (!(flags & MAP_ANONYMOUS)) |
232 | - start += offset - host_offset; | 242 | + host_start += offset - host_offset; |
243 | + start = h2g(host_start); | ||
233 | goto the_end1; | 244 | goto the_end1; |
234 | } | 245 | } |
235 | } | 246 | } |
@@ -239,7 +250,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | @@ -239,7 +250,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | ||
239 | return -1; | 250 | return -1; |
240 | } | 251 | } |
241 | end = start + len; | 252 | end = start + len; |
242 | - host_end = HOST_PAGE_ALIGN(end); | 253 | + real_end = HOST_PAGE_ALIGN(end); |
243 | 254 | ||
244 | /* worst case: we cannot map the file because the offset is not | 255 | /* worst case: we cannot map the file because the offset is not |
245 | aligned, so we read it */ | 256 | aligned, so we read it */ |
@@ -257,7 +268,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | @@ -257,7 +268,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | ||
257 | -1, 0); | 268 | -1, 0); |
258 | if (retaddr == -1) | 269 | if (retaddr == -1) |
259 | return retaddr; | 270 | return retaddr; |
260 | - pread(fd, (void *)start, len, offset); | 271 | + pread(fd, g2h(start), len, offset); |
261 | if (!(prot & PROT_WRITE)) { | 272 | if (!(prot & PROT_WRITE)) { |
262 | ret = target_mprotect(start, len, prot); | 273 | ret = target_mprotect(start, len, prot); |
263 | if (ret != 0) | 274 | if (ret != 0) |
@@ -267,40 +278,40 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | @@ -267,40 +278,40 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | ||
267 | } | 278 | } |
268 | 279 | ||
269 | /* handle the start of the mapping */ | 280 | /* handle the start of the mapping */ |
270 | - if (start > host_start) { | ||
271 | - if (host_end == host_start + qemu_host_page_size) { | 281 | + if (start > real_start) { |
282 | + if (real_end == real_start + qemu_host_page_size) { | ||
272 | /* one single host page */ | 283 | /* one single host page */ |
273 | - ret = mmap_frag(host_start, start, end, | 284 | + ret = mmap_frag(real_start, start, end, |
274 | prot, flags, fd, offset); | 285 | prot, flags, fd, offset); |
275 | if (ret == -1) | 286 | if (ret == -1) |
276 | return ret; | 287 | return ret; |
277 | goto the_end1; | 288 | goto the_end1; |
278 | } | 289 | } |
279 | - ret = mmap_frag(host_start, start, host_start + qemu_host_page_size, | 290 | + ret = mmap_frag(real_start, start, real_start + qemu_host_page_size, |
280 | prot, flags, fd, offset); | 291 | prot, flags, fd, offset); |
281 | if (ret == -1) | 292 | if (ret == -1) |
282 | return ret; | 293 | return ret; |
283 | - host_start += qemu_host_page_size; | 294 | + real_start += qemu_host_page_size; |
284 | } | 295 | } |
285 | /* handle the end of the mapping */ | 296 | /* handle the end of the mapping */ |
286 | - if (end < host_end) { | ||
287 | - ret = mmap_frag(host_end - qemu_host_page_size, | ||
288 | - host_end - qemu_host_page_size, host_end, | 297 | + if (end < real_end) { |
298 | + ret = mmap_frag(real_end - qemu_host_page_size, | ||
299 | + real_end - qemu_host_page_size, real_end, | ||
289 | prot, flags, fd, | 300 | prot, flags, fd, |
290 | - offset + host_end - qemu_host_page_size - start); | 301 | + offset + real_end - qemu_host_page_size - start); |
291 | if (ret == -1) | 302 | if (ret == -1) |
292 | return ret; | 303 | return ret; |
293 | - host_end -= qemu_host_page_size; | 304 | + real_end -= qemu_host_page_size; |
294 | } | 305 | } |
295 | 306 | ||
296 | /* map the middle (easier) */ | 307 | /* map the middle (easier) */ |
297 | - if (host_start < host_end) { | 308 | + if (real_start < real_end) { |
298 | unsigned long offset1; | 309 | unsigned long offset1; |
299 | if (flags & MAP_ANONYMOUS) | 310 | if (flags & MAP_ANONYMOUS) |
300 | offset1 = 0; | 311 | offset1 = 0; |
301 | else | 312 | else |
302 | - offset1 = offset + host_start - start; | ||
303 | - ret = (long)mmap((void *)host_start, host_end - host_start, | 313 | + offset1 = offset + real_start - start; |
314 | + ret = (long)mmap(g2h(real_start), real_end - real_start, | ||
304 | prot, flags, fd, offset1); | 315 | prot, flags, fd, offset1); |
305 | if (ret == -1) | 316 | if (ret == -1) |
306 | return ret; | 317 | return ret; |
@@ -316,9 +327,9 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | @@ -316,9 +327,9 @@ long target_mmap(unsigned long start, unsigned long len, int prot, | ||
316 | return start; | 327 | return start; |
317 | } | 328 | } |
318 | 329 | ||
319 | -int target_munmap(unsigned long start, unsigned long len) | 330 | +int target_munmap(target_ulong start, target_ulong len) |
320 | { | 331 | { |
321 | - unsigned long end, host_start, host_end, addr; | 332 | + target_ulong end, real_start, real_end, addr; |
322 | int prot, ret; | 333 | int prot, ret; |
323 | 334 | ||
324 | #ifdef DEBUG_MMAP | 335 | #ifdef DEBUG_MMAP |
@@ -330,36 +341,36 @@ int target_munmap(unsigned long start, unsigned long len) | @@ -330,36 +341,36 @@ int target_munmap(unsigned long start, unsigned long len) | ||
330 | if (len == 0) | 341 | if (len == 0) |
331 | return -EINVAL; | 342 | return -EINVAL; |
332 | end = start + len; | 343 | end = start + len; |
333 | - host_start = start & qemu_host_page_mask; | ||
334 | - host_end = HOST_PAGE_ALIGN(end); | 344 | + real_start = start & qemu_host_page_mask; |
345 | + real_end = HOST_PAGE_ALIGN(end); | ||
335 | 346 | ||
336 | - if (start > host_start) { | 347 | + if (start > real_start) { |
337 | /* handle host page containing start */ | 348 | /* handle host page containing start */ |
338 | prot = 0; | 349 | prot = 0; |
339 | - for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { | 350 | + for(addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) { |
340 | prot |= page_get_flags(addr); | 351 | prot |= page_get_flags(addr); |
341 | } | 352 | } |
342 | - if (host_end == host_start + qemu_host_page_size) { | ||
343 | - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { | 353 | + if (real_end == real_start + qemu_host_page_size) { |
354 | + for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { | ||
344 | prot |= page_get_flags(addr); | 355 | prot |= page_get_flags(addr); |
345 | } | 356 | } |
346 | - end = host_end; | 357 | + end = real_end; |
347 | } | 358 | } |
348 | if (prot != 0) | 359 | if (prot != 0) |
349 | - host_start += qemu_host_page_size; | 360 | + real_start += qemu_host_page_size; |
350 | } | 361 | } |
351 | - if (end < host_end) { | 362 | + if (end < real_end) { |
352 | prot = 0; | 363 | prot = 0; |
353 | - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { | 364 | + for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { |
354 | prot |= page_get_flags(addr); | 365 | prot |= page_get_flags(addr); |
355 | } | 366 | } |
356 | if (prot != 0) | 367 | if (prot != 0) |
357 | - host_end -= qemu_host_page_size; | 368 | + real_end -= qemu_host_page_size; |
358 | } | 369 | } |
359 | 370 | ||
360 | /* unmap what we can */ | 371 | /* unmap what we can */ |
361 | - if (host_start < host_end) { | ||
362 | - ret = munmap((void *)host_start, host_end - host_start); | 372 | + if (real_start < real_end) { |
373 | + ret = munmap((void *)real_start, real_end - real_start); | ||
363 | if (ret != 0) | 374 | if (ret != 0) |
364 | return ret; | 375 | return ret; |
365 | } | 376 | } |
@@ -370,25 +381,26 @@ int target_munmap(unsigned long start, unsigned long len) | @@ -370,25 +381,26 @@ int target_munmap(unsigned long start, unsigned long len) | ||
370 | 381 | ||
371 | /* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED | 382 | /* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED |
372 | blocks which have been allocated starting on a host page */ | 383 | blocks which have been allocated starting on a host page */ |
373 | -long target_mremap(unsigned long old_addr, unsigned long old_size, | ||
374 | - unsigned long new_size, unsigned long flags, | ||
375 | - unsigned long new_addr) | 384 | +long target_mremap(target_ulong old_addr, target_ulong old_size, |
385 | + target_ulong new_size, unsigned long flags, | ||
386 | + target_ulong new_addr) | ||
376 | { | 387 | { |
377 | int prot; | 388 | int prot; |
378 | 389 | ||
379 | /* XXX: use 5 args syscall */ | 390 | /* XXX: use 5 args syscall */ |
380 | - new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags); | 391 | + new_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags); |
381 | if (new_addr == -1) | 392 | if (new_addr == -1) |
382 | return new_addr; | 393 | return new_addr; |
394 | + new_addr = h2g(new_addr); | ||
383 | prot = page_get_flags(old_addr); | 395 | prot = page_get_flags(old_addr); |
384 | page_set_flags(old_addr, old_addr + old_size, 0); | 396 | page_set_flags(old_addr, old_addr + old_size, 0); |
385 | page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID); | 397 | page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID); |
386 | return new_addr; | 398 | return new_addr; |
387 | } | 399 | } |
388 | 400 | ||
389 | -int target_msync(unsigned long start, unsigned long len, int flags) | 401 | +int target_msync(target_ulong start, target_ulong len, int flags) |
390 | { | 402 | { |
391 | - unsigned long end; | 403 | + target_ulong end; |
392 | 404 | ||
393 | if (start & ~TARGET_PAGE_MASK) | 405 | if (start & ~TARGET_PAGE_MASK) |
394 | return -EINVAL; | 406 | return -EINVAL; |
@@ -400,6 +412,6 @@ int target_msync(unsigned long start, unsigned long len, int flags) | @@ -400,6 +412,6 @@ int target_msync(unsigned long start, unsigned long len, int flags) | ||
400 | return 0; | 412 | return 0; |
401 | 413 | ||
402 | start &= qemu_host_page_mask; | 414 | start &= qemu_host_page_mask; |
403 | - return msync((void *)start, end - start, flags); | 415 | + return msync(g2h(start), end - start, flags); |
404 | } | 416 | } |
405 | 417 |
linux-user/qemu.h
@@ -69,7 +69,7 @@ typedef struct TaskState { | @@ -69,7 +69,7 @@ typedef struct TaskState { | ||
69 | int swi_errno; | 69 | int swi_errno; |
70 | #endif | 70 | #endif |
71 | #ifdef TARGET_I386 | 71 | #ifdef TARGET_I386 |
72 | - struct target_vm86plus_struct *target_v86; | 72 | + target_ulong target_v86; |
73 | struct vm86_saved_state vm86_saved_regs; | 73 | struct vm86_saved_state vm86_saved_regs; |
74 | struct target_vm86plus_struct vm86plus; | 74 | struct target_vm86plus_struct vm86plus; |
75 | uint32_t v86flags; | 75 | uint32_t v86flags; |
@@ -84,8 +84,8 @@ extern TaskState *first_task_state; | @@ -84,8 +84,8 @@ extern TaskState *first_task_state; | ||
84 | int elf_exec(const char * filename, char ** argv, char ** envp, | 84 | int elf_exec(const char * filename, char ** argv, char ** envp, |
85 | struct target_pt_regs * regs, struct image_info *infop); | 85 | struct target_pt_regs * regs, struct image_info *infop); |
86 | 86 | ||
87 | -void target_set_brk(char *new_brk); | ||
88 | -long do_brk(char *new_brk); | 87 | +void target_set_brk(target_ulong new_brk); |
88 | +long do_brk(target_ulong new_brk); | ||
89 | void syscall_init(void); | 89 | void syscall_init(void); |
90 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | 90 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
91 | long arg4, long arg5, long arg6); | 91 | long arg4, long arg5, long arg6); |
@@ -112,19 +112,18 @@ long do_rt_sigreturn(CPUState *env); | @@ -112,19 +112,18 @@ long do_rt_sigreturn(CPUState *env); | ||
112 | void save_v86_state(CPUX86State *env); | 112 | void save_v86_state(CPUX86State *env); |
113 | void handle_vm86_trap(CPUX86State *env, int trapno); | 113 | void handle_vm86_trap(CPUX86State *env, int trapno); |
114 | void handle_vm86_fault(CPUX86State *env); | 114 | void handle_vm86_fault(CPUX86State *env); |
115 | -int do_vm86(CPUX86State *env, long subfunction, | ||
116 | - struct target_vm86plus_struct * target_v86); | 115 | +int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr); |
117 | #endif | 116 | #endif |
118 | 117 | ||
119 | /* mmap.c */ | 118 | /* mmap.c */ |
120 | -int target_mprotect(unsigned long start, unsigned long len, int prot); | ||
121 | -long target_mmap(unsigned long start, unsigned long len, int prot, | ||
122 | - int flags, int fd, unsigned long offset); | ||
123 | -int target_munmap(unsigned long start, unsigned long len); | ||
124 | -long target_mremap(unsigned long old_addr, unsigned long old_size, | ||
125 | - unsigned long new_size, unsigned long flags, | ||
126 | - unsigned long new_addr); | ||
127 | -int target_msync(unsigned long start, unsigned long len, int flags); | 119 | +int target_mprotect(target_ulong start, target_ulong len, int prot); |
120 | +long target_mmap(target_ulong start, target_ulong len, int prot, | ||
121 | + int flags, int fd, target_ulong offset); | ||
122 | +int target_munmap(target_ulong start, target_ulong len); | ||
123 | +long target_mremap(target_ulong old_addr, target_ulong old_size, | ||
124 | + target_ulong new_size, unsigned long flags, | ||
125 | + target_ulong new_addr); | ||
126 | +int target_msync(target_ulong start, target_ulong len, int flags); | ||
128 | 127 | ||
129 | /* user access */ | 128 | /* user access */ |
130 | 129 | ||
@@ -133,21 +132,22 @@ int target_msync(unsigned long start, unsigned long len, int flags); | @@ -133,21 +132,22 @@ int target_msync(unsigned long start, unsigned long len, int flags); | ||
133 | 132 | ||
134 | #define access_ok(type,addr,size) (1) | 133 | #define access_ok(type,addr,size) (1) |
135 | 134 | ||
135 | +/* NOTE get_user and put_user use host addresses. */ | ||
136 | #define __put_user(x,ptr)\ | 136 | #define __put_user(x,ptr)\ |
137 | ({\ | 137 | ({\ |
138 | int size = sizeof(*ptr);\ | 138 | int size = sizeof(*ptr);\ |
139 | switch(size) {\ | 139 | switch(size) {\ |
140 | case 1:\ | 140 | case 1:\ |
141 | - stb(ptr, (typeof(*ptr))(x));\ | 141 | + *(uint8_t *)(ptr) = (typeof(*ptr))(x);\ |
142 | break;\ | 142 | break;\ |
143 | case 2:\ | 143 | case 2:\ |
144 | - stw(ptr, (typeof(*ptr))(x));\ | 144 | + *(uint16_t *)(ptr) = tswap16((typeof(*ptr))(x));\ |
145 | break;\ | 145 | break;\ |
146 | case 4:\ | 146 | case 4:\ |
147 | - stl(ptr, (typeof(*ptr))(x));\ | 147 | + *(uint32_t *)(ptr) = tswap32((typeof(*ptr))(x));\ |
148 | break;\ | 148 | break;\ |
149 | case 8:\ | 149 | case 8:\ |
150 | - stq(ptr, (typeof(*ptr))(x));\ | 150 | + *(uint64_t *)(ptr) = tswap64((typeof(*ptr))(x));\ |
151 | break;\ | 151 | break;\ |
152 | default:\ | 152 | default:\ |
153 | abort();\ | 153 | abort();\ |
@@ -160,16 +160,16 @@ int target_msync(unsigned long start, unsigned long len, int flags); | @@ -160,16 +160,16 @@ int target_msync(unsigned long start, unsigned long len, int flags); | ||
160 | int size = sizeof(*ptr);\ | 160 | int size = sizeof(*ptr);\ |
161 | switch(size) {\ | 161 | switch(size) {\ |
162 | case 1:\ | 162 | case 1:\ |
163 | - x = (typeof(*ptr))ldub((void *)ptr);\ | 163 | + x = (typeof(*ptr))*(uint8_t *)(ptr);\ |
164 | break;\ | 164 | break;\ |
165 | case 2:\ | 165 | case 2:\ |
166 | - x = (typeof(*ptr))lduw((void *)ptr);\ | 166 | + x = (typeof(*ptr))tswap16(*(uint16_t *)(ptr));\ |
167 | break;\ | 167 | break;\ |
168 | case 4:\ | 168 | case 4:\ |
169 | - x = (typeof(*ptr))ldl((void *)ptr);\ | 169 | + x = (typeof(*ptr))tswap32(*(uint32_t *)(ptr));\ |
170 | break;\ | 170 | break;\ |
171 | case 8:\ | 171 | case 8:\ |
172 | - x = (typeof(*ptr))ldq((void *)ptr);\ | 172 | + x = (typeof(*ptr))tswap64(*(uint64_t *)(ptr));\ |
173 | break;\ | 173 | break;\ |
174 | default:\ | 174 | default:\ |
175 | abort();\ | 175 | abort();\ |
@@ -177,26 +177,6 @@ int target_msync(unsigned long start, unsigned long len, int flags); | @@ -177,26 +177,6 @@ int target_msync(unsigned long start, unsigned long len, int flags); | ||
177 | 0;\ | 177 | 0;\ |
178 | }) | 178 | }) |
179 | 179 | ||
180 | -static inline unsigned long __copy_to_user(void *dst, const void *src, | ||
181 | - unsigned long size) | ||
182 | -{ | ||
183 | - memcpy(dst, src, size); | ||
184 | - return 0; | ||
185 | -} | ||
186 | - | ||
187 | -static inline unsigned long __copy_from_user(void *dst, const void *src, | ||
188 | - unsigned long size) | ||
189 | -{ | ||
190 | - memcpy(dst, src, size); | ||
191 | - return 0; | ||
192 | -} | ||
193 | - | ||
194 | -static inline unsigned long __clear_user(void *dst, unsigned long size) | ||
195 | -{ | ||
196 | - memset(dst, 0, size); | ||
197 | - return 0; | ||
198 | -} | ||
199 | - | ||
200 | #define put_user(x,ptr)\ | 180 | #define put_user(x,ptr)\ |
201 | ({\ | 181 | ({\ |
202 | int __ret;\ | 182 | int __ret;\ |
@@ -217,30 +197,77 @@ static inline unsigned long __clear_user(void *dst, unsigned long size) | @@ -217,30 +197,77 @@ static inline unsigned long __clear_user(void *dst, unsigned long size) | ||
217 | __ret;\ | 197 | __ret;\ |
218 | }) | 198 | }) |
219 | 199 | ||
220 | -static inline unsigned long copy_to_user(void *dst, const void *src, | ||
221 | - unsigned long size) | 200 | +/* Functions for accessing guest memory. The tget and tput functions |
201 | + read/write single values, byteswapping as neccessary. The lock_user | ||
202 | + gets a pointer to a contiguous area of guest memory, but does not perform | ||
203 | + and byteswapping. lock_user may return either a pointer to the guest | ||
204 | + memory, or a temporary buffer. */ | ||
205 | + | ||
206 | +/* Lock an area of guest memory into the host. If copy is true then the | ||
207 | + host area will have the same contents as the guest. */ | ||
208 | +static inline void *lock_user(target_ulong guest_addr, long len, int copy) | ||
222 | { | 209 | { |
223 | - if (access_ok(VERIFY_WRITE, dst, size)) | ||
224 | - return __copy_to_user(dst, src, size); | 210 | +#ifdef DEBUG_REMAP |
211 | + void *addr; | ||
212 | + addr = malloc(len); | ||
213 | + if (copy) | ||
214 | + memcpy(addr, g2h(guest_addr), len); | ||
225 | else | 215 | else |
226 | - return size; | 216 | + memset(addr, 0, len); |
217 | + return addr; | ||
218 | +#else | ||
219 | + return g2h(guest_addr); | ||
220 | +#endif | ||
227 | } | 221 | } |
228 | 222 | ||
229 | -static inline unsigned long copy_from_user(void *dst, const void *src, | ||
230 | - unsigned long size) | 223 | +/* Unlock an area of guest memory. The first LEN bytes must be flushed back |
224 | + to guest memory. */ | ||
225 | +static inline void unlock_user(void *host_addr, target_ulong guest_addr, | ||
226 | + long len) | ||
231 | { | 227 | { |
232 | - if (access_ok(VERIFY_READ, src, size)) | ||
233 | - return __copy_from_user(dst, src, size); | ||
234 | - else | ||
235 | - return size; | 228 | +#ifdef DEBUG_REMAP |
229 | + if (host_addr == g2h(guest_addr)) | ||
230 | + return; | ||
231 | + if (len > 0) | ||
232 | + memcpy(g2h(guest_addr), host_addr, len); | ||
233 | + free(host_addr); | ||
234 | +#endif | ||
236 | } | 235 | } |
237 | 236 | ||
238 | -static inline unsigned long clear_user(void *dst, unsigned long size) | 237 | +/* Return the length of a string in target memory. */ |
238 | +static inline int target_strlen(target_ulong ptr) | ||
239 | { | 239 | { |
240 | - if (access_ok(VERIFY_WRITE, dst, size)) | ||
241 | - return __clear_user(dst, size); | ||
242 | - else | ||
243 | - return size; | 240 | + return strlen(g2h(ptr)); |
241 | +} | ||
242 | + | ||
243 | +/* Like lock_user but for null terminated strings. */ | ||
244 | +static inline void *lock_user_string(target_ulong guest_addr) | ||
245 | +{ | ||
246 | + long len; | ||
247 | + len = target_strlen(guest_addr) + 1; | ||
248 | + return lock_user(guest_addr, len, 1); | ||
244 | } | 249 | } |
245 | 250 | ||
251 | +/* Helper macros for locking/ulocking a target struct. */ | ||
252 | +#define lock_user_struct(host_ptr, guest_addr, copy) \ | ||
253 | + host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy) | ||
254 | +#define unlock_user_struct(host_ptr, guest_addr, copy) \ | ||
255 | + unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) | ||
256 | + | ||
257 | +#define tget8(addr) ldub(addr) | ||
258 | +#define tput8(addr, val) stb(addr, val) | ||
259 | +#define tget16(addr) lduw(addr) | ||
260 | +#define tput16(addr, val) stw(addr, val) | ||
261 | +#define tget32(addr) ldl(addr) | ||
262 | +#define tput32(addr, val) stl(addr, val) | ||
263 | +#define tget64(addr) ldq(addr) | ||
264 | +#define tput64(addr, val) stq(addr, val) | ||
265 | +#if TARGET_LONG_BITS == 64 | ||
266 | +#define tgetl(addr) ldq(addr) | ||
267 | +#define tputl(addr, val) stq(addr, val) | ||
268 | +#else | ||
269 | +#define tgetl(addr) ldl(addr) | ||
270 | +#define tputl(addr, val) stl(addr, val) | ||
271 | +#endif | ||
272 | + | ||
246 | #endif /* QEMU_H */ | 273 | #endif /* QEMU_H */ |
linux-user/signal.c
@@ -135,7 +135,7 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) | @@ -135,7 +135,7 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) | ||
135 | 135 | ||
136 | host_to_target_sigset_internal(&d1, s); | 136 | host_to_target_sigset_internal(&d1, s); |
137 | for(i = 0;i < TARGET_NSIG_WORDS; i++) | 137 | for(i = 0;i < TARGET_NSIG_WORDS; i++) |
138 | - __put_user(d1.sig[i], &d->sig[i]); | 138 | + d->sig[i] = tswapl(d1.sig[i]); |
139 | } | 139 | } |
140 | 140 | ||
141 | void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) | 141 | void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) |
@@ -168,7 +168,7 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) | @@ -168,7 +168,7 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) | ||
168 | int i; | 168 | int i; |
169 | 169 | ||
170 | for(i = 0;i < TARGET_NSIG_WORDS; i++) | 170 | for(i = 0;i < TARGET_NSIG_WORDS; i++) |
171 | - __get_user(s1.sig[i], &s->sig[i]); | 171 | + s1.sig[i] = tswapl(s->sig[i]); |
172 | target_to_host_sigset_internal(d, &s1); | 172 | target_to_host_sigset_internal(d, &s1); |
173 | } | 173 | } |
174 | 174 | ||
@@ -647,7 +647,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) | @@ -647,7 +647,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) | ||
647 | ka->sa.sa_restorer) { | 647 | ka->sa.sa_restorer) { |
648 | esp = (unsigned long) ka->sa.sa_restorer; | 648 | esp = (unsigned long) ka->sa.sa_restorer; |
649 | } | 649 | } |
650 | - return (void *)((esp - frame_size) & -8ul); | 650 | + return g2h((esp - frame_size) & -8ul); |
651 | } | 651 | } |
652 | 652 | ||
653 | static void setup_frame(int sig, struct emulated_sigaction *ka, | 653 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
@@ -694,7 +694,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -694,7 +694,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
694 | goto give_sigsegv; | 694 | goto give_sigsegv; |
695 | 695 | ||
696 | /* Set up registers for signal handler */ | 696 | /* Set up registers for signal handler */ |
697 | - env->regs[R_ESP] = (unsigned long) frame; | 697 | + env->regs[R_ESP] = h2g(frame); |
698 | env->eip = (unsigned long) ka->sa._sa_handler; | 698 | env->eip = (unsigned long) ka->sa._sa_handler; |
699 | 699 | ||
700 | cpu_x86_load_seg(env, R_DS, __USER_DS); | 700 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
@@ -835,7 +835,7 @@ badframe: | @@ -835,7 +835,7 @@ badframe: | ||
835 | 835 | ||
836 | long do_sigreturn(CPUX86State *env) | 836 | long do_sigreturn(CPUX86State *env) |
837 | { | 837 | { |
838 | - struct sigframe *frame = (struct sigframe *)(env->regs[R_ESP] - 8); | 838 | + struct sigframe *frame = (struct sigframe *)g2h(env->regs[R_ESP] - 8); |
839 | target_sigset_t target_set; | 839 | target_sigset_t target_set; |
840 | sigset_t set; | 840 | sigset_t set; |
841 | int eax, i; | 841 | int eax, i; |
@@ -866,7 +866,7 @@ badframe: | @@ -866,7 +866,7 @@ badframe: | ||
866 | 866 | ||
867 | long do_rt_sigreturn(CPUX86State *env) | 867 | long do_rt_sigreturn(CPUX86State *env) |
868 | { | 868 | { |
869 | - struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); | 869 | + struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env->regs[R_ESP] - 4); |
870 | sigset_t set; | 870 | sigset_t set; |
871 | // stack_t st; | 871 | // stack_t st; |
872 | int eax; | 872 | int eax; |
@@ -1029,7 +1029,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) | @@ -1029,7 +1029,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) | ||
1029 | /* | 1029 | /* |
1030 | * ATPCS B01 mandates 8-byte alignment | 1030 | * ATPCS B01 mandates 8-byte alignment |
1031 | */ | 1031 | */ |
1032 | - return (void *)((sp - framesize) & ~7); | 1032 | + return g2h((sp - framesize) & ~7); |
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | static int | 1035 | static int |
@@ -1084,7 +1084,7 @@ setup_return(CPUState *env, struct emulated_sigaction *ka, | @@ -1084,7 +1084,7 @@ setup_return(CPUState *env, struct emulated_sigaction *ka, | ||
1084 | } | 1084 | } |
1085 | 1085 | ||
1086 | env->regs[0] = usig; | 1086 | env->regs[0] = usig; |
1087 | - env->regs[13] = (target_ulong)frame; | 1087 | + env->regs[13] = h2g(frame); |
1088 | env->regs[14] = retcode; | 1088 | env->regs[14] = retcode; |
1089 | env->regs[15] = handler & (thumb ? ~1 : ~3); | 1089 | env->regs[15] = handler & (thumb ? ~1 : ~3); |
1090 | 1090 | ||
@@ -1130,7 +1130,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | @@ -1130,7 +1130,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, | ||
1130 | err |= copy_siginfo_to_user(&frame->info, info); | 1130 | err |= copy_siginfo_to_user(&frame->info, info); |
1131 | 1131 | ||
1132 | /* Clear all the bits of the ucontext we don't use. */ | 1132 | /* Clear all the bits of the ucontext we don't use. */ |
1133 | - err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); | 1133 | + memset(&frame->uc, 0, offsetof(struct target_ucontext, tuc_mcontext)); |
1134 | 1134 | ||
1135 | err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/ | 1135 | err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/ |
1136 | env, set->sig[0]); | 1136 | env, set->sig[0]); |
@@ -1202,7 +1202,7 @@ long do_sigreturn(CPUState *env) | @@ -1202,7 +1202,7 @@ long do_sigreturn(CPUState *env) | ||
1202 | if (env->regs[13] & 7) | 1202 | if (env->regs[13] & 7) |
1203 | goto badframe; | 1203 | goto badframe; |
1204 | 1204 | ||
1205 | - frame = (struct sigframe *)env->regs[13]; | 1205 | + frame = (struct sigframe *)g2h(env->regs[13]); |
1206 | 1206 | ||
1207 | #if 0 | 1207 | #if 0 |
1208 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) | 1208 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) |
@@ -1378,7 +1378,7 @@ static inline void *get_sigframe(struct emulated_sigaction *sa, CPUState *env, u | @@ -1378,7 +1378,7 @@ static inline void *get_sigframe(struct emulated_sigaction *sa, CPUState *env, u | ||
1378 | sp = current->sas_ss_sp + current->sas_ss_size; | 1378 | sp = current->sas_ss_sp + current->sas_ss_size; |
1379 | } | 1379 | } |
1380 | #endif | 1380 | #endif |
1381 | - return (void *)(sp - framesize); | 1381 | + return g2h(sp - framesize); |
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | static int | 1384 | static int |
@@ -1461,10 +1461,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -1461,10 +1461,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
1461 | goto sigsegv; | 1461 | goto sigsegv; |
1462 | 1462 | ||
1463 | /* 3. signal handler back-trampoline and parameters */ | 1463 | /* 3. signal handler back-trampoline and parameters */ |
1464 | - env->regwptr[UREG_FP] = (target_ulong) sf; | 1464 | + env->regwptr[UREG_FP] = h2g(sf); |
1465 | env->regwptr[UREG_I0] = sig; | 1465 | env->regwptr[UREG_I0] = sig; |
1466 | - env->regwptr[UREG_I1] = (target_ulong) &sf->info; | ||
1467 | - env->regwptr[UREG_I2] = (target_ulong) &sf->info; | 1466 | + env->regwptr[UREG_I1] = h2g(&sf->info); |
1467 | + env->regwptr[UREG_I2] = h2g(&sf->info); | ||
1468 | 1468 | ||
1469 | /* 4. signal handler */ | 1469 | /* 4. signal handler */ |
1470 | env->pc = (unsigned long) ka->sa._sa_handler; | 1470 | env->pc = (unsigned long) ka->sa._sa_handler; |
@@ -1473,7 +1473,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | @@ -1473,7 +1473,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, | ||
1473 | if (ka->sa.sa_restorer) | 1473 | if (ka->sa.sa_restorer) |
1474 | env->regwptr[UREG_I7] = (unsigned long)ka->sa.sa_restorer; | 1474 | env->regwptr[UREG_I7] = (unsigned long)ka->sa.sa_restorer; |
1475 | else { | 1475 | else { |
1476 | - env->regwptr[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); | 1476 | + env->regwptr[UREG_I7] = h2g(&(sf->insns[0]) - 2); |
1477 | 1477 | ||
1478 | /* mov __NR_sigreturn, %g1 */ | 1478 | /* mov __NR_sigreturn, %g1 */ |
1479 | err |= __put_user(0x821020d8, &sf->insns[0]); | 1479 | err |= __put_user(0x821020d8, &sf->insns[0]); |
@@ -1548,7 +1548,7 @@ long do_sigreturn(CPUState *env) | @@ -1548,7 +1548,7 @@ long do_sigreturn(CPUState *env) | ||
1548 | target_ulong fpu_save; | 1548 | target_ulong fpu_save; |
1549 | int err, i; | 1549 | int err, i; |
1550 | 1550 | ||
1551 | - sf = (struct target_signal_frame *) env->regwptr[UREG_FP]; | 1551 | + sf = (struct target_signal_frame *)g2h(env->regwptr[UREG_FP]); |
1552 | #if 0 | 1552 | #if 0 |
1553 | fprintf(stderr, "sigreturn\n"); | 1553 | fprintf(stderr, "sigreturn\n"); |
1554 | fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); | 1554 | fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); |
linux-user/syscall.c
@@ -252,44 +252,43 @@ static inline int is_error(long ret) | @@ -252,44 +252,43 @@ static inline int is_error(long ret) | ||
252 | return (unsigned long)ret >= (unsigned long)(-4096); | 252 | return (unsigned long)ret >= (unsigned long)(-4096); |
253 | } | 253 | } |
254 | 254 | ||
255 | -static char *target_brk; | ||
256 | -static char *target_original_brk; | 255 | +static target_ulong target_brk; |
256 | +static target_ulong target_original_brk; | ||
257 | 257 | ||
258 | -void target_set_brk(char *new_brk) | 258 | +void target_set_brk(target_ulong new_brk) |
259 | { | 259 | { |
260 | - target_brk = new_brk; | ||
261 | - target_original_brk = new_brk; | 260 | + target_original_brk = target_brk = new_brk; |
262 | } | 261 | } |
263 | 262 | ||
264 | -long do_brk(char *new_brk) | 263 | +long do_brk(target_ulong new_brk) |
265 | { | 264 | { |
266 | - char *brk_page; | 265 | + target_ulong brk_page; |
267 | long mapped_addr; | 266 | long mapped_addr; |
268 | int new_alloc_size; | 267 | int new_alloc_size; |
269 | 268 | ||
270 | if (!new_brk) | 269 | if (!new_brk) |
271 | - return (long)target_brk; | 270 | + return target_brk; |
272 | if (new_brk < target_original_brk) | 271 | if (new_brk < target_original_brk) |
273 | return -ENOMEM; | 272 | return -ENOMEM; |
274 | 273 | ||
275 | - brk_page = (char *)HOST_PAGE_ALIGN((unsigned long)target_brk); | 274 | + brk_page = HOST_PAGE_ALIGN(target_brk); |
276 | 275 | ||
277 | /* If the new brk is less than this, set it and we're done... */ | 276 | /* If the new brk is less than this, set it and we're done... */ |
278 | if (new_brk < brk_page) { | 277 | if (new_brk < brk_page) { |
279 | target_brk = new_brk; | 278 | target_brk = new_brk; |
280 | - return (long)target_brk; | 279 | + return target_brk; |
281 | } | 280 | } |
282 | 281 | ||
283 | /* We need to allocate more memory after the brk... */ | 282 | /* We need to allocate more memory after the brk... */ |
284 | new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); | 283 | new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); |
285 | - mapped_addr = get_errno(target_mmap((unsigned long)brk_page, new_alloc_size, | 284 | + mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, |
286 | PROT_READ|PROT_WRITE, | 285 | PROT_READ|PROT_WRITE, |
287 | MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); | 286 | MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); |
288 | if (is_error(mapped_addr)) { | 287 | if (is_error(mapped_addr)) { |
289 | return mapped_addr; | 288 | return mapped_addr; |
290 | } else { | 289 | } else { |
291 | target_brk = new_brk; | 290 | target_brk = new_brk; |
292 | - return (long)target_brk; | 291 | + return target_brk; |
293 | } | 292 | } |
294 | } | 293 | } |
295 | 294 | ||
@@ -354,9 +353,12 @@ static inline long host_to_target_clock_t(long ticks) | @@ -354,9 +353,12 @@ static inline long host_to_target_clock_t(long ticks) | ||
354 | #endif | 353 | #endif |
355 | } | 354 | } |
356 | 355 | ||
357 | -static inline void host_to_target_rusage(struct target_rusage *target_rusage, | 356 | +static inline void host_to_target_rusage(target_ulong target_addr, |
358 | const struct rusage *rusage) | 357 | const struct rusage *rusage) |
359 | { | 358 | { |
359 | + struct target_rusage *target_rusage; | ||
360 | + | ||
361 | + lock_user_struct(target_rusage, target_addr, 0); | ||
360 | target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); | 362 | target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); |
361 | target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); | 363 | target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); |
362 | target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); | 364 | target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); |
@@ -375,35 +377,64 @@ static inline void host_to_target_rusage(struct target_rusage *target_rusage, | @@ -375,35 +377,64 @@ static inline void host_to_target_rusage(struct target_rusage *target_rusage, | ||
375 | target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); | 377 | target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); |
376 | target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); | 378 | target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); |
377 | target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); | 379 | target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); |
380 | + unlock_user_struct(target_rusage, target_addr, 1); | ||
378 | } | 381 | } |
379 | 382 | ||
380 | -static inline void target_to_host_timeval(struct timeval *tv, | ||
381 | - const struct target_timeval *target_tv) | 383 | +static inline void target_to_host_timeval(struct timeval *tv, |
384 | + target_ulong target_addr) | ||
382 | { | 385 | { |
386 | + struct target_timeval *target_tv; | ||
387 | + | ||
388 | + lock_user_struct(target_tv, target_addr, 1); | ||
383 | tv->tv_sec = tswapl(target_tv->tv_sec); | 389 | tv->tv_sec = tswapl(target_tv->tv_sec); |
384 | tv->tv_usec = tswapl(target_tv->tv_usec); | 390 | tv->tv_usec = tswapl(target_tv->tv_usec); |
391 | + unlock_user_struct(target_tv, target_addr, 0); | ||
385 | } | 392 | } |
386 | 393 | ||
387 | -static inline void host_to_target_timeval(struct target_timeval *target_tv, | 394 | +static inline void host_to_target_timeval(target_ulong target_addr, |
388 | const struct timeval *tv) | 395 | const struct timeval *tv) |
389 | { | 396 | { |
397 | + struct target_timeval *target_tv; | ||
398 | + | ||
399 | + lock_user_struct(target_tv, target_addr, 0); | ||
390 | target_tv->tv_sec = tswapl(tv->tv_sec); | 400 | target_tv->tv_sec = tswapl(tv->tv_sec); |
391 | target_tv->tv_usec = tswapl(tv->tv_usec); | 401 | target_tv->tv_usec = tswapl(tv->tv_usec); |
402 | + unlock_user_struct(target_tv, target_addr, 1); | ||
392 | } | 403 | } |
393 | 404 | ||
394 | 405 | ||
395 | static long do_select(long n, | 406 | static long do_select(long n, |
396 | - target_long *target_rfds, target_long *target_wfds, | ||
397 | - target_long *target_efds, struct target_timeval *target_tv) | 407 | + target_ulong rfd_p, target_ulong wfd_p, |
408 | + target_ulong efd_p, target_ulong target_tv) | ||
398 | { | 409 | { |
399 | fd_set rfds, wfds, efds; | 410 | fd_set rfds, wfds, efds; |
400 | fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; | 411 | fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; |
412 | + target_long *target_rfds, *target_wfds, *target_efds; | ||
401 | struct timeval tv, *tv_ptr; | 413 | struct timeval tv, *tv_ptr; |
402 | long ret; | 414 | long ret; |
415 | + int ok; | ||
403 | 416 | ||
404 | - rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); | ||
405 | - wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); | ||
406 | - efds_ptr = target_to_host_fds(&efds, target_efds, n); | 417 | + if (rfd_p) { |
418 | + target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1); | ||
419 | + rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); | ||
420 | + } else { | ||
421 | + target_rfds = NULL; | ||
422 | + rfds_ptr = NULL; | ||
423 | + } | ||
424 | + if (wfd_p) { | ||
425 | + target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1); | ||
426 | + wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); | ||
427 | + } else { | ||
428 | + target_wfds = NULL; | ||
429 | + wfds_ptr = NULL; | ||
430 | + } | ||
431 | + if (efd_p) { | ||
432 | + target_efds = lock_user(efd_p, sizeof(target_long) * n, 1); | ||
433 | + efds_ptr = target_to_host_fds(&efds, target_efds, n); | ||
434 | + } else { | ||
435 | + target_efds = NULL; | ||
436 | + efds_ptr = NULL; | ||
437 | + } | ||
407 | 438 | ||
408 | if (target_tv) { | 439 | if (target_tv) { |
409 | target_to_host_timeval(&tv, target_tv); | 440 | target_to_host_timeval(&tv, target_tv); |
@@ -412,7 +443,9 @@ static long do_select(long n, | @@ -412,7 +443,9 @@ static long do_select(long n, | ||
412 | tv_ptr = NULL; | 443 | tv_ptr = NULL; |
413 | } | 444 | } |
414 | ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); | 445 | ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); |
415 | - if (!is_error(ret)) { | 446 | + ok = !is_error(ret); |
447 | + | ||
448 | + if (ok) { | ||
416 | host_to_target_fds(target_rfds, rfds_ptr, n); | 449 | host_to_target_fds(target_rfds, rfds_ptr, n); |
417 | host_to_target_fds(target_wfds, wfds_ptr, n); | 450 | host_to_target_fds(target_wfds, wfds_ptr, n); |
418 | host_to_target_fds(target_efds, efds_ptr, n); | 451 | host_to_target_fds(target_efds, efds_ptr, n); |
@@ -421,25 +454,41 @@ static long do_select(long n, | @@ -421,25 +454,41 @@ static long do_select(long n, | ||
421 | host_to_target_timeval(target_tv, &tv); | 454 | host_to_target_timeval(target_tv, &tv); |
422 | } | 455 | } |
423 | } | 456 | } |
457 | + if (target_rfds) | ||
458 | + unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0); | ||
459 | + if (target_wfds) | ||
460 | + unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0); | ||
461 | + if (target_efds) | ||
462 | + unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0); | ||
463 | + | ||
424 | return ret; | 464 | return ret; |
425 | } | 465 | } |
426 | 466 | ||
427 | static inline void target_to_host_sockaddr(struct sockaddr *addr, | 467 | static inline void target_to_host_sockaddr(struct sockaddr *addr, |
428 | - struct target_sockaddr *target_addr, | 468 | + target_ulong target_addr, |
429 | socklen_t len) | 469 | socklen_t len) |
430 | { | 470 | { |
431 | - memcpy(addr, target_addr, len); | ||
432 | - addr->sa_family = tswap16(target_addr->sa_family); | 471 | + struct target_sockaddr *target_saddr; |
472 | + | ||
473 | + target_saddr = lock_user(target_addr, len, 1); | ||
474 | + memcpy(addr, target_saddr, len); | ||
475 | + addr->sa_family = tswap16(target_saddr->sa_family); | ||
476 | + unlock_user(target_saddr, target_addr, 0); | ||
433 | } | 477 | } |
434 | 478 | ||
435 | -static inline void host_to_target_sockaddr(struct target_sockaddr *target_addr, | 479 | +static inline void host_to_target_sockaddr(target_ulong target_addr, |
436 | struct sockaddr *addr, | 480 | struct sockaddr *addr, |
437 | socklen_t len) | 481 | socklen_t len) |
438 | { | 482 | { |
439 | - memcpy(target_addr, addr, len); | ||
440 | - target_addr->sa_family = tswap16(addr->sa_family); | 483 | + struct target_sockaddr *target_saddr; |
484 | + | ||
485 | + target_saddr = lock_user(target_addr, len, 0); | ||
486 | + memcpy(target_saddr, addr, len); | ||
487 | + target_saddr->sa_family = tswap16(addr->sa_family); | ||
488 | + unlock_user(target_saddr, target_addr, len); | ||
441 | } | 489 | } |
442 | 490 | ||
491 | +/* ??? Should this also swap msgh->name? */ | ||
443 | static inline void target_to_host_cmsg(struct msghdr *msgh, | 492 | static inline void target_to_host_cmsg(struct msghdr *msgh, |
444 | struct target_msghdr *target_msgh) | 493 | struct target_msghdr *target_msgh) |
445 | { | 494 | { |
@@ -484,6 +533,7 @@ static inline void target_to_host_cmsg(struct msghdr *msgh, | @@ -484,6 +533,7 @@ static inline void target_to_host_cmsg(struct msghdr *msgh, | ||
484 | msgh->msg_controllen = space; | 533 | msgh->msg_controllen = space; |
485 | } | 534 | } |
486 | 535 | ||
536 | +/* ??? Should this also swap msgh->name? */ | ||
487 | static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, | 537 | static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, |
488 | struct msghdr *msgh) | 538 | struct msghdr *msgh) |
489 | { | 539 | { |
@@ -528,7 +578,7 @@ static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, | @@ -528,7 +578,7 @@ static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, | ||
528 | } | 578 | } |
529 | 579 | ||
530 | static long do_setsockopt(int sockfd, int level, int optname, | 580 | static long do_setsockopt(int sockfd, int level, int optname, |
531 | - void *optval, socklen_t optlen) | 581 | + target_ulong optval, socklen_t optlen) |
532 | { | 582 | { |
533 | int val, ret; | 583 | int val, ret; |
534 | 584 | ||
@@ -538,8 +588,7 @@ static long do_setsockopt(int sockfd, int level, int optname, | @@ -538,8 +588,7 @@ static long do_setsockopt(int sockfd, int level, int optname, | ||
538 | if (optlen < sizeof(uint32_t)) | 588 | if (optlen < sizeof(uint32_t)) |
539 | return -EINVAL; | 589 | return -EINVAL; |
540 | 590 | ||
541 | - if (get_user(val, (uint32_t *)optval)) | ||
542 | - return -EFAULT; | 591 | + val = tget32(optval); |
543 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); | 592 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
544 | break; | 593 | break; |
545 | case SOL_IP: | 594 | case SOL_IP: |
@@ -561,11 +610,9 @@ static long do_setsockopt(int sockfd, int level, int optname, | @@ -561,11 +610,9 @@ static long do_setsockopt(int sockfd, int level, int optname, | ||
561 | case IP_MULTICAST_LOOP: | 610 | case IP_MULTICAST_LOOP: |
562 | val = 0; | 611 | val = 0; |
563 | if (optlen >= sizeof(uint32_t)) { | 612 | if (optlen >= sizeof(uint32_t)) { |
564 | - if (get_user(val, (uint32_t *)optval)) | ||
565 | - return -EFAULT; | 613 | + val = tget32(optval); |
566 | } else if (optlen >= 1) { | 614 | } else if (optlen >= 1) { |
567 | - if (get_user(val, (uint8_t *)optval)) | ||
568 | - return -EFAULT; | 615 | + val = tget8(optval); |
569 | } | 616 | } |
570 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); | 617 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
571 | break; | 618 | break; |
@@ -598,8 +645,8 @@ static long do_setsockopt(int sockfd, int level, int optname, | @@ -598,8 +645,8 @@ static long do_setsockopt(int sockfd, int level, int optname, | ||
598 | case SO_SNDTIMEO: | 645 | case SO_SNDTIMEO: |
599 | if (optlen < sizeof(uint32_t)) | 646 | if (optlen < sizeof(uint32_t)) |
600 | return -EINVAL; | 647 | return -EINVAL; |
601 | - if (get_user(val, (uint32_t *)optval)) | ||
602 | - return -EFAULT; | 648 | + |
649 | + val = tget32(optval); | ||
603 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); | 650 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
604 | break; | 651 | break; |
605 | default: | 652 | default: |
@@ -615,7 +662,7 @@ static long do_setsockopt(int sockfd, int level, int optname, | @@ -615,7 +662,7 @@ static long do_setsockopt(int sockfd, int level, int optname, | ||
615 | } | 662 | } |
616 | 663 | ||
617 | static long do_getsockopt(int sockfd, int level, int optname, | 664 | static long do_getsockopt(int sockfd, int level, int optname, |
618 | - void *optval, socklen_t *optlen) | 665 | + target_ulong optval, target_ulong optlen) |
619 | { | 666 | { |
620 | int len, lv, val, ret; | 667 | int len, lv, val, ret; |
621 | 668 | ||
@@ -636,8 +683,7 @@ static long do_getsockopt(int sockfd, int level, int optname, | @@ -636,8 +683,7 @@ static long do_getsockopt(int sockfd, int level, int optname, | ||
636 | case SOL_TCP: | 683 | case SOL_TCP: |
637 | /* TCP options all take an 'int' value. */ | 684 | /* TCP options all take an 'int' value. */ |
638 | int_case: | 685 | int_case: |
639 | - if (get_user(len, optlen)) | ||
640 | - return -EFAULT; | 686 | + len = tget32(optlen); |
641 | if (len < 0) | 687 | if (len < 0) |
642 | return -EINVAL; | 688 | return -EINVAL; |
643 | lv = sizeof(int); | 689 | lv = sizeof(int); |
@@ -647,10 +693,11 @@ static long do_getsockopt(int sockfd, int level, int optname, | @@ -647,10 +693,11 @@ static long do_getsockopt(int sockfd, int level, int optname, | ||
647 | val = tswap32(val); | 693 | val = tswap32(val); |
648 | if (len > lv) | 694 | if (len > lv) |
649 | len = lv; | 695 | len = lv; |
650 | - if (copy_to_user(optval, &val, len)) | ||
651 | - return -EFAULT; | ||
652 | - if (put_user(len, optlen)) | ||
653 | - return -EFAULT; | 696 | + if (len == 4) |
697 | + tput32(optval, val); | ||
698 | + else | ||
699 | + tput8(optval, val); | ||
700 | + tput32(optlen, len); | ||
654 | break; | 701 | break; |
655 | case SOL_IP: | 702 | case SOL_IP: |
656 | switch(optname) { | 703 | switch(optname) { |
@@ -669,8 +716,7 @@ static long do_getsockopt(int sockfd, int level, int optname, | @@ -669,8 +716,7 @@ static long do_getsockopt(int sockfd, int level, int optname, | ||
669 | #endif | 716 | #endif |
670 | case IP_MULTICAST_TTL: | 717 | case IP_MULTICAST_TTL: |
671 | case IP_MULTICAST_LOOP: | 718 | case IP_MULTICAST_LOOP: |
672 | - if (get_user(len, optlen)) | ||
673 | - return -EFAULT; | 719 | + len = tget32(optlen); |
674 | if (len < 0) | 720 | if (len < 0) |
675 | return -EINVAL; | 721 | return -EINVAL; |
676 | lv = sizeof(int); | 722 | lv = sizeof(int); |
@@ -678,20 +724,14 @@ static long do_getsockopt(int sockfd, int level, int optname, | @@ -678,20 +724,14 @@ static long do_getsockopt(int sockfd, int level, int optname, | ||
678 | if (ret < 0) | 724 | if (ret < 0) |
679 | return ret; | 725 | return ret; |
680 | if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) { | 726 | if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) { |
681 | - unsigned char ucval = val; | ||
682 | len = 1; | 727 | len = 1; |
683 | - if (put_user(len, optlen)) | ||
684 | - return -EFAULT; | ||
685 | - if (copy_to_user(optval,&ucval,1)) | ||
686 | - return -EFAULT; | 728 | + tput32(optlen, len); |
729 | + tput8(optval, val); | ||
687 | } else { | 730 | } else { |
688 | - val = tswap32(val); | ||
689 | if (len > sizeof(int)) | 731 | if (len > sizeof(int)) |
690 | len = sizeof(int); | 732 | len = sizeof(int); |
691 | - if (put_user(len, optlen)) | ||
692 | - return -EFAULT; | ||
693 | - if (copy_to_user(optval, &val, len)) | ||
694 | - return -EFAULT; | 733 | + tput32(optlen, len); |
734 | + tput32(optval, val); | ||
695 | } | 735 | } |
696 | break; | 736 | break; |
697 | default: | 737 | default: |
@@ -708,25 +748,57 @@ static long do_getsockopt(int sockfd, int level, int optname, | @@ -708,25 +748,57 @@ static long do_getsockopt(int sockfd, int level, int optname, | ||
708 | return ret; | 748 | return ret; |
709 | } | 749 | } |
710 | 750 | ||
711 | -static long do_socketcall(int num, int32_t *vptr) | 751 | +static void lock_iovec(struct iovec *vec, target_ulong target_addr, |
752 | + int count, int copy) | ||
753 | +{ | ||
754 | + struct target_iovec *target_vec; | ||
755 | + target_ulong base; | ||
756 | + int i; | ||
757 | + | ||
758 | + target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); | ||
759 | + for(i = 0;i < count; i++) { | ||
760 | + base = tswapl(target_vec[i].iov_base); | ||
761 | + vec[i].iov_len = tswapl(target_vec[i].iov_len); | ||
762 | + vec[i].iov_base = lock_user(base, vec[i].iov_len, copy); | ||
763 | + } | ||
764 | + unlock_user (target_vec, target_addr, 0); | ||
765 | +} | ||
766 | + | ||
767 | +static void unlock_iovec(struct iovec *vec, target_ulong target_addr, | ||
768 | + int count, int copy) | ||
769 | +{ | ||
770 | + struct target_iovec *target_vec; | ||
771 | + target_ulong base; | ||
772 | + int i; | ||
773 | + | ||
774 | + target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); | ||
775 | + for(i = 0;i < count; i++) { | ||
776 | + base = tswapl(target_vec[i].iov_base); | ||
777 | + unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); | ||
778 | + } | ||
779 | + unlock_user (target_vec, target_addr, 0); | ||
780 | +} | ||
781 | + | ||
782 | +static long do_socketcall(int num, target_ulong vptr) | ||
712 | { | 783 | { |
713 | long ret; | 784 | long ret; |
785 | + const int n = sizeof(target_ulong); | ||
714 | 786 | ||
715 | switch(num) { | 787 | switch(num) { |
716 | case SOCKOP_socket: | 788 | case SOCKOP_socket: |
717 | { | 789 | { |
718 | - int domain = tswap32(vptr[0]); | ||
719 | - int type = tswap32(vptr[1]); | ||
720 | - int protocol = tswap32(vptr[2]); | 790 | + int domain = tgetl(vptr); |
791 | + int type = tgetl(vptr + n); | ||
792 | + int protocol = tgetl(vptr + 2 * n); | ||
721 | 793 | ||
722 | ret = get_errno(socket(domain, type, protocol)); | 794 | ret = get_errno(socket(domain, type, protocol)); |
723 | } | 795 | } |
724 | break; | 796 | break; |
725 | case SOCKOP_bind: | 797 | case SOCKOP_bind: |
726 | { | 798 | { |
727 | - int sockfd = tswap32(vptr[0]); | ||
728 | - void *target_addr = (void *)tswap32(vptr[1]); | ||
729 | - socklen_t addrlen = tswap32(vptr[2]); | 799 | + int sockfd = tgetl(vptr); |
800 | + target_ulong target_addr = tgetl(vptr + n); | ||
801 | + socklen_t addrlen = tgetl(vptr + 2 * n); | ||
730 | void *addr = alloca(addrlen); | 802 | void *addr = alloca(addrlen); |
731 | 803 | ||
732 | target_to_host_sockaddr(addr, target_addr, addrlen); | 804 | target_to_host_sockaddr(addr, target_addr, addrlen); |
@@ -735,9 +807,9 @@ static long do_socketcall(int num, int32_t *vptr) | @@ -735,9 +807,9 @@ static long do_socketcall(int num, int32_t *vptr) | ||
735 | break; | 807 | break; |
736 | case SOCKOP_connect: | 808 | case SOCKOP_connect: |
737 | { | 809 | { |
738 | - int sockfd = tswap32(vptr[0]); | ||
739 | - void *target_addr = (void *)tswap32(vptr[1]); | ||
740 | - socklen_t addrlen = tswap32(vptr[2]); | 810 | + int sockfd = tgetl(vptr); |
811 | + target_ulong target_addr = tgetl(vptr + n); | ||
812 | + socklen_t addrlen = tgetl(vptr + 2 * n); | ||
741 | void *addr = alloca(addrlen); | 813 | void *addr = alloca(addrlen); |
742 | 814 | ||
743 | target_to_host_sockaddr(addr, target_addr, addrlen); | 815 | target_to_host_sockaddr(addr, target_addr, addrlen); |
@@ -746,128 +818,142 @@ static long do_socketcall(int num, int32_t *vptr) | @@ -746,128 +818,142 @@ static long do_socketcall(int num, int32_t *vptr) | ||
746 | break; | 818 | break; |
747 | case SOCKOP_listen: | 819 | case SOCKOP_listen: |
748 | { | 820 | { |
749 | - int sockfd = tswap32(vptr[0]); | ||
750 | - int backlog = tswap32(vptr[1]); | 821 | + int sockfd = tgetl(vptr); |
822 | + int backlog = tgetl(vptr + n); | ||
751 | 823 | ||
752 | ret = get_errno(listen(sockfd, backlog)); | 824 | ret = get_errno(listen(sockfd, backlog)); |
753 | } | 825 | } |
754 | break; | 826 | break; |
755 | case SOCKOP_accept: | 827 | case SOCKOP_accept: |
756 | { | 828 | { |
757 | - int sockfd = tswap32(vptr[0]); | ||
758 | - void *target_addr = (void *)tswap32(vptr[1]); | ||
759 | - uint32_t *target_addrlen = (void *)tswap32(vptr[2]); | ||
760 | - socklen_t addrlen = tswap32(*target_addrlen); | 829 | + int sockfd = tgetl(vptr); |
830 | + target_ulong target_addr = tgetl(vptr + n); | ||
831 | + target_ulong target_addrlen = tgetl(vptr + 2 * n); | ||
832 | + socklen_t addrlen = tget32(target_addrlen); | ||
761 | void *addr = alloca(addrlen); | 833 | void *addr = alloca(addrlen); |
762 | 834 | ||
763 | ret = get_errno(accept(sockfd, addr, &addrlen)); | 835 | ret = get_errno(accept(sockfd, addr, &addrlen)); |
764 | if (!is_error(ret)) { | 836 | if (!is_error(ret)) { |
765 | host_to_target_sockaddr(target_addr, addr, addrlen); | 837 | host_to_target_sockaddr(target_addr, addr, addrlen); |
766 | - *target_addrlen = tswap32(addrlen); | 838 | + tput32(target_addrlen, addrlen); |
767 | } | 839 | } |
768 | } | 840 | } |
769 | break; | 841 | break; |
770 | case SOCKOP_getsockname: | 842 | case SOCKOP_getsockname: |
771 | { | 843 | { |
772 | - int sockfd = tswap32(vptr[0]); | ||
773 | - void *target_addr = (void *)tswap32(vptr[1]); | ||
774 | - uint32_t *target_addrlen = (void *)tswap32(vptr[2]); | ||
775 | - socklen_t addrlen = tswap32(*target_addrlen); | 844 | + int sockfd = tgetl(vptr); |
845 | + target_ulong target_addr = tgetl(vptr + n); | ||
846 | + target_ulong target_addrlen = tgetl(vptr + 2 * n); | ||
847 | + socklen_t addrlen = tget32(target_addrlen); | ||
776 | void *addr = alloca(addrlen); | 848 | void *addr = alloca(addrlen); |
777 | 849 | ||
778 | ret = get_errno(getsockname(sockfd, addr, &addrlen)); | 850 | ret = get_errno(getsockname(sockfd, addr, &addrlen)); |
779 | if (!is_error(ret)) { | 851 | if (!is_error(ret)) { |
780 | host_to_target_sockaddr(target_addr, addr, addrlen); | 852 | host_to_target_sockaddr(target_addr, addr, addrlen); |
781 | - *target_addrlen = tswap32(addrlen); | 853 | + tput32(target_addrlen, addrlen); |
782 | } | 854 | } |
783 | } | 855 | } |
784 | break; | 856 | break; |
785 | case SOCKOP_getpeername: | 857 | case SOCKOP_getpeername: |
786 | { | 858 | { |
787 | - int sockfd = tswap32(vptr[0]); | ||
788 | - void *target_addr = (void *)tswap32(vptr[1]); | ||
789 | - uint32_t *target_addrlen = (void *)tswap32(vptr[2]); | ||
790 | - socklen_t addrlen = tswap32(*target_addrlen); | 859 | + int sockfd = tgetl(vptr); |
860 | + target_ulong target_addr = tgetl(vptr + n); | ||
861 | + target_ulong target_addrlen = tgetl(vptr + 2 * n); | ||
862 | + socklen_t addrlen = tget32(target_addrlen); | ||
791 | void *addr = alloca(addrlen); | 863 | void *addr = alloca(addrlen); |
792 | 864 | ||
793 | ret = get_errno(getpeername(sockfd, addr, &addrlen)); | 865 | ret = get_errno(getpeername(sockfd, addr, &addrlen)); |
794 | if (!is_error(ret)) { | 866 | if (!is_error(ret)) { |
795 | host_to_target_sockaddr(target_addr, addr, addrlen); | 867 | host_to_target_sockaddr(target_addr, addr, addrlen); |
796 | - *target_addrlen = tswap32(addrlen); | 868 | + tput32(target_addrlen, addrlen); |
797 | } | 869 | } |
798 | } | 870 | } |
799 | break; | 871 | break; |
800 | case SOCKOP_socketpair: | 872 | case SOCKOP_socketpair: |
801 | { | 873 | { |
802 | - int domain = tswap32(vptr[0]); | ||
803 | - int type = tswap32(vptr[1]); | ||
804 | - int protocol = tswap32(vptr[2]); | ||
805 | - int32_t *target_tab = (void *)tswap32(vptr[3]); | 874 | + int domain = tgetl(vptr); |
875 | + int type = tgetl(vptr + n); | ||
876 | + int protocol = tgetl(vptr + 2 * n); | ||
877 | + target_ulong target_tab = tgetl(vptr + 3 * n); | ||
806 | int tab[2]; | 878 | int tab[2]; |
807 | 879 | ||
808 | ret = get_errno(socketpair(domain, type, protocol, tab)); | 880 | ret = get_errno(socketpair(domain, type, protocol, tab)); |
809 | if (!is_error(ret)) { | 881 | if (!is_error(ret)) { |
810 | - target_tab[0] = tswap32(tab[0]); | ||
811 | - target_tab[1] = tswap32(tab[1]); | 882 | + tput32(target_tab, tab[0]); |
883 | + tput32(target_tab + 4, tab[1]); | ||
812 | } | 884 | } |
813 | } | 885 | } |
814 | break; | 886 | break; |
815 | case SOCKOP_send: | 887 | case SOCKOP_send: |
816 | { | 888 | { |
817 | - int sockfd = tswap32(vptr[0]); | ||
818 | - void *msg = (void *)tswap32(vptr[1]); | ||
819 | - size_t len = tswap32(vptr[2]); | ||
820 | - int flags = tswap32(vptr[3]); | 889 | + int sockfd = tgetl(vptr); |
890 | + target_ulong msg = tgetl(vptr + n); | ||
891 | + size_t len = tgetl(vptr + 2 * n); | ||
892 | + int flags = tgetl(vptr + 3 * n); | ||
893 | + void *host_msg; | ||
821 | 894 | ||
822 | - ret = get_errno(send(sockfd, msg, len, flags)); | 895 | + host_msg = lock_user(msg, len, 1); |
896 | + ret = get_errno(send(sockfd, host_msg, len, flags)); | ||
897 | + unlock_user(host_msg, msg, 0); | ||
823 | } | 898 | } |
824 | break; | 899 | break; |
825 | case SOCKOP_recv: | 900 | case SOCKOP_recv: |
826 | { | 901 | { |
827 | - int sockfd = tswap32(vptr[0]); | ||
828 | - void *msg = (void *)tswap32(vptr[1]); | ||
829 | - size_t len = tswap32(vptr[2]); | ||
830 | - int flags = tswap32(vptr[3]); | 902 | + int sockfd = tgetl(vptr); |
903 | + target_ulong msg = tgetl(vptr + n); | ||
904 | + size_t len = tgetl(vptr + 2 * n); | ||
905 | + int flags = tgetl(vptr + 3 * n); | ||
906 | + void *host_msg; | ||
831 | 907 | ||
832 | - ret = get_errno(recv(sockfd, msg, len, flags)); | 908 | + host_msg = lock_user(msg, len, 0); |
909 | + ret = get_errno(recv(sockfd, host_msg, len, flags)); | ||
910 | + unlock_user(host_msg, msg, ret); | ||
833 | } | 911 | } |
834 | break; | 912 | break; |
835 | case SOCKOP_sendto: | 913 | case SOCKOP_sendto: |
836 | { | 914 | { |
837 | - int sockfd = tswap32(vptr[0]); | ||
838 | - void *msg = (void *)tswap32(vptr[1]); | ||
839 | - size_t len = tswap32(vptr[2]); | ||
840 | - int flags = tswap32(vptr[3]); | ||
841 | - void *target_addr = (void *)tswap32(vptr[4]); | ||
842 | - socklen_t addrlen = tswap32(vptr[5]); | 915 | + int sockfd = tgetl(vptr); |
916 | + target_ulong msg = tgetl(vptr + n); | ||
917 | + size_t len = tgetl(vptr + 2 * n); | ||
918 | + int flags = tgetl(vptr + 3 * n); | ||
919 | + target_ulong target_addr = tgetl(vptr + 4 * n); | ||
920 | + socklen_t addrlen = tgetl(vptr + 5 * n); | ||
843 | void *addr = alloca(addrlen); | 921 | void *addr = alloca(addrlen); |
922 | + void *host_msg; | ||
844 | 923 | ||
924 | + host_msg = lock_user(msg, len, 1); | ||
845 | target_to_host_sockaddr(addr, target_addr, addrlen); | 925 | target_to_host_sockaddr(addr, target_addr, addrlen); |
846 | - ret = get_errno(sendto(sockfd, msg, len, flags, addr, addrlen)); | 926 | + ret = get_errno(sendto(sockfd, host_msg, len, flags, addr, addrlen)); |
927 | + unlock_user(host_msg, msg, 0); | ||
847 | } | 928 | } |
848 | break; | 929 | break; |
849 | case SOCKOP_recvfrom: | 930 | case SOCKOP_recvfrom: |
850 | { | 931 | { |
851 | - int sockfd = tswap32(vptr[0]); | ||
852 | - void *msg = (void *)tswap32(vptr[1]); | ||
853 | - size_t len = tswap32(vptr[2]); | ||
854 | - int flags = tswap32(vptr[3]); | ||
855 | - void *target_addr = (void *)tswap32(vptr[4]); | ||
856 | - uint32_t *target_addrlen = (void *)tswap32(vptr[5]); | ||
857 | - socklen_t addrlen = tswap32(*target_addrlen); | 932 | + int sockfd = tgetl(vptr); |
933 | + target_ulong msg = tgetl(vptr + n); | ||
934 | + size_t len = tgetl(vptr + 2 * n); | ||
935 | + int flags = tgetl(vptr + 3 * n); | ||
936 | + target_ulong target_addr = tgetl(vptr + 4 * n); | ||
937 | + target_ulong target_addrlen = tgetl(vptr + 5 * n); | ||
938 | + socklen_t addrlen = tget32(target_addrlen); | ||
858 | void *addr = alloca(addrlen); | 939 | void *addr = alloca(addrlen); |
940 | + void *host_msg; | ||
859 | 941 | ||
860 | - ret = get_errno(recvfrom(sockfd, msg, len, flags, addr, &addrlen)); | 942 | + host_msg = lock_user(msg, len, 0); |
943 | + ret = get_errno(recvfrom(sockfd, host_msg, len, flags, addr, &addrlen)); | ||
861 | if (!is_error(ret)) { | 944 | if (!is_error(ret)) { |
862 | host_to_target_sockaddr(target_addr, addr, addrlen); | 945 | host_to_target_sockaddr(target_addr, addr, addrlen); |
863 | - *target_addrlen = tswap32(addrlen); | 946 | + tput32(target_addrlen, addrlen); |
947 | + unlock_user(host_msg, msg, len); | ||
948 | + } else { | ||
949 | + unlock_user(host_msg, msg, 0); | ||
864 | } | 950 | } |
865 | } | 951 | } |
866 | break; | 952 | break; |
867 | case SOCKOP_shutdown: | 953 | case SOCKOP_shutdown: |
868 | { | 954 | { |
869 | - int sockfd = tswap32(vptr[0]); | ||
870 | - int how = tswap32(vptr[1]); | 955 | + int sockfd = tgetl(vptr); |
956 | + int how = tgetl(vptr + n); | ||
871 | 957 | ||
872 | ret = get_errno(shutdown(sockfd, how)); | 958 | ret = get_errno(shutdown(sockfd, how)); |
873 | } | 959 | } |
@@ -876,32 +962,39 @@ static long do_socketcall(int num, int32_t *vptr) | @@ -876,32 +962,39 @@ static long do_socketcall(int num, int32_t *vptr) | ||
876 | case SOCKOP_recvmsg: | 962 | case SOCKOP_recvmsg: |
877 | { | 963 | { |
878 | int fd; | 964 | int fd; |
965 | + target_ulong target_msg; | ||
879 | struct target_msghdr *msgp; | 966 | struct target_msghdr *msgp; |
880 | struct msghdr msg; | 967 | struct msghdr msg; |
881 | - int flags, count, i; | 968 | + int flags, count; |
882 | struct iovec *vec; | 969 | struct iovec *vec; |
883 | - struct target_iovec *target_vec; | ||
884 | - | ||
885 | - msgp = (void *)tswap32(vptr[1]); | ||
886 | - msg.msg_name = (void *)tswapl(msgp->msg_name); | ||
887 | - msg.msg_namelen = tswapl(msgp->msg_namelen); | 970 | + target_ulong target_vec; |
971 | + int send = (num == SOCKOP_sendmsg); | ||
972 | + | ||
973 | + target_msg = tgetl(vptr + n); | ||
974 | + lock_user_struct(msgp, target_msg, 1); | ||
975 | + if (msgp->msg_name) { | ||
976 | + msg.msg_namelen = tswap32(msgp->msg_namelen); | ||
977 | + msg.msg_name = alloca(msg.msg_namelen); | ||
978 | + target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), | ||
979 | + msg.msg_namelen); | ||
980 | + } else { | ||
981 | + msg.msg_name = NULL; | ||
982 | + msg.msg_namelen = 0; | ||
983 | + } | ||
888 | msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); | 984 | msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); |
889 | msg.msg_control = alloca(msg.msg_controllen); | 985 | msg.msg_control = alloca(msg.msg_controllen); |
890 | msg.msg_flags = tswap32(msgp->msg_flags); | 986 | msg.msg_flags = tswap32(msgp->msg_flags); |
891 | 987 | ||
892 | count = tswapl(msgp->msg_iovlen); | 988 | count = tswapl(msgp->msg_iovlen); |
893 | vec = alloca(count * sizeof(struct iovec)); | 989 | vec = alloca(count * sizeof(struct iovec)); |
894 | - target_vec = (void *)tswapl(msgp->msg_iov); | ||
895 | - for(i = 0;i < count; i++) { | ||
896 | - vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base); | ||
897 | - vec[i].iov_len = tswapl(target_vec[i].iov_len); | ||
898 | - } | 990 | + target_vec = tswapl(msgp->msg_iov); |
991 | + lock_iovec(vec, target_vec, count, send); | ||
899 | msg.msg_iovlen = count; | 992 | msg.msg_iovlen = count; |
900 | msg.msg_iov = vec; | 993 | msg.msg_iov = vec; |
901 | 994 | ||
902 | - fd = tswap32(vptr[0]); | ||
903 | - flags = tswap32(vptr[2]); | ||
904 | - if (num == SOCKOP_sendmsg) { | 995 | + fd = tgetl(vptr); |
996 | + flags = tgetl(vptr + 2 * n); | ||
997 | + if (send) { | ||
905 | target_to_host_cmsg(&msg, msgp); | 998 | target_to_host_cmsg(&msg, msgp); |
906 | ret = get_errno(sendmsg(fd, &msg, flags)); | 999 | ret = get_errno(sendmsg(fd, &msg, flags)); |
907 | } else { | 1000 | } else { |
@@ -909,26 +1002,27 @@ static long do_socketcall(int num, int32_t *vptr) | @@ -909,26 +1002,27 @@ static long do_socketcall(int num, int32_t *vptr) | ||
909 | if (!is_error(ret)) | 1002 | if (!is_error(ret)) |
910 | host_to_target_cmsg(msgp, &msg); | 1003 | host_to_target_cmsg(msgp, &msg); |
911 | } | 1004 | } |
1005 | + unlock_iovec(vec, target_vec, count, !send); | ||
912 | } | 1006 | } |
913 | break; | 1007 | break; |
914 | case SOCKOP_setsockopt: | 1008 | case SOCKOP_setsockopt: |
915 | { | 1009 | { |
916 | - int sockfd = tswap32(vptr[0]); | ||
917 | - int level = tswap32(vptr[1]); | ||
918 | - int optname = tswap32(vptr[2]); | ||
919 | - void *optval = (void *)tswap32(vptr[3]); | ||
920 | - socklen_t optlen = tswap32(vptr[4]); | 1010 | + int sockfd = tgetl(vptr); |
1011 | + int level = tgetl(vptr + n); | ||
1012 | + int optname = tgetl(vptr + 2 * n); | ||
1013 | + target_ulong optval = tgetl(vptr + 3 * n); | ||
1014 | + socklen_t optlen = tgetl(vptr + 4 * n); | ||
921 | 1015 | ||
922 | ret = do_setsockopt(sockfd, level, optname, optval, optlen); | 1016 | ret = do_setsockopt(sockfd, level, optname, optval, optlen); |
923 | } | 1017 | } |
924 | break; | 1018 | break; |
925 | case SOCKOP_getsockopt: | 1019 | case SOCKOP_getsockopt: |
926 | { | 1020 | { |
927 | - int sockfd = tswap32(vptr[0]); | ||
928 | - int level = tswap32(vptr[1]); | ||
929 | - int optname = tswap32(vptr[2]); | ||
930 | - void *optval = (void *)tswap32(vptr[3]); | ||
931 | - uint32_t *poptlen = (void *)tswap32(vptr[4]); | 1021 | + int sockfd = tgetl(vptr); |
1022 | + int level = tgetl(vptr + n); | ||
1023 | + int optname = tgetl(vptr + 2 * n); | ||
1024 | + target_ulong optval = tgetl(vptr + 3 * n); | ||
1025 | + target_ulong poptlen = tgetl(vptr + 4 * n); | ||
932 | 1026 | ||
933 | ret = do_getsockopt(sockfd, level, optname, optval, poptlen); | 1027 | ret = do_getsockopt(sockfd, level, optname, optval, poptlen); |
934 | } | 1028 | } |
@@ -949,6 +1043,7 @@ static struct shm_region { | @@ -949,6 +1043,7 @@ static struct shm_region { | ||
949 | uint32_t size; | 1043 | uint32_t size; |
950 | } shm_regions[N_SHM_REGIONS]; | 1044 | } shm_regions[N_SHM_REGIONS]; |
951 | 1045 | ||
1046 | +/* ??? This only works with linear mappings. */ | ||
952 | static long do_ipc(long call, long first, long second, long third, | 1047 | static long do_ipc(long call, long first, long second, long third, |
953 | long ptr, long fifth) | 1048 | long ptr, long fifth) |
954 | { | 1049 | { |
@@ -1065,12 +1160,15 @@ IOCTLEntry ioctl_entries[] = { | @@ -1065,12 +1160,15 @@ IOCTLEntry ioctl_entries[] = { | ||
1065 | { 0, 0, }, | 1160 | { 0, 0, }, |
1066 | }; | 1161 | }; |
1067 | 1162 | ||
1163 | +/* ??? Implement proper locking for ioctls. */ | ||
1068 | static long do_ioctl(long fd, long cmd, long arg) | 1164 | static long do_ioctl(long fd, long cmd, long arg) |
1069 | { | 1165 | { |
1070 | const IOCTLEntry *ie; | 1166 | const IOCTLEntry *ie; |
1071 | const argtype *arg_type; | 1167 | const argtype *arg_type; |
1072 | long ret; | 1168 | long ret; |
1073 | uint8_t buf_temp[MAX_STRUCT_SIZE]; | 1169 | uint8_t buf_temp[MAX_STRUCT_SIZE]; |
1170 | + int target_size; | ||
1171 | + void *argptr; | ||
1074 | 1172 | ||
1075 | ie = ioctl_entries; | 1173 | ie = ioctl_entries; |
1076 | for(;;) { | 1174 | for(;;) { |
@@ -1098,23 +1196,32 @@ static long do_ioctl(long fd, long cmd, long arg) | @@ -1098,23 +1196,32 @@ static long do_ioctl(long fd, long cmd, long arg) | ||
1098 | break; | 1196 | break; |
1099 | case TYPE_PTR: | 1197 | case TYPE_PTR: |
1100 | arg_type++; | 1198 | arg_type++; |
1199 | + target_size = thunk_type_size(arg_type, 0); | ||
1101 | switch(ie->access) { | 1200 | switch(ie->access) { |
1102 | case IOC_R: | 1201 | case IOC_R: |
1103 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); | 1202 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1104 | if (!is_error(ret)) { | 1203 | if (!is_error(ret)) { |
1105 | - thunk_convert((void *)arg, buf_temp, arg_type, THUNK_TARGET); | 1204 | + argptr = lock_user(arg, target_size, 0); |
1205 | + thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); | ||
1206 | + unlock_user(argptr, arg, target_size); | ||
1106 | } | 1207 | } |
1107 | break; | 1208 | break; |
1108 | case IOC_W: | 1209 | case IOC_W: |
1109 | - thunk_convert(buf_temp, (void *)arg, arg_type, THUNK_HOST); | 1210 | + argptr = lock_user(arg, target_size, 1); |
1211 | + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); | ||
1212 | + unlock_user(argptr, arg, 0); | ||
1110 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); | 1213 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1111 | break; | 1214 | break; |
1112 | default: | 1215 | default: |
1113 | case IOC_RW: | 1216 | case IOC_RW: |
1114 | - thunk_convert(buf_temp, (void *)arg, arg_type, THUNK_HOST); | 1217 | + argptr = lock_user(arg, target_size, 1); |
1218 | + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); | ||
1219 | + unlock_user(argptr, arg, 0); | ||
1115 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); | 1220 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1116 | if (!is_error(ret)) { | 1221 | if (!is_error(ret)) { |
1117 | - thunk_convert((void *)arg, buf_temp, arg_type, THUNK_TARGET); | 1222 | + argptr = lock_user(arg, target_size, 0); |
1223 | + thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); | ||
1224 | + unlock_user(argptr, arg, target_size); | ||
1118 | } | 1225 | } |
1119 | break; | 1226 | break; |
1120 | } | 1227 | } |
@@ -1338,35 +1445,41 @@ static bitmask_transtbl fcntl_flags_tbl[] = { | @@ -1338,35 +1445,41 @@ static bitmask_transtbl fcntl_flags_tbl[] = { | ||
1338 | /* NOTE: there is really one LDT for all the threads */ | 1445 | /* NOTE: there is really one LDT for all the threads */ |
1339 | uint8_t *ldt_table; | 1446 | uint8_t *ldt_table; |
1340 | 1447 | ||
1341 | -static int read_ldt(void *ptr, unsigned long bytecount) | 1448 | +static int read_ldt(target_ulong ptr, unsigned long bytecount) |
1342 | { | 1449 | { |
1343 | int size; | 1450 | int size; |
1451 | + void *p; | ||
1344 | 1452 | ||
1345 | if (!ldt_table) | 1453 | if (!ldt_table) |
1346 | return 0; | 1454 | return 0; |
1347 | size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE; | 1455 | size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE; |
1348 | if (size > bytecount) | 1456 | if (size > bytecount) |
1349 | size = bytecount; | 1457 | size = bytecount; |
1350 | - memcpy(ptr, ldt_table, size); | 1458 | + p = lock_user(ptr, size, 0); |
1459 | + /* ??? Shoudl this by byteswapped? */ | ||
1460 | + memcpy(p, ldt_table, size); | ||
1461 | + unlock_user(p, ptr, size); | ||
1351 | return size; | 1462 | return size; |
1352 | } | 1463 | } |
1353 | 1464 | ||
1354 | /* XXX: add locking support */ | 1465 | /* XXX: add locking support */ |
1355 | static int write_ldt(CPUX86State *env, | 1466 | static int write_ldt(CPUX86State *env, |
1356 | - void *ptr, unsigned long bytecount, int oldmode) | 1467 | + target_ulong ptr, unsigned long bytecount, int oldmode) |
1357 | { | 1468 | { |
1358 | struct target_modify_ldt_ldt_s ldt_info; | 1469 | struct target_modify_ldt_ldt_s ldt_info; |
1470 | + struct target_modify_ldt_ldt_s *target_ldt_info; | ||
1359 | int seg_32bit, contents, read_exec_only, limit_in_pages; | 1471 | int seg_32bit, contents, read_exec_only, limit_in_pages; |
1360 | int seg_not_present, useable; | 1472 | int seg_not_present, useable; |
1361 | uint32_t *lp, entry_1, entry_2; | 1473 | uint32_t *lp, entry_1, entry_2; |
1362 | 1474 | ||
1363 | if (bytecount != sizeof(ldt_info)) | 1475 | if (bytecount != sizeof(ldt_info)) |
1364 | return -EINVAL; | 1476 | return -EINVAL; |
1365 | - memcpy(&ldt_info, ptr, sizeof(ldt_info)); | ||
1366 | - tswap32s(&ldt_info.entry_number); | ||
1367 | - tswapls((long *)&ldt_info.base_addr); | ||
1368 | - tswap32s(&ldt_info.limit); | ||
1369 | - tswap32s(&ldt_info.flags); | 1477 | + lock_user_struct(target_ldt_info, ptr, 1); |
1478 | + ldt_info.entry_number = tswap32(target_ldt_info->entry_number); | ||
1479 | + ldt_info.base_addr = tswapl(target_ldt_info->base_addr); | ||
1480 | + ldt_info.limit = tswap32(target_ldt_info->limit); | ||
1481 | + ldt_info.flags = tswap32(target_ldt_info->flags); | ||
1482 | + unlock_user_struct(target_ldt_info, ptr, 0); | ||
1370 | 1483 | ||
1371 | if (ldt_info.entry_number >= TARGET_LDT_ENTRIES) | 1484 | if (ldt_info.entry_number >= TARGET_LDT_ENTRIES) |
1372 | return -EINVAL; | 1485 | return -EINVAL; |
@@ -1389,7 +1502,7 @@ static int write_ldt(CPUX86State *env, | @@ -1389,7 +1502,7 @@ static int write_ldt(CPUX86State *env, | ||
1389 | if (!ldt_table) | 1502 | if (!ldt_table) |
1390 | return -ENOMEM; | 1503 | return -ENOMEM; |
1391 | memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE); | 1504 | memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE); |
1392 | - env->ldt.base = (long)ldt_table; | 1505 | + env->ldt.base = h2g(ldt_table); |
1393 | env->ldt.limit = 0xffff; | 1506 | env->ldt.limit = 0xffff; |
1394 | } | 1507 | } |
1395 | 1508 | ||
@@ -1432,7 +1545,7 @@ install: | @@ -1432,7 +1545,7 @@ install: | ||
1432 | } | 1545 | } |
1433 | 1546 | ||
1434 | /* specific and weird i386 syscalls */ | 1547 | /* specific and weird i386 syscalls */ |
1435 | -int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount) | 1548 | +int do_modify_ldt(CPUX86State *env, int func, target_ulong ptr, unsigned long bytecount) |
1436 | { | 1549 | { |
1437 | int ret = -ENOSYS; | 1550 | int ret = -ENOSYS; |
1438 | 1551 | ||
@@ -1523,31 +1636,35 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) | @@ -1523,31 +1636,35 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) | ||
1523 | return ret; | 1636 | return ret; |
1524 | } | 1637 | } |
1525 | 1638 | ||
1526 | -static long do_fcntl(int fd, int cmd, unsigned long arg) | 1639 | +static long do_fcntl(int fd, int cmd, target_ulong arg) |
1527 | { | 1640 | { |
1528 | struct flock fl; | 1641 | struct flock fl; |
1529 | - struct target_flock *target_fl = (void *)arg; | 1642 | + struct target_flock *target_fl; |
1530 | long ret; | 1643 | long ret; |
1531 | - | 1644 | + |
1532 | switch(cmd) { | 1645 | switch(cmd) { |
1533 | case TARGET_F_GETLK: | 1646 | case TARGET_F_GETLK: |
1534 | ret = fcntl(fd, cmd, &fl); | 1647 | ret = fcntl(fd, cmd, &fl); |
1535 | if (ret == 0) { | 1648 | if (ret == 0) { |
1649 | + lock_user_struct(target_fl, arg, 0); | ||
1536 | target_fl->l_type = tswap16(fl.l_type); | 1650 | target_fl->l_type = tswap16(fl.l_type); |
1537 | target_fl->l_whence = tswap16(fl.l_whence); | 1651 | target_fl->l_whence = tswap16(fl.l_whence); |
1538 | target_fl->l_start = tswapl(fl.l_start); | 1652 | target_fl->l_start = tswapl(fl.l_start); |
1539 | target_fl->l_len = tswapl(fl.l_len); | 1653 | target_fl->l_len = tswapl(fl.l_len); |
1540 | target_fl->l_pid = tswapl(fl.l_pid); | 1654 | target_fl->l_pid = tswapl(fl.l_pid); |
1655 | + unlock_user_struct(target_fl, arg, 1); | ||
1541 | } | 1656 | } |
1542 | break; | 1657 | break; |
1543 | 1658 | ||
1544 | case TARGET_F_SETLK: | 1659 | case TARGET_F_SETLK: |
1545 | case TARGET_F_SETLKW: | 1660 | case TARGET_F_SETLKW: |
1661 | + lock_user_struct(target_fl, arg, 1); | ||
1546 | fl.l_type = tswap16(target_fl->l_type); | 1662 | fl.l_type = tswap16(target_fl->l_type); |
1547 | fl.l_whence = tswap16(target_fl->l_whence); | 1663 | fl.l_whence = tswap16(target_fl->l_whence); |
1548 | fl.l_start = tswapl(target_fl->l_start); | 1664 | fl.l_start = tswapl(target_fl->l_start); |
1549 | fl.l_len = tswapl(target_fl->l_len); | 1665 | fl.l_len = tswapl(target_fl->l_len); |
1550 | fl.l_pid = tswapl(target_fl->l_pid); | 1666 | fl.l_pid = tswapl(target_fl->l_pid); |
1667 | + unlock_user_struct(target_fl, arg, 0); | ||
1551 | ret = fcntl(fd, cmd, &fl); | 1668 | ret = fcntl(fd, cmd, &fl); |
1552 | break; | 1669 | break; |
1553 | 1670 | ||
@@ -1690,12 +1807,35 @@ static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2, | @@ -1690,12 +1807,35 @@ static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2, | ||
1690 | } | 1807 | } |
1691 | #endif | 1808 | #endif |
1692 | 1809 | ||
1810 | +static inline void target_to_host_timespec(struct timespec *host_ts, | ||
1811 | + target_ulong target_addr) | ||
1812 | +{ | ||
1813 | + struct target_timespec *target_ts; | ||
1814 | + | ||
1815 | + lock_user_struct(target_ts, target_addr, 1); | ||
1816 | + host_ts->tv_sec = tswapl(target_ts->tv_sec); | ||
1817 | + host_ts->tv_nsec = tswapl(target_ts->tv_nsec); | ||
1818 | + unlock_user_struct(target_ts, target_addr, 0); | ||
1819 | +} | ||
1820 | + | ||
1821 | +static inline void host_to_target_timespec(target_ulong target_addr, | ||
1822 | + struct timespec *host_ts) | ||
1823 | +{ | ||
1824 | + struct target_timespec *target_ts; | ||
1825 | + | ||
1826 | + lock_user_struct(target_ts, target_addr, 0); | ||
1827 | + target_ts->tv_sec = tswapl(host_ts->tv_sec); | ||
1828 | + target_ts->tv_nsec = tswapl(host_ts->tv_nsec); | ||
1829 | + unlock_user_struct(target_ts, target_addr, 1); | ||
1830 | +} | ||
1831 | + | ||
1693 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | 1832 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1694 | long arg4, long arg5, long arg6) | 1833 | long arg4, long arg5, long arg6) |
1695 | { | 1834 | { |
1696 | long ret; | 1835 | long ret; |
1697 | struct stat st; | 1836 | struct stat st; |
1698 | struct statfs stfs; | 1837 | struct statfs stfs; |
1838 | + void *p; | ||
1699 | 1839 | ||
1700 | #ifdef DEBUG | 1840 | #ifdef DEBUG |
1701 | gemu_log("syscall %d", num); | 1841 | gemu_log("syscall %d", num); |
@@ -1711,89 +1851,140 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1711,89 +1851,140 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1711 | ret = 0; /* avoid warning */ | 1851 | ret = 0; /* avoid warning */ |
1712 | break; | 1852 | break; |
1713 | case TARGET_NR_read: | 1853 | case TARGET_NR_read: |
1714 | - page_unprotect_range((void *)arg2, arg3); | ||
1715 | - ret = get_errno(read(arg1, (void *)arg2, arg3)); | 1854 | + page_unprotect_range(arg2, arg3); |
1855 | + p = lock_user(arg2, arg3, 0); | ||
1856 | + ret = get_errno(read(arg1, p, arg3)); | ||
1857 | + unlock_user(p, arg2, ret); | ||
1716 | break; | 1858 | break; |
1717 | case TARGET_NR_write: | 1859 | case TARGET_NR_write: |
1718 | - ret = get_errno(write(arg1, (void *)arg2, arg3)); | 1860 | + p = lock_user(arg2, arg3, 1); |
1861 | + ret = get_errno(write(arg1, p, arg3)); | ||
1862 | + unlock_user(p, arg2, 0); | ||
1719 | break; | 1863 | break; |
1720 | case TARGET_NR_open: | 1864 | case TARGET_NR_open: |
1721 | - ret = get_errno(open(path((const char *)arg1), | 1865 | + p = lock_user_string(arg1); |
1866 | + ret = get_errno(open(path(p), | ||
1722 | target_to_host_bitmask(arg2, fcntl_flags_tbl), | 1867 | target_to_host_bitmask(arg2, fcntl_flags_tbl), |
1723 | arg3)); | 1868 | arg3)); |
1869 | + unlock_user(p, arg1, 0); | ||
1724 | break; | 1870 | break; |
1725 | case TARGET_NR_close: | 1871 | case TARGET_NR_close: |
1726 | ret = get_errno(close(arg1)); | 1872 | ret = get_errno(close(arg1)); |
1727 | break; | 1873 | break; |
1728 | case TARGET_NR_brk: | 1874 | case TARGET_NR_brk: |
1729 | - ret = do_brk((char *)arg1); | 1875 | + ret = do_brk(arg1); |
1730 | break; | 1876 | break; |
1731 | case TARGET_NR_fork: | 1877 | case TARGET_NR_fork: |
1732 | ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); | 1878 | ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); |
1733 | break; | 1879 | break; |
1734 | case TARGET_NR_waitpid: | 1880 | case TARGET_NR_waitpid: |
1735 | { | 1881 | { |
1736 | - int *status = (int *)arg2; | ||
1737 | - ret = get_errno(waitpid(arg1, status, arg3)); | ||
1738 | - if (!is_error(ret) && status) | ||
1739 | - tswapls((long *)&status); | 1882 | + int status; |
1883 | + ret = get_errno(waitpid(arg1, &status, arg3)); | ||
1884 | + if (!is_error(ret) && arg2) | ||
1885 | + tput32(arg2, status); | ||
1740 | } | 1886 | } |
1741 | break; | 1887 | break; |
1742 | case TARGET_NR_creat: | 1888 | case TARGET_NR_creat: |
1743 | - ret = get_errno(creat((const char *)arg1, arg2)); | 1889 | + p = lock_user_string(arg1); |
1890 | + ret = get_errno(creat(p, arg2)); | ||
1891 | + unlock_user(p, arg1, 0); | ||
1744 | break; | 1892 | break; |
1745 | case TARGET_NR_link: | 1893 | case TARGET_NR_link: |
1746 | - ret = get_errno(link((const char *)arg1, (const char *)arg2)); | 1894 | + { |
1895 | + void * p2; | ||
1896 | + p = lock_user_string(arg1); | ||
1897 | + p2 = lock_user_string(arg2); | ||
1898 | + ret = get_errno(link(p, p2)); | ||
1899 | + unlock_user(p2, arg2, 0); | ||
1900 | + unlock_user(p, arg1, 0); | ||
1901 | + } | ||
1747 | break; | 1902 | break; |
1748 | case TARGET_NR_unlink: | 1903 | case TARGET_NR_unlink: |
1749 | - ret = get_errno(unlink((const char *)arg1)); | 1904 | + p = lock_user_string(arg1); |
1905 | + ret = get_errno(unlink(p)); | ||
1906 | + unlock_user(p, arg1, 0); | ||
1750 | break; | 1907 | break; |
1751 | case TARGET_NR_execve: | 1908 | case TARGET_NR_execve: |
1752 | { | 1909 | { |
1753 | char **argp, **envp; | 1910 | char **argp, **envp; |
1754 | int argc, envc; | 1911 | int argc, envc; |
1755 | - uint32_t *p; | 1912 | + target_ulong gp; |
1913 | + target_ulong guest_argp; | ||
1914 | + target_ulong guest_envp; | ||
1915 | + target_ulong addr; | ||
1756 | char **q; | 1916 | char **q; |
1757 | 1917 | ||
1758 | argc = 0; | 1918 | argc = 0; |
1759 | - for (p = (void *)arg2; *p; p++) | 1919 | + guest_argp = arg2; |
1920 | + for (gp = guest_argp; tgetl(gp); gp++) | ||
1760 | argc++; | 1921 | argc++; |
1761 | envc = 0; | 1922 | envc = 0; |
1762 | - for (p = (void *)arg3; *p; p++) | 1923 | + guest_envp = arg3; |
1924 | + for (gp = guest_envp; tgetl(gp); gp++) | ||
1763 | envc++; | 1925 | envc++; |
1764 | 1926 | ||
1765 | argp = alloca((argc + 1) * sizeof(void *)); | 1927 | argp = alloca((argc + 1) * sizeof(void *)); |
1766 | envp = alloca((envc + 1) * sizeof(void *)); | 1928 | envp = alloca((envc + 1) * sizeof(void *)); |
1767 | 1929 | ||
1768 | - for (p = (void *)arg2, q = argp; *p; p++, q++) | ||
1769 | - *q = (void *)tswap32(*p); | 1930 | + for (gp = guest_argp, q = argp; ; |
1931 | + gp += sizeof(target_ulong), q++) { | ||
1932 | + addr = tgetl(gp); | ||
1933 | + if (!addr) | ||
1934 | + break; | ||
1935 | + *q = lock_user_string(addr); | ||
1936 | + } | ||
1770 | *q = NULL; | 1937 | *q = NULL; |
1771 | 1938 | ||
1772 | - for (p = (void *)arg3, q = envp; *p; p++, q++) | ||
1773 | - *q = (void *)tswap32(*p); | 1939 | + for (gp = guest_envp, q = envp; ; |
1940 | + gp += sizeof(target_ulong), q++) { | ||
1941 | + addr = tgetl(gp); | ||
1942 | + if (!addr) | ||
1943 | + break; | ||
1944 | + *q = lock_user_string(addr); | ||
1945 | + } | ||
1774 | *q = NULL; | 1946 | *q = NULL; |
1775 | 1947 | ||
1776 | - ret = get_errno(execve((const char *)arg1, argp, envp)); | 1948 | + p = lock_user_string(arg1); |
1949 | + ret = get_errno(execve(p, argp, envp)); | ||
1950 | + unlock_user(p, arg1, 0); | ||
1951 | + | ||
1952 | + for (gp = guest_argp, q = argp; *q; | ||
1953 | + gp += sizeof(target_ulong), q++) { | ||
1954 | + addr = tgetl(gp); | ||
1955 | + unlock_user(*q, addr, 0); | ||
1956 | + } | ||
1957 | + for (gp = guest_envp, q = envp; *q; | ||
1958 | + gp += sizeof(target_ulong), q++) { | ||
1959 | + addr = tgetl(gp); | ||
1960 | + unlock_user(*q, addr, 0); | ||
1961 | + } | ||
1777 | } | 1962 | } |
1778 | break; | 1963 | break; |
1779 | case TARGET_NR_chdir: | 1964 | case TARGET_NR_chdir: |
1780 | - ret = get_errno(chdir((const char *)arg1)); | 1965 | + p = lock_user_string(arg1); |
1966 | + ret = get_errno(chdir(p)); | ||
1967 | + unlock_user(p, arg1, 0); | ||
1781 | break; | 1968 | break; |
1782 | #ifdef TARGET_NR_time | 1969 | #ifdef TARGET_NR_time |
1783 | case TARGET_NR_time: | 1970 | case TARGET_NR_time: |
1784 | { | 1971 | { |
1785 | - int *time_ptr = (int *)arg1; | ||
1786 | - ret = get_errno(time((time_t *)time_ptr)); | ||
1787 | - if (!is_error(ret) && time_ptr) | ||
1788 | - tswap32s(time_ptr); | 1972 | + time_t host_time; |
1973 | + ret = get_errno(time(&host_time)); | ||
1974 | + if (!is_error(ret) && arg1) | ||
1975 | + tputl(arg1, host_time); | ||
1789 | } | 1976 | } |
1790 | break; | 1977 | break; |
1791 | #endif | 1978 | #endif |
1792 | case TARGET_NR_mknod: | 1979 | case TARGET_NR_mknod: |
1793 | - ret = get_errno(mknod((const char *)arg1, arg2, arg3)); | 1980 | + p = lock_user_string(arg1); |
1981 | + ret = get_errno(mknod(p, arg2, arg3)); | ||
1982 | + unlock_user(p, arg1, 0); | ||
1794 | break; | 1983 | break; |
1795 | case TARGET_NR_chmod: | 1984 | case TARGET_NR_chmod: |
1796 | - ret = get_errno(chmod((const char *)arg1, arg2)); | 1985 | + p = lock_user_string(arg1); |
1986 | + ret = get_errno(chmod(p, arg2)); | ||
1987 | + unlock_user(p, arg1, 0); | ||
1797 | break; | 1988 | break; |
1798 | #ifdef TARGET_NR_break | 1989 | #ifdef TARGET_NR_break |
1799 | case TARGET_NR_break: | 1990 | case TARGET_NR_break: |
@@ -1813,14 +2004,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1813,14 +2004,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1813 | /* need to look at the data field */ | 2004 | /* need to look at the data field */ |
1814 | goto unimplemented; | 2005 | goto unimplemented; |
1815 | case TARGET_NR_umount: | 2006 | case TARGET_NR_umount: |
1816 | - ret = get_errno(umount((const char *)arg1)); | 2007 | + p = lock_user_string(arg1); |
2008 | + ret = get_errno(umount(p)); | ||
2009 | + unlock_user(p, arg1, 0); | ||
1817 | break; | 2010 | break; |
1818 | case TARGET_NR_stime: | 2011 | case TARGET_NR_stime: |
1819 | { | 2012 | { |
1820 | - int *time_ptr = (int *)arg1; | ||
1821 | - if (time_ptr) | ||
1822 | - tswap32s(time_ptr); | ||
1823 | - ret = get_errno(stime((time_t *)time_ptr)); | 2013 | + time_t host_time; |
2014 | + host_time = tgetl(arg1); | ||
2015 | + ret = get_errno(stime(&host_time)); | ||
1824 | } | 2016 | } |
1825 | break; | 2017 | break; |
1826 | case TARGET_NR_ptrace: | 2018 | case TARGET_NR_ptrace: |
@@ -1837,30 +2029,36 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1837,30 +2029,36 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1837 | break; | 2029 | break; |
1838 | case TARGET_NR_utime: | 2030 | case TARGET_NR_utime: |
1839 | { | 2031 | { |
1840 | - struct utimbuf tbuf, *tbuf1; | ||
1841 | - struct target_utimbuf *target_tbuf = (void *)arg2; | ||
1842 | - if (target_tbuf) { | ||
1843 | - get_user(tbuf.actime, &target_tbuf->actime); | ||
1844 | - get_user(tbuf.modtime, &target_tbuf->modtime); | ||
1845 | - tbuf1 = &tbuf; | 2032 | + struct utimbuf tbuf, *host_tbuf; |
2033 | + struct target_utimbuf *target_tbuf; | ||
2034 | + if (arg2) { | ||
2035 | + lock_user_struct(target_tbuf, arg2, 1); | ||
2036 | + tbuf.actime = tswapl(target_tbuf->actime); | ||
2037 | + tbuf.modtime = tswapl(target_tbuf->modtime); | ||
2038 | + unlock_user_struct(target_tbuf, arg2, 0); | ||
2039 | + host_tbuf = &tbuf; | ||
1846 | } else { | 2040 | } else { |
1847 | - tbuf1 = NULL; | 2041 | + host_tbuf = NULL; |
1848 | } | 2042 | } |
1849 | - ret = get_errno(utime((const char *)arg1, tbuf1)); | 2043 | + p = lock_user_string(arg1); |
2044 | + ret = get_errno(utime(p, host_tbuf)); | ||
2045 | + unlock_user(p, arg1, 0); | ||
1850 | } | 2046 | } |
1851 | break; | 2047 | break; |
1852 | case TARGET_NR_utimes: | 2048 | case TARGET_NR_utimes: |
1853 | { | 2049 | { |
1854 | - struct target_timeval *target_tvp = (struct target_timeval *)arg2; | ||
1855 | struct timeval *tvp, tv[2]; | 2050 | struct timeval *tvp, tv[2]; |
1856 | - if (target_tvp) { | ||
1857 | - target_to_host_timeval(&tv[0], &target_tvp[0]); | ||
1858 | - target_to_host_timeval(&tv[1], &target_tvp[1]); | 2051 | + if (arg2) { |
2052 | + target_to_host_timeval(&tv[0], arg2); | ||
2053 | + target_to_host_timeval(&tv[1], | ||
2054 | + arg2 + sizeof (struct target_timeval)); | ||
1859 | tvp = tv; | 2055 | tvp = tv; |
1860 | } else { | 2056 | } else { |
1861 | tvp = NULL; | 2057 | tvp = NULL; |
1862 | } | 2058 | } |
1863 | - ret = get_errno(utimes((const char *)arg1, tvp)); | 2059 | + p = lock_user_string(arg1); |
2060 | + ret = get_errno(utimes(p, tvp)); | ||
2061 | + unlock_user(p, arg1, 0); | ||
1864 | } | 2062 | } |
1865 | break; | 2063 | break; |
1866 | #ifdef TARGET_NR_stty | 2064 | #ifdef TARGET_NR_stty |
@@ -1872,7 +2070,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1872,7 +2070,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1872 | goto unimplemented; | 2070 | goto unimplemented; |
1873 | #endif | 2071 | #endif |
1874 | case TARGET_NR_access: | 2072 | case TARGET_NR_access: |
1875 | - ret = get_errno(access((const char *)arg1, arg2)); | 2073 | + p = lock_user_string(arg1); |
2074 | + ret = get_errno(access(p, arg2)); | ||
2075 | + unlock_user(p, arg1, 0); | ||
1876 | break; | 2076 | break; |
1877 | case TARGET_NR_nice: | 2077 | case TARGET_NR_nice: |
1878 | ret = get_errno(nice(arg1)); | 2078 | ret = get_errno(nice(arg1)); |
@@ -1889,33 +2089,45 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1889,33 +2089,45 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1889 | ret = get_errno(kill(arg1, arg2)); | 2089 | ret = get_errno(kill(arg1, arg2)); |
1890 | break; | 2090 | break; |
1891 | case TARGET_NR_rename: | 2091 | case TARGET_NR_rename: |
1892 | - ret = get_errno(rename((const char *)arg1, (const char *)arg2)); | 2092 | + { |
2093 | + void *p2; | ||
2094 | + p = lock_user_string(arg1); | ||
2095 | + p2 = lock_user_string(arg2); | ||
2096 | + ret = get_errno(rename(p, p2)); | ||
2097 | + unlock_user(p2, arg2, 0); | ||
2098 | + unlock_user(p, arg1, 0); | ||
2099 | + } | ||
1893 | break; | 2100 | break; |
1894 | case TARGET_NR_mkdir: | 2101 | case TARGET_NR_mkdir: |
1895 | - ret = get_errno(mkdir((const char *)arg1, arg2)); | 2102 | + p = lock_user_string(arg1); |
2103 | + ret = get_errno(mkdir(p, arg2)); | ||
2104 | + unlock_user(p, arg1, 0); | ||
1896 | break; | 2105 | break; |
1897 | case TARGET_NR_rmdir: | 2106 | case TARGET_NR_rmdir: |
1898 | - ret = get_errno(rmdir((const char *)arg1)); | 2107 | + p = lock_user_string(arg1); |
2108 | + ret = get_errno(rmdir(p)); | ||
2109 | + unlock_user(p, arg1, 0); | ||
1899 | break; | 2110 | break; |
1900 | case TARGET_NR_dup: | 2111 | case TARGET_NR_dup: |
1901 | ret = get_errno(dup(arg1)); | 2112 | ret = get_errno(dup(arg1)); |
1902 | break; | 2113 | break; |
1903 | case TARGET_NR_pipe: | 2114 | case TARGET_NR_pipe: |
1904 | { | 2115 | { |
1905 | - int *pipe_ptr = (int *)arg1; | ||
1906 | - ret = get_errno(pipe(pipe_ptr)); | 2116 | + int host_pipe[2]; |
2117 | + ret = get_errno(pipe(host_pipe)); | ||
1907 | if (!is_error(ret)) { | 2118 | if (!is_error(ret)) { |
1908 | - tswap32s(&pipe_ptr[0]); | ||
1909 | - tswap32s(&pipe_ptr[1]); | 2119 | + tput32(arg1, host_pipe[0]); |
2120 | + tput32(arg1 + 4, host_pipe[1]); | ||
1910 | } | 2121 | } |
1911 | } | 2122 | } |
1912 | break; | 2123 | break; |
1913 | case TARGET_NR_times: | 2124 | case TARGET_NR_times: |
1914 | { | 2125 | { |
1915 | - struct target_tms *tmsp = (void *)arg1; | 2126 | + struct target_tms *tmsp; |
1916 | struct tms tms; | 2127 | struct tms tms; |
1917 | ret = get_errno(times(&tms)); | 2128 | ret = get_errno(times(&tms)); |
1918 | - if (tmsp) { | 2129 | + if (arg1) { |
2130 | + tmsp = lock_user(arg1, sizeof(struct target_tms), 0); | ||
1919 | tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime)); | 2131 | tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime)); |
1920 | tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime)); | 2132 | tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime)); |
1921 | tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime)); | 2133 | tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime)); |
@@ -1935,7 +2147,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1935,7 +2147,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1935 | case TARGET_NR_acct: | 2147 | case TARGET_NR_acct: |
1936 | goto unimplemented; | 2148 | goto unimplemented; |
1937 | case TARGET_NR_umount2: | 2149 | case TARGET_NR_umount2: |
1938 | - ret = get_errno(umount2((const char *)arg1, arg2)); | 2150 | + p = lock_user_string(arg1); |
2151 | + ret = get_errno(umount2(p, arg2)); | ||
2152 | + unlock_user(p, arg1, 0); | ||
1939 | break; | 2153 | break; |
1940 | #ifdef TARGET_NR_lock | 2154 | #ifdef TARGET_NR_lock |
1941 | case TARGET_NR_lock: | 2155 | case TARGET_NR_lock: |
@@ -1966,7 +2180,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1966,7 +2180,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1966 | ret = get_errno(umask(arg1)); | 2180 | ret = get_errno(umask(arg1)); |
1967 | break; | 2181 | break; |
1968 | case TARGET_NR_chroot: | 2182 | case TARGET_NR_chroot: |
1969 | - ret = get_errno(chroot((const char *)arg1)); | 2183 | + p = lock_user_string(arg1); |
2184 | + ret = get_errno(chroot(p)); | ||
2185 | + unlock_user(p, arg1, 0); | ||
1970 | break; | 2186 | break; |
1971 | case TARGET_NR_ustat: | 2187 | case TARGET_NR_ustat: |
1972 | goto unimplemented; | 2188 | goto unimplemented; |
@@ -1984,29 +2200,49 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -1984,29 +2200,49 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
1984 | break; | 2200 | break; |
1985 | case TARGET_NR_sigaction: | 2201 | case TARGET_NR_sigaction: |
1986 | { | 2202 | { |
1987 | - struct target_old_sigaction *old_act = (void *)arg2; | ||
1988 | - struct target_old_sigaction *old_oact = (void *)arg3; | 2203 | + struct target_old_sigaction *old_act; |
1989 | struct target_sigaction act, oact, *pact; | 2204 | struct target_sigaction act, oact, *pact; |
1990 | - if (old_act) { | 2205 | + if (arg2) { |
2206 | + lock_user_struct(old_act, arg2, 1); | ||
1991 | act._sa_handler = old_act->_sa_handler; | 2207 | act._sa_handler = old_act->_sa_handler; |
1992 | target_siginitset(&act.sa_mask, old_act->sa_mask); | 2208 | target_siginitset(&act.sa_mask, old_act->sa_mask); |
1993 | act.sa_flags = old_act->sa_flags; | 2209 | act.sa_flags = old_act->sa_flags; |
1994 | act.sa_restorer = old_act->sa_restorer; | 2210 | act.sa_restorer = old_act->sa_restorer; |
2211 | + unlock_user_struct(old_act, arg2, 0); | ||
1995 | pact = &act; | 2212 | pact = &act; |
1996 | } else { | 2213 | } else { |
1997 | pact = NULL; | 2214 | pact = NULL; |
1998 | } | 2215 | } |
1999 | ret = get_errno(do_sigaction(arg1, pact, &oact)); | 2216 | ret = get_errno(do_sigaction(arg1, pact, &oact)); |
2000 | - if (!is_error(ret) && old_oact) { | ||
2001 | - old_oact->_sa_handler = oact._sa_handler; | ||
2002 | - old_oact->sa_mask = oact.sa_mask.sig[0]; | ||
2003 | - old_oact->sa_flags = oact.sa_flags; | ||
2004 | - old_oact->sa_restorer = oact.sa_restorer; | 2217 | + if (!is_error(ret) && arg3) { |
2218 | + lock_user_struct(old_act, arg3, 0); | ||
2219 | + old_act->_sa_handler = oact._sa_handler; | ||
2220 | + old_act->sa_mask = oact.sa_mask.sig[0]; | ||
2221 | + old_act->sa_flags = oact.sa_flags; | ||
2222 | + old_act->sa_restorer = oact.sa_restorer; | ||
2223 | + unlock_user_struct(old_act, arg3, 1); | ||
2005 | } | 2224 | } |
2006 | } | 2225 | } |
2007 | break; | 2226 | break; |
2008 | case TARGET_NR_rt_sigaction: | 2227 | case TARGET_NR_rt_sigaction: |
2009 | - ret = get_errno(do_sigaction(arg1, (void *)arg2, (void *)arg3)); | 2228 | + { |
2229 | + struct target_sigaction *act; | ||
2230 | + struct target_sigaction *oact; | ||
2231 | + | ||
2232 | + if (arg2) | ||
2233 | + lock_user_struct(act, arg2, 1); | ||
2234 | + else | ||
2235 | + act = NULL; | ||
2236 | + if (arg3) | ||
2237 | + lock_user_struct(oact, arg3, 0); | ||
2238 | + else | ||
2239 | + oact = NULL; | ||
2240 | + ret = get_errno(do_sigaction(arg1, act, oact)); | ||
2241 | + if (arg2) | ||
2242 | + unlock_user_struct(act, arg2, 0); | ||
2243 | + if (arg3) | ||
2244 | + unlock_user_struct(oact, arg3, 1); | ||
2245 | + } | ||
2010 | break; | 2246 | break; |
2011 | case TARGET_NR_sgetmask: | 2247 | case TARGET_NR_sgetmask: |
2012 | { | 2248 | { |
@@ -2033,9 +2269,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2033,9 +2269,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2033 | { | 2269 | { |
2034 | int how = arg1; | 2270 | int how = arg1; |
2035 | sigset_t set, oldset, *set_ptr; | 2271 | sigset_t set, oldset, *set_ptr; |
2036 | - target_ulong *pset = (void *)arg2, *poldset = (void *)arg3; | ||
2037 | 2272 | ||
2038 | - if (pset) { | 2273 | + if (arg2) { |
2039 | switch(how) { | 2274 | switch(how) { |
2040 | case TARGET_SIG_BLOCK: | 2275 | case TARGET_SIG_BLOCK: |
2041 | how = SIG_BLOCK; | 2276 | how = SIG_BLOCK; |
@@ -2050,15 +2285,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2050,15 +2285,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2050 | ret = -EINVAL; | 2285 | ret = -EINVAL; |
2051 | goto fail; | 2286 | goto fail; |
2052 | } | 2287 | } |
2053 | - target_to_host_old_sigset(&set, pset); | 2288 | + p = lock_user(arg2, sizeof(target_sigset_t), 1); |
2289 | + target_to_host_old_sigset(&set, p); | ||
2290 | + unlock_user(p, arg2, 0); | ||
2054 | set_ptr = &set; | 2291 | set_ptr = &set; |
2055 | } else { | 2292 | } else { |
2056 | how = 0; | 2293 | how = 0; |
2057 | set_ptr = NULL; | 2294 | set_ptr = NULL; |
2058 | } | 2295 | } |
2059 | ret = get_errno(sigprocmask(arg1, set_ptr, &oldset)); | 2296 | ret = get_errno(sigprocmask(arg1, set_ptr, &oldset)); |
2060 | - if (!is_error(ret) && poldset) { | ||
2061 | - host_to_target_old_sigset(poldset, &oldset); | 2297 | + if (!is_error(ret) && arg3) { |
2298 | + p = lock_user(arg3, sizeof(target_sigset_t), 0); | ||
2299 | + host_to_target_old_sigset(p, &oldset); | ||
2300 | + unlock_user(p, arg3, sizeof(target_sigset_t)); | ||
2062 | } | 2301 | } |
2063 | } | 2302 | } |
2064 | break; | 2303 | break; |
@@ -2066,10 +2305,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2066,10 +2305,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2066 | { | 2305 | { |
2067 | int how = arg1; | 2306 | int how = arg1; |
2068 | sigset_t set, oldset, *set_ptr; | 2307 | sigset_t set, oldset, *set_ptr; |
2069 | - target_sigset_t *pset = (void *)arg2; | ||
2070 | - target_sigset_t *poldset = (void *)arg3; | ||
2071 | 2308 | ||
2072 | - if (pset) { | 2309 | + if (arg2) { |
2073 | switch(how) { | 2310 | switch(how) { |
2074 | case TARGET_SIG_BLOCK: | 2311 | case TARGET_SIG_BLOCK: |
2075 | how = SIG_BLOCK; | 2312 | how = SIG_BLOCK; |
@@ -2084,15 +2321,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2084,15 +2321,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2084 | ret = -EINVAL; | 2321 | ret = -EINVAL; |
2085 | goto fail; | 2322 | goto fail; |
2086 | } | 2323 | } |
2087 | - target_to_host_sigset(&set, pset); | 2324 | + p = lock_user(arg2, sizeof(target_sigset_t), 1); |
2325 | + target_to_host_sigset(&set, p); | ||
2326 | + unlock_user(p, arg2, 0); | ||
2088 | set_ptr = &set; | 2327 | set_ptr = &set; |
2089 | } else { | 2328 | } else { |
2090 | how = 0; | 2329 | how = 0; |
2091 | set_ptr = NULL; | 2330 | set_ptr = NULL; |
2092 | } | 2331 | } |
2093 | ret = get_errno(sigprocmask(how, set_ptr, &oldset)); | 2332 | ret = get_errno(sigprocmask(how, set_ptr, &oldset)); |
2094 | - if (!is_error(ret) && poldset) { | ||
2095 | - host_to_target_sigset(poldset, &oldset); | 2333 | + if (!is_error(ret) && arg3) { |
2334 | + p = lock_user(arg3, sizeof(target_sigset_t), 0); | ||
2335 | + host_to_target_sigset(p, &oldset); | ||
2336 | + unlock_user(p, arg3, sizeof(target_sigset_t)); | ||
2096 | } | 2337 | } |
2097 | } | 2338 | } |
2098 | break; | 2339 | break; |
@@ -2101,7 +2342,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2101,7 +2342,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2101 | sigset_t set; | 2342 | sigset_t set; |
2102 | ret = get_errno(sigpending(&set)); | 2343 | ret = get_errno(sigpending(&set)); |
2103 | if (!is_error(ret)) { | 2344 | if (!is_error(ret)) { |
2104 | - host_to_target_old_sigset((target_ulong *)arg1, &set); | 2345 | + p = lock_user(arg1, sizeof(target_sigset_t), 0); |
2346 | + host_to_target_old_sigset(p, &set); | ||
2347 | + unlock_user(p, arg1, sizeof(target_sigset_t)); | ||
2105 | } | 2348 | } |
2106 | } | 2349 | } |
2107 | break; | 2350 | break; |
@@ -2110,51 +2353,59 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2110,51 +2353,59 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2110 | sigset_t set; | 2353 | sigset_t set; |
2111 | ret = get_errno(sigpending(&set)); | 2354 | ret = get_errno(sigpending(&set)); |
2112 | if (!is_error(ret)) { | 2355 | if (!is_error(ret)) { |
2113 | - host_to_target_sigset((target_sigset_t *)arg1, &set); | 2356 | + p = lock_user(arg1, sizeof(target_sigset_t), 0); |
2357 | + host_to_target_sigset(p, &set); | ||
2358 | + unlock_user(p, arg1, sizeof(target_sigset_t)); | ||
2114 | } | 2359 | } |
2115 | } | 2360 | } |
2116 | break; | 2361 | break; |
2117 | case TARGET_NR_sigsuspend: | 2362 | case TARGET_NR_sigsuspend: |
2118 | { | 2363 | { |
2119 | sigset_t set; | 2364 | sigset_t set; |
2120 | - target_to_host_old_sigset(&set, (target_ulong *)arg1); | 2365 | + p = lock_user(arg1, sizeof(target_sigset_t), 1); |
2366 | + target_to_host_old_sigset(&set, p); | ||
2367 | + unlock_user(p, arg1, 0); | ||
2121 | ret = get_errno(sigsuspend(&set)); | 2368 | ret = get_errno(sigsuspend(&set)); |
2122 | } | 2369 | } |
2123 | break; | 2370 | break; |
2124 | case TARGET_NR_rt_sigsuspend: | 2371 | case TARGET_NR_rt_sigsuspend: |
2125 | { | 2372 | { |
2126 | sigset_t set; | 2373 | sigset_t set; |
2127 | - target_to_host_sigset(&set, (target_sigset_t *)arg1); | 2374 | + p = lock_user(arg1, sizeof(target_sigset_t), 1); |
2375 | + target_to_host_sigset(&set, p); | ||
2376 | + unlock_user(p, arg1, 0); | ||
2128 | ret = get_errno(sigsuspend(&set)); | 2377 | ret = get_errno(sigsuspend(&set)); |
2129 | } | 2378 | } |
2130 | break; | 2379 | break; |
2131 | case TARGET_NR_rt_sigtimedwait: | 2380 | case TARGET_NR_rt_sigtimedwait: |
2132 | { | 2381 | { |
2133 | - target_sigset_t *target_set = (void *)arg1; | ||
2134 | - target_siginfo_t *target_uinfo = (void *)arg2; | ||
2135 | - struct target_timespec *target_uts = (void *)arg3; | ||
2136 | sigset_t set; | 2382 | sigset_t set; |
2137 | struct timespec uts, *puts; | 2383 | struct timespec uts, *puts; |
2138 | siginfo_t uinfo; | 2384 | siginfo_t uinfo; |
2139 | 2385 | ||
2140 | - target_to_host_sigset(&set, target_set); | ||
2141 | - if (target_uts) { | 2386 | + p = lock_user(arg1, sizeof(target_sigset_t), 1); |
2387 | + target_to_host_sigset(&set, p); | ||
2388 | + unlock_user(p, arg1, 0); | ||
2389 | + if (arg3) { | ||
2142 | puts = &uts; | 2390 | puts = &uts; |
2143 | - puts->tv_sec = tswapl(target_uts->tv_sec); | ||
2144 | - puts->tv_nsec = tswapl(target_uts->tv_nsec); | 2391 | + target_to_host_timespec(puts, arg3); |
2145 | } else { | 2392 | } else { |
2146 | puts = NULL; | 2393 | puts = NULL; |
2147 | } | 2394 | } |
2148 | ret = get_errno(sigtimedwait(&set, &uinfo, puts)); | 2395 | ret = get_errno(sigtimedwait(&set, &uinfo, puts)); |
2149 | - if (!is_error(ret) && target_uinfo) { | ||
2150 | - host_to_target_siginfo(target_uinfo, &uinfo); | 2396 | + if (!is_error(ret) && arg2) { |
2397 | + p = lock_user(arg2, sizeof(target_sigset_t), 0); | ||
2398 | + host_to_target_siginfo(p, &uinfo); | ||
2399 | + unlock_user(p, arg2, sizeof(target_sigset_t)); | ||
2151 | } | 2400 | } |
2152 | } | 2401 | } |
2153 | break; | 2402 | break; |
2154 | case TARGET_NR_rt_sigqueueinfo: | 2403 | case TARGET_NR_rt_sigqueueinfo: |
2155 | { | 2404 | { |
2156 | siginfo_t uinfo; | 2405 | siginfo_t uinfo; |
2157 | - target_to_host_siginfo(&uinfo, (target_siginfo_t *)arg3); | 2406 | + p = lock_user(arg3, sizeof(target_sigset_t), 1); |
2407 | + target_to_host_siginfo(&uinfo, p); | ||
2408 | + unlock_user(p, arg1, 0); | ||
2158 | ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); | 2409 | ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); |
2159 | } | 2410 | } |
2160 | break; | 2411 | break; |
@@ -2167,16 +2418,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2167,16 +2418,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2167 | ret = do_rt_sigreturn(cpu_env); | 2418 | ret = do_rt_sigreturn(cpu_env); |
2168 | break; | 2419 | break; |
2169 | case TARGET_NR_sethostname: | 2420 | case TARGET_NR_sethostname: |
2170 | - ret = get_errno(sethostname((const char *)arg1, arg2)); | 2421 | + p = lock_user_string(arg1); |
2422 | + ret = get_errno(sethostname(p, arg2)); | ||
2423 | + unlock_user(p, arg1, 0); | ||
2171 | break; | 2424 | break; |
2172 | case TARGET_NR_setrlimit: | 2425 | case TARGET_NR_setrlimit: |
2173 | { | 2426 | { |
2174 | /* XXX: convert resource ? */ | 2427 | /* XXX: convert resource ? */ |
2175 | int resource = arg1; | 2428 | int resource = arg1; |
2176 | - struct target_rlimit *target_rlim = (void *)arg2; | 2429 | + struct target_rlimit *target_rlim; |
2177 | struct rlimit rlim; | 2430 | struct rlimit rlim; |
2431 | + lock_user_struct(target_rlim, arg2, 1); | ||
2178 | rlim.rlim_cur = tswapl(target_rlim->rlim_cur); | 2432 | rlim.rlim_cur = tswapl(target_rlim->rlim_cur); |
2179 | rlim.rlim_max = tswapl(target_rlim->rlim_max); | 2433 | rlim.rlim_max = tswapl(target_rlim->rlim_max); |
2434 | + unlock_user_struct(target_rlim, arg2, 0); | ||
2180 | ret = get_errno(setrlimit(resource, &rlim)); | 2435 | ret = get_errno(setrlimit(resource, &rlim)); |
2181 | } | 2436 | } |
2182 | break; | 2437 | break; |
@@ -2184,72 +2439,91 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2184,72 +2439,91 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2184 | { | 2439 | { |
2185 | /* XXX: convert resource ? */ | 2440 | /* XXX: convert resource ? */ |
2186 | int resource = arg1; | 2441 | int resource = arg1; |
2187 | - struct target_rlimit *target_rlim = (void *)arg2; | 2442 | + struct target_rlimit *target_rlim; |
2188 | struct rlimit rlim; | 2443 | struct rlimit rlim; |
2189 | 2444 | ||
2190 | ret = get_errno(getrlimit(resource, &rlim)); | 2445 | ret = get_errno(getrlimit(resource, &rlim)); |
2191 | if (!is_error(ret)) { | 2446 | if (!is_error(ret)) { |
2192 | - target_rlim->rlim_cur = tswapl(rlim.rlim_cur); | ||
2193 | - target_rlim->rlim_max = tswapl(rlim.rlim_max); | 2447 | + lock_user_struct(target_rlim, arg2, 0); |
2448 | + rlim.rlim_cur = tswapl(target_rlim->rlim_cur); | ||
2449 | + rlim.rlim_max = tswapl(target_rlim->rlim_max); | ||
2450 | + unlock_user_struct(target_rlim, arg2, 1); | ||
2194 | } | 2451 | } |
2195 | } | 2452 | } |
2196 | break; | 2453 | break; |
2197 | case TARGET_NR_getrusage: | 2454 | case TARGET_NR_getrusage: |
2198 | { | 2455 | { |
2199 | struct rusage rusage; | 2456 | struct rusage rusage; |
2200 | - struct target_rusage *target_rusage = (void *)arg2; | ||
2201 | ret = get_errno(getrusage(arg1, &rusage)); | 2457 | ret = get_errno(getrusage(arg1, &rusage)); |
2202 | if (!is_error(ret)) { | 2458 | if (!is_error(ret)) { |
2203 | - host_to_target_rusage(target_rusage, &rusage); | 2459 | + host_to_target_rusage(arg2, &rusage); |
2204 | } | 2460 | } |
2205 | } | 2461 | } |
2206 | break; | 2462 | break; |
2207 | case TARGET_NR_gettimeofday: | 2463 | case TARGET_NR_gettimeofday: |
2208 | { | 2464 | { |
2209 | - struct target_timeval *target_tv = (void *)arg1; | ||
2210 | struct timeval tv; | 2465 | struct timeval tv; |
2211 | ret = get_errno(gettimeofday(&tv, NULL)); | 2466 | ret = get_errno(gettimeofday(&tv, NULL)); |
2212 | if (!is_error(ret)) { | 2467 | if (!is_error(ret)) { |
2213 | - host_to_target_timeval(target_tv, &tv); | 2468 | + host_to_target_timeval(arg1, &tv); |
2214 | } | 2469 | } |
2215 | } | 2470 | } |
2216 | break; | 2471 | break; |
2217 | case TARGET_NR_settimeofday: | 2472 | case TARGET_NR_settimeofday: |
2218 | { | 2473 | { |
2219 | - struct target_timeval *target_tv = (void *)arg1; | ||
2220 | struct timeval tv; | 2474 | struct timeval tv; |
2221 | - target_to_host_timeval(&tv, target_tv); | 2475 | + target_to_host_timeval(&tv, arg1); |
2222 | ret = get_errno(settimeofday(&tv, NULL)); | 2476 | ret = get_errno(settimeofday(&tv, NULL)); |
2223 | } | 2477 | } |
2224 | break; | 2478 | break; |
2225 | #ifdef TARGET_NR_select | 2479 | #ifdef TARGET_NR_select |
2226 | case TARGET_NR_select: | 2480 | case TARGET_NR_select: |
2227 | { | 2481 | { |
2228 | - struct target_sel_arg_struct *sel = (void *)arg1; | ||
2229 | - sel->n = tswapl(sel->n); | ||
2230 | - sel->inp = tswapl(sel->inp); | ||
2231 | - sel->outp = tswapl(sel->outp); | ||
2232 | - sel->exp = tswapl(sel->exp); | ||
2233 | - sel->tvp = tswapl(sel->tvp); | ||
2234 | - ret = do_select(sel->n, (void *)sel->inp, (void *)sel->outp, | ||
2235 | - (void *)sel->exp, (void *)sel->tvp); | 2482 | + struct target_sel_arg_struct *sel; |
2483 | + target_ulong inp, outp, exp, tvp; | ||
2484 | + long nsel; | ||
2485 | + | ||
2486 | + lock_user_struct(sel, arg1, 1); | ||
2487 | + nsel = tswapl(sel->n); | ||
2488 | + inp = tswapl(sel->inp); | ||
2489 | + outp = tswapl(sel->outp); | ||
2490 | + exp = tswapl(sel->exp); | ||
2491 | + tvp = tswapl(sel->tvp); | ||
2492 | + unlock_user_struct(sel, arg1, 0); | ||
2493 | + ret = do_select(nsel, inp, outp, exp, tvp); | ||
2236 | } | 2494 | } |
2237 | break; | 2495 | break; |
2238 | #endif | 2496 | #endif |
2239 | case TARGET_NR_symlink: | 2497 | case TARGET_NR_symlink: |
2240 | - ret = get_errno(symlink((const char *)arg1, (const char *)arg2)); | 2498 | + { |
2499 | + void *p2; | ||
2500 | + p = lock_user_string(arg1); | ||
2501 | + p2 = lock_user_string(arg2); | ||
2502 | + ret = get_errno(symlink(p, p2)); | ||
2503 | + unlock_user(p2, arg2, 0); | ||
2504 | + unlock_user(p, arg1, 0); | ||
2505 | + } | ||
2241 | break; | 2506 | break; |
2242 | #ifdef TARGET_NR_oldlstat | 2507 | #ifdef TARGET_NR_oldlstat |
2243 | case TARGET_NR_oldlstat: | 2508 | case TARGET_NR_oldlstat: |
2244 | goto unimplemented; | 2509 | goto unimplemented; |
2245 | #endif | 2510 | #endif |
2246 | case TARGET_NR_readlink: | 2511 | case TARGET_NR_readlink: |
2247 | - ret = get_errno(readlink(path((const char *)arg1), (char *)arg2, arg3)); | 2512 | + { |
2513 | + void *p2; | ||
2514 | + p = lock_user_string(arg1); | ||
2515 | + p2 = lock_user(arg2, arg3, 0); | ||
2516 | + ret = get_errno(readlink(path(p), p2, arg3)); | ||
2517 | + unlock_user(p2, arg2, ret); | ||
2518 | + unlock_user(p, arg1, 0); | ||
2519 | + } | ||
2248 | break; | 2520 | break; |
2249 | case TARGET_NR_uselib: | 2521 | case TARGET_NR_uselib: |
2250 | goto unimplemented; | 2522 | goto unimplemented; |
2251 | case TARGET_NR_swapon: | 2523 | case TARGET_NR_swapon: |
2252 | - ret = get_errno(swapon((const char *)arg1, arg2)); | 2524 | + p = lock_user_string(arg1); |
2525 | + ret = get_errno(swapon(p, arg2)); | ||
2526 | + unlock_user(p, arg1, 0); | ||
2253 | break; | 2527 | break; |
2254 | case TARGET_NR_reboot: | 2528 | case TARGET_NR_reboot: |
2255 | goto unimplemented; | 2529 | goto unimplemented; |
@@ -2258,14 +2532,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2258,14 +2532,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2258 | case TARGET_NR_mmap: | 2532 | case TARGET_NR_mmap: |
2259 | #if defined(TARGET_I386) || defined(TARGET_ARM) | 2533 | #if defined(TARGET_I386) || defined(TARGET_ARM) |
2260 | { | 2534 | { |
2261 | - uint32_t v1, v2, v3, v4, v5, v6, *vptr; | ||
2262 | - vptr = (uint32_t *)arg1; | ||
2263 | - v1 = tswap32(vptr[0]); | ||
2264 | - v2 = tswap32(vptr[1]); | ||
2265 | - v3 = tswap32(vptr[2]); | ||
2266 | - v4 = tswap32(vptr[3]); | ||
2267 | - v5 = tswap32(vptr[4]); | ||
2268 | - v6 = tswap32(vptr[5]); | 2535 | + target_ulong *v; |
2536 | + target_ulong v1, v2, v3, v4, v5, v6; | ||
2537 | + v = lock_user(arg1, 6 * sizeof(target_ulong), 1); | ||
2538 | + v1 = tswapl(v[0]); | ||
2539 | + v2 = tswapl(v[1]); | ||
2540 | + v3 = tswapl(v[2]); | ||
2541 | + v4 = tswapl(v[3]); | ||
2542 | + v5 = tswapl(v[4]); | ||
2543 | + v6 = tswapl(v[5]); | ||
2544 | + unlock_user(v, arg1, 0); | ||
2269 | ret = get_errno(target_mmap(v1, v2, v3, | 2545 | ret = get_errno(target_mmap(v1, v2, v3, |
2270 | target_to_host_bitmask(v4, mmap_flags_tbl), | 2546 | target_to_host_bitmask(v4, mmap_flags_tbl), |
2271 | v5, v6)); | 2547 | v5, v6)); |
@@ -2299,14 +2575,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2299,14 +2575,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2299 | case TARGET_NR_mremap: | 2575 | case TARGET_NR_mremap: |
2300 | ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); | 2576 | ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); |
2301 | break; | 2577 | break; |
2578 | + /* ??? msync/mlock/munlock are broken for softmmu. */ | ||
2302 | case TARGET_NR_msync: | 2579 | case TARGET_NR_msync: |
2303 | - ret = get_errno(msync((void *)arg1, arg2, arg3)); | 2580 | + ret = get_errno(msync(g2h(arg1), arg2, arg3)); |
2304 | break; | 2581 | break; |
2305 | case TARGET_NR_mlock: | 2582 | case TARGET_NR_mlock: |
2306 | - ret = get_errno(mlock((void *)arg1, arg2)); | 2583 | + ret = get_errno(mlock(g2h(arg1), arg2)); |
2307 | break; | 2584 | break; |
2308 | case TARGET_NR_munlock: | 2585 | case TARGET_NR_munlock: |
2309 | - ret = get_errno(munlock((void *)arg1, arg2)); | 2586 | + ret = get_errno(munlock(g2h(arg1), arg2)); |
2310 | break; | 2587 | break; |
2311 | case TARGET_NR_mlockall: | 2588 | case TARGET_NR_mlockall: |
2312 | ret = get_errno(mlockall(arg1)); | 2589 | ret = get_errno(mlockall(arg1)); |
@@ -2315,7 +2592,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2315,7 +2592,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2315 | ret = get_errno(munlockall()); | 2592 | ret = get_errno(munlockall()); |
2316 | break; | 2593 | break; |
2317 | case TARGET_NR_truncate: | 2594 | case TARGET_NR_truncate: |
2318 | - ret = get_errno(truncate((const char *)arg1, arg2)); | 2595 | + p = lock_user_string(arg1); |
2596 | + ret = get_errno(truncate(p, arg2)); | ||
2597 | + unlock_user(p, arg1, 0); | ||
2319 | break; | 2598 | break; |
2320 | case TARGET_NR_ftruncate: | 2599 | case TARGET_NR_ftruncate: |
2321 | ret = get_errno(ftruncate(arg1, arg2)); | 2600 | ret = get_errno(ftruncate(arg1, arg2)); |
@@ -2334,11 +2613,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2334,11 +2613,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2334 | goto unimplemented; | 2613 | goto unimplemented; |
2335 | #endif | 2614 | #endif |
2336 | case TARGET_NR_statfs: | 2615 | case TARGET_NR_statfs: |
2337 | - ret = get_errno(statfs(path((const char *)arg1), &stfs)); | 2616 | + p = lock_user_string(arg1); |
2617 | + ret = get_errno(statfs(path(p), &stfs)); | ||
2618 | + unlock_user(p, arg1, 0); | ||
2338 | convert_statfs: | 2619 | convert_statfs: |
2339 | if (!is_error(ret)) { | 2620 | if (!is_error(ret)) { |
2340 | - struct target_statfs *target_stfs = (void *)arg2; | 2621 | + struct target_statfs *target_stfs; |
2341 | 2622 | ||
2623 | + lock_user_struct(target_stfs, arg2, 0); | ||
2624 | + /* ??? put_user is probably wrong. */ | ||
2342 | put_user(stfs.f_type, &target_stfs->f_type); | 2625 | put_user(stfs.f_type, &target_stfs->f_type); |
2343 | put_user(stfs.f_bsize, &target_stfs->f_bsize); | 2626 | put_user(stfs.f_bsize, &target_stfs->f_bsize); |
2344 | put_user(stfs.f_blocks, &target_stfs->f_blocks); | 2627 | put_user(stfs.f_blocks, &target_stfs->f_blocks); |
@@ -2348,6 +2631,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2348,6 +2631,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2348 | put_user(stfs.f_ffree, &target_stfs->f_ffree); | 2631 | put_user(stfs.f_ffree, &target_stfs->f_ffree); |
2349 | put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid); | 2632 | put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid); |
2350 | put_user(stfs.f_namelen, &target_stfs->f_namelen); | 2633 | put_user(stfs.f_namelen, &target_stfs->f_namelen); |
2634 | + unlock_user_struct(target_stfs, arg2, 1); | ||
2351 | } | 2635 | } |
2352 | break; | 2636 | break; |
2353 | case TARGET_NR_fstatfs: | 2637 | case TARGET_NR_fstatfs: |
@@ -2355,11 +2639,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2355,11 +2639,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2355 | goto convert_statfs; | 2639 | goto convert_statfs; |
2356 | #ifdef TARGET_NR_statfs64 | 2640 | #ifdef TARGET_NR_statfs64 |
2357 | case TARGET_NR_statfs64: | 2641 | case TARGET_NR_statfs64: |
2358 | - ret = get_errno(statfs(path((const char *)arg1), &stfs)); | 2642 | + p = lock_user_string(arg1); |
2643 | + ret = get_errno(statfs(path(p), &stfs)); | ||
2644 | + unlock_user(p, arg1, 0); | ||
2359 | convert_statfs64: | 2645 | convert_statfs64: |
2360 | if (!is_error(ret)) { | 2646 | if (!is_error(ret)) { |
2361 | - struct target_statfs64 *target_stfs = (void *)arg3; | ||
2362 | - | 2647 | + struct target_statfs64 *target_stfs; |
2648 | + | ||
2649 | + lock_user_struct(target_stfs, arg3, 0); | ||
2650 | + /* ??? put_user is probably wrong. */ | ||
2363 | put_user(stfs.f_type, &target_stfs->f_type); | 2651 | put_user(stfs.f_type, &target_stfs->f_type); |
2364 | put_user(stfs.f_bsize, &target_stfs->f_bsize); | 2652 | put_user(stfs.f_bsize, &target_stfs->f_bsize); |
2365 | put_user(stfs.f_blocks, &target_stfs->f_blocks); | 2653 | put_user(stfs.f_blocks, &target_stfs->f_blocks); |
@@ -2369,6 +2657,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2369,6 +2657,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2369 | put_user(stfs.f_ffree, &target_stfs->f_ffree); | 2657 | put_user(stfs.f_ffree, &target_stfs->f_ffree); |
2370 | put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid); | 2658 | put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid); |
2371 | put_user(stfs.f_namelen, &target_stfs->f_namelen); | 2659 | put_user(stfs.f_namelen, &target_stfs->f_namelen); |
2660 | + unlock_user_struct(target_stfs, arg3, 0); | ||
2372 | } | 2661 | } |
2373 | break; | 2662 | break; |
2374 | case TARGET_NR_fstatfs64: | 2663 | case TARGET_NR_fstatfs64: |
@@ -2380,60 +2669,63 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2380,60 +2669,63 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2380 | goto unimplemented; | 2669 | goto unimplemented; |
2381 | #endif | 2670 | #endif |
2382 | case TARGET_NR_socketcall: | 2671 | case TARGET_NR_socketcall: |
2383 | - ret = do_socketcall(arg1, (int32_t *)arg2); | 2672 | + ret = do_socketcall(arg1, arg2); |
2384 | break; | 2673 | break; |
2385 | case TARGET_NR_syslog: | 2674 | case TARGET_NR_syslog: |
2386 | goto unimplemented; | 2675 | goto unimplemented; |
2387 | case TARGET_NR_setitimer: | 2676 | case TARGET_NR_setitimer: |
2388 | { | 2677 | { |
2389 | - struct target_itimerval *target_value = (void *)arg2; | ||
2390 | - struct target_itimerval *target_ovalue = (void *)arg3; | ||
2391 | struct itimerval value, ovalue, *pvalue; | 2678 | struct itimerval value, ovalue, *pvalue; |
2392 | 2679 | ||
2393 | - if (target_value) { | 2680 | + if (arg2) { |
2394 | pvalue = &value; | 2681 | pvalue = &value; |
2395 | target_to_host_timeval(&pvalue->it_interval, | 2682 | target_to_host_timeval(&pvalue->it_interval, |
2396 | - &target_value->it_interval); | 2683 | + arg2); |
2397 | target_to_host_timeval(&pvalue->it_value, | 2684 | target_to_host_timeval(&pvalue->it_value, |
2398 | - &target_value->it_value); | 2685 | + arg2 + sizeof(struct target_timeval)); |
2399 | } else { | 2686 | } else { |
2400 | pvalue = NULL; | 2687 | pvalue = NULL; |
2401 | } | 2688 | } |
2402 | ret = get_errno(setitimer(arg1, pvalue, &ovalue)); | 2689 | ret = get_errno(setitimer(arg1, pvalue, &ovalue)); |
2403 | - if (!is_error(ret) && target_ovalue) { | ||
2404 | - host_to_target_timeval(&target_ovalue->it_interval, | 2690 | + if (!is_error(ret) && arg3) { |
2691 | + host_to_target_timeval(arg3, | ||
2405 | &ovalue.it_interval); | 2692 | &ovalue.it_interval); |
2406 | - host_to_target_timeval(&target_ovalue->it_value, | 2693 | + host_to_target_timeval(arg3 + sizeof(struct target_timeval), |
2407 | &ovalue.it_value); | 2694 | &ovalue.it_value); |
2408 | } | 2695 | } |
2409 | } | 2696 | } |
2410 | break; | 2697 | break; |
2411 | case TARGET_NR_getitimer: | 2698 | case TARGET_NR_getitimer: |
2412 | { | 2699 | { |
2413 | - struct target_itimerval *target_value = (void *)arg2; | ||
2414 | struct itimerval value; | 2700 | struct itimerval value; |
2415 | 2701 | ||
2416 | ret = get_errno(getitimer(arg1, &value)); | 2702 | ret = get_errno(getitimer(arg1, &value)); |
2417 | - if (!is_error(ret) && target_value) { | ||
2418 | - host_to_target_timeval(&target_value->it_interval, | 2703 | + if (!is_error(ret) && arg2) { |
2704 | + host_to_target_timeval(arg2, | ||
2419 | &value.it_interval); | 2705 | &value.it_interval); |
2420 | - host_to_target_timeval(&target_value->it_value, | 2706 | + host_to_target_timeval(arg2 + sizeof(struct target_timeval), |
2421 | &value.it_value); | 2707 | &value.it_value); |
2422 | } | 2708 | } |
2423 | } | 2709 | } |
2424 | break; | 2710 | break; |
2425 | case TARGET_NR_stat: | 2711 | case TARGET_NR_stat: |
2426 | - ret = get_errno(stat(path((const char *)arg1), &st)); | 2712 | + p = lock_user_string(arg1); |
2713 | + ret = get_errno(stat(path(p), &st)); | ||
2714 | + unlock_user(p, arg1, 0); | ||
2427 | goto do_stat; | 2715 | goto do_stat; |
2428 | case TARGET_NR_lstat: | 2716 | case TARGET_NR_lstat: |
2429 | - ret = get_errno(lstat(path((const char *)arg1), &st)); | 2717 | + p = lock_user_string(arg1); |
2718 | + ret = get_errno(lstat(path(p), &st)); | ||
2719 | + unlock_user(p, arg1, 0); | ||
2430 | goto do_stat; | 2720 | goto do_stat; |
2431 | case TARGET_NR_fstat: | 2721 | case TARGET_NR_fstat: |
2432 | { | 2722 | { |
2433 | ret = get_errno(fstat(arg1, &st)); | 2723 | ret = get_errno(fstat(arg1, &st)); |
2434 | do_stat: | 2724 | do_stat: |
2435 | if (!is_error(ret)) { | 2725 | if (!is_error(ret)) { |
2436 | - struct target_stat *target_st = (void *)arg2; | 2726 | + struct target_stat *target_st; |
2727 | + | ||
2728 | + lock_user_struct(target_st, arg2, 0); | ||
2437 | target_st->st_dev = tswap16(st.st_dev); | 2729 | target_st->st_dev = tswap16(st.st_dev); |
2438 | target_st->st_ino = tswapl(st.st_ino); | 2730 | target_st->st_ino = tswapl(st.st_ino); |
2439 | #if defined(TARGET_PPC) | 2731 | #if defined(TARGET_PPC) |
@@ -2453,6 +2745,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2453,6 +2745,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2453 | target_st->target_st_atime = tswapl(st.st_atime); | 2745 | target_st->target_st_atime = tswapl(st.st_atime); |
2454 | target_st->target_st_mtime = tswapl(st.st_mtime); | 2746 | target_st->target_st_mtime = tswapl(st.st_mtime); |
2455 | target_st->target_st_ctime = tswapl(st.st_ctime); | 2747 | target_st->target_st_ctime = tswapl(st.st_ctime); |
2748 | + unlock_user_struct(target_st, arg2, 1); | ||
2456 | } | 2749 | } |
2457 | } | 2750 | } |
2458 | break; | 2751 | break; |
@@ -2479,9 +2772,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2479,9 +2772,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2479 | case TARGET_NR_wait4: | 2772 | case TARGET_NR_wait4: |
2480 | { | 2773 | { |
2481 | int status; | 2774 | int status; |
2482 | - target_long *status_ptr = (void *)arg2; | 2775 | + target_long status_ptr = arg2; |
2483 | struct rusage rusage, *rusage_ptr; | 2776 | struct rusage rusage, *rusage_ptr; |
2484 | - struct target_rusage *target_rusage = (void *)arg4; | 2777 | + target_ulong target_rusage = arg4; |
2485 | if (target_rusage) | 2778 | if (target_rusage) |
2486 | rusage_ptr = &rusage; | 2779 | rusage_ptr = &rusage; |
2487 | else | 2780 | else |
@@ -2489,7 +2782,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2489,7 +2782,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2489 | ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr)); | 2782 | ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr)); |
2490 | if (!is_error(ret)) { | 2783 | if (!is_error(ret)) { |
2491 | if (status_ptr) | 2784 | if (status_ptr) |
2492 | - *status_ptr = tswap32(status); | 2785 | + tputl(status_ptr, status); |
2493 | if (target_rusage) { | 2786 | if (target_rusage) { |
2494 | host_to_target_rusage(target_rusage, &rusage); | 2787 | host_to_target_rusage(target_rusage, &rusage); |
2495 | } | 2788 | } |
@@ -2497,15 +2790,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2497,15 +2790,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2497 | } | 2790 | } |
2498 | break; | 2791 | break; |
2499 | case TARGET_NR_swapoff: | 2792 | case TARGET_NR_swapoff: |
2500 | - ret = get_errno(swapoff((const char *)arg1)); | 2793 | + p = lock_user_string(arg1); |
2794 | + ret = get_errno(swapoff(p)); | ||
2795 | + unlock_user(p, arg1, 0); | ||
2501 | break; | 2796 | break; |
2502 | case TARGET_NR_sysinfo: | 2797 | case TARGET_NR_sysinfo: |
2503 | { | 2798 | { |
2504 | - struct target_sysinfo *target_value = (void *)arg1; | 2799 | + struct target_sysinfo *target_value; |
2505 | struct sysinfo value; | 2800 | struct sysinfo value; |
2506 | ret = get_errno(sysinfo(&value)); | 2801 | ret = get_errno(sysinfo(&value)); |
2507 | - if (!is_error(ret) && target_value) | 2802 | + if (!is_error(ret) && arg1) |
2508 | { | 2803 | { |
2804 | + /* ??? __put_user is probably wrong. */ | ||
2805 | + lock_user_struct(target_value, arg1, 0); | ||
2509 | __put_user(value.uptime, &target_value->uptime); | 2806 | __put_user(value.uptime, &target_value->uptime); |
2510 | __put_user(value.loads[0], &target_value->loads[0]); | 2807 | __put_user(value.loads[0], &target_value->loads[0]); |
2511 | __put_user(value.loads[1], &target_value->loads[1]); | 2808 | __put_user(value.loads[1], &target_value->loads[1]); |
@@ -2520,6 +2817,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2520,6 +2817,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2520 | __put_user(value.totalhigh, &target_value->totalhigh); | 2817 | __put_user(value.totalhigh, &target_value->totalhigh); |
2521 | __put_user(value.freehigh, &target_value->freehigh); | 2818 | __put_user(value.freehigh, &target_value->freehigh); |
2522 | __put_user(value.mem_unit, &target_value->mem_unit); | 2819 | __put_user(value.mem_unit, &target_value->mem_unit); |
2820 | + unlock_user_struct(target_value, arg1, 1); | ||
2523 | } | 2821 | } |
2524 | } | 2822 | } |
2525 | break; | 2823 | break; |
@@ -2540,30 +2838,33 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2540,30 +2838,33 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2540 | break; | 2838 | break; |
2541 | #endif | 2839 | #endif |
2542 | case TARGET_NR_setdomainname: | 2840 | case TARGET_NR_setdomainname: |
2543 | - ret = get_errno(setdomainname((const char *)arg1, arg2)); | 2841 | + p = lock_user_string(arg1); |
2842 | + ret = get_errno(setdomainname(p, arg2)); | ||
2843 | + unlock_user(p, arg1, 0); | ||
2544 | break; | 2844 | break; |
2545 | case TARGET_NR_uname: | 2845 | case TARGET_NR_uname: |
2546 | /* no need to transcode because we use the linux syscall */ | 2846 | /* no need to transcode because we use the linux syscall */ |
2547 | { | 2847 | { |
2548 | struct new_utsname * buf; | 2848 | struct new_utsname * buf; |
2549 | 2849 | ||
2550 | - buf = (struct new_utsname *)arg1; | 2850 | + lock_user_struct(buf, arg1, 0); |
2551 | ret = get_errno(sys_uname(buf)); | 2851 | ret = get_errno(sys_uname(buf)); |
2552 | if (!is_error(ret)) { | 2852 | if (!is_error(ret)) { |
2553 | /* Overrite the native machine name with whatever is being | 2853 | /* Overrite the native machine name with whatever is being |
2554 | emulated. */ | 2854 | emulated. */ |
2555 | strcpy (buf->machine, UNAME_MACHINE); | 2855 | strcpy (buf->machine, UNAME_MACHINE); |
2556 | } | 2856 | } |
2857 | + unlock_user_struct(buf, arg1, 1); | ||
2557 | } | 2858 | } |
2558 | break; | 2859 | break; |
2559 | #ifdef TARGET_I386 | 2860 | #ifdef TARGET_I386 |
2560 | case TARGET_NR_modify_ldt: | 2861 | case TARGET_NR_modify_ldt: |
2561 | - ret = get_errno(do_modify_ldt(cpu_env, arg1, (void *)arg2, arg3)); | 2862 | + ret = get_errno(do_modify_ldt(cpu_env, arg1, arg2, arg3)); |
2562 | break; | 2863 | break; |
2563 | case TARGET_NR_vm86old: | 2864 | case TARGET_NR_vm86old: |
2564 | goto unimplemented; | 2865 | goto unimplemented; |
2565 | case TARGET_NR_vm86: | 2866 | case TARGET_NR_vm86: |
2566 | - ret = do_vm86(cpu_env, arg1, (void *)arg2); | 2867 | + ret = do_vm86(cpu_env, arg1, arg2); |
2567 | break; | 2868 | break; |
2568 | #endif | 2869 | #endif |
2569 | case TARGET_NR_adjtimex: | 2870 | case TARGET_NR_adjtimex: |
@@ -2594,20 +2895,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2594,20 +2895,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2594 | { | 2895 | { |
2595 | #if defined (__x86_64__) | 2896 | #if defined (__x86_64__) |
2596 | ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5)); | 2897 | ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5)); |
2597 | - *(int64_t *)arg4 = ret; | 2898 | + tput64(arg4, ret); |
2598 | #else | 2899 | #else |
2599 | int64_t res; | 2900 | int64_t res; |
2600 | ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5)); | 2901 | ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5)); |
2601 | - *(int64_t *)arg4 = tswap64(res); | 2902 | + tput64(arg4, res); |
2602 | #endif | 2903 | #endif |
2603 | } | 2904 | } |
2604 | break; | 2905 | break; |
2605 | case TARGET_NR_getdents: | 2906 | case TARGET_NR_getdents: |
2606 | #if TARGET_LONG_SIZE != 4 | 2907 | #if TARGET_LONG_SIZE != 4 |
2908 | + goto unimplemented; | ||
2607 | #warning not supported | 2909 | #warning not supported |
2608 | #elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8 | 2910 | #elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8 |
2609 | { | 2911 | { |
2610 | - struct target_dirent *target_dirp = (void *)arg2; | 2912 | + struct target_dirent *target_dirp; |
2611 | struct dirent *dirp; | 2913 | struct dirent *dirp; |
2612 | long count = arg3; | 2914 | long count = arg3; |
2613 | 2915 | ||
@@ -2625,6 +2927,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2625,6 +2927,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2625 | 2927 | ||
2626 | count1 = 0; | 2928 | count1 = 0; |
2627 | de = dirp; | 2929 | de = dirp; |
2930 | + target_dirp = lock_user(arg2, count, 0); | ||
2628 | tde = target_dirp; | 2931 | tde = target_dirp; |
2629 | while (len > 0) { | 2932 | while (len > 0) { |
2630 | reclen = de->d_reclen; | 2933 | reclen = de->d_reclen; |
@@ -2644,13 +2947,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2644,13 +2947,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2644 | } | 2947 | } |
2645 | ret = count1; | 2948 | ret = count1; |
2646 | } | 2949 | } |
2950 | + unlock_user(target_dirp, arg2, ret); | ||
2647 | free(dirp); | 2951 | free(dirp); |
2648 | } | 2952 | } |
2649 | #else | 2953 | #else |
2650 | { | 2954 | { |
2651 | - struct dirent *dirp = (void *)arg2; | 2955 | + struct dirent *dirp; |
2652 | long count = arg3; | 2956 | long count = arg3; |
2653 | 2957 | ||
2958 | + dirp = lock_user(arg2, count, 0); | ||
2654 | ret = get_errno(sys_getdents(arg1, dirp, count)); | 2959 | ret = get_errno(sys_getdents(arg1, dirp, count)); |
2655 | if (!is_error(ret)) { | 2960 | if (!is_error(ret)) { |
2656 | struct dirent *de; | 2961 | struct dirent *de; |
@@ -2668,14 +2973,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2668,14 +2973,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2668 | len -= reclen; | 2973 | len -= reclen; |
2669 | } | 2974 | } |
2670 | } | 2975 | } |
2976 | + unlock_user(dirp, arg2, ret); | ||
2671 | } | 2977 | } |
2672 | #endif | 2978 | #endif |
2673 | break; | 2979 | break; |
2674 | #ifdef TARGET_NR_getdents64 | 2980 | #ifdef TARGET_NR_getdents64 |
2675 | case TARGET_NR_getdents64: | 2981 | case TARGET_NR_getdents64: |
2676 | { | 2982 | { |
2677 | - struct dirent64 *dirp = (void *)arg2; | 2983 | + struct dirent64 *dirp; |
2678 | long count = arg3; | 2984 | long count = arg3; |
2985 | + dirp = lock_user(arg2, count, 0); | ||
2679 | ret = get_errno(sys_getdents64(arg1, dirp, count)); | 2986 | ret = get_errno(sys_getdents64(arg1, dirp, count)); |
2680 | if (!is_error(ret)) { | 2987 | if (!is_error(ret)) { |
2681 | struct dirent64 *de; | 2988 | struct dirent64 *de; |
@@ -2693,21 +3000,22 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2693,21 +3000,22 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2693 | len -= reclen; | 3000 | len -= reclen; |
2694 | } | 3001 | } |
2695 | } | 3002 | } |
3003 | + unlock_user(dirp, arg2, ret); | ||
2696 | } | 3004 | } |
2697 | break; | 3005 | break; |
2698 | #endif /* TARGET_NR_getdents64 */ | 3006 | #endif /* TARGET_NR_getdents64 */ |
2699 | case TARGET_NR__newselect: | 3007 | case TARGET_NR__newselect: |
2700 | - ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, | ||
2701 | - (void *)arg5); | 3008 | + ret = do_select(arg1, arg2, arg3, arg4, arg5); |
2702 | break; | 3009 | break; |
2703 | case TARGET_NR_poll: | 3010 | case TARGET_NR_poll: |
2704 | { | 3011 | { |
2705 | - struct target_pollfd *target_pfd = (void *)arg1; | 3012 | + struct target_pollfd *target_pfd; |
2706 | unsigned int nfds = arg2; | 3013 | unsigned int nfds = arg2; |
2707 | int timeout = arg3; | 3014 | int timeout = arg3; |
2708 | struct pollfd *pfd; | 3015 | struct pollfd *pfd; |
2709 | unsigned int i; | 3016 | unsigned int i; |
2710 | 3017 | ||
3018 | + target_pfd = lock_user(arg1, sizeof(struct target_pollfd) * nfds, 1); | ||
2711 | pfd = alloca(sizeof(struct pollfd) * nfds); | 3019 | pfd = alloca(sizeof(struct pollfd) * nfds); |
2712 | for(i = 0; i < nfds; i++) { | 3020 | for(i = 0; i < nfds; i++) { |
2713 | pfd[i].fd = tswap32(target_pfd[i].fd); | 3021 | pfd[i].fd = tswap32(target_pfd[i].fd); |
@@ -2718,7 +3026,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2718,7 +3026,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2718 | for(i = 0; i < nfds; i++) { | 3026 | for(i = 0; i < nfds; i++) { |
2719 | target_pfd[i].revents = tswap16(pfd[i].revents); | 3027 | target_pfd[i].revents = tswap16(pfd[i].revents); |
2720 | } | 3028 | } |
3029 | + ret += nfds * (sizeof(struct target_pollfd) | ||
3030 | + - sizeof(struct pollfd)); | ||
2721 | } | 3031 | } |
3032 | + unlock_user(target_pfd, arg1, ret); | ||
2722 | } | 3033 | } |
2723 | break; | 3034 | break; |
2724 | case TARGET_NR_flock: | 3035 | case TARGET_NR_flock: |
@@ -2729,31 +3040,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2729,31 +3040,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2729 | case TARGET_NR_readv: | 3040 | case TARGET_NR_readv: |
2730 | { | 3041 | { |
2731 | int count = arg3; | 3042 | int count = arg3; |
2732 | - int i; | ||
2733 | struct iovec *vec; | 3043 | struct iovec *vec; |
2734 | - struct target_iovec *target_vec = (void *)arg2; | ||
2735 | 3044 | ||
2736 | vec = alloca(count * sizeof(struct iovec)); | 3045 | vec = alloca(count * sizeof(struct iovec)); |
2737 | - for(i = 0;i < count; i++) { | ||
2738 | - vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base); | ||
2739 | - vec[i].iov_len = tswapl(target_vec[i].iov_len); | ||
2740 | - } | 3046 | + lock_iovec(vec, arg2, count, 0); |
2741 | ret = get_errno(readv(arg1, vec, count)); | 3047 | ret = get_errno(readv(arg1, vec, count)); |
3048 | + unlock_iovec(vec, arg2, count, 1); | ||
2742 | } | 3049 | } |
2743 | break; | 3050 | break; |
2744 | case TARGET_NR_writev: | 3051 | case TARGET_NR_writev: |
2745 | { | 3052 | { |
2746 | int count = arg3; | 3053 | int count = arg3; |
2747 | - int i; | ||
2748 | struct iovec *vec; | 3054 | struct iovec *vec; |
2749 | - struct target_iovec *target_vec = (void *)arg2; | ||
2750 | 3055 | ||
2751 | vec = alloca(count * sizeof(struct iovec)); | 3056 | vec = alloca(count * sizeof(struct iovec)); |
2752 | - for(i = 0;i < count; i++) { | ||
2753 | - vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base); | ||
2754 | - vec[i].iov_len = tswapl(target_vec[i].iov_len); | ||
2755 | - } | 3057 | + lock_iovec(vec, arg2, count, 1); |
2756 | ret = get_errno(writev(arg1, vec, count)); | 3058 | ret = get_errno(writev(arg1, vec, count)); |
3059 | + unlock_iovec(vec, arg2, count, 0); | ||
2757 | } | 3060 | } |
2758 | break; | 3061 | break; |
2759 | case TARGET_NR_getsid: | 3062 | case TARGET_NR_getsid: |
@@ -2768,27 +3071,34 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2768,27 +3071,34 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2768 | return -ENOTDIR; | 3071 | return -ENOTDIR; |
2769 | case TARGET_NR_sched_setparam: | 3072 | case TARGET_NR_sched_setparam: |
2770 | { | 3073 | { |
2771 | - struct sched_param *target_schp = (void *)arg2; | 3074 | + struct sched_param *target_schp; |
2772 | struct sched_param schp; | 3075 | struct sched_param schp; |
3076 | + | ||
3077 | + lock_user_struct(target_schp, arg2, 1); | ||
2773 | schp.sched_priority = tswap32(target_schp->sched_priority); | 3078 | schp.sched_priority = tswap32(target_schp->sched_priority); |
3079 | + unlock_user_struct(target_schp, arg2, 0); | ||
2774 | ret = get_errno(sched_setparam(arg1, &schp)); | 3080 | ret = get_errno(sched_setparam(arg1, &schp)); |
2775 | } | 3081 | } |
2776 | break; | 3082 | break; |
2777 | case TARGET_NR_sched_getparam: | 3083 | case TARGET_NR_sched_getparam: |
2778 | { | 3084 | { |
2779 | - struct sched_param *target_schp = (void *)arg2; | 3085 | + struct sched_param *target_schp; |
2780 | struct sched_param schp; | 3086 | struct sched_param schp; |
2781 | ret = get_errno(sched_getparam(arg1, &schp)); | 3087 | ret = get_errno(sched_getparam(arg1, &schp)); |
2782 | if (!is_error(ret)) { | 3088 | if (!is_error(ret)) { |
3089 | + lock_user_struct(target_schp, arg2, 0); | ||
2783 | target_schp->sched_priority = tswap32(schp.sched_priority); | 3090 | target_schp->sched_priority = tswap32(schp.sched_priority); |
3091 | + unlock_user_struct(target_schp, arg2, 1); | ||
2784 | } | 3092 | } |
2785 | } | 3093 | } |
2786 | break; | 3094 | break; |
2787 | case TARGET_NR_sched_setscheduler: | 3095 | case TARGET_NR_sched_setscheduler: |
2788 | { | 3096 | { |
2789 | - struct sched_param *target_schp = (void *)arg3; | 3097 | + struct sched_param *target_schp; |
2790 | struct sched_param schp; | 3098 | struct sched_param schp; |
3099 | + lock_user_struct(target_schp, arg3, 1); | ||
2791 | schp.sched_priority = tswap32(target_schp->sched_priority); | 3100 | schp.sched_priority = tswap32(target_schp->sched_priority); |
3101 | + unlock_user_struct(target_schp, arg3, 0); | ||
2792 | ret = get_errno(sched_setscheduler(arg1, arg2, &schp)); | 3102 | ret = get_errno(sched_setscheduler(arg1, arg2, &schp)); |
2793 | } | 3103 | } |
2794 | break; | 3104 | break; |
@@ -2806,26 +3116,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2806,26 +3116,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2806 | break; | 3116 | break; |
2807 | case TARGET_NR_sched_rr_get_interval: | 3117 | case TARGET_NR_sched_rr_get_interval: |
2808 | { | 3118 | { |
2809 | - struct target_timespec *target_ts = (void *)arg2; | ||
2810 | struct timespec ts; | 3119 | struct timespec ts; |
2811 | ret = get_errno(sched_rr_get_interval(arg1, &ts)); | 3120 | ret = get_errno(sched_rr_get_interval(arg1, &ts)); |
2812 | if (!is_error(ret)) { | 3121 | if (!is_error(ret)) { |
2813 | - target_ts->tv_sec = tswapl(ts.tv_sec); | ||
2814 | - target_ts->tv_nsec = tswapl(ts.tv_nsec); | 3122 | + host_to_target_timespec(arg2, &ts); |
2815 | } | 3123 | } |
2816 | } | 3124 | } |
2817 | break; | 3125 | break; |
2818 | case TARGET_NR_nanosleep: | 3126 | case TARGET_NR_nanosleep: |
2819 | { | 3127 | { |
2820 | - struct target_timespec *target_req = (void *)arg1; | ||
2821 | - struct target_timespec *target_rem = (void *)arg2; | ||
2822 | struct timespec req, rem; | 3128 | struct timespec req, rem; |
2823 | - req.tv_sec = tswapl(target_req->tv_sec); | ||
2824 | - req.tv_nsec = tswapl(target_req->tv_nsec); | 3129 | + target_to_host_timespec(&req, arg1); |
2825 | ret = get_errno(nanosleep(&req, &rem)); | 3130 | ret = get_errno(nanosleep(&req, &rem)); |
2826 | - if (is_error(ret) && target_rem) { | ||
2827 | - target_rem->tv_sec = tswapl(rem.tv_sec); | ||
2828 | - target_rem->tv_nsec = tswapl(rem.tv_nsec); | 3131 | + if (is_error(ret) && arg2) { |
3132 | + host_to_target_timespec(arg2, &rem); | ||
2829 | } | 3133 | } |
2830 | } | 3134 | } |
2831 | break; | 3135 | break; |
@@ -2837,15 +3141,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2837,15 +3141,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2837 | goto unimplemented; | 3141 | goto unimplemented; |
2838 | #ifdef TARGET_NR_pread | 3142 | #ifdef TARGET_NR_pread |
2839 | case TARGET_NR_pread: | 3143 | case TARGET_NR_pread: |
2840 | - page_unprotect_range((void *)arg2, arg3); | ||
2841 | - ret = get_errno(pread(arg1, (void *)arg2, arg3, arg4)); | 3144 | + page_unprotect_range(arg2, arg3); |
3145 | + p = lock_user(arg2, arg3, 0); | ||
3146 | + ret = get_errno(pread(arg1, p, arg3, arg4)); | ||
3147 | + unlock_user(p, arg2, ret); | ||
2842 | break; | 3148 | break; |
2843 | case TARGET_NR_pwrite: | 3149 | case TARGET_NR_pwrite: |
2844 | - ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4)); | 3150 | + p = lock_user(arg2, arg3, 1); |
3151 | + ret = get_errno(pwrite(arg1, p, arg3, arg4)); | ||
3152 | + unlock_user(p, arg2, 0); | ||
2845 | break; | 3153 | break; |
2846 | #endif | 3154 | #endif |
2847 | case TARGET_NR_getcwd: | 3155 | case TARGET_NR_getcwd: |
2848 | - ret = get_errno(sys_getcwd1((char *)arg1, arg2)); | 3156 | + p = lock_user(arg1, arg2, 0); |
3157 | + ret = get_errno(sys_getcwd1(p, arg2)); | ||
3158 | + unlock_user(p, arg1, ret); | ||
2849 | break; | 3159 | break; |
2850 | case TARGET_NR_capget: | 3160 | case TARGET_NR_capget: |
2851 | goto unimplemented; | 3161 | goto unimplemented; |
@@ -2874,16 +3184,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2874,16 +3184,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2874 | struct rlimit rlim; | 3184 | struct rlimit rlim; |
2875 | ret = get_errno(getrlimit(arg1, &rlim)); | 3185 | ret = get_errno(getrlimit(arg1, &rlim)); |
2876 | if (!is_error(ret)) { | 3186 | if (!is_error(ret)) { |
2877 | - struct target_rlimit *target_rlim = (void *)arg2; | 3187 | + struct target_rlimit *target_rlim; |
3188 | + lock_user_struct(target_rlim, arg2, 0); | ||
2878 | target_rlim->rlim_cur = tswapl(rlim.rlim_cur); | 3189 | target_rlim->rlim_cur = tswapl(rlim.rlim_cur); |
2879 | target_rlim->rlim_max = tswapl(rlim.rlim_max); | 3190 | target_rlim->rlim_max = tswapl(rlim.rlim_max); |
3191 | + unlock_user_struct(target_rlim, arg2, 1); | ||
2880 | } | 3192 | } |
2881 | break; | 3193 | break; |
2882 | } | 3194 | } |
2883 | #endif | 3195 | #endif |
2884 | #ifdef TARGET_NR_truncate64 | 3196 | #ifdef TARGET_NR_truncate64 |
2885 | case TARGET_NR_truncate64: | 3197 | case TARGET_NR_truncate64: |
2886 | - ret = target_truncate64(cpu_env, (const char *)arg1, arg2, arg3, arg4); | 3198 | + p = lock_user_string(arg1); |
3199 | + ret = target_truncate64(cpu_env, p, arg2, arg3, arg4); | ||
3200 | + unlock_user(p, arg1, 0); | ||
2887 | break; | 3201 | break; |
2888 | #endif | 3202 | #endif |
2889 | #ifdef TARGET_NR_ftruncate64 | 3203 | #ifdef TARGET_NR_ftruncate64 |
@@ -2893,12 +3207,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2893,12 +3207,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2893 | #endif | 3207 | #endif |
2894 | #ifdef TARGET_NR_stat64 | 3208 | #ifdef TARGET_NR_stat64 |
2895 | case TARGET_NR_stat64: | 3209 | case TARGET_NR_stat64: |
2896 | - ret = get_errno(stat(path((const char *)arg1), &st)); | 3210 | + p = lock_user_string(arg1); |
3211 | + ret = get_errno(stat(path(p), &st)); | ||
3212 | + unlock_user(p, arg1, 0); | ||
2897 | goto do_stat64; | 3213 | goto do_stat64; |
2898 | #endif | 3214 | #endif |
2899 | #ifdef TARGET_NR_lstat64 | 3215 | #ifdef TARGET_NR_lstat64 |
2900 | case TARGET_NR_lstat64: | 3216 | case TARGET_NR_lstat64: |
2901 | - ret = get_errno(lstat(path((const char *)arg1), &st)); | 3217 | + p = lock_user_string(arg1); |
3218 | + ret = get_errno(lstat(path(p), &st)); | ||
3219 | + unlock_user(p, arg1, 0); | ||
2902 | goto do_stat64; | 3220 | goto do_stat64; |
2903 | #endif | 3221 | #endif |
2904 | #ifdef TARGET_NR_fstat64 | 3222 | #ifdef TARGET_NR_fstat64 |
@@ -2909,8 +3227,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2909,8 +3227,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2909 | if (!is_error(ret)) { | 3227 | if (!is_error(ret)) { |
2910 | #ifdef TARGET_ARM | 3228 | #ifdef TARGET_ARM |
2911 | if (((CPUARMState *)cpu_env)->eabi) { | 3229 | if (((CPUARMState *)cpu_env)->eabi) { |
2912 | - struct target_eabi_stat64 *target_st = (void *)arg2; | 3230 | + struct target_eabi_stat64 *target_st; |
3231 | + lock_user_struct(target_st, arg2, 1); | ||
2913 | memset(target_st, 0, sizeof(struct target_eabi_stat64)); | 3232 | memset(target_st, 0, sizeof(struct target_eabi_stat64)); |
3233 | + /* put_user is probably wrong. */ | ||
2914 | put_user(st.st_dev, &target_st->st_dev); | 3234 | put_user(st.st_dev, &target_st->st_dev); |
2915 | put_user(st.st_ino, &target_st->st_ino); | 3235 | put_user(st.st_ino, &target_st->st_ino); |
2916 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | 3236 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
@@ -2928,11 +3248,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2928,11 +3248,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2928 | put_user(st.st_atime, &target_st->target_st_atime); | 3248 | put_user(st.st_atime, &target_st->target_st_atime); |
2929 | put_user(st.st_mtime, &target_st->target_st_mtime); | 3249 | put_user(st.st_mtime, &target_st->target_st_mtime); |
2930 | put_user(st.st_ctime, &target_st->target_st_ctime); | 3250 | put_user(st.st_ctime, &target_st->target_st_ctime); |
3251 | + unlock_user_struct(target_st, arg2, 0); | ||
2931 | } else | 3252 | } else |
2932 | #endif | 3253 | #endif |
2933 | { | 3254 | { |
2934 | - struct target_stat64 *target_st = (void *)arg2; | 3255 | + struct target_stat64 *target_st; |
3256 | + lock_user_struct(target_st, arg2, 1); | ||
2935 | memset(target_st, 0, sizeof(struct target_stat64)); | 3257 | memset(target_st, 0, sizeof(struct target_stat64)); |
3258 | + /* ??? put_user is probably wrong. */ | ||
2936 | put_user(st.st_dev, &target_st->st_dev); | 3259 | put_user(st.st_dev, &target_st->st_dev); |
2937 | put_user(st.st_ino, &target_st->st_ino); | 3260 | put_user(st.st_ino, &target_st->st_ino); |
2938 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | 3261 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
@@ -2950,6 +3273,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2950,6 +3273,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2950 | put_user(st.st_atime, &target_st->target_st_atime); | 3273 | put_user(st.st_atime, &target_st->target_st_atime); |
2951 | put_user(st.st_mtime, &target_st->target_st_mtime); | 3274 | put_user(st.st_mtime, &target_st->target_st_mtime); |
2952 | put_user(st.st_ctime, &target_st->target_st_ctime); | 3275 | put_user(st.st_ctime, &target_st->target_st_ctime); |
3276 | + unlock_user_struct(target_st, arg2, 0); | ||
2953 | } | 3277 | } |
2954 | } | 3278 | } |
2955 | } | 3279 | } |
@@ -2957,7 +3281,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2957,7 +3281,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2957 | #endif | 3281 | #endif |
2958 | #ifdef USE_UID16 | 3282 | #ifdef USE_UID16 |
2959 | case TARGET_NR_lchown: | 3283 | case TARGET_NR_lchown: |
2960 | - ret = get_errno(lchown((const char *)arg1, low2highuid(arg2), low2highgid(arg3))); | 3284 | + p = lock_user_string(arg1); |
3285 | + ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3))); | ||
3286 | + unlock_user(p, arg1, 0); | ||
2961 | break; | 3287 | break; |
2962 | case TARGET_NR_getuid: | 3288 | case TARGET_NR_getuid: |
2963 | ret = get_errno(high2lowuid(getuid())); | 3289 | ret = get_errno(high2lowuid(getuid())); |
@@ -2980,28 +3306,32 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -2980,28 +3306,32 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
2980 | case TARGET_NR_getgroups: | 3306 | case TARGET_NR_getgroups: |
2981 | { | 3307 | { |
2982 | int gidsetsize = arg1; | 3308 | int gidsetsize = arg1; |
2983 | - uint16_t *target_grouplist = (void *)arg2; | 3309 | + uint16_t *target_grouplist; |
2984 | gid_t *grouplist; | 3310 | gid_t *grouplist; |
2985 | int i; | 3311 | int i; |
2986 | 3312 | ||
2987 | grouplist = alloca(gidsetsize * sizeof(gid_t)); | 3313 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
2988 | ret = get_errno(getgroups(gidsetsize, grouplist)); | 3314 | ret = get_errno(getgroups(gidsetsize, grouplist)); |
2989 | if (!is_error(ret)) { | 3315 | if (!is_error(ret)) { |
3316 | + target_grouplist = lock_user(arg2, gidsetsize * 2, 0); | ||
2990 | for(i = 0;i < gidsetsize; i++) | 3317 | for(i = 0;i < gidsetsize; i++) |
2991 | target_grouplist[i] = tswap16(grouplist[i]); | 3318 | target_grouplist[i] = tswap16(grouplist[i]); |
3319 | + unlock_user(target_grouplist, arg2, gidsetsize * 2); | ||
2992 | } | 3320 | } |
2993 | } | 3321 | } |
2994 | break; | 3322 | break; |
2995 | case TARGET_NR_setgroups: | 3323 | case TARGET_NR_setgroups: |
2996 | { | 3324 | { |
2997 | int gidsetsize = arg1; | 3325 | int gidsetsize = arg1; |
2998 | - uint16_t *target_grouplist = (void *)arg2; | 3326 | + uint16_t *target_grouplist; |
2999 | gid_t *grouplist; | 3327 | gid_t *grouplist; |
3000 | int i; | 3328 | int i; |
3001 | 3329 | ||
3002 | grouplist = alloca(gidsetsize * sizeof(gid_t)); | 3330 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
3331 | + target_grouplist = lock_user(arg2, gidsetsize * 2, 1); | ||
3003 | for(i = 0;i < gidsetsize; i++) | 3332 | for(i = 0;i < gidsetsize; i++) |
3004 | grouplist[i] = tswap16(target_grouplist[i]); | 3333 | grouplist[i] = tswap16(target_grouplist[i]); |
3334 | + unlock_user(target_grouplist, arg2, 0); | ||
3005 | ret = get_errno(setgroups(gidsetsize, grouplist)); | 3335 | ret = get_errno(setgroups(gidsetsize, grouplist)); |
3006 | } | 3336 | } |
3007 | break; | 3337 | break; |
@@ -3018,12 +3348,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3018,12 +3348,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3018 | #ifdef TARGET_NR_getresuid | 3348 | #ifdef TARGET_NR_getresuid |
3019 | case TARGET_NR_getresuid: | 3349 | case TARGET_NR_getresuid: |
3020 | { | 3350 | { |
3021 | - int ruid, euid, suid; | 3351 | + uid_t ruid, euid, suid; |
3022 | ret = get_errno(getresuid(&ruid, &euid, &suid)); | 3352 | ret = get_errno(getresuid(&ruid, &euid, &suid)); |
3023 | if (!is_error(ret)) { | 3353 | if (!is_error(ret)) { |
3024 | - *(uint16_t *)arg1 = tswap16(high2lowuid(ruid)); | ||
3025 | - *(uint16_t *)arg2 = tswap16(high2lowuid(euid)); | ||
3026 | - *(uint16_t *)arg3 = tswap16(high2lowuid(suid)); | 3354 | + tput16(arg1, tswap16(high2lowuid(ruid))); |
3355 | + tput16(arg2, tswap16(high2lowuid(euid))); | ||
3356 | + tput16(arg3, tswap16(high2lowuid(suid))); | ||
3027 | } | 3357 | } |
3028 | } | 3358 | } |
3029 | break; | 3359 | break; |
@@ -3038,18 +3368,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3038,18 +3368,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3038 | #ifdef TARGET_NR_getresgid | 3368 | #ifdef TARGET_NR_getresgid |
3039 | case TARGET_NR_getresgid: | 3369 | case TARGET_NR_getresgid: |
3040 | { | 3370 | { |
3041 | - int rgid, egid, sgid; | 3371 | + gid_t rgid, egid, sgid; |
3042 | ret = get_errno(getresgid(&rgid, &egid, &sgid)); | 3372 | ret = get_errno(getresgid(&rgid, &egid, &sgid)); |
3043 | if (!is_error(ret)) { | 3373 | if (!is_error(ret)) { |
3044 | - *(uint16_t *)arg1 = tswap16(high2lowgid(rgid)); | ||
3045 | - *(uint16_t *)arg2 = tswap16(high2lowgid(egid)); | ||
3046 | - *(uint16_t *)arg3 = tswap16(high2lowgid(sgid)); | 3374 | + tput16(arg1, tswap16(high2lowgid(rgid))); |
3375 | + tput16(arg2, tswap16(high2lowgid(egid))); | ||
3376 | + tput16(arg3, tswap16(high2lowgid(sgid))); | ||
3047 | } | 3377 | } |
3048 | } | 3378 | } |
3049 | break; | 3379 | break; |
3050 | #endif | 3380 | #endif |
3051 | case TARGET_NR_chown: | 3381 | case TARGET_NR_chown: |
3052 | - ret = get_errno(chown((const char *)arg1, low2highuid(arg2), low2highgid(arg3))); | 3382 | + p = lock_user_string(arg1); |
3383 | + ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3))); | ||
3384 | + unlock_user(p, arg1, 0); | ||
3053 | break; | 3385 | break; |
3054 | case TARGET_NR_setuid: | 3386 | case TARGET_NR_setuid: |
3055 | ret = get_errno(setuid(low2highuid(arg1))); | 3387 | ret = get_errno(setuid(low2highuid(arg1))); |
@@ -3067,7 +3399,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3067,7 +3399,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3067 | 3399 | ||
3068 | #ifdef TARGET_NR_lchown32 | 3400 | #ifdef TARGET_NR_lchown32 |
3069 | case TARGET_NR_lchown32: | 3401 | case TARGET_NR_lchown32: |
3070 | - ret = get_errno(lchown((const char *)arg1, arg2, arg3)); | 3402 | + p = lock_user_string(arg1); |
3403 | + ret = get_errno(lchown(p, arg2, arg3)); | ||
3404 | + unlock_user(p, arg1, 0); | ||
3071 | break; | 3405 | break; |
3072 | #endif | 3406 | #endif |
3073 | #ifdef TARGET_NR_getuid32 | 3407 | #ifdef TARGET_NR_getuid32 |
@@ -3104,15 +3438,17 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3104,15 +3438,17 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3104 | case TARGET_NR_getgroups32: | 3438 | case TARGET_NR_getgroups32: |
3105 | { | 3439 | { |
3106 | int gidsetsize = arg1; | 3440 | int gidsetsize = arg1; |
3107 | - uint32_t *target_grouplist = (void *)arg2; | 3441 | + uint32_t *target_grouplist; |
3108 | gid_t *grouplist; | 3442 | gid_t *grouplist; |
3109 | int i; | 3443 | int i; |
3110 | 3444 | ||
3111 | grouplist = alloca(gidsetsize * sizeof(gid_t)); | 3445 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
3112 | ret = get_errno(getgroups(gidsetsize, grouplist)); | 3446 | ret = get_errno(getgroups(gidsetsize, grouplist)); |
3113 | if (!is_error(ret)) { | 3447 | if (!is_error(ret)) { |
3448 | + target_grouplist = lock_user(arg2, gidsetsize * 4, 0); | ||
3114 | for(i = 0;i < gidsetsize; i++) | 3449 | for(i = 0;i < gidsetsize; i++) |
3115 | - put_user(grouplist[i], &target_grouplist[i]); | 3450 | + target_grouplist[i] = tswap32(grouplist[i]); |
3451 | + unlock_user(target_grouplist, arg2, gidsetsize * 4); | ||
3116 | } | 3452 | } |
3117 | } | 3453 | } |
3118 | break; | 3454 | break; |
@@ -3121,13 +3457,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3121,13 +3457,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3121 | case TARGET_NR_setgroups32: | 3457 | case TARGET_NR_setgroups32: |
3122 | { | 3458 | { |
3123 | int gidsetsize = arg1; | 3459 | int gidsetsize = arg1; |
3124 | - uint32_t *target_grouplist = (void *)arg2; | 3460 | + uint32_t *target_grouplist; |
3125 | gid_t *grouplist; | 3461 | gid_t *grouplist; |
3126 | int i; | 3462 | int i; |
3127 | 3463 | ||
3128 | grouplist = alloca(gidsetsize * sizeof(gid_t)); | 3464 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
3465 | + target_grouplist = lock_user(arg2, gidsetsize * 4, 1); | ||
3129 | for(i = 0;i < gidsetsize; i++) | 3466 | for(i = 0;i < gidsetsize; i++) |
3130 | - get_user(grouplist[i], &target_grouplist[i]); | 3467 | + grouplist[i] = tswap32(target_grouplist[i]); |
3468 | + unlock_user(target_grouplist, arg2, 0); | ||
3131 | ret = get_errno(setgroups(gidsetsize, grouplist)); | 3469 | ret = get_errno(setgroups(gidsetsize, grouplist)); |
3132 | } | 3470 | } |
3133 | break; | 3471 | break; |
@@ -3145,12 +3483,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3145,12 +3483,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3145 | #ifdef TARGET_NR_getresuid32 | 3483 | #ifdef TARGET_NR_getresuid32 |
3146 | case TARGET_NR_getresuid32: | 3484 | case TARGET_NR_getresuid32: |
3147 | { | 3485 | { |
3148 | - int ruid, euid, suid; | 3486 | + uid_t ruid, euid, suid; |
3149 | ret = get_errno(getresuid(&ruid, &euid, &suid)); | 3487 | ret = get_errno(getresuid(&ruid, &euid, &suid)); |
3150 | if (!is_error(ret)) { | 3488 | if (!is_error(ret)) { |
3151 | - *(uint32_t *)arg1 = tswap32(ruid); | ||
3152 | - *(uint32_t *)arg2 = tswap32(euid); | ||
3153 | - *(uint32_t *)arg3 = tswap32(suid); | 3489 | + tput32(arg1, tswap32(ruid)); |
3490 | + tput32(arg2, tswap32(euid)); | ||
3491 | + tput32(arg3, tswap32(suid)); | ||
3154 | } | 3492 | } |
3155 | } | 3493 | } |
3156 | break; | 3494 | break; |
@@ -3163,19 +3501,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3163,19 +3501,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3163 | #ifdef TARGET_NR_getresgid32 | 3501 | #ifdef TARGET_NR_getresgid32 |
3164 | case TARGET_NR_getresgid32: | 3502 | case TARGET_NR_getresgid32: |
3165 | { | 3503 | { |
3166 | - int rgid, egid, sgid; | 3504 | + gid_t rgid, egid, sgid; |
3167 | ret = get_errno(getresgid(&rgid, &egid, &sgid)); | 3505 | ret = get_errno(getresgid(&rgid, &egid, &sgid)); |
3168 | if (!is_error(ret)) { | 3506 | if (!is_error(ret)) { |
3169 | - *(uint32_t *)arg1 = tswap32(rgid); | ||
3170 | - *(uint32_t *)arg2 = tswap32(egid); | ||
3171 | - *(uint32_t *)arg3 = tswap32(sgid); | 3507 | + tput32(arg1, tswap32(rgid)); |
3508 | + tput32(arg2, tswap32(egid)); | ||
3509 | + tput32(arg3, tswap32(sgid)); | ||
3172 | } | 3510 | } |
3173 | } | 3511 | } |
3174 | break; | 3512 | break; |
3175 | #endif | 3513 | #endif |
3176 | #ifdef TARGET_NR_chown32 | 3514 | #ifdef TARGET_NR_chown32 |
3177 | case TARGET_NR_chown32: | 3515 | case TARGET_NR_chown32: |
3178 | - ret = get_errno(chown((const char *)arg1, arg2, arg3)); | 3516 | + p = lock_user_string(arg1); |
3517 | + ret = get_errno(chown(p, arg2, arg3)); | ||
3518 | + unlock_user(p, arg1, 0); | ||
3179 | break; | 3519 | break; |
3180 | #endif | 3520 | #endif |
3181 | #ifdef TARGET_NR_setuid32 | 3521 | #ifdef TARGET_NR_setuid32 |
@@ -3213,9 +3553,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3213,9 +3553,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3213 | case TARGET_NR_fcntl64: | 3553 | case TARGET_NR_fcntl64: |
3214 | { | 3554 | { |
3215 | struct flock64 fl; | 3555 | struct flock64 fl; |
3216 | - struct target_flock64 *target_fl = (void *)arg3; | 3556 | + struct target_flock64 *target_fl; |
3217 | #ifdef TARGET_ARM | 3557 | #ifdef TARGET_ARM |
3218 | - struct target_eabi_flock64 *target_efl = (void *)arg3; | 3558 | + struct target_eabi_flock64 *target_efl; |
3219 | #endif | 3559 | #endif |
3220 | 3560 | ||
3221 | switch(arg2) { | 3561 | switch(arg2) { |
@@ -3224,19 +3564,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3224,19 +3564,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3224 | if (ret == 0) { | 3564 | if (ret == 0) { |
3225 | #ifdef TARGET_ARM | 3565 | #ifdef TARGET_ARM |
3226 | if (((CPUARMState *)cpu_env)->eabi) { | 3566 | if (((CPUARMState *)cpu_env)->eabi) { |
3567 | + lock_user_struct(target_efl, arg3, 0); | ||
3227 | target_efl->l_type = tswap16(fl.l_type); | 3568 | target_efl->l_type = tswap16(fl.l_type); |
3228 | target_efl->l_whence = tswap16(fl.l_whence); | 3569 | target_efl->l_whence = tswap16(fl.l_whence); |
3229 | target_efl->l_start = tswap64(fl.l_start); | 3570 | target_efl->l_start = tswap64(fl.l_start); |
3230 | target_efl->l_len = tswap64(fl.l_len); | 3571 | target_efl->l_len = tswap64(fl.l_len); |
3231 | target_efl->l_pid = tswapl(fl.l_pid); | 3572 | target_efl->l_pid = tswapl(fl.l_pid); |
3573 | + unlock_user_struct(target_efl, arg3, 1); | ||
3232 | } else | 3574 | } else |
3233 | #endif | 3575 | #endif |
3234 | { | 3576 | { |
3577 | + lock_user_struct(target_fl, arg3, 0); | ||
3235 | target_fl->l_type = tswap16(fl.l_type); | 3578 | target_fl->l_type = tswap16(fl.l_type); |
3236 | target_fl->l_whence = tswap16(fl.l_whence); | 3579 | target_fl->l_whence = tswap16(fl.l_whence); |
3237 | target_fl->l_start = tswap64(fl.l_start); | 3580 | target_fl->l_start = tswap64(fl.l_start); |
3238 | target_fl->l_len = tswap64(fl.l_len); | 3581 | target_fl->l_len = tswap64(fl.l_len); |
3239 | target_fl->l_pid = tswapl(fl.l_pid); | 3582 | target_fl->l_pid = tswapl(fl.l_pid); |
3583 | + unlock_user_struct(target_fl, arg3, 1); | ||
3240 | } | 3584 | } |
3241 | } | 3585 | } |
3242 | break; | 3586 | break; |
@@ -3245,19 +3589,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | @@ -3245,19 +3589,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, | ||
3245 | case F_SETLKW64: | 3589 | case F_SETLKW64: |
3246 | #ifdef TARGET_ARM | 3590 | #ifdef TARGET_ARM |
3247 | if (((CPUARMState *)cpu_env)->eabi) { | 3591 | if (((CPUARMState *)cpu_env)->eabi) { |
3592 | + lock_user_struct(target_efl, arg3, 1); | ||
3248 | fl.l_type = tswap16(target_efl->l_type); | 3593 | fl.l_type = tswap16(target_efl->l_type); |
3249 | fl.l_whence = tswap16(target_efl->l_whence); | 3594 | fl.l_whence = tswap16(target_efl->l_whence); |
3250 | fl.l_start = tswap64(target_efl->l_start); | 3595 | fl.l_start = tswap64(target_efl->l_start); |
3251 | fl.l_len = tswap64(target_efl->l_len); | 3596 | fl.l_len = tswap64(target_efl->l_len); |
3252 | fl.l_pid = tswapl(target_efl->l_pid); | 3597 | fl.l_pid = tswapl(target_efl->l_pid); |
3598 | + unlock_user_struct(target_efl, arg3, 0); | ||
3253 | } else | 3599 | } else |
3254 | #endif | 3600 | #endif |
3255 | { | 3601 | { |
3602 | + lock_user_struct(target_fl, arg3, 1); | ||
3256 | fl.l_type = tswap16(target_fl->l_type); | 3603 | fl.l_type = tswap16(target_fl->l_type); |
3257 | fl.l_whence = tswap16(target_fl->l_whence); | 3604 | fl.l_whence = tswap16(target_fl->l_whence); |
3258 | fl.l_start = tswap64(target_fl->l_start); | 3605 | fl.l_start = tswap64(target_fl->l_start); |
3259 | fl.l_len = tswap64(target_fl->l_len); | 3606 | fl.l_len = tswap64(target_fl->l_len); |
3260 | fl.l_pid = tswapl(target_fl->l_pid); | 3607 | fl.l_pid = tswapl(target_fl->l_pid); |
3608 | + unlock_user_struct(target_fl, arg3, 0); | ||
3261 | } | 3609 | } |
3262 | ret = get_errno(fcntl(arg1, arg2, &fl)); | 3610 | ret = get_errno(fcntl(arg1, arg2, &fl)); |
3263 | break; | 3611 | break; |
linux-user/syscall_types.h
@@ -68,6 +68,9 @@ STRUCT(dirent, | @@ -68,6 +68,9 @@ STRUCT(dirent, | ||
68 | STRUCT(kbentry, | 68 | STRUCT(kbentry, |
69 | TYPE_CHAR, TYPE_CHAR, TYPE_SHORT) | 69 | TYPE_CHAR, TYPE_CHAR, TYPE_SHORT) |
70 | 70 | ||
71 | +STRUCT(kbsentry, | ||
72 | + TYPE_CHAR, MK_ARRAY(TYPE_CHAR, 512)) | ||
73 | + | ||
71 | STRUCT(audio_buf_info, | 74 | STRUCT(audio_buf_info, |
72 | TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT) | 75 | TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT) |
73 | 76 |
linux-user/vm86.c
@@ -62,25 +62,28 @@ static inline unsigned int vm_getl(uint8_t *segptr, unsigned int reg16) | @@ -62,25 +62,28 @@ static inline unsigned int vm_getl(uint8_t *segptr, unsigned int reg16) | ||
62 | void save_v86_state(CPUX86State *env) | 62 | void save_v86_state(CPUX86State *env) |
63 | { | 63 | { |
64 | TaskState *ts = env->opaque; | 64 | TaskState *ts = env->opaque; |
65 | + struct target_vm86plus_struct * target_v86; | ||
65 | 66 | ||
67 | + lock_user_struct(target_v86, ts->target_v86, 0); | ||
66 | /* put the VM86 registers in the userspace register structure */ | 68 | /* put the VM86 registers in the userspace register structure */ |
67 | - ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); | ||
68 | - ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | ||
69 | - ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | ||
70 | - ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); | ||
71 | - ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); | ||
72 | - ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); | ||
73 | - ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | ||
74 | - ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); | ||
75 | - ts->target_v86->regs.eip = tswap32(env->eip); | ||
76 | - ts->target_v86->regs.cs = tswap16(env->segs[R_CS].selector); | ||
77 | - ts->target_v86->regs.ss = tswap16(env->segs[R_SS].selector); | ||
78 | - ts->target_v86->regs.ds = tswap16(env->segs[R_DS].selector); | ||
79 | - ts->target_v86->regs.es = tswap16(env->segs[R_ES].selector); | ||
80 | - ts->target_v86->regs.fs = tswap16(env->segs[R_FS].selector); | ||
81 | - ts->target_v86->regs.gs = tswap16(env->segs[R_GS].selector); | 69 | + target_v86->regs.eax = tswap32(env->regs[R_EAX]); |
70 | + target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | ||
71 | + target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | ||
72 | + target_v86->regs.edx = tswap32(env->regs[R_EDX]); | ||
73 | + target_v86->regs.esi = tswap32(env->regs[R_ESI]); | ||
74 | + target_v86->regs.edi = tswap32(env->regs[R_EDI]); | ||
75 | + target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | ||
76 | + target_v86->regs.esp = tswap32(env->regs[R_ESP]); | ||
77 | + target_v86->regs.eip = tswap32(env->eip); | ||
78 | + target_v86->regs.cs = tswap16(env->segs[R_CS].selector); | ||
79 | + target_v86->regs.ss = tswap16(env->segs[R_SS].selector); | ||
80 | + target_v86->regs.ds = tswap16(env->segs[R_DS].selector); | ||
81 | + target_v86->regs.es = tswap16(env->segs[R_ES].selector); | ||
82 | + target_v86->regs.fs = tswap16(env->segs[R_FS].selector); | ||
83 | + target_v86->regs.gs = tswap16(env->segs[R_GS].selector); | ||
82 | set_flags(env->eflags, ts->v86flags, VIF_MASK | ts->v86mask); | 84 | set_flags(env->eflags, ts->v86flags, VIF_MASK | ts->v86mask); |
83 | - ts->target_v86->regs.eflags = tswap32(env->eflags); | 85 | + target_v86->regs.eflags = tswap32(env->eflags); |
86 | + unlock_user_struct(target_v86, ts->target_v86, 1); | ||
84 | #ifdef DEBUG_VM86 | 87 | #ifdef DEBUG_VM86 |
85 | fprintf(logfile, "save_v86_state: eflags=%08x cs:ip=%04x:%04x\n", | 88 | fprintf(logfile, "save_v86_state: eflags=%08x cs:ip=%04x:%04x\n", |
86 | env->eflags, env->segs[R_CS].selector, env->eip); | 89 | env->eflags, env->segs[R_CS].selector, env->eip); |
@@ -378,10 +381,10 @@ void handle_vm86_fault(CPUX86State *env) | @@ -378,10 +381,10 @@ void handle_vm86_fault(CPUX86State *env) | ||
378 | } | 381 | } |
379 | } | 382 | } |
380 | 383 | ||
381 | -int do_vm86(CPUX86State *env, long subfunction, | ||
382 | - struct target_vm86plus_struct * target_v86) | 384 | +int do_vm86(CPUX86State *env, long subfunction, target_ulong vm86_addr) |
383 | { | 385 | { |
384 | TaskState *ts = env->opaque; | 386 | TaskState *ts = env->opaque; |
387 | + struct target_vm86plus_struct * target_v86; | ||
385 | int ret; | 388 | int ret; |
386 | 389 | ||
387 | switch (subfunction) { | 390 | switch (subfunction) { |
@@ -402,7 +405,6 @@ int do_vm86(CPUX86State *env, long subfunction, | @@ -402,7 +405,6 @@ int do_vm86(CPUX86State *env, long subfunction, | ||
402 | goto out; | 405 | goto out; |
403 | } | 406 | } |
404 | 407 | ||
405 | - ts->target_v86 = target_v86; | ||
406 | /* save current CPU regs */ | 408 | /* save current CPU regs */ |
407 | ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */ | 409 | ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */ |
408 | ts->vm86_saved_regs.ebx = env->regs[R_EBX]; | 410 | ts->vm86_saved_regs.ebx = env->regs[R_EBX]; |
@@ -421,6 +423,8 @@ int do_vm86(CPUX86State *env, long subfunction, | @@ -421,6 +423,8 @@ int do_vm86(CPUX86State *env, long subfunction, | ||
421 | ts->vm86_saved_regs.fs = env->segs[R_FS].selector; | 423 | ts->vm86_saved_regs.fs = env->segs[R_FS].selector; |
422 | ts->vm86_saved_regs.gs = env->segs[R_GS].selector; | 424 | ts->vm86_saved_regs.gs = env->segs[R_GS].selector; |
423 | 425 | ||
426 | + ts->target_v86 = vm86_addr; | ||
427 | + lock_user_struct(target_v86, vm86_addr, 1); | ||
424 | /* build vm86 CPU state */ | 428 | /* build vm86 CPU state */ |
425 | ts->v86flags = tswap32(target_v86->regs.eflags); | 429 | ts->v86flags = tswap32(target_v86->regs.eflags); |
426 | env->eflags = (env->eflags & ~SAFE_MASK) | | 430 | env->eflags = (env->eflags & ~SAFE_MASK) | |
@@ -465,6 +469,7 @@ int do_vm86(CPUX86State *env, long subfunction, | @@ -465,6 +469,7 @@ int do_vm86(CPUX86State *env, long subfunction, | ||
465 | ts->vm86plus.vm86plus.flags = tswapl(target_v86->vm86plus.flags); | 469 | ts->vm86plus.vm86plus.flags = tswapl(target_v86->vm86plus.flags); |
466 | memcpy(&ts->vm86plus.vm86plus.vm86dbg_intxxtab, | 470 | memcpy(&ts->vm86plus.vm86plus.vm86dbg_intxxtab, |
467 | target_v86->vm86plus.vm86dbg_intxxtab, 32); | 471 | target_v86->vm86plus.vm86dbg_intxxtab, 32); |
472 | + unlock_user_struct(target_v86, vm86_addr, 0); | ||
468 | 473 | ||
469 | #ifdef DEBUG_VM86 | 474 | #ifdef DEBUG_VM86 |
470 | fprintf(logfile, "do_vm86: cs:ip=%04x:%04x\n", | 475 | fprintf(logfile, "do_vm86: cs:ip=%04x:%04x\n", |
target-arm/nwfpe/fpa11_cpdt.c
@@ -31,48 +31,52 @@ | @@ -31,48 +31,52 @@ | ||
31 | static inline | 31 | static inline |
32 | void loadSingle(const unsigned int Fn,const unsigned int *pMem) | 32 | void loadSingle(const unsigned int Fn,const unsigned int *pMem) |
33 | { | 33 | { |
34 | + target_ulong addr = (target_ulong)(long)pMem; | ||
34 | FPA11 *fpa11 = GET_FPA11(); | 35 | FPA11 *fpa11 = GET_FPA11(); |
35 | fpa11->fType[Fn] = typeSingle; | 36 | fpa11->fType[Fn] = typeSingle; |
36 | - get_user(fpa11->fpreg[Fn].fSingle, pMem); | 37 | + fpa11->fpreg[Fn].fSingle = tget32(addr); |
37 | } | 38 | } |
38 | 39 | ||
39 | static inline | 40 | static inline |
40 | void loadDouble(const unsigned int Fn,const unsigned int *pMem) | 41 | void loadDouble(const unsigned int Fn,const unsigned int *pMem) |
41 | { | 42 | { |
43 | + target_ulong addr = (target_ulong)(long)pMem; | ||
42 | FPA11 *fpa11 = GET_FPA11(); | 44 | FPA11 *fpa11 = GET_FPA11(); |
43 | unsigned int *p; | 45 | unsigned int *p; |
44 | p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; | 46 | p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; |
45 | fpa11->fType[Fn] = typeDouble; | 47 | fpa11->fType[Fn] = typeDouble; |
46 | #ifdef WORDS_BIGENDIAN | 48 | #ifdef WORDS_BIGENDIAN |
47 | - get_user(p[0], &pMem[0]); /* sign & exponent */ | ||
48 | - get_user(p[1], &pMem[1]); | 49 | + p[0] = tget32(addr); /* sign & exponent */ |
50 | + p[1] = tget32(addr + 4); | ||
49 | #else | 51 | #else |
50 | - get_user(p[0], &pMem[1]); | ||
51 | - get_user(p[1], &pMem[0]); /* sign & exponent */ | 52 | + p[0] = tget32(addr + 4); |
53 | + p[1] = tget32(addr); /* sign & exponent */ | ||
52 | #endif | 54 | #endif |
53 | } | 55 | } |
54 | 56 | ||
55 | static inline | 57 | static inline |
56 | void loadExtended(const unsigned int Fn,const unsigned int *pMem) | 58 | void loadExtended(const unsigned int Fn,const unsigned int *pMem) |
57 | { | 59 | { |
60 | + target_ulong addr = (target_ulong)(long)pMem; | ||
58 | FPA11 *fpa11 = GET_FPA11(); | 61 | FPA11 *fpa11 = GET_FPA11(); |
59 | unsigned int *p; | 62 | unsigned int *p; |
60 | p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; | 63 | p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; |
61 | fpa11->fType[Fn] = typeExtended; | 64 | fpa11->fType[Fn] = typeExtended; |
62 | - get_user(p[0], &pMem[0]); /* sign & exponent */ | ||
63 | - get_user(p[1], &pMem[2]); /* ls bits */ | ||
64 | - get_user(p[2], &pMem[1]); /* ms bits */ | 65 | + p[0] = tget32(addr); /* sign & exponent */ |
66 | + p[1] = tget32(addr + 8); /* ls bits */ | ||
67 | + p[2] = tget32(addr + 4); /* ms bits */ | ||
65 | } | 68 | } |
66 | 69 | ||
67 | static inline | 70 | static inline |
68 | void loadMultiple(const unsigned int Fn,const unsigned int *pMem) | 71 | void loadMultiple(const unsigned int Fn,const unsigned int *pMem) |
69 | { | 72 | { |
73 | + target_ulong addr = (target_ulong)(long)pMem; | ||
70 | FPA11 *fpa11 = GET_FPA11(); | 74 | FPA11 *fpa11 = GET_FPA11(); |
71 | register unsigned int *p; | 75 | register unsigned int *p; |
72 | unsigned long x; | 76 | unsigned long x; |
73 | 77 | ||
74 | p = (unsigned int*)&(fpa11->fpreg[Fn]); | 78 | p = (unsigned int*)&(fpa11->fpreg[Fn]); |
75 | - get_user(x, &pMem[0]); | 79 | + x = tget32(addr); |
76 | fpa11->fType[Fn] = (x >> 14) & 0x00000003; | 80 | fpa11->fType[Fn] = (x >> 14) & 0x00000003; |
77 | 81 | ||
78 | switch (fpa11->fType[Fn]) | 82 | switch (fpa11->fType[Fn]) |
@@ -80,16 +84,16 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) | @@ -80,16 +84,16 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) | ||
80 | case typeSingle: | 84 | case typeSingle: |
81 | case typeDouble: | 85 | case typeDouble: |
82 | { | 86 | { |
83 | - get_user(p[0], &pMem[2]); /* Single */ | ||
84 | - get_user(p[1], &pMem[1]); /* double msw */ | 87 | + p[0] = tget32(addr + 8); /* Single */ |
88 | + p[1] = tget32(addr + 4); /* double msw */ | ||
85 | p[2] = 0; /* empty */ | 89 | p[2] = 0; /* empty */ |
86 | } | 90 | } |
87 | break; | 91 | break; |
88 | 92 | ||
89 | case typeExtended: | 93 | case typeExtended: |
90 | { | 94 | { |
91 | - get_user(p[1], &pMem[2]); | ||
92 | - get_user(p[2], &pMem[1]); /* msw */ | 95 | + p[1] = tget32(addr + 8); |
96 | + p[2] = tget32(addr + 4); /* msw */ | ||
93 | p[0] = (x & 0x80003fff); | 97 | p[0] = (x & 0x80003fff); |
94 | } | 98 | } |
95 | break; | 99 | break; |
@@ -99,6 +103,7 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) | @@ -99,6 +103,7 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) | ||
99 | static inline | 103 | static inline |
100 | void storeSingle(const unsigned int Fn,unsigned int *pMem) | 104 | void storeSingle(const unsigned int Fn,unsigned int *pMem) |
101 | { | 105 | { |
106 | + target_ulong addr = (target_ulong)(long)pMem; | ||
102 | FPA11 *fpa11 = GET_FPA11(); | 107 | FPA11 *fpa11 = GET_FPA11(); |
103 | float32 val; | 108 | float32 val; |
104 | register unsigned int *p = (unsigned int*)&val; | 109 | register unsigned int *p = (unsigned int*)&val; |
@@ -116,12 +121,13 @@ void storeSingle(const unsigned int Fn,unsigned int *pMem) | @@ -116,12 +121,13 @@ void storeSingle(const unsigned int Fn,unsigned int *pMem) | ||
116 | default: val = fpa11->fpreg[Fn].fSingle; | 121 | default: val = fpa11->fpreg[Fn].fSingle; |
117 | } | 122 | } |
118 | 123 | ||
119 | - put_user(p[0], pMem); | 124 | + tput32(addr, p[0]); |
120 | } | 125 | } |
121 | 126 | ||
122 | static inline | 127 | static inline |
123 | void storeDouble(const unsigned int Fn,unsigned int *pMem) | 128 | void storeDouble(const unsigned int Fn,unsigned int *pMem) |
124 | { | 129 | { |
130 | + target_ulong addr = (target_ulong)(long)pMem; | ||
125 | FPA11 *fpa11 = GET_FPA11(); | 131 | FPA11 *fpa11 = GET_FPA11(); |
126 | float64 val; | 132 | float64 val; |
127 | register unsigned int *p = (unsigned int*)&val; | 133 | register unsigned int *p = (unsigned int*)&val; |
@@ -139,17 +145,18 @@ void storeDouble(const unsigned int Fn,unsigned int *pMem) | @@ -139,17 +145,18 @@ void storeDouble(const unsigned int Fn,unsigned int *pMem) | ||
139 | default: val = fpa11->fpreg[Fn].fDouble; | 145 | default: val = fpa11->fpreg[Fn].fDouble; |
140 | } | 146 | } |
141 | #ifdef WORDS_BIGENDIAN | 147 | #ifdef WORDS_BIGENDIAN |
142 | - put_user(p[0], &pMem[0]); /* msw */ | ||
143 | - put_user(p[1], &pMem[1]); /* lsw */ | 148 | + tput32(addr, p[0]); /* msw */ |
149 | + tput32(addr + 4, p[1]); /* lsw */ | ||
144 | #else | 150 | #else |
145 | - put_user(p[1], &pMem[0]); /* msw */ | ||
146 | - put_user(p[0], &pMem[1]); /* lsw */ | 151 | + tput32(addr, p[1]); /* msw */ |
152 | + tput32(addr + 4, p[0]); /* lsw */ | ||
147 | #endif | 153 | #endif |
148 | } | 154 | } |
149 | 155 | ||
150 | static inline | 156 | static inline |
151 | void storeExtended(const unsigned int Fn,unsigned int *pMem) | 157 | void storeExtended(const unsigned int Fn,unsigned int *pMem) |
152 | { | 158 | { |
159 | + target_ulong addr = (target_ulong)(long)pMem; | ||
153 | FPA11 *fpa11 = GET_FPA11(); | 160 | FPA11 *fpa11 = GET_FPA11(); |
154 | floatx80 val; | 161 | floatx80 val; |
155 | register unsigned int *p = (unsigned int*)&val; | 162 | register unsigned int *p = (unsigned int*)&val; |
@@ -167,14 +174,15 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem) | @@ -167,14 +174,15 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem) | ||
167 | default: val = fpa11->fpreg[Fn].fExtended; | 174 | default: val = fpa11->fpreg[Fn].fExtended; |
168 | } | 175 | } |
169 | 176 | ||
170 | - put_user(p[0], &pMem[0]); /* sign & exp */ | ||
171 | - put_user(p[1], &pMem[2]); | ||
172 | - put_user(p[2], &pMem[1]); /* msw */ | 177 | + tput32(addr, p[0]); /* sign & exp */ |
178 | + tput32(addr + 8, p[1]); | ||
179 | + tput32(addr + 4, p[2]); /* msw */ | ||
173 | } | 180 | } |
174 | 181 | ||
175 | static inline | 182 | static inline |
176 | void storeMultiple(const unsigned int Fn,unsigned int *pMem) | 183 | void storeMultiple(const unsigned int Fn,unsigned int *pMem) |
177 | { | 184 | { |
185 | + target_ulong addr = (target_ulong)(long)pMem; | ||
178 | FPA11 *fpa11 = GET_FPA11(); | 186 | FPA11 *fpa11 = GET_FPA11(); |
179 | register unsigned int nType, *p; | 187 | register unsigned int nType, *p; |
180 | 188 | ||
@@ -186,17 +194,17 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) | @@ -186,17 +194,17 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) | ||
186 | case typeSingle: | 194 | case typeSingle: |
187 | case typeDouble: | 195 | case typeDouble: |
188 | { | 196 | { |
189 | - put_user(p[0], &pMem[2]); /* single */ | ||
190 | - put_user(p[1], &pMem[1]); /* double msw */ | ||
191 | - put_user(nType << 14, &pMem[0]); | 197 | + tput32(addr + 8, p[0]); /* single */ |
198 | + tput32(addr + 4, p[1]); /* double msw */ | ||
199 | + tput32(addr, nType << 14); | ||
192 | } | 200 | } |
193 | break; | 201 | break; |
194 | 202 | ||
195 | case typeExtended: | 203 | case typeExtended: |
196 | { | 204 | { |
197 | - put_user(p[2], &pMem[1]); /* msw */ | ||
198 | - put_user(p[1], &pMem[2]); | ||
199 | - put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); | 205 | + tput32(addr + 4, p[2]); /* msw */ |
206 | + tput32(addr + 8, p[1]); | ||
207 | + tput32(addr, (p[0] & 0x80003fff) | (nType << 14)); | ||
200 | } | 208 | } |
201 | break; | 209 | break; |
202 | } | 210 | } |