Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu

* 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
  linux-user: fix for loopmount ioctl
  linux-user: fix build errors for mmap2-only ports
  user: speed up init_paths a bit
  linux-user: implement sched_{g,s}etaffinity
  linux-user/FLAT: allow targets to override FLAT processing
  linux-user/FLAT: fix auto-stack sizing
  linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
  linux-user: add ppoll syscall support
  linux-user/elfload: add FDPIC support
  linux-user: fix sizeof handling for getsockopt
  linux-user: Fix possible realloc memory leak
  linux-user: Add support for -version option
This commit is contained in:
Aurelien Jarno 2011-02-09 19:53:36 +01:00
commit 1c0de9fa50
12 changed files with 298 additions and 39 deletions

View File

@ -107,7 +107,7 @@ ifdef CONFIG_LINUX_USER
$(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)) $(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \ obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \ elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
qemu-malloc.o $(oslib-obj-y) qemu-malloc.o $(oslib-obj-y)

19
elf.h
View File

@ -1191,6 +1191,25 @@ typedef struct elf64_note {
Elf64_Word n_type; /* Content type */ Elf64_Word n_type; /* Content type */
} Elf64_Nhdr; } Elf64_Nhdr;
/* This data structure represents a PT_LOAD segment. */
struct elf32_fdpic_loadseg {
/* Core address to which the segment is mapped. */
Elf32_Addr addr;
/* VMA recorded in the program header. */
Elf32_Addr p_vaddr;
/* Size of this segment in memory. */
Elf32_Word p_memsz;
};
struct elf32_fdpic_loadmap {
/* Protocol version number, must be zero. */
Elf32_Half version;
/* Number of segments in this map. */
Elf32_Half nsegs;
/* The actual memory map. */
struct elf32_fdpic_loadseg segs[/*nsegs*/];
};
#ifdef ELF_CLASS #ifdef ELF_CLASS
#if ELF_CLASS == ELFCLASS32 #if ELF_CLASS == ELFCLASS32

View File

@ -1075,6 +1075,33 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
} }
} }
#ifdef CONFIG_USE_FDPIC
static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
{
uint16_t n;
struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
/* elf32_fdpic_loadseg */
n = info->nsegs;
while (n--) {
sp -= 12;
put_user_u32(loadsegs[n].addr, sp+0);
put_user_u32(loadsegs[n].p_vaddr, sp+4);
put_user_u32(loadsegs[n].p_memsz, sp+8);
}
/* elf32_fdpic_loadmap */
sp -= 4;
put_user_u16(0, sp+0); /* version */
put_user_u16(info->nsegs, sp+2); /* nsegs */
info->personality = PER_LINUX_FDPIC;
info->loadmap_addr = sp;
return sp;
}
#endif
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
struct elfhdr *exec, struct elfhdr *exec,
struct image_info *info, struct image_info *info,
@ -1087,6 +1114,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
const int n = sizeof(elf_addr_t); const int n = sizeof(elf_addr_t);
sp = p; sp = p;
#ifdef CONFIG_USE_FDPIC
/* Needs to be before we load the env/argc/... */
if (elf_is_fdpic(exec)) {
/* Need 4 byte alignment for these structs */
sp &= ~3;
sp = loader_build_fdpic_loadmap(info, sp);
info->other_info = interp_info;
if (interp_info) {
interp_info->other_info = info;
sp = loader_build_fdpic_loadmap(interp_info, sp);
}
}
#endif
u_platform = 0; u_platform = 0;
k_platform = ELF_PLATFORM; k_platform = ELF_PLATFORM;
if (k_platform) { if (k_platform) {
@ -1197,6 +1239,11 @@ static void load_elf_image(const char *image_name, int image_fd,
} }
bswap_phdr(phdr, ehdr->e_phnum); bswap_phdr(phdr, ehdr->e_phnum);
#ifdef CONFIG_USE_FDPIC
info->nsegs = 0;
info->pt_dynamic_addr = 0;
#endif
/* Find the maximum size of the image and allocate an appropriate /* Find the maximum size of the image and allocate an appropriate
amount of memory to handle that. */ amount of memory to handle that. */
loaddr = -1, hiaddr = 0; loaddr = -1, hiaddr = 0;
@ -1210,6 +1257,9 @@ static void load_elf_image(const char *image_name, int image_fd,
if (a > hiaddr) { if (a > hiaddr) {
hiaddr = a; hiaddr = a;
} }
#ifdef CONFIG_USE_FDPIC
++info->nsegs;
#endif
} }
} }
@ -1290,6 +1340,27 @@ static void load_elf_image(const char *image_name, int image_fd,
} }
load_bias = load_addr - loaddr; load_bias = load_addr - loaddr;
#ifdef CONFIG_USE_FDPIC
{
struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
qemu_malloc(sizeof(*loadsegs) * info->nsegs);
for (i = 0; i < ehdr->e_phnum; ++i) {
switch (phdr[i].p_type) {
case PT_DYNAMIC:
info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
break;
case PT_LOAD:
loadsegs->addr = phdr[i].p_vaddr + load_bias;
loadsegs->p_vaddr = phdr[i].p_vaddr;
loadsegs->p_memsz = phdr[i].p_memsz;
++loadsegs;
break;
}
}
}
#endif
info->load_bias = load_bias; info->load_bias = load_bias;
info->load_addr = load_addr; info->load_addr = load_addr;
info->entry = ehdr->e_entry + load_bias; info->entry = ehdr->e_entry + load_bias;
@ -1481,7 +1552,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
struct elf_shdr *shdr; struct elf_shdr *shdr;
char *strings; char *strings;
struct syminfo *s; struct syminfo *s;
struct elf_sym *syms; struct elf_sym *syms, *new_syms;
shnum = hdr->e_shnum; shnum = hdr->e_shnum;
i = shnum * sizeof(struct elf_shdr); i = shnum * sizeof(struct elf_shdr);
@ -1550,12 +1621,14 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
that we threw away. Whether or not this has any effect on the that we threw away. Whether or not this has any effect on the
memory allocation depends on the malloc implementation and how memory allocation depends on the malloc implementation and how
many symbols we managed to discard. */ many symbols we managed to discard. */
syms = realloc(syms, nsyms * sizeof(*syms)); new_syms = realloc(syms, nsyms * sizeof(*syms));
if (syms == NULL) { if (new_syms == NULL) {
free(s); free(s);
free(syms);
free(strings); free(strings);
return; return;
} }
syms = new_syms;
qsort(syms, nsyms, sizeof(*syms), symcmp); qsort(syms, nsyms, sizeof(*syms), symcmp);

View File

