166e63ce3Schristos /* m32r exception, interrupt, and trap (EIT) support 2*c03b94e9Schristos Copyright (C) 1998-2016 Free Software Foundation, Inc. 366e63ce3Schristos Contributed by Renesas. 466e63ce3Schristos 566e63ce3Schristos This file is part of GDB, the GNU debugger. 666e63ce3Schristos 766e63ce3Schristos This program is free software; you can redistribute it and/or modify 866e63ce3Schristos it under the terms of the GNU General Public License as published by 966e63ce3Schristos the Free Software Foundation; either version 3 of the License, or 1066e63ce3Schristos (at your option) any later version. 1166e63ce3Schristos 1266e63ce3Schristos This program is distributed in the hope that it will be useful, 1366e63ce3Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 1466e63ce3Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1566e63ce3Schristos GNU General Public License for more details. 1666e63ce3Schristos 1766e63ce3Schristos You should have received a copy of the GNU General Public License 1866e63ce3Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1966e63ce3Schristos 2066e63ce3Schristos #include "sim-main.h" 21ed6a76a9Schristos #include "sim-syscall.h" 2266e63ce3Schristos #include "syscall.h" 2366e63ce3Schristos #include "targ-vals.h" 2466e63ce3Schristos #include <dirent.h> 2566e63ce3Schristos #include <errno.h> 2666e63ce3Schristos #include <fcntl.h> 2766e63ce3Schristos #include <time.h> 2866e63ce3Schristos #include <unistd.h> 2966e63ce3Schristos #include <utime.h> 3066e63ce3Schristos #include <sys/mman.h> 3166e63ce3Schristos #include <sys/poll.h> 3266e63ce3Schristos #include <sys/resource.h> 3366e63ce3Schristos #include <sys/sysinfo.h> 3466e63ce3Schristos #include <sys/stat.h> 3566e63ce3Schristos #include <sys/time.h> 3666e63ce3Schristos #include <sys/timeb.h> 3766e63ce3Schristos #include <sys/timex.h> 3866e63ce3Schristos #include <sys/types.h> 3966e63ce3Schristos #include <sys/uio.h> 4066e63ce3Schristos #include <sys/utsname.h> 4166e63ce3Schristos #include <sys/vfs.h> 4266e63ce3Schristos #include <linux/sysctl.h> 4366e63ce3Schristos #include <linux/types.h> 4466e63ce3Schristos #include <linux/unistd.h> 4566e63ce3Schristos 4666e63ce3Schristos #define TRAP_ELF_SYSCALL 0 4766e63ce3Schristos #define TRAP_LINUX_SYSCALL 2 4866e63ce3Schristos #define TRAP_FLUSH_CACHE 12 4966e63ce3Schristos 5066e63ce3Schristos /* The semantic code invokes this for invalid (unrecognized) instructions. */ 5166e63ce3Schristos 5266e63ce3Schristos SEM_PC 5366e63ce3Schristos sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) 5466e63ce3Schristos { 5566e63ce3Schristos SIM_DESC sd = CPU_STATE (current_cpu); 5666e63ce3Schristos 5766e63ce3Schristos #if 0 5866e63ce3Schristos if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) 5966e63ce3Schristos { 6066e63ce3Schristos h_bsm_set (current_cpu, h_sm_get (current_cpu)); 6166e63ce3Schristos h_bie_set (current_cpu, h_ie_get (current_cpu)); 6266e63ce3Schristos h_bcond_set (current_cpu, h_cond_get (current_cpu)); 6366e63ce3Schristos /* sm not changed */ 6466e63ce3Schristos h_ie_set (current_cpu, 0); 6566e63ce3Schristos h_cond_set (current_cpu, 0); 6666e63ce3Schristos 6766e63ce3Schristos h_bpc_set (current_cpu, cia); 6866e63ce3Schristos 6966e63ce3Schristos sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, 7066e63ce3Schristos EIT_RSVD_INSN_ADDR); 7166e63ce3Schristos } 7266e63ce3Schristos else 7366e63ce3Schristos #endif 7466e63ce3Schristos sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); 7566e63ce3Schristos return vpc; 7666e63ce3Schristos } 7766e63ce3Schristos 7866e63ce3Schristos /* Process an address exception. */ 7966e63ce3Schristos 8066e63ce3Schristos void 8166e63ce3Schristos m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, 8266e63ce3Schristos unsigned int map, int nr_bytes, address_word addr, 8366e63ce3Schristos transfer_type transfer, sim_core_signals sig) 8466e63ce3Schristos { 8566e63ce3Schristos if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) 8666e63ce3Schristos { 8766e63ce3Schristos m32rbf_h_cr_set (current_cpu, H_CR_BBPC, 8866e63ce3Schristos m32rbf_h_cr_get (current_cpu, H_CR_BPC)); 8966e63ce3Schristos if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32R) 9066e63ce3Schristos { 9166e63ce3Schristos m32rbf_h_bpsw_set (current_cpu, m32rbf_h_psw_get (current_cpu)); 9266e63ce3Schristos /* sm not changed */ 9366e63ce3Schristos m32rbf_h_psw_set (current_cpu, m32rbf_h_psw_get (current_cpu) & 0x80); 9466e63ce3Schristos } 9566e63ce3Schristos else if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32RX) 9666e63ce3Schristos { 9766e63ce3Schristos m32rxf_h_bpsw_set (current_cpu, m32rxf_h_psw_get (current_cpu)); 9866e63ce3Schristos /* sm not changed */ 9966e63ce3Schristos m32rxf_h_psw_set (current_cpu, m32rxf_h_psw_get (current_cpu) & 0x80); 10066e63ce3Schristos } 10166e63ce3Schristos else 10266e63ce3Schristos { 10366e63ce3Schristos m32r2f_h_bpsw_set (current_cpu, m32r2f_h_psw_get (current_cpu)); 10466e63ce3Schristos /* sm not changed */ 10566e63ce3Schristos m32r2f_h_psw_set (current_cpu, m32r2f_h_psw_get (current_cpu) & 0x80); 10666e63ce3Schristos } 10766e63ce3Schristos m32rbf_h_cr_set (current_cpu, H_CR_BPC, cia); 10866e63ce3Schristos 10966e63ce3Schristos sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, 11066e63ce3Schristos EIT_ADDR_EXCP_ADDR); 11166e63ce3Schristos } 11266e63ce3Schristos else 11366e63ce3Schristos sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, 11466e63ce3Schristos transfer, sig); 11566e63ce3Schristos } 11666e63ce3Schristos 11766e63ce3Schristos /* Translate target's address to host's address. */ 11866e63ce3Schristos 11966e63ce3Schristos static void * 12066e63ce3Schristos t2h_addr (host_callback *cb, struct cb_syscall *sc, 12166e63ce3Schristos unsigned long taddr) 12266e63ce3Schristos { 12366e63ce3Schristos void *addr; 12466e63ce3Schristos SIM_DESC sd = (SIM_DESC) sc->p1; 12566e63ce3Schristos SIM_CPU *cpu = (SIM_CPU *) sc->p2; 12666e63ce3Schristos 12766e63ce3Schristos if (taddr == 0) 12866e63ce3Schristos return NULL; 12966e63ce3Schristos 13066e63ce3Schristos return sim_core_trans_addr (sd, cpu, read_map, taddr); 13166e63ce3Schristos } 13266e63ce3Schristos 13366e63ce3Schristos static unsigned int 13466e63ce3Schristos conv_endian (unsigned int tvalue) 13566e63ce3Schristos { 13666e63ce3Schristos unsigned int hvalue; 13766e63ce3Schristos unsigned int t1, t2, t3, t4; 13866e63ce3Schristos 139*c03b94e9Schristos if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE) 14066e63ce3Schristos { 14166e63ce3Schristos t1 = tvalue & 0xff000000; 14266e63ce3Schristos t2 = tvalue & 0x00ff0000; 14366e63ce3Schristos t3 = tvalue & 0x0000ff00; 14466e63ce3Schristos t4 = tvalue & 0x000000ff; 14566e63ce3Schristos 14666e63ce3Schristos hvalue = t1 >> 24; 14766e63ce3Schristos hvalue += t2 >> 8; 14866e63ce3Schristos hvalue += t3 << 8; 14966e63ce3Schristos hvalue += t4 << 24; 15066e63ce3Schristos } 15166e63ce3Schristos else 15266e63ce3Schristos hvalue = tvalue; 15366e63ce3Schristos 15466e63ce3Schristos return hvalue; 15566e63ce3Schristos } 15666e63ce3Schristos 15766e63ce3Schristos static unsigned short 15866e63ce3Schristos conv_endian16 (unsigned short tvalue) 15966e63ce3Schristos { 16066e63ce3Schristos unsigned short hvalue; 16166e63ce3Schristos unsigned short t1, t2; 16266e63ce3Schristos 163*c03b94e9Schristos if (HOST_BYTE_ORDER == BFD_ENDIAN_LITTLE) 16466e63ce3Schristos { 16566e63ce3Schristos t1 = tvalue & 0xff00; 16666e63ce3Schristos t2 = tvalue & 0x00ff; 16766e63ce3Schristos 16866e63ce3Schristos hvalue = t1 >> 8; 16966e63ce3Schristos hvalue += t2 << 8; 17066e63ce3Schristos } 17166e63ce3Schristos else 17266e63ce3Schristos hvalue = tvalue; 17366e63ce3Schristos 17466e63ce3Schristos return hvalue; 17566e63ce3Schristos } 17666e63ce3Schristos 17766e63ce3Schristos static void 17866e63ce3Schristos translate_endian(void *addr, size_t size) 17966e63ce3Schristos { 18066e63ce3Schristos unsigned int *p = (unsigned int *) addr; 18166e63ce3Schristos int i; 18266e63ce3Schristos 18366e63ce3Schristos for (i = 0; i <= size - 4; i += 4,p++) 18466e63ce3Schristos *p = conv_endian(*p); 18566e63ce3Schristos 18666e63ce3Schristos if (i <= size - 2) 18766e63ce3Schristos *((unsigned short *) p) = conv_endian16(*((unsigned short *) p)); 18866e63ce3Schristos } 18966e63ce3Schristos 19066e63ce3Schristos /* Trap support. 19166e63ce3Schristos The result is the pc address to continue at. 19266e63ce3Schristos Preprocessing like saving the various registers has already been done. */ 19366e63ce3Schristos 19466e63ce3Schristos USI 19566e63ce3Schristos m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) 19666e63ce3Schristos { 19766e63ce3Schristos SIM_DESC sd = CPU_STATE (current_cpu); 19866e63ce3Schristos host_callback *cb = STATE_CALLBACK (sd); 19966e63ce3Schristos 20066e63ce3Schristos switch (num) 20166e63ce3Schristos { 20266e63ce3Schristos case TRAP_ELF_SYSCALL : 20366e63ce3Schristos { 204ed6a76a9Schristos long result, result2; 205ed6a76a9Schristos int errcode; 20666e63ce3Schristos 207ed6a76a9Schristos sim_syscall_multi (current_cpu, 208ed6a76a9Schristos m32rbf_h_gr_get (current_cpu, 0), 209ed6a76a9Schristos m32rbf_h_gr_get (current_cpu, 1), 210ed6a76a9Schristos m32rbf_h_gr_get (current_cpu, 2), 211ed6a76a9Schristos m32rbf_h_gr_get (current_cpu, 3), 212ed6a76a9Schristos m32rbf_h_gr_get (current_cpu, 4), 213ed6a76a9Schristos &result, &result2, &errcode); 21466e63ce3Schristos 215ed6a76a9Schristos m32rbf_h_gr_set (current_cpu, 2, errcode); 216ed6a76a9Schristos m32rbf_h_gr_set (current_cpu, 0, result); 217ed6a76a9Schristos m32rbf_h_gr_set (current_cpu, 1, result2); 21866e63ce3Schristos break; 21966e63ce3Schristos } 22066e63ce3Schristos 22166e63ce3Schristos case TRAP_LINUX_SYSCALL : 22266e63ce3Schristos { 22366e63ce3Schristos CB_SYSCALL s; 22466e63ce3Schristos unsigned int func, arg1, arg2, arg3, arg4, arg5, arg6, arg7; 22566e63ce3Schristos int result, result2, errcode; 22666e63ce3Schristos 22766e63ce3Schristos if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) 22866e63ce3Schristos { 22966e63ce3Schristos /* The new pc is the trap vector entry. 23066e63ce3Schristos We assume there's a branch there to some handler. 23166e63ce3Schristos Use cr5 as EVB (EIT Vector Base) register. */ 23266e63ce3Schristos USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; 23366e63ce3Schristos return new_pc; 23466e63ce3Schristos } 23566e63ce3Schristos 23666e63ce3Schristos func = m32rbf_h_gr_get (current_cpu, 7); 23766e63ce3Schristos arg1 = m32rbf_h_gr_get (current_cpu, 0); 23866e63ce3Schristos arg2 = m32rbf_h_gr_get (current_cpu, 1); 23966e63ce3Schristos arg3 = m32rbf_h_gr_get (current_cpu, 2); 24066e63ce3Schristos arg4 = m32rbf_h_gr_get (current_cpu, 3); 24166e63ce3Schristos arg5 = m32rbf_h_gr_get (current_cpu, 4); 24266e63ce3Schristos arg6 = m32rbf_h_gr_get (current_cpu, 5); 24366e63ce3Schristos arg7 = m32rbf_h_gr_get (current_cpu, 6); 24466e63ce3Schristos 24566e63ce3Schristos CB_SYSCALL_INIT (&s); 24666e63ce3Schristos s.func = func; 24766e63ce3Schristos s.arg1 = arg1; 24866e63ce3Schristos s.arg2 = arg2; 24966e63ce3Schristos s.arg3 = arg3; 25066e63ce3Schristos 25166e63ce3Schristos s.p1 = (PTR) sd; 25266e63ce3Schristos s.p2 = (PTR) current_cpu; 253ed6a76a9Schristos s.read_mem = sim_syscall_read_mem; 254ed6a76a9Schristos s.write_mem = sim_syscall_write_mem; 25566e63ce3Schristos 25666e63ce3Schristos result = 0; 25766e63ce3Schristos result2 = 0; 25866e63ce3Schristos errcode = 0; 25966e63ce3Schristos 26066e63ce3Schristos switch (func) 26166e63ce3Schristos { 26266e63ce3Schristos case __NR_exit: 26366e63ce3Schristos sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1); 26466e63ce3Schristos break; 26566e63ce3Schristos 26666e63ce3Schristos case __NR_read: 26766e63ce3Schristos result = read(arg1, t2h_addr(cb, &s, arg2), arg3); 26866e63ce3Schristos errcode = errno; 26966e63ce3Schristos break; 27066e63ce3Schristos 27166e63ce3Schristos case __NR_write: 27266e63ce3Schristos result = write(arg1, t2h_addr(cb, &s, arg2), arg3); 27366e63ce3Schristos errcode = errno; 27466e63ce3Schristos break; 27566e63ce3Schristos 27666e63ce3Schristos case __NR_open: 27766e63ce3Schristos result = open((char *) t2h_addr(cb, &s, arg1), arg2, arg3); 27866e63ce3Schristos errcode = errno; 27966e63ce3Schristos break; 28066e63ce3Schristos 28166e63ce3Schristos case __NR_close: 28266e63ce3Schristos result = close(arg1); 28366e63ce3Schristos errcode = errno; 28466e63ce3Schristos break; 28566e63ce3Schristos 28666e63ce3Schristos case __NR_creat: 28766e63ce3Schristos result = creat((char *) t2h_addr(cb, &s, arg1), arg2); 28866e63ce3Schristos errcode = errno; 28966e63ce3Schristos break; 29066e63ce3Schristos 29166e63ce3Schristos case __NR_link: 29266e63ce3Schristos result = link((char *) t2h_addr(cb, &s, arg1), 29366e63ce3Schristos (char *) t2h_addr(cb, &s, arg2)); 29466e63ce3Schristos errcode = errno; 29566e63ce3Schristos break; 29666e63ce3Schristos 29766e63ce3Schristos case __NR_unlink: 29866e63ce3Schristos result = unlink((char *) t2h_addr(cb, &s, arg1)); 29966e63ce3Schristos errcode = errno; 30066e63ce3Schristos break; 30166e63ce3Schristos 30266e63ce3Schristos case __NR_chdir: 30366e63ce3Schristos result = chdir((char *) t2h_addr(cb, &s, arg1)); 30466e63ce3Schristos errcode = errno; 30566e63ce3Schristos break; 30666e63ce3Schristos 30766e63ce3Schristos case __NR_time: 30866e63ce3Schristos { 30966e63ce3Schristos time_t t; 31066e63ce3Schristos 31166e63ce3Schristos if (arg1 == 0) 31266e63ce3Schristos { 31366e63ce3Schristos result = (int) time(NULL); 31466e63ce3Schristos errcode = errno; 31566e63ce3Schristos } 31666e63ce3Schristos else 31766e63ce3Schristos { 31866e63ce3Schristos result = (int) time(&t); 31966e63ce3Schristos errcode = errno; 32066e63ce3Schristos 32166e63ce3Schristos if (result != 0) 32266e63ce3Schristos break; 32366e63ce3Schristos 32466e63ce3Schristos translate_endian((void *) &t, sizeof(t)); 32566e63ce3Schristos if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t)) 32666e63ce3Schristos { 32766e63ce3Schristos result = -1; 32866e63ce3Schristos errcode = EINVAL; 32966e63ce3Schristos } 33066e63ce3Schristos } 33166e63ce3Schristos } 33266e63ce3Schristos break; 33366e63ce3Schristos 33466e63ce3Schristos case __NR_mknod: 33566e63ce3Schristos result = mknod((char *) t2h_addr(cb, &s, arg1), 33666e63ce3Schristos (mode_t) arg2, (dev_t) arg3); 33766e63ce3Schristos errcode = errno; 33866e63ce3Schristos break; 33966e63ce3Schristos 34066e63ce3Schristos case __NR_chmod: 34166e63ce3Schristos result = chmod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2); 34266e63ce3Schristos errcode = errno; 34366e63ce3Schristos break; 34466e63ce3Schristos 34566e63ce3Schristos case __NR_lchown32: 34666e63ce3Schristos case __NR_lchown: 34766e63ce3Schristos result = lchown((char *) t2h_addr(cb, &s, arg1), 34866e63ce3Schristos (uid_t) arg2, (gid_t) arg3); 34966e63ce3Schristos errcode = errno; 35066e63ce3Schristos break; 35166e63ce3Schristos 35266e63ce3Schristos case __NR_lseek: 35366e63ce3Schristos result = (int) lseek(arg1, (off_t) arg2, arg3); 35466e63ce3Schristos errcode = errno; 35566e63ce3Schristos break; 35666e63ce3Schristos 35766e63ce3Schristos case __NR_getpid: 35866e63ce3Schristos result = getpid(); 35966e63ce3Schristos errcode = errno; 36066e63ce3Schristos break; 36166e63ce3Schristos 36266e63ce3Schristos case __NR_getuid32: 36366e63ce3Schristos case __NR_getuid: 36466e63ce3Schristos result = getuid(); 36566e63ce3Schristos errcode = errno; 36666e63ce3Schristos break; 36766e63ce3Schristos 36866e63ce3Schristos case __NR_utime: 36966e63ce3Schristos { 37066e63ce3Schristos struct utimbuf buf; 37166e63ce3Schristos 37266e63ce3Schristos if (arg2 == 0) 37366e63ce3Schristos { 37466e63ce3Schristos result = utime((char *) t2h_addr(cb, &s, arg1), NULL); 37566e63ce3Schristos errcode = errno; 37666e63ce3Schristos } 37766e63ce3Schristos else 37866e63ce3Schristos { 37966e63ce3Schristos buf = *((struct utimbuf *) t2h_addr(cb, &s, arg2)); 38066e63ce3Schristos translate_endian((void *) &buf, sizeof(buf)); 38166e63ce3Schristos result = utime((char *) t2h_addr(cb, &s, arg1), &buf); 38266e63ce3Schristos errcode = errno; 38366e63ce3Schristos } 38466e63ce3Schristos } 38566e63ce3Schristos break; 38666e63ce3Schristos 38766e63ce3Schristos case __NR_access: 38866e63ce3Schristos result = access((char *) t2h_addr(cb, &s, arg1), arg2); 38966e63ce3Schristos errcode = errno; 39066e63ce3Schristos break; 39166e63ce3Schristos 39266e63ce3Schristos case __NR_ftime: 39366e63ce3Schristos { 39466e63ce3Schristos struct timeb t; 39566e63ce3Schristos 39666e63ce3Schristos result = ftime(&t); 39766e63ce3Schristos errcode = errno; 39866e63ce3Schristos 39966e63ce3Schristos if (result != 0) 40066e63ce3Schristos break; 40166e63ce3Schristos 40266e63ce3Schristos t.time = conv_endian(t.time); 40366e63ce3Schristos t.millitm = conv_endian16(t.millitm); 40466e63ce3Schristos t.timezone = conv_endian16(t.timezone); 40566e63ce3Schristos t.dstflag = conv_endian16(t.dstflag); 40666e63ce3Schristos if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) 40766e63ce3Schristos != sizeof(t)) 40866e63ce3Schristos { 40966e63ce3Schristos result = -1; 41066e63ce3Schristos errcode = EINVAL; 41166e63ce3Schristos } 41266e63ce3Schristos } 41366e63ce3Schristos 41466e63ce3Schristos case __NR_sync: 41566e63ce3Schristos sync(); 41666e63ce3Schristos result = 0; 41766e63ce3Schristos break; 41866e63ce3Schristos 41966e63ce3Schristos case __NR_rename: 42066e63ce3Schristos result = rename((char *) t2h_addr(cb, &s, arg1), 42166e63ce3Schristos (char *) t2h_addr(cb, &s, arg2)); 42266e63ce3Schristos errcode = errno; 42366e63ce3Schristos break; 42466e63ce3Schristos 42566e63ce3Schristos case __NR_mkdir: 42666e63ce3Schristos result = mkdir((char *) t2h_addr(cb, &s, arg1), arg2); 42766e63ce3Schristos errcode = errno; 42866e63ce3Schristos break; 42966e63ce3Schristos 43066e63ce3Schristos case __NR_rmdir: 43166e63ce3Schristos result = rmdir((char *) t2h_addr(cb, &s, arg1)); 43266e63ce3Schristos errcode = errno; 43366e63ce3Schristos break; 43466e63ce3Schristos 43566e63ce3Schristos case __NR_dup: 43666e63ce3Schristos result = dup(arg1); 43766e63ce3Schristos errcode = errno; 43866e63ce3Schristos break; 43966e63ce3Schristos 44066e63ce3Schristos case __NR_brk: 44166e63ce3Schristos result = brk((void *) arg1); 44266e63ce3Schristos errcode = errno; 44366e63ce3Schristos //result = arg1; 44466e63ce3Schristos break; 44566e63ce3Schristos 44666e63ce3Schristos case __NR_getgid32: 44766e63ce3Schristos case __NR_getgid: 44866e63ce3Schristos result = getgid(); 44966e63ce3Schristos errcode = errno; 45066e63ce3Schristos break; 45166e63ce3Schristos 45266e63ce3Schristos case __NR_geteuid32: 45366e63ce3Schristos case __NR_geteuid: 45466e63ce3Schristos result = geteuid(); 45566e63ce3Schristos errcode = errno; 45666e63ce3Schristos break; 45766e63ce3Schristos 45866e63ce3Schristos case __NR_getegid32: 45966e63ce3Schristos case __NR_getegid: 46066e63ce3Schristos result = getegid(); 46166e63ce3Schristos errcode = errno; 46266e63ce3Schristos break; 46366e63ce3Schristos 46466e63ce3Schristos case __NR_ioctl: 46566e63ce3Schristos result = ioctl(arg1, arg2, arg3); 46666e63ce3Schristos errcode = errno; 46766e63ce3Schristos break; 46866e63ce3Schristos 46966e63ce3Schristos case __NR_fcntl: 47066e63ce3Schristos result = fcntl(arg1, arg2, arg3); 47166e63ce3Schristos errcode = errno; 47266e63ce3Schristos break; 47366e63ce3Schristos 47466e63ce3Schristos case __NR_dup2: 47566e63ce3Schristos result = dup2(arg1, arg2); 47666e63ce3Schristos errcode = errno; 47766e63ce3Schristos break; 47866e63ce3Schristos 47966e63ce3Schristos case __NR_getppid: 48066e63ce3Schristos result = getppid(); 48166e63ce3Schristos errcode = errno; 48266e63ce3Schristos break; 48366e63ce3Schristos 48466e63ce3Schristos case __NR_getpgrp: 48566e63ce3Schristos result = getpgrp(); 48666e63ce3Schristos errcode = errno; 48766e63ce3Schristos break; 48866e63ce3Schristos 48966e63ce3Schristos case __NR_getrlimit: 49066e63ce3Schristos { 49166e63ce3Schristos struct rlimit rlim; 49266e63ce3Schristos 49366e63ce3Schristos result = getrlimit(arg1, &rlim); 49466e63ce3Schristos errcode = errno; 49566e63ce3Schristos 49666e63ce3Schristos if (result != 0) 49766e63ce3Schristos break; 49866e63ce3Schristos 49966e63ce3Schristos translate_endian((void *) &rlim, sizeof(rlim)); 50066e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &rlim, sizeof(rlim)) 50166e63ce3Schristos != sizeof(rlim)) 50266e63ce3Schristos { 50366e63ce3Schristos result = -1; 50466e63ce3Schristos errcode = EINVAL; 50566e63ce3Schristos } 50666e63ce3Schristos } 50766e63ce3Schristos break; 50866e63ce3Schristos 50966e63ce3Schristos case __NR_getrusage: 51066e63ce3Schristos { 51166e63ce3Schristos struct rusage usage; 51266e63ce3Schristos 51366e63ce3Schristos result = getrusage(arg1, &usage); 51466e63ce3Schristos errcode = errno; 51566e63ce3Schristos 51666e63ce3Schristos if (result != 0) 51766e63ce3Schristos break; 51866e63ce3Schristos 51966e63ce3Schristos translate_endian((void *) &usage, sizeof(usage)); 52066e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &usage, sizeof(usage)) 52166e63ce3Schristos != sizeof(usage)) 52266e63ce3Schristos { 52366e63ce3Schristos result = -1; 52466e63ce3Schristos errcode = EINVAL; 52566e63ce3Schristos } 52666e63ce3Schristos } 52766e63ce3Schristos break; 52866e63ce3Schristos 52966e63ce3Schristos case __NR_gettimeofday: 53066e63ce3Schristos { 53166e63ce3Schristos struct timeval tv; 53266e63ce3Schristos struct timezone tz; 53366e63ce3Schristos 53466e63ce3Schristos result = gettimeofday(&tv, &tz); 53566e63ce3Schristos errcode = errno; 53666e63ce3Schristos 53766e63ce3Schristos if (result != 0) 53866e63ce3Schristos break; 53966e63ce3Schristos 54066e63ce3Schristos translate_endian((void *) &tv, sizeof(tv)); 54166e63ce3Schristos if ((s.write_mem) (cb, &s, arg1, (char *) &tv, sizeof(tv)) 54266e63ce3Schristos != sizeof(tv)) 54366e63ce3Schristos { 54466e63ce3Schristos result = -1; 54566e63ce3Schristos errcode = EINVAL; 54666e63ce3Schristos } 54766e63ce3Schristos 54866e63ce3Schristos translate_endian((void *) &tz, sizeof(tz)); 54966e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &tz, sizeof(tz)) 55066e63ce3Schristos != sizeof(tz)) 55166e63ce3Schristos { 55266e63ce3Schristos result = -1; 55366e63ce3Schristos errcode = EINVAL; 55466e63ce3Schristos } 55566e63ce3Schristos } 55666e63ce3Schristos break; 55766e63ce3Schristos 55866e63ce3Schristos case __NR_getgroups32: 55966e63ce3Schristos case __NR_getgroups: 56066e63ce3Schristos { 56166e63ce3Schristos gid_t *list; 56266e63ce3Schristos 56366e63ce3Schristos if (arg1 > 0) 56466e63ce3Schristos list = (gid_t *) malloc(arg1 * sizeof(gid_t)); 56566e63ce3Schristos 56666e63ce3Schristos result = getgroups(arg1, list); 56766e63ce3Schristos errcode = errno; 56866e63ce3Schristos 56966e63ce3Schristos if (result != 0) 57066e63ce3Schristos break; 57166e63ce3Schristos 57266e63ce3Schristos translate_endian((void *) list, arg1 * sizeof(gid_t)); 57366e63ce3Schristos if (arg1 > 0) 57466e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) list, arg1 * sizeof(gid_t)) 57566e63ce3Schristos != arg1 * sizeof(gid_t)) 57666e63ce3Schristos { 57766e63ce3Schristos result = -1; 57866e63ce3Schristos errcode = EINVAL; 57966e63ce3Schristos } 58066e63ce3Schristos } 58166e63ce3Schristos break; 58266e63ce3Schristos 58366e63ce3Schristos case __NR_select: 58466e63ce3Schristos { 58566e63ce3Schristos int n; 58666e63ce3Schristos fd_set readfds; 58766e63ce3Schristos fd_set *treadfdsp; 58866e63ce3Schristos fd_set *hreadfdsp; 58966e63ce3Schristos fd_set writefds; 59066e63ce3Schristos fd_set *twritefdsp; 59166e63ce3Schristos fd_set *hwritefdsp; 59266e63ce3Schristos fd_set exceptfds; 59366e63ce3Schristos fd_set *texceptfdsp; 59466e63ce3Schristos fd_set *hexceptfdsp; 59566e63ce3Schristos struct timeval *ttimeoutp; 59666e63ce3Schristos struct timeval timeout; 59766e63ce3Schristos 59866e63ce3Schristos n = arg1; 59966e63ce3Schristos 60066e63ce3Schristos treadfdsp = (fd_set *) arg2; 60166e63ce3Schristos if (treadfdsp != NULL) 60266e63ce3Schristos { 60366e63ce3Schristos readfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) treadfdsp)); 60466e63ce3Schristos translate_endian((void *) &readfds, sizeof(readfds)); 60566e63ce3Schristos hreadfdsp = &readfds; 60666e63ce3Schristos } 60766e63ce3Schristos else 60866e63ce3Schristos hreadfdsp = NULL; 60966e63ce3Schristos 61066e63ce3Schristos twritefdsp = (fd_set *) arg3; 61166e63ce3Schristos if (twritefdsp != NULL) 61266e63ce3Schristos { 61366e63ce3Schristos writefds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) twritefdsp)); 61466e63ce3Schristos translate_endian((void *) &writefds, sizeof(writefds)); 61566e63ce3Schristos hwritefdsp = &writefds; 61666e63ce3Schristos } 61766e63ce3Schristos else 61866e63ce3Schristos hwritefdsp = NULL; 61966e63ce3Schristos 62066e63ce3Schristos texceptfdsp = (fd_set *) arg4; 62166e63ce3Schristos if (texceptfdsp != NULL) 62266e63ce3Schristos { 62366e63ce3Schristos exceptfds = *((fd_set *) t2h_addr(cb, &s, (unsigned int) texceptfdsp)); 62466e63ce3Schristos translate_endian((void *) &exceptfds, sizeof(exceptfds)); 62566e63ce3Schristos hexceptfdsp = &exceptfds; 62666e63ce3Schristos } 62766e63ce3Schristos else 62866e63ce3Schristos hexceptfdsp = NULL; 62966e63ce3Schristos 63066e63ce3Schristos ttimeoutp = (struct timeval *) arg5; 63166e63ce3Schristos timeout = *((struct timeval *) t2h_addr(cb, &s, (unsigned int) ttimeoutp)); 63266e63ce3Schristos translate_endian((void *) &timeout, sizeof(timeout)); 63366e63ce3Schristos 63466e63ce3Schristos result = select(n, hreadfdsp, hwritefdsp, hexceptfdsp, &timeout); 63566e63ce3Schristos errcode = errno; 63666e63ce3Schristos 63766e63ce3Schristos if (result != 0) 63866e63ce3Schristos break; 63966e63ce3Schristos 64066e63ce3Schristos if (treadfdsp != NULL) 64166e63ce3Schristos { 64266e63ce3Schristos translate_endian((void *) &readfds, sizeof(readfds)); 64366e63ce3Schristos if ((s.write_mem) (cb, &s, (unsigned long) treadfdsp, 64466e63ce3Schristos (char *) &readfds, sizeof(readfds)) != sizeof(readfds)) 64566e63ce3Schristos { 64666e63ce3Schristos result = -1; 64766e63ce3Schristos errcode = EINVAL; 64866e63ce3Schristos } 64966e63ce3Schristos } 65066e63ce3Schristos 65166e63ce3Schristos if (twritefdsp != NULL) 65266e63ce3Schristos { 65366e63ce3Schristos translate_endian((void *) &writefds, sizeof(writefds)); 65466e63ce3Schristos if ((s.write_mem) (cb, &s, (unsigned long) twritefdsp, 65566e63ce3Schristos (char *) &writefds, sizeof(writefds)) != sizeof(writefds)) 65666e63ce3Schristos { 65766e63ce3Schristos result = -1; 65866e63ce3Schristos errcode = EINVAL; 65966e63ce3Schristos } 66066e63ce3Schristos } 66166e63ce3Schristos 66266e63ce3Schristos if (texceptfdsp != NULL) 66366e63ce3Schristos { 66466e63ce3Schristos translate_endian((void *) &exceptfds, sizeof(exceptfds)); 66566e63ce3Schristos if ((s.write_mem) (cb, &s, (unsigned long) texceptfdsp, 66666e63ce3Schristos (char *) &exceptfds, sizeof(exceptfds)) != sizeof(exceptfds)) 66766e63ce3Schristos { 66866e63ce3Schristos result = -1; 66966e63ce3Schristos errcode = EINVAL; 67066e63ce3Schristos } 67166e63ce3Schristos } 67266e63ce3Schristos 67366e63ce3Schristos translate_endian((void *) &timeout, sizeof(timeout)); 67466e63ce3Schristos if ((s.write_mem) (cb, &s, (unsigned long) ttimeoutp, 67566e63ce3Schristos (char *) &timeout, sizeof(timeout)) != sizeof(timeout)) 67666e63ce3Schristos { 67766e63ce3Schristos result = -1; 67866e63ce3Schristos errcode = EINVAL; 67966e63ce3Schristos } 68066e63ce3Schristos } 68166e63ce3Schristos break; 68266e63ce3Schristos 68366e63ce3Schristos case __NR_symlink: 68466e63ce3Schristos result = symlink((char *) t2h_addr(cb, &s, arg1), 68566e63ce3Schristos (char *) t2h_addr(cb, &s, arg2)); 68666e63ce3Schristos errcode = errno; 68766e63ce3Schristos break; 68866e63ce3Schristos 68966e63ce3Schristos case __NR_readlink: 69066e63ce3Schristos result = readlink((char *) t2h_addr(cb, &s, arg1), 69166e63ce3Schristos (char *) t2h_addr(cb, &s, arg2), 69266e63ce3Schristos arg3); 69366e63ce3Schristos errcode = errno; 69466e63ce3Schristos break; 69566e63ce3Schristos 69666e63ce3Schristos case __NR_readdir: 69766e63ce3Schristos result = (int) readdir((DIR *) t2h_addr(cb, &s, arg1)); 69866e63ce3Schristos errcode = errno; 69966e63ce3Schristos break; 70066e63ce3Schristos 70166e63ce3Schristos #if 0 70266e63ce3Schristos case __NR_mmap: 70366e63ce3Schristos { 70466e63ce3Schristos result = (int) mmap((void *) t2h_addr(cb, &s, arg1), 70566e63ce3Schristos arg2, arg3, arg4, arg5, arg6); 70666e63ce3Schristos errcode = errno; 70766e63ce3Schristos 70866e63ce3Schristos if (errno == 0) 70966e63ce3Schristos { 71066e63ce3Schristos sim_core_attach (sd, NULL, 71166e63ce3Schristos 0, access_read_write_exec, 0, 71266e63ce3Schristos result, arg2, 0, NULL, NULL); 71366e63ce3Schristos } 71466e63ce3Schristos } 71566e63ce3Schristos break; 71666e63ce3Schristos #endif 71766e63ce3Schristos case __NR_mmap2: 71866e63ce3Schristos { 71966e63ce3Schristos void *addr; 72066e63ce3Schristos size_t len; 72166e63ce3Schristos int prot, flags, fildes; 72266e63ce3Schristos off_t off; 72366e63ce3Schristos 72466e63ce3Schristos addr = (void *) t2h_addr(cb, &s, arg1); 72566e63ce3Schristos len = arg2; 72666e63ce3Schristos prot = arg3; 72766e63ce3Schristos flags = arg4; 72866e63ce3Schristos fildes = arg5; 72966e63ce3Schristos off = arg6 << 12; 73066e63ce3Schristos 73166e63ce3Schristos result = (int) mmap(addr, len, prot, flags, fildes, off); 73266e63ce3Schristos errcode = errno; 73366e63ce3Schristos if (result != -1) 73466e63ce3Schristos { 73566e63ce3Schristos char c; 73666e63ce3Schristos if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0) 73766e63ce3Schristos sim_core_attach (sd, NULL, 73866e63ce3Schristos 0, access_read_write_exec, 0, 73966e63ce3Schristos result, len, 0, NULL, NULL); 74066e63ce3Schristos } 74166e63ce3Schristos } 74266e63ce3Schristos break; 74366e63ce3Schristos 74466e63ce3Schristos case __NR_mmap: 74566e63ce3Schristos { 74666e63ce3Schristos void *addr; 74766e63ce3Schristos size_t len; 74866e63ce3Schristos int prot, flags, fildes; 74966e63ce3Schristos off_t off; 75066e63ce3Schristos 75166e63ce3Schristos addr = *((void **) t2h_addr(cb, &s, arg1)); 75266e63ce3Schristos len = *((size_t *) t2h_addr(cb, &s, arg1 + 4)); 75366e63ce3Schristos prot = *((int *) t2h_addr(cb, &s, arg1 + 8)); 75466e63ce3Schristos flags = *((int *) t2h_addr(cb, &s, arg1 + 12)); 75566e63ce3Schristos fildes = *((int *) t2h_addr(cb, &s, arg1 + 16)); 75666e63ce3Schristos off = *((off_t *) t2h_addr(cb, &s, arg1 + 20)); 75766e63ce3Schristos 75866e63ce3Schristos addr = (void *) conv_endian((unsigned int) addr); 75966e63ce3Schristos len = conv_endian(len); 76066e63ce3Schristos prot = conv_endian(prot); 76166e63ce3Schristos flags = conv_endian(flags); 76266e63ce3Schristos fildes = conv_endian(fildes); 76366e63ce3Schristos off = conv_endian(off); 76466e63ce3Schristos 76566e63ce3Schristos //addr = (void *) t2h_addr(cb, &s, (unsigned int) addr); 76666e63ce3Schristos result = (int) mmap(addr, len, prot, flags, fildes, off); 76766e63ce3Schristos errcode = errno; 76866e63ce3Schristos 76966e63ce3Schristos //if (errno == 0) 77066e63ce3Schristos if (result != -1) 77166e63ce3Schristos { 77266e63ce3Schristos char c; 77366e63ce3Schristos if (sim_core_read_buffer (sd, NULL, read_map, &c, result, 1) == 0) 77466e63ce3Schristos sim_core_attach (sd, NULL, 77566e63ce3Schristos 0, access_read_write_exec, 0, 77666e63ce3Schristos result, len, 0, NULL, NULL); 77766e63ce3Schristos } 77866e63ce3Schristos } 77966e63ce3Schristos break; 78066e63ce3Schristos 78166e63ce3Schristos case __NR_munmap: 78266e63ce3Schristos { 78366e63ce3Schristos result = munmap((void *)arg1, arg2); 78466e63ce3Schristos errcode = errno; 78566e63ce3Schristos if (result != -1) 78666e63ce3Schristos { 78766e63ce3Schristos sim_core_detach (sd, NULL, 0, arg2, result); 78866e63ce3Schristos } 78966e63ce3Schristos } 79066e63ce3Schristos break; 79166e63ce3Schristos 79266e63ce3Schristos case __NR_truncate: 79366e63ce3Schristos result = truncate((char *) t2h_addr(cb, &s, arg1), arg2); 79466e63ce3Schristos errcode = errno; 79566e63ce3Schristos break; 79666e63ce3Schristos 79766e63ce3Schristos case __NR_ftruncate: 79866e63ce3Schristos result = ftruncate(arg1, arg2); 79966e63ce3Schristos errcode = errno; 80066e63ce3Schristos break; 80166e63ce3Schristos 80266e63ce3Schristos case __NR_fchmod: 80366e63ce3Schristos result = fchmod(arg1, arg2); 80466e63ce3Schristos errcode = errno; 80566e63ce3Schristos break; 80666e63ce3Schristos 80766e63ce3Schristos case __NR_fchown32: 80866e63ce3Schristos case __NR_fchown: 80966e63ce3Schristos result = fchown(arg1, arg2, arg3); 81066e63ce3Schristos errcode = errno; 81166e63ce3Schristos break; 81266e63ce3Schristos 81366e63ce3Schristos case __NR_statfs: 81466e63ce3Schristos { 81566e63ce3Schristos struct statfs statbuf; 81666e63ce3Schristos 81766e63ce3Schristos result = statfs((char *) t2h_addr(cb, &s, arg1), &statbuf); 81866e63ce3Schristos errcode = errno; 81966e63ce3Schristos 82066e63ce3Schristos if (result != 0) 82166e63ce3Schristos break; 82266e63ce3Schristos 82366e63ce3Schristos translate_endian((void *) &statbuf, sizeof(statbuf)); 82466e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) 82566e63ce3Schristos != sizeof(statbuf)) 82666e63ce3Schristos { 82766e63ce3Schristos result = -1; 82866e63ce3Schristos errcode = EINVAL; 82966e63ce3Schristos } 83066e63ce3Schristos } 83166e63ce3Schristos break; 83266e63ce3Schristos 83366e63ce3Schristos case __NR_fstatfs: 83466e63ce3Schristos { 83566e63ce3Schristos struct statfs statbuf; 83666e63ce3Schristos 83766e63ce3Schristos result = fstatfs(arg1, &statbuf); 83866e63ce3Schristos errcode = errno; 83966e63ce3Schristos 84066e63ce3Schristos if (result != 0) 84166e63ce3Schristos break; 84266e63ce3Schristos 84366e63ce3Schristos translate_endian((void *) &statbuf, sizeof(statbuf)); 84466e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &statbuf, sizeof(statbuf)) 84566e63ce3Schristos != sizeof(statbuf)) 84666e63ce3Schristos { 84766e63ce3Schristos result = -1; 84866e63ce3Schristos errcode = EINVAL; 84966e63ce3Schristos } 85066e63ce3Schristos } 85166e63ce3Schristos break; 85266e63ce3Schristos 85366e63ce3Schristos case __NR_syslog: 85466e63ce3Schristos result = syslog(arg1, (char *) t2h_addr(cb, &s, arg2)); 85566e63ce3Schristos errcode = errno; 85666e63ce3Schristos break; 85766e63ce3Schristos 85866e63ce3Schristos case __NR_setitimer: 85966e63ce3Schristos { 86066e63ce3Schristos struct itimerval value, ovalue; 86166e63ce3Schristos 86266e63ce3Schristos value = *((struct itimerval *) t2h_addr(cb, &s, arg2)); 86366e63ce3Schristos translate_endian((void *) &value, sizeof(value)); 86466e63ce3Schristos 86566e63ce3Schristos if (arg2 == 0) 86666e63ce3Schristos { 86766e63ce3Schristos result = setitimer(arg1, &value, NULL); 86866e63ce3Schristos errcode = errno; 86966e63ce3Schristos } 87066e63ce3Schristos else 87166e63ce3Schristos { 87266e63ce3Schristos result = setitimer(arg1, &value, &ovalue); 87366e63ce3Schristos errcode = errno; 87466e63ce3Schristos 87566e63ce3Schristos if (result != 0) 87666e63ce3Schristos break; 87766e63ce3Schristos 87866e63ce3Schristos translate_endian((void *) &ovalue, sizeof(ovalue)); 87966e63ce3Schristos if ((s.write_mem) (cb, &s, arg3, (char *) &ovalue, sizeof(ovalue)) 88066e63ce3Schristos != sizeof(ovalue)) 88166e63ce3Schristos { 88266e63ce3Schristos result = -1; 88366e63ce3Schristos errcode = EINVAL; 88466e63ce3Schristos } 88566e63ce3Schristos } 88666e63ce3Schristos } 88766e63ce3Schristos break; 88866e63ce3Schristos 88966e63ce3Schristos case __NR_getitimer: 89066e63ce3Schristos { 89166e63ce3Schristos struct itimerval value; 89266e63ce3Schristos 89366e63ce3Schristos result = getitimer(arg1, &value); 89466e63ce3Schristos errcode = errno; 89566e63ce3Schristos 89666e63ce3Schristos if (result != 0) 89766e63ce3Schristos break; 89866e63ce3Schristos 89966e63ce3Schristos translate_endian((void *) &value, sizeof(value)); 90066e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &value, sizeof(value)) 90166e63ce3Schristos != sizeof(value)) 90266e63ce3Schristos { 90366e63ce3Schristos result = -1; 90466e63ce3Schristos errcode = EINVAL; 90566e63ce3Schristos } 90666e63ce3Schristos } 90766e63ce3Schristos break; 90866e63ce3Schristos 90966e63ce3Schristos case __NR_stat: 91066e63ce3Schristos { 91166e63ce3Schristos char *buf; 91266e63ce3Schristos int buflen; 91366e63ce3Schristos struct stat statbuf; 91466e63ce3Schristos 91566e63ce3Schristos result = stat((char *) t2h_addr(cb, &s, arg1), &statbuf); 91666e63ce3Schristos errcode = errno; 91766e63ce3Schristos if (result < 0) 91866e63ce3Schristos break; 91966e63ce3Schristos 92066e63ce3Schristos buflen = cb_host_to_target_stat (cb, NULL, NULL); 92166e63ce3Schristos buf = xmalloc (buflen); 92266e63ce3Schristos if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) 92366e63ce3Schristos { 92466e63ce3Schristos /* The translation failed. This is due to an internal 92566e63ce3Schristos host program error, not the target's fault. */ 92666e63ce3Schristos free (buf); 92766e63ce3Schristos result = -1; 92866e63ce3Schristos errcode = ENOSYS; 92966e63ce3Schristos break; 93066e63ce3Schristos } 93166e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) 93266e63ce3Schristos { 93366e63ce3Schristos free (buf); 93466e63ce3Schristos result = -1; 93566e63ce3Schristos errcode = EINVAL; 93666e63ce3Schristos break; 93766e63ce3Schristos } 93866e63ce3Schristos free (buf); 93966e63ce3Schristos } 94066e63ce3Schristos break; 94166e63ce3Schristos 94266e63ce3Schristos case __NR_lstat: 94366e63ce3Schristos { 94466e63ce3Schristos char *buf; 94566e63ce3Schristos int buflen; 94666e63ce3Schristos struct stat statbuf; 94766e63ce3Schristos 94866e63ce3Schristos result = lstat((char *) t2h_addr(cb, &s, arg1), &statbuf); 94966e63ce3Schristos errcode = errno; 95066e63ce3Schristos if (result < 0) 95166e63ce3Schristos break; 95266e63ce3Schristos 95366e63ce3Schristos buflen = cb_host_to_target_stat (cb, NULL, NULL); 95466e63ce3Schristos buf = xmalloc (buflen); 95566e63ce3Schristos if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) 95666e63ce3Schristos { 95766e63ce3Schristos /* The translation failed. This is due to an internal 95866e63ce3Schristos host program error, not the target's fault. */ 95966e63ce3Schristos free (buf); 96066e63ce3Schristos result = -1; 96166e63ce3Schristos errcode = ENOSYS; 96266e63ce3Schristos break; 96366e63ce3Schristos } 96466e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) 96566e63ce3Schristos { 96666e63ce3Schristos free (buf); 96766e63ce3Schristos result = -1; 96866e63ce3Schristos errcode = EINVAL; 96966e63ce3Schristos break; 97066e63ce3Schristos } 97166e63ce3Schristos free (buf); 97266e63ce3Schristos } 97366e63ce3Schristos break; 97466e63ce3Schristos 97566e63ce3Schristos case __NR_fstat: 97666e63ce3Schristos { 97766e63ce3Schristos char *buf; 97866e63ce3Schristos int buflen; 97966e63ce3Schristos struct stat statbuf; 98066e63ce3Schristos 98166e63ce3Schristos result = fstat(arg1, &statbuf); 98266e63ce3Schristos errcode = errno; 98366e63ce3Schristos if (result < 0) 98466e63ce3Schristos break; 98566e63ce3Schristos 98666e63ce3Schristos buflen = cb_host_to_target_stat (cb, NULL, NULL); 98766e63ce3Schristos buf = xmalloc (buflen); 98866e63ce3Schristos if (cb_host_to_target_stat (cb, &statbuf, buf) != buflen) 98966e63ce3Schristos { 99066e63ce3Schristos /* The translation failed. This is due to an internal 99166e63ce3Schristos host program error, not the target's fault. */ 99266e63ce3Schristos free (buf); 99366e63ce3Schristos result = -1; 99466e63ce3Schristos errcode = ENOSYS; 99566e63ce3Schristos break; 99666e63ce3Schristos } 99766e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, buf, buflen) != buflen) 99866e63ce3Schristos { 99966e63ce3Schristos free (buf); 100066e63ce3Schristos result = -1; 100166e63ce3Schristos errcode = EINVAL; 100266e63ce3Schristos break; 100366e63ce3Schristos } 100466e63ce3Schristos free (buf); 100566e63ce3Schristos } 100666e63ce3Schristos break; 100766e63ce3Schristos 100866e63ce3Schristos case __NR_sysinfo: 100966e63ce3Schristos { 101066e63ce3Schristos struct sysinfo info; 101166e63ce3Schristos 101266e63ce3Schristos result = sysinfo(&info); 101366e63ce3Schristos errcode = errno; 101466e63ce3Schristos 101566e63ce3Schristos if (result != 0) 101666e63ce3Schristos break; 101766e63ce3Schristos 101866e63ce3Schristos info.uptime = conv_endian(info.uptime); 101966e63ce3Schristos info.loads[0] = conv_endian(info.loads[0]); 102066e63ce3Schristos info.loads[1] = conv_endian(info.loads[1]); 102166e63ce3Schristos info.loads[2] = conv_endian(info.loads[2]); 102266e63ce3Schristos info.totalram = conv_endian(info.totalram); 102366e63ce3Schristos info.freeram = conv_endian(info.freeram); 102466e63ce3Schristos info.sharedram = conv_endian(info.sharedram); 102566e63ce3Schristos info.bufferram = conv_endian(info.bufferram); 102666e63ce3Schristos info.totalswap = conv_endian(info.totalswap); 102766e63ce3Schristos info.freeswap = conv_endian(info.freeswap); 102866e63ce3Schristos info.procs = conv_endian16(info.procs); 102966e63ce3Schristos #if LINUX_VERSION_CODE >= 0x20400 103066e63ce3Schristos info.totalhigh = conv_endian(info.totalhigh); 103166e63ce3Schristos info.freehigh = conv_endian(info.freehigh); 103266e63ce3Schristos info.mem_unit = conv_endian(info.mem_unit); 103366e63ce3Schristos #endif 103466e63ce3Schristos if ((s.write_mem) (cb, &s, arg1, (char *) &info, sizeof(info)) 103566e63ce3Schristos != sizeof(info)) 103666e63ce3Schristos { 103766e63ce3Schristos result = -1; 103866e63ce3Schristos errcode = EINVAL; 103966e63ce3Schristos } 104066e63ce3Schristos } 104166e63ce3Schristos break; 104266e63ce3Schristos 104366e63ce3Schristos #if 0 104466e63ce3Schristos case __NR_ipc: 104566e63ce3Schristos { 104666e63ce3Schristos result = ipc(arg1, arg2, arg3, arg4, 104766e63ce3Schristos (void *) t2h_addr(cb, &s, arg5), arg6); 104866e63ce3Schristos errcode = errno; 104966e63ce3Schristos } 105066e63ce3Schristos break; 105166e63ce3Schristos #endif 105266e63ce3Schristos 105366e63ce3Schristos case __NR_fsync: 105466e63ce3Schristos result = fsync(arg1); 105566e63ce3Schristos errcode = errno; 105666e63ce3Schristos break; 105766e63ce3Schristos 105866e63ce3Schristos case __NR_uname: 105966e63ce3Schristos /* utsname contains only arrays of char, so it is not necessary 106066e63ce3Schristos to translate endian. */ 106166e63ce3Schristos result = uname((struct utsname *) t2h_addr(cb, &s, arg1)); 106266e63ce3Schristos errcode = errno; 106366e63ce3Schristos break; 106466e63ce3Schristos 106566e63ce3Schristos case __NR_adjtimex: 106666e63ce3Schristos { 106766e63ce3Schristos struct timex buf; 106866e63ce3Schristos 106966e63ce3Schristos result = adjtimex(&buf); 107066e63ce3Schristos errcode = errno; 107166e63ce3Schristos 107266e63ce3Schristos if (result != 0) 107366e63ce3Schristos break; 107466e63ce3Schristos 107566e63ce3Schristos translate_endian((void *) &buf, sizeof(buf)); 107666e63ce3Schristos if ((s.write_mem) (cb, &s, arg1, (char *) &buf, sizeof(buf)) 107766e63ce3Schristos != sizeof(buf)) 107866e63ce3Schristos { 107966e63ce3Schristos result = -1; 108066e63ce3Schristos errcode = EINVAL; 108166e63ce3Schristos } 108266e63ce3Schristos } 108366e63ce3Schristos break; 108466e63ce3Schristos 108566e63ce3Schristos case __NR_mprotect: 108666e63ce3Schristos result = mprotect((void *) arg1, arg2, arg3); 108766e63ce3Schristos errcode = errno; 108866e63ce3Schristos break; 108966e63ce3Schristos 109066e63ce3Schristos case __NR_fchdir: 109166e63ce3Schristos result = fchdir(arg1); 109266e63ce3Schristos errcode = errno; 109366e63ce3Schristos break; 109466e63ce3Schristos 109566e63ce3Schristos case __NR_setfsuid32: 109666e63ce3Schristos case __NR_setfsuid: 109766e63ce3Schristos result = setfsuid(arg1); 109866e63ce3Schristos errcode = errno; 109966e63ce3Schristos break; 110066e63ce3Schristos 110166e63ce3Schristos case __NR_setfsgid32: 110266e63ce3Schristos case __NR_setfsgid: 110366e63ce3Schristos result = setfsgid(arg1); 110466e63ce3Schristos errcode = errno; 110566e63ce3Schristos break; 110666e63ce3Schristos 110766e63ce3Schristos #if 0 110866e63ce3Schristos case __NR__llseek: 110966e63ce3Schristos { 111066e63ce3Schristos loff_t buf; 111166e63ce3Schristos 111266e63ce3Schristos result = _llseek(arg1, arg2, arg3, &buf, arg5); 111366e63ce3Schristos errcode = errno; 111466e63ce3Schristos 111566e63ce3Schristos if (result != 0) 111666e63ce3Schristos break; 111766e63ce3Schristos 111866e63ce3Schristos translate_endian((void *) &buf, sizeof(buf)); 111966e63ce3Schristos if ((s.write_mem) (cb, &s, t2h_addr(cb, &s, arg4), 112066e63ce3Schristos (char *) &buf, sizeof(buf)) != sizeof(buf)) 112166e63ce3Schristos { 112266e63ce3Schristos result = -1; 112366e63ce3Schristos errcode = EINVAL; 112466e63ce3Schristos } 112566e63ce3Schristos } 112666e63ce3Schristos break; 112766e63ce3Schristos 112866e63ce3Schristos case __NR_getdents: 112966e63ce3Schristos { 113066e63ce3Schristos struct dirent dir; 113166e63ce3Schristos 113266e63ce3Schristos result = getdents(arg1, &dir, arg3); 113366e63ce3Schristos errcode = errno; 113466e63ce3Schristos 113566e63ce3Schristos if (result != 0) 113666e63ce3Schristos break; 113766e63ce3Schristos 113866e63ce3Schristos dir.d_ino = conv_endian(dir.d_ino); 113966e63ce3Schristos dir.d_off = conv_endian(dir.d_off); 114066e63ce3Schristos dir.d_reclen = conv_endian16(dir.d_reclen); 114166e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &dir, sizeof(dir)) 114266e63ce3Schristos != sizeof(dir)) 114366e63ce3Schristos { 114466e63ce3Schristos result = -1; 114566e63ce3Schristos errcode = EINVAL; 114666e63ce3Schristos } 114766e63ce3Schristos } 114866e63ce3Schristos break; 114966e63ce3Schristos #endif 115066e63ce3Schristos 115166e63ce3Schristos case __NR_flock: 115266e63ce3Schristos result = flock(arg1, arg2); 115366e63ce3Schristos errcode = errno; 115466e63ce3Schristos break; 115566e63ce3Schristos 115666e63ce3Schristos case __NR_msync: 115766e63ce3Schristos result = msync((void *) arg1, arg2, arg3); 115866e63ce3Schristos errcode = errno; 115966e63ce3Schristos break; 116066e63ce3Schristos 116166e63ce3Schristos case __NR_readv: 116266e63ce3Schristos { 116366e63ce3Schristos struct iovec vector; 116466e63ce3Schristos 116566e63ce3Schristos vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); 116666e63ce3Schristos translate_endian((void *) &vector, sizeof(vector)); 116766e63ce3Schristos 116866e63ce3Schristos result = readv(arg1, &vector, arg3); 116966e63ce3Schristos errcode = errno; 117066e63ce3Schristos } 117166e63ce3Schristos break; 117266e63ce3Schristos 117366e63ce3Schristos case __NR_writev: 117466e63ce3Schristos { 117566e63ce3Schristos struct iovec vector; 117666e63ce3Schristos 117766e63ce3Schristos vector = *((struct iovec *) t2h_addr(cb, &s, arg2)); 117866e63ce3Schristos translate_endian((void *) &vector, sizeof(vector)); 117966e63ce3Schristos 118066e63ce3Schristos result = writev(arg1, &vector, arg3); 118166e63ce3Schristos errcode = errno; 118266e63ce3Schristos } 118366e63ce3Schristos break; 118466e63ce3Schristos 118566e63ce3Schristos case __NR_fdatasync: 118666e63ce3Schristos result = fdatasync(arg1); 118766e63ce3Schristos errcode = errno; 118866e63ce3Schristos break; 118966e63ce3Schristos 119066e63ce3Schristos case __NR_mlock: 119166e63ce3Schristos result = mlock((void *) t2h_addr(cb, &s, arg1), arg2); 119266e63ce3Schristos errcode = errno; 119366e63ce3Schristos break; 119466e63ce3Schristos 119566e63ce3Schristos case __NR_munlock: 119666e63ce3Schristos result = munlock((void *) t2h_addr(cb, &s, arg1), arg2); 119766e63ce3Schristos errcode = errno; 119866e63ce3Schristos break; 119966e63ce3Schristos 120066e63ce3Schristos case __NR_nanosleep: 120166e63ce3Schristos { 120266e63ce3Schristos struct timespec req, rem; 120366e63ce3Schristos 120466e63ce3Schristos req = *((struct timespec *) t2h_addr(cb, &s, arg2)); 120566e63ce3Schristos translate_endian((void *) &req, sizeof(req)); 120666e63ce3Schristos 120766e63ce3Schristos result = nanosleep(&req, &rem); 120866e63ce3Schristos errcode = errno; 120966e63ce3Schristos 121066e63ce3Schristos if (result != 0) 121166e63ce3Schristos break; 121266e63ce3Schristos 121366e63ce3Schristos translate_endian((void *) &rem, sizeof(rem)); 121466e63ce3Schristos if ((s.write_mem) (cb, &s, arg2, (char *) &rem, sizeof(rem)) 121566e63ce3Schristos != sizeof(rem)) 121666e63ce3Schristos { 121766e63ce3Schristos result = -1; 121866e63ce3Schristos errcode = EINVAL; 121966e63ce3Schristos } 122066e63ce3Schristos } 122166e63ce3Schristos break; 122266e63ce3Schristos 122366e63ce3Schristos case __NR_mremap: /* FIXME */ 122466e63ce3Schristos result = (int) mremap((void *) t2h_addr(cb, &s, arg1), arg2, arg3, arg4); 122566e63ce3Schristos errcode = errno; 122666e63ce3Schristos break; 122766e63ce3Schristos 122866e63ce3Schristos case __NR_getresuid32: 122966e63ce3Schristos case __NR_getresuid: 123066e63ce3Schristos { 123166e63ce3Schristos uid_t ruid, euid, suid; 123266e63ce3Schristos 123366e63ce3Schristos result = getresuid(&ruid, &euid, &suid); 123466e63ce3Schristos errcode = errno; 123566e63ce3Schristos 123666e63ce3Schristos if (result != 0) 123766e63ce3Schristos break; 123866e63ce3Schristos 123966e63ce3Schristos *((uid_t *) t2h_addr(cb, &s, arg1)) = conv_endian(ruid); 124066e63ce3Schristos *((uid_t *) t2h_addr(cb, &s, arg2)) = conv_endian(euid); 124166e63ce3Schristos *((uid_t *) t2h_addr(cb, &s, arg3)) = conv_endian(suid); 124266e63ce3Schristos } 124366e63ce3Schristos break; 124466e63ce3Schristos 124566e63ce3Schristos case __NR_poll: 124666e63ce3Schristos { 124766e63ce3Schristos struct pollfd ufds; 124866e63ce3Schristos 124966e63ce3Schristos ufds = *((struct pollfd *) t2h_addr(cb, &s, arg1)); 125066e63ce3Schristos ufds.fd = conv_endian(ufds.fd); 125166e63ce3Schristos ufds.events = conv_endian16(ufds.events); 125266e63ce3Schristos ufds.revents = conv_endian16(ufds.revents); 125366e63ce3Schristos 125466e63ce3Schristos result = poll(&ufds, arg2, arg3); 125566e63ce3Schristos errcode = errno; 125666e63ce3Schristos } 125766e63ce3Schristos break; 125866e63ce3Schristos 125966e63ce3Schristos case __NR_getresgid32: 126066e63ce3Schristos case __NR_getresgid: 126166e63ce3Schristos { 126266e63ce3Schristos uid_t rgid, egid, sgid; 126366e63ce3Schristos 126466e63ce3Schristos result = getresgid(&rgid, &egid, &sgid); 126566e63ce3Schristos errcode = errno; 126666e63ce3Schristos 126766e63ce3Schristos if (result != 0) 126866e63ce3Schristos break; 126966e63ce3Schristos 127066e63ce3Schristos *((uid_t *) t2h_addr(cb, &s, arg1)) = conv_endian(rgid); 127166e63ce3Schristos *((uid_t *) t2h_addr(cb, &s, arg2)) = conv_endian(egid); 127266e63ce3Schristos *((uid_t *) t2h_addr(cb, &s, arg3)) = conv_endian(sgid); 127366e63ce3Schristos } 127466e63ce3Schristos break; 127566e63ce3Schristos 127666e63ce3Schristos case __NR_pread: 127766e63ce3Schristos result = pread(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); 127866e63ce3Schristos errcode = errno; 127966e63ce3Schristos break; 128066e63ce3Schristos 128166e63ce3Schristos case __NR_pwrite: 128266e63ce3Schristos result = pwrite(arg1, (void *) t2h_addr(cb, &s, arg2), arg3, arg4); 128366e63ce3Schristos errcode = errno; 128466e63ce3Schristos break; 128566e63ce3Schristos 128666e63ce3Schristos case __NR_chown32: 128766e63ce3Schristos case __NR_chown: 128866e63ce3Schristos result = chown((char *) t2h_addr(cb, &s, arg1), arg2, arg3); 128966e63ce3Schristos errcode = errno; 129066e63ce3Schristos break; 129166e63ce3Schristos 129266e63ce3Schristos case __NR_getcwd: 129366e63ce3Schristos result = (int) getcwd((char *) t2h_addr(cb, &s, arg1), arg2); 129466e63ce3Schristos errcode = errno; 129566e63ce3Schristos break; 129666e63ce3Schristos 129766e63ce3Schristos case __NR_sendfile: 129866e63ce3Schristos { 129966e63ce3Schristos off_t offset; 130066e63ce3Schristos 130166e63ce3Schristos offset = *((off_t *) t2h_addr(cb, &s, arg3)); 130266e63ce3Schristos offset = conv_endian(offset); 130366e63ce3Schristos 130466e63ce3Schristos result = sendfile(arg1, arg2, &offset, arg3); 130566e63ce3Schristos errcode = errno; 130666e63ce3Schristos 130766e63ce3Schristos if (result != 0) 130866e63ce3Schristos break; 130966e63ce3Schristos 131066e63ce3Schristos *((off_t *) t2h_addr(cb, &s, arg3)) = conv_endian(offset); 131166e63ce3Schristos } 131266e63ce3Schristos break; 131366e63ce3Schristos 131466e63ce3Schristos default: 131566e63ce3Schristos result = -1; 131666e63ce3Schristos errcode = ENOSYS; 131766e63ce3Schristos break; 131866e63ce3Schristos } 131966e63ce3Schristos 132066e63ce3Schristos if (result == -1) 132166e63ce3Schristos m32rbf_h_gr_set (current_cpu, 0, -errcode); 132266e63ce3Schristos else 132366e63ce3Schristos m32rbf_h_gr_set (current_cpu, 0, result); 132466e63ce3Schristos break; 132566e63ce3Schristos } 132666e63ce3Schristos 132766e63ce3Schristos case TRAP_BREAKPOINT: 132866e63ce3Schristos sim_engine_halt (sd, current_cpu, NULL, pc, 132966e63ce3Schristos sim_stopped, SIM_SIGTRAP); 133066e63ce3Schristos break; 133166e63ce3Schristos 133266e63ce3Schristos case TRAP_FLUSH_CACHE: 133366e63ce3Schristos /* Do nothing. */ 133466e63ce3Schristos break; 133566e63ce3Schristos 133666e63ce3Schristos default : 133766e63ce3Schristos { 133866e63ce3Schristos /* Use cr5 as EVB (EIT Vector Base) register. */ 133966e63ce3Schristos USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; 134066e63ce3Schristos return new_pc; 134166e63ce3Schristos } 134266e63ce3Schristos } 134366e63ce3Schristos 134466e63ce3Schristos /* Fake an "rte" insn. */ 134566e63ce3Schristos /* FIXME: Should duplicate all of rte processing. */ 134666e63ce3Schristos return (pc & -4) + 4; 134766e63ce3Schristos } 1348