Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libproc/common/Pgcore.c
+++ new/usr/src/lib/libproc/common/Pgcore.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.
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]
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26 /*
27 27 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
28 - * Copyright 2015 Joyent, Inc.
28 + * Copyright 2018 Joyent, Inc.
29 29 * Copyright (c) 2013 by Delphix. All rights reserved.
30 30 */
31 31
32 32 #define _STRUCTURED_PROC 1
33 33
34 34 #include <stdlib.h>
35 35 #include <ctype.h>
36 36 #include <string.h>
37 37 #include <strings.h>
38 38 #include <errno.h>
39 39 #include <procfs.h>
40 40 #include <priv.h>
41 41 #include <sys/elf.h>
42 42 #include <sys/machelf.h>
43 43 #include <sys/sysmacros.h>
44 44 #include <sys/systeminfo.h>
45 45 #include <sys/proc.h>
46 46 #include <sys/utsname.h>
47 47
48 48 #include <sys/old_procfs.h>
49 49
50 50 #include "Pcontrol.h"
51 51 #include "P32ton.h"
52 52
53 53 typedef enum {
54 54 STR_NONE,
55 55 STR_CTF,
56 56 STR_SYMTAB,
57 57 STR_DYNSYM,
58 58 STR_STRTAB,
59 59 STR_DYNSTR,
60 60 STR_SHSTRTAB,
61 61 STR_NUM
62 62 } shstrtype_t;
63 63
64 64 static const char *shstrtab_data[] = {
65 65 "",
66 66 ".SUNW_ctf",
67 67 ".symtab",
68 68 ".dynsym",
69 69 ".strtab",
70 70 ".dynstr",
71 71 ".shstrtab"
72 72 };
73 73
74 74 typedef struct shstrtab {
75 75 int sst_ndx[STR_NUM];
76 76 int sst_cur;
77 77 } shstrtab_t;
78 78
79 79 typedef struct {
80 80 struct ps_prochandle *P;
81 81 int pgc_fd;
82 82 off64_t *pgc_poff;
83 83 off64_t *pgc_soff;
84 84 off64_t *pgc_doff;
85 85 core_content_t pgc_content;
86 86 void *pgc_chunk;
87 87 size_t pgc_chunksz;
88 88
89 89 shstrtab_t pgc_shstrtab;
90 90 } pgcore_t;
91 91
92 92 typedef struct {
93 93 int fd_fd;
94 94 off64_t *fd_doff;
95 95 } fditer_t;
96 96
97 97 static int
98 98 gc_pwrite64(int fd, const void *buf, size_t len, off64_t off)
99 99 {
100 100 int err;
101 101
102 102 err = pwrite64(fd, buf, len, off);
103 103
104 104 if (err < 0)
105 105 return (err);
106 106
107 107 /*
108 108 * We will take a page from ZFS's book here and use the otherwise
109 109 * unused EBADE to mean a short write. Typically this will actually
110 110 * result from ENOSPC or EDQUOT, but we can't be sure.
111 111 */
112 112 if (err < len) {
113 113 errno = EBADE;
114 114 return (-1);
115 115 }
116 116
117 117 return (0);
118 118 }
119 119
120 120 static void
121 121 shstrtab_init(shstrtab_t *s)
122 122 {
123 123 bzero(&s->sst_ndx, sizeof (s->sst_ndx));
124 124 s->sst_cur = 1;
125 125 }
126 126
127 127 static int
128 128 shstrtab_ndx(shstrtab_t *s, shstrtype_t type)
129 129 {
130 130 int ret;
131 131
132 132 if ((ret = s->sst_ndx[type]) != 0 || type == STR_NONE)
133 133 return (ret);
134 134
135 135 ret = s->sst_ndx[type] = s->sst_cur;
136 136 s->sst_cur += strlen(shstrtab_data[type]) + 1;
137 137
138 138 return (ret);
139 139 }
140 140
141 141 static size_t
142 142 shstrtab_size(const shstrtab_t *s)
143 143 {
144 144 return (s->sst_cur);
145 145 }
146 146
147 147 int
148 148 Pgcore(struct ps_prochandle *P, const char *fname, core_content_t content)
149 149 {
150 150 int fd;
151 151 int err;
152 152 int saved_errno;
153 153
154 154 if ((fd = creat64(fname, 0666)) < 0)
155 155 return (-1);
156 156
157 157 if ((err = Pfgcore(P, fd, content)) != 0) {
158 158 saved_errno = errno;
159 159 (void) close(fd);
160 160 (void) unlink(fname);
161 161 errno = saved_errno;
162 162 return (err);
163 163 }
164 164
165 165 return (close(fd));
166 166 }
167 167
168 168 /*
169 169 * Since we don't want to use the old-school procfs interfaces, we use the
170 170 * new-style data structures we already have to construct the old-style
171 171 * data structures. We include these data structures in core files for
172 172 * backward compatability.
173 173 */
174 174
175 175 static void
176 176 mkprstatus(struct ps_prochandle *P, const lwpstatus_t *lsp,
177 177 const lwpsinfo_t *lip, prstatus_t *psp)
178 178 {
179 179 bzero(psp, sizeof (*psp));
180 180
181 181 if (lsp->pr_flags & PR_STOPPED)
182 182 psp->pr_flags = 0x0001;
183 183 if (lsp->pr_flags & PR_ISTOP)
184 184 psp->pr_flags = 0x0002;
185 185 if (lsp->pr_flags & PR_DSTOP)
186 186 psp->pr_flags = 0x0004;
187 187 if (lsp->pr_flags & PR_ASLEEP)
188 188 psp->pr_flags = 0x0008;
189 189 if (lsp->pr_flags & PR_FORK)
190 190 psp->pr_flags = 0x0010;
191 191 if (lsp->pr_flags & PR_RLC)
192 192 psp->pr_flags = 0x0020;
193 193 /*
194 194 * Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set;
195 195 * PR_PCOMPAT corresponds to PR_PTRACE in the newer <sys/procfs.h>.
196 196 */
197 197 if (lsp->pr_flags & PR_PCINVAL)
198 198 psp->pr_flags = 0x0080;
199 199 if (lsp->pr_flags & PR_ISSYS)
200 200 psp->pr_flags = 0x0100;
201 201 if (lsp->pr_flags & PR_STEP)
202 202 psp->pr_flags = 0x0200;
203 203 if (lsp->pr_flags & PR_KLC)
204 204 psp->pr_flags = 0x0400;
205 205 if (lsp->pr_flags & PR_ASYNC)
206 206 psp->pr_flags = 0x0800;
207 207 if (lsp->pr_flags & PR_PTRACE)
208 208 psp->pr_flags = 0x1000;
209 209 if (lsp->pr_flags & PR_MSACCT)
210 210 psp->pr_flags = 0x2000;
211 211 if (lsp->pr_flags & PR_BPTADJ)
212 212 psp->pr_flags = 0x4000;
213 213 if (lsp->pr_flags & PR_ASLWP)
214 214 psp->pr_flags = 0x8000;
215 215
216 216 psp->pr_why = lsp->pr_why;
217 217 psp->pr_what = lsp->pr_what;
218 218 psp->pr_info = lsp->pr_info;
219 219 psp->pr_cursig = lsp->pr_cursig;
220 220 psp->pr_nlwp = P->status.pr_nlwp;
221 221 psp->pr_sigpend = P->status.pr_sigpend;
222 222 psp->pr_sighold = lsp->pr_lwphold;
223 223 psp->pr_altstack = lsp->pr_altstack;
224 224 psp->pr_action = lsp->pr_action;
225 225 psp->pr_pid = P->status.pr_pid;
226 226 psp->pr_ppid = P->status.pr_ppid;
227 227 psp->pr_pgrp = P->status.pr_pgid;
228 228 psp->pr_sid = P->status.pr_sid;
229 229 psp->pr_utime = P->status.pr_utime;
230 230 psp->pr_stime = P->status.pr_stime;
231 231 psp->pr_cutime = P->status.pr_cutime;
232 232 psp->pr_cstime = P->status.pr_cstime;
233 233 (void) strncpy(psp->pr_clname, lsp->pr_clname, sizeof (psp->pr_clname));
234 234 psp->pr_syscall = lsp->pr_syscall;
235 235 psp->pr_nsysarg = lsp->pr_nsysarg;
236 236 bcopy(lsp->pr_sysarg, psp->pr_sysarg, sizeof (psp->pr_sysarg));
237 237 psp->pr_who = lsp->pr_lwpid;
238 238 psp->pr_lwppend = lsp->pr_lwppend;
239 239 psp->pr_oldcontext = (ucontext_t *)lsp->pr_oldcontext;
240 240 psp->pr_brkbase = (caddr_t)P->status.pr_brkbase;
241 241 psp->pr_brksize = P->status.pr_brksize;
242 242 psp->pr_stkbase = (caddr_t)P->status.pr_stkbase;
243 243 psp->pr_stksize = P->status.pr_stksize;
244 244 psp->pr_processor = (short)lip->pr_onpro;
245 245 psp->pr_bind = (short)lip->pr_bindpro;
246 246 psp->pr_instr = lsp->pr_instr;
247 247 bcopy(lsp->pr_reg, psp->pr_reg, sizeof (psp->pr_sysarg));
248 248 }
249 249
250 250 static void
251 251 mkprpsinfo(struct ps_prochandle *P, prpsinfo_t *psp)
252 252 {
253 253 bzero(psp, sizeof (*psp));
254 254 psp->pr_state = P->psinfo.pr_lwp.pr_state;
255 255 psp->pr_sname = P->psinfo.pr_lwp.pr_sname;
256 256 psp->pr_zomb = (psp->pr_state == SZOMB);
257 257 psp->pr_nice = P->psinfo.pr_lwp.pr_nice;
258 258 psp->pr_flag = P->psinfo.pr_lwp.pr_flag;
259 259 psp->pr_uid = P->psinfo.pr_uid;
260 260 psp->pr_gid = P->psinfo.pr_gid;
261 261 psp->pr_pid = P->psinfo.pr_pid;
262 262 psp->pr_ppid = P->psinfo.pr_ppid;
263 263 psp->pr_pgrp = P->psinfo.pr_pgid;
264 264 psp->pr_sid = P->psinfo.pr_sid;
265 265 psp->pr_addr = (caddr_t)P->psinfo.pr_addr;
266 266 psp->pr_size = P->psinfo.pr_size;
267 267 psp->pr_rssize = P->psinfo.pr_rssize;
268 268 psp->pr_wchan = (caddr_t)P->psinfo.pr_lwp.pr_wchan;
269 269 psp->pr_start = P->psinfo.pr_start;
270 270 psp->pr_time = P->psinfo.pr_time;
271 271 psp->pr_pri = P->psinfo.pr_lwp.pr_pri;
272 272 psp->pr_oldpri = P->psinfo.pr_lwp.pr_oldpri;
273 273 psp->pr_cpu = P->psinfo.pr_lwp.pr_cpu;
274 274 psp->pr_ottydev = cmpdev(P->psinfo.pr_ttydev);
275 275 psp->pr_lttydev = P->psinfo.pr_ttydev;
276 276 (void) strncpy(psp->pr_clname, P->psinfo.pr_lwp.pr_clname,
277 277 sizeof (psp->pr_clname));
278 278 (void) strncpy(psp->pr_fname, P->psinfo.pr_fname,
279 279 sizeof (psp->pr_fname));
280 280 bcopy(&P->psinfo.pr_psargs, &psp->pr_psargs,
281 281 sizeof (psp->pr_psargs));
282 282 psp->pr_syscall = P->psinfo.pr_lwp.pr_syscall;
283 283 psp->pr_ctime = P->psinfo.pr_ctime;
284 284 psp->pr_bysize = psp->pr_size * PAGESIZE;
285 285 psp->pr_byrssize = psp->pr_rssize * PAGESIZE;
286 286 psp->pr_argc = P->psinfo.pr_argc;
287 287 psp->pr_argv = (char **)P->psinfo.pr_argv;
288 288 psp->pr_envp = (char **)P->psinfo.pr_envp;
289 289 psp->pr_wstat = P->psinfo.pr_wstat;
290 290 psp->pr_pctcpu = P->psinfo.pr_pctcpu;
291 291 psp->pr_pctmem = P->psinfo.pr_pctmem;
292 292 psp->pr_euid = P->psinfo.pr_euid;
293 293 psp->pr_egid = P->psinfo.pr_egid;
294 294 psp->pr_aslwpid = 0;
295 295 psp->pr_dmodel = P->psinfo.pr_dmodel;
296 296 }
297 297
298 298 #ifdef _LP64
299 299
300 300 static void
301 301 mkprstatus32(struct ps_prochandle *P, const lwpstatus_t *lsp,
302 302 const lwpsinfo_t *lip, prstatus32_t *psp)
303 303 {
304 304 bzero(psp, sizeof (*psp));
305 305
306 306 if (lsp->pr_flags & PR_STOPPED)
307 307 psp->pr_flags = 0x0001;
308 308 if (lsp->pr_flags & PR_ISTOP)
309 309 psp->pr_flags = 0x0002;
310 310 if (lsp->pr_flags & PR_DSTOP)
311 311 psp->pr_flags = 0x0004;
312 312 if (lsp->pr_flags & PR_ASLEEP)
313 313 psp->pr_flags = 0x0008;
314 314 if (lsp->pr_flags & PR_FORK)
315 315 psp->pr_flags = 0x0010;
316 316 if (lsp->pr_flags & PR_RLC)
317 317 psp->pr_flags = 0x0020;
318 318 /*
319 319 * Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set;
320 320 * PR_PCOMPAT corresponds to PR_PTRACE in the newer <sys/procfs.h>.
321 321 */
322 322 if (lsp->pr_flags & PR_PCINVAL)
323 323 psp->pr_flags = 0x0080;
324 324 if (lsp->pr_flags & PR_ISSYS)
325 325 psp->pr_flags = 0x0100;
326 326 if (lsp->pr_flags & PR_STEP)
327 327 psp->pr_flags = 0x0200;
328 328 if (lsp->pr_flags & PR_KLC)
329 329 psp->pr_flags = 0x0400;
330 330 if (lsp->pr_flags & PR_ASYNC)
331 331 psp->pr_flags = 0x0800;
332 332 if (lsp->pr_flags & PR_PTRACE)
333 333 psp->pr_flags = 0x1000;
334 334 if (lsp->pr_flags & PR_MSACCT)
335 335 psp->pr_flags = 0x2000;
336 336 if (lsp->pr_flags & PR_BPTADJ)
337 337 psp->pr_flags = 0x4000;
338 338 if (lsp->pr_flags & PR_ASLWP)
339 339 psp->pr_flags = 0x8000;
340 340
341 341 psp->pr_why = lsp->pr_why;
342 342 psp->pr_what = lsp->pr_what;
343 343 siginfo_n_to_32(&lsp->pr_info, &psp->pr_info);
344 344 psp->pr_cursig = lsp->pr_cursig;
345 345 psp->pr_nlwp = P->status.pr_nlwp;
346 346 psp->pr_sigpend = P->status.pr_sigpend;
347 347 psp->pr_sighold = lsp->pr_lwphold;
348 348 stack_n_to_32(&lsp->pr_altstack, &psp->pr_altstack);
349 349 sigaction_n_to_32(&lsp->pr_action, &psp->pr_action);
350 350 psp->pr_pid = P->status.pr_pid;
351 351 psp->pr_ppid = P->status.pr_ppid;
352 352 psp->pr_pgrp = P->status.pr_pgid;
353 353 psp->pr_sid = P->status.pr_sid;
354 354 timestruc_n_to_32(&P->status.pr_utime, &psp->pr_utime);
355 355 timestruc_n_to_32(&P->status.pr_stime, &psp->pr_stime);
356 356 timestruc_n_to_32(&P->status.pr_cutime, &psp->pr_cutime);
357 357 timestruc_n_to_32(&P->status.pr_cstime, &psp->pr_cstime);
358 358 (void) strncpy(psp->pr_clname, lsp->pr_clname, sizeof (psp->pr_clname));
359 359 psp->pr_syscall = lsp->pr_syscall;
360 360 psp->pr_nsysarg = lsp->pr_nsysarg;
361 361 bcopy(lsp->pr_sysarg, psp->pr_sysarg, sizeof (psp->pr_sysarg));
362 362 psp->pr_who = lsp->pr_lwpid;
363 363 psp->pr_lwppend = lsp->pr_lwppend;
364 364 psp->pr_oldcontext = (caddr32_t)lsp->pr_oldcontext;
365 365 psp->pr_brkbase = (caddr32_t)P->status.pr_brkbase;
366 366 psp->pr_brksize = P->status.pr_brksize;
367 367 psp->pr_stkbase = (caddr32_t)P->status.pr_stkbase;
368 368 psp->pr_stksize = P->status.pr_stksize;
369 369 psp->pr_processor = (short)lip->pr_onpro;
370 370 psp->pr_bind = (short)lip->pr_bindpro;
371 371 psp->pr_instr = lsp->pr_instr;
372 372 bcopy(lsp->pr_reg, psp->pr_reg, sizeof (psp->pr_sysarg));
373 373 }
374 374
375 375 static void
376 376 mkprpsinfo32(struct ps_prochandle *P, prpsinfo32_t *psp)
377 377 {
378 378 bzero(psp, sizeof (*psp));
379 379 psp->pr_state = P->psinfo.pr_lwp.pr_state;
380 380 psp->pr_sname = P->psinfo.pr_lwp.pr_sname;
381 381 psp->pr_zomb = (psp->pr_state == SZOMB);
382 382 psp->pr_nice = P->psinfo.pr_lwp.pr_nice;
383 383 psp->pr_flag = P->psinfo.pr_lwp.pr_flag;
384 384 psp->pr_uid = P->psinfo.pr_uid;
385 385 psp->pr_gid = P->psinfo.pr_gid;
386 386 psp->pr_pid = P->psinfo.pr_pid;
387 387 psp->pr_ppid = P->psinfo.pr_ppid;
388 388 psp->pr_pgrp = P->psinfo.pr_pgid;
389 389 psp->pr_sid = P->psinfo.pr_sid;
390 390 psp->pr_addr = (caddr32_t)P->psinfo.pr_addr;
391 391 psp->pr_size = P->psinfo.pr_size;
392 392 psp->pr_rssize = P->psinfo.pr_rssize;
393 393 psp->pr_wchan = (caddr32_t)P->psinfo.pr_lwp.pr_wchan;
394 394 timestruc_n_to_32(&P->psinfo.pr_start, &psp->pr_start);
395 395 timestruc_n_to_32(&P->psinfo.pr_time, &psp->pr_time);
396 396 psp->pr_pri = P->psinfo.pr_lwp.pr_pri;
397 397 psp->pr_oldpri = P->psinfo.pr_lwp.pr_oldpri;
398 398 psp->pr_cpu = P->psinfo.pr_lwp.pr_cpu;
399 399 psp->pr_ottydev = cmpdev(P->psinfo.pr_ttydev);
400 400 psp->pr_lttydev = prcmpldev(P->psinfo.pr_ttydev);
401 401 (void) strncpy(psp->pr_clname, P->psinfo.pr_lwp.pr_clname,
402 402 sizeof (psp->pr_clname));
403 403 (void) strncpy(psp->pr_fname, P->psinfo.pr_fname,
404 404 sizeof (psp->pr_fname));
405 405 bcopy(&P->psinfo.pr_psargs, &psp->pr_psargs,
406 406 sizeof (psp->pr_psargs));
407 407 psp->pr_syscall = P->psinfo.pr_lwp.pr_syscall;
408 408 timestruc_n_to_32(&P->psinfo.pr_ctime, &psp->pr_ctime);
409 409 psp->pr_bysize = psp->pr_size * PAGESIZE;
410 410 psp->pr_byrssize = psp->pr_rssize * PAGESIZE;
411 411 psp->pr_argc = P->psinfo.pr_argc;
412 412 psp->pr_argv = (caddr32_t)P->psinfo.pr_argv;
413 413 psp->pr_envp = (caddr32_t)P->psinfo.pr_envp;
414 414 psp->pr_wstat = P->psinfo.pr_wstat;
415 415 psp->pr_pctcpu = P->psinfo.pr_pctcpu;
416 416 psp->pr_pctmem = P->psinfo.pr_pctmem;
417 417 psp->pr_euid = P->psinfo.pr_euid;
418 418 psp->pr_egid = P->psinfo.pr_egid;
419 419 psp->pr_aslwpid = 0;
420 420 psp->pr_dmodel = P->psinfo.pr_dmodel;
421 421 }
422 422
423 423 #endif /* _LP64 */
424 424
425 425 static int
426 426 write_note(int fd, uint_t type, const void *desc, size_t descsz, off64_t *offp)
427 427 {
428 428 /*
429 429 * Note headers are the same regardless of the data model of the
430 430 * ELF file; we arbitrarily use Elf64_Nhdr here.
431 431 */
432 432 struct {
433 433 Elf64_Nhdr nhdr;
434 434 char name[8];
435 435 } n;
436 436
437 437 bzero(&n, sizeof (n));
438 438 bcopy("CORE", n.name, 4);
439 439 n.nhdr.n_type = type;
440 440 n.nhdr.n_namesz = 5;
441 441 n.nhdr.n_descsz = roundup(descsz, 4);
442 442
443 443 if (gc_pwrite64(fd, &n, sizeof (n), *offp) != 0)
444 444 return (-1);
445 445
446 446 *offp += sizeof (n);
447 447
448 448 if (gc_pwrite64(fd, desc, n.nhdr.n_descsz, *offp) != 0)
449 449 return (-1);
450 450
451 451 *offp += n.nhdr.n_descsz;
452 452
453 453 return (0);
454 454 }
455 455
456 456 static int
457 457 old_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
458 458 {
459 459 pgcore_t *pgc = data;
460 460 struct ps_prochandle *P = pgc->P;
461 461
462 462 /*
463 463 * Legacy core files don't contain information about zombie LWPs.
464 464 * We use Plwp_iter_all() so that we get the lwpsinfo_t structure
465 465 * more cheaply.
466 466 */
467 467 if (lsp == NULL)
468 468 return (0);
469 469
470 470 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
471 471 prstatus_t prstatus;
472 472 mkprstatus(P, lsp, lip, &prstatus);
473 473 if (write_note(pgc->pgc_fd, NT_PRSTATUS, &prstatus,
474 474 sizeof (prstatus_t), pgc->pgc_doff) != 0)
475 475 return (0);
476 476 if (write_note(pgc->pgc_fd, NT_PRFPREG, &lsp->pr_fpreg,
477 477 sizeof (prfpregset_t), pgc->pgc_doff) != 0)
478 478 return (1);
479 479 #ifdef _LP64
480 480 } else {
481 481 prstatus32_t pr32;
482 482 prfpregset32_t pf32;
483 483 mkprstatus32(P, lsp, lip, &pr32);
484 484 if (write_note(pgc->pgc_fd, NT_PRSTATUS, &pr32,
485 485 sizeof (prstatus32_t), pgc->pgc_doff) != 0)
486 486 return (1);
487 487 prfpregset_n_to_32(&lsp->pr_fpreg, &pf32);
488 488 if (write_note(pgc->pgc_fd, NT_PRFPREG, &pf32,
489 489 sizeof (prfpregset32_t), pgc->pgc_doff) != 0)
490 490 return (1);
491 491 #endif /* _LP64 */
492 492 }
493 493
494 494 #ifdef sparc
495 495 {
496 496 prxregset_t xregs;
497 497 if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs) == 0 &&
498 498 write_note(pgc->pgc_fd, NT_PRXREG, &xregs,
499 499 sizeof (prxregset_t), pgc->pgc_doff) != 0)
500 500 return (1);
501 501 }
↓ open down ↓ |
463 lines elided |
↑ open up ↑ |
502 502 #endif /* sparc */
503 503
504 504 return (0);
505 505 }
506 506
507 507 static int
508 508 new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
509 509 {
510 510 pgcore_t *pgc = data;
511 511 struct ps_prochandle *P = pgc->P;
512 + prlwpname_t name = { 0, "" };
512 513 psinfo_t ps;
513 514
514 515 /*
515 516 * If lsp is NULL this indicates that this is a zombie LWP in
516 517 * which case we dump only the lwpsinfo_t structure and none of
517 518 * the other ancillary LWP state data.
518 519 */
519 520 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
520 521 if (write_note(pgc->pgc_fd, NT_LWPSINFO, lip,
521 522 sizeof (lwpsinfo_t), pgc->pgc_doff) != 0)
522 523 return (1);
523 524 if (lsp == NULL)
524 525 return (0);
525 526 if (write_note(pgc->pgc_fd, NT_LWPSTATUS, lsp,
526 527 sizeof (lwpstatus_t), pgc->pgc_doff) != 0)
527 528 return (1);
528 529 #ifdef _LP64
529 530 } else {
530 531 lwpsinfo32_t li32;
531 532 lwpstatus32_t ls32;
532 533 lwpsinfo_n_to_32(lip, &li32);
533 534 if (write_note(pgc->pgc_fd, NT_LWPSINFO, &li32,
534 535 sizeof (lwpsinfo32_t), pgc->pgc_doff) != 0)
535 536 return (1);
536 537 if (lsp == NULL)
537 538 return (0);
538 539 lwpstatus_n_to_32(lsp, &ls32);
539 540 if (write_note(pgc->pgc_fd, NT_LWPSTATUS, &ls32,
540 541 sizeof (lwpstatus32_t), pgc->pgc_doff) != 0)
541 542 return (1);
542 543 #endif /* _LP64 */
543 544 }
544 545
545 546 #ifdef sparc
546 547 {
547 548 prxregset_t xregs;
548 549 gwindows_t gwins;
549 550 size_t size;
550 551
551 552 if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs) == 0) {
552 553 if (write_note(pgc->pgc_fd, NT_PRXREG, &xregs,
553 554 sizeof (prxregset_t), pgc->pgc_doff) != 0)
554 555 return (1);
555 556 }
556 557
557 558 if (Plwp_getgwindows(P, lsp->pr_lwpid, &gwins) == 0 &&
558 559 gwins.wbcnt > 0) {
559 560 size = sizeof (gwins) - sizeof (gwins.wbuf) +
560 561 gwins.wbcnt * sizeof (gwins.wbuf[0]);
561 562
562 563 if (write_note(pgc->pgc_fd, NT_GWINDOWS, &gwins, size,
563 564 pgc->pgc_doff) != 0)
564 565 return (1);
565 566 }
566 567
567 568 }
568 569 #ifdef __sparcv9
569 570 if (P->status.pr_dmodel == PR_MODEL_LP64) {
↓ open down ↓ |
48 lines elided |
↑ open up ↑ |
570 571 asrset_t asrs;
571 572 if (Plwp_getasrs(P, lsp->pr_lwpid, asrs) == 0) {
572 573 if (write_note(pgc->pgc_fd, NT_ASRS, &asrs,
573 574 sizeof (asrset_t), pgc->pgc_doff) != 0)
574 575 return (1);
575 576 }
576 577 }
577 578 #endif /* __sparcv9 */
578 579 #endif /* sparc */
579 580
581 + if (Plwp_getname(P, lsp->pr_lwpid, name.pr_lwpname,
582 + sizeof (name.pr_lwpname)) == 0) {
583 + name.pr_lwpid = lsp->pr_lwpid;
584 + if (write_note(pgc->pgc_fd, NT_LWPNAME, &name,
585 + sizeof (name), pgc->pgc_doff) != 0)
586 + return (1);
587 + }
588 +
580 589 if (!(lsp->pr_flags & PR_AGENT))
581 590 return (0);
582 591
583 592 if (Plwp_getspymaster(P, lsp->pr_lwpid, &ps) != 0)
584 593 return (0);
585 594
586 595 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
587 596 if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps,
588 597 sizeof (psinfo_t), pgc->pgc_doff) != 0)
589 598 return (1);
590 599 #ifdef _LP64
591 600 } else {
592 601 psinfo32_t ps32;
593 602 psinfo_n_to_32(&ps, &ps32);
594 603 if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps32,
595 604 sizeof (psinfo32_t), pgc->pgc_doff) != 0)
596 605 return (1);
597 606 #endif /* _LP64 */
598 607 }
599 608
600 609
601 610 return (0);
602 611 }
603 612
604 613 static int
605 614 iter_fd(void *data, prfdinfo_t *fdinfo)
606 615 {
607 616 fditer_t *iter = data;
608 617
609 618 if (write_note(iter->fd_fd, NT_FDINFO, fdinfo,
610 619 sizeof (*fdinfo), iter->fd_doff) != 0)
611 620 return (1);
612 621 return (0);
613 622 }
614 623
615 624 static uint_t
616 625 count_sections(pgcore_t *pgc)
617 626 {
618 627 struct ps_prochandle *P = pgc->P;
619 628 file_info_t *fptr;
620 629 uint_t cnt;
621 630 uint_t nshdrs = 0;
622 631
623 632 if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)))
624 633 return (0);
625 634
626 635 fptr = list_next(&P->file_head);
627 636 for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) {
628 637 int hit_symtab = 0;
629 638
630 639 Pbuild_file_symtab(P, fptr);
631 640
632 641 if ((pgc->pgc_content & CC_CONTENT_CTF) &&
633 642 Pbuild_file_ctf(P, fptr) != NULL) {
634 643 sym_tbl_t *sym;
635 644
636 645 nshdrs++;
637 646
638 647 if (fptr->file_ctf_dyn) {
639 648 sym = &fptr->file_dynsym;
640 649 } else {
641 650 sym = &fptr->file_symtab;
642 651 hit_symtab = 1;
643 652 }
644 653
645 654 if (sym->sym_data_pri != NULL && sym->sym_symn != 0 &&
646 655 sym->sym_strs != NULL)
647 656 nshdrs += 2;
648 657 }
649 658
650 659 if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab &&
651 660 fptr->file_symtab.sym_data_pri != NULL &&
652 661 fptr->file_symtab.sym_symn != 0 &&
653 662 fptr->file_symtab.sym_strs != NULL) {
654 663 nshdrs += 2;
655 664 }
656 665 }
657 666
658 667 return (nshdrs == 0 ? 0 : nshdrs + 2);
659 668 }
660 669
661 670 static int
662 671 write_shdr(pgcore_t *pgc, shstrtype_t name, uint_t type, ulong_t flags,
663 672 uintptr_t addr, ulong_t offset, size_t size, uint_t link, uint_t info,
664 673 uintptr_t addralign, uintptr_t entsize)
665 674 {
666 675 if (pgc->P->status.pr_dmodel == PR_MODEL_ILP32) {
667 676 Elf32_Shdr shdr;
668 677
669 678 bzero(&shdr, sizeof (shdr));
670 679 shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name);
671 680 shdr.sh_type = type;
672 681 shdr.sh_flags = flags;
673 682 shdr.sh_addr = (Elf32_Addr)addr;
674 683 shdr.sh_offset = offset;
675 684 shdr.sh_size = size;
676 685 shdr.sh_link = link;
677 686 shdr.sh_info = info;
678 687 shdr.sh_addralign = addralign;
679 688 shdr.sh_entsize = entsize;
680 689
681 690 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
682 691 *pgc->pgc_soff) != 0)
683 692 return (-1);
684 693
685 694 *pgc->pgc_soff += sizeof (shdr);
686 695 #ifdef _LP64
687 696 } else {
688 697 Elf64_Shdr shdr;
689 698
690 699 bzero(&shdr, sizeof (shdr));
691 700 shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name);
692 701 shdr.sh_type = type;
693 702 shdr.sh_flags = flags;
694 703 shdr.sh_addr = addr;
695 704 shdr.sh_offset = offset;
696 705 shdr.sh_size = size;
697 706 shdr.sh_link = link;
698 707 shdr.sh_info = info;
699 708 shdr.sh_addralign = addralign;
700 709 shdr.sh_entsize = entsize;
701 710
702 711 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
703 712 *pgc->pgc_soff) != 0)
704 713 return (-1);
705 714
706 715 *pgc->pgc_soff += sizeof (shdr);
707 716 #endif /* _LP64 */
708 717 }
709 718
710 719 return (0);
711 720 }
712 721
713 722 static int
714 723 dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym)
715 724 {
716 725 sym_tbl_t *sym = dynsym ? &fptr->file_dynsym : &fptr->file_symtab;
717 726 shstrtype_t symname = dynsym ? STR_DYNSYM : STR_SYMTAB;
718 727 shstrtype_t strname = dynsym ? STR_DYNSTR : STR_STRTAB;
719 728 uint_t symtype = dynsym ? SHT_DYNSYM : SHT_SYMTAB;
720 729 size_t size;
721 730 uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr;
722 731
723 732 if (sym->sym_data_pri == NULL || sym->sym_symn == 0 ||
724 733 sym->sym_strs == NULL)
725 734 return (0);
726 735
727 736 size = sym->sym_hdr_pri.sh_size;
728 737 if (gc_pwrite64(pgc->pgc_fd, sym->sym_data_pri->d_buf, size,
729 738 *pgc->pgc_doff) != 0)
730 739 return (-1);
731 740
732 741 if (write_shdr(pgc, symname, symtype, 0, addr, *pgc->pgc_doff, size,
733 742 index + 1, sym->sym_hdr_pri.sh_info, sym->sym_hdr_pri.sh_addralign,
734 743 sym->sym_hdr_pri.sh_entsize) != 0)
735 744 return (-1);
736 745
737 746 *pgc->pgc_doff += roundup(size, 8);
738 747
739 748 size = sym->sym_strhdr.sh_size;
740 749 if (gc_pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != 0)
741 750 return (-1);
742 751
743 752 if (write_shdr(pgc, strname, SHT_STRTAB, SHF_STRINGS, addr,
744 753 *pgc->pgc_doff, size, 0, 0, 1, 0) != 0)
745 754 return (-1);
746 755
747 756 *pgc->pgc_doff += roundup(size, 8);
748 757
749 758 return (0);
750 759 }
751 760
752 761 static int
753 762 dump_sections(pgcore_t *pgc)
754 763 {
755 764 struct ps_prochandle *P = pgc->P;
756 765 file_info_t *fptr;
757 766 uint_t cnt;
758 767 uint_t index = 1;
759 768
760 769 if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)))
761 770 return (0);
762 771
763 772 fptr = list_next(&P->file_head);
764 773 for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) {
765 774 int hit_symtab = 0;
766 775
767 776 Pbuild_file_symtab(P, fptr);
768 777
769 778 if ((pgc->pgc_content & CC_CONTENT_CTF) &&
770 779 Pbuild_file_ctf(P, fptr) != NULL) {
771 780 sym_tbl_t *sym;
772 781 uint_t dynsym;
773 782 uint_t symindex = 0;
774 783
775 784 /*
776 785 * Write the symtab out first so we can correctly
777 786 * set the sh_link field in the CTF section header.
778 787 * symindex will be 0 if there is no corresponding
779 788 * symbol table section.
780 789 */
781 790 if (fptr->file_ctf_dyn) {
782 791 sym = &fptr->file_dynsym;
783 792 dynsym = 1;
784 793 } else {
785 794 sym = &fptr->file_symtab;
786 795 dynsym = 0;
787 796 hit_symtab = 1;
788 797 }
789 798
790 799 if (sym->sym_data_pri != NULL && sym->sym_symn != 0 &&
791 800 sym->sym_strs != NULL) {
792 801 symindex = index;
793 802 if (dump_symtab(pgc, fptr, index, dynsym) != 0)
794 803 return (-1);
795 804 index += 2;
796 805 }
797 806
798 807 /*
799 808 * Write the CTF data that we've read out of the
800 809 * file itself into the core file.
801 810 */
802 811 if (gc_pwrite64(pgc->pgc_fd, fptr->file_ctf_buf,
803 812 fptr->file_ctf_size, *pgc->pgc_doff) != 0)
804 813 return (-1);
805 814
806 815 if (write_shdr(pgc, STR_CTF, SHT_PROGBITS, 0,
807 816 fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff,
808 817 fptr->file_ctf_size, symindex, 0, 4, 0) != 0)
809 818 return (-1);
810 819
811 820 index++;
812 821 *pgc->pgc_doff += roundup(fptr->file_ctf_size, 8);
813 822 }
814 823
815 824 if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab &&
816 825 fptr->file_symtab.sym_data_pri != NULL &&
817 826 fptr->file_symtab.sym_symn != 0 &&
818 827 fptr->file_symtab.sym_strs != NULL) {
819 828 if (dump_symtab(pgc, fptr, index, 0) != 0)
820 829 return (-1);
821 830 index += 2;
822 831 }
823 832 }
824 833
825 834 return (0);
826 835 }
827 836
828 837 /*ARGSUSED*/
829 838 static int
830 839 dump_map(void *data, const prmap_t *pmp, const char *name)
831 840 {
832 841 pgcore_t *pgc = data;
833 842 struct ps_prochandle *P = pgc->P;
834 843 #ifdef _LP64
835 844 Elf64_Phdr phdr;
836 845 #else
837 846 Elf32_Phdr phdr;
838 847 #endif
839 848 size_t n;
840 849
841 850 bzero(&phdr, sizeof (phdr));
842 851 phdr.p_type = PT_LOAD;
843 852 phdr.p_vaddr = pmp->pr_vaddr;
844 853 phdr.p_memsz = pmp->pr_size;
845 854 if (pmp->pr_mflags & MA_READ)
846 855 phdr.p_flags |= PF_R;
847 856 if (pmp->pr_mflags & MA_WRITE)
848 857 phdr.p_flags |= PF_W;
849 858 if (pmp->pr_mflags & MA_EXEC)
850 859 phdr.p_flags |= PF_X;
851 860
852 861 if (pmp->pr_vaddr + pmp->pr_size > P->status.pr_stkbase &&
853 862 pmp->pr_vaddr < P->status.pr_stkbase + P->status.pr_stksize) {
854 863 if (!(pgc->pgc_content & CC_CONTENT_STACK))
855 864 goto exclude;
856 865
857 866 } else if ((pmp->pr_mflags & MA_ANON) &&
858 867 pmp->pr_vaddr + pmp->pr_size > P->status.pr_brkbase &&
859 868 pmp->pr_vaddr < P->status.pr_brkbase + P->status.pr_brksize) {
860 869 if (!(pgc->pgc_content & CC_CONTENT_HEAP))
861 870 goto exclude;
862 871
863 872 } else if (pmp->pr_mflags & MA_ISM) {
864 873 if (pmp->pr_mflags & MA_NORESERVE) {
865 874 if (!(pgc->pgc_content & CC_CONTENT_DISM))
866 875 goto exclude;
867 876 } else {
868 877 if (!(pgc->pgc_content & CC_CONTENT_ISM))
869 878 goto exclude;
870 879 }
871 880
872 881 } else if (pmp->pr_mflags & MA_SHM) {
873 882 if (!(pgc->pgc_content & CC_CONTENT_SHM))
874 883 goto exclude;
875 884
876 885 } else if (pmp->pr_mflags & MA_SHARED) {
877 886 if (pmp->pr_mflags & MA_ANON) {
878 887 if (!(pgc->pgc_content & CC_CONTENT_SHANON))
879 888 goto exclude;
880 889 } else {
881 890 if (!(pgc->pgc_content & CC_CONTENT_SHFILE))
882 891 goto exclude;
883 892 }
884 893
885 894 } else if (pmp->pr_mflags & MA_ANON) {
886 895 if (!(pgc->pgc_content & CC_CONTENT_ANON))
887 896 goto exclude;
888 897
889 898 } else if (phdr.p_flags == (PF_R | PF_X)) {
890 899 if (!(pgc->pgc_content & CC_CONTENT_TEXT))
891 900 goto exclude;
892 901
893 902 } else if (phdr.p_flags == PF_R) {
894 903 if (!(pgc->pgc_content & CC_CONTENT_RODATA))
895 904 goto exclude;
896 905
897 906 } else {
898 907 if (!(pgc->pgc_content & CC_CONTENT_DATA))
899 908 goto exclude;
900 909 }
901 910
902 911 n = 0;
903 912 while (n < pmp->pr_size) {
904 913 size_t csz = MIN(pmp->pr_size - n, pgc->pgc_chunksz);
905 914
906 915 /*
907 916 * If we can't read out part of the victim's address
908 917 * space for some reason ignore that failure and try to
909 918 * emit a partial core file without that mapping's data.
910 919 * As in the kernel, we mark these failures with the
911 920 * PF_SUNW_FAILURE flag and store the errno where the
912 921 * mapping would have been.
913 922 */
914 923 if (Pread(P, pgc->pgc_chunk, csz, pmp->pr_vaddr + n) != csz ||
915 924 gc_pwrite64(pgc->pgc_fd, pgc->pgc_chunk, csz,
916 925 *pgc->pgc_doff + n) != 0) {
917 926 int err = errno;
918 927 (void) gc_pwrite64(pgc->pgc_fd, &err, sizeof (err),
919 928 *pgc->pgc_doff);
920 929 *pgc->pgc_doff += roundup(sizeof (err), 8);
921 930
922 931 phdr.p_flags |= PF_SUNW_FAILURE;
923 932 (void) ftruncate64(pgc->pgc_fd, *pgc->pgc_doff);
924 933 goto exclude;
925 934 }
926 935
927 936 n += csz;
928 937 }
929 938
930 939 phdr.p_offset = *pgc->pgc_doff;
931 940 phdr.p_filesz = pmp->pr_size;
932 941 *pgc->pgc_doff += roundup(phdr.p_filesz, 8);
933 942
934 943 exclude:
935 944 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
936 945 if (gc_pwrite64(pgc->pgc_fd, &phdr, sizeof (phdr),
937 946 *pgc->pgc_poff) != 0)
938 947 return (1);
939 948
940 949 *pgc->pgc_poff += sizeof (phdr);
941 950 #ifdef _LP64
942 951 } else {
943 952 Elf32_Phdr phdr32;
944 953
945 954 bzero(&phdr32, sizeof (phdr32));
946 955 phdr32.p_type = phdr.p_type;
947 956 phdr32.p_vaddr = (Elf32_Addr)phdr.p_vaddr;
948 957 phdr32.p_memsz = (Elf32_Word)phdr.p_memsz;
949 958 phdr32.p_flags = phdr.p_flags;
950 959 phdr32.p_offset = (Elf32_Off)phdr.p_offset;
951 960 phdr32.p_filesz = (Elf32_Word)phdr.p_filesz;
952 961
953 962 if (gc_pwrite64(pgc->pgc_fd, &phdr32, sizeof (phdr32),
954 963 *pgc->pgc_poff) != 0)
955 964 return (1);
956 965
957 966 *pgc->pgc_poff += sizeof (phdr32);
958 967 #endif /* _LP64 */
959 968 }
960 969
961 970 return (0);
962 971 }
963 972
964 973 int
965 974 write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc)
966 975 {
967 976 off64_t off = *pgc->pgc_doff;
968 977 size_t size = 0;
969 978 shstrtab_t *s = &pgc->pgc_shstrtab;
970 979 int i, ndx;
971 980
972 981 if (shstrtab_size(s) == 1)
973 982 return (0);
974 983
975 984 /*
976 985 * Preemptively stick the name of the shstrtab in the string table.
977 986 */
978 987 (void) shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB);
979 988 size = shstrtab_size(s);
980 989
981 990 /*
982 991 * Dump all the strings that we used being sure we include the
983 992 * terminating null character.
984 993 */
985 994 for (i = 0; i < STR_NUM; i++) {
986 995 if ((ndx = s->sst_ndx[i]) != 0 || i == STR_NONE) {
987 996 const char *str = shstrtab_data[i];
988 997 size_t len = strlen(str) + 1;
989 998 if (gc_pwrite64(pgc->pgc_fd, str, len, off + ndx) != 0)
990 999 return (1);
991 1000 }
992 1001 }
993 1002
994 1003 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
995 1004 Elf32_Shdr shdr;
996 1005
997 1006 bzero(&shdr, sizeof (shdr));
998 1007 shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB);
999 1008 shdr.sh_size = size;
1000 1009 shdr.sh_offset = *pgc->pgc_doff;
1001 1010 shdr.sh_addralign = 1;
1002 1011 shdr.sh_flags = SHF_STRINGS;
1003 1012 shdr.sh_type = SHT_STRTAB;
1004 1013
1005 1014 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
1006 1015 *pgc->pgc_soff) != 0)
1007 1016 return (1);
1008 1017
1009 1018 *pgc->pgc_soff += sizeof (shdr);
1010 1019 #ifdef _LP64
1011 1020 } else {
1012 1021 Elf64_Shdr shdr;
1013 1022
1014 1023 bzero(&shdr, sizeof (shdr));
1015 1024 shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB);
1016 1025 shdr.sh_size = size;
1017 1026 shdr.sh_offset = *pgc->pgc_doff;
1018 1027 shdr.sh_addralign = 1;
1019 1028 shdr.sh_flags = SHF_STRINGS;
1020 1029 shdr.sh_type = SHT_STRTAB;
1021 1030
1022 1031 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
1023 1032 *pgc->pgc_soff) != 0)
1024 1033 return (1);
1025 1034
1026 1035 *pgc->pgc_soff += sizeof (shdr);
1027 1036 #endif /* _LP64 */
1028 1037 }
1029 1038
1030 1039 *pgc->pgc_doff += roundup(size, 8);
1031 1040
1032 1041 return (0);
1033 1042 }
1034 1043
1035 1044 /*
1036 1045 * Don't explicity stop the process; that's up to the consumer.
1037 1046 */
1038 1047 int
1039 1048 Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
1040 1049 {
1041 1050 char plat[SYS_NMLN];
1042 1051 char zonename[ZONENAME_MAX];
1043 1052 int platlen = -1;
1044 1053 pgcore_t pgc;
1045 1054 off64_t poff, soff, doff, boff;
1046 1055 struct utsname uts;
1047 1056 uint_t nphdrs, nshdrs;
1048 1057
1049 1058 if (ftruncate64(fd, 0) != 0)
1050 1059 return (-1);
1051 1060
1052 1061 if (content == CC_CONTENT_INVALID) {
1053 1062 errno = EINVAL;
1054 1063 return (-1);
1055 1064 }
1056 1065
1057 1066 /*
1058 1067 * Cache the mappings and other useful data.
1059 1068 */
1060 1069 (void) Prd_agent(P);
1061 1070 (void) Ppsinfo(P);
1062 1071
1063 1072 pgc.P = P;
1064 1073 pgc.pgc_fd = fd;
1065 1074 pgc.pgc_poff = &poff;
1066 1075 pgc.pgc_soff = &soff;
1067 1076 pgc.pgc_doff = &doff;
1068 1077 pgc.pgc_content = content;
1069 1078 pgc.pgc_chunksz = PAGESIZE;
1070 1079 if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL)
1071 1080 return (-1);
1072 1081
1073 1082 shstrtab_init(&pgc.pgc_shstrtab);
1074 1083
1075 1084 /*
1076 1085 * There are two PT_NOTE program headers for ancillary data, and
1077 1086 * one for each mapping.
1078 1087 */
1079 1088 nphdrs = 2 + P->map_count;
1080 1089 nshdrs = count_sections(&pgc);
1081 1090
1082 1091 (void) Pplatform(P, plat, sizeof (plat));
1083 1092 platlen = strlen(plat) + 1;
1084 1093 Preadauxvec(P);
1085 1094 (void) Puname(P, &uts);
1086 1095 if (Pzonename(P, zonename, sizeof (zonename)) == NULL)
1087 1096 zonename[0] = '\0';
1088 1097
1089 1098 /*
1090 1099 * The core file contents may required zero section headers, but if we
1091 1100 * overflow the 16 bits allotted to the program header count in the ELF
1092 1101 * header, we'll need that program header at index zero.
1093 1102 */
1094 1103 if (nshdrs == 0 && nphdrs >= PN_XNUM)
1095 1104 nshdrs = 1;
1096 1105
1097 1106 /*
1098 1107 * Set up the ELF header.
1099 1108 */
1100 1109 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1101 1110 Elf32_Ehdr ehdr;
1102 1111
1103 1112 bzero(&ehdr, sizeof (ehdr));
1104 1113 ehdr.e_ident[EI_MAG0] = ELFMAG0;
1105 1114 ehdr.e_ident[EI_MAG1] = ELFMAG1;
1106 1115 ehdr.e_ident[EI_MAG2] = ELFMAG2;
1107 1116 ehdr.e_ident[EI_MAG3] = ELFMAG3;
1108 1117 ehdr.e_type = ET_CORE;
1109 1118
1110 1119 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
1111 1120 #if defined(__sparc)
1112 1121 ehdr.e_machine = EM_SPARC;
1113 1122 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
1114 1123 #elif defined(__i386) || defined(__amd64)
1115 1124 ehdr.e_machine = EM_386;
1116 1125 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
1117 1126 #else
1118 1127 #error "unknown machine type"
1119 1128 #endif
1120 1129 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1121 1130
1122 1131 ehdr.e_version = EV_CURRENT;
1123 1132 ehdr.e_ehsize = sizeof (ehdr);
1124 1133
1125 1134 if (nphdrs >= PN_XNUM)
1126 1135 ehdr.e_phnum = PN_XNUM;
1127 1136 else
1128 1137 ehdr.e_phnum = (unsigned short)nphdrs;
1129 1138
1130 1139 ehdr.e_phentsize = sizeof (Elf32_Phdr);
1131 1140 ehdr.e_phoff = ehdr.e_ehsize;
1132 1141
1133 1142 if (nshdrs > 0) {
1134 1143 if (nshdrs >= SHN_LORESERVE)
1135 1144 ehdr.e_shnum = 0;
1136 1145 else
1137 1146 ehdr.e_shnum = (unsigned short)nshdrs;
1138 1147
1139 1148 if (nshdrs - 1 >= SHN_LORESERVE)
1140 1149 ehdr.e_shstrndx = SHN_XINDEX;
1141 1150 else
1142 1151 ehdr.e_shstrndx = (unsigned short)(nshdrs - 1);
1143 1152
1144 1153 ehdr.e_shentsize = sizeof (Elf32_Shdr);
1145 1154 ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs;
1146 1155 }
1147 1156
1148 1157 if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0)
1149 1158 goto err;
1150 1159
1151 1160 poff = ehdr.e_phoff;
1152 1161 soff = ehdr.e_shoff;
1153 1162 doff = boff = ehdr.e_ehsize +
1154 1163 ehdr.e_phentsize * nphdrs +
1155 1164 ehdr.e_shentsize * nshdrs;
1156 1165
1157 1166 #ifdef _LP64
1158 1167 } else {
1159 1168 Elf64_Ehdr ehdr;
1160 1169
1161 1170 bzero(&ehdr, sizeof (ehdr));
1162 1171 ehdr.e_ident[EI_MAG0] = ELFMAG0;
1163 1172 ehdr.e_ident[EI_MAG1] = ELFMAG1;
1164 1173 ehdr.e_ident[EI_MAG2] = ELFMAG2;
1165 1174 ehdr.e_ident[EI_MAG3] = ELFMAG3;
1166 1175 ehdr.e_type = ET_CORE;
1167 1176
1168 1177 ehdr.e_ident[EI_CLASS] = ELFCLASS64;
1169 1178 #if defined(__sparc)
1170 1179 ehdr.e_machine = EM_SPARCV9;
1171 1180 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
1172 1181 #elif defined(__i386) || defined(__amd64)
1173 1182 ehdr.e_machine = EM_AMD64;
1174 1183 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
1175 1184 #else
1176 1185 #error "unknown machine type"
1177 1186 #endif
1178 1187 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1179 1188
1180 1189 ehdr.e_version = EV_CURRENT;
1181 1190 ehdr.e_ehsize = sizeof (ehdr);
1182 1191
1183 1192 if (nphdrs >= PN_XNUM)
1184 1193 ehdr.e_phnum = PN_XNUM;
1185 1194 else
1186 1195 ehdr.e_phnum = (unsigned short)nphdrs;
1187 1196
1188 1197 ehdr.e_phentsize = sizeof (Elf64_Phdr);
1189 1198 ehdr.e_phoff = ehdr.e_ehsize;
1190 1199
1191 1200 if (nshdrs > 0) {
1192 1201 if (nshdrs >= SHN_LORESERVE)
1193 1202 ehdr.e_shnum = 0;
1194 1203 else
1195 1204 ehdr.e_shnum = (unsigned short)nshdrs;
1196 1205
1197 1206 if (nshdrs - 1 >= SHN_LORESERVE)
1198 1207 ehdr.e_shstrndx = SHN_XINDEX;
1199 1208 else
1200 1209 ehdr.e_shstrndx = (unsigned short)(nshdrs - 1);
1201 1210
1202 1211 ehdr.e_shentsize = sizeof (Elf64_Shdr);
1203 1212 ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs;
1204 1213 }
1205 1214
1206 1215 if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0)
1207 1216 goto err;
1208 1217
1209 1218 poff = ehdr.e_phoff;
1210 1219 soff = ehdr.e_shoff;
1211 1220 doff = boff = ehdr.e_ehsize +
1212 1221 ehdr.e_phentsize * nphdrs +
1213 1222 ehdr.e_shentsize * nshdrs;
1214 1223
1215 1224 #endif /* _LP64 */
1216 1225 }
1217 1226
1218 1227 /*
1219 1228 * Write the zero indexed section if it exists.
1220 1229 */
1221 1230 if (nshdrs > 0 && write_shdr(&pgc, STR_NONE, 0, 0, 0, 0,
1222 1231 nshdrs >= SHN_LORESERVE ? nshdrs : 0,
1223 1232 nshdrs - 1 >= SHN_LORESERVE ? nshdrs - 1 : 0,
1224 1233 nphdrs >= PN_XNUM ? nphdrs : 0, 0, 0) != 0)
1225 1234 goto err;
1226 1235
1227 1236 /*
1228 1237 * Construct the old-style note header and section.
1229 1238 */
1230 1239
1231 1240 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
1232 1241 prpsinfo_t prpsinfo;
1233 1242
1234 1243 mkprpsinfo(P, &prpsinfo);
1235 1244 if (write_note(fd, NT_PRPSINFO, &prpsinfo, sizeof (prpsinfo_t),
1236 1245 &doff) != 0) {
1237 1246 goto err;
1238 1247 }
1239 1248 if (write_note(fd, NT_AUXV, P->auxv,
1240 1249 P->nauxv * sizeof (P->auxv[0]), &doff) != 0) {
1241 1250 goto err;
1242 1251 }
1243 1252 #ifdef _LP64
1244 1253 } else {
1245 1254 prpsinfo32_t pi32;
1246 1255 auxv32_t *av32;
1247 1256 size_t size = sizeof (auxv32_t) * P->nauxv;
1248 1257 int i;
1249 1258
1250 1259 mkprpsinfo32(P, &pi32);
1251 1260 if (write_note(fd, NT_PRPSINFO, &pi32, sizeof (prpsinfo32_t),
1252 1261 &doff) != 0) {
1253 1262 goto err;
1254 1263 }
1255 1264
1256 1265 if ((av32 = malloc(size)) == NULL)
1257 1266 goto err;
1258 1267
1259 1268 for (i = 0; i < P->nauxv; i++) {
1260 1269 auxv_n_to_32(&P->auxv[i], &av32[i]);
1261 1270 }
1262 1271
1263 1272 if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) {
1264 1273 free(av32);
1265 1274 goto err;
1266 1275 }
1267 1276
1268 1277 free(av32);
1269 1278 #endif /* _LP64 */
1270 1279 }
1271 1280
1272 1281 if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0)
1273 1282 goto err;
1274 1283
1275 1284 if (Plwp_iter_all(P, old_per_lwp, &pgc) != 0)
1276 1285 goto err;
1277 1286
1278 1287 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1279 1288 Elf32_Phdr phdr;
1280 1289
1281 1290 bzero(&phdr, sizeof (phdr));
1282 1291 phdr.p_type = PT_NOTE;
1283 1292 phdr.p_flags = PF_R;
1284 1293 phdr.p_offset = (Elf32_Off)boff;
1285 1294 phdr.p_filesz = doff - boff;
1286 1295 boff = doff;
1287 1296
1288 1297 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1289 1298 goto err;
1290 1299 poff += sizeof (phdr);
1291 1300 #ifdef _LP64
1292 1301 } else {
1293 1302 Elf64_Phdr phdr;
1294 1303
1295 1304 bzero(&phdr, sizeof (phdr));
1296 1305 phdr.p_type = PT_NOTE;
1297 1306 phdr.p_flags = PF_R;
1298 1307 phdr.p_offset = boff;
1299 1308 phdr.p_filesz = doff - boff;
1300 1309 boff = doff;
1301 1310
1302 1311 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1303 1312 goto err;
1304 1313 poff += sizeof (phdr);
1305 1314 #endif /* _LP64 */
1306 1315 }
1307 1316
1308 1317 /*
1309 1318 * Construct the new-style note header and section.
1310 1319 */
1311 1320
1312 1321 if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
1313 1322 if (write_note(fd, NT_PSINFO, &P->psinfo, sizeof (psinfo_t),
1314 1323 &doff) != 0) {
1315 1324 goto err;
1316 1325 }
1317 1326 if (write_note(fd, NT_PSTATUS, &P->status, sizeof (pstatus_t),
1318 1327 &doff) != 0) {
1319 1328 goto err;
1320 1329 }
1321 1330 if (write_note(fd, NT_AUXV, P->auxv,
1322 1331 P->nauxv * sizeof (P->auxv[0]), &doff) != 0) {
1323 1332 goto err;
1324 1333 }
1325 1334 #ifdef _LP64
1326 1335 } else {
1327 1336 psinfo32_t pi32;
1328 1337 pstatus32_t ps32;
1329 1338 auxv32_t *av32;
1330 1339 size_t size = sizeof (auxv32_t) * P->nauxv;
1331 1340 int i;
1332 1341
1333 1342 psinfo_n_to_32(&P->psinfo, &pi32);
1334 1343 if (write_note(fd, NT_PSINFO, &pi32, sizeof (psinfo32_t),
1335 1344 &doff) != 0) {
1336 1345 goto err;
1337 1346 }
1338 1347 pstatus_n_to_32(&P->status, &ps32);
1339 1348 if (write_note(fd, NT_PSTATUS, &ps32, sizeof (pstatus32_t),
1340 1349 &doff) != 0) {
1341 1350 goto err;
1342 1351 }
1343 1352 if ((av32 = malloc(size)) == NULL)
1344 1353 goto err;
1345 1354
1346 1355 for (i = 0; i < P->nauxv; i++) {
1347 1356 auxv_n_to_32(&P->auxv[i], &av32[i]);
1348 1357 }
1349 1358
1350 1359 if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) {
1351 1360 free(av32);
1352 1361 goto err;
1353 1362 }
1354 1363
1355 1364 free(av32);
1356 1365 #endif /* _LP64 */
1357 1366 }
1358 1367
1359 1368 if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0 ||
1360 1369 write_note(fd, NT_UTSNAME, &uts, sizeof (uts), &doff) != 0 ||
1361 1370 write_note(fd, NT_CONTENT, &content, sizeof (content), &doff) != 0)
1362 1371 goto err;
1363 1372
1364 1373 {
1365 1374 prcred_t cred, *cp;
1366 1375 size_t size = sizeof (prcred_t);
1367 1376
1368 1377 if (Pcred(P, &cred, 0) != 0)
1369 1378 goto err;
1370 1379
1371 1380 if (cred.pr_ngroups > 0)
1372 1381 size += sizeof (gid_t) * (cred.pr_ngroups - 1);
1373 1382 if ((cp = malloc(size)) == NULL)
1374 1383 goto err;
1375 1384
1376 1385 if (Pcred(P, cp, cred.pr_ngroups) != 0 ||
1377 1386 write_note(fd, NT_PRCRED, cp, size, &doff) != 0) {
1378 1387 free(cp);
1379 1388 goto err;
1380 1389 }
1381 1390
1382 1391 free(cp);
1383 1392 }
1384 1393
1385 1394 {
1386 1395 prpriv_t *ppriv = NULL;
1387 1396 const priv_impl_info_t *pinfo;
1388 1397 size_t pprivsz, pinfosz;
1389 1398
1390 1399 if (Ppriv(P, &ppriv) == -1)
1391 1400 goto err;
1392 1401 pprivsz = PRIV_PRPRIV_SIZE(ppriv);
1393 1402
1394 1403 if (write_note(fd, NT_PRPRIV, ppriv, pprivsz, &doff) != 0) {
1395 1404 Ppriv_free(P, ppriv);
1396 1405 goto err;
1397 1406 }
1398 1407 Ppriv_free(P, ppriv);
1399 1408
1400 1409 if ((pinfo = getprivimplinfo()) == NULL)
1401 1410 goto err;
1402 1411 pinfosz = PRIV_IMPL_INFO_SIZE(pinfo);
1403 1412
1404 1413 if (write_note(fd, NT_PRPRIVINFO, pinfo, pinfosz, &doff) != 0)
1405 1414 goto err;
1406 1415 }
1407 1416
1408 1417 if (write_note(fd, NT_ZONENAME, zonename, strlen(zonename) + 1,
1409 1418 &doff) != 0)
1410 1419 goto err;
1411 1420
1412 1421 {
1413 1422 fditer_t iter;
1414 1423 iter.fd_fd = fd;
1415 1424 iter.fd_doff = &doff;
1416 1425
1417 1426 if (Pfdinfo_iter(P, iter_fd, &iter) != 0)
1418 1427 goto err;
1419 1428 }
1420 1429
1421 1430
1422 1431 {
1423 1432 prsecflags_t *psf = NULL;
1424 1433
1425 1434 if (Psecflags(P, &psf) != 0)
1426 1435 goto err;
1427 1436
1428 1437 if (write_note(fd, NT_SECFLAGS, psf,
1429 1438 sizeof (prsecflags_t), &doff) != 0) {
1430 1439 Psecflags_free(psf);
1431 1440 goto err;
1432 1441 }
1433 1442
1434 1443 Psecflags_free(psf);
1435 1444 }
1436 1445
1437 1446 #if defined(__i386) || defined(__amd64)
1438 1447 /* CSTYLED */
1439 1448 {
1440 1449 struct ssd *ldtp;
1441 1450 size_t size;
1442 1451 int nldt;
1443 1452
1444 1453 /*
1445 1454 * Only dump out non-zero sized LDT notes.
1446 1455 */
1447 1456 if ((nldt = Pldt(P, NULL, 0)) != 0) {
1448 1457 size = sizeof (struct ssd) * nldt;
1449 1458 if ((ldtp = malloc(size)) == NULL)
1450 1459 goto err;
1451 1460
1452 1461 if (Pldt(P, ldtp, nldt) == -1 ||
1453 1462 write_note(fd, NT_LDT, ldtp, size, &doff) != 0) {
1454 1463 free(ldtp);
1455 1464 goto err;
1456 1465 }
1457 1466
1458 1467 free(ldtp);
1459 1468 }
1460 1469 }
1461 1470 #endif /* __i386 || __amd64 */
1462 1471
1463 1472 if (Plwp_iter_all(P, new_per_lwp, &pgc) != 0)
1464 1473 goto err;
1465 1474
1466 1475 if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1467 1476 Elf32_Phdr phdr;
1468 1477
1469 1478 bzero(&phdr, sizeof (phdr));
1470 1479 phdr.p_type = PT_NOTE;
1471 1480 phdr.p_flags = PF_R;
1472 1481 phdr.p_offset = (Elf32_Off)boff;
1473 1482 phdr.p_filesz = doff - boff;
1474 1483 boff = doff;
1475 1484
1476 1485 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1477 1486 goto err;
1478 1487 poff += sizeof (phdr);
1479 1488 #ifdef _LP64
1480 1489 } else {
1481 1490 Elf64_Phdr phdr;
1482 1491
1483 1492 bzero(&phdr, sizeof (phdr));
1484 1493 phdr.p_type = PT_NOTE;
1485 1494 phdr.p_flags = PF_R;
1486 1495 phdr.p_offset = boff;
1487 1496 phdr.p_filesz = doff - boff;
1488 1497 boff = doff;
1489 1498
1490 1499 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1491 1500 goto err;
1492 1501 poff += sizeof (phdr);
1493 1502 #endif /* _LP64 */
1494 1503 }
1495 1504
1496 1505 /*
1497 1506 * Construct the headers for each mapping and write out its data
1498 1507 * if the content parameter indicates that it should be present
1499 1508 * in the core file.
1500 1509 */
1501 1510 if (Pmapping_iter(P, dump_map, &pgc) != 0)
1502 1511 goto err;
1503 1512
1504 1513 if (dump_sections(&pgc) != 0)
1505 1514 goto err;
1506 1515
1507 1516 if (write_shstrtab(P, &pgc) != 0)
1508 1517 goto err;
1509 1518
1510 1519 free(pgc.pgc_chunk);
1511 1520
1512 1521 return (0);
1513 1522
1514 1523 err:
1515 1524 /*
1516 1525 * Wipe out anything we may have written if there was an error.
1517 1526 */
1518 1527 (void) ftruncate64(fd, 0);
1519 1528 free(pgc.pgc_chunk);
1520 1529
1521 1530 return (-1);
1522 1531 }
1523 1532
1524 1533 static const char *content_str[] = {
1525 1534 "stack", /* CC_CONTENT_STACK */
1526 1535 "heap", /* CC_CONTENT_HEAP */
1527 1536 "shfile", /* CC_CONTENT_SHFILE */
1528 1537 "shanon", /* CC_CONTENT_SHANON */
1529 1538 "text", /* CC_CONTENT_TEXT */
1530 1539 "data", /* CC_CONTENT_DATA */
1531 1540 "rodata", /* CC_CONTENT_RODATA */
1532 1541 "anon", /* CC_CONTENT_ANON */
1533 1542 "shm", /* CC_CONTENT_SHM */
1534 1543 "ism", /* CC_CONTENT_ISM */
1535 1544 "dism", /* CC_CONTENT_DISM */
1536 1545 "ctf", /* CC_CONTENT_CTF */
1537 1546 "symtab", /* CC_CONTENT_SYMTAB */
1538 1547 };
1539 1548
1540 1549 static uint_t ncontent_str = sizeof (content_str) / sizeof (content_str[0]);
1541 1550
1542 1551 #define STREQ(a, b, n) (strlen(b) == (n) && strncmp(a, b, n) == 0)
1543 1552
1544 1553 int
1545 1554 proc_str2content(const char *str, core_content_t *cp)
1546 1555 {
1547 1556 const char *cur = str;
1548 1557 int add = 1;
1549 1558 core_content_t mask, content = 0;
1550 1559
1551 1560 for (;;) {
1552 1561 for (cur = str; isalpha(*cur); cur++)
1553 1562 continue;
1554 1563
1555 1564 if (STREQ(str, "default", cur - str)) {
1556 1565 mask = CC_CONTENT_DEFAULT;
1557 1566 } else if (STREQ(str, "all", cur - str)) {
1558 1567 mask = CC_CONTENT_ALL;
1559 1568 } else if (STREQ(str, "none", cur - str)) {
1560 1569 mask = 0;
1561 1570 } else {
1562 1571 int i = 0;
1563 1572
1564 1573 while (!STREQ(str, content_str[i], cur - str)) {
1565 1574 i++;
1566 1575
1567 1576 if (i >= ncontent_str)
1568 1577 return (-1);
1569 1578 }
1570 1579
1571 1580 mask = (core_content_t)1 << i;
1572 1581 }
1573 1582
1574 1583 if (add)
1575 1584 content |= mask;
1576 1585 else
1577 1586 content &= ~mask;
1578 1587
1579 1588 switch (*cur) {
1580 1589 case '\0':
1581 1590 *cp = content;
1582 1591 return (0);
1583 1592 case '+':
1584 1593 add = 1;
1585 1594 break;
1586 1595 case '-':
1587 1596 add = 0;
1588 1597 break;
1589 1598 default:
1590 1599 return (-1);
1591 1600 }
1592 1601
1593 1602 str = cur + 1;
1594 1603 }
1595 1604 }
1596 1605
1597 1606 static int
1598 1607 popc(core_content_t x)
1599 1608 {
1600 1609 int i;
1601 1610
1602 1611 for (i = 0; x != 0; i++)
1603 1612 x &= x - 1;
1604 1613
1605 1614 return (i);
1606 1615 }
1607 1616
1608 1617 int
1609 1618 proc_content2str(core_content_t content, char *buf, size_t size)
1610 1619 {
1611 1620 int nonecnt, defcnt, allcnt;
1612 1621 core_content_t mask, bit;
1613 1622 int first;
1614 1623 uint_t index;
1615 1624 size_t n, tot = 0;
1616 1625
1617 1626 if (content == 0)
1618 1627 return ((int)strlcpy(buf, "none", size));
1619 1628
1620 1629 if (content & ~CC_CONTENT_ALL)
1621 1630 return ((int)strlcpy(buf, "<invalid>", size));
1622 1631
1623 1632 nonecnt = popc(content);
1624 1633 defcnt = 1 + popc(content ^ CC_CONTENT_DEFAULT);
1625 1634 allcnt = 1 + popc(content ^ CC_CONTENT_ALL);
1626 1635
1627 1636 if (defcnt <= nonecnt && defcnt <= allcnt) {
1628 1637 mask = content ^ CC_CONTENT_DEFAULT;
1629 1638 first = 0;
1630 1639 tot += (n = strlcpy(buf, "default", size));
1631 1640 if (n > size)
1632 1641 n = size;
1633 1642 buf += n;
1634 1643 size -= n;
1635 1644 } else if (allcnt < nonecnt) {
1636 1645 mask = content ^ CC_CONTENT_ALL;
1637 1646 first = 0;
1638 1647 tot += (n = strlcpy(buf, "all", size));
1639 1648 if (n > size)
1640 1649 n = size;
1641 1650 buf += n;
1642 1651 size -= n;
1643 1652 } else {
1644 1653 mask = content;
1645 1654 first = 1;
1646 1655 }
1647 1656
1648 1657 while (mask != 0) {
1649 1658 bit = mask ^ (mask & (mask - 1));
1650 1659
1651 1660 if (!first) {
1652 1661 if (size > 1) {
1653 1662 *buf = (bit & content) ? '+' : '-';
1654 1663 buf++;
1655 1664 size--;
1656 1665 }
1657 1666
1658 1667 tot++;
1659 1668 }
1660 1669 index = popc(bit - 1);
1661 1670 tot += (n = strlcpy(buf, content_str[index], size));
1662 1671 if (n > size)
1663 1672 n = size;
1664 1673 buf += n;
1665 1674 size -= n;
1666 1675
1667 1676 mask ^= bit;
1668 1677 first = 0;
1669 1678 }
1670 1679
1671 1680 return ((int)tot);
1672 1681 }
↓ open down ↓ |
1083 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX