From ac9548059b9ca25c3d990925a6b0602ae932637b Mon Sep 17 00:00:00 2001 From: Stu Grossman Date: Tue, 15 Oct 1996 23:44:13 +0000 Subject: * buildsym.c (finish_block): Treat LOC_BASEREG_ARG and LOC_LOCAL_ARG as arguments so that GDB will know about function args declared this way. Mostly affects dwarf. * dwarfread.c (decode_die_type): Change default type from int to void. This allows GDB to recognize void functions. * (new_symbol): If AT_PROTOTYPED is present, set a flag in the type structure. * findvar.c (extract_floating store_floating): Clean up comments to reflect reality. * gdbtypes.h: Add TYPE_FLAG_PROTOTYPED so that we can tell if a function has a prototype. Currently, only dwarf supports this. * utils.c (floatformat_from_doublest): Fix logic error with converting from double to float. (It wasn't shifting mant_long if it had a hidden bit.) * v850-tdep.c: Add support for function calling. Fix some problems with debugging code w/o debug symbols. * config/v850/tm-v850.h: Ditto. --- gdb/ChangeLog | 26 +++++- gdb/buildsym.c | 8 +- gdb/config/v850/tm-v850.h | 33 ++++++++ gdb/dwarfread.c | 4 +- gdb/gdbtypes.h | 6 ++ gdb/v850-tdep.c | 204 ++++++++++++++++++++++++++++++++++++++++------ 6 files changed, 247 insertions(+), 34 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c1f5a87..1199419 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +Tue Oct 15 16:30:07 1996 Stu Grossman (grossman@critters.cygnus.com) + + * buildsym.c (finish_block): Treat LOC_BASEREG_ARG and + LOC_LOCAL_ARG as arguments so that GDB will know about function + args declared this way. Mostly affects dwarf. + * dwarfread.c (decode_die_type): Change default type from int to + void. This allows GDB to recognize void functions. + * (new_symbol): If AT_PROTOTYPED is present, set a flag in the + type structure. + * findvar.c (extract_floating store_floating): Clean up comments + to reflect reality. + * gdbtypes.h: Add TYPE_FLAG_PROTOTYPED so that we can tell if a + function has a prototype. Currently, only dwarf supports this. + * utils.c (floatformat_from_doublest): Fix logic error with + converting from double to float. (It wasn't shifting mant_long if + it had a hidden bit.) + +start-sanitize-v850 + * v850-tdep.c: Add support for function calling. Fix some + problems with debugging code w/o debug symbols. + * config/v850/tm-v850.h: Ditto. +end-sanitize-v850 Tue Oct 15 18:19:42 1996 Ian Lance Taylor * utils.c: Always ensure that size_t is defined. Check @@ -16,8 +38,8 @@ Sun Oct 13 11:38:25 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) Fri Oct 11 15:43:54 1996 Stu Grossman (grossman@critters.cygnus.com) - * frame.h: Move definition of struct frame_saved_args to before - struct frame to make it possible to use frame_saved_args in + * frame.h: Move definition of struct frame_saved_regs to before + struct frame to make it possible to use frame_saved_regs in EXTRA_FRAME_INFO macro. start-sanitize-v850 diff --git a/gdb/buildsym.c b/gdb/buildsym.c index e28c727..02d7dfc 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -268,6 +268,8 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile) case LOC_REF_ARG: case LOC_REGPARM: case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + case LOC_LOCAL_ARG: nparams++; break; case LOC_UNDEF: @@ -279,9 +281,7 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile) case LOC_LABEL: case LOC_BLOCK: case LOC_CONST_BYTES: - case LOC_LOCAL_ARG: case LOC_BASEREG: - case LOC_BASEREG_ARG: case LOC_UNRESOLVED: case LOC_OPTIMIZED_OUT: default: @@ -303,6 +303,8 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile) case LOC_REF_ARG: case LOC_REGPARM: case LOC_REGPARM_ADDR: + case LOC_BASEREG_ARG: + case LOC_LOCAL_ARG: TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym); iparams++; break; @@ -315,9 +317,7 @@ finish_block (symbol, listhead, old_blocks, start, end, objfile) case LOC_LABEL: case LOC_BLOCK: case LOC_CONST_BYTES: - case LOC_LOCAL_ARG: case LOC_BASEREG: - case LOC_BASEREG_ARG: case LOC_UNRESOLVED: case LOC_OPTIMIZED_OUT: default: diff --git a/gdb/config/v850/tm-v850.h b/gdb/config/v850/tm-v850.h index 5aa11b5..9bd1b48 100644 --- a/gdb/config/v850/tm-v850.h +++ b/gdb/config/v850/tm-v850.h @@ -68,6 +68,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ struct frame_info; struct frame_saved_regs; struct type; +struct value; #endif #define EXTRA_FRAME_INFO struct frame_saved_regs fsr; @@ -106,3 +107,35 @@ extern CORE_ADDR v850_skip_prologue PARAMS ((CORE_ADDR pc)); extern struct frame_info *v850_pop_frame PARAMS ((struct frame_info *frame)); #define POP_FRAME v850_pop_frame (get_current_frame ()) + +#define CALL_DUMMY { 0 } + +#define CALL_DUMMY_START_OFFSET (0) + +#define CALL_DUMMY_BREAKPOINT_OFFSET (0) + +extern void v850_push_dummy_frame PARAMS ((void)); +#define PUSH_DUMMY_FRAME v850_push_dummy_frame () + +#define FIX_CALL_DUMMY(DUMMY1, START_SP, FUNADDR, NARGS, ARGS, VALUE_TYPE, USING_GCC) + +#define CALL_DUMMY_LOCATION AT_ENTRY_POINT + +#define STACK_ALIGN(x) ((x + 3) & ~3) + +extern CORE_ADDR +v850_push_arguments PARAMS ((int nargs, struct value **args, CORE_ADDR sp, + unsigned char struct_return, + CORE_ADDR struct_addr)); +#define PUSH_ARGUMENTS(NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) \ + (SP) = v850_push_arguments (NARGS, ARGS, SP, STRUCT_RETURN, STRUCT_ADDR) + +#define STORE_STRUCT_RETURN(STRUCT_ADDR, SP) + +#define CALL_DUMMY_ADDRESS() (entry_point_address ()) + +extern int v850_pc_in_call_dummy PARAMS ((CORE_ADDR pc)); +#define PC_IN_CALL_DUMMY(PC, SP, FP) v850_pc_in_call_dummy (PC) + +#define USE_STRUCT_CONVENTION(GCC_P, TYPE) \ + (TYPE_NFIELDS (TYPE) > 1 || TYPE_LENGTH (TYPE) > 4) diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index 98ceb49..529f01b 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -964,7 +964,7 @@ decode_die_type (dip) } else { - type = dwarf_fundamental_type (current_objfile, FT_INTEGER); + type = dwarf_fundamental_type (current_objfile, FT_VOID); } return (type); } @@ -2957,6 +2957,8 @@ new_symbol (dip, objfile) case TAG_subroutine: SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc; SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym)); + if (dip -> at_prototyped) + TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED; SYMBOL_CLASS (sym) = LOC_BLOCK; if (dip -> die_tag == TAG_global_subroutine) { diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 3a40f1c..a7d8c39 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -154,6 +154,12 @@ enum type_code #define TYPE_FLAG_TARGET_STUB (1 << 3) +/* This is a function type which appears to have a prototype. We need this + for function calls in order to tell us if it's necessary to coerce the args, + or to just do the standard conversions. */ + +#define TYPE_FLAG_PROTOTYPED (1 << 4) + struct type { diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index 7363fc2..7e6b431 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -1,6 +1,5 @@ /* Target-dependent code for the NEC V850 for GDB, the GNU debugger. - Copyright 1986, 1996 - Free Software Foundation, Inc. + Copyright 1996, Free Software Foundation, Inc. This file is part of GDB. @@ -18,8 +17,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* ??? Support for calling functions from gdb in sparc64 is unfinished. */ - #include "defs.h" #include "frame.h" #include "inferior.h" @@ -28,9 +25,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "value.h" #include "bfd.h" #include "gdb_string.h" - #include "gdbcore.h" +struct dummy_frame +{ + struct dummy_frame *next; + + CORE_ADDR fp; + CORE_ADDR sp; + CORE_ADDR rp; + CORE_ADDR pc; +}; + +static struct dummy_frame *dummy_frame_stack = NULL; /* This function actually figures out the frame address for a given pc and sp. This is tricky on the v850 because we only use an explicit frame @@ -49,7 +56,7 @@ v850_init_extra_frame_info (fi) int framereg; if (fi->next) - fi->pc = v850_find_callers_reg (fi->next, RP_REGNUM); + fi->pc = FRAME_SAVED_PC (fi->next); /* First, figure out the bounds of the prologue so that we can limit the search to something reasonable. */ @@ -58,7 +65,10 @@ v850_init_extra_frame_info (fi) { sal = find_pc_line (func_addr, 0); - prologue_end = sal.end; + if (sal.line == 0) + prologue_end = fi->pc; + else + prologue_end = sal.end; } else prologue_end = func_addr + 100; /* We're in the boondocks */ @@ -108,21 +118,10 @@ v850_init_extra_frame_info (fi) } } -#if 0 - if (!fi->next) - fi->frame = read_register (framereg); - else - if (framereg == SP_REGNUM) - fi->frame = fi->next->frame; - else - fi->frame = v850_find_callers_reg (fi, framereg); - - if (framereg == SP_REGNUM) - fi->frame -= frameoffset; -#else - if (!fi->next && framereg == SP_REGNUM) + if (PC_IN_CALL_DUMMY (fi->pc, NULL, NULL)) + fi->frame = dummy_frame_stack->sp; + else if (!fi->next && framereg == SP_REGNUM) fi->frame = read_register (framereg) - frameoffset; -#endif for (reg = 0; reg < NUM_REGS; reg++) if (fi->fsr.regs[reg] != 0) @@ -137,6 +136,24 @@ v850_find_callers_reg (fi, regnum) struct frame_info *fi; int regnum; { + /* XXX - Won't work if multiple dummy frames are active */ + if (PC_IN_CALL_DUMMY (fi->pc, NULL, NULL)) + switch (regnum) + { + case SP_REGNUM: + return dummy_frame_stack->sp; + break; + case FP_REGNUM: + return dummy_frame_stack->fp; + break; + case RP_REGNUM: + return dummy_frame_stack->pc; + break; + case PC_REGNUM: + return dummy_frame_stack->pc; + break; + } + for (; fi; fi = fi->next) if (fi->fsr.regs[regnum] != 0) return read_memory_integer (fi->fsr.regs[regnum], 4); @@ -149,13 +166,15 @@ v850_frame_chain (fi) struct frame_info *fi; { CORE_ADDR callers_pc, callers_sp; - struct frame_info temp_fi; CORE_ADDR func_addr, prologue_end, current_pc; int frameoffset; /* First, find out who called us */ - callers_pc = v850_find_callers_reg (fi, RP_REGNUM); + callers_pc = FRAME_SAVED_PC (fi); + + if (PC_IN_CALL_DUMMY (callers_pc, NULL, NULL)) + return dummy_frame_stack->sp; /* XXX Won't work if multiple dummy frames on stack! */ /* Next, figure out where his prologue is. */ @@ -163,9 +182,16 @@ v850_frame_chain (fi) { struct symtab_and_line sal; + /* Stop when the caller is the entry point function */ + if (func_addr == entry_point_address ()) + return 0; + sal = find_pc_line (func_addr, 0); - prologue_end = sal.end; + if (sal.line == 0) + prologue_end = callers_pc; + else + prologue_end = sal.end; } else prologue_end = func_addr + 100; /* We're in the boondocks */ @@ -217,11 +243,12 @@ v850_skip_prologue (pc) sal = find_pc_line (func_addr, 0); - if (sal.end < func_end) + if (sal.line != 0 && sal.end < func_end) return sal.end; else - /* The line after the prologue is after the end of the function. In - this case, there probably isn't a prologue. */ + /* Either there's no line info, or the line after the prologue is after + the end of the function. In this case, there probably isn't a + prologue. */ return pc; } @@ -229,12 +256,60 @@ v850_skip_prologue (pc) return pc; } +/* All we do here is record SP and FP on the call dummy stack */ + +void +v850_push_dummy_frame () +{ + struct dummy_frame *dummy_frame; + + dummy_frame = xmalloc (sizeof (struct dummy_frame)); + + dummy_frame->fp = read_register (FP_REGNUM); + dummy_frame->sp = read_register (SP_REGNUM); + dummy_frame->rp = read_register (RP_REGNUM); + dummy_frame->pc = read_register (PC_REGNUM); + dummy_frame->next = dummy_frame_stack; + dummy_frame_stack = dummy_frame; +} + +int +v850_pc_in_call_dummy (pc) + CORE_ADDR pc; +{ + return dummy_frame_stack + && pc >= CALL_DUMMY_ADDRESS () + && pc <= CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK; +} + struct frame_info * v850_pop_frame (frame) struct frame_info *frame; { int regnum; + if (PC_IN_CALL_DUMMY (frame->pc, NULL, NULL)) + { + struct dummy_frame *dummy_frame; + + dummy_frame = dummy_frame_stack; + if (!dummy_frame) + error ("Can't pop dummy frame!"); + + dummy_frame_stack = dummy_frame->next; + + write_register (FP_REGNUM, dummy_frame->fp); + write_register (SP_REGNUM, dummy_frame->sp); + write_register (RP_REGNUM, dummy_frame->rp); + write_register (PC_REGNUM, dummy_frame->pc); + + free (dummy_frame); + + flush_cached_frames (); + + return NULL; + } + write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); for (regnum = 0; regnum < NUM_REGS; regnum++) @@ -246,6 +321,81 @@ v850_pop_frame (frame) return NULL; } + +/* Put arguments in the right places, and setup return address register (RP) to + point at a convenient place to put a breakpoint. First four args go in + R6->R9, subsequent args go into sp + 16 -> sp + ... Structs are passed by + reference. 64 bit quantities (doubles and long longs) may be split between + the regs and the stack. When calling a function that returns a struct, a + pointer to the struct is passed in as a secret first argument (always in R6). + + By the time we get here, stack space has been allocated for the args, but + not for the struct return pointer. */ + +CORE_ADDR +v850_push_arguments (nargs, args, sp, struct_return, struct_addr) + int nargs; + value_ptr *args; + CORE_ADDR sp; + unsigned char struct_return; + CORE_ADDR struct_addr; +{ + int argreg; + int argnum; + + argreg = 6; + + if (struct_return) + { + write_register (argreg++, struct_addr); + sp -= 4; + } + + for (argnum = 0; argnum < nargs; argnum++) + { + int len; + char *val; + char valbuf[4]; + + if (TYPE_CODE (VALUE_TYPE (*args)) == TYPE_CODE_STRUCT + && TYPE_LENGTH (VALUE_TYPE (*args)) > 8) + { + store_address (valbuf, 4, VALUE_ADDRESS (*args)); + len = 4; + val = valbuf; + } + else + { + len = TYPE_LENGTH (VALUE_TYPE (*args)); + val = (char *)VALUE_CONTENTS (*args); + } + + while (len > 0) + if (argreg <= 9) + { + CORE_ADDR regval; + + regval = extract_address (val, REGISTER_RAW_SIZE (argreg)); + write_register (argreg, regval); + + len -= REGISTER_RAW_SIZE (argreg); + val += REGISTER_RAW_SIZE (argreg); + argreg++; + } + else + { + write_memory (sp + argnum * 4, val, 4); + + len -= 4; + val += 4; + } + args++; + } + + write_register (RP_REGNUM, entry_point_address ()); + + return sp; +} void _initialize_sparc_tdep () -- cgit v1.1