Back to index

glibc  2.9
fetch-value.c
Go to the documentation of this file.
00001 /* Helper routines for libthread_db.
00002    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include "thread_dbP.h"
00021 #include <byteswap.h>
00022 #include <assert.h>
00023 
00024 td_err_e
00025 _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
00026 {
00027   if (*sizep == 0)
00028     {
00029       psaddr_t descptr;
00030       ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
00031       if (err == PS_NOSYM)
00032        return TD_NOCAPAB;
00033       if (err == PS_OK)
00034        err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
00035       if (err != PS_OK)
00036        return TD_ERR;
00037       if (*sizep & 0xff000000U)
00038        *sizep = bswap_32 (*sizep);
00039     }
00040   return TD_OK;
00041 }
00042 
00043 td_err_e
00044 _td_locate_field (td_thragent_t *ta,
00045                 db_desc_t desc, int descriptor_name,
00046                 psaddr_t idx, psaddr_t *address)
00047 {
00048   uint32_t elemsize;
00049 
00050   if (DB_DESC_SIZE (desc) == 0)
00051     {
00052       /* Read the information about this field from the inferior.  */
00053       psaddr_t descptr;
00054       ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr);
00055       if (err == PS_NOSYM)
00056        return TD_NOCAPAB;
00057       if (err == PS_OK)
00058        err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC);
00059       if (err != PS_OK)
00060        return TD_ERR;
00061       if (DB_DESC_SIZE (desc) == 0)
00062        return TD_DBERR;
00063       if (DB_DESC_SIZE (desc) & 0xff000000U)
00064        {
00065          /* Byte-swap these words, though we leave the size word
00066             in native order as the handy way to distinguish.  */
00067          DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc));
00068          DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc));
00069        }
00070     }
00071 
00072   if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
00073     /* This is an internal indicator to callers with nonzero IDX
00074        that the IDX value is too big.  */
00075     return TD_NOAPLIC;
00076 
00077   elemsize = DB_DESC_SIZE (desc);
00078   if (elemsize & 0xff000000U)
00079     elemsize = bswap_32 (elemsize);
00080 
00081   *address += (int32_t) DB_DESC_OFFSET (desc);
00082   *address += (elemsize / 8 * (idx - (psaddr_t) 0));
00083   return TD_OK;
00084 }
00085 
00086 td_err_e
00087 _td_fetch_value (td_thragent_t *ta,
00088                db_desc_t desc, int descriptor_name,
00089                psaddr_t idx, psaddr_t address,
00090                psaddr_t *result)
00091 {
00092   ps_err_e err;
00093   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
00094   if (terr != TD_OK)
00095     return terr;
00096 
00097   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
00098     {
00099       uint8_t value;
00100       err = ps_pdread (ta->ph, address, &value, sizeof value);
00101       *result = (psaddr_t) 0 + value;
00102     }
00103   else if (DB_DESC_SIZE (desc) == 32)
00104     {
00105       uint32_t value;
00106       err = ps_pdread (ta->ph, address, &value, sizeof value);
00107       *result = (psaddr_t) 0 + value;
00108     }
00109   else if (DB_DESC_SIZE (desc) == 64)
00110     {
00111       uint64_t value;
00112       if (sizeof (psaddr_t) < 8)
00113        return TD_NOCAPAB;
00114       err = ps_pdread (ta->ph, address, &value, sizeof value);
00115       *result = (psaddr_t) 0 + value;
00116     }
00117   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
00118     {
00119       uint32_t value;
00120       err = ps_pdread (ta->ph, address, &value, sizeof value);
00121       value = bswap_32 (value);
00122       *result = (psaddr_t) 0 + value;
00123     }
00124   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
00125     {
00126       uint64_t value;
00127       if (sizeof (psaddr_t) < 8)
00128        return TD_NOCAPAB;
00129       err = ps_pdread (ta->ph, address, &value, sizeof value);
00130       value = bswap_64 (value);
00131       *result = (psaddr_t) 0 + value;
00132     }
00133   else
00134     return TD_DBERR;
00135 
00136   return err == PS_OK ? TD_OK : TD_ERR;
00137 }
00138 
00139 
00140 td_err_e
00141 _td_store_value (td_thragent_t *ta,
00142                uint32_t desc[2], int descriptor_name, psaddr_t idx,
00143                psaddr_t address, psaddr_t widened_value)
00144 {
00145   ps_err_e err;
00146   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
00147   if (terr != TD_OK)
00148     return terr;
00149 
00150   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
00151     {
00152       uint8_t value = widened_value - (psaddr_t) 0;
00153       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
00154     }
00155   else if (DB_DESC_SIZE (desc) == 32)
00156     {
00157       uint32_t value = widened_value - (psaddr_t) 0;
00158       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
00159     }
00160   else if (DB_DESC_SIZE (desc) == 64)
00161     {
00162       uint64_t value = widened_value - (psaddr_t) 0;
00163       if (sizeof (psaddr_t) < 8)
00164        return TD_NOCAPAB;
00165       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
00166     }
00167   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
00168     {
00169       uint32_t value = widened_value - (psaddr_t) 0;
00170       value = bswap_32 (value);
00171       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
00172     }
00173   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
00174     {
00175       uint64_t value = widened_value - (psaddr_t) 0;
00176       if (sizeof (psaddr_t) < 8)
00177        return TD_NOCAPAB;
00178       value = bswap_64 (value);
00179       err = ps_pdwrite (ta->ph, address, &value, sizeof value);
00180     }
00181   else
00182     return TD_DBERR;
00183 
00184   return err == PS_OK ? TD_OK : TD_ERR;
00185 }
00186 
00187 td_err_e
00188 _td_fetch_value_local (td_thragent_t *ta,
00189                      db_desc_t desc, int descriptor_name, psaddr_t idx,
00190                      void *address,
00191                      psaddr_t *result)
00192 {
00193   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
00194   if (terr != TD_OK)
00195     return terr;
00196 
00197   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
00198     {
00199       uint8_t value;
00200       memcpy (&value, address, sizeof value);
00201       *result = (psaddr_t) 0 + value;
00202     }
00203   else if (DB_DESC_SIZE (desc) == 32)
00204     {
00205       uint32_t value;
00206       memcpy (&value, address, sizeof value);
00207       *result = (psaddr_t) 0 + value;
00208     }
00209   else if (DB_DESC_SIZE (desc) == 64)
00210     {
00211       uint64_t value;
00212       if (sizeof (psaddr_t) < 8)
00213        return TD_NOCAPAB;
00214       memcpy (&value, address, sizeof value);
00215       *result = (psaddr_t) 0 + value;
00216     }
00217   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
00218     {
00219       uint32_t value;
00220       memcpy (&value, address, sizeof value);
00221       value = bswap_32 (value);
00222       *result = (psaddr_t) 0 + value;
00223     }
00224   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
00225     {
00226       uint64_t value;
00227       if (sizeof (psaddr_t) < 8)
00228        return TD_NOCAPAB;
00229       memcpy (&value, address, sizeof value);
00230       value = bswap_64 (value);
00231       *result = (psaddr_t) 0 + value;
00232     }
00233   else
00234     return TD_DBERR;
00235 
00236   return TD_OK;
00237 }
00238 
00239 
00240 td_err_e
00241 _td_store_value_local (td_thragent_t *ta,
00242                      uint32_t desc[2], int descriptor_name, psaddr_t idx,
00243                      void *address, psaddr_t widened_value)
00244 {
00245   td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
00246   if (terr != TD_OK)
00247     return terr;
00248 
00249   if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
00250     {
00251       uint8_t value = widened_value - (psaddr_t) 0;
00252       memcpy (address, &value, sizeof value);
00253     }
00254   else if (DB_DESC_SIZE (desc) == 32)
00255     {
00256       uint32_t value = widened_value - (psaddr_t) 0;
00257       memcpy (address, &value, sizeof value);
00258     }
00259   else if (DB_DESC_SIZE (desc) == 64)
00260     {
00261       uint64_t value = widened_value - (psaddr_t) 0;
00262       if (sizeof (psaddr_t) < 8)
00263        return TD_NOCAPAB;
00264       memcpy (address, &value, sizeof value);
00265     }
00266   else if (DB_DESC_SIZE (desc) == bswap_32 (32))
00267     {
00268       uint32_t value = widened_value - (psaddr_t) 0;
00269       value = bswap_32 (value);
00270       memcpy (address, &value, sizeof value);
00271     }
00272   else if (DB_DESC_SIZE (desc) == bswap_32 (64))
00273     {
00274       uint64_t value = widened_value - (psaddr_t) 0;
00275       if (sizeof (psaddr_t) < 8)
00276        return TD_NOCAPAB;
00277       value = bswap_64 (value);
00278       memcpy (address, &value, sizeof value);
00279     }
00280   else
00281     return TD_DBERR;
00282 
00283   return TD_OK;
00284 }