mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-01-31 14:04:12 +00:00
* config/mips/tm-mips.h (ADDR_BITS_REMOVE, TARGET_READ_SP): Define.
(mips_addr_bits_remove): Declare. * mips-tdep.c (mips_push_dummy_frame): Fix heuristic-fence-post errors when hitting breakpoints during inferior function calls in 64-bit programs. (fix_sign_extension): Make public, rename to mips_addr_bits_remove. * utils.c (paddr_nz, preg_nz): New functions, similar to paddr and preg but don't print leading zeroes. * defs.h (paddr_nz, preg_nz): Declare. * remote-mips.c: Use paddr_nz instead of paddr throughout to reduce packet size. (pmon_end_download): Improve timeout error handling.
This commit is contained in:
parent
92284aaa35
commit
96431497ff
@ -1,3 +1,18 @@
|
||||
Tue Nov 26 19:21:35 1996 Mark Alexander <marka@cygnus.com>
|
||||
|
||||
* config/mips/tm-mips.h (ADDR_BITS_REMOVE, TARGET_READ_SP): Define.
|
||||
(mips_addr_bits_remove): Declare.
|
||||
* mips-tdep.c (mips_push_dummy_frame): Fix heuristic-fence-post
|
||||
errors when hitting breakpoints during inferior function calls
|
||||
in 64-bit programs.
|
||||
(fix_sign_extension): Make public, rename to mips_addr_bits_remove.
|
||||
* utils.c (paddr_nz, preg_nz): New functions, similar to
|
||||
paddr and preg but don't print leading zeroes.
|
||||
* defs.h (paddr_nz, preg_nz): Declare.
|
||||
* remote-mips.c: Use paddr_nz instead of paddr throughout
|
||||
to reduce packet size.
|
||||
(pmon_end_download): Improve timeout error handling.
|
||||
|
||||
Tue Nov 26 17:21:37 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||
|
||||
* configure: Rebuild with autoconf 2.12.
|
||||
|
143
gdb/mips-tdep.c
143
gdb/mips-tdep.c
@ -42,11 +42,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
extern struct obstack frame_cache_obstack;
|
||||
|
||||
/* FIXME! this code assumes 4-byte instructions. */
|
||||
#define MIPS_INSTLEN 4
|
||||
#define MIPS_NUMREGS 32 /* FIXME! how many on 64-bit mips? */
|
||||
typedef unsigned long t_inst;
|
||||
#define MIPS_INSTLEN 4 /* Length of an instruction */
|
||||
#define MIPS_NUMREGS 32 /* Number of integer or float registers */
|
||||
typedef unsigned long t_inst; /* Integer big enough to hold an instruction */
|
||||
|
||||
|
||||
#if 0
|
||||
static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
|
||||
#endif
|
||||
@ -209,7 +208,6 @@ struct linked_proc_info
|
||||
struct linked_proc_info *next;
|
||||
} *linked_proc_desc_table = NULL;
|
||||
|
||||
|
||||
|
||||
/* This returns the PC of the first inst after the prologue. If we can't
|
||||
find the prologue, then return 0. */
|
||||
@ -444,6 +442,37 @@ read_next_frame_reg(fi, regno)
|
||||
return read_register (regno);
|
||||
}
|
||||
|
||||
/* mips_addr_bits_remove - remove useless address bits */
|
||||
|
||||
CORE_ADDR
|
||||
mips_addr_bits_remove (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
if (GDB_TARGET_IS_MIPS64
|
||||
&& (addr >> 32 == (CORE_ADDR)0xffffffff)
|
||||
&& (strcmp(target_shortname,"pmon")==0
|
||||
|| strcmp(target_shortname,"ddb")==0
|
||||
|| strcmp(target_shortname,"sim")==0))
|
||||
{
|
||||
/* This hack is a work-around for existing boards using PMON,
|
||||
the simulator, and any other 64-bit targets that doesn't have
|
||||
true 64-bit addressing. On these targets, the upper 32 bits
|
||||
of addresses are ignored by the hardware. Thus, the PC or SP
|
||||
are likely to have been sign extended to all 1s by instruction
|
||||
sequences that load 32-bit addresses. For example, a typical
|
||||
piece of code that loads an address is this:
|
||||
lui $r2, <upper 16 bits>
|
||||
ori $r2, <lower 16 bits>
|
||||
But the lui sign-extends the value such that the upper 32 bits
|
||||
may be all 1s. The workaround is simply to mask off these bits.
|
||||
In the future, gcc may be changed to support true 64-bit
|
||||
addressing, and this masking will have to be disabled. */
|
||||
addr &= (CORE_ADDR)0xffffffff;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
mips_frame_saved_pc(frame)
|
||||
struct frame_info *frame;
|
||||
@ -460,18 +489,7 @@ mips_frame_saved_pc(frame)
|
||||
else
|
||||
saved_pc = read_next_frame_reg(frame, pcreg);
|
||||
|
||||
if (GDB_TARGET_IS_MIPS64 && strcmp(current_target.to_shortname,"pmon")==0)
|
||||
{
|
||||
/* This hack is a work-around for PMON.
|
||||
* The PMON version in the Vr4300 board has been
|
||||
* compiled without the 64bit register access commands.
|
||||
* Thus, the upper word of the PC may be sign extended to all 1s.
|
||||
* If so, change it to zero. */
|
||||
if (saved_pc >> 32 == (CORE_ADDR)0xffffffff)
|
||||
saved_pc &= (CORE_ADDR)0xffffffff;
|
||||
}
|
||||
|
||||
return saved_pc;
|
||||
return ADDR_BITS_REMOVE (saved_pc);
|
||||
}
|
||||
|
||||
static struct mips_extra_func_info temp_proc_desc;
|
||||
@ -511,7 +529,7 @@ heuristic_proc_start(pc)
|
||||
else
|
||||
warning("Hit heuristic-fence-post without finding");
|
||||
|
||||
warning("enclosing function for address 0x%x", pc);
|
||||
warning("enclosing function for address 0x%s", paddr (pc));
|
||||
if (!blurb_printed)
|
||||
{
|
||||
printf_filtered ("\
|
||||
@ -530,7 +548,7 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\
|
||||
else if (ABOUT_TO_RETURN(start_pc))
|
||||
break;
|
||||
|
||||
start_pc += 8; /* skip return, and its delay slot */ /* FIXME!! */
|
||||
start_pc += 2 * MIPS_INSTLEN; /* skip return, and its delay slot */
|
||||
#if 0
|
||||
/* skip nops (usually 1) 0 - is this */
|
||||
while (start_pc < pc && read_memory_integer (start_pc, MIPS_INSTLEN) == 0)
|
||||
@ -569,11 +587,12 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame)
|
||||
if (status) memory_error (status, cur_pc);
|
||||
word = (unsigned long) extract_unsigned_integer (buf, MIPS_INSTLEN); /* FIXME!! */
|
||||
|
||||
if ((word & 0xFFFF0000) == 0x27bd0000) /* addiu $sp,$sp,-i */
|
||||
if ((word & 0xFFFF0000) == 0x27bd0000 /* addiu $sp,$sp,-i */
|
||||
|| (word & 0xFFFF0000) == 0x23bd0000 /* addi $sp,$sp,-i */
|
||||
|| (word & 0xFFFF0000) == 0x67bd0000) /* daddiu $sp,$sp,-i */
|
||||
frame_size += (-word) & 0xFFFF;
|
||||
else if ((word & 0xFFFF0000) == 0x23bd0000) /* addu $sp,$sp,-i */
|
||||
frame_size += (-word) & 0xFFFF;
|
||||
else if ((word & 0xFFE00000) == 0xafa00000) { /* sw reg,offset($sp) */
|
||||
else if ((word & 0xFFE00000) == 0xafa00000 /* sw reg,offset($sp) */
|
||||
|| (word & 0xFFE00000) == 0xffa00000) { /* sd reg,offset($sp) */
|
||||
int reg = (word & 0x001F0000) >> 16;
|
||||
reg_mask |= 1 << reg;
|
||||
temp_saved_regs.regs[reg] = sp + (word & 0xffff);
|
||||
@ -697,6 +716,15 @@ find_proc_desc (pc, next_frame)
|
||||
return proc_desc;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
get_frame_pointer(frame, proc_desc)
|
||||
struct frame_info *frame;
|
||||
mips_extra_func_info_t proc_desc;
|
||||
{
|
||||
return ADDR_BITS_REMOVE (read_next_frame_reg (frame,
|
||||
PROC_FRAME_REG(proc_desc)) + PROC_FRAME_OFFSET(proc_desc));
|
||||
}
|
||||
|
||||
mips_extra_func_info_t cached_proc_desc;
|
||||
|
||||
CORE_ADDR
|
||||
@ -725,14 +753,15 @@ mips_frame_chain(frame)
|
||||
&& !frame->signal_handler_caller)
|
||||
return 0;
|
||||
else
|
||||
return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
|
||||
+ PROC_FRAME_OFFSET(proc_desc);
|
||||
return get_frame_pointer (frame, proc_desc);
|
||||
}
|
||||
|
||||
void
|
||||
init_extra_frame_info(fci)
|
||||
struct frame_info *fci;
|
||||
{
|
||||
int regnum;
|
||||
|
||||
/* Use proc_desc calculated in frame_chain */
|
||||
mips_extra_func_info_t proc_desc =
|
||||
fci->next ? cached_proc_desc : find_proc_desc(fci->pc, fci->next);
|
||||
@ -750,9 +779,7 @@ init_extra_frame_info(fci)
|
||||
&& !PROC_DESC_IS_DUMMY (proc_desc))
|
||||
fci->frame = read_next_frame_reg (fci->next, SP_REGNUM);
|
||||
else
|
||||
fci->frame =
|
||||
read_next_frame_reg (fci->next, PROC_FRAME_REG (proc_desc))
|
||||
+ PROC_FRAME_OFFSET (proc_desc);
|
||||
fci->frame = get_frame_pointer (fci->next, proc_desc);
|
||||
|
||||
if (proc_desc == &temp_proc_desc)
|
||||
{
|
||||
@ -775,12 +802,15 @@ init_extra_frame_info(fci)
|
||||
}
|
||||
|
||||
/* hack: if argument regs are saved, guess these contain args */
|
||||
if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1;
|
||||
/* FIXME! Increase this for MIPS EABI */
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x80) == 0) fci->num_args = 4;
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x40) == 0) fci->num_args = 3;
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x20) == 0) fci->num_args = 2;
|
||||
else if ((PROC_REG_MASK(proc_desc) & 0x10) == 0) fci->num_args = 1;
|
||||
fci->num_args = -1; /* assume we can't tell how many args for now */
|
||||
for (regnum = MIPS_LAST_ARG_REGNUM; regnum >= A0_REGNUM; regnum--)
|
||||
{
|
||||
if (PROC_REG_MASK(proc_desc) & (1 << regnum))
|
||||
{
|
||||
fci->num_args = regnum - A0_REGNUM + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -841,8 +871,8 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
|
||||
/* Allocate descriptors for each argument, plus some extras for the
|
||||
dummies we will create to zero-fill the holes left when we align
|
||||
arguments passed in registers that are smaller than a register. */
|
||||
mips_args = /* FIXME! Should this 4 be increased for MIPS64? */
|
||||
(struct mips_arg*) alloca ((nargs + 4) * sizeof (struct mips_arg));
|
||||
mips_args =
|
||||
(struct mips_arg*) alloca ((nargs + MIPS_NUM_ARG_REGS) * sizeof (struct mips_arg));
|
||||
|
||||
/* Build up the list of argument descriptors. */
|
||||
for (i = 0, m_arg = mips_args; i < nargs; i++, m_arg++) {
|
||||
@ -852,7 +882,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
|
||||
* on 8-byte boundaries. It still isn't quite right, because MIPS decided
|
||||
* to align 'struct {int a, b}' on 4-byte boundaries (even though this
|
||||
* breaks their varargs implementation...). A correct solution
|
||||
* requires an simulation of gcc's 'alignof' (and use of 'alignof'
|
||||
* requires a simulation of gcc's 'alignof' (and use of 'alignof'
|
||||
* in stdarg.h/varargs.h).
|
||||
* On the 64 bit r4000 we always pass the first four arguments
|
||||
* using eight bytes each, so that we can load them up correctly
|
||||
@ -867,19 +897,17 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
|
||||
accumulate_size = ALIGN (accumulate_size + len, 4);
|
||||
else
|
||||
{
|
||||
/* If the argument is being passed on the stack, not a register,
|
||||
adjust the size of the argument upward to account for stack
|
||||
alignment. The EABI allows 8 arguments to be passed in
|
||||
registers; the old ABI allows only four. This code seems
|
||||
bogus to me: shouldn't we be right-aligning small arguments
|
||||
as we do below for the args-in-registers case? FIXME!! */
|
||||
#if MIPS_EABI
|
||||
if (accumulate_size >= 8 * MIPS_REGSIZE) /* Ignores FP. FIXME!! */
|
||||
/* The following test attempts to determine if the argument
|
||||
is being passed on the stack. But it fails account for
|
||||
floating point arguments in the EABI, which should have their
|
||||
own accumulated size separate from that for integer arguments.
|
||||
FIXME!! */
|
||||
if (accumulate_size >= MIPS_NUM_ARG_REGS * MIPS_REGSIZE)
|
||||
/* The argument is being passed on the stack, not a register,
|
||||
so adjust the size of the argument upward to account for stack
|
||||
alignment. But shouldn't we be right-aligning small arguments
|
||||
as we do below for the args-in-registers case? FIXME!! */
|
||||
accumulate_size = ALIGN (accumulate_size + len, 8);
|
||||
#else
|
||||
if (accumulate_size >= 4 * MIPS_REGSIZE)
|
||||
accumulate_size = ALIGN (accumulate_size + len, 4);
|
||||
#endif
|
||||
else
|
||||
{
|
||||
if (len < MIPS_REGSIZE)
|
||||
@ -946,7 +974,7 @@ mips_push_dummy_frame()
|
||||
struct linked_proc_info *link = (struct linked_proc_info*)
|
||||
xmalloc(sizeof(struct linked_proc_info));
|
||||
mips_extra_func_info_t proc_desc = &link->info;
|
||||
CORE_ADDR sp = read_register (SP_REGNUM);
|
||||
CORE_ADDR sp = ADDR_BITS_REMOVE (read_register (SP_REGNUM));
|
||||
CORE_ADDR old_sp = sp;
|
||||
link->next = linked_proc_desc_table;
|
||||
linked_proc_desc_table = link;
|
||||
@ -954,13 +982,9 @@ mips_push_dummy_frame()
|
||||
/* FIXME! are these correct ? */
|
||||
#define PUSH_FP_REGNUM 16 /* must be a register preserved across calls */
|
||||
#define GEN_REG_SAVE_MASK MASK(1,16)|MASK(24,28)|(1<<(MIPS_NUMREGS-1))
|
||||
#define GEN_REG_SAVE_COUNT 22
|
||||
#define FLOAT_REG_SAVE_MASK MASK(0,19)
|
||||
#define FLOAT_REG_SAVE_COUNT 20
|
||||
#define FLOAT_SINGLE_REG_SAVE_MASK \
|
||||
((1<<18)|(1<<16)|(1<<14)|(1<<12)|(1<<10)|(1<<8)|(1<<6)|(1<<4)|(1<<2)|(1<<0))
|
||||
#define FLOAT_SINGLE_REG_SAVE_COUNT 10
|
||||
#define SPECIAL_REG_SAVE_COUNT 4
|
||||
/*
|
||||
* The registers we must save are all those not preserved across
|
||||
* procedure calls. Dest_Reg (see tm-mips.h) must also be saved.
|
||||
@ -1186,7 +1210,7 @@ mips_frame_num_args (frame)
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Is this a branch with a delay slot? */
|
||||
|
||||
static int is_delayed PARAMS ((unsigned long));
|
||||
@ -1210,12 +1234,12 @@ int
|
||||
mips_step_skips_delay (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
char buf[4]; /* FIXME!! */
|
||||
char buf[MIPS_INSTLEN];
|
||||
|
||||
if (target_read_memory (pc, buf, 4) != 0) /* FIXME!! */
|
||||
if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
|
||||
/* If error reading memory, guess that it is not a delayed branch. */
|
||||
return 0;
|
||||
return is_delayed ((unsigned long)extract_unsigned_integer (buf, 4)); /* FIXME */
|
||||
return is_delayed ((unsigned long)extract_unsigned_integer (buf, MIPS_INSTLEN));
|
||||
}
|
||||
|
||||
/* To skip prologues, I use this predicate. Returns either PC itself
|
||||
@ -1253,7 +1277,7 @@ mips_skip_prologue (pc, lenient)
|
||||
/* Skip the typical prologue instructions. These are the stack adjustment
|
||||
instruction and the instructions that save registers on the stack
|
||||
or in the gcc frame. */
|
||||
for (offset = 0; offset < 100; offset += MIPS_INSTLEN) /* FIXME!! */
|
||||
for (offset = 0; offset < 100; offset += MIPS_INSTLEN)
|
||||
{
|
||||
char buf[MIPS_INSTLEN];
|
||||
int status;
|
||||
@ -1268,6 +1292,7 @@ mips_skip_prologue (pc, lenient)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* Must add cases for 64-bit operations. FIXME!! */
|
||||
if ((inst & 0xffff0000) == 0x27bd0000) /* addiu $sp,$sp,offset */
|
||||
seen_sp_adjust = 1;
|
||||
else if (inst == 0x03a1e823 || /* subu $sp,$sp,$at */
|
||||
|
@ -1184,7 +1184,7 @@ mips_request (cmd, addr, data, perr, timeout, buff)
|
||||
{
|
||||
if (mips_need_reply)
|
||||
fatal ("mips_request: Trying to send command before reply");
|
||||
sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, paddr(addr), paddr(data));
|
||||
sprintf (buff, "0x0 %c 0x%s 0x%s", cmd, paddr_nz (addr), paddr_nz (data));
|
||||
mips_send_packet (buff, 1);
|
||||
mips_need_reply = 1;
|
||||
}
|
||||
@ -1968,7 +1968,7 @@ mips_fetch_word (addr)
|
||||
mips_receive_wait, NULL);
|
||||
if (err)
|
||||
mips_error ("Can't read address 0x%s: %s",
|
||||
paddr(addr), safe_strerror (errno));
|
||||
paddr_nz (addr), safe_strerror (errno));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@ -2340,7 +2340,9 @@ pmon_remove_breakpoint (addr, contents_cache)
|
||||
|
||||
if (bpnum >= PMON_MAX_BP)
|
||||
{
|
||||
fprintf_unfiltered (stderr, "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n", paddr(addr));
|
||||
fprintf_unfiltered (stderr,
|
||||
"pmon_remove_breakpoint: Failed to find breakpoint at address 0x%s\n",
|
||||
paddr_nz (addr));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2471,9 +2473,10 @@ common_breakpoint (cmd, addr, mask, flags)
|
||||
int nfields;
|
||||
|
||||
if (flags)
|
||||
sprintf (buf, "0x0 %c 0x%s 0x%s %s", cmd, paddr (addr), paddr (mask), flags);
|
||||
sprintf (buf, "0x0 %c 0x%s 0x%s %s", cmd, paddr_nz (addr), paddr_nz (mask),
|
||||
flags);
|
||||
else
|
||||
sprintf (buf, "0x0 %c 0x%s", cmd, paddr (addr));
|
||||
sprintf (buf, "0x0 %c 0x%s", cmd, paddr_nz (addr));
|
||||
|
||||
mips_send_packet (buf, 1);
|
||||
|
||||
@ -2494,7 +2497,7 @@ common_breakpoint (cmd, addr, mask, flags)
|
||||
rresponse = rerrflg;
|
||||
if (rresponse != 22) /* invalid argument */
|
||||
fprintf_unfiltered (stderr, "common_breakpoint (0x%s): Got error: 0x%x\n",
|
||||
paddr(addr), rresponse);
|
||||
paddr_nz (addr), rresponse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2906,6 +2909,20 @@ pmon_start_download ()
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mips_expect_download (char *string)
|
||||
{
|
||||
if (!mips_expect (string))
|
||||
{
|
||||
fprintf_unfiltered (gdb_stderr, "Load did not complete successfully.\n");
|
||||
if (tftp_in_use)
|
||||
remove (tftp_localname); /* Remove temporary file */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
pmon_end_download (final, bintotal)
|
||||
int final;
|
||||
@ -2937,9 +2954,12 @@ pmon_end_download (final, bintotal)
|
||||
strcat (cmd, "\r");
|
||||
mips_send_command (cmd, 0);
|
||||
free (cmd);
|
||||
mips_expect ("Downloading from ");
|
||||
mips_expect (tftp_name);
|
||||
mips_expect (", ^C to abort\r\n");
|
||||
if (!mips_expect_download ("Downloading from "))
|
||||
return;
|
||||
if (!mips_expect_download (tftp_name))
|
||||
return;
|
||||
if (!mips_expect_download (", ^C to abort\r\n"))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for the stuff that PMON prints after the load has completed.
|
||||
@ -2953,8 +2973,8 @@ pmon_end_download (final, bintotal)
|
||||
mips_expect ("\r\ntotal = 0x");
|
||||
sprintf (hexnumber,"%x",bintotal);
|
||||
mips_expect (hexnumber);
|
||||
if (!mips_expect (" bytes\r\n"))
|
||||
fprintf_unfiltered (gdb_stderr, "Load did not complete successfully.\n");
|
||||
if (!mips_expect_download (" bytes\r\n"))
|
||||
return;
|
||||
|
||||
if (tftp_in_use)
|
||||
remove (tftp_localname); /* Remove temporary file */
|
||||
|
Loading…
x
Reference in New Issue
Block a user