#include "_UPT_internal.h"
#if HAVE_DECL_PTRACE_POKEDATA || defined(HAVE_TTRACE)
int
_UPT_access_mem (unw_addr_space_t as UNUSED, unw_word_t addr, unw_word_t *val,
int write, void *arg)
{
struct UPT_info *ui = arg;
int i, end;
unw_word_t tmp_val;
if (!ui)
return -UNW_EINVAL;
pid_t pid = ui->pid;
if (sizeof(long) == 4 && sizeof(unw_word_t) == 8)
end = 2;
else
end = 1;
for (i = 0; i < end; i++)
{
unw_word_t tmp_addr = i == 0 ? addr : addr + 4;
errno = 0;
if (write)
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
tmp_val = i == 0 ? *val : *val >> 32;
#else
tmp_val = i == 0 && end == 2 ? *val >> 32 : *val;
#endif
Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val);
#ifdef HAVE_TTRACE
# warning No support for ttrace() yet.
#else
ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val);
if (errno)
return -UNW_EINVAL;
#endif
}
else
{
#ifdef HAVE_TTRACE
# warning No support for ttrace() yet.
#else
tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0);
if (i == 0)
*val = 0;
#if __BYTE_ORDER == __LITTLE_ENDIAN
*val |= tmp_val << (i * 32);
#else
*val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val;
#endif
if (errno)
return -UNW_EINVAL;
#endif
Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val);
}
}
return 0;
}
#elif HAVE_DECL_PT_IO
int
_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
int write, void *arg)
{
struct UPT_info *ui = arg;
if (!ui)
return -UNW_EINVAL;
pid_t pid = ui->pid;
struct ptrace_io_desc iod;
iod.piod_offs = (void *)addr;
iod.piod_addr = val;
iod.piod_len = sizeof(*val);
iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D;
if (write)
Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val);
if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1)
return -UNW_EINVAL;
if (!write)
Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val);
return 0;
}
#else
#error Fix me
#endif