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 ()
66 extern char registers
[];
68 /* read 32 general purpose registers. */
70 for (ii
=0; ii
< 32; ++ii
)
71 *(int*)®isters
[REGISTER_BYTE (ii
)] =
72 ptrace (PT_READ_GPR
, inferior_pid
, ii
, 0, 0);
74 /* read general purpose floating point registers. */
76 for (ii
=0; ii
< 32; ++ii
)
77 ptrace (PT_READ_FPR
, inferior_pid
,
78 (int*)®isters
[REGISTER_BYTE (FP0_REGNUM
+ii
)], FPR0
+ii
, 0);
80 /* read special registers. */
81 for (ii
=0; ii
<= LAST_SP_REGNUM
-FIRST_SP_REGNUM
; ++ii
)
82 *(int*)®isters
[REGISTER_BYTE (FIRST_SP_REGNUM
+ii
)] =
83 ptrace (PT_READ_GPR
, inferior_pid
, special_regs
[ii
], 0, 0);
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). */
90 store_inferior_registers (regno
)
93 extern char registers
[];
97 if (regno
== -1) { /* for all registers.. */
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) */
105 exec_one_dummy_insn ();
107 /* write general purpose registers first! */
108 for ( ii
=GPR0
; ii
<=GPR31
; ++ii
) {
109 ptrace (PT_WRITE_GPR
, inferior_pid
, ii
,
110 *(int*)®isters
[REGISTER_BYTE (ii
)], 0);
112 perror ("ptrace write_gpr"); errno
= 0;
116 /* write floating point registers now. */
117 for ( ii
=0; ii
< 32; ++ii
) {
118 ptrace (PT_WRITE_FPR
, inferior_pid
,
119 (int*)®isters
[REGISTER_BYTE (FP0_REGNUM
+ii
)], FPR0
+ii
, 0);
121 perror ("ptrace write_fpr"); errno
= 0;
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*)®isters
[REGISTER_BYTE (FIRST_SP_REGNUM
+ii
)], 0);
130 perror ("ptrace write_gpr"); errno
= 0;
135 /* else, a specific register number is given... */
137 else if (regno
< FP0_REGNUM
) { /* a GPR */
139 ptrace (PT_WRITE_GPR
, inferior_pid
, regno
,
140 *(int*)®isters
[REGISTER_BYTE (regno
)], 0);
143 else if (regno
<= FPLAST_REGNUM
) { /* a FPR */
144 ptrace (PT_WRITE_FPR
, inferior_pid
,
145 (int*)®isters
[REGISTER_BYTE (regno
)], regno
-FP0_REGNUM
+FPR0
, 0);
148 else if (regno
<= LAST_SP_REGNUM
) { /* a special register */
150 ptrace (PT_WRITE_GPR
, inferior_pid
, special_regs
[regno
-FIRST_SP_REGNUM
],
151 *(int*)®isters
[REGISTER_BYTE (regno
)], 0);
155 fprintf (stderr
, "Gdb error: register no %d not implemented.\n", regno
);
158 perror ("ptrace write"); errno
= 0;
165 fetch_core_registers (core_reg_sect
, core_reg_size
, which
)
167 unsigned core_reg_size
;
170 /* fetch GPRs and special registers from the first register section
174 /* copy GPRs first. */
175 bcopy (core_reg_sect
, registers
, 32 * 4);
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
, ®isters
[REGISTER_BYTE (FIRST_SP_REGNUM
)],
183 (LAST_SP_REGNUM
- FIRST_SP_REGNUM
+ 1) * 4);
186 /* fetch floating point registers from register section 2 in core bfd. */
188 bcopy (core_reg_sect
, ®isters
[REGISTER_BYTE (FP0_REGNUM
)], 32 * 8);
191 fprintf (stderr
, "Gdb error: unknown parameter to fetch_core_registers().\n");
195 frameless_function_invocation (fi
)
196 struct frame_info
*fi
;
199 CORE_ADDR func_start
, after_prologue
;
202 func_start
= (LOAD_ADDR (get_pc_function_start (fi
->pc
)) +
203 FUNCTION_START_OFFSET
);
205 func_start
= get_pc_function_start (fi
->pc
) + FUNCTION_START_OFFSET
;
209 after_prologue
= func_start
;
210 SKIP_PROLOGUE (after_prologue
);
211 ret
= (after_prologue
== func_start
);
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. */
225 /* aixcoff_relocate_symtab - hook for symbol table relocation.
226 also reads shared libraries.. */
228 aixcoff_relocate_symtab (pid
)
231 #define MAX_LOAD_SEGS 64 /* maximum number of load segments */
233 extern int compare_misc_functions ();
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_misc_function_vector ();
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
);
This page took 0.037544 seconds and 4 git commands to generate.