(root)/
glibc-2.38/
nptl_db/
fetch-value.c
       1  /* Helper routines for libthread_db.
       2     Copyright (C) 2003-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include "thread_dbP.h"
      20  #include <byteswap.h>
      21  #include <assert.h>
      22  #include <stdint.h>
      23  
      24  td_err_e
      25  _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
      26  {
      27    if (*sizep == 0)
      28      {
      29        psaddr_t descptr;
      30        ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
      31        if (err == PS_NOSYM)
      32  	return TD_NOCAPAB;
      33        if (err == PS_OK)
      34  	err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
      35        if (err != PS_OK)
      36  	return TD_ERR;
      37        if (*sizep & 0xff000000U)
      38  	*sizep = bswap_32 (*sizep);
      39      }
      40    return TD_OK;
      41  }
      42  
      43  td_err_e
      44  _td_locate_field (td_thragent_t *ta,
      45  		  db_desc_t desc, int descriptor_name,
      46  		  psaddr_t idx, psaddr_t *address)
      47  {
      48    uint32_t elemsize;
      49  
      50    if (DB_DESC_SIZE (desc) == 0)
      51      {
      52        /* Read the information about this field from the inferior.  */
      53        psaddr_t descptr;
      54        ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr);
      55        if (err == PS_NOSYM)
      56  	return TD_NOCAPAB;
      57        if (err == PS_OK)
      58  	err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC);
      59        if (err != PS_OK)
      60  	return TD_ERR;
      61        if (DB_DESC_SIZE (desc) == 0)
      62  	return TD_DBERR;
      63        if (DB_DESC_SIZE (desc) & 0xff000000U)
      64  	{
      65  	  /* Byte-swap these words, though we leave the size word
      66  	     in native order as the handy way to distinguish.  */
      67  	  DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc));
      68  	  DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc));
      69  	}
      70      }
      71  
      72    if (idx != 0 && DB_DESC_NELEM (desc) != 0
      73        && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
      74      /* This is an internal indicator to callers with nonzero IDX
      75         that the IDX value is too big.  */
      76      return TD_NOAPLIC;
      77  
      78    elemsize = DB_DESC_SIZE (desc);
      79    if (elemsize & 0xff000000U)
      80      elemsize = bswap_32 (elemsize);
      81  
      82    *address += (int32_t) DB_DESC_OFFSET (desc);
      83    *address += (elemsize / 8 * (idx - (psaddr_t) 0));
      84    return TD_OK;
      85  }
      86  
      87  td_err_e
      88  _td_fetch_value (td_thragent_t *ta,
      89  		 db_desc_t desc, int descriptor_name,
      90  		 psaddr_t idx, psaddr_t address,
      91  		 psaddr_t *result)
      92  {
      93    ps_err_e err;
      94    td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
      95    if (terr != TD_OK)
      96      return terr;
      97  
      98    if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
      99      {
     100        uint8_t value;
     101        err = ps_pdread (ta->ph, address, &value, sizeof value);
     102        *result = (psaddr_t) 0 + value;
     103      }
     104    else if (DB_DESC_SIZE (desc) == 32)
     105      {
     106        uint32_t value;
     107        err = ps_pdread (ta->ph, address, &value, sizeof value);
     108        *result = (psaddr_t) 0 + value;
     109      }
     110    else if (DB_DESC_SIZE (desc) == 64)
     111      {
     112        uint64_t value;
     113        if (sizeof (psaddr_t) < 8)
     114  	return TD_NOCAPAB;
     115        err = ps_pdread (ta->ph, address, &value, sizeof value);
     116        *result = (psaddr_t) 0 + value;
     117      }
     118    else if (DB_DESC_SIZE (desc) == bswap_32 (32))
     119      {
     120        uint32_t value;
     121        err = ps_pdread (ta->ph, address, &value, sizeof value);
     122        value = bswap_32 (value);
     123        *result = (psaddr_t) 0 + value;
     124      }
     125    else if (DB_DESC_SIZE (desc) == bswap_32 (64))
     126      {
     127        uint64_t value;
     128        if (sizeof (psaddr_t) < 8)
     129  	return TD_NOCAPAB;
     130        err = ps_pdread (ta->ph, address, &value, sizeof value);
     131        value = bswap_64 (value);
     132        *result = (psaddr_t) 0 + value;
     133      }
     134    else
     135      return TD_DBERR;
     136  
     137    return err == PS_OK ? TD_OK : TD_ERR;
     138  }
     139  
     140  
     141  td_err_e
     142  _td_store_value (td_thragent_t *ta,
     143  		 db_desc_t desc, int descriptor_name, psaddr_t idx,
     144  		 psaddr_t address, psaddr_t widened_value)
     145  {
     146    ps_err_e err;
     147    td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
     148    if (terr != TD_OK)
     149      return terr;
     150  
     151    if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
     152      {
     153        uint8_t value = widened_value - (psaddr_t) 0;
     154        err = ps_pdwrite (ta->ph, address, &value, sizeof value);
     155      }
     156    else if (DB_DESC_SIZE (desc) == 32)
     157      {
     158        uint32_t value = widened_value - (psaddr_t) 0;
     159        err = ps_pdwrite (ta->ph, address, &value, sizeof value);
     160      }
     161    else if (DB_DESC_SIZE (desc) == 64)
     162      {
     163        uint64_t value = widened_value - (psaddr_t) 0;
     164        if (sizeof (psaddr_t) < 8)
     165  	return TD_NOCAPAB;
     166        err = ps_pdwrite (ta->ph, address, &value, sizeof value);
     167      }
     168    else if (DB_DESC_SIZE (desc) == bswap_32 (32))
     169      {
     170        uint32_t value = widened_value - (psaddr_t) 0;
     171        value = bswap_32 (value);
     172        err = ps_pdwrite (ta->ph, address, &value, sizeof value);
     173      }
     174    else if (DB_DESC_SIZE (desc) == bswap_32 (64))
     175      {
     176        uint64_t value = widened_value - (psaddr_t) 0;
     177        if (sizeof (psaddr_t) < 8)
     178  	return TD_NOCAPAB;
     179        value = bswap_64 (value);
     180        err = ps_pdwrite (ta->ph, address, &value, sizeof value);
     181      }
     182    else
     183      return TD_DBERR;
     184  
     185    return err == PS_OK ? TD_OK : TD_ERR;
     186  }
     187  
     188  td_err_e
     189  _td_fetch_value_local (td_thragent_t *ta,
     190  		       db_desc_t desc, int descriptor_name, psaddr_t idx,
     191  		       void *address,
     192  		       psaddr_t *result)
     193  {
     194    td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
     195    if (terr != TD_OK)
     196      return terr;
     197  
     198    if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
     199      {
     200        uint8_t value;
     201        memcpy (&value, address, sizeof value);
     202        *result = (psaddr_t) 0 + value;
     203      }
     204    else if (DB_DESC_SIZE (desc) == 32)
     205      {
     206        uint32_t value;
     207        memcpy (&value, address, sizeof value);
     208        *result = (psaddr_t) 0 + value;
     209      }
     210    else if (DB_DESC_SIZE (desc) == 64)
     211      {
     212        uint64_t value;
     213        if (sizeof (psaddr_t) < 8)
     214  	return TD_NOCAPAB;
     215        memcpy (&value, address, sizeof value);
     216        *result = (psaddr_t) 0 + value;
     217      }
     218    else if (DB_DESC_SIZE (desc) == bswap_32 (32))
     219      {
     220        uint32_t value;
     221        memcpy (&value, address, sizeof value);
     222        value = bswap_32 (value);
     223        *result = (psaddr_t) 0 + value;
     224      }
     225    else if (DB_DESC_SIZE (desc) == bswap_32 (64))
     226      {
     227        uint64_t value;
     228        if (sizeof (psaddr_t) < 8)
     229  	return TD_NOCAPAB;
     230        memcpy (&value, address, sizeof value);
     231        value = bswap_64 (value);
     232        *result = (psaddr_t) 0 + value;
     233      }
     234    else
     235      return TD_DBERR;
     236  
     237    return TD_OK;
     238  }
     239  
     240  
     241  td_err_e
     242  _td_store_value_local (td_thragent_t *ta,
     243  		       db_desc_t desc, int descriptor_name, psaddr_t idx,
     244  		       void *address, psaddr_t widened_value)
     245  {
     246    td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
     247    if (terr != TD_OK)
     248      return terr;
     249  
     250    if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
     251      {
     252        uint8_t value = widened_value - (psaddr_t) 0;
     253        memcpy (address, &value, sizeof value);
     254      }
     255    else if (DB_DESC_SIZE (desc) == 32)
     256      {
     257        uint32_t value = widened_value - (psaddr_t) 0;
     258        memcpy (address, &value, sizeof value);
     259      }
     260    else if (DB_DESC_SIZE (desc) == 64)
     261      {
     262        uint64_t value = widened_value - (psaddr_t) 0;
     263        if (sizeof (psaddr_t) < 8)
     264  	return TD_NOCAPAB;
     265        memcpy (address, &value, sizeof value);
     266      }
     267    else if (DB_DESC_SIZE (desc) == bswap_32 (32))
     268      {
     269        uint32_t value = widened_value - (psaddr_t) 0;
     270        value = bswap_32 (value);
     271        memcpy (address, &value, sizeof value);
     272      }
     273    else if (DB_DESC_SIZE (desc) == bswap_32 (64))
     274      {
     275        uint64_t value = widened_value - (psaddr_t) 0;
     276        if (sizeof (psaddr_t) < 8)
     277  	return TD_NOCAPAB;
     278        value = bswap_64 (value);
     279        memcpy (address, &value, sizeof value);
     280      }
     281    else
     282      return TD_DBERR;
     283  
     284    return TD_OK;
     285  }