/* Native-dependent code for ptx 4.0 Copyright 1988, 1989, 1991, 1992, 1994, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GDB. 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 of the License, 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 "defs.h" #include "inferior.h" #include "gdbcore.h" #include "regcache.h" #include <sys/procfs.h> #include <sys/ptrace.h> #include <sys/param.h> #include <fcntl.h> /* Prototypes for supply_gregset etc. */ #include "gregset.h" /* Given a pointer to a general register set in /proc format (gregset_t *), unpack the register contents and supply them as gdb's idea of the current register values. */ void supply_gregset (gregset_t *gregsetp) { supply_register (EAX_REGNUM, (char *) &(*gregsetp)[EAX]); supply_register (EDX_REGNUM, (char *) &(*gregsetp)[EDX]); supply_register (ECX_REGNUM, (char *) &(*gregsetp)[ECX]); supply_register (EBX_REGNUM, (char *) &(*gregsetp)[EBX]); supply_register (ESI_REGNUM, (char *) &(*gregsetp)[ESI]); supply_register (EDI_REGNUM, (char *) &(*gregsetp)[EDI]); supply_register (ESP_REGNUM, (char *) &(*gregsetp)[UESP]); supply_register (EBP_REGNUM, (char *) &(*gregsetp)[EBP]); supply_register (EIP_REGNUM, (char *) &(*gregsetp)[EIP]); supply_register (EFLAGS_REGNUM, (char *) &(*gregsetp)[EFL]); } void fill_gregset (gregset_t *gregsetp, int regno) { int regi; for (regi = 0; regi < NUM_REGS; regi++) { if ((regno == -1) || (regno == regi)) { (*gregsetp)[regi] = *(greg_t *) & registers[REGISTER_BYTE (regi)]; } } } /* Given a pointer to a floating point register set in /proc format (fpregset_t *), unpack the register contents and supply them as gdb's idea of the current floating point register values. */ void supply_fpregset (fpregset_t *fpregsetp) { supply_fpu_registers ((struct fpusave *) &fpregsetp->fp_reg_set); supply_fpa_registers ((struct fpasave *) &fpregsetp->f_wregs); } /* Given a pointer to a floating point register set in /proc format (fpregset_t *), update the register specified by REGNO from gdb's idea of the current floating point register set. If REGNO is -1, update them all. */ void fill_fpregset (fpregset_t *fpregsetp, int regno) { int regi; char *to; char *from; /* FIXME: see m68k-tdep.c for an example, for the m68k. */ } /* * This doesn't quite do the same thing as the procfs.c version, but give * it the same name so we don't have to put an ifdef in solib.c. */ /* this could use elf_interpreter() from elfread.c */ int proc_iterate_over_mappings (int (*func) (int, CORE_ADDR)) { vaddr_t curseg, memptr; pt_vseg_t pv; int rv, cmperr; sec_ptr interp_sec; char *interp_content; int interp_fd, funcstat; unsigned int size; char buf1[NBPG], buf2[NBPG]; /* * The following is really vile. We can get the name of the * shared library from the exec_bfd, and we can get a list of * each virtual memory segment, but there is no simple way to * find the mapped segment from the shared library (ala * procfs's PIOCOPENMEM). As a pretty nasty kludge, we * compare the virtual memory segment to the contents of the * .interp file. If they match, we assume that we've got the * right one. */ /* * TODO: for attach, use XPT_OPENT to get the executable, in * case we're attached without knowning the executable's * filename. */ #ifdef VERBOSE_DEBUG printf ("proc_iter\n"); #endif interp_sec = bfd_get_section_by_name (exec_bfd, ".interp"); if (!interp_sec) { return 0; } size = bfd_section_size (exec_bfd, interp_sec); interp_content = alloca (size); if (0 == bfd_get_section_contents (exec_bfd, interp_sec, interp_content, (file_ptr) 0, size)) { return 0; } #ifdef VERBOSE_DEBUG printf ("proc_iter: \"%s\"\n", interp_content); #endif interp_fd = open (interp_content, O_RDONLY, 0); if (-1 == interp_fd) { return 0; } curseg = 0; while (1) { rv = ptrace (PT_NEXT_VSEG, PIDGET (inferior_ptid), &pv, curseg); #ifdef VERBOSE_DEBUG printf ("PT_NEXT_VSEG: rv %d errno %d\n", rv, errno); #endif if (-1 == rv) break; if (0 == rv) break; #ifdef VERBOSE_DEBUG printf ("pv.pv_start 0x%x pv_size 0x%x pv_prot 0x%x\n", pv.pv_start, pv.pv_size, pv.pv_prot); #endif curseg = pv.pv_start + pv.pv_size; rv = lseek (interp_fd, 0, SEEK_SET); if (-1 == rv) { perror ("lseek"); close (interp_fd); return 0; } for (memptr = pv.pv_start; memptr < pv.pv_start + pv.pv_size; memptr += NBPG) { #ifdef VERBOSE_DEBUG printf ("memptr 0x%x\n", memptr); #endif rv = read (interp_fd, buf1, NBPG); if (-1 == rv) { perror ("read"); close (interp_fd); return 0; } rv = ptrace (PT_RDATA_PAGE, PIDGET (inferior_ptid), buf2, memptr); if (-1 == rv) { perror ("ptrace"); close (interp_fd); return 0; } cmperr = memcmp (buf1, buf2, NBPG); if (cmperr) break; } if (0 == cmperr) { /* this is it */ funcstat = (*func) (interp_fd, pv.pv_start); break; } } close (interp_fd); return 0; }