along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
-
#include "defs.h"
#include "frame.h"
#include "inferior.h"
/* Nonzero if we just simulated a single step break. */
int one_stepped;
+
/* Breakpoint shadows for the single step instructions will be kept here. */
static struct sstep_breaks {
}
one_stepped = 1;
- ptrace (PT_CONTINUE, inferior_pid, 1, signal, 0);
+ ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal, 0);
}
else {
if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
pc += 4;
op = read_memory_integer (pc, 4);
- }
-#if 0
- if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
- pc += 4; /* store floating register double */
- op = read_memory_integer (pc, 4);
+ /* At this point, make sure this is not a trampoline function
+ (a function that simply calls another functions, and nothing else).
+ If the next is not a nop, this branch was part of the function
+ prologue. */
+
+ if (op == 0x4def7b82 || /* crorc 15, 15, 15 */
+ op == 0x0)
+ return pc - 4; /* don't skip over this branch */
}
-#endif
if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */
pc += 4;
op = read_memory_integer (pc, 4);
}
- /* store parameters into stack */
+ /* store parameters into stack */
while(
(op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
(op & 0xfc1f0000) == 0x90010000 || /* st r?, NUM(r1) */
tmp += 0x20;
}
}
+#if 0
+/* I have problems with skipping over __main() that I need to address
+ * sometime. Previously, I used to use misc_function_vector which
+ * didn't work as well as I wanted to be. -MGO */
+
+ /* If the first thing after skipping a prolog is a branch to a function,
+ this might be a call to an initializer in main(), introduced by gcc2.
+ We'd like to skip over it as well. Fortunately, xlc does some extra
+ work before calling a function right after a prologue, thus we can
+ single out such gcc2 behaviour. */
+
+
+ if ((op & 0xfc000001) == 0x48000001) { /* bl foo, an initializer function? */
+ op = read_memory_integer (pc+4, 4);
+
+ if (op == 0x4def7b82) { /* cror 0xf, 0xf, 0xf (nop) */
+
+ /* check and see if we are in main. If so, skip over this initializer
+ function as well. */
+
+ tmp = find_pc_misc_function (pc);
+ if (tmp >= 0 && !strcmp (misc_function_vector [tmp].name, "main"))
+ return pc + 8;
+ }
+ }
+#endif /* 0 */
+
return pc;
}
int sp, pc; /* stack pointer and link register */
int ii;
+ fetch_inferior_registers (-1);
+
if (dummy_frame_count >= dummy_frame_size) {
dummy_frame_size += DUMMY_FRAME_ADDR_SIZE;
if (dummy_frame_addr)
dummy_frame_addr [dummy_frame_count++] = sp;
/* Be careful! If the stack pointer is not decremented first, then kernel
- thinks he is free to use the sapce underneath it. And kernel actually
+ thinks he is free to use the space underneath it. And kernel actually
uses that area for IPC purposes when executing ptrace(2) calls. So
before writing register values into the new frame, decrement and update
%sp first in order to secure your frame. */
/* save program counter in link register's space. */
write_memory (sp+8, &pc, 4);
- /* save full floating point registers here. They will be from F14..F31
- for know. I am not sure if we need to save everything here! */
+ /* save all floating point and general purpose registers here. */
/* fpr's, f0..f31 */
for (ii = 0; ii < 32; ++ii)
pop_frame ()
{
int pc, lr, sp, prev_sp; /* %pc, %lr, %sp */
+ struct aix_framedata fdata;
FRAME fr = get_current_frame ();
- int offset = 0;
- int frameless = 0; /* TRUE if function is frameless */
int addr, ii;
- int saved_gpr, saved_fpr; /* # of saved gpr's and fpr's */
pc = read_pc ();
sp = FRAME_FP (fr);
saved %pc value in the previous frame. */
addr = get_pc_function_start (fr->pc) + FUNCTION_START_OFFSET;
- function_frame_info (addr, &frameless, &offset, &saved_gpr, &saved_fpr);
+ function_frame_info (addr, &fdata);
read_memory (sp, &prev_sp, 4);
- if (frameless)
+ if (fdata.frameless)
lr = read_register (LR_REGNUM);
else
read_memory (prev_sp+8, &lr, 4);
write_register (PC_REGNUM, lr);
/* reset register values if any was saved earlier. */
- addr = prev_sp - offset;
+ addr = prev_sp - fdata.offset;
- if (saved_gpr != -1)
- for (ii=saved_gpr; ii <= 31; ++ii) {
+ if (fdata.saved_gpr != -1)
+ for (ii=fdata.saved_gpr; ii <= 31; ++ii) {
read_memory (addr, ®isters [REGISTER_BYTE (ii)], 4);
addr += sizeof (int);
}
- if (saved_fpr != -1)
- for (ii=saved_fpr; ii <= 31; ++ii) {
+ if (fdata.saved_fpr != -1)
+ for (ii=fdata.saved_fpr; ii <= 31; ++ii) {
read_memory (addr, ®isters [REGISTER_BYTE (ii+FP0_REGNUM)], 8);
addr += 8;
}
/* return information about a function frame.
+ in struct aix_frameinfo fdata:
- frameless is TRUE, if function does not save %pc value in its frame.
- offset is the number of bytes used in the frame to save registers.
- saved_gpr is the number of the first saved gpr.
- saved_fpr is the number of the first saved fpr.
+ - alloca_reg is the number of the register used for alloca() handling.
+ Otherwise -1.
*/
-function_frame_info (pc, frameless, offset, saved_gpr, saved_fpr)
+function_frame_info (pc, fdata)
int pc;
- int *frameless, *offset, *saved_gpr, *saved_fpr;
+ struct aix_framedata *fdata;
{
unsigned int tmp;
register unsigned int op;
- *offset = 0;
- *saved_gpr = *saved_fpr = -1;
-
- if (!inferior_pid)
- return;
+ fdata->offset = 0;
+ fdata->saved_gpr = fdata->saved_fpr = fdata->alloca_reg = -1;
op = read_memory_integer (pc, 4);
if (op == 0x7c0802a6) { /* mflr r0 */
pc += 4;
op = read_memory_integer (pc, 4);
- *frameless = 0;
+ fdata->frameless = 0;
}
else /* else, this is a frameless invocation */
- *frameless = 1;
+ fdata->frameless = 1;
if ((op & 0xfc00003e) == 0x7c000026) { /* mfcr Rx */
if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
pc += 4;
op = read_memory_integer (pc, 4);
+ /* At this point, make sure this is not a trampoline function
+ (a function that simply calls another functions, and nothing else).
+ If the next is not a nop, this branch was part of the function
+ prologue. */
+
+ if (op == 0x4def7b82 || /* crorc 15, 15, 15 */
+ op == 0x0)
+ return; /* prologue is over */
}
if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */
int tmp2;
- *saved_gpr = (op >> 21) & 0x1f;
+ fdata->saved_gpr = (op >> 21) & 0x1f;
tmp2 = op & 0xffff;
if (tmp2 > 0x7fff)
tmp2 = 0xffff0000 | tmp2;
if (tmp2 < 0) {
tmp2 = tmp2 * -1;
- *saved_fpr = (tmp2 - ((32 - *saved_gpr) * 4)) / 8;
- if ( *saved_fpr > 0)
- *saved_fpr = 32 - *saved_fpr;
+ fdata->saved_fpr = (tmp2 - ((32 - fdata->saved_gpr) * 4)) / 8;
+ if ( fdata->saved_fpr > 0)
+ fdata->saved_fpr = 32 - fdata->saved_fpr;
else
- *saved_fpr = -1;
+ fdata->saved_fpr = -1;
}
- *offset = tmp2;
+ fdata->offset = tmp2;
+ pc += 4;
+ op = read_memory_integer (pc, 4);
}
+
+ while (((tmp = op >> 16) == 0x9001) || /* st r0, NUM(r1) */
+ (tmp == 0x9421) || /* stu r1, NUM(r1) */
+ (op == 0x93e1fffc)) /* st r31,-4(r1) */
+ {
+ /* gcc takes a short cut and uses this instruction to save r31 only. */
+
+ if (op == 0x93e1fffc) {
+ if (fdata->offset)
+/* fatal ("Unrecognized prolog."); */
+ printf ("Unrecognized prolog!\n");
+
+ fdata->saved_gpr = 31;
+ fdata->offset = 4;
+ }
+ pc += 4;
+ op = read_memory_integer (pc, 4);
+ }
+
+ while ((tmp = (op >> 22)) == 0x20f) { /* l r31, ... or */
+ pc += 4; /* l r30, ... */
+ op = read_memory_integer (pc, 4);
+ }
+
+ /* store parameters into stack */
+ while(
+ (op & 0xfc1f0000) == 0xd8010000 || /* stfd Rx,NUM(r1) */
+ (op & 0xfc1f0000) == 0x90010000 || /* st r?, NUM(r1) */
+ (op & 0xfc000000) == 0xfc000000 || /* frsp, fp?, .. */
+ (op & 0xd0000000) == 0xd0000000) /* stfs, fp?, .. */
+ {
+ pc += 4; /* store fpr double */
+ op = read_memory_integer (pc, 4);
+ }
+
+ if (op == 0x603f0000) /* oril r31, r1, 0x0 */
+ fdata->alloca_reg = 31;
}
write_register (SP_REGNUM, sp);
-#if 0
- pc = read_pc ();
- flush_cached_frames ();
- set_current_frame (create_new_frame (sp, pc));
-#endif
-
/* if the last argument copied into the registers didn't fit there
completely, push the rest of it into stack. */
ii += ((len + 3) & -4) / 4;
}
}
- else {
-
+ else
/* Secure stack areas first, before doing anything else. */
write_register (SP_REGNUM, sp);
-#if 0
- pc = read_pc ();
- flush_cached_frames ();
- set_current_frame (create_new_frame (sp, pc));
-#endif
- }
-
saved_sp = dummy_frame_addr [dummy_frame_count - 1];
read_memory (saved_sp, tmp_buffer, 24);
write_memory (sp, tmp_buffer, 24);
-/* Indirect function calls use a piece of trampoline code do co context switching,
- i.e. to set the new TOC table. Skip such code if exists. */
+/* Indirect function calls use a piece of trampoline code to do context
+ switching, i.e. to set the new TOC table. Skip such code if we are on
+ its first instruction (as when we have single-stepped to here).
+ Result is desired PC to step until, or NULL if we are not in
+ trampoline code. */
skip_trampoline_code (pc)
int pc;