gdb/gdbserver/linux-x86-low.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "server.h"
- #include <signal.h>
- #include <limits.h>
- #include <inttypes.h>
- #include "linux-low.h"
- #include "i387-fp.h"
- #include "x86-low.h"
- #include "x86-xstate.h"
- #include "gdb_proc_service.h"
- #ifndef ELFMAG0
- #include "elf/common.h"
- #endif
- #include "agent.h"
- #include "tdesc.h"
- #include "tracepoint.h"
- #include "ax.h"
- #ifdef __x86_64__
- void init_registers_amd64_linux (void);
- extern const struct target_desc *tdesc_amd64_linux;
- void init_registers_amd64_avx_linux (void);
- extern const struct target_desc *tdesc_amd64_avx_linux;
- void init_registers_amd64_avx512_linux (void);
- extern const struct target_desc *tdesc_amd64_avx512_linux;
- void init_registers_amd64_mpx_linux (void);
- extern const struct target_desc *tdesc_amd64_mpx_linux;
- void init_registers_x32_linux (void);
- extern const struct target_desc *tdesc_x32_linux;
- void init_registers_x32_avx_linux (void);
- extern const struct target_desc *tdesc_x32_avx_linux;
- void init_registers_x32_avx512_linux (void);
- extern const struct target_desc *tdesc_x32_avx512_linux;
- #endif
- void init_registers_i386_linux (void);
- extern const struct target_desc *tdesc_i386_linux;
- void init_registers_i386_mmx_linux (void);
- extern const struct target_desc *tdesc_i386_mmx_linux;
- void init_registers_i386_avx_linux (void);
- extern const struct target_desc *tdesc_i386_avx_linux;
- void init_registers_i386_avx512_linux (void);
- extern const struct target_desc *tdesc_i386_avx512_linux;
- void init_registers_i386_mpx_linux (void);
- extern const struct target_desc *tdesc_i386_mpx_linux;
- #ifdef __x86_64__
- static struct target_desc *tdesc_amd64_linux_no_xml;
- #endif
- static struct target_desc *tdesc_i386_linux_no_xml;
- static unsigned char jump_insn[] = { 0xe9, 0, 0, 0, 0 };
- static unsigned char small_jump_insn[] = { 0x66, 0xe9, 0, 0 };
- static const char *xmltarget_i386_linux_no_xml = "@<target>\
- <architecture>i386</architecture>\
- <osabi>GNU/Linux</osabi>\
- </target>";
- #ifdef __x86_64__
- static const char *xmltarget_amd64_linux_no_xml = "@<target>\
- <architecture>i386:x86-64</architecture>\
- <osabi>GNU/Linux</osabi>\
- </target>";
- #endif
- #include <sys/reg.h>
- #include <sys/procfs.h>
- #include <sys/ptrace.h>
- #include <sys/uio.h>
- #ifndef PTRACE_GETREGSET
- #define PTRACE_GETREGSET 0x4204
- #endif
- #ifndef PTRACE_SETREGSET
- #define PTRACE_SETREGSET 0x4205
- #endif
- #ifndef PTRACE_GET_THREAD_AREA
- #define PTRACE_GET_THREAD_AREA 25
- #endif
- #ifndef PTRACE_ARCH_PRCTL
- #define PTRACE_ARCH_PRCTL 30
- #endif
- #ifndef ARCH_GET_FS
- #define ARCH_SET_GS 0x1001
- #define ARCH_SET_FS 0x1002
- #define ARCH_GET_FS 0x1003
- #define ARCH_GET_GS 0x1004
- #endif
- struct arch_process_info
- {
- struct x86_debug_reg_state debug_reg_state;
- };
- struct arch_lwp_info
- {
-
- int debug_registers_changed;
- };
- #ifdef __x86_64__
- static int i386_regmap[] =
- {
- RAX * 8, RCX * 8, RDX * 8, RBX * 8,
- RSP * 8, RBP * 8, RSI * 8, RDI * 8,
- RIP * 8, EFLAGS * 8, CS * 8, SS * 8,
- DS * 8, ES * 8, FS * 8, GS * 8
- };
- #define I386_NUM_REGS (sizeof (i386_regmap) / sizeof (i386_regmap[0]))
- #define ORIG_EAX ORIG_RAX
- static const int x86_64_regmap[] =
- {
- RAX * 8, RBX * 8, RCX * 8, RDX * 8,
- RSI * 8, RDI * 8, RBP * 8, RSP * 8,
- R8 * 8, R9 * 8, R10 * 8, R11 * 8,
- R12 * 8, R13 * 8, R14 * 8, R15 * 8,
- RIP * 8, EFLAGS * 8, CS * 8, SS * 8,
- DS * 8, ES * 8, FS * 8, GS * 8,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- ORIG_RAX * 8,
- -1, -1, -1, -1,
- -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
- };
- #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0]))
- #define X86_64_USER_REGS (GS + 1)
- #else
- static int i386_regmap[] =
- {
- EAX * 4, ECX * 4, EDX * 4, EBX * 4,
- UESP * 4, EBP * 4, ESI * 4, EDI * 4,
- EIP * 4, EFL * 4, CS * 4, SS * 4,
- DS * 4, ES * 4, FS * 4, GS * 4
- };
- #define I386_NUM_REGS (sizeof (i386_regmap) / sizeof (i386_regmap[0]))
- #endif
- #ifdef __x86_64__
- static int
- is_64bit_tdesc (void)
- {
- struct regcache *regcache = get_thread_regcache (current_thread, 0);
- return register_size (regcache->tdesc, 0) == 8;
- }
- #endif
- ps_err_e
- ps_get_thread_area (const struct ps_prochandle *ph,
- lwpid_t lwpid, int idx, void **base)
- {
- #ifdef __x86_64__
- int use_64bit = is_64bit_tdesc ();
- if (use_64bit)
- {
- switch (idx)
- {
- case FS:
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) == 0)
- return PS_OK;
- break;
- case GS:
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) == 0)
- return PS_OK;
- break;
- default:
- return PS_BADADDR;
- }
- return PS_ERR;
- }
- #endif
- {
- unsigned int desc[4];
- if (ptrace (PTRACE_GET_THREAD_AREA, lwpid,
- (void *) (intptr_t) idx, (unsigned long) &desc) < 0)
- return PS_ERR;
-
- *base = (void *) (uintptr_t) desc[1];
- return PS_OK;
- }
- }
- static int
- x86_get_thread_area (int lwpid, CORE_ADDR *addr)
- {
- #ifdef __x86_64__
- int use_64bit = is_64bit_tdesc ();
- if (use_64bit)
- {
- void *base;
- if (ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_GET_FS) == 0)
- {
- *addr = (CORE_ADDR) (uintptr_t) base;
- return 0;
- }
- return -1;
- }
- #endif
- {
- struct lwp_info *lwp = find_lwp_pid (pid_to_ptid (lwpid));
- struct thread_info *thr = get_lwp_thread (lwp);
- struct regcache *regcache = get_thread_regcache (thr, 1);
- unsigned int desc[4];
- ULONGEST gs = 0;
- const int reg_thread_area = 3;
- int idx;
- collect_register_by_name (regcache, "gs", &gs);
- idx = gs >> reg_thread_area;
- if (ptrace (PTRACE_GET_THREAD_AREA,
- lwpid_of (thr),
- (void *) (long) idx, (unsigned long) &desc) < 0)
- return -1;
- *addr = desc[1];
- return 0;
- }
- }
- static int
- x86_cannot_store_register (int regno)
- {
- #ifdef __x86_64__
- if (is_64bit_tdesc ())
- return 0;
- #endif
- return regno >= I386_NUM_REGS;
- }
- static int
- x86_cannot_fetch_register (int regno)
- {
- #ifdef __x86_64__
- if (is_64bit_tdesc ())
- return 0;
- #endif
- return regno >= I386_NUM_REGS;
- }
- static void
- x86_fill_gregset (struct regcache *regcache, void *buf)
- {
- int i;
- #ifdef __x86_64__
- if (register_size (regcache->tdesc, 0) == 8)
- {
- for (i = 0; i < X86_64_NUM_REGS; i++)
- if (x86_64_regmap[i] != -1)
- collect_register (regcache, i, ((char *) buf) + x86_64_regmap[i]);
- return;
- }
-
- memset (buf, 0x00, X86_64_USER_REGS * 8);
- #endif
- for (i = 0; i < I386_NUM_REGS; i++)
- collect_register (regcache, i, ((char *) buf) + i386_regmap[i]);
- collect_register_by_name (regcache, "orig_eax",
- ((char *) buf) + ORIG_EAX * 4);
- }
- static void
- x86_store_gregset (struct regcache *regcache, const void *buf)
- {
- int i;
- #ifdef __x86_64__
- if (register_size (regcache->tdesc, 0) == 8)
- {
- for (i = 0; i < X86_64_NUM_REGS; i++)
- if (x86_64_regmap[i] != -1)
- supply_register (regcache, i, ((char *) buf) + x86_64_regmap[i]);
- return;
- }
- #endif
- for (i = 0; i < I386_NUM_REGS; i++)
- supply_register (regcache, i, ((char *) buf) + i386_regmap[i]);
- supply_register_by_name (regcache, "orig_eax",
- ((char *) buf) + ORIG_EAX * 4);
- }
- static void
- x86_fill_fpregset (struct regcache *regcache, void *buf)
- {
- #ifdef __x86_64__
- i387_cache_to_fxsave (regcache, buf);
- #else
- i387_cache_to_fsave (regcache, buf);
- #endif
- }
- static void
- x86_store_fpregset (struct regcache *regcache, const void *buf)
- {
- #ifdef __x86_64__
- i387_fxsave_to_cache (regcache, buf);
- #else
- i387_fsave_to_cache (regcache, buf);
- #endif
- }
- #ifndef __x86_64__
- static void
- x86_fill_fpxregset (struct regcache *regcache, void *buf)
- {
- i387_cache_to_fxsave (regcache, buf);
- }
- static void
- x86_store_fpxregset (struct regcache *regcache, const void *buf)
- {
- i387_fxsave_to_cache (regcache, buf);
- }
- #endif
- static void
- x86_fill_xstateregset (struct regcache *regcache, void *buf)
- {
- i387_cache_to_xsave (regcache, buf);
- }
- static void
- x86_store_xstateregset (struct regcache *regcache, const void *buf)
- {
- i387_xsave_to_cache (regcache, buf);
- }
- static struct regset_info x86_regsets[] =
- {
- #ifdef HAVE_PTRACE_GETREGS
- { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
- GENERAL_REGS,
- x86_fill_gregset, x86_store_gregset },
- { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_X86_XSTATE, 0,
- EXTENDED_REGS, x86_fill_xstateregset, x86_store_xstateregset },
- # ifndef __x86_64__
- # ifdef HAVE_PTRACE_GETFPXREGS
- { PTRACE_GETFPXREGS, PTRACE_SETFPXREGS, 0, sizeof (elf_fpxregset_t),
- EXTENDED_REGS,
- x86_fill_fpxregset, x86_store_fpxregset },
- # endif
- # endif
- { PTRACE_GETFPREGS, PTRACE_SETFPREGS, 0, sizeof (elf_fpregset_t),
- FP_REGS,
- x86_fill_fpregset, x86_store_fpregset },
- #endif
- { 0, 0, 0, -1, -1, NULL, NULL }
- };
- static CORE_ADDR
- x86_get_pc (struct regcache *regcache)
- {
- int use_64bit = register_size (regcache->tdesc, 0) == 8;
- if (use_64bit)
- {
- unsigned long pc;
- collect_register_by_name (regcache, "rip", &pc);
- return (CORE_ADDR) pc;
- }
- else
- {
- unsigned int pc;
- collect_register_by_name (regcache, "eip", &pc);
- return (CORE_ADDR) pc;
- }
- }
- static void
- x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
- {
- int use_64bit = register_size (regcache->tdesc, 0) == 8;
- if (use_64bit)
- {
- unsigned long newpc = pc;
- supply_register_by_name (regcache, "rip", &newpc);
- }
- else
- {
- unsigned int newpc = pc;
- supply_register_by_name (regcache, "eip", &newpc);
- }
- }
- static const unsigned char x86_breakpoint[] = { 0xCC };
- #define x86_breakpoint_len 1
- static int
- x86_breakpoint_at (CORE_ADDR pc)
- {
- unsigned char c;
- (*the_target->read_memory) (pc, &c, 1);
- if (c == 0xCC)
- return 1;
- return 0;
- }
- static unsigned long
- x86_linux_dr_get (ptid_t ptid, int regnum)
- {
- int tid;
- unsigned long value;
- tid = ptid_get_lwp (ptid);
- errno = 0;
- value = ptrace (PTRACE_PEEKUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), 0);
- if (errno != 0)
- error ("Couldn't read debug register");
- return value;
- }
- static void
- x86_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
- {
- int tid;
- tid = ptid_get_lwp (ptid);
- errno = 0;
- ptrace (PTRACE_POKEUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), value);
- if (errno != 0)
- error ("Couldn't write debug register");
- }
- static int
- update_debug_registers_callback (struct inferior_list_entry *entry,
- void *pid_p)
- {
- struct thread_info *thr = (struct thread_info *) entry;
- struct lwp_info *lwp = get_thread_lwp (thr);
- int pid = *(int *) pid_p;
-
- if (pid_of (thr) == pid)
- {
-
- lwp->arch_private->debug_registers_changed = 1;
-
- if (!lwp->stopped)
- linux_stop_lwp (lwp);
- }
- return 0;
- }
- static void
- x86_dr_low_set_addr (int regnum, CORE_ADDR addr)
- {
-
- int pid = pid_of (current_thread);
- gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
- find_inferior (&all_threads, update_debug_registers_callback, &pid);
- }
- static CORE_ADDR
- x86_dr_low_get_addr (int regnum)
- {
- ptid_t ptid = ptid_of (current_thread);
- gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
- return x86_linux_dr_get (ptid, regnum);
- }
- static void
- x86_dr_low_set_control (unsigned long control)
- {
-
- int pid = pid_of (current_thread);
- find_inferior (&all_threads, update_debug_registers_callback, &pid);
- }
- static unsigned long
- x86_dr_low_get_control (void)
- {
- ptid_t ptid = ptid_of (current_thread);
- return x86_linux_dr_get (ptid, DR_CONTROL);
- }
- static unsigned long
- x86_dr_low_get_status (void)
- {
- ptid_t ptid = ptid_of (current_thread);
- return x86_linux_dr_get (ptid, DR_STATUS);
- }
- struct x86_dr_low_type x86_dr_low =
- {
- x86_dr_low_set_control,
- x86_dr_low_set_addr,
- x86_dr_low_get_addr,
- x86_dr_low_get_status,
- x86_dr_low_get_control,
- sizeof (void *),
- };
- static int
- x86_supports_z_point_type (char z_type)
- {
- switch (z_type)
- {
- case Z_PACKET_SW_BP:
- case Z_PACKET_HW_BP:
- case Z_PACKET_WRITE_WP:
- case Z_PACKET_ACCESS_WP:
- return 1;
- default:
- return 0;
- }
- }
- static int
- x86_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
- int size, struct raw_breakpoint *bp)
- {
- struct process_info *proc = current_process ();
- switch (type)
- {
- case raw_bkpt_type_sw:
- return insert_memory_breakpoint (bp);
- case raw_bkpt_type_hw:
- case raw_bkpt_type_write_wp:
- case raw_bkpt_type_access_wp:
- {
- enum target_hw_bp_type hw_type
- = raw_bkpt_type_to_target_hw_bp_type (type);
- struct x86_debug_reg_state *state
- = &proc->private->arch_private->debug_reg_state;
- return x86_dr_insert_watchpoint (state, hw_type, addr, size);
- }
- default:
-
- return 1;
- }
- }
- static int
- x86_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
- int size, struct raw_breakpoint *bp)
- {
- struct process_info *proc = current_process ();
- switch (type)
- {
- case raw_bkpt_type_sw:
- return remove_memory_breakpoint (bp);
- case raw_bkpt_type_hw:
- case raw_bkpt_type_write_wp:
- case raw_bkpt_type_access_wp:
- {
- enum target_hw_bp_type hw_type
- = raw_bkpt_type_to_target_hw_bp_type (type);
- struct x86_debug_reg_state *state
- = &proc->private->arch_private->debug_reg_state;
- return x86_dr_remove_watchpoint (state, hw_type, addr, size);
- }
- default:
-
- return 1;
- }
- }
- static int
- x86_stopped_by_watchpoint (void)
- {
- struct process_info *proc = current_process ();
- return x86_dr_stopped_by_watchpoint (&proc->private->arch_private->debug_reg_state);
- }
- static CORE_ADDR
- x86_stopped_data_address (void)
- {
- struct process_info *proc = current_process ();
- CORE_ADDR addr;
- if (x86_dr_stopped_data_address (&proc->private->arch_private->debug_reg_state,
- &addr))
- return addr;
- return 0;
- }
- static struct arch_process_info *
- x86_linux_new_process (void)
- {
- struct arch_process_info *info = XCNEW (struct arch_process_info);
- x86_low_init_dregs (&info->debug_reg_state);
- return info;
- }
- static struct arch_lwp_info *
- x86_linux_new_thread (void)
- {
- struct arch_lwp_info *info = XCNEW (struct arch_lwp_info);
- info->debug_registers_changed = 1;
- return info;
- }
- static void
- x86_linux_prepare_to_resume (struct lwp_info *lwp)
- {
- ptid_t ptid = ptid_of (get_lwp_thread (lwp));
- int clear_status = 0;
- if (lwp->arch_private->debug_registers_changed)
- {
- int i;
- int pid = ptid_get_pid (ptid);
- struct process_info *proc = find_process_pid (pid);
- struct x86_debug_reg_state *state
- = &proc->private->arch_private->debug_reg_state;
- x86_linux_dr_set (ptid, DR_CONTROL, 0);
- ALL_DEBUG_ADDRESS_REGISTERS (i)
- if (state->dr_ref_count[i] > 0)
- {
- x86_linux_dr_set (ptid, i, state->dr_mirror[i]);
-
- clear_status = 1;
- }
- if (state->dr_control_mirror != 0)
- x86_linux_dr_set (ptid, DR_CONTROL, state->dr_control_mirror);
- lwp->arch_private->debug_registers_changed = 0;
- }
- if (clear_status || lwp->stop_reason == LWP_STOPPED_BY_WATCHPOINT)
- x86_linux_dr_set (ptid, DR_STATUS, 0);
- }
- #ifdef __x86_64__
- typedef int compat_int_t;
- typedef unsigned int compat_uptr_t;
- typedef int compat_time_t;
- typedef int compat_timer_t;
- typedef int compat_clock_t;
- struct compat_timeval
- {
- compat_time_t tv_sec;
- int tv_usec;
- };
- typedef union compat_sigval
- {
- compat_int_t sival_int;
- compat_uptr_t sival_ptr;
- } compat_sigval_t;
- typedef struct compat_siginfo
- {
- int si_signo;
- int si_errno;
- int si_code;
- union
- {
- int _pad[((128 / sizeof (int)) - 3)];
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- } _kill;
-
- struct
- {
- compat_timer_t _tid;
- int _overrun;
- compat_sigval_t _sigval;
- } _timer;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- compat_sigval_t _sigval;
- } _rt;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- int _status;
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- struct
- {
- unsigned int _addr;
- } _sigfault;
-
- struct
- {
- int _band;
- int _fd;
- } _sigpoll;
- } _sifields;
- } compat_siginfo_t;
- typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t;
- typedef struct compat_x32_siginfo
- {
- int si_signo;
- int si_errno;
- int si_code;
- union
- {
- int _pad[((128 / sizeof (int)) - 3)];
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- } _kill;
-
- struct
- {
- compat_timer_t _tid;
- int _overrun;
- compat_sigval_t _sigval;
- } _timer;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- compat_sigval_t _sigval;
- } _rt;
-
- struct
- {
- unsigned int _pid;
- unsigned int _uid;
- int _status;
- compat_x32_clock_t _utime;
- compat_x32_clock_t _stime;
- } _sigchld;
-
- struct
- {
- unsigned int _addr;
- } _sigfault;
-
- struct
- {
- int _band;
- int _fd;
- } _sigpoll;
- } _sifields;
- } compat_x32_siginfo_t __attribute__ ((__aligned__ (8)));
- #define cpt_si_pid _sifields._kill._pid
- #define cpt_si_uid _sifields._kill._uid
- #define cpt_si_timerid _sifields._timer._tid
- #define cpt_si_overrun _sifields._timer._overrun
- #define cpt_si_status _sifields._sigchld._status
- #define cpt_si_utime _sifields._sigchld._utime
- #define cpt_si_stime _sifields._sigchld._stime
- #define cpt_si_ptr _sifields._rt._sigval.sival_ptr
- #define cpt_si_addr _sifields._sigfault._addr
- #define cpt_si_band _sifields._sigpoll._band
- #define cpt_si_fd _sifields._sigpoll._fd
- #ifndef si_timerid
- #define si_timerid si_timer1
- #endif
- #ifndef si_overrun
- #define si_overrun si_timer2
- #endif
- static void
- compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->cpt_si_timerid = from->si_timerid;
- to->cpt_si_overrun = from->si_overrun;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- }
- else if (to->si_code < 0)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_status = from->si_status;
- to->cpt_si_utime = from->si_utime;
- to->cpt_si_stime = from->si_stime;
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->cpt_si_addr = (intptr_t) from->si_addr;
- break;
- case SIGPOLL:
- to->cpt_si_band = from->si_band;
- to->cpt_si_fd = from->si_fd;
- break;
- default:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- break;
- }
- }
- }
- static void
- siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->si_timerid = from->cpt_si_timerid;
- to->si_overrun = from->cpt_si_overrun;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- }
- else if (to->si_code < 0)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_status = from->cpt_si_status;
- to->si_utime = from->cpt_si_utime;
- to->si_stime = from->cpt_si_stime;
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
- break;
- case SIGPOLL:
- to->si_band = from->cpt_si_band;
- to->si_fd = from->cpt_si_fd;
- break;
- default:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
- break;
- }
- }
- }
- static void
- compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
- siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->cpt_si_timerid = from->si_timerid;
- to->cpt_si_overrun = from->si_overrun;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- }
- else if (to->si_code < 0)
- {
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_status = from->si_status;
- to->cpt_si_utime = from->si_utime;
- to->cpt_si_stime = from->si_stime;
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->cpt_si_addr = (intptr_t) from->si_addr;
- break;
- case SIGPOLL:
- to->cpt_si_band = from->si_band;
- to->cpt_si_fd = from->si_fd;
- break;
- default:
- to->cpt_si_pid = from->si_pid;
- to->cpt_si_uid = from->si_uid;
- to->cpt_si_ptr = (intptr_t) from->si_ptr;
- break;
- }
- }
- }
- static void
- siginfo_from_compat_x32_siginfo (siginfo_t *to,
- compat_x32_siginfo_t *from)
- {
- memset (to, 0, sizeof (*to));
- to->si_signo = from->si_signo;
- to->si_errno = from->si_errno;
- to->si_code = from->si_code;
- if (to->si_code == SI_TIMER)
- {
- to->si_timerid = from->cpt_si_timerid;
- to->si_overrun = from->cpt_si_overrun;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else if (to->si_code == SI_USER)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- }
- else if (to->si_code < 0)
- {
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
- }
- else
- {
- switch (to->si_signo)
- {
- case SIGCHLD:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_status = from->cpt_si_status;
- to->si_utime = from->cpt_si_utime;
- to->si_stime = from->cpt_si_stime;
- break;
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
- case SIGBUS:
- to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
- break;
- case SIGPOLL:
- to->si_band = from->cpt_si_band;
- to->si_fd = from->cpt_si_fd;
- break;
- default:
- to->si_pid = from->cpt_si_pid;
- to->si_uid = from->cpt_si_uid;
- to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
- break;
- }
- }
- }
- #endif
- static int
- x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
- {
- #ifdef __x86_64__
- unsigned int machine;
- int tid = lwpid_of (current_thread);
- int is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
-
- if (!is_64bit_tdesc ())
- {
- gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t));
- if (direction == 0)
- compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
- else
- siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
- return 1;
- }
-
- else if (!is_elf64 && sizeof (void *) == 8)
- {
- gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t));
- if (direction == 0)
- compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
- native);
- else
- siginfo_from_compat_x32_siginfo (native,
- (struct compat_x32_siginfo *) inf);
- return 1;
- }
- #endif
- return 0;
- }
- static int use_xml;
- #define I386_LINUX_XSAVE_XCR0_OFFSET 464
- int have_ptrace_getfpxregs =
- #ifdef HAVE_PTRACE_GETFPXREGS
- -1
- #else
- 0
- #endif
- ;
- static int have_ptrace_getregset = -1;
- static const struct target_desc *
- x86_linux_read_description (void)
- {
- unsigned int machine;
- int is_elf64;
- int xcr0_features;
- int tid;
- static uint64_t xcr0;
- struct regset_info *regset;
- tid = lwpid_of (current_thread);
- is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
- if (sizeof (void *) == 4)
- {
- if (is_elf64 > 0)
- error (_("Can't debug 64-bit process with 32-bit GDBserver"));
- #ifndef __x86_64__
- else if (machine == EM_X86_64)
- error (_("Can't debug x86-64 process with 32-bit GDBserver"));
- #endif
- }
- #if !defined __x86_64__ && defined HAVE_PTRACE_GETFPXREGS
- if (machine == EM_386 && have_ptrace_getfpxregs == -1)
- {
- elf_fpxregset_t fpxregs;
- if (ptrace (PTRACE_GETFPXREGS, tid, 0, (long) &fpxregs) < 0)
- {
- have_ptrace_getfpxregs = 0;
- have_ptrace_getregset = 0;
- return tdesc_i386_mmx_linux;
- }
- else
- have_ptrace_getfpxregs = 1;
- }
- #endif
- if (!use_xml)
- {
- x86_xcr0 = X86_XSTATE_SSE_MASK;
-
- #ifdef __x86_64__
- if (machine == EM_X86_64)
- return tdesc_amd64_linux_no_xml;
- else
- #endif
- return tdesc_i386_linux_no_xml;
- }
- if (have_ptrace_getregset == -1)
- {
- uint64_t xstateregs[(X86_XSTATE_SSE_SIZE / sizeof (uint64_t))];
- struct iovec iov;
- iov.iov_base = xstateregs;
- iov.iov_len = sizeof (xstateregs);
-
- if (ptrace (PTRACE_GETREGSET, tid,
- (unsigned int) NT_X86_XSTATE, (long) &iov) < 0)
- have_ptrace_getregset = 0;
- else
- {
- have_ptrace_getregset = 1;
-
- xcr0 = xstateregs[(I386_LINUX_XSAVE_XCR0_OFFSET
- / sizeof (uint64_t))];
-
- for (regset = x86_regsets;
- regset->fill_function != NULL; regset++)
- if (regset->get_request == PTRACE_GETREGSET)
- regset->size = X86_XSTATE_SIZE (xcr0);
- else if (regset->type != GENERAL_REGS)
- regset->size = 0;
- }
- }
-
- xcr0_features = (have_ptrace_getregset
- && (xcr0 & X86_XSTATE_ALL_MASK));
- if (xcr0_features)
- x86_xcr0 = xcr0;
- if (machine == EM_X86_64)
- {
- #ifdef __x86_64__
- if (is_elf64)
- {
- if (xcr0_features)
- {
- switch (xcr0 & X86_XSTATE_ALL_MASK)
- {
- case X86_XSTATE_AVX512_MASK:
- return tdesc_amd64_avx512_linux;
- case X86_XSTATE_MPX_MASK:
- return tdesc_amd64_mpx_linux;
- case X86_XSTATE_AVX_MASK:
- return tdesc_amd64_avx_linux;
- default:
- return tdesc_amd64_linux;
- }
- }
- else
- return tdesc_amd64_linux;
- }
- else
- {
- if (xcr0_features)
- {
- switch (xcr0 & X86_XSTATE_ALL_MASK)
- {
- case X86_XSTATE_AVX512_MASK:
- return tdesc_x32_avx512_linux;
- case X86_XSTATE_MPX_MASK:
- case X86_XSTATE_AVX_MASK:
- return tdesc_x32_avx_linux;
- default:
- return tdesc_x32_linux;
- }
- }
- else
- return tdesc_x32_linux;
- }
- #endif
- }
- else
- {
- if (xcr0_features)
- {
- switch (xcr0 & X86_XSTATE_ALL_MASK)
- {
- case (X86_XSTATE_AVX512_MASK):
- return tdesc_i386_avx512_linux;
- case (X86_XSTATE_MPX_MASK):
- return tdesc_i386_mpx_linux;
- case (X86_XSTATE_AVX_MASK):
- return tdesc_i386_avx_linux;
- default:
- return tdesc_i386_linux;
- }
- }
- else
- return tdesc_i386_linux;
- }
- gdb_assert_not_reached ("failed to return tdesc");
- }
- static int
- same_process_callback (struct inferior_list_entry *entry, void *data)
- {
- int pid = *(int *) data;
- return (ptid_get_pid (entry->id) == pid);
- }
- static void
- x86_arch_setup_process_callback (struct inferior_list_entry *entry)
- {
- int pid = ptid_get_pid (entry->id);
-
- current_thread
- = (struct thread_info *) find_inferior (&all_threads,
- same_process_callback, &pid);
- the_low_target.arch_setup ();
- }
- static void
- x86_linux_update_xmltarget (void)
- {
- struct thread_info *saved_thread = current_thread;
-
- regcache_release ();
- for_each_inferior (&all_processes, x86_arch_setup_process_callback);
- current_thread = saved_thread;
- }
- static void
- x86_linux_process_qsupported (const char *query)
- {
-
- use_xml = 0;
- if (query != NULL && strncmp (query, "xmlRegisters=", 13) == 0)
- {
- char *copy = xstrdup (query + 13);
- char *p;
- for (p = strtok (copy, ","); p != NULL; p = strtok (NULL, ","))
- {
- if (strcmp (p, "i386") == 0)
- {
- use_xml = 1;
- break;
- }
- }
- free (copy);
- }
- x86_linux_update_xmltarget ();
- }
- static struct regsets_info x86_regsets_info =
- {
- x86_regsets,
- 0,
- NULL,
- };
- #ifdef __x86_64__
- static struct regs_info amd64_linux_regs_info =
- {
- NULL,
- NULL,
- &x86_regsets_info
- };
- #endif
- static struct usrregs_info i386_linux_usrregs_info =
- {
- I386_NUM_REGS,
- i386_regmap,
- };
- static struct regs_info i386_linux_regs_info =
- {
- NULL,
- &i386_linux_usrregs_info,
- &x86_regsets_info
- };
- const struct regs_info *
- x86_linux_regs_info (void)
- {
- #ifdef __x86_64__
- if (is_64bit_tdesc ())
- return &amd64_linux_regs_info;
- else
- #endif
- return &i386_linux_regs_info;
- }
- static void
- x86_arch_setup (void)
- {
- current_process ()->tdesc = x86_linux_read_description ();
- }
- static int
- x86_supports_tracepoints (void)
- {
- return 1;
- }
- static void
- append_insns (CORE_ADDR *to, size_t len, const unsigned char *buf)
- {
- write_inferior_memory (*to, buf, len);
- *to += len;
- }
- static int
- push_opcode (unsigned char *buf, char *op)
- {
- unsigned char *buf_org = buf;
- while (1)
- {
- char *endptr;
- unsigned long ul = strtoul (op, &endptr, 16);
- if (endptr == op)
- break;
- *buf++ = ul;
- op = endptr;
- }
- return buf - buf_org;
- }
- #ifdef __x86_64__
- static int
- amd64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
- CORE_ADDR collector,
- CORE_ADDR lockaddr,
- ULONGEST orig_size,
- CORE_ADDR *jump_entry,
- CORE_ADDR *trampoline,
- ULONGEST *trampoline_size,
- unsigned char *jjump_pad_insn,
- ULONGEST *jjump_pad_insn_size,
- CORE_ADDR *adjusted_insn_addr,
- CORE_ADDR *adjusted_insn_addr_end,
- char *err)
- {
- unsigned char buf[40];
- int i, offset;
- int64_t loffset;
- CORE_ADDR buildaddr = *jump_entry;
-
-
- i = 0;
-
- buf[i++] = 0x54;
- buf[i++] = 0x55;
- buf[i++] = 0x57;
- buf[i++] = 0x56;
- buf[i++] = 0x52;
- buf[i++] = 0x51;
- buf[i++] = 0x53;
- buf[i++] = 0x50;
- buf[i++] = 0x41; buf[i++] = 0x57;
- buf[i++] = 0x41; buf[i++] = 0x56;
- buf[i++] = 0x41; buf[i++] = 0x55;
- buf[i++] = 0x41; buf[i++] = 0x54;
- buf[i++] = 0x41; buf[i++] = 0x53;
- buf[i++] = 0x41; buf[i++] = 0x52;
- buf[i++] = 0x41; buf[i++] = 0x51;
- buf[i++] = 0x41; buf[i++] = 0x50;
- buf[i++] = 0x9c;
- buf[i++] = 0x48;
- buf[i++] = 0xbf;
- *((unsigned long *)(buf + i)) = (unsigned long) tpaddr;
- i += sizeof (unsigned long);
- buf[i++] = 0x57;
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "48 83 ec 18");
- i += push_opcode (&buf[i], "48 b8");
- memcpy (buf + i, &tpoint, 8);
- i += 8;
- i += push_opcode (&buf[i], "48 89 04 24");
- i += push_opcode (&buf[i],
- "64 48 8b 04 25 00 00 00 00");
- i += push_opcode (&buf[i], "48 89 44 24 08");
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "48 be");
- memcpy (&buf[i], (void *) &lockaddr, 8);
- i += 8;
- i += push_opcode (&buf[i], "48 89 e1");
- i += push_opcode (&buf[i], "31 c0");
- i += push_opcode (&buf[i], "f0 48 0f b1 0e");
- i += push_opcode (&buf[i], "48 85 c0");
- i += push_opcode (&buf[i], "75 f4");
- append_insns (&buildaddr, i, buf);
-
-
- i = 0;
- i += push_opcode (&buf[i], "48 89 e6");
- i += push_opcode (&buf[i], "48 83 c6 18");
-
- i += push_opcode (&buf[i], "48 bf");
- memcpy (buf + i, &tpoint, 8);
- i += 8;
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "48 b8");
- memcpy (buf + i, &collector, 8);
- i += 8;
- i += push_opcode (&buf[i], "ff d0");
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "31 c0");
- i += push_opcode (&buf[i], "48 a3");
- memcpy (buf + i, &lockaddr, 8);
- i += 8;
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "48 83 c4 18");
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- buf[i++] = 0x48;
- buf[i++] = 0x83;
- buf[i++] = 0xc4;
- buf[i++] = 0x08;
- buf[i++] = 0x9d;
- buf[i++] = 0x41; buf[i++] = 0x58;
- buf[i++] = 0x41; buf[i++] = 0x59;
- buf[i++] = 0x41; buf[i++] = 0x5a;
- buf[i++] = 0x41; buf[i++] = 0x5b;
- buf[i++] = 0x41; buf[i++] = 0x5c;
- buf[i++] = 0x41; buf[i++] = 0x5d;
- buf[i++] = 0x41; buf[i++] = 0x5e;
- buf[i++] = 0x41; buf[i++] = 0x5f;
- buf[i++] = 0x58;
- buf[i++] = 0x5b;
- buf[i++] = 0x59;
- buf[i++] = 0x5a;
- buf[i++] = 0x5e;
- buf[i++] = 0x5f;
- buf[i++] = 0x5d;
- buf[i++] = 0x5c;
- append_insns (&buildaddr, i, buf);
-
- *adjusted_insn_addr = buildaddr;
- relocate_instruction (&buildaddr, tpaddr);
- *adjusted_insn_addr_end = buildaddr;
-
- loffset = (tpaddr + orig_size) - (buildaddr + sizeof (jump_insn));
- if (loffset > INT_MAX || loffset < INT_MIN)
- {
- sprintf (err,
- "E.Jump back from jump pad too far from tracepoint "
- "(offset 0x%" PRIx64 " > int32).", loffset);
- return 1;
- }
- offset = (int) loffset;
- memcpy (buf, jump_insn, sizeof (jump_insn));
- memcpy (buf + 1, &offset, 4);
- append_insns (&buildaddr, sizeof (jump_insn), buf);
-
- loffset = *jump_entry - (tpaddr + sizeof (jump_insn));
- if (loffset > INT_MAX || loffset < INT_MIN)
- {
- sprintf (err,
- "E.Jump pad too far from tracepoint "
- "(offset 0x%" PRIx64 " > int32).", loffset);
- return 1;
- }
- offset = (int) loffset;
- memcpy (buf, jump_insn, sizeof (jump_insn));
- memcpy (buf + 1, &offset, 4);
- memcpy (jjump_pad_insn, buf, sizeof (jump_insn));
- *jjump_pad_insn_size = sizeof (jump_insn);
-
- *jump_entry = buildaddr;
- return 0;
- }
- #endif
- static int
- i386_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
- CORE_ADDR collector,
- CORE_ADDR lockaddr,
- ULONGEST orig_size,
- CORE_ADDR *jump_entry,
- CORE_ADDR *trampoline,
- ULONGEST *trampoline_size,
- unsigned char *jjump_pad_insn,
- ULONGEST *jjump_pad_insn_size,
- CORE_ADDR *adjusted_insn_addr,
- CORE_ADDR *adjusted_insn_addr_end,
- char *err)
- {
- unsigned char buf[0x100];
- int i, offset;
- CORE_ADDR buildaddr = *jump_entry;
-
-
- i = 0;
- buf[i++] = 0x60;
- buf[i++] = 0x68;
- *((int *)(buf + i)) = (int) tpaddr;
- i += 4;
- buf[i++] = 0x9c;
- buf[i++] = 0x1e;
- buf[i++] = 0x06;
- buf[i++] = 0x0f;
- buf[i++] = 0xa0;
- buf[i++] = 0x0f;
- buf[i++] = 0xa8;
- buf[i++] = 0x16;
- buf[i++] = 0x0e;
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "83 ec 08");
-
- i += push_opcode (&buf[i], "b8");
- memcpy (buf + i, &tpoint, 4);
- i += 4;
- i += push_opcode (&buf[i], "89 04 24");
- i += push_opcode (&buf[i], "65 a1 00 00 00 00");
- i += push_opcode (&buf[i], "89 44 24 04");
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "31 c0");
- i += push_opcode (&buf[i], "f0 0f b1 25");
- memcpy (&buf[i], (void *) &lockaddr, 4);
- i += 4;
- i += push_opcode (&buf[i], "85 c0");
- i += push_opcode (&buf[i], "75 f2");
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "89 e0");
- i += push_opcode (&buf[i], "83 c0 08");
- i += push_opcode (&buf[i], "89 44 24 fc");
- append_insns (&buildaddr, i, buf);
- i = 0;
- i += push_opcode (&buf[i], "83 ec 08");
- append_insns (&buildaddr, i, buf);
- i = 0;
- i += push_opcode (&buf[i], "c7 04 24");
- memcpy (&buf[i], (void *) &tpoint, 4);
- i += 4;
- append_insns (&buildaddr, i, buf);
- buf[0] = 0xe8;
- offset = collector - (buildaddr + sizeof (jump_insn));
- memcpy (buf + 1, &offset, 4);
- append_insns (&buildaddr, 5, buf);
-
- buf[0] = 0x83;
- buf[1] = 0xc4;
- buf[2] = 0x08;
- append_insns (&buildaddr, 3, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "31 c0");
- i += push_opcode (&buf[i], "a3");
- memcpy (buf + i, &lockaddr, 4);
- i += 4;
- append_insns (&buildaddr, i, buf);
-
- i = 0;
- i += push_opcode (&buf[i], "83 c4 08");
- append_insns (&buildaddr, i, buf);
- i = 0;
- buf[i++] = 0x83;
- buf[i++] = 0xc4;
- buf[i++] = 0x04;
- buf[i++] = 0x17;
- buf[i++] = 0x0f;
- buf[i++] = 0xa9;
- buf[i++] = 0x0f;
- buf[i++] = 0xa1;
- buf[i++] = 0x07;
- buf[i++] = 0x1f;
- buf[i++] = 0x9d;
- buf[i++] = 0x83;
- buf[i++] = 0xc4;
- buf[i++] = 0x04;
- buf[i++] = 0x61;
- append_insns (&buildaddr, i, buf);
-
- *adjusted_insn_addr = buildaddr;
- relocate_instruction (&buildaddr, tpaddr);
- *adjusted_insn_addr_end = buildaddr;
-
- offset = (tpaddr + orig_size) - (buildaddr + sizeof (jump_insn));
- memcpy (buf, jump_insn, sizeof (jump_insn));
- memcpy (buf + 1, &offset, 4);
- append_insns (&buildaddr, sizeof (jump_insn), buf);
-
- if (orig_size == 4)
- {
-
- *trampoline_size = sizeof (jump_insn);
- if (!claim_trampoline_space (*trampoline_size, trampoline))
- {
-
- strcpy (err,
- "E.Cannot allocate trampoline space needed for fast "
- "tracepoints on 4-byte instructions.");
- return 1;
- }
- offset = *jump_entry - (*trampoline + sizeof (jump_insn));
- memcpy (buf, jump_insn, sizeof (jump_insn));
- memcpy (buf + 1, &offset, 4);
- write_inferior_memory (*trampoline, buf, sizeof (jump_insn));
-
- offset = (*trampoline - (tpaddr + sizeof (small_jump_insn))) & 0xffff;
- memcpy (buf, small_jump_insn, sizeof (small_jump_insn));
- memcpy (buf + 2, &offset, 2);
- memcpy (jjump_pad_insn, buf, sizeof (small_jump_insn));
- *jjump_pad_insn_size = sizeof (small_jump_insn);
- }
- else
- {
-
- offset = *jump_entry - (tpaddr + sizeof (jump_insn));
- memcpy (buf, jump_insn, sizeof (jump_insn));
- memcpy (buf + 1, &offset, 4);
- memcpy (jjump_pad_insn, buf, sizeof (jump_insn));
- *jjump_pad_insn_size = sizeof (jump_insn);
- }
-
- *jump_entry = buildaddr;
- return 0;
- }
- static int
- x86_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
- CORE_ADDR collector,
- CORE_ADDR lockaddr,
- ULONGEST orig_size,
- CORE_ADDR *jump_entry,
- CORE_ADDR *trampoline,
- ULONGEST *trampoline_size,
- unsigned char *jjump_pad_insn,
- ULONGEST *jjump_pad_insn_size,
- CORE_ADDR *adjusted_insn_addr,
- CORE_ADDR *adjusted_insn_addr_end,
- char *err)
- {
- #ifdef __x86_64__
- if (is_64bit_tdesc ())
- return amd64_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
- collector, lockaddr,
- orig_size, jump_entry,
- trampoline, trampoline_size,
- jjump_pad_insn,
- jjump_pad_insn_size,
- adjusted_insn_addr,
- adjusted_insn_addr_end,
- err);
- #endif
- return i386_install_fast_tracepoint_jump_pad (tpoint, tpaddr,
- collector, lockaddr,
- orig_size, jump_entry,
- trampoline, trampoline_size,
- jjump_pad_insn,
- jjump_pad_insn_size,
- adjusted_insn_addr,
- adjusted_insn_addr_end,
- err);
- }
- static int
- x86_get_min_fast_tracepoint_insn_len (void)
- {
- static int warned_about_fast_tracepoints = 0;
- #ifdef __x86_64__
-
- if (is_64bit_tdesc ())
- return 5;
- #endif
- if (agent_loaded_p ())
- {
- char errbuf[IPA_BUFSIZ];
- errbuf[0] = '\0';
-
- if (have_fast_tracepoint_trampoline_buffer (errbuf))
- return 4;
- else
- {
-
- if (!warned_about_fast_tracepoints)
- {
- warning ("4-byte fast tracepoints not available; %s\n", errbuf);
- warned_about_fast_tracepoints = 1;
- }
- return 5;
- }
- }
- else
- {
-
- return 0;
- }
- }
- static void
- add_insns (unsigned char *start, int len)
- {
- CORE_ADDR buildaddr = current_insn_ptr;
- if (debug_threads)
- debug_printf ("Adding %d bytes of insn at %s\n",
- len, paddress (buildaddr));
- append_insns (&buildaddr, len, start);
- current_insn_ptr = buildaddr;
- }
- #define EMIT_ASM(NAME, INSNS) \
- do \
- { \
- extern unsigned char start_ ## NAME, end_ ## NAME; \
- add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME); \
- __asm__ ("jmp end_" #NAME "\n" \
- "\t" "start_" #NAME ":" \
- "\t" INSNS "\n" \
- "\t" "end_" #NAME ":"); \
- } while (0)
- #ifdef __x86_64__
- #define EMIT_ASM32(NAME,INSNS) \
- do \
- { \
- extern unsigned char start_ ## NAME, end_ ## NAME; \
- add_insns (&start_ ## NAME, &end_ ## NAME - &start_ ## NAME); \
- __asm__ (".code32\n" \
- "\t" "jmp end_" #NAME "\n" \
- "\t" "start_" #NAME ":\n" \
- "\t" INSNS "\n" \
- "\t" "end_" #NAME ":\n" \
- ".code64\n"); \
- } while (0)
- #else
- #define EMIT_ASM32(NAME,INSNS) EMIT_ASM(NAME,INSNS)
- #endif
- #ifdef __x86_64__
- static void
- amd64_emit_prologue (void)
- {
- EMIT_ASM (amd64_prologue,
- "pushq %rbp\n\t"
- "movq %rsp,%rbp\n\t"
- "sub $0x20,%rsp\n\t"
- "movq %rdi,-8(%rbp)\n\t"
- "movq %rsi,-16(%rbp)");
- }
- static void
- amd64_emit_epilogue (void)
- {
- EMIT_ASM (amd64_epilogue,
- "movq -16(%rbp),%rdi\n\t"
- "movq %rax,(%rdi)\n\t"
- "xor %rax,%rax\n\t"
- "leave\n\t"
- "ret");
- }
- static void
- amd64_emit_add (void)
- {
- EMIT_ASM (amd64_add,
- "add (%rsp),%rax\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_sub (void)
- {
- EMIT_ASM (amd64_sub,
- "sub %rax,(%rsp)\n\t"
- "pop %rax");
- }
- static void
- amd64_emit_mul (void)
- {
- emit_error = 1;
- }
- static void
- amd64_emit_lsh (void)
- {
- emit_error = 1;
- }
- static void
- amd64_emit_rsh_signed (void)
- {
- emit_error = 1;
- }
- static void
- amd64_emit_rsh_unsigned (void)
- {
- emit_error = 1;
- }
- static void
- amd64_emit_ext (int arg)
- {
- switch (arg)
- {
- case 8:
- EMIT_ASM (amd64_ext_8,
- "cbtw\n\t"
- "cwtl\n\t"
- "cltq");
- break;
- case 16:
- EMIT_ASM (amd64_ext_16,
- "cwtl\n\t"
- "cltq");
- break;
- case 32:
- EMIT_ASM (amd64_ext_32,
- "cltq");
- break;
- default:
- emit_error = 1;
- }
- }
- static void
- amd64_emit_log_not (void)
- {
- EMIT_ASM (amd64_log_not,
- "test %rax,%rax\n\t"
- "sete %cl\n\t"
- "movzbq %cl,%rax");
- }
- static void
- amd64_emit_bit_and (void)
- {
- EMIT_ASM (amd64_and,
- "and (%rsp),%rax\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_bit_or (void)
- {
- EMIT_ASM (amd64_or,
- "or (%rsp),%rax\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_bit_xor (void)
- {
- EMIT_ASM (amd64_xor,
- "xor (%rsp),%rax\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_bit_not (void)
- {
- EMIT_ASM (amd64_bit_not,
- "xorq $0xffffffffffffffff,%rax");
- }
- static void
- amd64_emit_equal (void)
- {
- EMIT_ASM (amd64_equal,
- "cmp %rax,(%rsp)\n\t"
- "je .Lamd64_equal_true\n\t"
- "xor %rax,%rax\n\t"
- "jmp .Lamd64_equal_end\n\t"
- ".Lamd64_equal_true:\n\t"
- "mov $0x1,%rax\n\t"
- ".Lamd64_equal_end:\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_less_signed (void)
- {
- EMIT_ASM (amd64_less_signed,
- "cmp %rax,(%rsp)\n\t"
- "jl .Lamd64_less_signed_true\n\t"
- "xor %rax,%rax\n\t"
- "jmp .Lamd64_less_signed_end\n\t"
- ".Lamd64_less_signed_true:\n\t"
- "mov $1,%rax\n\t"
- ".Lamd64_less_signed_end:\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_less_unsigned (void)
- {
- EMIT_ASM (amd64_less_unsigned,
- "cmp %rax,(%rsp)\n\t"
- "jb .Lamd64_less_unsigned_true\n\t"
- "xor %rax,%rax\n\t"
- "jmp .Lamd64_less_unsigned_end\n\t"
- ".Lamd64_less_unsigned_true:\n\t"
- "mov $1,%rax\n\t"
- ".Lamd64_less_unsigned_end:\n\t"
- "lea 0x8(%rsp),%rsp");
- }
- static void
- amd64_emit_ref (int size)
- {
- switch (size)
- {
- case 1:
- EMIT_ASM (amd64_ref1,
- "movb (%rax),%al");
- break;
- case 2:
- EMIT_ASM (amd64_ref2,
- "movw (%rax),%ax");
- break;
- case 4:
- EMIT_ASM (amd64_ref4,
- "movl (%rax),%eax");
- break;
- case 8:
- EMIT_ASM (amd64_ref8,
- "movq (%rax),%rax");
- break;
- }
- }
- static void
- amd64_emit_if_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_if_goto,
- "mov %rax,%rcx\n\t"
- "pop %rax\n\t"
- "cmp $0,%rcx\n\t"
- ".byte 0x0f, 0x85, 0x0, 0x0, 0x0, 0x0");
- if (offset_p)
- *offset_p = 10;
- if (size_p)
- *size_p = 4;
- }
- static void
- amd64_emit_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_goto,
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0");
- if (offset_p)
- *offset_p = 1;
- if (size_p)
- *size_p = 4;
- }
- static void
- amd64_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
- {
- int diff = (to - (from + size));
- unsigned char buf[sizeof (int)];
- if (size != 4)
- {
- emit_error = 1;
- return;
- }
- memcpy (buf, &diff, sizeof (int));
- write_inferior_memory (from, buf, sizeof (int));
- }
- static void
- amd64_emit_const (LONGEST num)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0x48; buf[i++] = 0xb8;
- memcpy (&buf[i], &num, sizeof (num));
- i += 8;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- }
- static void
- amd64_emit_call (CORE_ADDR fn)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
- LONGEST offset64;
-
- buildaddr = current_insn_ptr;
- offset64 = fn - (buildaddr + 1 + 4 );
- i = 0;
- if (offset64 > INT_MAX || offset64 < INT_MIN)
- {
-
- buf[i++] = 0x48;
- buf[i++] = 0xba;
- memcpy (buf + i, &fn, 8);
- i += 8;
- buf[i++] = 0xff;
- buf[i++] = 0xd2;
- }
- else
- {
- int offset32 = offset64;
- memcpy (buf + i, &offset32, 4);
- i += 4;
- }
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- }
- static void
- amd64_emit_reg (int reg)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
-
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xbe;
- memcpy (&buf[i], ®, sizeof (reg));
- i += 4;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- amd64_emit_call (get_raw_reg_func_addr ());
- }
- static void
- amd64_emit_pop (void)
- {
- EMIT_ASM (amd64_pop,
- "pop %rax");
- }
- static void
- amd64_emit_stack_flush (void)
- {
- EMIT_ASM (amd64_stack_flush,
- "push %rax");
- }
- static void
- amd64_emit_zero_ext (int arg)
- {
- switch (arg)
- {
- case 8:
- EMIT_ASM (amd64_zero_ext_8,
- "and $0xff,%rax");
- break;
- case 16:
- EMIT_ASM (amd64_zero_ext_16,
- "and $0xffff,%rax");
- break;
- case 32:
- EMIT_ASM (amd64_zero_ext_32,
- "mov $0xffffffff,%rcx\n\t"
- "and %rcx,%rax");
- break;
- default:
- emit_error = 1;
- }
- }
- static void
- amd64_emit_swap (void)
- {
- EMIT_ASM (amd64_swap,
- "mov %rax,%rcx\n\t"
- "pop %rax\n\t"
- "push %rcx");
- }
- static void
- amd64_emit_stack_adjust (int n)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0x48;
- buf[i++] = 0x8d;
- buf[i++] = 0x64;
- buf[i++] = 0x24;
-
- buf[i++] = n * 8;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- }
- static void
- amd64_emit_int_call_1 (CORE_ADDR fn, int arg1)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xbf;
- memcpy (&buf[i], &arg1, sizeof (arg1));
- i += 4;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- amd64_emit_call (fn);
- }
- static void
- amd64_emit_void_call_2 (CORE_ADDR fn, int arg1)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xbf;
- memcpy (&buf[i], &arg1, sizeof (arg1));
- i += 4;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- EMIT_ASM (amd64_void_call_2_a,
-
- "push %rax\n\t"
-
- "mov %rax,%rsi");
- amd64_emit_call (fn);
- EMIT_ASM (amd64_void_call_2_b,
-
- "pop %rax");
- }
- void
- amd64_emit_eq_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_eq,
- "cmp %rax,(%rsp)\n\t"
- "jne .Lamd64_eq_fallthru\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lamd64_eq_fallthru:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax");
- if (offset_p)
- *offset_p = 13;
- if (size_p)
- *size_p = 4;
- }
- void
- amd64_emit_ne_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_ne,
- "cmp %rax,(%rsp)\n\t"
- "je .Lamd64_ne_fallthru\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lamd64_ne_fallthru:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax");
- if (offset_p)
- *offset_p = 13;
- if (size_p)
- *size_p = 4;
- }
- void
- amd64_emit_lt_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_lt,
- "cmp %rax,(%rsp)\n\t"
- "jnl .Lamd64_lt_fallthru\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lamd64_lt_fallthru:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax");
- if (offset_p)
- *offset_p = 13;
- if (size_p)
- *size_p = 4;
- }
- void
- amd64_emit_le_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_le,
- "cmp %rax,(%rsp)\n\t"
- "jnle .Lamd64_le_fallthru\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lamd64_le_fallthru:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax");
- if (offset_p)
- *offset_p = 13;
- if (size_p)
- *size_p = 4;
- }
- void
- amd64_emit_gt_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_gt,
- "cmp %rax,(%rsp)\n\t"
- "jng .Lamd64_gt_fallthru\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lamd64_gt_fallthru:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax");
- if (offset_p)
- *offset_p = 13;
- if (size_p)
- *size_p = 4;
- }
- void
- amd64_emit_ge_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM (amd64_ge,
- "cmp %rax,(%rsp)\n\t"
- "jnge .Lamd64_ge_fallthru\n\t"
- ".Lamd64_ge_jump:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lamd64_ge_fallthru:\n\t"
- "lea 0x8(%rsp),%rsp\n\t"
- "pop %rax");
- if (offset_p)
- *offset_p = 13;
- if (size_p)
- *size_p = 4;
- }
- struct emit_ops amd64_emit_ops =
- {
- amd64_emit_prologue,
- amd64_emit_epilogue,
- amd64_emit_add,
- amd64_emit_sub,
- amd64_emit_mul,
- amd64_emit_lsh,
- amd64_emit_rsh_signed,
- amd64_emit_rsh_unsigned,
- amd64_emit_ext,
- amd64_emit_log_not,
- amd64_emit_bit_and,
- amd64_emit_bit_or,
- amd64_emit_bit_xor,
- amd64_emit_bit_not,
- amd64_emit_equal,
- amd64_emit_less_signed,
- amd64_emit_less_unsigned,
- amd64_emit_ref,
- amd64_emit_if_goto,
- amd64_emit_goto,
- amd64_write_goto_address,
- amd64_emit_const,
- amd64_emit_call,
- amd64_emit_reg,
- amd64_emit_pop,
- amd64_emit_stack_flush,
- amd64_emit_zero_ext,
- amd64_emit_swap,
- amd64_emit_stack_adjust,
- amd64_emit_int_call_1,
- amd64_emit_void_call_2,
- amd64_emit_eq_goto,
- amd64_emit_ne_goto,
- amd64_emit_lt_goto,
- amd64_emit_le_goto,
- amd64_emit_gt_goto,
- amd64_emit_ge_goto
- };
- #endif
- static void
- i386_emit_prologue (void)
- {
- EMIT_ASM32 (i386_prologue,
- "push %ebp\n\t"
- "mov %esp,%ebp\n\t"
- "push %ebx");
-
- }
- static void
- i386_emit_epilogue (void)
- {
- EMIT_ASM32 (i386_epilogue,
- "mov 12(%ebp),%ecx\n\t"
- "mov %eax,(%ecx)\n\t"
- "mov %ebx,0x4(%ecx)\n\t"
- "xor %eax,%eax\n\t"
- "pop %ebx\n\t"
- "pop %ebp\n\t"
- "ret");
- }
- static void
- i386_emit_add (void)
- {
- EMIT_ASM32 (i386_add,
- "add (%esp),%eax\n\t"
- "adc 0x4(%esp),%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_sub (void)
- {
- EMIT_ASM32 (i386_sub,
- "subl %eax,(%esp)\n\t"
- "sbbl %ebx,4(%esp)\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t");
- }
- static void
- i386_emit_mul (void)
- {
- emit_error = 1;
- }
- static void
- i386_emit_lsh (void)
- {
- emit_error = 1;
- }
- static void
- i386_emit_rsh_signed (void)
- {
- emit_error = 1;
- }
- static void
- i386_emit_rsh_unsigned (void)
- {
- emit_error = 1;
- }
- static void
- i386_emit_ext (int arg)
- {
- switch (arg)
- {
- case 8:
- EMIT_ASM32 (i386_ext_8,
- "cbtw\n\t"
- "cwtl\n\t"
- "movl %eax,%ebx\n\t"
- "sarl $31,%ebx");
- break;
- case 16:
- EMIT_ASM32 (i386_ext_16,
- "cwtl\n\t"
- "movl %eax,%ebx\n\t"
- "sarl $31,%ebx");
- break;
- case 32:
- EMIT_ASM32 (i386_ext_32,
- "movl %eax,%ebx\n\t"
- "sarl $31,%ebx");
- break;
- default:
- emit_error = 1;
- }
- }
- static void
- i386_emit_log_not (void)
- {
- EMIT_ASM32 (i386_log_not,
- "or %ebx,%eax\n\t"
- "test %eax,%eax\n\t"
- "sete %cl\n\t"
- "xor %ebx,%ebx\n\t"
- "movzbl %cl,%eax");
- }
- static void
- i386_emit_bit_and (void)
- {
- EMIT_ASM32 (i386_and,
- "and (%esp),%eax\n\t"
- "and 0x4(%esp),%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_bit_or (void)
- {
- EMIT_ASM32 (i386_or,
- "or (%esp),%eax\n\t"
- "or 0x4(%esp),%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_bit_xor (void)
- {
- EMIT_ASM32 (i386_xor,
- "xor (%esp),%eax\n\t"
- "xor 0x4(%esp),%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_bit_not (void)
- {
- EMIT_ASM32 (i386_bit_not,
- "xor $0xffffffff,%eax\n\t"
- "xor $0xffffffff,%ebx\n\t");
- }
- static void
- i386_emit_equal (void)
- {
- EMIT_ASM32 (i386_equal,
- "cmpl %ebx,4(%esp)\n\t"
- "jne .Li386_equal_false\n\t"
- "cmpl %eax,(%esp)\n\t"
- "je .Li386_equal_true\n\t"
- ".Li386_equal_false:\n\t"
- "xor %eax,%eax\n\t"
- "jmp .Li386_equal_end\n\t"
- ".Li386_equal_true:\n\t"
- "mov $1,%eax\n\t"
- ".Li386_equal_end:\n\t"
- "xor %ebx,%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_less_signed (void)
- {
- EMIT_ASM32 (i386_less_signed,
- "cmpl %ebx,4(%esp)\n\t"
- "jl .Li386_less_signed_true\n\t"
- "jne .Li386_less_signed_false\n\t"
- "cmpl %eax,(%esp)\n\t"
- "jl .Li386_less_signed_true\n\t"
- ".Li386_less_signed_false:\n\t"
- "xor %eax,%eax\n\t"
- "jmp .Li386_less_signed_end\n\t"
- ".Li386_less_signed_true:\n\t"
- "mov $1,%eax\n\t"
- ".Li386_less_signed_end:\n\t"
- "xor %ebx,%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_less_unsigned (void)
- {
- EMIT_ASM32 (i386_less_unsigned,
- "cmpl %ebx,4(%esp)\n\t"
- "jb .Li386_less_unsigned_true\n\t"
- "jne .Li386_less_unsigned_false\n\t"
- "cmpl %eax,(%esp)\n\t"
- "jb .Li386_less_unsigned_true\n\t"
- ".Li386_less_unsigned_false:\n\t"
- "xor %eax,%eax\n\t"
- "jmp .Li386_less_unsigned_end\n\t"
- ".Li386_less_unsigned_true:\n\t"
- "mov $1,%eax\n\t"
- ".Li386_less_unsigned_end:\n\t"
- "xor %ebx,%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_ref (int size)
- {
- switch (size)
- {
- case 1:
- EMIT_ASM32 (i386_ref1,
- "movb (%eax),%al");
- break;
- case 2:
- EMIT_ASM32 (i386_ref2,
- "movw (%eax),%ax");
- break;
- case 4:
- EMIT_ASM32 (i386_ref4,
- "movl (%eax),%eax");
- break;
- case 8:
- EMIT_ASM32 (i386_ref8,
- "movl 4(%eax),%ebx\n\t"
- "movl (%eax),%eax");
- break;
- }
- }
- static void
- i386_emit_if_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (i386_if_goto,
- "mov %eax,%ecx\n\t"
- "or %ebx,%ecx\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
- "cmpl $0,%ecx\n\t"
-
- ".byte 0x0f, 0x85, 0x0, 0x0, 0x0, 0x0");
- if (offset_p)
- *offset_p = 11;
- if (size_p)
- *size_p = 4;
- }
- static void
- i386_emit_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (i386_goto,
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0");
- if (offset_p)
- *offset_p = 1;
- if (size_p)
- *size_p = 4;
- }
- static void
- i386_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
- {
- int diff = (to - (from + size));
- unsigned char buf[sizeof (int)];
-
- if (size != 4)
- {
- emit_error = 1;
- return;
- }
- memcpy (buf, &diff, sizeof (int));
- write_inferior_memory (from, buf, sizeof (int));
- }
- static void
- i386_emit_const (LONGEST num)
- {
- unsigned char buf[16];
- int i, hi, lo;
- CORE_ADDR buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xb8;
- lo = num & 0xffffffff;
- memcpy (&buf[i], &lo, sizeof (lo));
- i += 4;
- hi = ((num >> 32) & 0xffffffff);
- if (hi)
- {
- buf[i++] = 0xbb;
- memcpy (&buf[i], &hi, sizeof (hi));
- i += 4;
- }
- else
- {
- buf[i++] = 0x31; buf[i++] = 0xdb;
- }
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- }
- static void
- i386_emit_call (CORE_ADDR fn)
- {
- unsigned char buf[16];
- int i, offset;
- CORE_ADDR buildaddr;
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xe8;
- offset = ((int) fn) - (buildaddr + 5);
- memcpy (buf + 1, &offset, 4);
- append_insns (&buildaddr, 5, buf);
- current_insn_ptr = buildaddr;
- }
- static void
- i386_emit_reg (int reg)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
- EMIT_ASM32 (i386_reg_a,
- "sub $0x8,%esp");
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xb8;
- memcpy (&buf[i], ®, sizeof (reg));
- i += 4;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- EMIT_ASM32 (i386_reg_b,
- "mov %eax,4(%esp)\n\t"
- "mov 8(%ebp),%eax\n\t"
- "mov %eax,(%esp)");
- i386_emit_call (get_raw_reg_func_addr ());
- EMIT_ASM32 (i386_reg_c,
- "xor %ebx,%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_pop (void)
- {
- EMIT_ASM32 (i386_pop,
- "pop %eax\n\t"
- "pop %ebx");
- }
- static void
- i386_emit_stack_flush (void)
- {
- EMIT_ASM32 (i386_stack_flush,
- "push %ebx\n\t"
- "push %eax");
- }
- static void
- i386_emit_zero_ext (int arg)
- {
- switch (arg)
- {
- case 8:
- EMIT_ASM32 (i386_zero_ext_8,
- "and $0xff,%eax\n\t"
- "xor %ebx,%ebx");
- break;
- case 16:
- EMIT_ASM32 (i386_zero_ext_16,
- "and $0xffff,%eax\n\t"
- "xor %ebx,%ebx");
- break;
- case 32:
- EMIT_ASM32 (i386_zero_ext_32,
- "xor %ebx,%ebx");
- break;
- default:
- emit_error = 1;
- }
- }
- static void
- i386_emit_swap (void)
- {
- EMIT_ASM32 (i386_swap,
- "mov %eax,%ecx\n\t"
- "mov %ebx,%edx\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
- "push %edx\n\t"
- "push %ecx");
- }
- static void
- i386_emit_stack_adjust (int n)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0x8d;
- buf[i++] = 0x64;
- buf[i++] = 0x24;
- buf[i++] = n * 8;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- }
- static void
- i386_emit_int_call_1 (CORE_ADDR fn, int arg1)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
- EMIT_ASM32 (i386_int_call_1_a,
-
- "sub $0x8,%esp");
-
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xc7;
- buf[i++] = 0x04;
- buf[i++] = 0x24;
- memcpy (&buf[i], &arg1, sizeof (arg1));
- i += 4;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- i386_emit_call (fn);
- EMIT_ASM32 (i386_int_call_1_c,
- "mov %edx,%ebx\n\t"
- "lea 0x8(%esp),%esp");
- }
- static void
- i386_emit_void_call_2 (CORE_ADDR fn, int arg1)
- {
- unsigned char buf[16];
- int i;
- CORE_ADDR buildaddr;
- EMIT_ASM32 (i386_void_call_2_a,
-
- "push %eax\n\t"
-
- "sub $0x10,%esp\n\t"
-
- "mov %eax,4(%esp)\n\t"
- "mov %ebx,8(%esp)");
-
- buildaddr = current_insn_ptr;
- i = 0;
- buf[i++] = 0xc7;
- buf[i++] = 0x04;
- buf[i++] = 0x24;
- memcpy (&buf[i], &arg1, sizeof (arg1));
- i += 4;
- append_insns (&buildaddr, i, buf);
- current_insn_ptr = buildaddr;
- i386_emit_call (fn);
- EMIT_ASM32 (i386_void_call_2_b,
- "lea 0x10(%esp),%esp\n\t"
-
- "pop %eax");
- }
- void
- i386_emit_eq_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (eq,
-
- "cmpl %eax,(%esp)\n\t"
- "jne .Leq_fallthru\n\t"
- "cmpl %ebx,4(%esp)\n\t"
- "jne .Leq_fallthru\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Leq_fallthru:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx");
- if (offset_p)
- *offset_p = 18;
- if (size_p)
- *size_p = 4;
- }
- void
- i386_emit_ne_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (ne,
-
- "cmpl %eax,(%esp)\n\t"
- "jne .Lne_jump\n\t"
- "cmpl %ebx,4(%esp)\n\t"
- "je .Lne_fallthru\n\t"
- ".Lne_jump:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lne_fallthru:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx");
- if (offset_p)
- *offset_p = 18;
- if (size_p)
- *size_p = 4;
- }
- void
- i386_emit_lt_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (lt,
- "cmpl %ebx,4(%esp)\n\t"
- "jl .Llt_jump\n\t"
- "jne .Llt_fallthru\n\t"
- "cmpl %eax,(%esp)\n\t"
- "jnl .Llt_fallthru\n\t"
- ".Llt_jump:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Llt_fallthru:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx");
- if (offset_p)
- *offset_p = 20;
- if (size_p)
- *size_p = 4;
- }
- void
- i386_emit_le_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (le,
- "cmpl %ebx,4(%esp)\n\t"
- "jle .Lle_jump\n\t"
- "jne .Lle_fallthru\n\t"
- "cmpl %eax,(%esp)\n\t"
- "jnle .Lle_fallthru\n\t"
- ".Lle_jump:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lle_fallthru:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx");
- if (offset_p)
- *offset_p = 20;
- if (size_p)
- *size_p = 4;
- }
- void
- i386_emit_gt_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (gt,
- "cmpl %ebx,4(%esp)\n\t"
- "jg .Lgt_jump\n\t"
- "jne .Lgt_fallthru\n\t"
- "cmpl %eax,(%esp)\n\t"
- "jng .Lgt_fallthru\n\t"
- ".Lgt_jump:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lgt_fallthru:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx");
- if (offset_p)
- *offset_p = 20;
- if (size_p)
- *size_p = 4;
- }
- void
- i386_emit_ge_goto (int *offset_p, int *size_p)
- {
- EMIT_ASM32 (ge,
- "cmpl %ebx,4(%esp)\n\t"
- "jge .Lge_jump\n\t"
- "jne .Lge_fallthru\n\t"
- "cmpl %eax,(%esp)\n\t"
- "jnge .Lge_fallthru\n\t"
- ".Lge_jump:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx\n\t"
-
- ".byte 0xe9, 0x0, 0x0, 0x0, 0x0\n\t"
- ".Lge_fallthru:\n\t"
- "lea 0x8(%esp),%esp\n\t"
- "pop %eax\n\t"
- "pop %ebx");
- if (offset_p)
- *offset_p = 20;
- if (size_p)
- *size_p = 4;
- }
- struct emit_ops i386_emit_ops =
- {
- i386_emit_prologue,
- i386_emit_epilogue,
- i386_emit_add,
- i386_emit_sub,
- i386_emit_mul,
- i386_emit_lsh,
- i386_emit_rsh_signed,
- i386_emit_rsh_unsigned,
- i386_emit_ext,
- i386_emit_log_not,
- i386_emit_bit_and,
- i386_emit_bit_or,
- i386_emit_bit_xor,
- i386_emit_bit_not,
- i386_emit_equal,
- i386_emit_less_signed,
- i386_emit_less_unsigned,
- i386_emit_ref,
- i386_emit_if_goto,
- i386_emit_goto,
- i386_write_goto_address,
- i386_emit_const,
- i386_emit_call,
- i386_emit_reg,
- i386_emit_pop,
- i386_emit_stack_flush,
- i386_emit_zero_ext,
- i386_emit_swap,
- i386_emit_stack_adjust,
- i386_emit_int_call_1,
- i386_emit_void_call_2,
- i386_emit_eq_goto,
- i386_emit_ne_goto,
- i386_emit_lt_goto,
- i386_emit_le_goto,
- i386_emit_gt_goto,
- i386_emit_ge_goto
- };
- static struct emit_ops *
- x86_emit_ops (void)
- {
- #ifdef __x86_64__
- if (is_64bit_tdesc ())
- return &amd64_emit_ops;
- else
- #endif
- return &i386_emit_ops;
- }
- static int
- x86_supports_range_stepping (void)
- {
- return 1;
- }
- struct linux_target_ops the_low_target =
- {
- x86_arch_setup,
- x86_linux_regs_info,
- x86_cannot_fetch_register,
- x86_cannot_store_register,
- NULL,
- x86_get_pc,
- x86_set_pc,
- x86_breakpoint,
- x86_breakpoint_len,
- NULL,
- 1,
- x86_breakpoint_at,
- x86_supports_z_point_type,
- x86_insert_point,
- x86_remove_point,
- x86_stopped_by_watchpoint,
- x86_stopped_data_address,
-
- NULL,
- NULL,
-
- x86_siginfo_fixup,
- x86_linux_new_process,
- x86_linux_new_thread,
- x86_linux_prepare_to_resume,
- x86_linux_process_qsupported,
- x86_supports_tracepoints,
- x86_get_thread_area,
- x86_install_fast_tracepoint_jump_pad,
- x86_emit_ops,
- x86_get_min_fast_tracepoint_insn_len,
- x86_supports_range_stepping,
- };
- void
- initialize_low_arch (void)
- {
-
- #ifdef __x86_64__
- init_registers_amd64_linux ();
- init_registers_amd64_avx_linux ();
- init_registers_amd64_avx512_linux ();
- init_registers_amd64_mpx_linux ();
- init_registers_x32_linux ();
- init_registers_x32_avx_linux ();
- init_registers_x32_avx512_linux ();
- tdesc_amd64_linux_no_xml = xmalloc (sizeof (struct target_desc));
- copy_target_description (tdesc_amd64_linux_no_xml, tdesc_amd64_linux);
- tdesc_amd64_linux_no_xml->xmltarget = xmltarget_amd64_linux_no_xml;
- #endif
- init_registers_i386_linux ();
- init_registers_i386_mmx_linux ();
- init_registers_i386_avx_linux ();
- init_registers_i386_avx512_linux ();
- init_registers_i386_mpx_linux ();
- tdesc_i386_linux_no_xml = xmalloc (sizeof (struct target_desc));
- copy_target_description (tdesc_i386_linux_no_xml, tdesc_i386_linux);
- tdesc_i386_linux_no_xml->xmltarget = xmltarget_i386_linux_no_xml;
- initialize_regsets_info (&x86_regsets_info);
- }