Imported Upstream version 1.3.1
[platform/upstream/libunwind.git] / src / ptrace / _UPT_access_mem.c
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2003-2004 Hewlett-Packard Co
3         Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4    Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
5
6 This file is part of libunwind.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
26
27 #include "_UPT_internal.h"
28
29 #if HAVE_DECL_PTRACE_POKEDATA || HAVE_TTRACE
30 int
31 _UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
32                  int write, void *arg)
33 {
34   struct UPT_info *ui = arg;
35   int    i, end;
36   unw_word_t tmp_val;
37
38   if (!ui)
39         return -UNW_EINVAL;
40
41   pid_t pid = ui->pid;
42
43   // Some 32-bit archs have to define a 64-bit unw_word_t.
44   // Callers of this function therefore expect a 64-bit
45   // return value, but ptrace only returns a 32-bit value
46   // in such cases.
47   if (sizeof(long) == 4 && sizeof(unw_word_t) == 8)
48     end = 2;
49   else
50     end = 1;
51
52   for (i = 0; i < end; i++)
53     {
54       unw_word_t tmp_addr = i == 0 ? addr : addr + 4;
55
56       errno = 0;
57       if (write)
58         {
59 #if __BYTE_ORDER == __LITTLE_ENDIAN
60           tmp_val = i == 0 ? *val : *val >> 32;
61 #else
62           tmp_val = i == 0 && end == 2 ? *val >> 32 : *val;
63 #endif
64
65           Debug (16, "mem[%lx] <- %lx\n", (long) tmp_addr, (long) tmp_val);
66 #ifdef HAVE_TTRACE
67 #         warning No support for ttrace() yet.
68 #else
69           ptrace (PTRACE_POKEDATA, pid, tmp_addr, tmp_val);
70           if (errno)
71             return -UNW_EINVAL;
72 #endif
73         }
74       else
75         {
76 #ifdef HAVE_TTRACE
77 #         warning No support for ttrace() yet.
78 #else
79           tmp_val = (unsigned long) ptrace (PTRACE_PEEKDATA, pid, tmp_addr, 0);
80
81           if (i == 0)
82               *val = 0;
83
84 #if __BYTE_ORDER == __LITTLE_ENDIAN
85           *val |= tmp_val << (i * 32);
86 #else
87           *val |= i == 0 && end == 2 ? tmp_val << 32 : tmp_val;
88 #endif
89
90           if (errno)
91             return -UNW_EINVAL;
92 #endif
93           Debug (16, "mem[%lx] -> %lx\n", (long) tmp_addr, (long) tmp_val);
94         }
95     }
96   return 0;
97 }
98 #elif HAVE_DECL_PT_IO
99 int
100 _UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val,
101                  int write, void *arg)
102 {
103   struct UPT_info *ui = arg;
104   if (!ui)
105         return -UNW_EINVAL;
106   pid_t pid = ui->pid;
107   struct ptrace_io_desc iod;
108
109   iod.piod_offs = (void *)addr;
110   iod.piod_addr = val;
111   iod.piod_len = sizeof(*val);
112   iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D;
113   if (write)
114     Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val);
115   if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1)
116     return -UNW_EINVAL;
117   if (!write)
118      Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val);
119   return 0;
120 }
121 #else
122 #error Fix me
123 #endif