1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1998-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include "libproc.h"
31 
32 typedef union {
33 	offset_t	full;		/* full 64 bit offset value */
34 	uint32_t	half[2];	/* two 32-bit halves */
35 } offsets_t;
36 
37 /*
38  * lseek() system call -- executed by subject process.
39  */
40 off_t
pr_lseek(struct ps_prochandle * Pr,int filedes,off_t offset,int whence)41 pr_lseek(struct ps_prochandle *Pr, int filedes, off_t offset, int whence)
42 {
43 	int syscall;		/* SYS_lseek or SYS_llseek */
44 	int nargs;		/* 3 or 4, depending on syscall */
45 	offsets_t off;
46 	sysret_t rval;		/* return value from lseek() */
47 	argdes_t argd[4];	/* arg descriptors for lseek() */
48 	argdes_t *adp;
49 	int error;
50 
51 	if (Pr == NULL)
52 		return (lseek(filedes, offset, whence));
53 
54 	adp = &argd[0];		/* filedes argument */
55 	adp->arg_value = filedes;
56 	adp->arg_object = NULL;
57 	adp->arg_type = AT_BYVAL;
58 	adp->arg_inout = AI_INPUT;
59 	adp->arg_size = 0;
60 
61 	adp++;			/* offset argument */
62 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_NATIVE) {
63 		syscall = SYS_lseek;
64 		nargs = 3;
65 		adp->arg_value = offset;
66 		adp->arg_object = NULL;
67 		adp->arg_type = AT_BYVAL;
68 		adp->arg_inout = AI_INPUT;
69 		adp->arg_size = 0;
70 	} else {
71 		syscall = SYS_llseek;
72 		nargs = 4;
73 		off.full = offset;
74 		adp->arg_value = off.half[0];	/* first 32 bits */
75 		adp->arg_object = NULL;
76 		adp->arg_type = AT_BYVAL;
77 		adp->arg_inout = AI_INPUT;
78 		adp->arg_size = 0;
79 		adp++;
80 		adp->arg_value = off.half[1];	/* second 32 bits */
81 		adp->arg_object = NULL;
82 		adp->arg_type = AT_BYVAL;
83 		adp->arg_inout = AI_INPUT;
84 		adp->arg_size = 0;
85 	}
86 
87 	adp++;			/* whence argument */
88 	adp->arg_value = whence;
89 	adp->arg_object = NULL;
90 	adp->arg_type = AT_BYVAL;
91 	adp->arg_inout = AI_INPUT;
92 	adp->arg_size = 0;
93 
94 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
95 
96 	if (error) {
97 		errno = (error > 0)? error : ENOSYS;
98 		return ((off_t)(-1));
99 	}
100 
101 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_NATIVE)
102 		offset = rval.sys_rval1;
103 	else {
104 		off.half[0] = (uint32_t)rval.sys_rval1;
105 		off.half[1] = (uint32_t)rval.sys_rval2;
106 		offset = (off_t)off.full;
107 	}
108 
109 	return (offset);
110 }
111 
112 /*
113  * llseek() system call -- executed by subject process.
114  */
115 offset_t
pr_llseek(struct ps_prochandle * Pr,int filedes,offset_t offset,int whence)116 pr_llseek(struct ps_prochandle *Pr, int filedes, offset_t offset, int whence)
117 {
118 	int syscall;		/* SYS_lseek or SYS_llseek */
119 	int nargs;		/* 3 or 4, depending on syscall */
120 	offsets_t off;
121 	sysret_t rval;		/* return value from llseek() */
122 	argdes_t argd[4];	/* arg descriptors for llseek() */
123 	argdes_t *adp;
124 	int error;
125 
126 	if (Pr == NULL)
127 		return (llseek(filedes, offset, whence));
128 
129 	adp = &argd[0];		/* filedes argument */
130 	adp->arg_value = filedes;
131 	adp->arg_object = NULL;
132 	adp->arg_type = AT_BYVAL;
133 	adp->arg_inout = AI_INPUT;
134 	adp->arg_size = 0;
135 
136 	adp++;			/* offset argument */
137 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) {
138 		syscall = SYS_lseek;
139 		nargs = 3;
140 		adp->arg_value = offset;
141 		adp->arg_object = NULL;
142 		adp->arg_type = AT_BYVAL;
143 		adp->arg_inout = AI_INPUT;
144 		adp->arg_size = 0;
145 	} else {
146 		syscall = SYS_llseek;
147 		nargs = 4;
148 		off.full = offset;
149 		adp->arg_value = off.half[0];	/* first 32 bits */
150 		adp->arg_object = NULL;
151 		adp->arg_type = AT_BYVAL;
152 		adp->arg_inout = AI_INPUT;
153 		adp->arg_size = 0;
154 		adp++;
155 		adp->arg_value = off.half[1];	/* second 32 bits */
156 		adp->arg_object = NULL;
157 		adp->arg_type = AT_BYVAL;
158 		adp->arg_inout = AI_INPUT;
159 		adp->arg_size = 0;
160 	}
161 
162 	adp++;			/* whence argument */
163 	adp->arg_value = whence;
164 	adp->arg_object = NULL;
165 	adp->arg_type = AT_BYVAL;
166 	adp->arg_inout = AI_INPUT;
167 	adp->arg_size = 0;
168 
169 	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
170 
171 	if (error) {
172 		errno = (error > 0)? error : ENOSYS;
173 		return ((offset_t)(-1));
174 	}
175 
176 	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64)
177 		offset = rval.sys_rval1;
178 	else {
179 		off.half[0] = (uint32_t)rval.sys_rval1;
180 		off.half[1] = (uint32_t)rval.sys_rval2;
181 		offset = off.full;
182 	}
183 
184 	return (offset);
185 }
186