Print this page
3946 ::gcore
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libproc/common/Pidle.c
+++ new/usr/src/lib/libproc/common/Pidle.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 +/*
26 + * Copyright (c) 2013 by Delphix. All rights reserved.
27 + */
25 28
26 29 #include <stdlib.h>
27 30 #include <libelf.h>
28 31 #include <libgen.h>
29 32 #include <string.h>
30 33 #include <strings.h>
31 34 #include <errno.h>
32 35 #include <sys/sysmacros.h>
33 36
34 37 #include "libproc.h"
35 38 #include "Pcontrol.h"
36 39
40 +/*ARGSUSED*/
37 41 static ssize_t
38 -Pread_idle(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
42 +Pread_idle(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
43 + void *data)
39 44 {
40 45 size_t resid = n;
41 46
42 47 while (resid > 0) {
43 48 map_info_t *mp;
44 49 uintptr_t mapoff;
45 50 ssize_t len;
46 51 off64_t off;
47 52
48 53 if ((mp = Paddr2mptr(P, addr)) == NULL)
49 54 break;
50 55
51 56 mapoff = addr - mp->map_pmap.pr_vaddr;
52 57 len = MIN(resid, mp->map_pmap.pr_size - mapoff);
53 58 off = mp->map_offset + mapoff;
54 59
55 60 if ((len = pread64(P->asfd, buf, len, off)) <= 0)
56 61 break;
57 62
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
58 63 resid -= len;
59 64 addr += len;
60 65 buf = (char *)buf + len;
61 66 }
62 67
63 68 return (n - resid);
64 69 }
65 70
66 71 /*ARGSUSED*/
67 72 static ssize_t
68 -Pwrite_idle(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
73 +Pwrite_idle(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
74 + void *data)
69 75 {
70 76 errno = EIO;
71 77 return (-1);
72 78 }
73 79
74 -static const ps_rwops_t P_idle_ops = {
75 - Pread_idle,
76 - Pwrite_idle
80 +/*ARGSUSED*/
81 +static int
82 +Ppriv_idle(struct ps_prochandle *P, prpriv_t **pprv, void *data)
83 +{
84 + prpriv_t *pp;
85 +
86 + pp = proc_get_priv(P->pid);
87 + if (pp == NULL) {
88 + return (-1);
89 + }
90 +
91 + *pprv = pp;
92 + return (0);
93 +}
94 +
95 +/* Default operations for the idl ops vector. */
96 +static void *
97 +Pidle_voidp()
98 +{
99 + errno = ENODATA;
100 + return (NULL);
101 +}
102 +
103 +static int
104 +Pidle_int()
105 +{
106 + errno = ENODATA;
107 + return (-1);
108 +}
109 +
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_psinfo = (pop_psinfo_t)Pidle_voidp,
116 + .pop_platform = (pop_platform_t)Pidle_voidp,
117 + .pop_uname = (pop_uname_t)Pidle_int,
118 + .pop_zonename = (pop_zonename_t)Pidle_voidp,
119 +#if defined(__i386) || defined(__amd64)
120 + .pop_ldt = (pop_ldt_t)Pidle_int
121 +#endif
77 122 };
78 123
79 124 static int
80 125 idle_add_mapping(struct ps_prochandle *P, GElf_Phdr *php, file_info_t *fp)
81 126 {
82 127 prmap_t pmap;
83 128
84 129 dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
85 130 (u_longlong_t)php->p_vaddr, (u_longlong_t)php->p_filesz,
86 131 (u_longlong_t)php->p_memsz, (u_longlong_t)php->p_offset);
87 132
88 133 pmap.pr_vaddr = (uintptr_t)php->p_vaddr;
89 134 pmap.pr_size = php->p_filesz;
90 135 (void) strncpy(pmap.pr_mapname, fp->file_pname,
91 136 sizeof (pmap.pr_mapname));
92 137 pmap.pr_offset = php->p_offset;
93 138
94 139 pmap.pr_mflags = 0;
95 140 if (php->p_flags & PF_R)
96 141 pmap.pr_mflags |= MA_READ;
97 142 if (php->p_flags & PF_W)
98 143 pmap.pr_mflags |= MA_WRITE;
99 144 if (php->p_flags & PF_X)
100 145 pmap.pr_mflags |= MA_EXEC;
101 146
102 147 pmap.pr_pagesize = 0;
103 148 pmap.pr_shmid = -1;
104 149
105 150 return (Padd_mapping(P, php->p_offset, fp, &pmap));
106 151 }
107 152
108 153 struct ps_prochandle *
109 154 Pgrab_file(const char *fname, int *perr)
110 155 {
111 156 struct ps_prochandle *P = NULL;
112 157 char buf[PATH_MAX];
113 158 GElf_Ehdr ehdr;
114 159 Elf *elf = NULL;
115 160 size_t phnum;
116 161 file_info_t *fp = NULL;
117 162 int fd;
118 163 int i;
119 164
120 165 if ((fd = open64(fname, O_RDONLY)) < 0) {
121 166 dprintf("couldn't open file");
122 167 *perr = (errno == ENOENT) ? G_NOEXEC : G_STRANGE;
123 168 return (NULL);
124 169 }
125 170
126 171 if (elf_version(EV_CURRENT) == EV_NONE) {
127 172 dprintf("libproc ELF version is more recent than libelf");
128 173 *perr = G_ELF;
129 174 goto err;
130 175 }
131 176
132 177 if ((P = calloc(1, sizeof (struct ps_prochandle))) == NULL) {
133 178 *perr = G_STRANGE;
134 179 goto err;
135 180 }
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
136 181
137 182 (void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);
138 183 P->state = PS_IDLE;
139 184 P->pid = (pid_t)-1;
140 185 P->asfd = fd;
141 186 P->ctlfd = -1;
142 187 P->statfd = -1;
143 188 P->agentctlfd = -1;
144 189 P->agentstatfd = -1;
145 190 P->info_valid = -1;
146 - P->ops = &P_idle_ops;
191 + Pinit_ops(&P->ops, &P_idle_ops);
147 192 Pinitsym(P);
148 193
149 194 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
150 195 *perr = G_ELF;
151 196 return (NULL);
152 197 }
153 198
154 199 /*
155 200 * Construct a file_info_t that corresponds to this file.
156 201 */
157 202 if ((fp = calloc(1, sizeof (file_info_t))) == NULL) {
158 203 *perr = G_STRANGE;
159 204 goto err;
160 205 }
161 206
162 207 if ((fp->file_lo = calloc(1, sizeof (rd_loadobj_t))) == NULL) {
163 208 *perr = G_STRANGE;
164 209 goto err;
165 210 }
166 211
167 212 if (*fname == '/') {
168 213 (void) strncpy(fp->file_pname, fname, sizeof (fp->file_pname));
169 214 } else {
170 215 size_t sz;
171 216
172 217 if (getcwd(fp->file_pname, sizeof (fp->file_pname) - 1) ==
173 218 NULL) {
174 219 *perr = G_STRANGE;
175 220 goto err;
176 221 }
177 222
178 223 sz = strlen(fp->file_pname);
179 224 (void) snprintf(&fp->file_pname[sz],
180 225 sizeof (fp->file_pname) - sz, "/%s", fname);
181 226 }
182 227
183 228 fp->file_fd = fd;
184 229 fp->file_lo->rl_lmident = LM_ID_BASE;
185 230 if ((fp->file_lname = strdup(fp->file_pname)) == NULL) {
186 231 *perr = G_STRANGE;
187 232 goto err;
188 233 }
189 234 fp->file_lbase = basename(fp->file_lname);
190 235
191 236 if ((P->execname = strdup(fp->file_pname)) == NULL) {
192 237 *perr = G_STRANGE;
193 238 goto err;
194 239 }
195 240
196 241 P->num_files++;
197 242 list_link(fp, &P->file_head);
198 243
199 244 if (gelf_getehdr(elf, &ehdr) == NULL) {
200 245 *perr = G_STRANGE;
201 246 goto err;
202 247 }
203 248
204 249 if (elf_getphdrnum(elf, &phnum) == -1) {
205 250 *perr = G_STRANGE;
206 251 goto err;
207 252 }
208 253
209 254 dprintf("Pgrab_file: program header count = %lu\n", (ulong_t)phnum);
210 255
211 256 /*
212 257 * Sift through the program headers making the relevant maps.
213 258 */
214 259 for (i = 0; i < phnum; i++) {
215 260 GElf_Phdr phdr, *php;
216 261
217 262 if ((php = gelf_getphdr(elf, i, &phdr)) == NULL) {
218 263 *perr = G_STRANGE;
219 264 goto err;
220 265 }
221 266
222 267 if (php->p_type != PT_LOAD)
223 268 continue;
224 269
225 270 if (idle_add_mapping(P, php, fp) != 0) {
226 271 *perr = G_STRANGE;
227 272 goto err;
228 273 }
229 274 }
230 275 Psort_mappings(P);
231 276
232 277 (void) elf_end(elf);
233 278
234 279 P->map_exec = fp->file_map;
235 280
236 281 P->status.pr_flags = PR_STOPPED;
237 282 P->status.pr_nlwp = 0;
238 283 P->status.pr_pid = (pid_t)-1;
239 284 P->status.pr_ppid = (pid_t)-1;
240 285 P->status.pr_pgid = (pid_t)-1;
241 286 P->status.pr_sid = (pid_t)-1;
242 287 P->status.pr_taskid = (taskid_t)-1;
243 288 P->status.pr_projid = (projid_t)-1;
244 289 P->status.pr_zoneid = (zoneid_t)-1;
245 290 switch (ehdr.e_ident[EI_CLASS]) {
246 291 case ELFCLASS32:
247 292 P->status.pr_dmodel = PR_MODEL_ILP32;
248 293 break;
249 294 case ELFCLASS64:
250 295 P->status.pr_dmodel = PR_MODEL_LP64;
251 296 break;
252 297 default:
253 298 *perr = G_FORMAT;
254 299 goto err;
255 300 }
256 301
257 302 /*
258 303 * Pfindobj() checks what zone a process is associated with, so
259 304 * we call it after initializing pr_zoneid to -1. This ensures
260 305 * we don't get associated with any zone on the system.
261 306 */
262 307 if (Pfindobj(P, fp->file_lname, buf, sizeof (buf)) != NULL) {
263 308 free(P->execname);
264 309 P->execname = strdup(buf);
265 310 if ((fp->file_rname = strdup(buf)) != NULL)
266 311 fp->file_rbase = basename(fp->file_rname);
267 312 }
268 313
269 314 /*
270 315 * The file and map lists are complete, and will never need to be
271 316 * adjusted.
272 317 */
273 318 P->info_valid = 1;
274 319
275 320 return (P);
276 321 err:
277 322 (void) close(fd);
278 323 if (P != NULL)
279 324 Pfree(P);
280 325 if (elf != NULL)
281 326 (void) elf_end(elf);
282 327 return (NULL);
283 328 }
↓ open down ↓ |
127 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX