📄 traps-linux.c
字号:
/* m32r exception, interrupt, and trap (EIT) support Copyright (C) 1998, 2003 Free Software Foundation, Inc. Contributed by Renesas. This file is part of GDB, the GNU debugger. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "sim-main.h"#include "syscall.h"#include "targ-vals.h"#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <time.h>#include <unistd.h>#include <utime.h>#include <sys/mman.h>#include <sys/poll.h>#include <sys/resource.h>#include <sys/sysinfo.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/timeb.h>#include <sys/timex.h>#include <sys/types.h>#include <sys/uio.h>#include <sys/utsname.h>#include <sys/vfs.h>#include <linux/sysctl.h>#include <linux/types.h>#include <linux/unistd.h>#define TRAP_ELF_SYSCALL 0#define TRAP_LINUX_SYSCALL 2#define TRAP_FLUSH_CACHE 12/* The semantic code invokes this for invalid (unrecognized) instructions. */SEM_PCsim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc){ SIM_DESC sd = CPU_STATE (current_cpu);#if 0 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) { h_bsm_set (current_cpu, h_sm_get (current_cpu)); h_bie_set (current_cpu, h_ie_get (current_cpu)); h_bcond_set (current_cpu, h_cond_get (current_cpu)); /* sm not changed */ h_ie_set (current_cpu, 0); h_cond_set (current_cpu, 0); h_bpc_set (current_cpu, cia); sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, EIT_RSVD_INSN_ADDR); } else#endif sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL); return vpc;}/* Process an address exception. */voidm32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, unsigned int map, int nr_bytes, address_word addr, transfer_type transfer, sim_core_signals sig){ if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) { m32rbf_h_cr_set (current_cpu, H_CR_BBPC, m32rbf_h_cr_get (current_cpu, H_CR_BPC)); if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32R) { m32rbf_h_bpsw_set (current_cpu, m32rbf_h_psw_get (current_cpu)); /* sm not changed */ m32rbf_h_psw_set (current_cpu, m32rbf_h_psw_get (current_cpu) & 0x80); } else if (MACH_NUM (CPU_MACH (current_cpu)) == MACH_M32RX) { m32rxf_h_bpsw_set (current_cpu, m32rxf_h_psw_get (current_cpu)); /* sm not changed */ m32rxf_h_psw_set (current_cpu, m32rxf_h_psw_get (current_cpu) & 0x80); } else { m32r2f_h_bpsw_set (current_cpu, m32r2f_h_psw_get (current_cpu)); /* sm not changed */ m32r2f_h_psw_set (current_cpu, m32r2f_h_psw_get (current_cpu) & 0x80); } m32rbf_h_cr_set (current_cpu, H_CR_BPC, cia); sim_engine_restart (CPU_STATE (current_cpu), current_cpu, NULL, EIT_ADDR_EXCP_ADDR); } else sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, transfer, sig);}/* Read/write functions for system call interface. */static intsyscall_read_mem (host_callback *cb, struct cb_syscall *sc, unsigned long taddr, char *buf, int bytes){ SIM_DESC sd = (SIM_DESC) sc->p1; SIM_CPU *cpu = (SIM_CPU *) sc->p2; return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);}static intsyscall_write_mem (host_callback *cb, struct cb_syscall *sc, unsigned long taddr, const char *buf, int bytes){ SIM_DESC sd = (SIM_DESC) sc->p1; SIM_CPU *cpu = (SIM_CPU *) sc->p2; return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);}/* Translate target's address to host's address. */static void *t2h_addr (host_callback *cb, struct cb_syscall *sc, unsigned long taddr){ extern sim_core_trans_addr (SIM_DESC, sim_cpu *, unsigned, address_word); void *addr; SIM_DESC sd = (SIM_DESC) sc->p1; SIM_CPU *cpu = (SIM_CPU *) sc->p2; if (taddr == 0) return NULL; return sim_core_trans_addr (sd, cpu, read_map, taddr);}static unsigned intconv_endian (unsigned int tvalue){ unsigned int hvalue; unsigned int t1, t2, t3, t4; if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) { t1 = tvalue & 0xff000000; t2 = tvalue & 0x00ff0000; t3 = tvalue & 0x0000ff00; t4 = tvalue & 0x000000ff; hvalue = t1 >> 24; hvalue += t2 >> 8; hvalue += t3 << 8; hvalue += t4 << 24; } else hvalue = tvalue; return hvalue;}static unsigned shortconv_endian16 (unsigned short tvalue){ unsigned short hvalue; unsigned short t1, t2; if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN) { t1 = tvalue & 0xff00; t2 = tvalue & 0x00ff; hvalue = t1 >> 8; hvalue += t2 << 8; } else hvalue = tvalue; return hvalue;}static voidtranslate_endian(void *addr, size_t size){ unsigned int *p = (unsigned int *) addr; int i; for (i = 0; i <= size - 4; i += 4,p++) *p = conv_endian(*p); if (i <= size - 2) *((unsigned short *) p) = conv_endian16(*((unsigned short *) p));}/* Trap support. The result is the pc address to continue at. Preprocessing like saving the various registers has already been done. */USIm32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num){ SIM_DESC sd = CPU_STATE (current_cpu); host_callback *cb = STATE_CALLBACK (sd);#ifdef SIM_HAVE_BREAKPOINTS /* Check for breakpoints "owned" by the simulator first, regardless of --environment. */ if (num == TRAP_BREAKPOINT) { /* First try sim-break.c. If it's a breakpoint the simulator "owns" it doesn't return. Otherwise it returns and let's us try. */ sim_handle_breakpoint (sd, current_cpu, pc); /* Fall through. */ }#endif switch (num) { case TRAP_ELF_SYSCALL : { CB_SYSCALL s; CB_SYSCALL_INIT (&s); s.func = m32rbf_h_gr_get (current_cpu, 0); s.arg1 = m32rbf_h_gr_get (current_cpu, 1); s.arg2 = m32rbf_h_gr_get (current_cpu, 2); s.arg3 = m32rbf_h_gr_get (current_cpu, 3); if (s.func == TARGET_SYS_exit) { sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, s.arg1); } s.p1 = (PTR) sd; s.p2 = (PTR) current_cpu; s.read_mem = syscall_read_mem; s.write_mem = syscall_write_mem; cb_syscall (cb, &s); m32rbf_h_gr_set (current_cpu, 2, s.errcode); m32rbf_h_gr_set (current_cpu, 0, s.result); m32rbf_h_gr_set (current_cpu, 1, s.result2); break; } case TRAP_LINUX_SYSCALL : { CB_SYSCALL s; unsigned int func, arg1, arg2, arg3, arg4, arg5, arg6, arg7; int result, result2, errcode; if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) { /* The new pc is the trap vector entry. We assume there's a branch there to some handler. Use cr5 as EVB (EIT Vector Base) register. */ USI new_pc = m32rbf_h_cr_get (current_cpu, 5) + 0x40 + num * 4; return new_pc; } func = m32rbf_h_gr_get (current_cpu, 7); arg1 = m32rbf_h_gr_get (current_cpu, 0); arg2 = m32rbf_h_gr_get (current_cpu, 1); arg3 = m32rbf_h_gr_get (current_cpu, 2); arg4 = m32rbf_h_gr_get (current_cpu, 3); arg5 = m32rbf_h_gr_get (current_cpu, 4); arg6 = m32rbf_h_gr_get (current_cpu, 5); arg7 = m32rbf_h_gr_get (current_cpu, 6); CB_SYSCALL_INIT (&s); s.func = func; s.arg1 = arg1; s.arg2 = arg2; s.arg3 = arg3; s.p1 = (PTR) sd; s.p2 = (PTR) current_cpu; s.read_mem = syscall_read_mem; s.write_mem = syscall_write_mem; result = 0; result2 = 0; errcode = 0; switch (func) { case __NR_exit: sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1); break; case __NR_read: result = read(arg1, t2h_addr(cb, &s, arg2), arg3); errcode = errno; break; case __NR_write: result = write(arg1, t2h_addr(cb, &s, arg2), arg3); errcode = errno; break; case __NR_open: result = open((char *) t2h_addr(cb, &s, arg1), arg2, arg3); errcode = errno; break; case __NR_close: result = close(arg1); errcode = errno; break; case __NR_creat: result = creat((char *) t2h_addr(cb, &s, arg1), arg2); errcode = errno; break; case __NR_link: result = link((char *) t2h_addr(cb, &s, arg1), (char *) t2h_addr(cb, &s, arg2)); errcode = errno; break; case __NR_unlink: result = unlink((char *) t2h_addr(cb, &s, arg1)); errcode = errno; break; case __NR_chdir: result = chdir((char *) t2h_addr(cb, &s, arg1)); errcode = errno; break; case __NR_time: { time_t t; if (arg1 == 0) { result = (int) time(NULL); errcode = errno; } else { result = (int) time(&t); errcode = errno; if (result != 0) break; translate_endian((void *) &t, sizeof(t)); if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t)) { result = -1; errcode = EINVAL; } } } break; case __NR_mknod: result = mknod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2, (dev_t) arg3); errcode = errno; break; case __NR_chmod: result = chmod((char *) t2h_addr(cb, &s, arg1), (mode_t) arg2); errcode = errno; break; case __NR_lchown: result = lchown((char *) t2h_addr(cb, &s, arg1), (uid_t) arg2, (gid_t) arg3); errcode = errno; break; case __NR_lseek: result = (int) lseek(arg1, (off_t) arg2, arg3); errcode = errno; break; case __NR_getpid: result = getpid(); errcode = errno; break; case __NR_getuid: result = getuid(); errcode = errno; break; case __NR_utime: { struct utimbuf buf; if (arg2 == 0) { result = utime((char *) t2h_addr(cb, &s, arg1), NULL); errcode = errno; } else { buf = *((struct utimbuf *) t2h_addr(cb, &s, arg2)); translate_endian((void *) &buf, sizeof(buf)); result = utime((char *) t2h_addr(cb, &s, arg1), &buf); errcode = errno; } } break; case __NR_access: result = access((char *) t2h_addr(cb, &s, arg1), arg2); errcode = errno; break; case __NR_ftime: { struct timeb t; result = ftime(&t); errcode = errno; if (result != 0) break; t.time = conv_endian(t.time); t.millitm = conv_endian16(t.millitm); t.timezone = conv_endian16(t.timezone); t.dstflag = conv_endian16(t.dstflag); if ((s.write_mem) (cb, &s, arg1, (char *) &t, sizeof(t)) != sizeof(t)) { result = -1; errcode = EINVAL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -