1 /* IBM RS/6000 host-dependent code for GDB, the GNU debugger.
2 Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
27 #include <sys/param.h>
31 #include <sys/ioctl.h>
34 #include <sys/ptrace.h>
44 extern int attach_flag
;
46 /* Conversion from gdb-to-system special purpose register numbers.. */
48 static int special_regs
[] = {
59 /* Nonzero if we just simulated a single step break. */
60 extern int one_stepped
;
63 fetch_inferior_registers (regno
)
67 extern char registers
[];
69 /* read 32 general purpose registers. */
71 for (ii
=0; ii
< 32; ++ii
)
72 *(int*)®isters
[REGISTER_BYTE (ii
)] =
73 ptrace (PT_READ_GPR
, inferior_pid
, ii
, 0, 0);
75 /* read general purpose floating point registers. */
77 for (ii
=0; ii
< 32; ++ii
)
78 ptrace (PT_READ_FPR
, inferior_pid
,
79 (int*)®isters
[REGISTER_BYTE (FP0_REGNUM
+ii
)], FPR0
+ii
, 0);
81 /* read special registers. */
82 for (ii
=0; ii
<= LAST_SP_REGNUM
-FIRST_SP_REGNUM
; ++ii
)
83 *(int*)®isters
[REGISTER_BYTE (FIRST_SP_REGNUM
+ii
)] =
84 ptrace (PT_READ_GPR
, inferior_pid
, special_regs
[ii
], 0, 0);
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). */
92 store_inferior_registers (regno
)
95 extern char registers
[];
99 if (regno
== -1) { /* for all registers.. */
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) */
107 exec_one_dummy_insn ();
109 /* write general purpose registers first! */
110 for ( ii
=GPR0
; ii
<=GPR31
; ++ii
) {
111 ptrace (PT_WRITE_GPR
, inferior_pid
, ii
,
112 *(int*)®isters
[REGISTER_BYTE (ii
)], 0);
114 perror ("ptrace write_gpr"); errno
= 0;
118 /* write floating point registers now. */
119 for ( ii
=0; ii
< 32; ++ii
) {
120 ptrace (PT_WRITE_FPR
, inferior_pid
,
121 (int*)®isters
[REGISTER_BYTE (FP0_REGNUM
+ii
)], FPR0
+ii
, 0);
123 perror ("ptrace write_fpr"); errno
= 0;
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*)®isters
[REGISTER_BYTE (FIRST_SP_REGNUM
+ii
)], 0);
132 perror ("ptrace write_gpr"); errno
= 0;
137 /* else, a specific register number is given... */
139 else if (regno
< FP0_REGNUM
) { /* a GPR */
141 ptrace (PT_WRITE_GPR
, inferior_pid
, regno
,
142 *(int*)®isters
[REGISTER_BYTE (regno
)], 0);
145 else if (regno
<= FPLAST_REGNUM
) { /* a FPR */
146 ptrace (PT_WRITE_FPR
, inferior_pid
,
147 (int*)®isters
[REGISTER_BYTE (regno
)], regno
-FP0_REGNUM
+FPR0
, 0);
150 else if (regno
<= LAST_SP_REGNUM
) { /* a special register */
152 ptrace (PT_WRITE_GPR
, inferior_pid
, special_regs
[regno
-FIRST_SP_REGNUM
],
153 *(int*)®isters
[REGISTER_BYTE (regno
)], 0);
157 fprintf (stderr
, "Gdb error: register no %d not implemented.\n", regno
);
160 perror ("ptrace write"); errno
= 0;
165 fetch_core_registers (core_reg_sect
, core_reg_size
, which
, reg_addr
)
167 unsigned core_reg_size
;
169 unsigned int reg_addr
; /* Unused in this version */
171 /* fetch GPRs and special registers from the first register section
175 /* copy GPRs first. */
176 bcopy (core_reg_sect
, registers
, 32 * 4);
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
, ®isters
[REGISTER_BYTE (FIRST_SP_REGNUM
)],
184 (LAST_SP_REGNUM
- FIRST_SP_REGNUM
+ 1) * 4);
187 /* fetch floating point registers from register section 2 in core bfd. */
189 bcopy (core_reg_sect
, ®isters
[REGISTER_BYTE (FP0_REGNUM
)], 32 * 8);
192 fprintf (stderr
, "Gdb error: unknown parameter to fetch_core_registers().\n");
196 frameless_function_invocation (fi
)
197 struct frame_info
*fi
;
200 CORE_ADDR func_start
, after_prologue
;
203 func_start
= (LOAD_ADDR (get_pc_function_start (fi
->pc
)) +
204 FUNCTION_START_OFFSET
);
206 func_start
= get_pc_function_start (fi
->pc
) + FUNCTION_START_OFFSET
;
210 after_prologue
= func_start
;
211 SKIP_PROLOGUE (after_prologue
);
212 ret
= (after_prologue
== func_start
);
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. */
226 /* aixcoff_relocate_symtab - hook for symbol table relocation.
227 also reads shared libraries.. */
229 aixcoff_relocate_symtab (pid
)
232 #define MAX_LOAD_SEGS 64 /* maximum number of load segments */
237 ldi
= (void *) alloca(MAX_LOAD_SEGS
* sizeof (*ldi
));
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. */
247 ptrace(PT_LDINFO
, pid
, ldi
, MAX_LOAD_SEGS
* sizeof(*ldi
), ldi
);
249 perror_with_name ("ptrace ldinfo");
254 add_text_to_loadinfo (ldi
->ldinfo_textorg
, ldi
->ldinfo_dataorg
);
255 } while (ldi
->ldinfo_next
256 && (ldi
= (void *) (ldi
->ldinfo_next
+ (char *) ldi
)));
258 /* Now that we've jumbled things around, re-sort them. */
259 sort_minimal_symbols ();
261 /* relocate the exec and core sections as well. */
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. */
270 unsigned long textorg
, dataorg
, toc_offset
;
273 #define LOADINFOLEN 10
275 static LoadInfo
*loadInfo
= NULL
;
276 static int loadInfoLen
= 0;
277 static int loadInfoTocIndex
= 0;
278 static int loadInfoTextIndex
= 0;
281 xcoff_init_loadinfo ()
283 loadInfoTocIndex
= 0;
284 loadInfoTextIndex
= 0;
286 if (loadInfoLen
== 0) {
287 loadInfo
= (void*) xmalloc (sizeof (LoadInfo
) * LOADINFOLEN
);
288 loadInfoLen
= LOADINFOLEN
;
299 loadInfoTocIndex
= 0;
300 loadInfoTextIndex
= 0;
304 xcoff_add_toc_to_loadinfo (unsigned long tocaddr
)
306 while (loadInfoTocIndex
>= loadInfoLen
) {
307 loadInfoLen
+= LOADINFOLEN
;
308 loadInfo
= (void*) xrealloc (loadInfo
, sizeof(LoadInfo
) * loadInfoLen
);
310 loadInfo
[loadInfoTocIndex
++].toc_offset
= tocaddr
;
314 add_text_to_loadinfo (unsigned long textaddr
, unsigned long dataaddr
)
316 while (loadInfoTextIndex
>= loadInfoLen
) {
317 loadInfoLen
+= LOADINFOLEN
;
318 loadInfo
= (void*) xrealloc (loadInfo
, sizeof(LoadInfo
) * loadInfoLen
);
320 loadInfo
[loadInfoTextIndex
].textorg
= textaddr
;
321 loadInfo
[loadInfoTextIndex
].dataorg
= dataaddr
;
327 find_toc_address (unsigned long pc
)
331 for (ii
=0; ii
< loadInfoTextIndex
; ++ii
)
332 if (pc
> loadInfo
[ii
].textorg
)
335 return loadInfo
[toc_entry
].dataorg
+ loadInfo
[toc_entry
].toc_offset
;
339 /* execute one dummy breakpoint instruction. This way we give kernel
340 a chance to do some housekeeping and update inferior's internal data,
343 exec_one_dummy_insn ()
345 #define DUMMY_INSN_ADDR 0x10000200
347 unsigned long shadow
;
348 unsigned int status
, pid
;
350 target_insert_breakpoint (DUMMY_INSN_ADDR
, &shadow
);
353 ptrace (PT_CONTINUE
, inferior_pid
, DUMMY_INSN_ADDR
, 0, 0);
355 perror ("pt_continue");
358 pid
= wait (&status
);
359 } while (pid
!= inferior_pid
);
361 target_remove_breakpoint (DUMMY_INSN_ADDR
, &shadow
);