#include "inferior.h"
#include "symtab.h"
#include "target.h"
+#include "gdbcore.h"
+
+#include "xcoffsolib.h"
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/ioctl.h>
#include <fcntl.h>
-#include <sys/ptrace.h>
-#include <sys/reg.h>
-
#include <a.out.h>
#include <sys/file.h>
#include <sys/stat.h>
/* Breakpoint shadows for the single step instructions will be kept here. */
static struct sstep_breaks {
- int address;
- int data;
+ /* Address, or 0 if this is not in use. */
+ CORE_ADDR address;
+ /* Shadow contents. */
+ char data[4];
} stepBreaks[2];
/* Static function prototypes */
-static void
-add_text_to_loadinfo PARAMS ((CORE_ADDR textaddr, CORE_ADDR dataaddr));
-
static CORE_ADDR
find_toc_address PARAMS ((CORE_ADDR pc));
dest = read_register (LR_REGNUM) & ~3;
else if (ext_op == 528) /* br cond to count reg */
- dest = read_register (CTR_REGNUM) & ~3;
-
+ {
+ dest = read_register (CTR_REGNUM) & ~3;
+
+ /* If we are about to execute a system call, dest is something
+ like 0x22fc or 0x3b00. Upon completion the system call
+ will return to the address in the link register. */
+ if (dest < TEXT_SEGMENT_BASE)
+ dest = read_register (LR_REGNUM) & ~3;
+ }
else return -1;
break;
/* AIX does not support PT_STEP. Simulate it. */
-int
+void
single_step (signal)
-int signal;
+ int signal;
{
#define INSNLEN(OPCODE) 4
static char breakp[] = BREAKPOINT;
- int ii, insn, ret, loc;
- int breaks[2], opcode;
+ int ii, insn;
+ CORE_ADDR loc;
+ CORE_ADDR breaks[2];
+ int opcode;
if (!one_stepped) {
loc = read_pc ();
- ret = read_memory (loc, &insn, sizeof (int));
- if (ret)
- printf ("Error in single_step()!!\n");
+ read_memory (loc, (char *) &insn, 4);
breaks[0] = loc + INSNLEN(insn);
opcode = insn >> 26;
if (breaks[1] == breaks[0])
breaks[1] = -1;
- stepBreaks[1].address = -1;
+ stepBreaks[1].address = 0;
for (ii=0; ii < 2; ++ii) {
if ( breaks[ii] == -1)
continue;
- read_memory (breaks[ii], &(stepBreaks[ii].data), sizeof(int));
+ read_memory (breaks[ii], stepBreaks[ii].data, 4);
- ret = write_memory (breaks[ii], breakp, sizeof(int));
+ write_memory (breaks[ii], breakp, 4);
stepBreaks[ii].address = breaks[ii];
}
one_stepped = 1;
- ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal, 0);
- }
- else {
+ } else {
/* remove step breakpoints. */
for (ii=0; ii < 2; ++ii)
- if (stepBreaks[ii].address != -1)
+ if (stepBreaks[ii].address != 0)
write_memory
- (stepBreaks[ii].address, &(stepBreaks[ii].data), sizeof(int));
+ (stepBreaks[ii].address, stepBreaks[ii].data, 4);
one_stepped = 0;
}
- errno = 0;
- return 1;
+ errno = 0; /* FIXME, don't ignore errors! */
+ /* What errors? {read,write}_memory call error(). */
}
skip_prologue (pc)
CORE_ADDR pc;
{
+ char buf[4];
unsigned int tmp;
- unsigned int op; /* FIXME, assumes instruction size matches host int!!! */
+ unsigned long op;
- if (target_read_memory (pc, (char *)&op, sizeof (op)))
+ if (target_read_memory (pc, buf, 4))
return pc; /* Can't access it -- assume no prologue. */
- SWAP_TARGET_AND_HOST (&op, sizeof (op));
+ op = extract_unsigned_integer (buf, 4);
/* Assume that subsequent fetches can fail with low probability. */
return pc - 4; /* don't skip over this branch */
}
+ if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
+ pc += 4; /* store floating register double */
+ op = read_memory_integer (pc, 4);
+ }
+
if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */
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) */
+ (tmp == 0x93e1)) /* st r31,NUM(r1) */
{
pc += 4;
op = read_memory_integer (pc, 4);
function as well. */
tmp = find_pc_misc_function (pc);
- if (tmp >= 0 && !strcmp (misc_function_vector [tmp].name, "main"))
+ if (tmp >= 0 && STREQ (misc_function_vector [tmp].name, "main"))
return pc + 8;
}
}
void
push_dummy_frame ()
{
- int sp, pc; /* stack pointer and link register */
+ /* stack pointer. */
+ CORE_ADDR sp;
+
+ /* link register. */
+ CORE_ADDR pc;
+ /* Same thing, target byte order. */
+ char pc_targ[4];
+
int ii;
- fetch_inferior_registers (-1);
+ target_fetch_registers (-1);
if (dummy_frame_count >= dummy_frame_size) {
dummy_frame_size += DUMMY_FRAME_ADDR_SIZE;
}
sp = read_register(SP_REGNUM);
- pc = read_register(PC_REGNUM);
+ pc = read_register(PC_REGNUM);
+ memcpy (pc_targ, (char *) &pc, 4);
dummy_frame_addr [dummy_frame_count++] = sp;
set_current_frame (create_new_frame (sp-DUMMY_FRAME_SIZE, pc));
/* save program counter in link register's space. */
- write_memory (sp+8, &pc, 4);
+ write_memory (sp+8, pc_targ, 4);
/* save all floating point and general purpose registers here. */
sp -= DUMMY_FRAME_SIZE;
/* And finally, this is the back chain. */
- write_memory (sp+8, &pc, 4);
+ write_memory (sp+8, pc_targ, 4);
}
/* Now we can restore all registers. */
- store_inferior_registers (-1);
+ target_store_registers (-1);
pc = read_pc ();
flush_cached_frames ();
set_current_frame (create_new_frame (sp, pc));
void
pop_frame ()
{
- int pc, lr, sp, prev_sp; /* %pc, %lr, %sp */
+ CORE_ADDR pc, lr, sp, prev_sp; /* %pc, %lr, %sp */
struct aix_framedata fdata;
FRAME fr = get_current_frame ();
int addr, ii;
addr = get_pc_function_start (fr->pc) + FUNCTION_START_OFFSET;
function_frame_info (addr, &fdata);
- read_memory (sp, &prev_sp, 4);
+ prev_sp = read_memory_integer (sp, 4);
if (fdata.frameless)
lr = read_register (LR_REGNUM);
else
- read_memory (prev_sp+8, &lr, 4);
+ lr = read_memory_integer (prev_sp+8, 4);
/* reset %pc value. */
write_register (PC_REGNUM, lr);
if (fdata.saved_gpr != -1)
for (ii=fdata.saved_gpr; ii <= 31; ++ii) {
read_memory (addr, ®isters [REGISTER_BYTE (ii)], 4);
- addr += sizeof (int);
+ addr += 4;
}
if (fdata.saved_fpr != -1)
}
write_register (SP_REGNUM, prev_sp);
- store_inferior_registers (-1);
+ target_store_registers (-1);
flush_cached_frames ();
set_current_frame (create_new_frame (prev_sp, lr));
}
/* return information about a function frame.
in struct aix_frameinfo fdata:
- - frameless is TRUE, if function does not save %pc value in its frame.
+ - frameless is TRUE, if function does not have a frame.
+ - nosavedpc 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.
fdata->offset = 0;
fdata->saved_gpr = fdata->saved_fpr = fdata->alloca_reg = -1;
+ fdata->frameless = 1;
op = read_memory_integer (pc, 4);
if (op == 0x7c0802a6) { /* mflr r0 */
pc += 4;
op = read_memory_integer (pc, 4);
+ fdata->nosavedpc = 0;
fdata->frameless = 0;
}
- else /* else, this is a frameless invocation */
- fdata->frameless = 1;
-
+ else /* else, pc is not saved */
+ fdata->nosavedpc = 1;
if ((op & 0xfc00003e) == 0x7c000026) { /* mfcr Rx */
pc += 4;
op = read_memory_integer (pc, 4);
+ fdata->frameless = 0;
}
if ((op & 0xfc000000) == 0x48000000) { /* bl foo, to save fprs??? */
if (op == 0x4def7b82 || /* crorc 15, 15, 15 */
op == 0x0)
return; /* prologue is over */
+ fdata->frameless = 0;
}
if ((op & 0xfc1f0000) == 0xd8010000) { /* stfd Rx,NUM(r1) */
pc += 4; /* store floating register double */
op = read_memory_integer (pc, 4);
+ fdata->frameless = 0;
}
if ((op & 0xfc1f0000) == 0xbc010000) { /* stm Rx, NUM(r1) */
fdata->saved_gpr = (op >> 21) & 0x1f;
tmp2 = op & 0xffff;
if (tmp2 > 0x7fff)
- tmp2 = 0xffff0000 | tmp2;
+ tmp2 = (~0 &~ 0xffff) | tmp2;
if (tmp2 < 0) {
tmp2 = tmp2 * -1;
fdata->offset = tmp2;
pc += 4;
op = read_memory_integer (pc, 4);
+ fdata->frameless = 0;
}
while (((tmp = op >> 16) == 0x9001) || /* st r0, NUM(r1) */
(tmp == 0x9421) || /* stu r1, NUM(r1) */
- (op == 0x93e1fffc)) /* st r31,-4(r1) */
+ (tmp == 0x93e1)) /* st r31, NUM(r1) */
{
+ int tmp2;
+
/* gcc takes a short cut and uses this instruction to save r31 only. */
- if (op == 0x93e1fffc) {
+ if (tmp == 0x93e1) {
if (fdata->offset)
/* fatal ("Unrecognized prolog."); */
- printf ("Unrecognized prolog!\n");
+ printf_unfiltered ("Unrecognized prolog!\n");
fdata->saved_gpr = 31;
- fdata->offset = 4;
+ tmp2 = op & 0xffff;
+ if (tmp2 > 0x7fff) {
+ tmp2 = - ((~0 &~ 0xffff) | tmp2);
+ fdata->saved_fpr = (tmp2 - ((32 - 31) * 4)) / 8;
+ if ( fdata->saved_fpr > 0)
+ fdata->saved_fpr = 32 - fdata->saved_fpr;
+ else
+ fdata->saved_fpr = -1;
+ }
+ fdata->offset = tmp2;
}
pc += 4;
op = read_memory_integer (pc, 4);
+ fdata->frameless = 0;
}
while ((tmp = (op >> 22)) == 0x20f) { /* l r31, ... or */
pc += 4; /* l r30, ... */
op = read_memory_integer (pc, 4);
+ fdata->frameless = 0;
}
/* store parameters into stack */
{
pc += 4; /* store fpr double */
op = read_memory_integer (pc, 4);
+ fdata->frameless = 0;
}
- if (op == 0x603f0000) /* oril r31, r1, 0x0 */
+ if (op == 0x603f0000) { /* oril r31, r1, 0x0 */
fdata->alloca_reg = 31;
+ fdata->frameless = 0;
+ }
}
CORE_ADDR saved_sp, pc;
if ( dummy_frame_count <= 0)
- printf ("FATAL ERROR -push_arguments()! frame not found!!\n");
+ printf_unfiltered ("FATAL ERROR -push_arguments()! frame not found!!\n");
/* The first eight words of ther arguments are passed in registers. Copy
them appropriately.
there is no way we would run out of them. */
if (len > 8)
- printf (
+ printf_unfiltered (
"Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
- bcopy (VALUE_CONTENTS (arg),
- ®isters[REGISTER_BYTE(FP0_REGNUM + 1 + f_argno)], len);
+ memcpy (®isters[REGISTER_BYTE(FP0_REGNUM + 1 + f_argno)], VALUE_CONTENTS (arg),
+ len);
++f_argno;
}
while (argbytes < len) {
*(int*)®isters[REGISTER_BYTE(ii+3)] = 0;
- bcopy ( ((char*)VALUE_CONTENTS (arg))+argbytes,
- ®isters[REGISTER_BYTE(ii+3)],
+ memcpy (®isters[REGISTER_BYTE(ii+3)],
+ ((char*)VALUE_CONTENTS (arg))+argbytes,
(len - argbytes) > 4 ? 4 : len - argbytes);
++ii, argbytes += 4;
}
else { /* Argument can fit in one register. No problem. */
*(int*)®isters[REGISTER_BYTE(ii+3)] = 0;
- bcopy (VALUE_CONTENTS (arg), ®isters[REGISTER_BYTE(ii+3)], len);
+ memcpy (®isters[REGISTER_BYTE(ii+3)], VALUE_CONTENTS (arg), len);
}
++argno;
}
if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_FLT && f_argno < 13) {
if (len > 8)
- printf (
+ printf_unfiltered (
"Fatal Error: a floating point parameter #%d with a size > 8 is found!\n", argno);
- bcopy (VALUE_CONTENTS (arg),
- ®isters[REGISTER_BYTE(FP0_REGNUM + 1 + f_argno)], len);
+ memcpy (®isters[REGISTER_BYTE(FP0_REGNUM + 1 + f_argno)], VALUE_CONTENTS (arg),
+ len);
++f_argno;
}
- write_memory (sp+24+(ii*4), VALUE_CONTENTS (arg), len);
+ write_memory (sp+24+(ii*4), (char *) VALUE_CONTENTS (arg), len);
ii += ((len + 3) & -4) / 4;
}
}
write_memory (sp, &saved_sp, 4); /* set back chain properly */
- store_inferior_registers (-1);
+ target_store_registers (-1);
return sp;
}
necessary. */
if (TYPE_LENGTH (valtype) > 4) /* this is a double */
- bcopy (®buf[REGISTER_BYTE (FP0_REGNUM + 1)], valbuf,
+ memcpy (valbuf, ®buf[REGISTER_BYTE (FP0_REGNUM + 1)],
TYPE_LENGTH (valtype));
else { /* float */
- bcopy (®buf[REGISTER_BYTE (FP0_REGNUM + 1)], &dd, 8);
+ memcpy (&dd, ®buf[REGISTER_BYTE (FP0_REGNUM + 1)], 8);
ff = (float)dd;
- bcopy (&ff, valbuf, sizeof(float));
+ memcpy (valbuf, &ff, sizeof(float));
}
}
else
/* return value is copied starting from r3. */
- bcopy (®buf[REGISTER_BYTE (3)], valbuf, TYPE_LENGTH (valtype));
+ memcpy (valbuf, ®buf[REGISTER_BYTE (3)], TYPE_LENGTH (valtype));
}
CORE_ADDR rs6000_struct_return_address;
-/* Throw away this debugging code. FIXMEmgo. */
-void
-print_frame(fram)
-int fram;
-{
- int ii, val;
- for (ii=0; ii<40; ++ii) {
- if ((ii % 4) == 0)
- printf ("\n");
- val = read_memory_integer (fram + ii * 4, 4);
- printf ("0x%08x\t", val);
- }
- printf ("\n");
-}
-
-
-
/* 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).
for (ii=0; trampoline_code[ii]; ++ii) {
op = read_memory_integer (pc + (ii*4), 4);
if (op != trampoline_code [ii])
- return NULL;
+ return 0;
}
ii = read_register (11); /* r11 holds destination addr */
pc = read_memory_integer (ii, 4); /* (r11) value */
/* Determines whether the function FI has a frame on the stack or not.
- Called from the FRAMELESS_FUNCTION_INVOCATION macro in tm.h. */
+ Called from the FRAMELESS_FUNCTION_INVOCATION macro in tm.h with a
+ second argument of 0, and from the FRAME_SAVED_PC macro with a
+ second argument of 1. */
int
-frameless_function_invocation (fi)
+frameless_function_invocation (fi, pcsaved)
struct frame_info *fi;
+int pcsaved;
{
CORE_ADDR func_start;
struct aix_framedata fdata;
+ if (fi->next != NULL)
+ /* Don't even think about framelessness except on the innermost frame. */
+ /* FIXME: Can also be frameless if fi->next->signal_handler_caller (if
+ a signal happens while executing in a frameless function). */
+ return 0;
+
func_start = get_pc_function_start (fi->pc) + FUNCTION_START_OFFSET;
/* If we failed to find the start of the function, it is a mistake
return 0;
function_frame_info (func_start, &fdata);
- return fdata.frameless;
+ return pcsaved ? fdata.nosavedpc : fdata.frameless;
}
fi->cache_fsr = (struct frame_saved_regs *)
obstack_alloc (&frame_cache_obstack, sizeof (struct frame_saved_regs));
- bzero (fi->cache_fsr, sizeof (struct frame_saved_regs));
+ memset (fi->cache_fsr, '\0', sizeof (struct frame_saved_regs));
if (fi->prev && fi->prev->frame)
frame_addr = fi->prev->frame;
for (callee_fi = fi->next; callee_fi; callee_fi = callee_fi->next) {
if (!callee_fi->cache_fsr)
- frame_get_cache_fsr (fi, NULL);
+ frame_get_cache_fsr (callee_fi, NULL);
/* this is the address in which alloca register is saved. */
return fi->initial_sp = read_register (fdata.alloca_reg);
}
+FRAME_ADDR
+rs6000_frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+ FRAME_ADDR fp;
+ if (inside_entry_file ((thisframe)->pc))
+ return 0;
+ if (thisframe->signal_handler_caller)
+ {
+ /* This was determined by experimentation on AIX 3.2. Perhaps
+ it corresponds to some offset in /usr/include/sys/user.h or
+ something like that. Using some system include file would
+ have the advantage of probably being more robust in the face
+ of OS upgrades, but the disadvantage of being wrong for
+ cross-debugging. */
+
+#define SIG_FRAME_FP_OFFSET 284
+ fp = read_memory_integer (thisframe->frame + SIG_FRAME_FP_OFFSET, 4);
+ }
+ else
+ fp = read_memory_integer ((thisframe)->frame, 4);
+
+ return fp;
+}
+
+\f
/* xcoff_relocate_symtab - hook for symbol table relocation.
also reads shared libraries.. */
vmap_ldinfo(ldi);
do {
- add_text_to_loadinfo (ldi->ldinfo_textorg, ldi->ldinfo_dataorg);
+ /* We are allowed to assume CORE_ADDR == pointer. This code is
+ native only. */
+ add_text_to_loadinfo ((CORE_ADDR) ldi->ldinfo_textorg,
+ (CORE_ADDR) ldi->ldinfo_dataorg);
} while (ldi->ldinfo_next
&& (ldi = (void *) (ldi->ldinfo_next + (char *) ldi)));
#define LOADINFOLEN 10
-/* FIXME Warning -- loadinfotextindex is used for a nefarious purpose by
- tm-rs6000.h. */
-
static struct loadinfo *loadinfo = NULL;
static int loadinfolen = 0;
static int loadinfotocindex = 0;
-int loadinfotextindex = 0;
+static int loadinfotextindex = 0;
void
}
-static void
+void
add_text_to_loadinfo (textaddr, dataaddr)
CORE_ADDR textaddr;
CORE_ADDR dataaddr;