4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright (c) 2013 by Delphix. All rights reserved.
35 #include <sys/sysmacros.h>
42 Pread_idle(struct ps_prochandle
*P
, void *buf
, size_t n
, uintptr_t addr
,
53 if ((mp
= Paddr2mptr(P
, addr
)) == NULL
)
56 mapoff
= addr
- mp
->map_pmap
.pr_vaddr
;
57 len
= MIN(resid
, mp
->map_pmap
.pr_size
- mapoff
);
58 off
= mp
->map_offset
+ mapoff
;
60 if ((len
= pread64(P
->asfd
, buf
, len
, off
)) <= 0)
65 buf
= (char *)buf
+ len
;
73 Pwrite_idle(struct ps_prochandle
*P
, const void *buf
, size_t n
, uintptr_t addr
,
82 Ppriv_idle(struct ps_prochandle
*P
, prpriv_t
**pprv
, void *data
)
86 pp
= proc_get_priv(P
->pid
);
95 /* Default operations for the idl ops vector. */
110 static const ps_ops_t P_idle_ops
= {
111 .pop_pread
= Pread_idle
,
112 .pop_pwrite
= Pwrite_idle
,
113 .pop_cred
= (pop_cred_t
)Pidle_int
,
114 .pop_priv
= Ppriv_idle
,
115 .pop_secflags
= (pop_secflags_t
)Pidle_int
,
116 .pop_psinfo
= (pop_psinfo_t
)Pidle_voidp
,
117 .pop_platform
= (pop_platform_t
)Pidle_voidp
,
118 .pop_uname
= (pop_uname_t
)Pidle_int
,
119 .pop_zonename
= (pop_zonename_t
)Pidle_voidp
,
120 #if defined(__i386) || defined(__amd64)
121 .pop_ldt
= (pop_ldt_t
)Pidle_int
126 idle_add_mapping(struct ps_prochandle
*P
, GElf_Phdr
*php
, file_info_t
*fp
)
130 dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
131 (u_longlong_t
)php
->p_vaddr
, (u_longlong_t
)php
->p_filesz
,
132 (u_longlong_t
)php
->p_memsz
, (u_longlong_t
)php
->p_offset
);
134 pmap
.pr_vaddr
= (uintptr_t)php
->p_vaddr
;
135 pmap
.pr_size
= php
->p_filesz
;
136 (void) strncpy(pmap
.pr_mapname
, fp
->file_pname
,
137 sizeof (pmap
.pr_mapname
));
138 pmap
.pr_offset
= php
->p_offset
;
141 if (php
->p_flags
& PF_R
)
142 pmap
.pr_mflags
|= MA_READ
;
143 if (php
->p_flags
& PF_W
)
144 pmap
.pr_mflags
|= MA_WRITE
;
145 if (php
->p_flags
& PF_X
)
146 pmap
.pr_mflags
|= MA_EXEC
;
148 pmap
.pr_pagesize
= 0;
151 return (Padd_mapping(P
, php
->p_offset
, fp
, &pmap
));
154 struct ps_prochandle
*
155 Pgrab_file(const char *fname
, int *perr
)
157 struct ps_prochandle
*P
= NULL
;
162 file_info_t
*fp
= NULL
;
166 if ((fd
= open64(fname
, O_RDONLY
)) < 0) {
167 dprintf("couldn't open file");
168 *perr
= (errno
== ENOENT
) ? G_NOEXEC
: G_STRANGE
;
172 if (elf_version(EV_CURRENT
) == EV_NONE
) {
173 dprintf("libproc ELF version is more recent than libelf");
178 if ((P
= calloc(1, sizeof (struct ps_prochandle
))) == NULL
) {
183 (void) mutex_init(&P
->proc_lock
, USYNC_THREAD
, NULL
);
192 Pinit_ops(&P
->ops
, &P_idle_ops
);
195 if ((elf
= elf_begin(fd
, ELF_C_READ
, NULL
)) == NULL
) {
201 * Construct a file_info_t that corresponds to this file.
203 if ((fp
= calloc(1, sizeof (file_info_t
))) == NULL
) {
208 if ((fp
->file_lo
= calloc(1, sizeof (rd_loadobj_t
))) == NULL
) {
214 (void) strncpy(fp
->file_pname
, fname
, sizeof (fp
->file_pname
));
218 if (getcwd(fp
->file_pname
, sizeof (fp
->file_pname
) - 1) ==
224 sz
= strlen(fp
->file_pname
);
225 (void) snprintf(&fp
->file_pname
[sz
],
226 sizeof (fp
->file_pname
) - sz
, "/%s", fname
);
230 fp
->file_lo
->rl_lmident
= LM_ID_BASE
;
231 if ((fp
->file_lname
= strdup(fp
->file_pname
)) == NULL
) {
235 fp
->file_lbase
= basename(fp
->file_lname
);
237 if ((P
->execname
= strdup(fp
->file_pname
)) == NULL
) {
243 list_link(fp
, &P
->file_head
);
245 if (gelf_getehdr(elf
, &ehdr
) == NULL
) {
250 if (elf_getphdrnum(elf
, &phnum
) == -1) {
255 dprintf("Pgrab_file: program header count = %lu\n", (ulong_t
)phnum
);
258 * Sift through the program headers making the relevant maps.
260 for (i
= 0; i
< phnum
; i
++) {
261 GElf_Phdr phdr
, *php
;
263 if ((php
= gelf_getphdr(elf
, i
, &phdr
)) == NULL
) {
268 if (php
->p_type
!= PT_LOAD
)
271 if (idle_add_mapping(P
, php
, fp
) != 0) {
280 P
->map_exec
= fp
->file_map
;
282 P
->status
.pr_flags
= PR_STOPPED
;
283 P
->status
.pr_nlwp
= 0;
284 P
->status
.pr_pid
= (pid_t
)-1;
285 P
->status
.pr_ppid
= (pid_t
)-1;
286 P
->status
.pr_pgid
= (pid_t
)-1;
287 P
->status
.pr_sid
= (pid_t
)-1;
288 P
->status
.pr_taskid
= (taskid_t
)-1;
289 P
->status
.pr_projid
= (projid_t
)-1;
290 P
->status
.pr_zoneid
= (zoneid_t
)-1;
291 switch (ehdr
.e_ident
[EI_CLASS
]) {
293 P
->status
.pr_dmodel
= PR_MODEL_ILP32
;
296 P
->status
.pr_dmodel
= PR_MODEL_LP64
;
304 * Pfindobj() checks what zone a process is associated with, so
305 * we call it after initializing pr_zoneid to -1. This ensures
306 * we don't get associated with any zone on the system.
308 if (Pfindobj(P
, fp
->file_lname
, buf
, sizeof (buf
)) != NULL
) {
310 P
->execname
= strdup(buf
);
311 if ((fp
->file_rname
= strdup(buf
)) != NULL
)
312 fp
->file_rbase
= basename(fp
->file_rname
);
316 * The file and map lists are complete, and will never need to be