diff options
author | Ian Lance Taylor <ian@airs.com> | 1993-12-06 17:31:05 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1993-12-06 17:31:05 +0000 |
commit | e03c0cc67016bb6c50add63e0176a4c3cd0f011e (patch) | |
tree | 3bae27291c07e86bf4459bc93f88dd61d25f4f95 /gdb/mips-tdep.c | |
parent | a17535c780bc66cecbfaa51a8bdcc9bbfb27bcaf (diff) | |
download | gdb-e03c0cc67016bb6c50add63e0176a4c3cd0f011e.zip gdb-e03c0cc67016bb6c50add63e0176a4c3cd0f011e.tar.gz gdb-e03c0cc67016bb6c50add63e0176a4c3cd0f011e.tar.bz2 |
Added Irix 5 support.
* configure.in (mips-sgi-irix5*): New host and target. Use irix5
for both.
* config/mips/irix5.mh, config/mips/irix5.mt,
config/mips/xm-irix5.h, config/mips/nm-irix5.h,
config/mips/tm-irix5.h, irix5-nat.c: New files for Irix 5 support.
* mdebugread.c: New file, split out of mipsread.c. Added
elfmdebug_build_psymtabs routine. Added some checks on external
symbols. Changed code to keep ecoff_debug_info and
ecoff_debug_swap structs in the psymtab and in global pointers
rather than retrieving them from the bfd. Also changed to keep
the pending list with the psymtab rather than the objfile (each
psymtab for a single objfile points to the same pending list).
* mipsread.c: Bulk of file moved into mdebugread.c, leaving just
the sym_fns.
* Makefile.in (SFILES): Added mdebugread.c.
(OBS): Added mdebugread.o.
(mdebugread.o): New target.
* symfile.h: Declare mdebug_build_psymtabs and
elfmdebug_build_psymtabs.
* elfread.c (struct elfinfo): Added mdebugsect field.
(elf_locate_sections): Remember location of .mdebug section.
(elf_symfile_read): Call elfmdebug_build_psymtabs on .mdebug
section.
* infrun.c (AT_FUNCTION_START): Set to 0 if not already defined.
(wait_for_inferior): Use AT_FUNCTION_START if it is defined to see
if PC is at the start of a function.
* mips-tdep.c (read_next_frame_reg): Use SIGFRAME_REG_SIZE, and
give it a default definition.
(mips_skip_prologue): Skip instructions which initialize $gp
register.
(in_sigtramp): New procedure, moved in from mipsread.c.
* config/mips/tm-mips.h: Declare in_sigtramp.
Diffstat (limited to 'gdb/mips-tdep.c')
-rw-r--r-- | gdb/mips-tdep.c | 199 |
1 files changed, 111 insertions, 88 deletions
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index c5f870f..454ab73 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -78,17 +78,19 @@ read_next_frame_reg(fi, regno) /* If it is the frame for sigtramp we have a complete sigcontext immediately below the frame and we get the saved registers from there. If the stack layout for sigtramp changes we might have to change these - constants and the companion fixup_sigtramp in mipsread.c */ + constants and the companion fixup_sigtramp in mdebugread.c */ #ifndef SIGFRAME_BASE #define SIGFRAME_BASE 0x12c /* sizeof(sigcontext) */ #define SIGFRAME_PC_OFF (-SIGFRAME_BASE + 2 * 4) #define SIGFRAME_REGSAVE_OFF (-SIGFRAME_BASE + 3 * 4) +#define SIGFRAME_REG_SIZE 4 #endif for (; fi; fi = fi->next) if (in_sigtramp(fi->pc, 0)) { int offset; if (regno == PC_REGNUM) offset = SIGFRAME_PC_OFF; - else if (regno < 32) offset = SIGFRAME_REGSAVE_OFF + regno * 4; + else if (regno < 32) offset = (SIGFRAME_REGSAVE_OFF + + regno * SIGFRAME_REG_SIZE); else return 0; return read_memory_integer(fi->frame + offset, 4); } @@ -185,7 +187,7 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame) CORE_ADDR cur_pc; int frame_size; int has_frame_reg = 0; - int reg30; /* Value of $r30. Used by gcc for frame-pointer */ + int reg30 = 0; /* Value of $r30. Used by gcc for frame-pointer */ unsigned long reg_mask = 0; if (start_pc == 0) return NULL; @@ -224,7 +226,7 @@ heuristic_proc_desc(start_pc, limit_pc, next_frame) alloca_adjust = reg30 - (sp + (word & 0xffff)); if (alloca_adjust > 0) { /* FP > SP + frame_size. This may be because - /* of an alloca or somethings similar. + * of an alloca or somethings similar. * Fix sp to "pre-alloca" value, and try again. */ sp += alloca_adjust; @@ -376,7 +378,6 @@ init_extra_frame_info(fci) { int ireg; CORE_ADDR reg_position; - unsigned long mask; /* r0 bit means kernel trap */ int kernel_trap = PROC_REG_MASK(proc_desc) & 1; @@ -390,99 +391,101 @@ init_extra_frame_info(fci) if (proc_desc == &temp_proc_desc) *fci->saved_regs = temp_saved_regs; - else if (/* In any frame other than the innermost, we assume that all - registers have been saved. This assumes that all register - saves in a function happen before the first function - call. */ - fci->next != NULL - - /* In a dummy frame we know exactly where things are saved. */ - || PROC_DESC_IS_DUMMY (proc_desc) - - /* Not sure exactly what kernel_trap means, but if it means - the kernel saves the registers without a prologue doing it, - we better not examine the prologue to see whether registers - have been saved yet. */ - || kernel_trap) + else { - /* All the registers which will be saved have been saved, so we - can believe the proc_desc. */ - - /* find which general-purpose registers were saved */ - reg_position = fci->frame + PROC_REG_OFFSET(proc_desc); - mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc); - for (ireg= 31; mask; --ireg, mask <<= 1) - if (mask & 0x80000000) + /* What registers have been saved? Bitmasks. */ + unsigned long gen_mask, float_mask; + + gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK(proc_desc); + float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc); + + if (/* In any frame other than the innermost, we assume that all + registers have been saved. This assumes that all register + saves in a function happen before the first function + call. */ + fci->next == NULL + + /* In a dummy frame we know exactly where things are saved. */ + && !PROC_DESC_IS_DUMMY (proc_desc) + + /* Not sure exactly what kernel_trap means, but if it means + the kernel saves the registers without a prologue doing it, + we better not examine the prologue to see whether registers + have been saved yet. */ + && !kernel_trap) + { + /* We need to figure out whether the registers that the proc_desc + claims are saved have been saved yet. */ + + CORE_ADDR addr; + int status; + char buf[4]; + unsigned long inst; + + /* Bitmasks; set if we have found a save for the register. */ + unsigned long gen_save_found = 0; + unsigned long float_save_found = 0; + + for (addr = PROC_LOW_ADDR (proc_desc); + addr < fci->pc && (gen_mask != gen_save_found + || float_mask != float_save_found); + addr += 4) + { + status = read_memory_nobpt (addr, buf, 4); + if (status) + memory_error (status, addr); + inst = extract_unsigned_integer (buf, 4); + if (/* sw reg,n($sp) */ + (inst & 0xffe00000) == 0xafa00000 + + /* sw reg,n($r30) */ + || (inst & 0xffe00000) == 0xafc00000) + { + /* It might be possible to use the instruction to + find the offset, rather than the code below which + is based on things being in a certain order in the + frame, but figuring out what the instruction's offset + is relative to might be a little tricky. */ + int reg = (inst & 0x001f0000) >> 16; + gen_save_found |= (1 << reg); + } + else if (/* swc1 freg,n($sp) */ + (inst & 0xffe00000) == 0xe7a00000 + + /* swc1 freg,n($r30) */ + || (inst & 0xffe00000) == 0xe7c00000) + { + int reg = ((inst & 0x001f0000) >> 16); + float_save_found |= (1 << reg); + } + } + gen_mask = gen_save_found; + float_mask = float_save_found; + } + + /* Fill in the offsets for the registers which gen_mask says + were saved. */ + reg_position = fci->frame + PROC_REG_OFFSET (proc_desc); + for (ireg= 31; gen_mask; --ireg, gen_mask <<= 1) + if (gen_mask & 0x80000000) { fci->saved_regs->regs[ireg] = reg_position; reg_position -= 4; } - /* find which floating-point registers were saved */ - reg_position = fci->frame + PROC_FREG_OFFSET(proc_desc); + /* Fill in the offsets for the registers which float_mask says + were saved. */ + reg_position = fci->frame + PROC_FREG_OFFSET (proc_desc); /* The freg_offset points to where the first *double* register is saved. So skip to the high-order word. */ reg_position += 4; - mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK(proc_desc); - for (ireg = 31; mask; --ireg, mask <<= 1) - if (mask & 0x80000000) + for (ireg = 31; float_mask; --ireg, float_mask <<= 1) + if (float_mask & 0x80000000) { fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position; reg_position -= 4; } } - else - { - /* We need to figure out whether the registers that the proc_desc - claims are saved have been saved yet. */ - - CORE_ADDR addr; - int status; - char buf[4]; - unsigned long inst; - /* Bitmasks; set if the proc_desc claims the register is saved and we - haven't found a save instruction for it yet. */ - unsigned long gen_mask, float_mask; - - gen_mask = PROC_REG_MASK (proc_desc); - float_mask = PROC_FREG_MASK (proc_desc); - - for (addr = PROC_LOW_ADDR (proc_desc); - addr < fci->pc && (gen_mask | float_mask); - addr += 4) - { - status = read_memory_nobpt (addr, buf, 4); - if (status) - memory_error (status, addr); - inst = extract_unsigned_integer (buf, 4); - if (/* sw reg,n($sp) */ - (inst & 0xffe00000) == 0xafa00000 - - /* sw reg,n($r30) */ - || (inst & 0xffe00000) == 0xafc00000) - { - /* We assume that all saves are relative to the - PROC_FRAME_REG, which is what we used to set up - ->frame. */ - int reg = (inst & 0x001f0000) >> 16; - if (gen_mask & (1 << reg)) - fci->saved_regs.regs[reg] = fci->frame + (inst & 0xffff); - gen_mask &= ~(1 << reg); - } - else if (/* swc1 freg,n($sp) */ - (inst & 0xffe00000) == 0xe7a00000 - - /* swc1 freg,n($r30) */ - (inst & 0xffe00000) == 0xe7c00000) - { - int reg = ((inst & 0x001f0000) >> 16); - if (float_mask & (1 << reg)) - fci->saved_regs.regs[FP0_REGNUM + reg] - = fci->frame + (inst & 0xffff); - float_mask &= ~(1 << reg); - } - } - } /* hack: if argument regs are saved, guess these contain args */ if ((PROC_REG_MASK(proc_desc) & 0xF0) == 0) fci->num_args = -1; @@ -566,7 +569,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr) } /* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */ -#define MASK(i,j) ((1 << (j)+1)-1 ^ (1 << (i))-1) +#define MASK(i,j) (((1 << ((j)+1))-1) ^ ((1 << (i))-1)) void mips_push_dummy_frame() @@ -713,7 +716,6 @@ mips_print_register (regnum, all) int regnum, all; { unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE]; - REGISTER_TYPE val; /* Get the data in raw format. */ if (read_relative_register_raw_bytes (regnum, raw_buffer)) @@ -847,8 +849,6 @@ mips_skip_prologue (pc, lenient) CORE_ADDR pc; int lenient; { - struct symbol *f; - struct block *b; unsigned long inst; int offset; int seen_sp_adjust = 0; @@ -885,6 +885,13 @@ mips_skip_prologue (pc, lenient) continue; else if ((inst & 0xFF9F07FF) == 0x00800021) /* move reg,$a0-$a3 */ continue; + else if ((inst & 0xffff0000) == 0x3c1c0000) /* lui $gp,n */ + continue; + else if ((inst & 0xffff0000) == 0x279c0000) /* addiu $gp,$gp,n */ + continue; + else if (inst == 0x0399e021 /* addu $gp,$gp,$t9 */ + || inst == 0x033ce021) /* addu $gp,$t9,$gp */ + continue; else break; } @@ -976,6 +983,22 @@ mips_store_return_value (valtype, valbuf) write_register_bytes(REGISTER_BYTE (regnum), raw_buffer, TYPE_LENGTH (valtype)); } +/* These exist in mdebugread.c. */ +extern CORE_ADDR sigtramp_address, sigtramp_end; +extern void fixup_sigtramp PARAMS ((void)); + +/* Exported procedure: Is PC in the signal trampoline code */ + +int +in_sigtramp (pc, ignore) + CORE_ADDR pc; + char *ignore; /* function name */ +{ + if (sigtramp_address == 0) + fixup_sigtramp (); + return (pc >= sigtramp_address && pc < sigtramp_end); +} + static void reinit_frame_cache_sfunc PARAMS ((char *, int, struct cmd_list_element *)); |