diff options
Diffstat (limited to 'libpthread/nptl_db/fetch-value.c')
| -rw-r--r-- | libpthread/nptl_db/fetch-value.c | 284 | 
1 files changed, 284 insertions, 0 deletions
| diff --git a/libpthread/nptl_db/fetch-value.c b/libpthread/nptl_db/fetch-value.c new file mode 100644 index 000000000..0d9bb0eb8 --- /dev/null +++ b/libpthread/nptl_db/fetch-value.c @@ -0,0 +1,284 @@ +/* Helper routines for libthread_db. +   Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library 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 +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "thread_dbP.h" +#include <byteswap.h> +#include <assert.h> + +td_err_e +_td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name) +{ +  if (*sizep == 0) +    { +      psaddr_t descptr; +      ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr); +      if (err == PS_NOSYM) +	return TD_NOCAPAB; +      if (err == PS_OK) +	err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep); +      if (err != PS_OK) +	return TD_ERR; +      if (*sizep & 0xff000000U) +	*sizep = bswap_32 (*sizep); +    } +  return TD_OK; +} + +td_err_e +_td_locate_field (td_thragent_t *ta, +		  db_desc_t desc, int descriptor_name, +		  psaddr_t idx, psaddr_t *address) +{ +  uint32_t elemsize; + +  if (DB_DESC_SIZE (desc) == 0) +    { +      /* Read the information about this field from the inferior.  */ +      psaddr_t descptr; +      ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr); +      if (err == PS_NOSYM) +	return TD_NOCAPAB; +      if (err == PS_OK) +	err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC); +      if (err != PS_OK) +	return TD_ERR; +      if (DB_DESC_SIZE (desc) == 0) +	return TD_DBERR; +      if (DB_DESC_SIZE (desc) & 0xff000000U) +	{ +	  /* Byte-swap these words, though we leave the size word +	     in native order as the handy way to distinguish.  */ +	  DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc)); +	  DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc)); +	} +    } + +  if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc)) +    /* This is an internal indicator to callers with nonzero IDX +       that the IDX value is too big.  */ +    return TD_NOAPLIC; + +  elemsize = DB_DESC_SIZE (desc); +  if (elemsize & 0xff000000U) +    elemsize = bswap_32 (elemsize); + +  *address += (int32_t) DB_DESC_OFFSET (desc); +  *address += (elemsize / 8 * (idx - (psaddr_t) 0)); +  return TD_OK; +} + +td_err_e +_td_fetch_value (td_thragent_t *ta, +		 db_desc_t desc, int descriptor_name, +		 psaddr_t idx, psaddr_t address, +		 psaddr_t *result) +{ +  ps_err_e err; +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      value = bswap_32 (value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      err = ps_pdread (ta->ph, address, &value, sizeof value); +      value = bswap_64 (value); +      *result = (psaddr_t) 0 + value; +    } +  else +    return TD_DBERR; + +  return err == PS_OK ? TD_OK : TD_ERR; +} + + +td_err_e +_td_store_value (td_thragent_t *ta, +		 uint32_t desc[2], int descriptor_name, psaddr_t idx, +		 psaddr_t address, psaddr_t widened_value) +{ +  ps_err_e err; +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value = widened_value - (psaddr_t) 0; +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      value = bswap_32 (value); +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      value = bswap_64 (value); +      err = ps_pdwrite (ta->ph, address, &value, sizeof value); +    } +  else +    return TD_DBERR; + +  return err == PS_OK ? TD_OK : TD_ERR; +} + +td_err_e +_td_fetch_value_local (td_thragent_t *ta, +		       db_desc_t desc, int descriptor_name, psaddr_t idx, +		       void *address, +		       psaddr_t *result) +{ +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value; +      memcpy (&value, address, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value; +      memcpy (&value, address, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      memcpy (&value, address, sizeof value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value; +      memcpy (&value, address, sizeof value); +      value = bswap_32 (value); +      *result = (psaddr_t) 0 + value; +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      memcpy (&value, address, sizeof value); +      value = bswap_64 (value); +      *result = (psaddr_t) 0 + value; +    } +  else +    return TD_DBERR; + +  return TD_OK; +} + + +td_err_e +_td_store_value_local (td_thragent_t *ta, +		       uint32_t desc[2], int descriptor_name, psaddr_t idx, +		       void *address, psaddr_t widened_value) +{ +  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); +  if (terr != TD_OK) +    return terr; + +  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) +    { +      uint8_t value = widened_value - (psaddr_t) 0; +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 32) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == 64) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (32)) +    { +      uint32_t value = widened_value - (psaddr_t) 0; +      value = bswap_32 (value); +      memcpy (address, &value, sizeof value); +    } +  else if (DB_DESC_SIZE (desc) == bswap_32 (64)) +    { +      uint64_t value = widened_value - (psaddr_t) 0; +      if (sizeof (psaddr_t) < 8) +	return TD_NOCAPAB; +      value = bswap_64 (value); +      memcpy (address, &value, sizeof value); +    } +  else +    return TD_DBERR; + +  return TD_OK; +} | 