@ -41,6 +41,8 @@
#include "qemu.h" #include "qemu.h"
#include "flat.h" #include "flat.h"
#define ntohl(x) be32_to_cpu(x)
#include <target_flat.h>
//#define DEBUG //#define DEBUG
@ -50,14 +52,6 @@
#define DBG_FLT(...) #define DBG_FLT(...)
#endif #endif
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_old_ram_flag(flag) (flag)
#ifdef TARGET_WORDS_BIGENDIAN
#define flat_get_relocate_addr(relval) (relval)
#else
#define flat_get_relocate_addr(relval) bswap32(relval)
#endif
#define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
@ -78,8 +72,6 @@ static int load_flat_shared_library(int id, struct lib_info *p);
struct linux_binprm; struct linux_binprm;
#define ntohl(x) be32_to_cpu(x)
/****************************************************************************/ /****************************************************************************/
/* /*
* create_flat_tables() parses the env- and arg-strings in new user * create_flat_tables() parses the env- and arg-strings in new user
@ -625,6 +617,7 @@ static int load_flat_file(struct linux_binprm * bprm,
* __start to address 4 so that is okay). * __start to address 4 so that is okay).
*/ */
if (rev > OLD_FLAT_VERSION) { if (rev > OLD_FLAT_VERSION) {
abi_ulong persistent = 0;
for (i = 0; i < relocs; i++) { for (i = 0; i < relocs; i++) {
abi_ulong addr, relval; abi_ulong addr, relval;
@ -633,6 +626,9 @@ static int load_flat_file(struct linux_binprm * bprm,
relocated first). */ relocated first). */
if (get_user_ual(relval, reloc + i * sizeof(abi_ulong))) if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
return -EFAULT; return -EFAULT;
relval = ntohl(relval);
if (flat_set_persistent(relval, &persistent))
continue;
addr = flat_get_relocate_addr(relval); addr = flat_get_relocate_addr(relval);
rp = calc_reloc(addr, libinfo, id, 1); rp = calc_reloc(addr, libinfo, id, 1);
if (rp == RELOC_FAILED) if (rp == RELOC_FAILED)
@ -641,22 +637,20 @@ static int load_flat_file(struct linux_binprm * bprm,
/* Get the pointer's value. */ /* Get the pointer's value. */
if (get_user_ual(addr, rp)) if (get_user_ual(addr, rp))
return -EFAULT; return -EFAULT;
addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
if (addr != 0) { if (addr != 0) {
/* /*
* Do the relocation. PIC relocs in the data section are * Do the relocation. PIC relocs in the data section are
* already in target order * already in target order
*/ */
#ifndef TARGET_WORDS_BIGENDIAN
if ((flags & FLAT_FLAG_GOTPIC) == 0) if ((flags & FLAT_FLAG_GOTPIC) == 0)
addr = bswap32(addr); addr = ntohl(addr);
#endif
addr = calc_reloc(addr, libinfo, id, 0); addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED) if (addr == RELOC_FAILED)
return -ENOEXEC; return -ENOEXEC;
/* Write back the relocated pointer. */ /* Write back the relocated pointer. */
if (put_user_ual(addr, rp)) if (flat_put_addr_at_rp(rp, addr, relval))
return -EFAULT; return -EFAULT;
} }
} }
@ -733,8 +727,15 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
* pedantic and include space for the argv/envp array as it may have * pedantic and include space for the argv/envp array as it may have
* a lot of entries. * a lot of entries.
*/ */
#define TOP_OF_ARGS (TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *)) stack_len = 0;
stack_len = TOP_OF_ARGS - bprm->p; /* the strings */ for (i = 0; i < bprm->argc; ++i) {
/* the argv strings */
stack_len += strlen(bprm->argv[i]);
}
for (i = 0; i < bprm->envc; ++i) {
/* the envp strings */
stack_len += strlen(bprm->envp[i]);
}
stack_len += (bprm->argc + 1) * 4; /* the argv array */ stack_len += (bprm->argc + 1) * 4; /* the argv array */
stack_len += (bprm->envc + 1) * 4; /* the envp array */ stack_len += (bprm->envc + 1) * 4; /* the envp array */
@ -775,7 +776,8 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
stack_len *= sizeof(abi_ulong); stack_len *= sizeof(abi_ulong);
if ((sp + stack_len) & 15) if ((sp + stack_len) & 15)
sp -= 16 - ((sp + stack_len) & 15); sp -= 16 - ((sp + stack_len) & 15);
sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1); sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p,
flat_argvp_envp_on_stack());
/* Fake some return addresses to ensure the call chain will /* Fake some return addresses to ensure the call chain will
* initialise library in order for us. We are required to call * initialise library in order for us. We are required to call

View File

@ -312,10 +312,8 @@
IOCTL(LOOP_CLR_FD, 0, TYPE_INT) IOCTL(LOOP_CLR_FD, 0, TYPE_INT)
IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
#if 0 /* These have some problems - not fully tested */
IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
#endif
IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT) IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT)
IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop))) IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop)))

View File

