]>
Commit | Line | Data |
---|---|---|
59144a81 JK |
1 | /* Native-dependent code for ptx 4.0 |
2 | Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
6c9638b4 | 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
59144a81 JK |
19 | |
20 | #include "defs.h" | |
21 | #include "inferior.h" | |
22 | #include "gdbcore.h" | |
23 | #include <sys/procfs.h> | |
24 | #include <sys/ptrace.h> | |
25 | #include <sys/param.h> | |
26 | #include <fcntl.h> | |
27 | ||
28 | /* Given a pointer to a general register set in /proc format (gregset_t *), | |
29 | unpack the register contents and supply them as gdb's idea of the current | |
30 | register values. */ | |
31 | ||
32 | void | |
33 | supply_gregset (gregsetp) | |
34 | gregset_t *gregsetp; | |
35 | { | |
36 | supply_register(EAX_REGNUM, (char *)&(*gregsetp)[EAX]); | |
37 | supply_register(EDX_REGNUM, (char *)&(*gregsetp)[EDX]); | |
38 | supply_register(ECX_REGNUM, (char *)&(*gregsetp)[ECX]); | |
39 | supply_register(EBX_REGNUM, (char *)&(*gregsetp)[EBX]); | |
40 | supply_register(ESI_REGNUM, (char *)&(*gregsetp)[ESI]); | |
41 | supply_register(EDI_REGNUM, (char *)&(*gregsetp)[EDI]); | |
42 | supply_register(ESP_REGNUM, (char *)&(*gregsetp)[UESP]); | |
43 | supply_register(EBP_REGNUM, (char *)&(*gregsetp)[EBP]); | |
44 | supply_register(EIP_REGNUM, (char *)&(*gregsetp)[EIP]); | |
45 | supply_register(EFLAGS_REGNUM, (char *)&(*gregsetp)[EFL]); | |
46 | } | |
47 | ||
48 | void | |
49 | fill_gregset (gregsetp, regno) | |
50 | gregset_t *gregsetp; | |
51 | int regno; | |
52 | { | |
53 | int regi; | |
54 | extern char registers[]; | |
55 | ||
56 | for (regi = 0 ; regi < NUM_REGS ; regi++) | |
57 | { | |
58 | if ((regno == -1) || (regno == regi)) | |
59 | { | |
60 | (*gregsetp)[regi] = *(greg_t *)®isters[REGISTER_BYTE (regi)]; | |
61 | } | |
62 | } | |
63 | } | |
64 | ||
65 | #if defined (FP0_REGNUM) | |
66 | ||
67 | /* Given a pointer to a floating point register set in /proc format | |
68 | (fpregset_t *), unpack the register contents and supply them as gdb's | |
69 | idea of the current floating point register values. */ | |
70 | ||
71 | void | |
72 | supply_fpregset (fpregsetp) | |
73 | fpregset_t *fpregsetp; | |
74 | { | |
75 | supply_fpu_registers((struct fpusave *)&fpregsetp->fp_reg_set); | |
76 | supply_fpa_registers((struct fpasave *)&fpregsetp->f_wregs); | |
77 | } | |
78 | ||
79 | /* Given a pointer to a floating point register set in /proc format | |
80 | (fpregset_t *), update the register specified by REGNO from gdb's idea | |
81 | of the current floating point register set. If REGNO is -1, update | |
82 | them all. */ | |
83 | ||
84 | void | |
85 | fill_fpregset (fpregsetp, regno) | |
86 | fpregset_t *fpregsetp; | |
87 | int regno; | |
88 | { | |
89 | int regi; | |
90 | char *to; | |
91 | char *from; | |
92 | extern char registers[]; | |
93 | ||
94 | /* FIXME: see m68k-tdep.c for an example, for the m68k. */ | |
95 | } | |
96 | ||
97 | #endif /* defined (FP0_REGNUM) */ | |
98 | ||
99 | /* | |
100 | * This doesn't quite do the same thing as the procfs.c version, but give | |
101 | * it the same name so we don't have to put an ifdef in solib.c. | |
102 | */ | |
103 | /* this could use elf_interpreter() from elfread.c */ | |
104 | int | |
105 | proc_iterate_over_mappings(func) | |
106 | int (*func) PARAMS ((int, CORE_ADDR)); | |
107 | { | |
108 | vaddr_t curseg, memptr; | |
109 | pt_vseg_t pv; | |
110 | int rv, cmperr; | |
111 | sec_ptr interp_sec; | |
112 | char *interp_content; | |
113 | int interp_fd, funcstat; | |
114 | unsigned int size; | |
115 | char buf1[NBPG], buf2[NBPG]; | |
116 | ||
117 | /* | |
118 | * The following is really vile. We can get the name of the | |
119 | * shared library from the exec_bfd, and we can get a list of | |
120 | * each virtual memory segment, but there is no simple way to | |
121 | * find the mapped segment from the shared library (ala | |
122 | * procfs's PIOCOPENMEM). As a pretty nasty kludge, we | |
123 | * compare the virtual memory segment to the contents of the | |
124 | * .interp file. If they match, we assume that we've got the | |
125 | * right one. | |
126 | */ | |
127 | ||
128 | /* | |
129 | * TODO: for attach, use XPT_OPENT to get the executable, in | |
130 | * case we're attached without knowning the executable's | |
131 | * filename. | |
132 | */ | |
133 | ||
134 | #ifdef VERBOSE_DEBUG | |
135 | printf("proc_iter\n"); | |
136 | #endif | |
137 | interp_sec = bfd_get_section_by_name(exec_bfd, ".interp"); | |
138 | if (!interp_sec) { | |
139 | return 0; | |
140 | } | |
141 | ||
142 | size = bfd_section_size(exec_bfd, interp_sec); | |
143 | interp_content = alloca(size); | |
144 | if (0 == bfd_get_section_contents(exec_bfd, interp_sec, | |
145 | interp_content, (file_ptr)0, size)) { | |
146 | return 0; | |
147 | } | |
148 | ||
149 | #ifdef VERBOSE_DEBUG | |
150 | printf("proc_iter: \"%s\"\n", interp_content); | |
151 | #endif | |
152 | interp_fd = open(interp_content, O_RDONLY, 0); | |
153 | if (-1 == interp_fd) { | |
154 | return 0; | |
155 | } | |
156 | ||
157 | curseg = 0; | |
158 | while (1) { | |
159 | rv = ptrace(PT_NEXT_VSEG, inferior_pid, &pv, curseg); | |
160 | #ifdef VERBOSE_DEBUG | |
161 | printf("PT_NEXT_VSEG: rv %d errno %d\n", rv, errno); | |
162 | #endif | |
163 | if (-1 == rv) | |
164 | break; | |
165 | if (0 == rv) | |
166 | break; | |
167 | #ifdef VERBOSE_DEBUG | |
168 | printf("pv.pv_start 0x%x pv_size 0x%x pv_prot 0x%x\n", | |
169 | pv.pv_start, pv.pv_size, pv.pv_prot); | |
170 | #endif | |
171 | curseg = pv.pv_start + pv.pv_size; | |
172 | ||
173 | rv = lseek(interp_fd, 0, SEEK_SET); | |
174 | if (-1 == rv) { | |
175 | perror("lseek"); | |
176 | close(interp_fd); | |
177 | return 0; | |
178 | } | |
179 | for (memptr = pv.pv_start; memptr < pv.pv_start + pv.pv_size; | |
180 | memptr += NBPG) { | |
181 | #ifdef VERBOSE_DEBUG | |
182 | printf("memptr 0x%x\n", memptr); | |
183 | #endif | |
184 | rv = read(interp_fd, buf1, NBPG); | |
185 | if (-1 == rv) { | |
186 | perror("read"); | |
187 | close(interp_fd); | |
188 | return 0; | |
189 | } | |
190 | rv = ptrace(PT_RDATA_PAGE, inferior_pid, buf2, | |
191 | memptr); | |
192 | if (-1 == rv) { | |
193 | perror("ptrace"); | |
194 | close(interp_fd); | |
195 | return 0; | |
196 | } | |
197 | cmperr = memcmp(buf1, buf2, NBPG); | |
198 | if (cmperr) | |
199 | break; | |
200 | } | |
201 | if (0 == cmperr) { | |
202 | /* this is it */ | |
203 | funcstat = (*func)(interp_fd, pv.pv_start); | |
204 | break; | |
205 | } | |
206 | } | |
207 | close(interp_fd); | |
208 | return 0; | |
209 | } |