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
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.
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]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
34 #include <sys/types32.h>
39 * VERSION FOR MACHINES WITH STACKS GROWING DOWNWARD IN MEMORY
41 * On program entry, the top of the stack frame looks like this:
43 * hi: |-----------------------|
45 * |-----------------------|+
47 * | arg and env strings | > no more than NCARGS bytes
49 * |-----------------------|+
51 * |-----------------------|
52 * | null auxiliary vector |
53 * |-----------------------|
54 * | auxiliary vector |
55 * | (2-word entries) |
57 * |-----------------------|
59 * |-----------------------|
60 * | ptrs to env strings |
62 * |-----------------------|
64 * |-----------------------|
65 * | ptrs to arg strings |
66 * | (argc = # of ptrs) |
68 * |-----------------------|
70 * low: |-----------------------|
73 #define RoundUp(v, t) (((v) + sizeof (t) - 1) & ~(sizeof (t) - 1))
76 kvm_getcmd32(kvm_t
*kd
,
77 struct proc
*p
, struct user
*u
, char ***arg
, char ***env
)
79 #if defined(_LP64) || defined(lint)
95 * Bring the entire stack into memory first, size it
96 * as an LP64 user stack, then allocate and copy into
97 * the buffer(s) to be returned to the caller.
99 size32
= (size_t)p
->p_usrstack
- (size_t)u
->u_argv
;
100 if ((stack32
= malloc(size32
)) == NULL
)
102 if (kvm_uread(kd
, (uintptr_t)u
->u_argv
, stack32
, size32
) != size32
) {
108 * Find the interesting sizes of a 32-bit stack.
111 stackp
= (caddr_t
)stack32
+ ((1 + argc
) * sizeof (caddr32_t
));
113 for (envc
= 0; *(caddr32_t
*)stackp
; envc
++) {
114 stackp
+= sizeof (caddr32_t
);
115 if ((stackp
- (caddr_t
)stack32
) >= size32
) {
121 if (u
->u_auxv
[0].a_type
!= AT_NULL
) {
122 stackp
+= sizeof (caddr32_t
);
123 for (auxc
= 0; *(int32_t *)stackp
; auxc
++) {
124 stackp
+= 2 * sizeof (caddr32_t
);
125 if ((stackp
- (caddr_t
)stack32
) >= size32
) {
130 auxc
++; /* terminating AT_NULL record */
134 * Compute the sizes of the stuff we're going to allocate or copy.
136 eptrcount
= (envc
+ 1) + 2 * auxc
;
137 aptrcount
= (argc
+ 1) + eptrcount
;
138 strpoolsz
= size32
- aptrcount
* sizeof (caddr32_t
);
140 asize
= aptrcount
* sizeof (uintptr_t) + RoundUp(strpoolsz
, uintptr_t);
141 if (arg
&& (argv
= calloc(1, asize
+ sizeof (uintptr_t))) == NULL
) {
146 esize
= eptrcount
* sizeof (uintptr_t) + RoundUp(strpoolsz
, uintptr_t);
147 if (env
&& (envp
= calloc(1, esize
+ sizeof (uintptr_t))) == NULL
) {
154 * Walk up the 32-bit stack, filling in the 64-bit argv and envp
157 stackp
= (caddr_t
)stack32
;
163 for (i
= 0; i
< argc
; i
++) {
164 argv
[i
] = (char *)(uintptr_t)(*(caddr32_t
*)stackp
);
165 stackp
+= sizeof (caddr32_t
);
168 stackp
+= sizeof (caddr32_t
);
170 stackp
+= (1 + argc
) * sizeof (caddr32_t
);
176 for (i
= 0; i
< envc
; i
++) {
177 envp
[i
] = (char *)(uintptr_t)(*(caddr32_t
*)stackp
);
178 stackp
+= sizeof (caddr32_t
);
181 stackp
+= sizeof (caddr32_t
);
183 stackp
+= (1 + envc
) * sizeof (caddr32_t
);
186 * auxiliary vector (skip it..)
188 stackp
+= auxc
* (sizeof (int32_t) + sizeof (uint32_t));
191 * Copy the string pool, untranslated
194 (void) memcpy(argv
+ aptrcount
, (void *)stackp
, strpoolsz
);
196 (void) memcpy(envp
+ eptrcount
, (void *)stackp
, strpoolsz
);
201 * Relocate the pointers to point at the newly allocated space.
202 * Use the same algorithms as kvm_getcmd to handle naughty
203 * changes to the argv and envp arrays.
206 char *argv_null
= (char *)argv
+ asize
;
208 reloc
= (char *)(argv
+ aptrcount
) - (char *)
209 ((caddr_t
)u
->u_argv
+ aptrcount
* sizeof (caddr32_t
));
211 for (i
= 0; i
< argc
; i
++)
212 if (argv
[i
] != NULL
) {
213 str
= (argv
[i
] += reloc
);
214 if (str
< (char *)argv
||
215 str
>= (char *)argv
+ asize
)
223 char *envp_null
= (char *)envp
+ esize
;
226 reloc
= (char *)(envp
+ eptrcount
) - (char *)
227 ((caddr_t
)u
->u_envp
+ eptrcount
* sizeof (caddr32_t
));
229 last_str
= (char *)((size_t)u
->u_argv
+
230 (1 + argc
) * sizeof (caddr32_t
) + reloc
);
231 if (last_str
< (char *)envp
||
232 last_str
>= (char *)envp
+ esize
)
233 last_str
= envp_null
;
235 for (i
= 0; i
< envc
; i
++) {
236 str
= (envp
[i
] += reloc
);
237 if (str
< (char *)envp
||
238 str
>= (char *)envp
+ esize
) {
239 if (last_str
!= envp_null
)
240 envp
[i
] = (char *)((size_t)last_str
+
241 strlen(last_str
) + 1);
249 #endif /* _LP64 || lint */
254 * reconstruct an argv-like argument list from the target process
257 kvm_getcmd(kvm_t
*kd
,
258 struct proc
*proc
, struct user
*u
, char ***arg
, char ***env
)
269 char *argv_null
; /* Known null in the returned argv */
270 char *envp_null
; /* Known null in the returned envp */
272 if (proc
->p_flag
& SSYS
) /* system process */
276 * Protect against proc structs found by kvm_nextproc()
277 * while the kernel was doing a fork(). Such a proc struct
278 * may have p_usrstack set but a still zeroed uarea.
279 * We wouldn't want to unecessarily allocate 4GB memory ...
281 if (u
->u_argv
== (uintptr_t)NULL
|| u
->u_envp
== (uintptr_t)NULL
)
285 * If this is a 32-bit process running on a 64-bit system,
286 * then the stack is laid out using ILP32 pointers, not LP64.
287 * To minimize potential confusion, we blow it up to "LP64
288 * shaped" right here.
290 if (proc
->p_model
!= DATAMODEL_NATIVE
&&
291 proc
->p_model
== DATAMODEL_ILP32
)
292 return (kvm_getcmd32(kd
, proc
, u
, arg
, env
));
295 * Space for the stack, from the argument vector. An additional
296 * word is added to guarantee a NULL word terminates the buffer.
299 asize
= (size_t)proc
->p_usrstack
- (size_t)u
->u_argv
;
300 if ((argv
= malloc(asize
+ sizeof (uintptr_t))) == NULL
)
302 argv_null
= (char *)argv
+ asize
;
303 *(uintptr_t *)argv_null
= 0;
307 * Space for the stack, from the environment vector. An additional
308 * word is added to guarantee a NULL word terminates the buffer.
311 esize
= (size_t)proc
->p_usrstack
- (size_t)u
->u_envp
;
312 if ((envp
= malloc(esize
+ sizeof (uintptr_t))) == NULL
) {
316 envp_null
= (char *)envp
+ esize
;
317 *(uintptr_t *)envp_null
= 0;
323 /* read the whole initial stack */
325 (uintptr_t)u
->u_argv
, argv
, asize
) != asize
) {
333 * Copy it to the malloc()d space for the envp array
335 (void) memcpy(envp
, &argv
[argc
+ 1], esize
);
338 /* read most of the initial stack (excluding argv) */
340 (uintptr_t)u
->u_envp
, envp
, esize
) != esize
) {
347 * Relocate and sanity check the argv array. Entries which have
348 * been explicity nulled are left that way. Entries which have
349 * been replaced are pointed to a null string. Well behaved apps
350 * don't do any of this.
353 /* relocate the argv[] addresses */
354 offset
= (char *)argv
- (char *)u
->u_argv
;
355 for (i
= 0; i
< argc
; i
++) {
356 if (argv
[i
] != NULL
) {
357 str
= (argv
[i
] += offset
);
358 if (str
< (char *)argv
||
359 str
>= (char *)argv
+ asize
)
368 * Relocate and sanity check the envp array. A null entry indicates
369 * the end of the environment. Entries which point outside of the
370 * initial stack are replaced with what must have been the initial
371 * value based on the known ordering of the string table by the
372 * kernel. If stack corruption prevents the calculation of the
373 * location of an initial string value, a pointer to a null string
374 * is returned. To return a null pointer would prematurely terminate
375 * the list. Well behaved apps do set pointers outside of the
376 * initial stack via the putenv(3C) library routine.
381 * Determine the start of the environment strings as one
382 * past the last argument string.
384 offset
= (char *)envp
- (char *)u
->u_envp
;
387 (uintptr_t)u
->u_argv
+ (argc
- 1) * sizeof (char **),
388 &last_str
, sizeof (last_str
)) != sizeof (last_str
))
389 last_str
= envp_null
;
392 if (last_str
< (char *)envp
||
393 last_str
>= (char *)envp
+ esize
)
394 last_str
= envp_null
;
398 * Relocate the envp[] addresses, while ensuring that we
399 * don't return bad addresses.
401 for (i
= 0; envp
[i
] != NULL
; i
++) {
402 str
= (envp
[i
] += offset
);
403 if (str
< (char *)envp
|| str
>= (char *)envp
+ esize
) {
404 if (last_str
!= envp_null
)
406 strlen(last_str
) + 1;