diff options
author | Sergio Durigan Junior <sergiodj@redhat.com> | 2019-02-07 00:05:49 -0500 |
---|---|---|
committer | Sergio Durigan Junior <sergiodj@redhat.com> | 2019-02-07 00:06:03 -0500 |
commit | a5083498fad514ebed80e5c84ab618f24e33649f (patch) | |
tree | 9a1b03302ebe86f49ce588e5bc9f8c3879b0df25 | |
parent | 31528deca52123a5a6dee19d47bee94dff041325 (diff) | |
download | binutils-a5083498fad514ebed80e5c84ab618f24e33649f.zip binutils-a5083498fad514ebed80e5c84ab618f24e33649f.tar.gz binutils-a5083498fad514ebed80e5c84ab618f24e33649f.tar.bz2 |
Initial attempt
-rw-r--r-- | gdb/aarch64-tdep.c | 73 | ||||
-rw-r--r-- | gdb/common/length-type.h | 384 | ||||
-rw-r--r-- | gdb/corefile.c | 9 | ||||
-rw-r--r-- | gdb/gdbcore.h | 5 | ||||
-rw-r--r-- | gdb/gdbtypes.h | 3 |
5 files changed, 437 insertions, 37 deletions
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index bc928e14..7c740ba 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1081,19 +1081,19 @@ typedef struct const gdb_byte *data; /* Size in bytes of value to pass on stack. */ - int len; + length_t len; } stack_item_t; DEF_VEC_O (stack_item_t); /* Return the alignment (in bytes) of the given type. */ -static int +static length_t aarch64_type_align (struct type *t) { int n; - int align; - int falign; + length_t align; + length_t falign; t = check_typedef (t); switch (TYPE_CODE (t)) @@ -1206,14 +1206,13 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type, else { struct type *target_type = TYPE_TARGET_TYPE (type); - int count = aapcs_is_vfp_call_or_return_candidate_1 - (target_type, fundamental_type); + slength_t count = aapcs_is_vfp_call_or_return_candidate_1 + (target_type, fundamental_type); - if (count == -1) - return count; + if (count != -1) + count *= (TYPE_LENGTH (type) / TYPE_LENGTH (target_type)); - count *= (TYPE_LENGTH (type) / TYPE_LENGTH (target_type)); - return count; + return (int) count; } } @@ -1239,8 +1238,8 @@ aapcs_is_vfp_call_or_return_candidate_1 (struct type *type, /* Ensure there is no padding between the fields (allowing for empty zero length structs) */ - int ftype_length = (*fundamental_type == nullptr) - ? 0 : TYPE_LENGTH (*fundamental_type); + length_t ftype_length = (*fundamental_type == nullptr) + ? 0 : TYPE_LENGTH (*fundamental_type); if (count * ftype_length != TYPE_LENGTH (type)) return -1; @@ -1309,7 +1308,7 @@ struct aarch64_call_info /* The next stacked argument address, equivalent to NSAA as described in the AArch64 Procedure Call Standard. */ - unsigned nsaa; + length_t nsaa; /* Stack item vector. */ VEC(stack_item_t) *si; @@ -1324,7 +1323,7 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache, struct value *arg) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int len = TYPE_LENGTH (type); + length_t len = TYPE_LENGTH (type); enum type_code typecode = TYPE_CODE (type); int regnum = AARCH64_X0_REGNUM + info->ngrn; const bfd_byte *buf = value_contents (arg); @@ -1333,8 +1332,8 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache, while (len > 0) { - int partial_len = len < X_REGISTER_SIZE ? len : X_REGISTER_SIZE; - CORE_ADDR regval = extract_unsigned_integer (buf, partial_len, + length_t partial_len = len < X_REGISTER_SIZE ? len : X_REGISTER_SIZE; + CORE_ADDR regval = extract_unsigned_integer (buf, (int) partial_len, byte_order); @@ -1342,7 +1341,7 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache, if (byte_order == BFD_ENDIAN_BIG && partial_len < X_REGISTER_SIZE && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)) - regval <<= ((X_REGISTER_SIZE - partial_len) * TARGET_CHAR_BIT); + regval <<= ((X_REGISTER_SIZE - (int) partial_len) * TARGET_CHAR_BIT); if (aarch64_debug) { @@ -1352,7 +1351,7 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache, } regcache_cooked_write_unsigned (regcache, regnum, regval); len -= partial_len; - buf += partial_len; + buf += (int) partial_len; regnum++; } } @@ -1366,7 +1365,7 @@ static int pass_in_v (struct gdbarch *gdbarch, struct regcache *regcache, struct aarch64_call_info *info, - int len, const bfd_byte *buf) + length_t &len, const bfd_byte *buf) { if (info->nsrn < 8) { @@ -1381,7 +1380,7 @@ pass_in_v (struct gdbarch *gdbarch, memset (reg, 0, sizeof (reg)); /* PCS C.1, the argument is allocated to the least significant bits of V register. */ - memcpy (reg, buf, len); + memcpy (reg, buf, static_cast<size_t> (len)); regcache->cooked_write (regnum, reg); if (aarch64_debug) @@ -1402,8 +1401,8 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, struct value *arg) { const bfd_byte *buf = value_contents (arg); - int len = TYPE_LENGTH (type); - int align; + length_t len = TYPE_LENGTH (type); + length_t align; stack_item_t item; info->argnum++; @@ -1412,7 +1411,7 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, /* PCS C.17 Stack should be aligned to the larger of 8 bytes or the Natural alignment of the argument's type. */ - align = align_up (align, 8); + align = align_up (static_cast<ULONGEST> (align), 8); /* The AArch64 PCS requires at most doubleword alignment. */ if (align > 16) @@ -1420,8 +1419,8 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, if (aarch64_debug) { - debug_printf ("arg %d len=%d @ sp + %d\n", info->argnum, len, - info->nsaa); + debug_printf ("arg %d len=%s @ sp + %s\n", info->argnum, len.c_str (), + info->nsaa.c_str ()); } item.len = len; @@ -1429,10 +1428,10 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, VEC_safe_push (stack_item_t, info->si, &item); info->nsaa += len; - if (info->nsaa & (align - 1)) + if ((info->nsaa & (align - 1)) != 0) { /* Push stack alignment padding. */ - int pad = align - (info->nsaa & (align - 1)); + length_t pad = align - (info->nsaa & (align - 1)); item.len = pad; item.data = NULL; @@ -1451,8 +1450,8 @@ pass_in_x_or_stack (struct gdbarch *gdbarch, struct regcache *regcache, struct aarch64_call_info *info, struct type *type, struct value *arg) { - int len = TYPE_LENGTH (type); - int nregs = (len + X_REGISTER_SIZE - 1) / X_REGISTER_SIZE; + length_t len = TYPE_LENGTH (type); + int nregs = static_cast<int> ((len + X_REGISTER_SIZE - 1) / X_REGISTER_SIZE); /* PCS C.13 - Pass in registers if we have enough spare */ if (info->ngrn + nregs <= 8) @@ -1493,7 +1492,8 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache, return false; return pass_in_v (gdbarch, regcache, info, TYPE_LENGTH (target_type), - buf + TYPE_LENGTH (target_type)); + buf + + static_cast<ULONGEST> (TYPE_LENGTH (target_type))); } case TYPE_CODE_ARRAY: @@ -1588,7 +1588,8 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, { struct value *arg = args[argnum]; struct type *arg_type, *fundamental_type; - int len, elements; + length_t len; + int elements; arg_type = check_typedef (value_type (arg)); len = TYPE_LENGTH (arg_type); @@ -1642,7 +1643,7 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, invisible reference. */ /* Allocate aligned storage. */ - sp = align_down (sp - len, 16); + sp = align_down (sp - static_cast<CORE_ADDR> (len), 16); /* Write the real data into the stack. */ write_memory (sp, value_contents (arg), len); @@ -1664,14 +1665,14 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } /* Make sure stack retains 16 byte alignment. */ - if (info.nsaa & 15) - sp -= 16 - (info.nsaa & 15); + if ((info.nsaa & length_t (15)) != 0) + sp -= 16 - (static_cast<CORE_ADDR> (info.nsaa) & 15); while (!VEC_empty (stack_item_t, info.si)) { stack_item_t *si = VEC_last (stack_item_t, info.si); - sp -= si->len; + sp -= static_cast<CORE_ADDR> (si->len); if (si->data != NULL) write_memory (sp, si->data, si->len); VEC_pop (stack_item_t, info.si); @@ -1920,7 +1921,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs, if (aapcs_is_vfp_call_or_return_candidate (type, &elements, &fundamental_type)) { - int len = TYPE_LENGTH (fundamental_type); + length_t len = TYPE_LENGTH (fundamental_type); for (int i = 0; i < elements; i++) { diff --git a/gdb/common/length-type.h b/gdb/common/length-type.h new file mode 100644 index 0000000..74d8050 --- /dev/null +++ b/gdb/common/length-type.h @@ -0,0 +1,384 @@ +/* Length types for GDB. + + Copyright (C) 2019 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef COMMON_LENGH_TYPE_H +#define COMMON_LENGH_TYPE_H + +#include <limits> + +template<typename T> +class gdb_len +{ +public: + T m_len; + + gdb_len () = default; + + gdb_len (T l) + : m_len (l) + { + } + + gdb_len (int l) + : m_len (l) + { + } + + /* const T get () const */ + /* { */ + /* return m_len; */ + /* } */ + + /* void set (const T l) */ + /* { */ + /* m_len = l; */ + /* } */ + + const char *c_str () const + { + return std::numeric_limits<T>::is_signed + ? plongest (m_len) : pulongest (m_len); + } + + explicit operator int () const + { + if (m_len > std::numeric_limits<int>::max ()) + error (_("Cannot cast variable: too long")); + + return static_cast<int> (m_len); + } + + explicit operator unsigned int () const + { + if (std::numeric_limits<T>::is_signed && m_len < 0) + error (_("Cannot cast negative variable.")); + + if (m_len > std::numeric_limits<unsigned int>::max ()) + error (_("Cannot cast variable: too long.")); + + return static_cast<unsigned int> (m_len); + } + + /* explicit operator size_t () const */ + /* { */ + /* if (std::numeric_limits<T>::is_signed && m_len < 0) */ + /* error (_("Cannot cast negative variable to 'size_t'.")); */ + + /* if (m_len > std::numeric_limits<size_t>::max ()) */ + /* error (_("Cannot cast variable: too long")); */ + + /* return static_cast<size_t> (m_len); */ + /* } */ + + explicit operator ULONGEST () const + { + if (!std::numeric_limits<T>::is_signed) + return m_len; + + if (m_len < 0) + error (_("Cannot cast negative variable to 'ULONGEST'.")); + + return static_cast<ULONGEST> (m_len); + } + + explicit operator LONGEST () const + { + if (std::numeric_limits<T>::is_signed) + return m_len; + + if (m_len > std::numeric_limits<T>::max ()) + error (_("Cannot cast variable: too long")); + + return static_cast<LONGEST> (m_len); + } + +#define DEFINE_LENGTH_REL_OP_TYPE(TYPE, OP) \ + constexpr bool \ + operator OP (const TYPE rhs) \ + { \ + return (static_cast<TYPE> (*this) OP rhs); \ + } \ + +#define DEFINE_ALL_LENGTH_REL_OP_TYPE(TYPE) \ + DEFINE_LENGTH_REL_OP_TYPE (TYPE, >) \ + DEFINE_LENGTH_REL_OP_TYPE (TYPE, >=) \ + DEFINE_LENGTH_REL_OP_TYPE (TYPE, <) \ + DEFINE_LENGTH_REL_OP_TYPE (TYPE, <=) \ + DEFINE_LENGTH_REL_OP_TYPE (TYPE, ==) \ + DEFINE_LENGTH_REL_OP_TYPE (TYPE, !=) + +DEFINE_ALL_LENGTH_REL_OP_TYPE (int) +DEFINE_ALL_LENGTH_REL_OP_TYPE (ULONGEST) +DEFINE_ALL_LENGTH_REL_OP_TYPE (LONGEST) + +#define DEFINE_LENGTH_REL_OP(OP) \ + constexpr bool \ + operator OP (const gdb_len<T> &rhs) \ + { \ + return (m_len OP rhs.m_len); \ + } + +DEFINE_LENGTH_REL_OP (>) +DEFINE_LENGTH_REL_OP (>=) +DEFINE_LENGTH_REL_OP (<) +DEFINE_LENGTH_REL_OP (<=) +DEFINE_LENGTH_REL_OP (==) +DEFINE_LENGTH_REL_OP (!=) + + +#define DEFINE_LENGTH_ARITHM_OP_TYPE(TYPE, OP) \ + gdb_len<T> & \ + operator OP ## = (const TYPE rhs) \ + { \ + if (std::numeric_limits<TYPE>::is_signed \ + && !std::numeric_limits<T>::is_signed \ + && rhs < 0) \ + error (_("Cannot cast negative variable to unsigned type.")); \ + else if (!std::numeric_limits<TYPE>::is_signed \ + && std::numeric_limits<T>::is_signed \ + && rhs > std::numeric_limits<T>::max ()) \ + error (_("Cannot cast variable: too long.")); \ + \ + m_len OP ## = static_cast<T> (rhs); \ + return *this; \ + } \ + \ + friend constexpr gdb_len<T> \ + operator OP (const gdb_len<T> &lhs, const TYPE rhs) \ + { \ + return gdb_len<T> (static_cast<TYPE> (lhs) OP rhs); \ + } \ + \ + friend constexpr gdb_len<T> \ + operator OP (const TYPE rhs, const gdb_len<T> &lhs) \ + { \ + return gdb_len<T> (rhs OP static_cast<TYPE> (lhs)); \ + } + +#define DEFINE_ALL_LENGTH_ARITHM_OP_TYPE(TYPE) \ + DEFINE_LENGTH_ARITHM_OP_TYPE (TYPE, +) \ + DEFINE_LENGTH_ARITHM_OP_TYPE (TYPE, -) \ + DEFINE_LENGTH_ARITHM_OP_TYPE (TYPE, *) \ + DEFINE_LENGTH_ARITHM_OP_TYPE (TYPE, /) \ + DEFINE_LENGTH_ARITHM_OP_TYPE (TYPE, %) + +DEFINE_ALL_LENGTH_ARITHM_OP_TYPE (int) +DEFINE_ALL_LENGTH_ARITHM_OP_TYPE (unsigned int) +DEFINE_ALL_LENGTH_ARITHM_OP_TYPE (ULONGEST) +DEFINE_ALL_LENGTH_ARITHM_OP_TYPE (LONGEST) + +#define DEFINE_LENGTH_ARITHM_OP(OP) \ + gdb_len<T> & \ + operator OP ## = (const gdb_len<T> &rhs) \ + { \ + m_len OP ## = rhs.m_len; \ + return *this; \ + } \ + \ + friend constexpr gdb_len<T> \ + operator OP (const gdb_len<T> &lhs, const gdb_len<T> &rhs) \ + { \ + return gdb_len<T> (lhs.m_len OP rhs.m_len); \ + } + +DEFINE_LENGTH_ARITHM_OP (+) +DEFINE_LENGTH_ARITHM_OP (-) +DEFINE_LENGTH_ARITHM_OP (*) +DEFINE_LENGTH_ARITHM_OP (/) +DEFINE_LENGTH_ARITHM_OP (%) +DEFINE_LENGTH_ARITHM_OP (&) + +private: +}; + +typedef gdb_len<ULONGEST> length_t; +typedef gdb_len<LONGEST> slength_t; + + +/* Operators for length_t and slength_t. */ + +#define DEFINE_ARITHM_OPS(OP) \ + length_t & \ + operator OP ## = (length_t &lhs, const slength_t &rhs) \ + { \ + lhs.m_len OP ## = static_cast<ULONGEST> (rhs); \ + return lhs; \ + } \ + \ + slength_t & \ + operator OP ## = (slength_t &lhs, const length_t &rhs) \ + { \ + lhs.m_len OP ## = static_cast<LONGEST> (rhs); \ + return lhs; \ + } \ + \ + slength_t \ + operator OP (const length_t &lhs, const slength_t &rhs) \ + { \ + return static_cast<LONGEST> (lhs) OP rhs; \ + } \ + \ + slength_t \ + operator OP (const slength_t &lhs, const length_t &rhs) \ + { \ + return lhs OP static_cast<LONGEST> (rhs); \ + } + +DEFINE_ARITHM_OPS (+) +DEFINE_ARITHM_OPS (-) +DEFINE_ARITHM_OPS (*) +DEFINE_ARITHM_OPS (/) +DEFINE_ARITHM_OPS (%) + + + + + + +#if 0 + +#define DEFINE_LENGTH_ARITHM_OP(TYPE, OP) \ + constexpr TYPE \ + operator OP (TYPE lhs, ULONGEST rhs) \ + { \ + return (TYPE) (lhs.m_len OP rhs); \ + } \ + \ + constexpr TYPE \ + operator OP (ULONGEST lhs, TYPE rhs) \ + { \ + return (TYPE) (lhs OP static_cast<ULONGEST> (rhs)); \ + } \ + \ + length_t & \ + operator OP ## = (length_t &lhs, ULONGEST rhs) \ + { \ + lhs = (length_t) (static_cast<ULONGEST> (lhs) OP rhs); \ + return lhs; \ + } \ + \ + constexpr length_t \ + operator OP (length_t lhs, length_t rhs) \ + { \ + return (length_t) (static_cast<ULONGEST> (lhs) \ + OP static_cast<ULONGEST> (rhs)); \ + } \ + \ + length_t & \ + operator OP ## = (length_t &lhs, length_t rhs) \ + { \ + lhs = (length_t) (static_cast<ULONGEST> (lhs) \ + OP static_cast<ULONGEST> (rhs)); \ + return lhs; \ + } \ + +DEFINE_LENGTH_ARITHM_OP (+) +DEFINE_LENGTH_ARITHM_OP (-) +DEFINE_LENGTH_ARITHM_OP (*) +DEFINE_LENGTH_ARITHM_OP (/) +#endif + + +#if 0 +enum class length_t : ULONGEST {}; + +enum class slenght_t : LONGEST {}; + +#define DEFINE_LENGTH_REL_OP(OP) \ + constexpr bool \ + operator OP (length_t lhs, int rhs) \ + { \ + return (lhs OP static_cast<ULONGEST> (rhs)); \ + } + +DEFINE_LENGTH_REL_OP (>) +DEFINE_LENGTH_REL_OP (>=) +DEFINE_LENGTH_REL_OP (<) +DEFINE_LENGTH_REL_OP (<=) +DEFINE_LENGTH_REL_OP (==) +DEFINE_LENGTH_REL_OP (!=) + +#define DEFINE_LENGTH_ARITHM_OP(OP) \ + constexpr length_t \ + operator OP (length_t lhs, ULONGEST rhs) \ + { \ + return (length_t) (static_cast<ULONGEST> (lhs) OP rhs); \ + } \ + \ + constexpr length_t \ + operator OP (ULONGEST lhs, length_t rhs) \ + { \ + return (length_t) (lhs OP static_cast<ULONGEST> (rhs)); \ + } \ + \ + length_t & \ + operator OP ## = (length_t &lhs, ULONGEST rhs) \ + { \ + lhs = (length_t) (static_cast<ULONGEST> (lhs) OP rhs); \ + return lhs; \ + } \ + \ + constexpr length_t \ + operator OP (length_t lhs, length_t rhs) \ + { \ + return (length_t) (static_cast<ULONGEST> (lhs) \ + OP static_cast<ULONGEST> (rhs)); \ + } \ + \ + length_t & \ + operator OP ## = (length_t &lhs, length_t rhs) \ + { \ + lhs = (length_t) (static_cast<ULONGEST> (lhs) \ + OP static_cast<ULONGEST> (rhs)); \ + return lhs; \ + } \ + +DEFINE_LENGTH_ARITHM_OP (+) +DEFINE_LENGTH_ARITHM_OP (-) +DEFINE_LENGTH_ARITHM_OP (*) +DEFINE_LENGTH_ARITHM_OP (/) + +inline const char * +to_str (length_t &l) +{ + return pulongest (to_underlying (l)); +} + +inline int +to_int (length_t &l) +{ + return static_cast<int> (l); +} + +inline ssize_t +to_ssize_t (length_t &l) +{ + return static_cast<ssize_t> (l); +} + +inline LONGEST +to_LONGEST (length_t &l) +{ + return static_cast<LONGEST> (l); +} +#endif //0 + + + +#endif /* ! COMMON_LENGH_TYPE_H */ diff --git a/gdb/corefile.c b/gdb/corefile.c index bf859fb..9dfe7ec 100644 --- a/gdb/corefile.c +++ b/gdb/corefile.c @@ -377,6 +377,15 @@ write_memory (CORE_ADDR memaddr, memory_error (TARGET_XFER_E_IO, memaddr); } +/* See gdbcore.h. */ + +void +write_memory (CORE_ADDR memaddr, + const bfd_byte *myaddr, length_t &len) +{ + write_memory (memaddr, myaddr, static_cast<ssize_t> len); +} + /* Same as write_memory, but notify 'memory_changed' observers. */ void diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h index 6f9b4d8..78a1092 100644 --- a/gdb/gdbcore.h +++ b/gdb/gdbcore.h @@ -104,6 +104,11 @@ CORE_ADDR read_memory_typed_address (CORE_ADDR addr, struct type *type); extern void write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len); +/* Same as above, but with length_t. */ + +extern void write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, + length_t &len); + /* Same as write_memory, but notify 'memory_changed' observers. */ extern void write_memory_with_notification (CORE_ADDR memaddr, diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index a6d4f64..5736ced 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -50,6 +50,7 @@ #include "common/enum-flags.h" #include "common/underlying.h" #include "common/print-utils.h" +#include "common/length-type.h" #include "gdbarch.h" /* Forward declarations for prototypes. */ @@ -859,7 +860,7 @@ struct type type_length_units function should be used in order to get the length expressed in target addressable memory units. */ - unsigned int length; + length_t length; /* * Core type, shared by a group of qualified types. */ |