1*6881a400Schristos /* Miscellaneous routines making it easier to use GMP within GDB's framework. 2*6881a400Schristos 3*6881a400Schristos Copyright (C) 2019-2023 Free Software Foundation, Inc. 4*6881a400Schristos 5*6881a400Schristos This file is part of GDB. 6*6881a400Schristos 7*6881a400Schristos This program is free software; you can redistribute it and/or modify 8*6881a400Schristos it under the terms of the GNU General Public License as published by 9*6881a400Schristos the Free Software Foundation; either version 3 of the License, or 10*6881a400Schristos (at your option) any later version. 11*6881a400Schristos 12*6881a400Schristos This program is distributed in the hope that it will be useful, 13*6881a400Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14*6881a400Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*6881a400Schristos GNU General Public License for more details. 16*6881a400Schristos 17*6881a400Schristos You should have received a copy of the GNU General Public License 18*6881a400Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19*6881a400Schristos 20*6881a400Schristos #ifndef GMP_UTILS_H 21*6881a400Schristos #define GMP_UTILS_H 22*6881a400Schristos 23*6881a400Schristos #include "defs.h" 24*6881a400Schristos 25*6881a400Schristos /* Include <stdio.h> and <stdarg.h> ahead of <gmp.h>, so as to get 26*6881a400Schristos access to GMP's various formatting functions. */ 27*6881a400Schristos #include <stdio.h> 28*6881a400Schristos #include <stdarg.h> 29*6881a400Schristos #include <gmp.h> 30*6881a400Schristos #include "gdbsupport/traits.h" 31*6881a400Schristos 32*6881a400Schristos /* Same as gmp_asprintf, but returning an std::string. */ 33*6881a400Schristos 34*6881a400Schristos std::string gmp_string_printf (const char *fmt, ...); 35*6881a400Schristos 36*6881a400Schristos /* A class to make it easier to use GMP's mpz_t values within GDB. */ 37*6881a400Schristos 38*6881a400Schristos struct gdb_mpz 39*6881a400Schristos { 40*6881a400Schristos mpz_t val; 41*6881a400Schristos 42*6881a400Schristos /* Constructors. */ 43*6881a400Schristos gdb_mpz () { mpz_init (val); } 44*6881a400Schristos 45*6881a400Schristos explicit gdb_mpz (const mpz_t &from_val) 46*6881a400Schristos { 47*6881a400Schristos mpz_init (val); 48*6881a400Schristos mpz_set (val, from_val); 49*6881a400Schristos } 50*6881a400Schristos 51*6881a400Schristos gdb_mpz (const gdb_mpz &from) 52*6881a400Schristos { 53*6881a400Schristos mpz_init (val); 54*6881a400Schristos mpz_set (val, from.val); 55*6881a400Schristos } 56*6881a400Schristos 57*6881a400Schristos /* Initialize using the given integral value. 58*6881a400Schristos 59*6881a400Schristos The main advantage of this method is that it handles both signed 60*6881a400Schristos and unsigned types, with no size restriction. */ 61*6881a400Schristos template<typename T, typename = gdb::Requires<std::is_integral<T>>> 62*6881a400Schristos explicit gdb_mpz (T src) 63*6881a400Schristos { 64*6881a400Schristos mpz_init (val); 65*6881a400Schristos set (src); 66*6881a400Schristos } 67*6881a400Schristos 68*6881a400Schristos explicit gdb_mpz (gdb_mpz &&from) 69*6881a400Schristos { 70*6881a400Schristos mpz_init (val); 71*6881a400Schristos mpz_swap (val, from.val); 72*6881a400Schristos } 73*6881a400Schristos 74*6881a400Schristos 75*6881a400Schristos gdb_mpz &operator= (const gdb_mpz &from) 76*6881a400Schristos { 77*6881a400Schristos mpz_set (val, from.val); 78*6881a400Schristos return *this; 79*6881a400Schristos } 80*6881a400Schristos 81*6881a400Schristos gdb_mpz &operator= (gdb_mpz &&other) 82*6881a400Schristos { 83*6881a400Schristos mpz_swap (val, other.val); 84*6881a400Schristos return *this; 85*6881a400Schristos } 86*6881a400Schristos 87*6881a400Schristos template<typename T, typename = gdb::Requires<std::is_integral<T>>> 88*6881a400Schristos gdb_mpz &operator= (T src) 89*6881a400Schristos { 90*6881a400Schristos set (src); 91*6881a400Schristos return *this; 92*6881a400Schristos } 93*6881a400Schristos 94*6881a400Schristos /* Convert VAL to an integer of the given type. 95*6881a400Schristos 96*6881a400Schristos The return type can signed or unsigned, with no size restriction. */ 97*6881a400Schristos template<typename T> T as_integer () const; 98*6881a400Schristos 99*6881a400Schristos /* Set VAL by importing the number stored in the byte array (BUF), 100*6881a400Schristos using the given BYTE_ORDER. The size of the data to read is 101*6881a400Schristos the byte array's size. 102*6881a400Schristos 103*6881a400Schristos UNSIGNED_P indicates whether the number has an unsigned type. */ 104*6881a400Schristos void read (gdb::array_view<const gdb_byte> buf, enum bfd_endian byte_order, 105*6881a400Schristos bool unsigned_p); 106*6881a400Schristos 107*6881a400Schristos /* Write VAL into BUF as a number whose byte size is the size of BUF, 108*6881a400Schristos using the given BYTE_ORDER. 109*6881a400Schristos 110*6881a400Schristos UNSIGNED_P indicates whether the number has an unsigned type. */ 111*6881a400Schristos void write (gdb::array_view<gdb_byte> buf, enum bfd_endian byte_order, 112*6881a400Schristos bool unsigned_p) const; 113*6881a400Schristos 114*6881a400Schristos /* Return a string containing VAL. */ 115*6881a400Schristos std::string str () const { return gmp_string_printf ("%Zd", val); } 116*6881a400Schristos 117*6881a400Schristos /* The destructor. */ 118*6881a400Schristos ~gdb_mpz () { mpz_clear (val); } 119*6881a400Schristos 120*6881a400Schristos private: 121*6881a400Schristos 122*6881a400Schristos /* Helper template for constructor and operator=. */ 123*6881a400Schristos template<typename T> void set (T src); 124*6881a400Schristos 125*6881a400Schristos /* Low-level function to export VAL into BUF as a number whose byte size 126*6881a400Schristos is the size of BUF. 127*6881a400Schristos 128*6881a400Schristos If UNSIGNED_P is true, then export VAL into BUF as an unsigned value. 129*6881a400Schristos Otherwise, export it as a signed value. 130*6881a400Schristos 131*6881a400Schristos The API is inspired from GMP's mpz_export, hence the naming and types 132*6881a400Schristos of the following parameter: 133*6881a400Schristos - ENDIAN should be: 134*6881a400Schristos . 1 for most significant byte first; or 135*6881a400Schristos . -1 for least significant byte first; or 136*6881a400Schristos . 0 for native endianness. 137*6881a400Schristos 138*6881a400Schristos An error is raised if BUF is not large enough to contain the value 139*6881a400Schristos being exported. */ 140*6881a400Schristos void safe_export (gdb::array_view<gdb_byte> buf, 141*6881a400Schristos int endian, bool unsigned_p) const; 142*6881a400Schristos }; 143*6881a400Schristos 144*6881a400Schristos /* A class to make it easier to use GMP's mpq_t values within GDB. */ 145*6881a400Schristos 146*6881a400Schristos struct gdb_mpq 147*6881a400Schristos { 148*6881a400Schristos mpq_t val; 149*6881a400Schristos 150*6881a400Schristos /* Constructors. */ 151*6881a400Schristos gdb_mpq () { mpq_init (val); } 152*6881a400Schristos 153*6881a400Schristos explicit gdb_mpq (const mpq_t &from_val) 154*6881a400Schristos { 155*6881a400Schristos mpq_init (val); 156*6881a400Schristos mpq_set (val, from_val); 157*6881a400Schristos } 158*6881a400Schristos 159*6881a400Schristos gdb_mpq (const gdb_mpq &from) 160*6881a400Schristos { 161*6881a400Schristos mpq_init (val); 162*6881a400Schristos mpq_set (val, from.val); 163*6881a400Schristos } 164*6881a400Schristos 165*6881a400Schristos explicit gdb_mpq (gdb_mpq &&from) 166*6881a400Schristos { 167*6881a400Schristos mpq_init (val); 168*6881a400Schristos mpq_swap (val, from.val); 169*6881a400Schristos } 170*6881a400Schristos 171*6881a400Schristos /* Copy assignment operator. */ 172*6881a400Schristos gdb_mpq &operator= (const gdb_mpq &from) 173*6881a400Schristos { 174*6881a400Schristos mpq_set (val, from.val); 175*6881a400Schristos return *this; 176*6881a400Schristos } 177*6881a400Schristos 178*6881a400Schristos gdb_mpq &operator= (gdb_mpq &&from) 179*6881a400Schristos { 180*6881a400Schristos mpq_swap (val, from.val); 181*6881a400Schristos return *this; 182*6881a400Schristos } 183*6881a400Schristos 184*6881a400Schristos /* Return a string representing VAL as "<numerator> / <denominator>". */ 185*6881a400Schristos std::string str () const { return gmp_string_printf ("%Qd", val); } 186*6881a400Schristos 187*6881a400Schristos /* Return VAL rounded to the nearest integer. */ 188*6881a400Schristos gdb_mpz get_rounded () const; 189*6881a400Schristos 190*6881a400Schristos /* Set VAL from the contents of the given byte array (BUF), which 191*6881a400Schristos contains the unscaled value of a fixed point type object. 192*6881a400Schristos The byte size of the data is the size of BUF. 193*6881a400Schristos 194*6881a400Schristos BYTE_ORDER provides the byte_order to use when reading the data. 195*6881a400Schristos 196*6881a400Schristos UNSIGNED_P indicates whether the number has an unsigned type. 197*6881a400Schristos SCALING_FACTOR is the scaling factor to apply after having 198*6881a400Schristos read the unscaled value from our buffer. */ 199*6881a400Schristos void read_fixed_point (gdb::array_view<const gdb_byte> buf, 200*6881a400Schristos enum bfd_endian byte_order, bool unsigned_p, 201*6881a400Schristos const gdb_mpq &scaling_factor); 202*6881a400Schristos 203*6881a400Schristos /* Write VAL into BUF as fixed point value following the given BYTE_ORDER. 204*6881a400Schristos The size of BUF is used as the length to write the value into. 205*6881a400Schristos 206*6881a400Schristos UNSIGNED_P indicates whether the number has an unsigned type. 207*6881a400Schristos SCALING_FACTOR is the scaling factor to apply before writing 208*6881a400Schristos the unscaled value to our buffer. */ 209*6881a400Schristos void write_fixed_point (gdb::array_view<gdb_byte> buf, 210*6881a400Schristos enum bfd_endian byte_order, bool unsigned_p, 211*6881a400Schristos const gdb_mpq &scaling_factor) const; 212*6881a400Schristos 213*6881a400Schristos /* The destructor. */ 214*6881a400Schristos ~gdb_mpq () { mpq_clear (val); } 215*6881a400Schristos }; 216*6881a400Schristos 217*6881a400Schristos /* A class to make it easier to use GMP's mpf_t values within GDB. 218*6881a400Schristos 219*6881a400Schristos Should MPFR become a required dependency, we should probably 220*6881a400Schristos drop this class in favor of using MPFR. */ 221*6881a400Schristos 222*6881a400Schristos struct gdb_mpf 223*6881a400Schristos { 224*6881a400Schristos mpf_t val; 225*6881a400Schristos 226*6881a400Schristos /* Constructors. */ 227*6881a400Schristos gdb_mpf () { mpf_init (val); } 228*6881a400Schristos 229*6881a400Schristos DISABLE_COPY_AND_ASSIGN (gdb_mpf); 230*6881a400Schristos 231*6881a400Schristos /* Set VAL from the contents of the given buffer (BUF), which 232*6881a400Schristos contains the unscaled value of a fixed point type object 233*6881a400Schristos with the given size (LEN) and byte order (BYTE_ORDER). 234*6881a400Schristos 235*6881a400Schristos UNSIGNED_P indicates whether the number has an unsigned type. 236*6881a400Schristos SCALING_FACTOR is the scaling factor to apply after having 237*6881a400Schristos read the unscaled value from our buffer. */ 238*6881a400Schristos void read_fixed_point (gdb::array_view<const gdb_byte> buf, 239*6881a400Schristos enum bfd_endian byte_order, bool unsigned_p, 240*6881a400Schristos const gdb_mpq &scaling_factor) 241*6881a400Schristos { 242*6881a400Schristos gdb_mpq tmp_q; 243*6881a400Schristos 244*6881a400Schristos tmp_q.read_fixed_point (buf, byte_order, unsigned_p, scaling_factor); 245*6881a400Schristos mpf_set_q (val, tmp_q.val); 246*6881a400Schristos } 247*6881a400Schristos 248*6881a400Schristos /* The destructor. */ 249*6881a400Schristos ~gdb_mpf () { mpf_clear (val); } 250*6881a400Schristos }; 251*6881a400Schristos 252*6881a400Schristos /* See declaration above. */ 253*6881a400Schristos 254*6881a400Schristos template<typename T> 255*6881a400Schristos void 256*6881a400Schristos gdb_mpz::set (T src) 257*6881a400Schristos { 258*6881a400Schristos mpz_import (val, 1 /* count */, -1 /* order */, 259*6881a400Schristos sizeof (T) /* size */, 0 /* endian (0 = native) */, 260*6881a400Schristos 0 /* nails */, &src /* op */); 261*6881a400Schristos if (std::is_signed<T>::value && src < 0) 262*6881a400Schristos { 263*6881a400Schristos /* mpz_import does not handle the sign, so our value was imported 264*6881a400Schristos as an unsigned. Adjust that imported value so as to make it 265*6881a400Schristos the correct negative value. */ 266*6881a400Schristos gdb_mpz neg_offset; 267*6881a400Schristos 268*6881a400Schristos mpz_ui_pow_ui (neg_offset.val, 2, sizeof (T) * HOST_CHAR_BIT); 269*6881a400Schristos mpz_sub (val, val, neg_offset.val); 270*6881a400Schristos } 271*6881a400Schristos } 272*6881a400Schristos 273*6881a400Schristos /* See declaration above. */ 274*6881a400Schristos 275*6881a400Schristos template<typename T> 276*6881a400Schristos T 277*6881a400Schristos gdb_mpz::as_integer () const 278*6881a400Schristos { 279*6881a400Schristos T result; 280*6881a400Schristos 281*6881a400Schristos this->safe_export ({(gdb_byte *) &result, sizeof (result)}, 282*6881a400Schristos 0 /* endian (0 = native) */, 283*6881a400Schristos !std::is_signed<T>::value /* unsigned_p */); 284*6881a400Schristos 285*6881a400Schristos return result; 286*6881a400Schristos } 287*6881a400Schristos 288*6881a400Schristos #endif 289