summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/gdb/ptx4-nat.c
blob: 564b79917284368af6feda120d2fdabbccf25271 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* Native-dependent code for ptx 4.0
   Copyright 1988, 1989, 1991, 1992 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 <sys/procfs.h>
#include <sys/ptrace.h>
#include <sys/param.h>
#include <fcntl.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 (gregsetp)
     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 (gregsetp, regno)
     gregset_t *gregsetp;
     int regno;
{
  int regi;
  extern char registers[];

  for (regi = 0 ; regi < NUM_REGS ; regi++)
    {
      if ((regno == -1) || (regno == regi))
	{
	  (*gregsetp)[regi] = *(greg_t *)&registers[REGISTER_BYTE (regi)];
	}
    }
}

#if defined (FP0_REGNUM)

/*  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 (fpregsetp)
     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 (fpregsetp, regno)
     fpregset_t *fpregsetp;
     int regno;
{
  int regi;
  char *to;
  char *from;
  extern char registers[];

  /* FIXME: see m68k-tdep.c for an example, for the m68k. */
}

#endif	/* defined (FP0_REGNUM) */

/*
 * 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(func)
	int (*func) PARAMS ((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, inferior_pid, &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, inferior_pid, 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;
}