From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5669 invoked by alias); 8 Dec 2006 15:52:04 -0000 Received: (qmail 5649 invoked by uid 22791); 8 Dec 2006 15:51:56 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate5.de.ibm.com (HELO mtagate5.de.ibm.com) (195.212.29.154) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 08 Dec 2006 15:51:48 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate5.de.ibm.com (8.13.8/8.13.8) with ESMTP id kB8Fpinb142584 for ; Fri, 8 Dec 2006 15:51:44 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.6/8.13.6/NCO v8.1.1) with ESMTP id kB8FpiBD3088508 for ; Fri, 8 Dec 2006 16:51:44 +0100 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id kB8FpidO012744 for ; Fri, 8 Dec 2006 16:51:44 +0100 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id kB8FpiGI012741; Fri, 8 Dec 2006 16:51:44 +0100 Message-Id: <200612081551.kB8FpiGI012741@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Fri, 8 Dec 2006 16:51:44 +0100 Subject: [RFC][2/2] Rework value_from_register To: gdb-patches@sourceware.org Date: Fri, 08 Dec 2006 15:52:00 -0000 From: "Ulrich Weigand" Cc: jimb@codesourcery.com, drow@false.org X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-12/txt/msg00123.txt.bz2 Hello, based on the value_from_register cleanup patch, this patch adds a new gdbarch method, gdbarch_value_from_register, that back-ends can use instead of convert_register_p / value_to_register / register_to_value. The idea is that the gdbarch routine sets up the contents of the struct value such that subsequently, common code is able to access the register (including sub-values) without further interaction with gdbarch methods. This currently works only on spu and s390, because there we simply need to set the proper value_offset, and everything else works automatically. In the future, assuming Jim's per-value read/write methods are implemented, the gdbarch_value_from_register routine could set those to effect any arbitrary change; that solution would then completly replace the existing value_to_register / register_to_value. Until that is implemented, I've left in the old way as well. I've considered one interface alternative; the patch below has common code generate the struct value and fill in default values; the gdbarch_value_from_register routine gets the struct value is may change things as appropriate. The alternative would be to have gdbarch_value_from_register fully construct the value itself (possibly falling back on a common helper routine). Any preference on that question? Tested without regressions on spu-elf, s390-ibm-linux, s390x-ibm-linux. Fixes all the currently existing sub-value problems on spu. Bye, Ulrich ChangeLog: * gdbarch.sh (value_from_register): New gdbarch function. * gdbarch.c, gdbarch.h: Regenerate. * findvar.c (default_value_from_register): New function. (value_from_register): Use gdbarch_value_from_register. * value.h (default_value_from_register): Declare. * spu-tdep.c (spu_convert_register_p, spu_register_to_value, spu_value_to_register): Remove. (spu_value_from_register): New function. (spu_gdbarch_init): Do not call set_gdbarch_convert_register_p, set_gdbarch_register_to_value, set_gdbarch_value_to_register. Call set_gdbarch_value_from_register. * s390-tdep.c (s390_convert_register_p, s390_register_to_value, s390_value_to_register): Remove. (s390_value_from_register): New function. (s390_gdbarch_init): Do not call set_gdbarch_convert_register_p, set_gdbarch_register_to_value, set_gdbarch_value_to_register. Call set_gdbarch_value_from_register. diff -urp gdb-orig/gdb/findvar.c gdb-head/gdb/findvar.c diff -urp gdb-orig/gdb/findvar.c gdb-head/gdb/findvar.c --- gdb-orig/gdb/findvar.c 2006-12-08 14:54:18.000000000 +0100 +++ gdb-head/gdb/findvar.c 2006-12-08 15:27:51.647466736 +0100 @@ -599,6 +599,26 @@ addresses have not been bound by the dyn return v; } +/* Install default attributes for register values. */ + +void +default_value_from_register (struct gdbarch *gdbarch, struct value *value) +{ + int len = TYPE_LENGTH (value_type (value)); + int regnum = VALUE_REGNUM (value); + + /* Any structure stored in more than one register will always be + an integral number of registers. Otherwise, you need to do + some fiddling with the last register copied here for little + endian machines. */ + if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG + && len < register_size (gdbarch, regnum)) + /* Big-endian, and we want less than full size. */ + set_value_offset (value, register_size (gdbarch, regnum) - len); + else + set_value_offset (value, 0); +} + /* Return a value of type TYPE, stored in register REGNUM, in frame FRAME. */ struct value * @@ -628,16 +648,8 @@ value_from_register (struct type *type, struct gdbarch *gdbarch = get_frame_arch (frame); int len = TYPE_LENGTH (type); - /* Any structure stored in more than one register will always be - an integral number of registers. Otherwise, you need to do - some fiddling with the last register copied here for little - endian machines. */ - if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG - && len < register_size (gdbarch, regnum)) - /* Big-endian, and we want less than full size. */ - set_value_offset (v, register_size (gdbarch, regnum) - len); - else - set_value_offset (v, 0); + /* Install value attributes. */ + gdbarch_value_from_register (gdbarch, v); /* Get the data. */ if (!get_frame_register_bytes (frame, regnum, value_offset (v), len, diff -urp gdb-orig/gdb/gdbarch.c gdb-head/gdb/gdbarch.c --- gdb-orig/gdb/gdbarch.c 2006-12-08 14:38:45.000000000 +0100 +++ gdb-head/gdb/gdbarch.c 2006-12-08 15:19:20.115487104 +0100 @@ -183,6 +183,7 @@ struct gdbarch gdbarch_convert_register_p_ftype *convert_register_p; gdbarch_register_to_value_ftype *register_to_value; gdbarch_value_to_register_ftype *value_to_register; + gdbarch_value_from_register_ftype *value_from_register; gdbarch_pointer_to_address_ftype *pointer_to_address; gdbarch_address_to_pointer_ftype *address_to_pointer; gdbarch_integer_to_address_ftype *integer_to_address; @@ -309,6 +310,7 @@ struct gdbarch startup_gdbarch = 0, /* convert_register_p */ 0, /* register_to_value */ 0, /* value_to_register */ + default_value_from_register, /* value_from_register */ 0, /* pointer_to_address */ 0, /* address_to_pointer */ 0, /* integer_to_address */ @@ -429,6 +431,7 @@ gdbarch_alloc (const struct gdbarch_info current_gdbarch->cannot_fetch_register = cannot_register_not; current_gdbarch->cannot_store_register = cannot_register_not; current_gdbarch->convert_register_p = generic_convert_register_p; + current_gdbarch->value_from_register = default_value_from_register; current_gdbarch->pointer_to_address = unsigned_pointer_to_address; current_gdbarch->address_to_pointer = unsigned_address_to_pointer; current_gdbarch->return_value = legacy_return_value; @@ -562,6 +565,8 @@ verify_gdbarch (struct gdbarch *current_ /* Skip verify of cannot_store_register, invalid_p == 0 */ /* Skip verify of get_longjmp_target, has predicate */ /* Skip verify of convert_register_p, invalid_p == 0 */ + if (current_gdbarch->value_from_register == default_value_from_register) + fprintf_unfiltered (log, "\n\tvalue_from_register"); /* 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 */ @@ -1586,6 +1591,9 @@ gdbarch_dump (struct gdbarch *current_gd fprintf_unfiltered (file, "gdbarch_dump: unwind_sp = <0x%lx>\n", (long) current_gdbarch->unwind_sp); + fprintf_unfiltered (file, + "gdbarch_dump: value_from_register = <0x%lx>\n", + (long) current_gdbarch->value_from_register); #ifdef VALUE_TO_REGISTER fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", @@ -2636,6 +2644,23 @@ set_gdbarch_value_to_register (struct gd gdbarch->value_to_register = value_to_register; } +void +gdbarch_value_from_register (struct gdbarch *gdbarch, struct value *value) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->value_from_register != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_value_from_register called\n"); + gdbarch->value_from_register (gdbarch, value); +} + +void +set_gdbarch_value_from_register (struct gdbarch *gdbarch, + gdbarch_value_from_register_ftype value_from_register) +{ + gdbarch->value_from_register = value_from_register; +} + CORE_ADDR gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) { diff -urp gdb-orig/gdb/gdbarch.h gdb-head/gdb/gdbarch.h --- gdb-orig/gdb/gdbarch.h 2006-12-08 14:38:45.000000000 +0100 +++ gdb-head/gdb/gdbarch.h 2006-12-08 15:19:00.783497440 +0100 @@ -704,6 +704,10 @@ extern void set_gdbarch_value_to_registe #define VALUE_TO_REGISTER(frame, regnum, type, buf) (gdbarch_value_to_register (current_gdbarch, frame, regnum, type, buf)) #endif +typedef void (gdbarch_value_from_register_ftype) (struct gdbarch *gdbarch, struct value *value); +extern void gdbarch_value_from_register (struct gdbarch *gdbarch, struct value *value); +extern void set_gdbarch_value_from_register (struct gdbarch *gdbarch, gdbarch_value_from_register_ftype *value_from_register); + typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct type *type, const gdb_byte *buf); extern CORE_ADDR gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf); extern void set_gdbarch_pointer_to_address (struct gdbarch *gdbarch, gdbarch_pointer_to_address_ftype *pointer_to_address); diff -urp gdb-orig/gdb/gdbarch.sh gdb-head/gdb/gdbarch.sh --- gdb-orig/gdb/gdbarch.sh 2006-12-08 14:38:45.000000000 +0100 +++ gdb-head/gdb/gdbarch.sh 2006-12-08 15:18:51.648421896 +0100 @@ -496,6 +496,7 @@ v:=:int:believe_pcc_promotion::::::: f:=:int:convert_register_p:int regnum, struct type *type:regnum, type:0:generic_convert_register_p::0 f:=:void:register_to_value:struct frame_info *frame, int regnum, struct type *type, gdb_byte *buf:frame, regnum, type, buf:0 f:=:void:value_to_register:struct frame_info *frame, int regnum, struct type *type, const gdb_byte *buf:frame, regnum, type, buf:0 +m::void:value_from_register:struct value *value:value::default_value_from_register # f:=:CORE_ADDR:pointer_to_address:struct type *type, const gdb_byte *buf:type, buf::unsigned_pointer_to_address::0 f:=:void:address_to_pointer:struct type *type, gdb_byte *buf, CORE_ADDR addr:type, buf, addr::unsigned_address_to_pointer::0 diff -urp gdb-orig/gdb/s390-tdep.c gdb-head/gdb/s390-tdep.c --- gdb-orig/gdb/s390-tdep.c 2006-11-28 21:46:03.000000000 +0100 +++ gdb-head/gdb/s390-tdep.c 2006-12-08 15:28:09.919485824 +0100 @@ -306,36 +306,16 @@ s390x_pseudo_register_write (struct gdba /* 'float' values are stored in the upper half of floating-point registers, even though we are otherwise a big-endian platform. */ -static int -s390_convert_register_p (int regno, struct type *type) -{ - return (regno >= S390_F0_REGNUM && regno <= S390_F15_REGNUM) - && TYPE_LENGTH (type) < 8; -} - static void -s390_register_to_value (struct frame_info *frame, int regnum, - struct type *valtype, gdb_byte *out) +s390_value_from_register (struct gdbarch *gdbarch, struct value *value) { - gdb_byte in[8]; - int len = TYPE_LENGTH (valtype); - gdb_assert (len < 8); + int len = TYPE_LENGTH (value_type (value)); + int regnum = VALUE_REGNUM (value); - get_frame_register (frame, regnum, in); - memcpy (out, in, len); -} + default_value_from_register (gdbarch, value); -static void -s390_value_to_register (struct frame_info *frame, int regnum, - struct type *valtype, const gdb_byte *in) -{ - gdb_byte out[8]; - int len = TYPE_LENGTH (valtype); - gdb_assert (len < 8); - - memset (out, 0, 8); - memcpy (out, in, len); - put_frame_register (frame, regnum, out); + if (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM && len < 8) + set_value_offset (value, 0); } /* Register groups. */ @@ -2411,9 +2391,7 @@ s390_gdbarch_init (struct gdbarch_info i set_gdbarch_stab_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); set_gdbarch_dwarf_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, s390_dwarf_reg_to_regnum); - set_gdbarch_convert_register_p (gdbarch, s390_convert_register_p); - set_gdbarch_register_to_value (gdbarch, s390_register_to_value); - set_gdbarch_value_to_register (gdbarch, s390_value_to_register); + set_gdbarch_value_from_register (gdbarch, s390_value_from_register); set_gdbarch_register_reggroup_p (gdbarch, s390_register_reggroup_p); set_gdbarch_regset_from_core_section (gdbarch, s390_regset_from_core_section); diff -urp gdb-orig/gdb/spu-tdep.c gdb-head/gdb/spu-tdep.c --- gdb-orig/gdb/spu-tdep.c 2006-11-24 15:00:40.000000000 +0100 +++ gdb-head/gdb/spu-tdep.c 2006-12-08 15:28:21.653433624 +0100 @@ -143,37 +143,19 @@ spu_pseudo_register_write (struct gdbarc /* Value conversion -- access scalar values at the preferred slot. */ -static int -spu_convert_register_p (int regno, struct type *type) -{ - return regno < SPU_NUM_GPRS && TYPE_LENGTH (type) < 16; -} - static void -spu_register_to_value (struct frame_info *frame, int regnum, - struct type *valtype, gdb_byte *out) +spu_value_from_register (struct gdbarch *gdbarch, struct value *value) { - gdb_byte in[16]; - int len = TYPE_LENGTH (valtype); - int preferred_slot = len < 4 ? 4 - len : 0; - gdb_assert (len < 16); + int len = TYPE_LENGTH (value_type (value)); + int regnum = VALUE_REGNUM (value); - get_frame_register (frame, regnum, in); - memcpy (out, in + preferred_slot, len); -} + default_value_from_register (gdbarch, value); -static void -spu_value_to_register (struct frame_info *frame, int regnum, - struct type *valtype, const gdb_byte *in) -{ - gdb_byte out[16]; - int len = TYPE_LENGTH (valtype); - int preferred_slot = len < 4 ? 4 - len : 0; - gdb_assert (len < 16); - - memset (out, 0, 16); - memcpy (out + preferred_slot, in, len); - put_frame_register (frame, regnum, out); + if (regnum < SPU_NUM_GPRS && len < 16) + { + int preferred_slot = len < 4 ? 4 - len : 0; + set_value_offset (value, preferred_slot); + } } /* Register groups. */ @@ -1048,9 +1030,7 @@ spu_gdbarch_init (struct gdbarch_info in set_gdbarch_register_type (gdbarch, spu_register_type); set_gdbarch_pseudo_register_read (gdbarch, spu_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, spu_pseudo_register_write); - set_gdbarch_convert_register_p (gdbarch, spu_convert_register_p); - set_gdbarch_register_to_value (gdbarch, spu_register_to_value); - set_gdbarch_value_to_register (gdbarch, spu_value_to_register); + set_gdbarch_value_from_register (gdbarch, spu_value_from_register); set_gdbarch_register_reggroup_p (gdbarch, spu_register_reggroup_p); /* Data types. */ diff -urp gdb-orig/gdb/value.h gdb-head/gdb/value.h --- gdb-orig/gdb/value.h 2006-11-24 17:56:28.000000000 +0100 +++ gdb-head/gdb/value.h 2006-12-08 15:20:29.836407912 +0100 @@ -279,6 +279,9 @@ extern struct value *value_from_string ( extern struct value *value_at (struct type *type, CORE_ADDR addr); extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr); +extern void default_value_from_register (struct gdbarch *gdbarch, + struct value *value); + extern struct value *value_from_register (struct type *type, int regnum, struct frame_info *frame); -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com