* Check in Fred Fish's changes in these modules. Fred
[deliverable/binutils-gdb.git] / gdb / rs6000-xdep.c
1 /* IBM RS/6000 host-dependent code for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1989, 1991 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
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include <stdio.h>
21 #include "defs.h"
22 #include "frame.h"
23 #include "inferior.h"
24 #include "symtab.h"
25 #include "target.h"
26
27 #include <sys/param.h>
28 #include <sys/dir.h>
29 #include <sys/user.h>
30 #include <signal.h>
31 #include <sys/ioctl.h>
32 #include <fcntl.h>
33
34 #include <sys/ptrace.h>
35 #include <sys/reg.h>
36
37 #include <a.out.h>
38 #include <sys/file.h>
39 #include <sys/stat.h>
40 #include <sys/core.h>
41 #include <sys/ldr.h>
42
43 extern int errno;
44 extern int attach_flag;
45
46 /* Conversion from gdb-to-system special purpose register numbers.. */
47
48 static int special_regs[] = {
49 IAR, /* PC_REGNUM */
50 MSR, /* PS_REGNUM */
51 CR, /* CR_REGNUM */
52 LR, /* LR_REGNUM */
53 CTR, /* CTR_REGNUM */
54 XER, /* XER_REGNUM */
55 MQ /* MQ_REGNUM */
56 };
57
58
59 /* Nonzero if we just simulated a single step break. */
60 extern int one_stepped;
61
62 \f
63 fetch_inferior_registers (regno)
64 int regno;
65 {
66 int ii;
67 extern char registers[];
68
69 /* read 32 general purpose registers. */
70
71 for (ii=0; ii < 32; ++ii)
72 *(int*)&registers[REGISTER_BYTE (ii)] =
73 ptrace (PT_READ_GPR, inferior_pid, ii, 0, 0);
74
75 /* read general purpose floating point registers. */
76
77 for (ii=0; ii < 32; ++ii)
78 ptrace (PT_READ_FPR, inferior_pid,
79 (int*)&registers [REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0);
80
81 /* read special registers. */
82 for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
83 *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] =
84 ptrace (PT_READ_GPR, inferior_pid, special_regs[ii], 0, 0);
85 }
86
87 /* Store our register values back into the inferior.
88 If REGNO is -1, do this for all registers.
89 Otherwise, REGNO specifies which register (so we can save time). */
90
91 void
92 store_inferior_registers (regno)
93 int regno;
94 {
95 extern char registers[];
96
97 errno = 0;
98
99 if (regno == -1) { /* for all registers.. */
100 int ii;
101
102 /* execute one dummy instruction (which is a breakpoint) in inferior
103 process. So give kernel a chance to do internal house keeping.
104 Otherwise the following ptrace(2) calls will mess up user stack
105 since kernel will get confused about the bottom of the stack (%sp) */
106
107 exec_one_dummy_insn ();
108
109 /* write general purpose registers first! */
110 for ( ii=GPR0; ii<=GPR31; ++ii) {
111 ptrace (PT_WRITE_GPR, inferior_pid, ii,
112 *(int*)&registers[REGISTER_BYTE (ii)], 0);
113 if ( errno ) {
114 perror ("ptrace write_gpr"); errno = 0;
115 }
116 }
117
118 /* write floating point registers now. */
119 for ( ii=0; ii < 32; ++ii) {
120 ptrace (PT_WRITE_FPR, inferior_pid,
121 (int*)&registers[REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0);
122 if ( errno ) {
123 perror ("ptrace write_fpr"); errno = 0;
124 }
125 }
126
127 /* write special registers. */
128 for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) {
129 ptrace (PT_WRITE_GPR, inferior_pid, special_regs[ii],
130 *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
131 if ( errno ) {
132 perror ("ptrace write_gpr"); errno = 0;
133 }
134 }
135 }
136
137 /* else, a specific register number is given... */
138
139 else if (regno < FP0_REGNUM) { /* a GPR */
140
141 ptrace (PT_WRITE_GPR, inferior_pid, regno,
142 *(int*)&registers[REGISTER_BYTE (regno)], 0);
143 }
144
145 else if (regno <= FPLAST_REGNUM) { /* a FPR */
146 ptrace (PT_WRITE_FPR, inferior_pid,
147 (int*)&registers[REGISTER_BYTE (regno)], regno-FP0_REGNUM+FPR0, 0);
148 }
149
150 else if (regno <= LAST_SP_REGNUM) { /* a special register */
151
152 ptrace (PT_WRITE_GPR, inferior_pid, special_regs [regno-FIRST_SP_REGNUM],
153 *(int*)&registers[REGISTER_BYTE (regno)], 0);
154 }
155
156 else
157 fprintf (stderr, "Gdb error: register no %d not implemented.\n", regno);
158
159 if ( errno ) {
160 perror ("ptrace write"); errno = 0;
161 }
162 }
163
164 void
165 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
166 char *core_reg_sect;
167 unsigned core_reg_size;
168 int which;
169 unsigned int reg_addr; /* Unused in this version */
170 {
171 /* fetch GPRs and special registers from the first register section
172 in core bfd. */
173 if (which == 0) {
174
175 /* copy GPRs first. */
176 bcopy (core_reg_sect, registers, 32 * 4);
177
178 /* gdb's internal register template and bfd's register section layout
179 should share a common include file. FIXMEmgo */
180 /* then comes special registes. They are supposed to be in the same
181 order in gdb template and bfd `.reg' section. */
182 core_reg_sect += (32 * 4);
183 bcopy (core_reg_sect, &registers [REGISTER_BYTE (FIRST_SP_REGNUM)],
184 (LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4);
185 }
186
187 /* fetch floating point registers from register section 2 in core bfd. */
188 else if (which == 2)
189 bcopy (core_reg_sect, &registers [REGISTER_BYTE (FP0_REGNUM)], 32 * 8);
190
191 else
192 fprintf (stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");
193 }
194
195
196 frameless_function_invocation (fi)
197 struct frame_info *fi;
198 {
199 int ret;
200 CORE_ADDR func_start, after_prologue;
201
202 #if 0
203 func_start = (LOAD_ADDR (get_pc_function_start (fi->pc)) +
204 FUNCTION_START_OFFSET);
205 #else
206 func_start = get_pc_function_start (fi->pc) + FUNCTION_START_OFFSET;
207 #endif
208 if (func_start)
209 {
210 after_prologue = func_start;
211 SKIP_PROLOGUE (after_prologue);
212 ret = (after_prologue == func_start);
213 }
214 else
215 /* If we can't find the start of the function, we don't really */
216 /* know whether the function is frameless, but we should be */
217 /* able to get a reasonable (i.e. best we can do under the */
218 /* circumstances) backtrace by saying that it isn't. */
219 ret = 0;
220
221 return ret;
222
223 }
224
225
226 /* aixcoff_relocate_symtab - hook for symbol table relocation.
227 also reads shared libraries.. */
228
229 aixcoff_relocate_symtab (pid)
230 unsigned int pid;
231 {
232 #define MAX_LOAD_SEGS 64 /* maximum number of load segments */
233
234 struct ld_info *ldi;
235 int temp;
236
237 ldi = (void *) alloca(MAX_LOAD_SEGS * sizeof (*ldi));
238
239 /* According to my humble theory, aixcoff has some timing problems and
240 when the user stack grows, kernel doesn't update stack info in time
241 and ptrace calls step on user stack. That is why we sleep here a little,
242 and give kernel to update its internals. */
243
244 usleep (36000);
245
246 errno = 0;
247 ptrace(PT_LDINFO, pid, ldi, MAX_LOAD_SEGS * sizeof(*ldi), ldi);
248 if (errno)
249 perror_with_name ("ptrace ldinfo");
250
251 vmap_ldinfo(ldi);
252
253 do {
254 add_text_to_loadinfo (ldi->ldinfo_textorg, ldi->ldinfo_dataorg);
255 } while (ldi->ldinfo_next
256 && (ldi = (void *) (ldi->ldinfo_next + (char *) ldi)));
257
258 /* Now that we've jumbled things around, re-sort them. */
259 sort_minimal_symbols ();
260
261 /* relocate the exec and core sections as well. */
262 vmap_exec ();
263 }
264
265
266 /* Keep an array of load segment information and their TOC table addresses.
267 This info will be useful when calling a shared library function by hand. */
268
269 typedef struct {
270 unsigned long textorg, dataorg, toc_offset;
271 } LoadInfo;
272
273 #define LOADINFOLEN 10
274
275 static LoadInfo *loadInfo = NULL;
276 static int loadInfoLen = 0;
277 static int loadInfoTocIndex = 0;
278 static int loadInfoTextIndex = 0;
279
280
281 xcoff_init_loadinfo ()
282 {
283 loadInfoTocIndex = 0;
284 loadInfoTextIndex = 0;
285
286 if (loadInfoLen == 0) {
287 loadInfo = (void*) xmalloc (sizeof (LoadInfo) * LOADINFOLEN);
288 loadInfoLen = LOADINFOLEN;
289 }
290 }
291
292
293 free_loadinfo ()
294 {
295 if (loadInfo)
296 free (loadInfo);
297 loadInfo = NULL;
298 loadInfoLen = 0;
299 loadInfoTocIndex = 0;
300 loadInfoTextIndex = 0;
301 }
302
303
304 xcoff_add_toc_to_loadinfo (unsigned long tocaddr)
305 {
306 while (loadInfoTocIndex >= loadInfoLen) {
307 loadInfoLen += LOADINFOLEN;
308 loadInfo = (void*) xrealloc (loadInfo, sizeof(LoadInfo) * loadInfoLen);
309 }
310 loadInfo [loadInfoTocIndex++].toc_offset = tocaddr;
311 }
312
313
314 add_text_to_loadinfo (unsigned long textaddr, unsigned long dataaddr)
315 {
316 while (loadInfoTextIndex >= loadInfoLen) {
317 loadInfoLen += LOADINFOLEN;
318 loadInfo = (void*) xrealloc (loadInfo, sizeof(LoadInfo) * loadInfoLen);
319 }
320 loadInfo [loadInfoTextIndex].textorg = textaddr;
321 loadInfo [loadInfoTextIndex].dataorg = dataaddr;
322 ++loadInfoTextIndex;
323 }
324
325
326 unsigned long
327 find_toc_address (unsigned long pc)
328 {
329 int ii, toc_entry;
330
331 for (ii=0; ii < loadInfoTextIndex; ++ii)
332 if (pc > loadInfo [ii].textorg)
333 toc_entry = ii;
334
335 return loadInfo [toc_entry].dataorg + loadInfo [toc_entry].toc_offset;
336 }
337
338
339 /* execute one dummy breakpoint instruction. This way we give kernel
340 a chance to do some housekeeping and update inferior's internal data,
341 including u_area. */
342
343 exec_one_dummy_insn ()
344 {
345 #define DUMMY_INSN_ADDR 0x10000200
346
347 unsigned long shadow;
348 unsigned int status, pid;
349
350 target_insert_breakpoint (DUMMY_INSN_ADDR, &shadow);
351
352 errno = 0;
353 ptrace (PT_CONTINUE, inferior_pid, DUMMY_INSN_ADDR, 0, 0);
354 if (errno)
355 perror ("pt_continue");
356
357 do {
358 pid = wait (&status);
359 } while (pid != inferior_pid);
360
361 target_remove_breakpoint (DUMMY_INSN_ADDR, &shadow);
362 }
363
This page took 0.037902 seconds and 5 git commands to generate.