@ -2624,14 +2624,21 @@ void cpu_loop (CPUState *env)
} }
#endif /* TARGET_ALPHA */ #endif /* TARGET_ALPHA */
static void version(void)
{
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
", Copyright (c) 2003-2008 Fabrice Bellard\n");
}
static void usage(void) static void usage(void)
{ {
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n" version();
"usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n" printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
"Linux CPU emulator (compiled for %s emulation)\n" "Linux CPU emulator (compiled for %s emulation)\n"
"\n" "\n"
"Standard options:\n" "Standard options:\n"
"-h print this help\n" "-h print this help\n"
"-version display version information and exit\n"
"-g port wait gdb connection to port\n" "-g port wait gdb connection to port\n"
"-L path set the elf interpreter prefix (default=%s)\n" "-L path set the elf interpreter prefix (default=%s)\n"
"-s size set the stack size in bytes (default=%ld)\n" "-s size set the stack size in bytes (default=%ld)\n"
@ -2886,8 +2893,10 @@ int main(int argc, char **argv, char **envp)
singlestep = 1; singlestep = 1;
} else if (!strcmp(r, "strace")) { } else if (!strcmp(r, "strace")) {
do_strace = 1; do_strace = 1;
} else } else if (!strcmp(r, "version")) {
{ version();
exit(0);
} else {
usage(); usage();
} }
} }

View File

@ -51,6 +51,13 @@ struct image_info {
abi_ulong arg_start; abi_ulong arg_start;
abi_ulong arg_end; abi_ulong arg_end;
int personality; int personality;
#ifdef CONFIG_USE_FDPIC
abi_ulong loadmap_addr;
uint16_t nsegs;
void *loadsegs;
abi_ulong pt_dynamic_addr;
struct image_info *other_info;
#endif
}; };
#ifdef TARGET_I386 #ifdef TARGET_I386

View File

