summaryrefslogtreecommitdiffstats
path: root/lib/libthread_db
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2008-07-31 20:25:52 +0000
committermarcel <marcel@FreeBSD.org>2008-07-31 20:25:52 +0000
commit0bfdb53f7a57e9d090b45a377593b069fc8bb9cf (patch)
tree65d9947dc77c0961b657e407a18fd7a07eb7a151 /lib/libthread_db
parent60897dc1209244297522ea674bb2d05773409889 (diff)
downloadFreeBSD-src-0bfdb53f7a57e9d090b45a377593b069fc8bb9cf.zip
FreeBSD-src-0bfdb53f7a57e9d090b45a377593b069fc8bb9cf.tar.gz
Add thr_pread_{int,long,ptr} and thr_pwrite_{int,long,ptr} to
help abstract the sizes and endianness of the primary types of the target. These currently use the native characteristics.
Diffstat (limited to 'lib/libthread_db')
-rw-r--r--lib/libthread_db/thread_db.c169
-rw-r--r--lib/libthread_db/thread_db_int.h10
2 files changed, 179 insertions, 0 deletions
diff --git a/lib/libthread_db/thread_db.c b/lib/libthread_db/thread_db.c
index f129a1e..69cc42e 100644
--- a/lib/libthread_db/thread_db.c
+++ b/lib/libthread_db/thread_db.c
@@ -32,6 +32,8 @@ __FBSDID("$FreeBSD$");
#include <thread_db.h>
#include <unistd.h>
#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/errno.h>
#include <sys/linker_set.h>
#include "thread_db_int.h"
@@ -257,3 +259,170 @@ td_thr_sstep(const td_thrhandle_t *th, int step)
const td_thragent_t *ta = th->th_ta;
return (ta->ta_ops->to_thr_sstep(th, step));
}
+
+/*
+ * Support functions for reading from and writing to the target
+ * address space.
+ */
+
+static int
+thr_pread(struct ps_prochandle *ph, psaddr_t addr, uint64_t *val,
+ u_int size, u_int byteorder)
+{
+ uint8_t buf[sizeof(*val)];
+ ps_err_e err;
+
+ if (size > sizeof(buf))
+ return (EOVERFLOW);
+
+ err = ps_pread(ph, addr, buf, size);
+ if (err != PS_OK)
+ return (EFAULT);
+
+ switch (byteorder) {
+ case BIG_ENDIAN:
+ switch (size) {
+ case 1:
+ *val = buf[0];
+ break;
+ case 2:
+ *val = be16dec(buf);
+ break;
+ case 4:
+ *val = be32dec(buf);
+ break;
+ case 8:
+ *val = be64dec(buf);
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ case LITTLE_ENDIAN:
+ switch (size) {
+ case 1:
+ *val = buf[0];
+ break;
+ case 2:
+ *val = le16dec(buf);
+ break;
+ case 4:
+ *val = le32dec(buf);
+ break;
+ case 8:
+ *val = le64dec(buf);
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+int
+thr_pread_int(struct td_thragent *ta, psaddr_t addr, uint32_t *val)
+{
+ uint64_t tmp;
+ int error;
+
+ error = thr_pread(ta->ph, addr, &tmp, sizeof(int), BYTE_ORDER);
+ if (!error)
+ *val = tmp;
+
+ return (error);
+}
+
+int
+thr_pread_long(struct td_thragent *ta, psaddr_t addr, uint64_t *val)
+{
+
+ return (thr_pread(ta->ph, addr, val, sizeof(long), BYTE_ORDER));
+}
+
+int
+thr_pread_ptr(struct td_thragent *ta, psaddr_t addr, uint64_t *val)
+{
+
+ return (thr_pread(ta->ph, addr, val, sizeof(void *), BYTE_ORDER));
+}
+
+static int
+thr_pwrite(struct ps_prochandle *ph, psaddr_t addr, uint64_t val,
+ u_int size, u_int byteorder)
+{
+ uint8_t buf[sizeof(val)];
+ ps_err_e err;
+
+ if (size > sizeof(buf))
+ return (EOVERFLOW);
+
+ switch (byteorder) {
+ case BIG_ENDIAN:
+ switch (size) {
+ case 1:
+ buf[0] = (uint8_t)val;
+ break;
+ case 2:
+ be16enc(buf, (uint16_t)val);
+ break;
+ case 4:
+ be32enc(buf, (uint32_t)val);
+ break;
+ case 8:
+ be64enc(buf, (uint64_t)val);
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ case LITTLE_ENDIAN:
+ switch (size) {
+ case 1:
+ buf[0] = (uint8_t)val;
+ break;
+ case 2:
+ le16enc(buf, (uint16_t)val);
+ break;
+ case 4:
+ le32enc(buf, (uint32_t)val);
+ break;
+ case 8:
+ le64enc(buf, (uint64_t)val);
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ err = ps_pwrite(ph, addr, buf, size);
+ return ((err != PS_OK) ? EFAULT : 0);
+}
+
+int
+thr_pwrite_int(struct td_thragent *ta, psaddr_t addr, uint32_t val)
+{
+
+ return (thr_pwrite(ta->ph, addr, val, sizeof(int), BYTE_ORDER));
+}
+
+int
+thr_pwrite_long(struct td_thragent *ta, psaddr_t addr, uint64_t val)
+{
+
+ return (thr_pwrite(ta->ph, addr, val, sizeof(long), BYTE_ORDER));
+}
+
+int
+thr_pwrite_ptr(struct td_thragent *ta, psaddr_t addr, uint64_t val)
+{
+
+ return (thr_pwrite(ta->ph, addr, val, sizeof(void *), BYTE_ORDER));
+}
+
diff --git a/lib/libthread_db/thread_db_int.h b/lib/libthread_db/thread_db_int.h
index de545e3..bffa0f3 100644
--- a/lib/libthread_db/thread_db_int.h
+++ b/lib/libthread_db/thread_db_int.h
@@ -93,4 +93,14 @@ struct ta_ops {
#define TDBG_FUNC()
#endif
+struct td_thragent;
+
+int thr_pread_int(struct td_thragent *, psaddr_t, uint32_t *);
+int thr_pread_long(struct td_thragent *, psaddr_t, uint64_t *);
+int thr_pread_ptr(struct td_thragent *, psaddr_t, uint64_t *);
+
+int thr_pwrite_int(struct td_thragent *, psaddr_t, uint32_t);
+int thr_pwrite_long(struct td_thragent *, psaddr_t, uint64_t);
+int thr_pwrite_ptr(struct td_thragent *, psaddr_t, uint64_t);
+
#endif /* _THREAD_DB_INT_H_ */
OpenPOWER on IntegriCloud