diff options
-rw-r--r-- | gdb/ChangeLog | 16 | ||||
-rw-r--r-- | gdb/defs.h | 15 | ||||
-rw-r--r-- | gdb/doc/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/doc/gdbint.texinfo | 54 | ||||
-rw-r--r-- | gdb/gdbarch.c | 113 | ||||
-rw-r--r-- | gdb/gdbarch.h | 58 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 22 | ||||
-rw-r--r-- | gdb/infcmd.c | 39 | ||||
-rw-r--r-- | gdb/ppc-sysv-tdep.c | 15 | ||||
-rw-r--r-- | gdb/values.c | 103 |
10 files changed, 329 insertions, 113 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 28fa74569dc..bed0fbf1664 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,21 @@ 2003-10-20 Andrew Cagney <cagney@redhat.com> + * values.c (register_value_being_returned): Update comments. Use + "gdbarch_return_value" when available. + (using_struct_return): Ditto. + (set_return_value): Ditto. Use "gdbarch_return_value" when + available.. Print a warning, and not an error, when an unhandled + return type is encountered. + * infcmd.c: Include "gdb_assert.h". + (print_return_value): When gdbarch_return_value_p, and using + struct return, assume that the value is not available. + * defs.h (return_value_convention): Define. + * gdbarch.sh (gdbarch_return_value): New predicate method. + * gdbarch.h, gdbarch.c: Re-generate + * ppc-sysv-tdep.c (return_value_convention): Delete definition. + +2003-10-20 Andrew Cagney <cagney@redhat.com> + * symtab.c: Replace "struct sec" with "struct bfd_section". * objfiles.c, linespec.c, blockframe.c, block.c: Ditto. diff --git a/gdb/defs.h b/gdb/defs.h index 696ee5b4452..c7713b90c34 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -230,6 +230,21 @@ enum auto_boolean AUTO_BOOLEAN_AUTO }; +/* Potential ways that a function can return a value of a given type. */ +enum return_value_convention +{ + /* Where the return value has been squeezed into one or more + registers. */ + RETURN_VALUE_REGISTER_CONVENTION, + /* Commonly known as the "struct return convention". The caller + passes an additional hidden first parameter to the caller. That + parameter contains the address at which the value being returned + should be stored. While typically, and historically, used for + large structs, this is convention is applied to values of many + different types. */ + RETURN_VALUE_STRUCT_CONVENTION +}; + /* the cleanup list records things that have to be undone if an error happens (descriptors to be closed, memory to be freed, etc.) Each link in the chain records a function to call and an diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index d81239f862c..115921d38af 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2003-10-20 Andrew Cagney <cagney@redhat.com> + + * gdbint.texinfo (Target Architecture Definition): Document + gdbarch_return_value. Add cross references from + USE_STRUCT_CONVENTION, EXTRACT_RETURN_VALUE, and + STORE_RETURN_VALUE, and from/to EXTRACT_STRUCT_VALUE_ADDRESS. + 2003-10-18 Mark Kettenis <kettenis@gnu.org> * gdbint.texinfo (Target Architecture Definition): Document diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index e0dcf3541ef..77e2b7eb690 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -3219,13 +3219,17 @@ Define this to extract a function's return value of type @var{type} from the raw register state @var{regbuf} and copy that, in virtual format, into @var{valbuf}. +This method has been deprecated in favour of @code{gdbarch_return_value} +(@pxref{gdbarch_return_value}). + @item EXTRACT_STRUCT_VALUE_ADDRESS(@var{regbuf}) @findex EXTRACT_STRUCT_VALUE_ADDRESS +@anchor{EXTRACT_STRUCT_VALUE_ADDRESS} When defined, extract from the array @var{regbuf} (containing the raw register state) the @code{CORE_ADDR} at which a function should return its structure value. -If not defined, @code{EXTRACT_RETURN_VALUE} is used. +@xref{gdbarch_return_value}. @item EXTRACT_STRUCT_VALUE_ADDRESS_P() @findex EXTRACT_STRUCT_VALUE_ADDRESS_P @@ -3824,6 +3828,48 @@ allocated on the stack. @xref{unwind_dummy_id}. Define this to convert sdb register numbers into @value{GDBN} regnums. If not defined, no conversion will be done. +@item enum return_value_convention gdbarch_return_value (struct gdbarch *@var{gdbarch}, struct type *@var{valtype}, struct regcache *@var{regcache}, const void *@var{inval}, void *@var{outval}) +@findex gdbarch_return_value +@anchor{gdbarch_return_value} Given a function with a return-value of +type @var{rettype}, return which return-value convention that function +would use. + +@value{GDBN} currently recognizes two function return-value conventions: +@code{RETURN_VALUE_REGISTER_CONVENTION} where the return value is found +in registers; and @code{RETURN_VALUE_STRUCT_CONVENTION} where the return +value is found in memory and the address of that memory location is +passed in as the function's first parameter. + +If the register convention is being used, and @var{inval} is +non-@code{NULL}, also copy the return-value in @var{inval} into +@var{regcache}. + +If the register convention is being used, and @var{outval} is +non-@code{NULL}, also copy the return value from @var{regcache} into +@var{outval} (@var{regcache} contains a copy of the registers from the +just returned function). + +@xref{EXTRACT_STRUCT_VALUE_ADDRESS}, for a description of how +return-values that use the struct convention are handled. + +@emph{Maintainer note: This method replaces separate predicate, extract, +store methods. By having only one method, the logic needed to determine +the return-value convention need only be implemented in one place. If +@value{GDBN} were written in an @sc{oo} language, this method would +instead return an object that knew how to perform the register +return-value extract and store.} + +@emph{Maintainer note: This method does not take a @var{gcc_p} +parameter, and such a parameter should not be added. If an architecture +that requires per-compiler or per-function information be identified, +then the replacement of @var{rettype} with @code{struct value} +@var{function} should be persued.} + +@emph{Maintainer note: The @var{regcache} parameter limits this methods +to the inner most frame. While replacing @var{regcache} with a +@code{struct frame_info} @var{frame} parameter would remove that +limitation there has yet to be a demonstrated need for such a change.} + @item SKIP_PERMANENT_BREAKPOINT @findex SKIP_PERMANENT_BREAKPOINT Advance the inferior's PC past a permanent breakpoint. @value{GDBN} normally @@ -3882,6 +3928,9 @@ A C expression that writes the function return value, found in @var{valbuf}, into the @var{regcache}. @var{type} is the type of the value that is to be returned. +This method has been deprecated in favour of @code{gdbarch_return_value} +(@pxref{gdbarch_return_value}). + @item SUN_FIXED_LBRAC_BUG @findex SUN_FIXED_LBRAC_BUG (Used only for Sun-3 and Sun-4 targets.) @@ -4017,6 +4066,9 @@ being considered is known to have been compiled by GCC; this is helpful for systems where GCC is known to use different calling convention than other compilers. +This method has been deprecated in favour of @code{gdbarch_return_value} +(@pxref{gdbarch_return_value}). + @item VALUE_TO_REGISTER(@var{type}, @var{regnum}, @var{from}, @var{to}) @findex VALUE_TO_REGISTER Convert a value of type @var{type} into the raw contents of register diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index feb67256069..1983421d0f3 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -203,16 +203,17 @@ struct gdbarch gdbarch_pointer_to_address_ftype *pointer_to_address; gdbarch_address_to_pointer_ftype *address_to_pointer; gdbarch_integer_to_address_ftype *integer_to_address; - gdbarch_return_value_on_stack_ftype *return_value_on_stack; gdbarch_deprecated_pop_frame_ftype *deprecated_pop_frame; gdbarch_deprecated_store_struct_return_ftype *deprecated_store_struct_return; + gdbarch_return_value_ftype *return_value; + gdbarch_return_value_on_stack_ftype *return_value_on_stack; gdbarch_extract_return_value_ftype *extract_return_value; gdbarch_store_return_value_ftype *store_return_value; gdbarch_deprecated_extract_return_value_ftype *deprecated_extract_return_value; gdbarch_deprecated_store_return_value_ftype *deprecated_store_return_value; + gdbarch_use_struct_convention_ftype *use_struct_convention; gdbarch_extract_struct_value_address_ftype *extract_struct_value_address; gdbarch_deprecated_extract_struct_value_address_ftype *deprecated_extract_struct_value_address; - gdbarch_use_struct_convention_ftype *use_struct_convention; gdbarch_deprecated_frame_init_saved_regs_ftype *deprecated_frame_init_saved_regs; gdbarch_deprecated_init_extra_frame_info_ftype *deprecated_init_extra_frame_info; gdbarch_skip_prologue_ftype *skip_prologue; @@ -374,16 +375,17 @@ struct gdbarch startup_gdbarch = 0, /* pointer_to_address */ 0, /* address_to_pointer */ 0, /* integer_to_address */ - 0, /* return_value_on_stack */ 0, /* deprecated_pop_frame */ 0, /* deprecated_store_struct_return */ + 0, /* return_value */ + 0, /* return_value_on_stack */ 0, /* extract_return_value */ 0, /* store_return_value */ 0, /* deprecated_extract_return_value */ 0, /* deprecated_store_return_value */ + 0, /* use_struct_convention */ 0, /* extract_struct_value_address */ 0, /* deprecated_extract_struct_value_address */ - 0, /* use_struct_convention */ 0, /* deprecated_frame_init_saved_regs */ 0, /* deprecated_init_extra_frame_info */ 0, /* skip_prologue */ @@ -692,14 +694,15 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of pointer_to_address, invalid_p == 0 */ /* Skip verify of address_to_pointer, invalid_p == 0 */ /* Skip verify of integer_to_address, has predicate */ - /* Skip verify of return_value_on_stack, invalid_p == 0 */ /* Skip verify of deprecated_pop_frame, has predicate */ /* Skip verify of deprecated_store_struct_return, has predicate */ + /* Skip verify of return_value, has predicate */ + /* Skip verify of return_value_on_stack, invalid_p == 0 */ /* Skip verify of extract_return_value, invalid_p == 0 */ /* Skip verify of store_return_value, invalid_p == 0 */ + /* Skip verify of use_struct_convention, invalid_p == 0 */ /* Skip verify of extract_struct_value_address, has predicate */ /* Skip verify of deprecated_extract_struct_value_address, has predicate */ - /* Skip verify of use_struct_convention, invalid_p == 0 */ /* Skip verify of deprecated_frame_init_saved_regs, has predicate */ /* Skip verify of deprecated_init_extra_frame_info, has predicate */ if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) @@ -808,6 +811,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: regset_from_core_section = 0x%08lx\n", (long) current_gdbarch->regset_from_core_section); fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_return_value_p() = %d\n", + gdbarch_return_value_p (current_gdbarch)); + fprintf_unfiltered (file, + "gdbarch_dump: return_value = 0x%08lx\n", + (long) current_gdbarch->return_value); + fprintf_unfiltered (file, "gdbarch_dump: in_function_epilogue_p = 0x%08lx\n", (long) current_gdbarch->in_function_epilogue_p); fprintf_unfiltered (file, @@ -4230,23 +4239,6 @@ set_gdbarch_integer_to_address (struct gdbarch *gdbarch, } int -gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type) -{ - gdb_assert (gdbarch != NULL); - gdb_assert (gdbarch->return_value_on_stack != NULL); - if (gdbarch_debug >= 2) - fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value_on_stack called\n"); - return gdbarch->return_value_on_stack (type); -} - -void -set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch, - gdbarch_return_value_on_stack_ftype return_value_on_stack) -{ - gdbarch->return_value_on_stack = return_value_on_stack; -} - -int gdbarch_deprecated_pop_frame_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); @@ -4294,6 +4286,47 @@ set_gdbarch_deprecated_store_struct_return (struct gdbarch *gdbarch, gdbarch->deprecated_store_struct_return = deprecated_store_struct_return; } +int +gdbarch_return_value_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->return_value != NULL; +} + +enum return_value_convention +gdbarch_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, const void *inval, void *outval) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->return_value != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value called\n"); + return gdbarch->return_value (gdbarch, valtype, regcache, inval, outval); +} + +void +set_gdbarch_return_value (struct gdbarch *gdbarch, + gdbarch_return_value_ftype return_value) +{ + gdbarch->return_value = return_value; +} + +int +gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->return_value_on_stack != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value_on_stack called\n"); + return gdbarch->return_value_on_stack (type); +} + +void +set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch, + gdbarch_return_value_on_stack_ftype return_value_on_stack) +{ + gdbarch->return_value_on_stack = return_value_on_stack; +} + void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regcache *regcache, void *valbuf) { @@ -4363,6 +4396,23 @@ set_gdbarch_deprecated_store_return_value (struct gdbarch *gdbarch, } int +gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->use_struct_convention != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_use_struct_convention called\n"); + return gdbarch->use_struct_convention (gcc_p, value_type); +} + +void +set_gdbarch_use_struct_convention (struct gdbarch *gdbarch, + gdbarch_use_struct_convention_ftype use_struct_convention) +{ + gdbarch->use_struct_convention = use_struct_convention; +} + +int gdbarch_extract_struct_value_address_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); @@ -4411,23 +4461,6 @@ set_gdbarch_deprecated_extract_struct_value_address (struct gdbarch *gdbarch, } int -gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type) -{ - gdb_assert (gdbarch != NULL); - gdb_assert (gdbarch->use_struct_convention != NULL); - if (gdbarch_debug >= 2) - fprintf_unfiltered (gdb_stdlog, "gdbarch_use_struct_convention called\n"); - return gdbarch->use_struct_convention (gcc_p, value_type); -} - -void -set_gdbarch_use_struct_convention (struct gdbarch *gdbarch, - gdbarch_use_struct_convention_ftype use_struct_convention) -{ - gdbarch->use_struct_convention = use_struct_convention; -} - -int gdbarch_deprecated_frame_init_saved_regs_p (struct gdbarch *gdbarch) { gdb_assert (gdbarch != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index a82a12faac4..03dcc37272b 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -1392,16 +1392,6 @@ extern void set_gdbarch_integer_to_address (struct gdbarch *gdbarch, gdbarch_int #define INTEGER_TO_ADDRESS(type, buf) (gdbarch_integer_to_address (current_gdbarch, type, buf)) #endif -typedef int (gdbarch_return_value_on_stack_ftype) (struct type *type); -extern int gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type); -extern void set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch, gdbarch_return_value_on_stack_ftype *return_value_on_stack); -#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (RETURN_VALUE_ON_STACK) -#error "Non multi-arch definition of RETURN_VALUE_ON_STACK" -#endif -#if !defined (RETURN_VALUE_ON_STACK) -#define RETURN_VALUE_ON_STACK(type) (gdbarch_return_value_on_stack (current_gdbarch, type)) -#endif - #if defined (DEPRECATED_POP_FRAME) /* Legacy for systems yet to multi-arch DEPRECATED_POP_FRAME */ #if !defined (DEPRECATED_POP_FRAME_P) @@ -1454,6 +1444,34 @@ extern void set_gdbarch_deprecated_store_struct_return (struct gdbarch *gdbarch, #define DEPRECATED_STORE_STRUCT_RETURN(addr, sp) (gdbarch_deprecated_store_struct_return (current_gdbarch, addr, sp)) #endif +/* It has been suggested that this, well actually its predecessor, + should take the type/value of the function to be called and not the + return type. This is left as an exercise for the reader. */ + +extern int gdbarch_return_value_p (struct gdbarch *gdbarch); + +typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, const void *inval, void *outval); +extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, const void *inval, void *outval); +extern void set_gdbarch_return_value (struct gdbarch *gdbarch, gdbarch_return_value_ftype *return_value); + +/* The deprecated methods RETURN_VALUE_ON_STACK, EXTRACT_RETURN_VALUE, + STORE_RETURN_VALUE and USE_STRUCT_CONVENTION have all been folded + into RETURN_VALUE. For the moment do not try to fold in + EXTRACT_STRUCT_VALUE_ADDRESS as, dependant on the ABI, the debug + info, and the level of effort, it may well be possible to find the + address of a structure being return on the stack. Someone else can + make that change. */ + +typedef int (gdbarch_return_value_on_stack_ftype) (struct type *type); +extern int gdbarch_return_value_on_stack (struct gdbarch *gdbarch, struct type *type); +extern void set_gdbarch_return_value_on_stack (struct gdbarch *gdbarch, gdbarch_return_value_on_stack_ftype *return_value_on_stack); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (RETURN_VALUE_ON_STACK) +#error "Non multi-arch definition of RETURN_VALUE_ON_STACK" +#endif +#if !defined (RETURN_VALUE_ON_STACK) +#define RETURN_VALUE_ON_STACK(type) (gdbarch_return_value_on_stack (current_gdbarch, type)) +#endif + typedef void (gdbarch_extract_return_value_ftype) (struct type *type, struct regcache *regcache, void *valbuf); extern void gdbarch_extract_return_value (struct gdbarch *gdbarch, struct type *type, struct regcache *regcache, void *valbuf); extern void set_gdbarch_extract_return_value (struct gdbarch *gdbarch, gdbarch_extract_return_value_ftype *extract_return_value); @@ -1494,6 +1512,16 @@ extern void set_gdbarch_deprecated_store_return_value (struct gdbarch *gdbarch, #define DEPRECATED_STORE_RETURN_VALUE(type, valbuf) (gdbarch_deprecated_store_return_value (current_gdbarch, type, valbuf)) #endif +typedef int (gdbarch_use_struct_convention_ftype) (int gcc_p, struct type *value_type); +extern int gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type); +extern void set_gdbarch_use_struct_convention (struct gdbarch *gdbarch, gdbarch_use_struct_convention_ftype *use_struct_convention); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (USE_STRUCT_CONVENTION) +#error "Non multi-arch definition of USE_STRUCT_CONVENTION" +#endif +#if !defined (USE_STRUCT_CONVENTION) +#define USE_STRUCT_CONVENTION(gcc_p, value_type) (gdbarch_use_struct_convention (current_gdbarch, gcc_p, value_type)) +#endif + #if defined (EXTRACT_STRUCT_VALUE_ADDRESS) /* Legacy for systems yet to multi-arch EXTRACT_STRUCT_VALUE_ADDRESS */ #if !defined (EXTRACT_STRUCT_VALUE_ADDRESS_P) @@ -1544,16 +1572,6 @@ extern void set_gdbarch_deprecated_extract_struct_value_address (struct gdbarch #define DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS(regbuf) (gdbarch_deprecated_extract_struct_value_address (current_gdbarch, regbuf)) #endif -typedef int (gdbarch_use_struct_convention_ftype) (int gcc_p, struct type *value_type); -extern int gdbarch_use_struct_convention (struct gdbarch *gdbarch, int gcc_p, struct type *value_type); -extern void set_gdbarch_use_struct_convention (struct gdbarch *gdbarch, gdbarch_use_struct_convention_ftype *use_struct_convention); -#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (USE_STRUCT_CONVENTION) -#error "Non multi-arch definition of USE_STRUCT_CONVENTION" -#endif -#if !defined (USE_STRUCT_CONVENTION) -#define USE_STRUCT_CONVENTION(gcc_p, value_type) (gdbarch_use_struct_convention (current_gdbarch, gcc_p, value_type)) -#endif - #if defined (DEPRECATED_FRAME_INIT_SAVED_REGS) /* Legacy for systems yet to multi-arch DEPRECATED_FRAME_INIT_SAVED_REGS */ #if !defined (DEPRECATED_FRAME_INIT_SAVED_REGS_P) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 3835ac0b940..8e1c0a44482 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -593,19 +593,33 @@ f:2:POINTER_TO_ADDRESS:CORE_ADDR:pointer_to_address:struct type *type, const voi f:2:ADDRESS_TO_POINTER:void:address_to_pointer:struct type *type, void *buf, CORE_ADDR addr:type, buf, addr:::unsigned_address_to_pointer::0 F:2:INTEGER_TO_ADDRESS:CORE_ADDR:integer_to_address:struct type *type, void *buf:type, buf # -f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0 F:2:DEPRECATED_POP_FRAME:void:deprecated_pop_frame:void:- # NOTE: cagney/2003-03-24: Replaced by PUSH_ARGUMENTS. F:2:DEPRECATED_STORE_STRUCT_RETURN:void:deprecated_store_struct_return:CORE_ADDR addr, CORE_ADDR sp:addr, sp -# + +# It has been suggested that this, well actually its predecessor, +# should take the type/value of the function to be called and not the +# return type. This is left as an exercise for the reader. + +M:::enum return_value_convention:return_value:struct type *valtype, struct regcache *regcache, const void *inval, void *outval:valtype, regcache, inval, outval + +# The deprecated methods RETURN_VALUE_ON_STACK, EXTRACT_RETURN_VALUE, +# STORE_RETURN_VALUE and USE_STRUCT_CONVENTION have all been folded +# into RETURN_VALUE. For the moment do not try to fold in +# EXTRACT_STRUCT_VALUE_ADDRESS as, dependant on the ABI, the debug +# info, and the level of effort, it may well be possible to find the +# address of a structure being return on the stack. Someone else can +# make that change. + +f:2:RETURN_VALUE_ON_STACK:int:return_value_on_stack:struct type *type:type:::generic_return_value_on_stack_not::0 f:2:EXTRACT_RETURN_VALUE:void:extract_return_value:struct type *type, struct regcache *regcache, void *valbuf:type, regcache, valbuf:::legacy_extract_return_value::0 f:2:STORE_RETURN_VALUE:void:store_return_value:struct type *type, struct regcache *regcache, const void *valbuf:type, regcache, valbuf:::legacy_store_return_value::0 f:2:DEPRECATED_EXTRACT_RETURN_VALUE:void:deprecated_extract_return_value:struct type *type, char *regbuf, char *valbuf:type, regbuf, valbuf f:2:DEPRECATED_STORE_RETURN_VALUE:void:deprecated_store_return_value:struct type *type, char *valbuf:type, valbuf -# +f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0 + F:2:EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:extract_struct_value_address:struct regcache *regcache:regcache F:2:DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS:CORE_ADDR:deprecated_extract_struct_value_address:char *regbuf:regbuf -f:2:USE_STRUCT_CONVENTION:int:use_struct_convention:int gcc_p, struct type *value_type:gcc_p, value_type:::generic_use_struct_convention::0 # F:2:DEPRECATED_FRAME_INIT_SAVED_REGS:void:deprecated_frame_init_saved_regs:struct frame_info *frame:frame F:2:DEPRECATED_INIT_EXTRA_FRAME_INFO:void:deprecated_init_extra_frame_info:int fromleaf, struct frame_info *frame:fromleaf, frame diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 60ebbea9ee2..9287f031e98 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -44,6 +44,7 @@ #include "reggroups.h" #include "block.h" #include <ctype.h> +#include "gdb_assert.h" /* Functions exported for general use, in inferior.h: */ @@ -1079,25 +1080,34 @@ print_return_value (int structure_return, struct type *value_type) ui_out_field_stream (uiout, "return-value", stb); ui_out_text (uiout, "\n"); } - else - { - /* FIXME: 2003-09-27: When returning from a nested inferior - function call, it's possible (with no help from the - architecture vector) to locate and return/print a "struct - return" value. This is just a more complicated case of what - is already being done in in the inferior function call code. - In fact, when inferior function calls are made async, this - will likely be made the norm. */ - /* We cannot determine the contents of the structure because - it is on the stack, and we don't know where, since we did not - initiate the call, as opposed to the call_function_by_hand case */ + /* FIXME: 2003-09-27: When returning from a nested inferior function + call, it's possible (with no help from the architecture vector) + to locate and return/print a "struct return" value. This is just + a more complicated case of what is already being done in in the + inferior function call code. In fact, when inferior function + calls are made async, this will likely be made the norm. */ #ifdef DEPRECATED_VALUE_RETURNED_FROM_STACK - value = 0; +#define DEPRECATED_VALUE_RETURNED_FROM_STACK_P 1 +#else +#define DEPRECATED_VALUE_RETURNED_FROM_STACK_P 0 +#endif + else if (gdbarch_return_value_p (current_gdbarch) + || DEPRECATED_VALUE_RETURNED_FROM_STACK_P) + /* We cannot determine the contents of the structure because it is + on the stack, and we don't know where, since we did not + initiate the call, as opposed to the call_function_by_hand + case. */ + { + gdb_assert (gdbarch_return_value (current_gdbarch, value_type, NULL, NULL, NULL) + == RETURN_VALUE_STRUCT_CONVENTION); ui_out_text (uiout, "Value returned has type: "); ui_out_field_string (uiout, "return-type", TYPE_NAME (value_type)); ui_out_text (uiout, "."); ui_out_text (uiout, " Cannot determine contents\n"); -#else + return; + } + else + { if (EXTRACT_STRUCT_VALUE_ADDRESS_P ()) { CORE_ADDR addr = EXTRACT_STRUCT_VALUE_ADDRESS (stop_registers); @@ -1133,7 +1143,6 @@ print_return_value (int structure_return, struct type *value_type) value_print (value, stb->stream, 0, Val_no_prettyprint); ui_out_field_stream (uiout, "return-value", stb); ui_out_text (uiout, "\n"); -#endif } } diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 8091c2f56c2..0fb0d6a6c95 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -305,21 +305,6 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, return sp; } -/* Potential ways that a function can return a value of a given type. */ -enum return_value_convention -{ - /* Where the return value has been squeezed into one or more - registers. */ - RETURN_VALUE_REGISTER_CONVENTION, - /* Commonly known as the "struct return convention". The caller - passes an additional hidden first parameter to the caller. That - parameter contains the address at which the value being returned - should be stored. While typically, and historically, used for - large structs, this is convention is applied to values of many - different types. */ - RETURN_VALUE_STRUCT_CONVENTION -}; - /* Handle the return-value conventions specified by the SysV 32-bit PowerPC ABI (including all the supplements): diff --git a/gdb/values.c b/gdb/values.c index 3b1bca8a786..da5c18022d6 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1202,25 +1202,48 @@ value_from_double (struct type *type, DOUBLEST num) return val; } -/* Deal with the value that is "about to be returned". +/* Deal with the return-value of a function that has "just returned". - Return the value that a function, using the register convention, - returning now would be returning to its caller, assuming its type - is VALTYPE. RETBUF is where we look for what ought to be the - contents of the registers (in raw form). This is because it is - often desirable to restore old values to those registers after - saving the contents of interest, and then call this function using - the saved values. */ + Extract the return-value (as a "struct value") that a function, + using register convention, has just returned to its caller. Assume + that the type of the function is VALTYPE, and that the "just + returned" register state is found in RETBUF. + + The function has "just returned" because GDB halts a returning + function by setting a breakpoint at the return address (in the + caller), and not the return instruction (in the callee). + + Because, in the case of a return from an inferior function call, + GDB needs to restore the inferiors registers, RETBUF is normally a + copy of the inferior's registers. */ struct value * register_value_being_returned (struct type *valtype, struct regcache *retbuf) { struct value *val = allocate_value (valtype); - CHECK_TYPEDEF (valtype); + /* If the function returns void, don't bother fetching the return value. */ - if (TYPE_CODE (valtype) != TYPE_CODE_VOID) - EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val)); + if (TYPE_CODE (valtype) == TYPE_CODE_VOID) + return val; + + if (!gdbarch_return_value_p (current_gdbarch)) + { + /* NOTE: cagney/2003-10-20: Unlike "gdbarch_return_value", the + EXTRACT_RETURN_VALUE and USE_STRUCT_CONVENTION methods do not + handle the edge case of a function returning a small + structure / union in registers. */ + CHECK_TYPEDEF (valtype); + EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val)); + return val; + } + + /* This function only handles "register convention". */ + gdb_assert (gdbarch_return_value (current_gdbarch, valtype, + NULL, NULL, NULL) + == RETURN_VALUE_REGISTER_CONVENTION); + gdbarch_return_value (current_gdbarch, valtype, retbuf, + NULL, VALUE_CONTENTS_RAW (val)); return val; } @@ -1262,13 +1285,25 @@ using_struct_return (struct type *value_type, int gcc_p) if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); - if (code == TYPE_CODE_STRUCT - || code == TYPE_CODE_UNION - || code == TYPE_CODE_ARRAY - || RETURN_VALUE_ON_STACK (value_type)) - return USE_STRUCT_CONVENTION (gcc_p, value_type); + if (!gdbarch_return_value_p (current_gdbarch)) + { + /* FIXME: cagney/2003-10-01: The below is dead. Instead an + architecture should implement "gdbarch_return_value". Using + that new function it is possible to exactly specify the ABIs + "struct return" vs "register return" conventions. */ + if (code == TYPE_CODE_STRUCT + || code == TYPE_CODE_UNION + || code == TYPE_CODE_ARRAY + || RETURN_VALUE_ON_STACK (value_type)) + return USE_STRUCT_CONVENTION (gcc_p, value_type); + else + return 0; + } - return 0; + /* Probe the architecture for the return-value convention. */ + return (gdbarch_return_value (current_gdbarch, value_type, + NULL, NULL, NULL) + == RETURN_VALUE_STRUCT_CONVENTION); } /* Store VAL so it will be returned if a function returns now. @@ -1284,9 +1319,41 @@ set_return_value (struct value *val) if (code == TYPE_CODE_ERROR) error ("Function return type unknown."); + if (gdbarch_return_value_p (current_gdbarch)) + { + switch (gdbarch_return_value (current_gdbarch, type, NULL, NULL, NULL)) + { + case RETURN_VALUE_REGISTER_CONVENTION: + /* Success. The architecture can deal with it, write it to + the regcache. */ + gdbarch_return_value (current_gdbarch, type, current_regcache, + VALUE_CONTENTS (val), NULL); + return; + case RETURN_VALUE_STRUCT_CONVENTION: + /* Failure. For the moment, assume that it is not possible + to find the location, on the stack, at which the "struct + return" value should be stored. Only a warning because + an error aborts the "return" command leaving GDB in a + weird state. */ + warning ("Location of return value unknown"); + return; + } + } + + if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) /* FIXME, implement struct return. */ - error ("GDB does not support specifying a struct or union return value."); + /* FIXME: cagney/2003-10-20: This should be an internal-warning. + The problem is that while GDB's core supports "struct return" + using "register convention", many architectures haven't been + updated to implement the mechanisms needed to make it work. + It's a warning, and not an error, as otherwize it will jump out + of the "return" command leaving both GDB and the user in a very + confused state. */ + { + warning ("This architecture does not support specifying a struct or union return-value."); + return; + } STORE_RETURN_VALUE (type, current_regcache, VALUE_CONTENTS (val)); } |