1*cf84ac9aSAndroid Build Coastguard Worker /*
2*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1991, 1992 Paul Kranenburg <[email protected]>
3*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1993 Branko Lankester <[email protected]>
4*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <[email protected]>
5*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1996-1999 Wichert Akkerman <[email protected]>
6*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7*cf84ac9aSAndroid Build Coastguard Worker * Linux for s390 port by D.J. Barrow
8*cf84ac9aSAndroid Build Coastguard Worker * <[email protected],[email protected]>
9*cf84ac9aSAndroid Build Coastguard Worker * Copyright (c) 1999-2018 The strace developers.
10*cf84ac9aSAndroid Build Coastguard Worker * All rights reserved.
11*cf84ac9aSAndroid Build Coastguard Worker *
12*cf84ac9aSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
13*cf84ac9aSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
14*cf84ac9aSAndroid Build Coastguard Worker * are met:
15*cf84ac9aSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
16*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
17*cf84ac9aSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
18*cf84ac9aSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
19*cf84ac9aSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
20*cf84ac9aSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
21*cf84ac9aSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
22*cf84ac9aSAndroid Build Coastguard Worker *
23*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24*cf84ac9aSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25*cf84ac9aSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26*cf84ac9aSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27*cf84ac9aSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28*cf84ac9aSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29*cf84ac9aSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30*cf84ac9aSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31*cf84ac9aSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32*cf84ac9aSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*cf84ac9aSAndroid Build Coastguard Worker */
34*cf84ac9aSAndroid Build Coastguard Worker
35*cf84ac9aSAndroid Build Coastguard Worker #include "defs.h"
36*cf84ac9aSAndroid Build Coastguard Worker #include <sys/uio.h>
37*cf84ac9aSAndroid Build Coastguard Worker #include <asm/unistd.h>
38*cf84ac9aSAndroid Build Coastguard Worker
39*cf84ac9aSAndroid Build Coastguard Worker #include "scno.h"
40*cf84ac9aSAndroid Build Coastguard Worker #include "ptrace.h"
41*cf84ac9aSAndroid Build Coastguard Worker
42*cf84ac9aSAndroid Build Coastguard Worker static bool process_vm_readv_not_supported;
43*cf84ac9aSAndroid Build Coastguard Worker
44*cf84ac9aSAndroid Build Coastguard Worker #ifndef HAVE_PROCESS_VM_READV
45*cf84ac9aSAndroid Build Coastguard Worker /*
46*cf84ac9aSAndroid Build Coastguard Worker * Need to do this since process_vm_readv() is not yet available in libc.
47*cf84ac9aSAndroid Build Coastguard Worker * When libc is updated, only "static bool process_vm_readv_not_supported"
48*cf84ac9aSAndroid Build Coastguard Worker * line remains.
49*cf84ac9aSAndroid Build Coastguard Worker * The name is different to avoid potential collision with OS headers.
50*cf84ac9aSAndroid Build Coastguard Worker */
strace_process_vm_readv(pid_t pid,const struct iovec * lvec,unsigned long liovcnt,const struct iovec * rvec,unsigned long riovcnt,unsigned long flags)51*cf84ac9aSAndroid Build Coastguard Worker static ssize_t strace_process_vm_readv(pid_t pid,
52*cf84ac9aSAndroid Build Coastguard Worker const struct iovec *lvec,
53*cf84ac9aSAndroid Build Coastguard Worker unsigned long liovcnt,
54*cf84ac9aSAndroid Build Coastguard Worker const struct iovec *rvec,
55*cf84ac9aSAndroid Build Coastguard Worker unsigned long riovcnt,
56*cf84ac9aSAndroid Build Coastguard Worker unsigned long flags)
57*cf84ac9aSAndroid Build Coastguard Worker {
58*cf84ac9aSAndroid Build Coastguard Worker return syscall(__NR_process_vm_readv,
59*cf84ac9aSAndroid Build Coastguard Worker (long) pid, lvec, liovcnt, rvec, riovcnt, flags);
60*cf84ac9aSAndroid Build Coastguard Worker }
61*cf84ac9aSAndroid Build Coastguard Worker # define process_vm_readv strace_process_vm_readv
62*cf84ac9aSAndroid Build Coastguard Worker #endif /* !HAVE_PROCESS_VM_READV */
63*cf84ac9aSAndroid Build Coastguard Worker
64*cf84ac9aSAndroid Build Coastguard Worker static ssize_t
vm_read_mem(const pid_t pid,void * const laddr,const kernel_ulong_t raddr,const size_t len)65*cf84ac9aSAndroid Build Coastguard Worker vm_read_mem(const pid_t pid, void *const laddr,
66*cf84ac9aSAndroid Build Coastguard Worker const kernel_ulong_t raddr, const size_t len)
67*cf84ac9aSAndroid Build Coastguard Worker {
68*cf84ac9aSAndroid Build Coastguard Worker const unsigned long truncated_raddr = raddr;
69*cf84ac9aSAndroid Build Coastguard Worker
70*cf84ac9aSAndroid Build Coastguard Worker #if SIZEOF_LONG < SIZEOF_KERNEL_LONG_T
71*cf84ac9aSAndroid Build Coastguard Worker if (raddr != (kernel_ulong_t) truncated_raddr) {
72*cf84ac9aSAndroid Build Coastguard Worker errno = EIO;
73*cf84ac9aSAndroid Build Coastguard Worker return -1;
74*cf84ac9aSAndroid Build Coastguard Worker }
75*cf84ac9aSAndroid Build Coastguard Worker #endif
76*cf84ac9aSAndroid Build Coastguard Worker
77*cf84ac9aSAndroid Build Coastguard Worker const struct iovec local = {
78*cf84ac9aSAndroid Build Coastguard Worker .iov_base = laddr,
79*cf84ac9aSAndroid Build Coastguard Worker .iov_len = len
80*cf84ac9aSAndroid Build Coastguard Worker };
81*cf84ac9aSAndroid Build Coastguard Worker const struct iovec remote = {
82*cf84ac9aSAndroid Build Coastguard Worker .iov_base = (void *) truncated_raddr,
83*cf84ac9aSAndroid Build Coastguard Worker .iov_len = len
84*cf84ac9aSAndroid Build Coastguard Worker };
85*cf84ac9aSAndroid Build Coastguard Worker
86*cf84ac9aSAndroid Build Coastguard Worker const ssize_t rc = process_vm_readv(pid, &local, 1, &remote, 1, 0);
87*cf84ac9aSAndroid Build Coastguard Worker if (rc < 0 && errno == ENOSYS)
88*cf84ac9aSAndroid Build Coastguard Worker process_vm_readv_not_supported = true;
89*cf84ac9aSAndroid Build Coastguard Worker
90*cf84ac9aSAndroid Build Coastguard Worker return rc;
91*cf84ac9aSAndroid Build Coastguard Worker }
92*cf84ac9aSAndroid Build Coastguard Worker
93*cf84ac9aSAndroid Build Coastguard Worker static bool
tracee_addr_is_invalid(kernel_ulong_t addr)94*cf84ac9aSAndroid Build Coastguard Worker tracee_addr_is_invalid(kernel_ulong_t addr)
95*cf84ac9aSAndroid Build Coastguard Worker {
96*cf84ac9aSAndroid Build Coastguard Worker return
97*cf84ac9aSAndroid Build Coastguard Worker #if ANY_WORDSIZE_LESS_THAN_KERNEL_LONG
98*cf84ac9aSAndroid Build Coastguard Worker current_wordsize < sizeof(addr) && addr & ~(kernel_ulong_t) -1U;
99*cf84ac9aSAndroid Build Coastguard Worker #else
100*cf84ac9aSAndroid Build Coastguard Worker false;
101*cf84ac9aSAndroid Build Coastguard Worker #endif
102*cf84ac9aSAndroid Build Coastguard Worker }
103*cf84ac9aSAndroid Build Coastguard Worker
104*cf84ac9aSAndroid Build Coastguard Worker /* legacy method of copying from tracee */
105*cf84ac9aSAndroid Build Coastguard Worker static int
umoven_peekdata(const int pid,kernel_ulong_t addr,unsigned int len,void * laddr)106*cf84ac9aSAndroid Build Coastguard Worker umoven_peekdata(const int pid, kernel_ulong_t addr, unsigned int len,
107*cf84ac9aSAndroid Build Coastguard Worker void *laddr)
108*cf84ac9aSAndroid Build Coastguard Worker {
109*cf84ac9aSAndroid Build Coastguard Worker unsigned int nread = 0;
110*cf84ac9aSAndroid Build Coastguard Worker unsigned int residue = addr & (sizeof(long) - 1);
111*cf84ac9aSAndroid Build Coastguard Worker
112*cf84ac9aSAndroid Build Coastguard Worker while (len) {
113*cf84ac9aSAndroid Build Coastguard Worker addr &= -sizeof(long); /* aligned address */
114*cf84ac9aSAndroid Build Coastguard Worker
115*cf84ac9aSAndroid Build Coastguard Worker errno = 0;
116*cf84ac9aSAndroid Build Coastguard Worker union {
117*cf84ac9aSAndroid Build Coastguard Worker long val;
118*cf84ac9aSAndroid Build Coastguard Worker char x[sizeof(long)];
119*cf84ac9aSAndroid Build Coastguard Worker } u = { .val = ptrace(PTRACE_PEEKDATA, pid, addr, 0) };
120*cf84ac9aSAndroid Build Coastguard Worker
121*cf84ac9aSAndroid Build Coastguard Worker switch (errno) {
122*cf84ac9aSAndroid Build Coastguard Worker case 0:
123*cf84ac9aSAndroid Build Coastguard Worker break;
124*cf84ac9aSAndroid Build Coastguard Worker case ESRCH: case EINVAL:
125*cf84ac9aSAndroid Build Coastguard Worker /* these could be seen if the process is gone */
126*cf84ac9aSAndroid Build Coastguard Worker return -1;
127*cf84ac9aSAndroid Build Coastguard Worker case EFAULT: case EIO: case EPERM:
128*cf84ac9aSAndroid Build Coastguard Worker /* address space is inaccessible */
129*cf84ac9aSAndroid Build Coastguard Worker if (nread) {
130*cf84ac9aSAndroid Build Coastguard Worker perror_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
131*cf84ac9aSAndroid Build Coastguard Worker nread, nread + len, addr - nread);
132*cf84ac9aSAndroid Build Coastguard Worker }
133*cf84ac9aSAndroid Build Coastguard Worker return -1;
134*cf84ac9aSAndroid Build Coastguard Worker default:
135*cf84ac9aSAndroid Build Coastguard Worker /* all the rest is strange and should be reported */
136*cf84ac9aSAndroid Build Coastguard Worker perror_msg("umoven: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
137*cf84ac9aSAndroid Build Coastguard Worker pid, addr);
138*cf84ac9aSAndroid Build Coastguard Worker return -1;
139*cf84ac9aSAndroid Build Coastguard Worker }
140*cf84ac9aSAndroid Build Coastguard Worker
141*cf84ac9aSAndroid Build Coastguard Worker unsigned int m = MIN(sizeof(long) - residue, len);
142*cf84ac9aSAndroid Build Coastguard Worker memcpy(laddr, &u.x[residue], m);
143*cf84ac9aSAndroid Build Coastguard Worker residue = 0;
144*cf84ac9aSAndroid Build Coastguard Worker addr += sizeof(long);
145*cf84ac9aSAndroid Build Coastguard Worker laddr += m;
146*cf84ac9aSAndroid Build Coastguard Worker nread += m;
147*cf84ac9aSAndroid Build Coastguard Worker len -= m;
148*cf84ac9aSAndroid Build Coastguard Worker }
149*cf84ac9aSAndroid Build Coastguard Worker
150*cf84ac9aSAndroid Build Coastguard Worker return 0;
151*cf84ac9aSAndroid Build Coastguard Worker }
152*cf84ac9aSAndroid Build Coastguard Worker
153*cf84ac9aSAndroid Build Coastguard Worker /*
154*cf84ac9aSAndroid Build Coastguard Worker * Copy `len' bytes of data from process `pid'
155*cf84ac9aSAndroid Build Coastguard Worker * at address `addr' to our space at `our_addr'.
156*cf84ac9aSAndroid Build Coastguard Worker */
157*cf84ac9aSAndroid Build Coastguard Worker int
umoven(struct tcb * const tcp,kernel_ulong_t addr,unsigned int len,void * const our_addr)158*cf84ac9aSAndroid Build Coastguard Worker umoven(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len,
159*cf84ac9aSAndroid Build Coastguard Worker void *const our_addr)
160*cf84ac9aSAndroid Build Coastguard Worker {
161*cf84ac9aSAndroid Build Coastguard Worker if (tracee_addr_is_invalid(addr))
162*cf84ac9aSAndroid Build Coastguard Worker return -1;
163*cf84ac9aSAndroid Build Coastguard Worker
164*cf84ac9aSAndroid Build Coastguard Worker const int pid = tcp->pid;
165*cf84ac9aSAndroid Build Coastguard Worker
166*cf84ac9aSAndroid Build Coastguard Worker if (process_vm_readv_not_supported)
167*cf84ac9aSAndroid Build Coastguard Worker return umoven_peekdata(pid, addr, len, our_addr);
168*cf84ac9aSAndroid Build Coastguard Worker
169*cf84ac9aSAndroid Build Coastguard Worker int r = vm_read_mem(pid, our_addr, addr, len);
170*cf84ac9aSAndroid Build Coastguard Worker if ((unsigned int) r == len)
171*cf84ac9aSAndroid Build Coastguard Worker return 0;
172*cf84ac9aSAndroid Build Coastguard Worker if (r >= 0) {
173*cf84ac9aSAndroid Build Coastguard Worker error_msg("umoven: short read (%u < %u) @0x%" PRI_klx,
174*cf84ac9aSAndroid Build Coastguard Worker (unsigned int) r, len, addr);
175*cf84ac9aSAndroid Build Coastguard Worker return -1;
176*cf84ac9aSAndroid Build Coastguard Worker }
177*cf84ac9aSAndroid Build Coastguard Worker switch (errno) {
178*cf84ac9aSAndroid Build Coastguard Worker case ENOSYS:
179*cf84ac9aSAndroid Build Coastguard Worker case EPERM:
180*cf84ac9aSAndroid Build Coastguard Worker /* try PTRACE_PEEKDATA */
181*cf84ac9aSAndroid Build Coastguard Worker return umoven_peekdata(pid, addr, len, our_addr);
182*cf84ac9aSAndroid Build Coastguard Worker case ESRCH:
183*cf84ac9aSAndroid Build Coastguard Worker /* the process is gone */
184*cf84ac9aSAndroid Build Coastguard Worker return -1;
185*cf84ac9aSAndroid Build Coastguard Worker case EFAULT: case EIO:
186*cf84ac9aSAndroid Build Coastguard Worker /* address space is inaccessible */
187*cf84ac9aSAndroid Build Coastguard Worker return -1;
188*cf84ac9aSAndroid Build Coastguard Worker default:
189*cf84ac9aSAndroid Build Coastguard Worker /* all the rest is strange and should be reported */
190*cf84ac9aSAndroid Build Coastguard Worker perror_msg("process_vm_readv: pid:%d @0x%" PRI_klx,
191*cf84ac9aSAndroid Build Coastguard Worker pid, addr);
192*cf84ac9aSAndroid Build Coastguard Worker return -1;
193*cf84ac9aSAndroid Build Coastguard Worker }
194*cf84ac9aSAndroid Build Coastguard Worker }
195*cf84ac9aSAndroid Build Coastguard Worker
196*cf84ac9aSAndroid Build Coastguard Worker /*
197*cf84ac9aSAndroid Build Coastguard Worker * Like umoven_peekdata but make the additional effort of looking
198*cf84ac9aSAndroid Build Coastguard Worker * for a terminating zero byte.
199*cf84ac9aSAndroid Build Coastguard Worker */
200*cf84ac9aSAndroid Build Coastguard Worker static int
umovestr_peekdata(const int pid,kernel_ulong_t addr,unsigned int len,void * laddr)201*cf84ac9aSAndroid Build Coastguard Worker umovestr_peekdata(const int pid, kernel_ulong_t addr, unsigned int len,
202*cf84ac9aSAndroid Build Coastguard Worker void *laddr)
203*cf84ac9aSAndroid Build Coastguard Worker {
204*cf84ac9aSAndroid Build Coastguard Worker unsigned int nread = 0;
205*cf84ac9aSAndroid Build Coastguard Worker unsigned int residue = addr & (sizeof(long) - 1);
206*cf84ac9aSAndroid Build Coastguard Worker void *const orig_addr = laddr;
207*cf84ac9aSAndroid Build Coastguard Worker
208*cf84ac9aSAndroid Build Coastguard Worker while (len) {
209*cf84ac9aSAndroid Build Coastguard Worker addr &= -sizeof(long); /* aligned address */
210*cf84ac9aSAndroid Build Coastguard Worker
211*cf84ac9aSAndroid Build Coastguard Worker errno = 0;
212*cf84ac9aSAndroid Build Coastguard Worker union {
213*cf84ac9aSAndroid Build Coastguard Worker unsigned long val;
214*cf84ac9aSAndroid Build Coastguard Worker char x[sizeof(long)];
215*cf84ac9aSAndroid Build Coastguard Worker } u = { .val = ptrace(PTRACE_PEEKDATA, pid, addr, 0) };
216*cf84ac9aSAndroid Build Coastguard Worker
217*cf84ac9aSAndroid Build Coastguard Worker switch (errno) {
218*cf84ac9aSAndroid Build Coastguard Worker case 0:
219*cf84ac9aSAndroid Build Coastguard Worker break;
220*cf84ac9aSAndroid Build Coastguard Worker case ESRCH: case EINVAL:
221*cf84ac9aSAndroid Build Coastguard Worker /* these could be seen if the process is gone */
222*cf84ac9aSAndroid Build Coastguard Worker return -1;
223*cf84ac9aSAndroid Build Coastguard Worker case EFAULT: case EIO: case EPERM:
224*cf84ac9aSAndroid Build Coastguard Worker /* address space is inaccessible */
225*cf84ac9aSAndroid Build Coastguard Worker if (nread) {
226*cf84ac9aSAndroid Build Coastguard Worker perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
227*cf84ac9aSAndroid Build Coastguard Worker nread, nread + len, addr - nread);
228*cf84ac9aSAndroid Build Coastguard Worker }
229*cf84ac9aSAndroid Build Coastguard Worker return -1;
230*cf84ac9aSAndroid Build Coastguard Worker default:
231*cf84ac9aSAndroid Build Coastguard Worker /* all the rest is strange and should be reported */
232*cf84ac9aSAndroid Build Coastguard Worker perror_msg("umovestr: PTRACE_PEEKDATA pid:%d @0x%" PRI_klx,
233*cf84ac9aSAndroid Build Coastguard Worker pid, addr);
234*cf84ac9aSAndroid Build Coastguard Worker return -1;
235*cf84ac9aSAndroid Build Coastguard Worker }
236*cf84ac9aSAndroid Build Coastguard Worker
237*cf84ac9aSAndroid Build Coastguard Worker unsigned int m = MIN(sizeof(long) - residue, len);
238*cf84ac9aSAndroid Build Coastguard Worker memcpy(laddr, &u.x[residue], m);
239*cf84ac9aSAndroid Build Coastguard Worker while (residue < sizeof(long))
240*cf84ac9aSAndroid Build Coastguard Worker if (u.x[residue++] == '\0')
241*cf84ac9aSAndroid Build Coastguard Worker return (laddr - orig_addr) + residue;
242*cf84ac9aSAndroid Build Coastguard Worker residue = 0;
243*cf84ac9aSAndroid Build Coastguard Worker addr += sizeof(long);
244*cf84ac9aSAndroid Build Coastguard Worker laddr += m;
245*cf84ac9aSAndroid Build Coastguard Worker nread += m;
246*cf84ac9aSAndroid Build Coastguard Worker len -= m;
247*cf84ac9aSAndroid Build Coastguard Worker }
248*cf84ac9aSAndroid Build Coastguard Worker
249*cf84ac9aSAndroid Build Coastguard Worker return 0;
250*cf84ac9aSAndroid Build Coastguard Worker }
251*cf84ac9aSAndroid Build Coastguard Worker
252*cf84ac9aSAndroid Build Coastguard Worker /*
253*cf84ac9aSAndroid Build Coastguard Worker * Like `umove' but make the additional effort of looking
254*cf84ac9aSAndroid Build Coastguard Worker * for a terminating zero byte.
255*cf84ac9aSAndroid Build Coastguard Worker *
256*cf84ac9aSAndroid Build Coastguard Worker * Returns < 0 on error, strlen + 1 if NUL was seen,
257*cf84ac9aSAndroid Build Coastguard Worker * else 0 if len bytes were read but no NUL byte seen.
258*cf84ac9aSAndroid Build Coastguard Worker *
259*cf84ac9aSAndroid Build Coastguard Worker * Note: there is no guarantee we won't overwrite some bytes
260*cf84ac9aSAndroid Build Coastguard Worker * in laddr[] _after_ terminating NUL (but, of course,
261*cf84ac9aSAndroid Build Coastguard Worker * we never write past laddr[len-1]).
262*cf84ac9aSAndroid Build Coastguard Worker */
263*cf84ac9aSAndroid Build Coastguard Worker int
umovestr(struct tcb * const tcp,kernel_ulong_t addr,unsigned int len,char * laddr)264*cf84ac9aSAndroid Build Coastguard Worker umovestr(struct tcb *const tcp, kernel_ulong_t addr, unsigned int len,
265*cf84ac9aSAndroid Build Coastguard Worker char *laddr)
266*cf84ac9aSAndroid Build Coastguard Worker {
267*cf84ac9aSAndroid Build Coastguard Worker if (tracee_addr_is_invalid(addr))
268*cf84ac9aSAndroid Build Coastguard Worker return -1;
269*cf84ac9aSAndroid Build Coastguard Worker
270*cf84ac9aSAndroid Build Coastguard Worker const int pid = tcp->pid;
271*cf84ac9aSAndroid Build Coastguard Worker
272*cf84ac9aSAndroid Build Coastguard Worker if (process_vm_readv_not_supported)
273*cf84ac9aSAndroid Build Coastguard Worker return umovestr_peekdata(pid, addr, len, laddr);
274*cf84ac9aSAndroid Build Coastguard Worker
275*cf84ac9aSAndroid Build Coastguard Worker const size_t page_size = get_pagesize();
276*cf84ac9aSAndroid Build Coastguard Worker const size_t page_mask = page_size - 1;
277*cf84ac9aSAndroid Build Coastguard Worker unsigned int nread = 0;
278*cf84ac9aSAndroid Build Coastguard Worker
279*cf84ac9aSAndroid Build Coastguard Worker while (len) {
280*cf84ac9aSAndroid Build Coastguard Worker /*
281*cf84ac9aSAndroid Build Coastguard Worker * Don't cross pages, otherwise we can get EFAULT
282*cf84ac9aSAndroid Build Coastguard Worker * and fail to notice that terminating NUL lies
283*cf84ac9aSAndroid Build Coastguard Worker * in the existing (first) page.
284*cf84ac9aSAndroid Build Coastguard Worker */
285*cf84ac9aSAndroid Build Coastguard Worker unsigned int chunk_len = len > page_size ? page_size : len;
286*cf84ac9aSAndroid Build Coastguard Worker unsigned int end_in_page = (addr + chunk_len) & page_mask;
287*cf84ac9aSAndroid Build Coastguard Worker if (chunk_len > end_in_page) /* crosses to the next page */
288*cf84ac9aSAndroid Build Coastguard Worker chunk_len -= end_in_page;
289*cf84ac9aSAndroid Build Coastguard Worker
290*cf84ac9aSAndroid Build Coastguard Worker int r = vm_read_mem(pid, laddr, addr, chunk_len);
291*cf84ac9aSAndroid Build Coastguard Worker if (r > 0) {
292*cf84ac9aSAndroid Build Coastguard Worker char *nul_addr = memchr(laddr, '\0', r);
293*cf84ac9aSAndroid Build Coastguard Worker
294*cf84ac9aSAndroid Build Coastguard Worker if (nul_addr)
295*cf84ac9aSAndroid Build Coastguard Worker return (nul_addr - laddr) + 1;
296*cf84ac9aSAndroid Build Coastguard Worker addr += r;
297*cf84ac9aSAndroid Build Coastguard Worker laddr += r;
298*cf84ac9aSAndroid Build Coastguard Worker nread += r;
299*cf84ac9aSAndroid Build Coastguard Worker len -= r;
300*cf84ac9aSAndroid Build Coastguard Worker continue;
301*cf84ac9aSAndroid Build Coastguard Worker }
302*cf84ac9aSAndroid Build Coastguard Worker switch (errno) {
303*cf84ac9aSAndroid Build Coastguard Worker case ENOSYS:
304*cf84ac9aSAndroid Build Coastguard Worker case EPERM:
305*cf84ac9aSAndroid Build Coastguard Worker /* try PTRACE_PEEKDATA */
306*cf84ac9aSAndroid Build Coastguard Worker if (!nread)
307*cf84ac9aSAndroid Build Coastguard Worker return umovestr_peekdata(pid, addr,
308*cf84ac9aSAndroid Build Coastguard Worker len, laddr);
309*cf84ac9aSAndroid Build Coastguard Worker ATTRIBUTE_FALLTHROUGH;
310*cf84ac9aSAndroid Build Coastguard Worker case EFAULT: case EIO:
311*cf84ac9aSAndroid Build Coastguard Worker /* address space is inaccessible */
312*cf84ac9aSAndroid Build Coastguard Worker if (nread)
313*cf84ac9aSAndroid Build Coastguard Worker perror_msg("umovestr: short read (%d < %d) @0x%" PRI_klx,
314*cf84ac9aSAndroid Build Coastguard Worker nread, nread + len, addr - nread);
315*cf84ac9aSAndroid Build Coastguard Worker return -1;
316*cf84ac9aSAndroid Build Coastguard Worker case ESRCH:
317*cf84ac9aSAndroid Build Coastguard Worker /* the process is gone */
318*cf84ac9aSAndroid Build Coastguard Worker return -1;
319*cf84ac9aSAndroid Build Coastguard Worker default:
320*cf84ac9aSAndroid Build Coastguard Worker /* all the rest is strange and should be reported */
321*cf84ac9aSAndroid Build Coastguard Worker perror_msg("process_vm_readv: pid:%d @0x%" PRI_klx,
322*cf84ac9aSAndroid Build Coastguard Worker pid, addr);
323*cf84ac9aSAndroid Build Coastguard Worker return -1;
324*cf84ac9aSAndroid Build Coastguard Worker }
325*cf84ac9aSAndroid Build Coastguard Worker }
326*cf84ac9aSAndroid Build Coastguard Worker
327*cf84ac9aSAndroid Build Coastguard Worker return 0;
328*cf84ac9aSAndroid Build Coastguard Worker }
329