Moved the position of the #### lines so that the makefile fragments
[deliverable/binutils-gdb.git] / gdb / rs6000-xdep.c
CommitLineData
41abdfbd
JG
1/* IBM RS/6000 host-dependent code for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include <stdio.h>
21#include "defs.h"
41abdfbd
JG
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
43extern int errno;
44extern int attach_flag;
45
46/* Conversion from gdb-to-system special purpose register numbers.. */
47
48static 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. */
60extern int one_stepped;
61
62\f
63fetch_inferior_registers ()
64{
65 int ii;
66 extern char registers[];
67
68 /* read 32 general purpose registers. */
69
70 for (ii=0; ii < 32; ++ii)
71 *(int*)&registers[REGISTER_BYTE (ii)] =
72 ptrace (PT_READ_GPR, inferior_pid, ii, 0, 0);
73
74 /* read general purpose floating point registers. */
75
76 for (ii=0; ii < 32; ++ii)
77 ptrace (PT_READ_FPR, inferior_pid,
78 (int*)&registers [REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0);
79
80 /* read special registers. */
81 for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
82 *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] =
83 ptrace (PT_READ_GPR, inferior_pid, special_regs[ii], 0, 0);
84}
85
86/* Store our register values back into the inferior.
87 If REGNO is -1, do this for all registers.
88 Otherwise, REGNO specifies which register (so we can save time). */
89
90store_inferior_registers (regno)
91 int regno;
92{
93 extern char registers[];
94
95 errno = 0;
96
97 if (regno == -1) { /* for all registers.. */
98 int ii;
99
100 /* execute one dummy instruction (which is a breakpoint) in inferior
101 process. So give kernel a chance to do internal house keeping.
102 Otherwise the following ptrace(2) calls will mess up user stack
103 since kernel will get confused about the bottom of the stack (%sp) */
104
105 exec_one_dummy_insn ();
106
107 /* write general purpose registers first! */
108 for ( ii=GPR0; ii<=GPR31; ++ii) {
109 ptrace (PT_WRITE_GPR, inferior_pid, ii,
110 *(int*)&registers[REGISTER_BYTE (ii)], 0);
111 if ( errno ) {
112 perror ("ptrace write_gpr"); errno = 0;
113 }
114 }
115
116 /* write floating point registers now. */
117 for ( ii=0; ii < 32; ++ii) {
118 ptrace (PT_WRITE_FPR, inferior_pid,
119 (int*)&registers[REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0);
120 if ( errno ) {
121 perror ("ptrace write_fpr"); errno = 0;
122 }
123 }
124
125 /* write special registers. */
126 for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) {
127 ptrace (PT_WRITE_GPR, inferior_pid, special_regs[ii],
128 *(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
129 if ( errno ) {
130 perror ("ptrace write_gpr"); errno = 0;
131 }
132 }
133 }
134
135 /* else, a specific register number is given... */
136
137 else if (regno < FP0_REGNUM) { /* a GPR */
138
139 ptrace (PT_WRITE_GPR, inferior_pid, regno,
140 *(int*)&registers[REGISTER_BYTE (regno)], 0);
141 }
142
143 else if (regno <= FPLAST_REGNUM) { /* a FPR */
144 ptrace (PT_WRITE_FPR, inferior_pid,
145 (int*)&registers[REGISTER_BYTE (regno)], regno-FP0_REGNUM+FPR0, 0);
146 }
147
148 else if (regno <= LAST_SP_REGNUM) { /* a special register */
149
150 ptrace (PT_WRITE_GPR, inferior_pid, special_regs [regno-FIRST_SP_REGNUM],
151 *(int*)&registers[REGISTER_BYTE (regno)], 0);
152 }
153
154 else
155 fprintf (stderr, "Gdb error: register no %d not implemented.\n", regno);
156
157 if ( errno ) {
158 perror ("ptrace write"); errno = 0;
159 return -1;
160 }
161 return 0;
162}
163
164void
165fetch_core_registers (core_reg_sect, core_reg_size, which)
166 char *core_reg_sect;
167 unsigned core_reg_size;
168 int which;
169{
170 /* fetch GPRs and special registers from the first register section
171 in core bfd. */
172 if (which == 0) {
173
174 /* copy GPRs first. */
175 bcopy (core_reg_sect, registers, 32 * 4);
176
177 /* gdb's internal register template and bfd's register section layout
178 should share a common include file. FIXMEmgo */
179 /* then comes special registes. They are supposed to be in the same
180 order in gdb template and bfd `.reg' section. */
181 core_reg_sect += (32 * 4);
182 bcopy (core_reg_sect, &registers [REGISTER_BYTE (FIRST_SP_REGNUM)],
183 (LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4);
184 }
185
186 /* fetch floating point registers from register section 2 in core bfd. */
187 else if (which == 2)
188 bcopy (core_reg_sect, &registers [REGISTER_BYTE (FP0_REGNUM)], 32 * 8);
189
190 else
191 fprintf (stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");
192}
193
194
195frameless_function_invocation (fi)
196struct frame_info *fi;
197{
198 int ret;
199 CORE_ADDR func_start, after_prologue;
200
201#if 0
202 func_start = (LOAD_ADDR (get_pc_function_start (fi->pc)) +
203 FUNCTION_START_OFFSET);
204#else
205 func_start = get_pc_function_start (fi->pc) + FUNCTION_START_OFFSET;
206#endif
207 if (func_start)
208 {
209 after_prologue = func_start;
210 SKIP_PROLOGUE (after_prologue);
211 ret = (after_prologue == func_start);
212 }
213 else
214 /* If we can't find the start of the function, we don't really */
215 /* know whether the function is frameless, but we should be */
216 /* able to get a reasonable (i.e. best we can do under the */
217 /* circumstances) backtrace by saying that it isn't. */
218 ret = 0;
219
220 return ret;
221
222}
223
224
225/* aixcoff_relocate_symtab - hook for symbol table relocation.
226 also reads shared libraries.. */
227
228aixcoff_relocate_symtab (pid)
229unsigned int pid;
230{
231#define MAX_LOAD_SEGS 64 /* maximum number of load segments */
232
233 extern int compare_misc_functions ();
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_misc_function_vector ();
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
269typedef struct {
270 unsigned long textorg, dataorg, toc_offset;
271} LoadInfo;
272
273#define LOADINFOLEN 10
274
275static LoadInfo *loadInfo = NULL;
276static int loadInfoLen = 0;
277static int loadInfoTocIndex = 0;
278static int loadInfoTextIndex = 0;
279
280
281xcoff_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
293free_loadinfo ()
294{
295 if (loadInfo)
296 free (loadInfo);
297 loadInfo = NULL;
298 loadInfoLen = 0;
299 loadInfoTocIndex = 0;
300 loadInfoTextIndex = 0;
301}
302
303
304xcoff_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
314add_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
326unsigned long
327find_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
343exec_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.037026 seconds and 4 git commands to generate.