/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <kvm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <kvm.h>
#include <strings.h>
#define _SYSCALL32
/*
* VERSION FOR MACHINES WITH STACKS GROWING DOWNWARD IN MEMORY
*
* On program entry, the top of the stack frame looks like this:
*
* hi: |-----------------------|
* | unspecified |
* |-----------------------|+
* | : | \
* | arg and env strings | > no more than NCARGS bytes
* | : | /
* |-----------------------|+
* | unspecified |
* |-----------------------|
* | null auxiliary vector |
* |-----------------------|
* | auxiliary vector |
* | (2-word entries) |
* | : |
* |-----------------------|
* | (char *)0 |
* |-----------------------|
* | ptrs to env strings |
* | : |
* |-----------------------|
* | (char *)0 |
* |-----------------------|
* | ptrs to arg strings |
* | (argc = # of ptrs) |
* | : |
* |-----------------------|
* | argc |
* low: |-----------------------|
*/
static int
{
void *stack32;
int auxc = 0;
int aptrcount;
int eptrcount;
char *str;
/*
* Bring the entire stack into memory first, size it
* as an LP64 user stack, then allocate and copy into
* the buffer(s) to be returned to the caller.
*/
return (-1);
return (-1);
}
/*
* Find the interesting sizes of a 32-bit stack.
*/
return (-1);
}
}
return (-1);
}
}
auxc++; /* terminating AT_NULL record */
}
/*
* Compute the sizes of the stuff we're going to allocate or copy.
*/
return (-1);
}
if (argv)
return (-1);
}
/*
* Walk up the 32-bit stack, filling in the 64-bit argv and envp
* as we go.
*/
/*
* argument vector
*/
if (argv) {
for (i = 0; i < argc; i++) {
}
} else
/*
* environment
*/
if (envp) {
for (i = 0; i < envc; i++) {
}
} else
/*
* auxiliary vector (skip it..)
*/
/*
* Copy the string pool, untranslated
*/
if (argv)
if (envp)
/*
* Relocate the pointers to point at the newly allocated space.
* Use the same algorithms as kvm_getcmd to handle naughty
* changes to the argv and envp arrays.
*/
if (argv) {
for (i = 0; i < argc; i++)
}
}
if (envp) {
char *last_str;
for (i = 0; i < envc; i++) {
else
}
}
}
#endif /* _LP64 || lint */
return (0);
}
/*
* reconstruct an argv-like argument list from the target process
*/
int
{
int i;
int argc;
char *str;
char *last_str;
return (-1);
/*
* Protect against proc structs found by kvm_nextproc()
* while the kernel was doing a fork(). Such a proc struct
* may have p_usrstack set but a still zeroed uarea.
* We wouldn't want to unecessarily allocate 4GB memory ...
*/
return (-1);
/*
* If this is a 32-bit process running on a 64-bit system,
* then the stack is laid out using ILP32 pointers, not LP64.
* To minimize potential confusion, we blow it up to "LP64
* shaped" right here.
*/
/*
* Space for the stack, from the argument vector. An additional
* word is added to guarantee a NULL word terminates the buffer.
*/
if (arg) {
return (-1);
}
/*
* Space for the stack, from the environment vector. An additional
* word is added to guarantee a NULL word terminates the buffer.
*/
if (env) {
if (argv)
return (-1);
}
}
if (argv) {
/* read the whole initial stack */
if (envp)
return (-1);
}
if (envp) {
/*
* Copy it to the malloc()d space for the envp array
*/
}
} else if (envp) {
/* read most of the initial stack (excluding argv) */
return (-1);
}
}
/*
* Relocate and sanity check the argv array. Entries which have
* been explicity nulled are left that way. Entries which have
* been replaced are pointed to a null string. Well behaved apps
* don't do any of this.
*/
if (argv) {
/* relocate the argv[] addresses */
for (i = 0; i < argc; i++) {
}
}
}
/*
* Relocate and sanity check the envp array. A null entry indicates
* the end of the environment. Entries which point outside of the
* initial stack are replaced with what must have been the initial
* value based on the known ordering of the string table by the
* kernel. If stack corruption prevents the calculation of the
* location of an initial string value, a pointer to a null string
* is returned. To return a null pointer would prematurely terminate
* the list. Well behaved apps do set pointers outside of the
* initial stack via the putenv(3C) library routine.
*/
if (envp) {
/*
* Determine the start of the environment strings as one
* past the last argument string.
*/
else {
}
/*
* Relocate the envp[] addresses, while ensuring that we
* don't return bad addresses.
*/
else
}
}
}
return (0);
}