@ -398,6 +398,7 @@ UNUSED static struct flags mmap_flags[] = {
FLAG_TARGET(MAP_DENYWRITE), FLAG_TARGET(MAP_DENYWRITE),
FLAG_TARGET(MAP_FIXED), FLAG_TARGET(MAP_FIXED),
FLAG_TARGET(MAP_GROWSDOWN), FLAG_TARGET(MAP_GROWSDOWN),
FLAG_TARGET(MAP_EXECUTABLE),
#ifdef MAP_LOCKED #ifdef MAP_LOCKED
FLAG_TARGET(MAP_LOCKED), FLAG_TARGET(MAP_LOCKED),
#endif #endif
@ -407,6 +408,9 @@ UNUSED static struct flags mmap_flags[] = {
FLAG_TARGET(MAP_NORESERVE), FLAG_TARGET(MAP_NORESERVE),
#ifdef MAP_POPULATE #ifdef MAP_POPULATE
FLAG_TARGET(MAP_POPULATE), FLAG_TARGET(MAP_POPULATE),
#endif
#ifdef TARGET_MAP_UNINITIALIZED
FLAG_TARGET(MAP_UNINITIALIZED),
#endif #endif
FLAG_END, FLAG_END,
}; };
@ -1199,7 +1203,7 @@ print_utimensat(const struct syscallname *name,
} }
#endif #endif
#ifdef TARGET_NR_mmap #if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
static void static void
print_mmap(const struct syscallname *name, print_mmap(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg0, abi_long arg1, abi_long arg2,

View File

@ -235,6 +235,12 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3) const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif #endif
#endif #endif
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
static bitmask_transtbl fcntl_flags_tbl[] = { static bitmask_transtbl fcntl_flags_tbl[] = {
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
@ -529,6 +535,15 @@ static int sys_inotify_init1(int flags)
#undef TARGET_NR_inotify_rm_watch #undef TARGET_NR_inotify_rm_watch
#endif /* CONFIG_INOTIFY */ #endif /* CONFIG_INOTIFY */
#if defined(TARGET_NR_ppoll)
#ifndef __NR_ppoll
# define __NR_ppoll -1
#endif
#define __NR_sys_ppoll __NR_ppoll
_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
struct timespec *, timeout, const __sigset_t *, sigmask,
size_t, sigsetsize)
#endif
extern int personality(int); extern int personality(int);
extern int flock(int, int); extern int flock(int, int);
@ -1448,7 +1463,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
return -TARGET_EFAULT; return -TARGET_EFAULT;
if (len < 0) if (len < 0)
return -TARGET_EINVAL; return -TARGET_EINVAL;
lv = sizeof(int); lv = sizeof(lv);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -1485,7 +1500,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
return -TARGET_EFAULT; return -TARGET_EFAULT;
if (len < 0) if (len < 0)
return -TARGET_EINVAL; return -TARGET_EINVAL;
lv = sizeof(int); lv = sizeof(lv);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -6230,8 +6245,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_select(arg1, arg2, arg3, arg4, arg5); ret = do_select(arg1, arg2, arg3, arg4, arg5);
break; break;
#endif #endif
#ifdef TARGET_NR_poll #if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
# ifdef TARGET_NR_poll
case TARGET_NR_poll: case TARGET_NR_poll:
# endif
# ifdef TARGET_NR_ppoll
case TARGET_NR_ppoll:
# endif
{ {
struct target_pollfd *target_pfd; struct target_pollfd *target_pfd;
unsigned int nfds = arg2; unsigned int nfds = arg2;
@ -6242,12 +6262,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1); target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
if (!target_pfd) if (!target_pfd)
goto efault; goto efault;
pfd = alloca(sizeof(struct pollfd) * nfds); pfd = alloca(sizeof(struct pollfd) * nfds);
for(i = 0; i < nfds; i++) { for(i = 0; i < nfds; i++) {
pfd[i].fd = tswap32(target_pfd[i].fd); pfd[i].fd = tswap32(target_pfd[i].fd);
pfd[i].events = tswap16(target_pfd[i].events); pfd[i].events = tswap16(target_pfd[i].events);
} }
ret = get_errno(poll(pfd, nfds, timeout));
# ifdef TARGET_NR_ppoll
if (num == TARGET_NR_ppoll) {
struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
target_sigset_t *target_set;
sigset_t _set, *set = &_set;
if (arg3) {
if (target_to_host_timespec(timeout_ts, arg3)) {
unlock_user(target_pfd, arg1, 0);
goto efault;
}
} else {
timeout_ts = NULL;
}
if (arg4) {
target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
if (!target_set) {
unlock_user(target_pfd, arg1, 0);
goto efault;
}
target_to_host_sigset(set, target_set);
} else {
set = NULL;
}
ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
if (!is_error(ret) && arg3) {
host_to_target_timespec(arg3, timeout_ts);
}
if (arg4) {
unlock_user(target_set, arg4, 0);
}
} else
# endif
ret = get_errno(poll(pfd, nfds, timeout));
if (!is_error(ret)) { if (!is_error(ret)) {
for(i = 0; i < nfds; i++) { for(i = 0; i < nfds; i++) {
target_pfd[i].revents = tswap16(pfd[i].revents); target_pfd[i].revents = tswap16(pfd[i].revents);
@ -6301,6 +6360,67 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
return value. */ return value. */
ret = -TARGET_ENOTDIR; ret = -TARGET_ENOTDIR;
break; break;
case TARGET_NR_sched_getaffinity:
{
unsigned int mask_size;
unsigned long *mask;
/*
* sched_getaffinity needs multiples of ulong, so need to take
* care of mismatches between target ulong and host ulong sizes.
*/
if (arg2 & (sizeof(abi_ulong) - 1)) {
ret = -TARGET_EINVAL;
break;
}
mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
mask = alloca(mask_size);
ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
if (!is_error(ret)) {
if (arg2 > ret) {
/* Zero out any extra space kernel didn't fill */
unsigned long zero = arg2 - ret;
p = alloca(zero);
memset(p, 0, zero);
if (copy_to_user(arg3 + zero, p, zero)) {
goto efault;
}
arg2 = ret;
}
if (copy_to_user(arg3, mask, arg2)) {
goto efault;
}
ret = arg2;
}
}
break;
case TARGET_NR_sched_setaffinity:
{
unsigned int mask_size;
unsigned long *mask;
/*
* sched_setaffinity needs multiples of ulong, so need to take
* care of mismatches between target ulong and host ulong sizes.
*/
if (arg2 & (sizeof(abi_ulong) - 1)) {
ret = -TARGET_EINVAL;
break;
}
mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
mask = alloca(mask_size);
if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
goto efault;
}
memcpy(mask, p, arg2);
unlock_user_struct(p, arg2, 0);
ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
}
break;
case TARGET_NR_sched_setparam: case TARGET_NR_sched_setparam:
{ {
struct sched_param *target_schp; struct sched_param *target_schp;

View File

@ -999,6 +999,7 @@ struct target_winsize {
#define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */ #define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */
#define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ #define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
#define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */ #define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */
#define TARGET_MAP_UNINITIALIZED 0x4000000 /* for anonymous mmap, memory could be uninitialized */
#endif #endif
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS) #if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)

10
linux-user/target_flat.h Normal file
View File

@ -0,0 +1,10 @@
/* If your arch needs to do custom stuff, create your own target_flat.h
* header file in linux-user/<your arch>/
*/
#define flat_argvp_envp_on_stack() 1
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_old_ram_flag(flag) (flag)
#define flat_get_relocate_addr(relval) (relval)
#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp)
#define flat_set_persistent(relval, persistent) (*persistent)
#define flat_put_addr_at_rp(rp, addr, relval) put_user_ual(addr, rp)

28
path.c
View File

@ -38,7 +38,8 @@ static int strneq(const char *s1, unsigned int n, const char *s2)
return s2[i] == 0; return s2[i] == 0;
} }
static struct pathelem *add_entry(struct pathelem *root, const char *name); static struct pathelem *add_entry(struct pathelem *root, const char *name,
unsigned char type);
static struct pathelem *new_entry(const char *root, static struct pathelem *new_entry(const char *root,
struct pathelem *parent, struct pathelem *parent,
@ -56,6 +57,15 @@ static struct pathelem *new_entry(const char *root,
#define streq(a,b) (strcmp((a), (b)) == 0) #define streq(a,b) (strcmp((a), (b)) == 0)
/* Not all systems provide this feature */
#if defined(DT_DIR) && defined(DT_UNKNOWN)
# define dirent_type(dirent) ((dirent)->d_type)
# define is_dir_maybe(type) ((type) == DT_DIR || (type) == DT_UNKNOWN)
#else
# define dirent_type(dirent) (1)
# define is_dir_maybe(type) (type)
#endif
static struct pathelem *add_dir_maybe(struct pathelem *path) static struct pathelem *add_dir_maybe(struct pathelem *path)
{ {
DIR *dir; DIR *dir;
@ -65,7 +75,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
while ((dirent = readdir(dir)) != NULL) { while ((dirent = readdir(dir)) != NULL) {
if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){ if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
path = add_entry(path, dirent->d_name); path = add_entry(path, dirent->d_name, dirent_type(dirent));
} }
} }
closedir(dir); closedir(dir);
@ -73,16 +83,22 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
return path; return path;
} }
static struct pathelem *add_entry(struct pathelem *root, const char *name) static struct pathelem *add_entry(struct pathelem *root, const char *name,
unsigned char type)
{ {
struct pathelem **e;
root->num_entries++; root->num_entries++;
root = realloc(root, sizeof(*root) root = realloc(root, sizeof(*root)
+ sizeof(root->entries[0])*root->num_entries); + sizeof(root->entries[0])*root->num_entries);
e = &root->entries[root->num_entries-1];
*e = new_entry(root->pathname, root, name);
if (is_dir_maybe(type)) {
*e = add_dir_maybe(*e);
}
root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
root->entries[root->num_entries-1]
= add_dir_maybe(root->entries[root->num_entries-1]);
return root; return root;
} }