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:
commit
1c0de9fa50
@ -107,7 +107,7 @@ ifdef CONFIG_LINUX_USER
|
||||
|
||||
$(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 \
|
||||
elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
|
||||
qemu-malloc.o $(oslib-obj-y)
|
||||
|
19
elf.h
19
elf.h
@ -1191,6 +1191,25 @@ typedef struct elf64_note {
|
||||
Elf64_Word n_type; /* Content type */
|
||||
} 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
|
||||
#if ELF_CLASS == ELFCLASS32
|
||||
|
||||
|
@ -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,
|
||||
struct elfhdr *exec,
|
||||
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);
|
||||
|
||||
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;
|
||||
k_platform = ELF_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);
|
||||
|
||||
#ifdef CONFIG_USE_FDPIC
|
||||
info->nsegs = 0;
|
||||
info->pt_dynamic_addr = 0;
|
||||
#endif
|
||||
|
||||
/* Find the maximum size of the image and allocate an appropriate
|
||||
amount of memory to handle that. */
|
||||
loaddr = -1, hiaddr = 0;
|
||||
@ -1210,6 +1257,9 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
if (a > hiaddr) {
|
||||
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;
|
||||
|
||||
#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_addr = load_addr;
|
||||
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;
|
||||
char *strings;
|
||||
struct syminfo *s;
|
||||
struct elf_sym *syms;
|
||||
struct elf_sym *syms, *new_syms;
|
||||
|
||||
shnum = hdr->e_shnum;
|
||||
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
|
||||
memory allocation depends on the malloc implementation and how
|
||||
many symbols we managed to discard. */
|
||||
syms = realloc(syms, nsyms * sizeof(*syms));
|
||||
if (syms == NULL) {
|
||||
new_syms = realloc(syms, nsyms * sizeof(*syms));
|
||||
if (new_syms == NULL) {
|
||||
free(s);
|
||||
free(syms);
|
||||
free(strings);
|
||||
return;
|
||||
}
|
||||
syms = new_syms;
|
||||
|
||||
qsort(syms, nsyms, sizeof(*syms), symcmp);
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
#include "qemu.h"
|
||||
#include "flat.h"
|
||||
#define ntohl(x) be32_to_cpu(x)
|
||||
#include <target_flat.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
@ -50,14 +52,6 @@
|
||||
#define DBG_FLT(...)
|
||||
#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 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;
|
||||
|
||||
#define ntohl(x) be32_to_cpu(x)
|
||||
|
||||
/****************************************************************************/
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
if (rev > OLD_FLAT_VERSION) {
|
||||
abi_ulong persistent = 0;
|
||||
for (i = 0; i < relocs; i++) {
|
||||
abi_ulong addr, relval;
|
||||
|
||||
@ -633,6 +626,9 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
relocated first). */
|
||||
if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
|
||||
return -EFAULT;
|
||||
relval = ntohl(relval);
|
||||
if (flat_set_persistent(relval, &persistent))
|
||||
continue;
|
||||
addr = flat_get_relocate_addr(relval);
|
||||
rp = calc_reloc(addr, libinfo, id, 1);
|
||||
if (rp == RELOC_FAILED)
|
||||
@ -641,22 +637,20 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||
/* Get the pointer's value. */
|
||||
if (get_user_ual(addr, rp))
|
||||
return -EFAULT;
|
||||
addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
|
||||
if (addr != 0) {
|
||||
/*
|
||||
* Do the relocation. PIC relocs in the data section are
|
||||
* already in target order
|
||||
*/
|
||||
|
||||
#ifndef TARGET_WORDS_BIGENDIAN
|
||||
if ((flags & FLAT_FLAG_GOTPIC) == 0)
|
||||
addr = bswap32(addr);
|
||||
#endif
|
||||
addr = ntohl(addr);
|
||||
addr = calc_reloc(addr, libinfo, id, 0);
|
||||
if (addr == RELOC_FAILED)
|
||||
return -ENOEXEC;
|
||||
|
||||
/* Write back the relocated pointer. */
|
||||
if (put_user_ual(addr, rp))
|
||||
if (flat_put_addr_at_rp(rp, addr, relval))
|
||||
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
|
||||
* a lot of entries.
|
||||
*/
|
||||
#define TOP_OF_ARGS (TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
|
||||
stack_len = TOP_OF_ARGS - bprm->p; /* the strings */
|
||||
stack_len = 0;
|
||||
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->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);
|
||||
if ((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
|
||||
* initialise library in order for us. We are required to call
|
||||
|
@ -312,10 +312,8 @@
|
||||
IOCTL(LOOP_CLR_FD, 0, TYPE_INT)
|
||||
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)))
|
||||
#if 0 /* These have some problems - not fully tested */
|
||||
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)))
|
||||
#endif
|
||||
IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT)
|
||||
|
||||
IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop)))
|
||||
|
@ -2624,14 +2624,21 @@ void cpu_loop (CPUState *env)
|
||||
}
|
||||
#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)
|
||||
{
|
||||
printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
|
||||
"usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
|
||||
version();
|
||||
printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
|
||||
"Linux CPU emulator (compiled for %s emulation)\n"
|
||||
"\n"
|
||||
"Standard options:\n"
|
||||
"-h print this help\n"
|
||||
"-version display version information and exit\n"
|
||||
"-g port wait gdb connection to port\n"
|
||||
"-L path set the elf interpreter prefix (default=%s)\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;
|
||||
} else if (!strcmp(r, "strace")) {
|
||||
do_strace = 1;
|
||||
} else
|
||||
{
|
||||
} else if (!strcmp(r, "version")) {
|
||||
version();
|
||||
exit(0);
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,13 @@ struct image_info {
|
||||
abi_ulong arg_start;
|
||||
abi_ulong arg_end;
|
||||
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
|
||||
|
@ -398,6 +398,7 @@ UNUSED static struct flags mmap_flags[] = {
|
||||
FLAG_TARGET(MAP_DENYWRITE),
|
||||
FLAG_TARGET(MAP_FIXED),
|
||||
FLAG_TARGET(MAP_GROWSDOWN),
|
||||
FLAG_TARGET(MAP_EXECUTABLE),
|
||||
#ifdef MAP_LOCKED
|
||||
FLAG_TARGET(MAP_LOCKED),
|
||||
#endif
|
||||
@ -407,6 +408,9 @@ UNUSED static struct flags mmap_flags[] = {
|
||||
FLAG_TARGET(MAP_NORESERVE),
|
||||
#ifdef MAP_POPULATE
|
||||
FLAG_TARGET(MAP_POPULATE),
|
||||
#endif
|
||||
#ifdef TARGET_MAP_UNINITIALIZED
|
||||
FLAG_TARGET(MAP_UNINITIALIZED),
|
||||
#endif
|
||||
FLAG_END,
|
||||
};
|
||||
@ -1199,7 +1203,7 @@ print_utimensat(const struct syscallname *name,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_mmap
|
||||
#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
|
||||
static void
|
||||
print_mmap(const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
|
@ -235,6 +235,12 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
|
||||
const struct timespec *,timeout,int *,uaddr2,int,val3)
|
||||
#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[] = {
|
||||
{ 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
|
||||
#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 flock(int, int);
|
||||
@ -1448,7 +1463,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
|
||||
return -TARGET_EFAULT;
|
||||
if (len < 0)
|
||||
return -TARGET_EINVAL;
|
||||
lv = sizeof(int);
|
||||
lv = sizeof(lv);
|
||||
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -1485,7 +1500,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
|
||||
return -TARGET_EFAULT;
|
||||
if (len < 0)
|
||||
return -TARGET_EINVAL;
|
||||
lv = sizeof(int);
|
||||
lv = sizeof(lv);
|
||||
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
|
||||
if (ret < 0)
|
||||
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);
|
||||
break;
|
||||
#endif
|
||||
#ifdef TARGET_NR_poll
|
||||
#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
|
||||
# ifdef TARGET_NR_poll
|
||||
case TARGET_NR_poll:
|
||||
# endif
|
||||
# ifdef TARGET_NR_ppoll
|
||||
case TARGET_NR_ppoll:
|
||||
# endif
|
||||
{
|
||||
struct target_pollfd *target_pfd;
|
||||
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);
|
||||
if (!target_pfd)
|
||||
goto efault;
|
||||
|
||||
pfd = alloca(sizeof(struct pollfd) * nfds);
|
||||
for(i = 0; i < nfds; i++) {
|
||||
pfd[i].fd = tswap32(target_pfd[i].fd);
|
||||
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)) {
|
||||
for(i = 0; i < nfds; i++) {
|
||||
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. */
|
||||
ret = -TARGET_ENOTDIR;
|
||||
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:
|
||||
{
|
||||
struct sched_param *target_schp;
|
||||
|
@ -999,6 +999,7 @@ struct target_winsize {
|
||||
#define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */
|
||||
#define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
|
||||
#define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */
|
||||
#define TARGET_MAP_UNINITIALIZED 0x4000000 /* for anonymous mmap, memory could be uninitialized */
|
||||
#endif
|
||||
|
||||
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
|
||||
|
10
linux-user/target_flat.h
Normal file
10
linux-user/target_flat.h
Normal 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
28
path.c
@ -38,7 +38,8 @@ static int strneq(const char *s1, unsigned int n, const char *s2)
|
||||
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,
|
||||
struct pathelem *parent,
|
||||
@ -56,6 +57,15 @@ static struct pathelem *new_entry(const char *root,
|
||||
|
||||
#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)
|
||||
{
|
||||
DIR *dir;
|
||||
@ -65,7 +75,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
|
||||
|
||||
while ((dirent = readdir(dir)) != NULL) {
|
||||
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);
|
||||
@ -73,16 +83,22 @@ static struct pathelem *add_dir_maybe(struct pathelem *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 = realloc(root, sizeof(*root)
|
||||
+ 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user