9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
27 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 */
30
31 #include <sys/types.h>
32 #include <sys/utsname.h>
33 #include <sys/sysmacros.h>
34 #include <sys/proc.h>
35
36 #include <alloca.h>
37 #include <rtld_db.h>
38 #include <libgen.h>
39 #include <limits.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <gelf.h>
45 #include <stddef.h>
46 #include <signal.h>
47
48 #include "libproc.h"
49 #include "Pcontrol.h"
50 #include "P32ton.h"
51 #include "Putil.h"
52 #include "Pcore_linux.h"
53
54 /*
55 * Pcore.c - Code to initialize a ps_prochandle from a core dump. We
56 * allocate an additional structure to hold information from the core
57 * file, and attach this to the standard ps_prochandle in place of the
58 * ability to examine /proc/<pid>/ files.
59 */
60
61 /*
62 * Basic i/o function for reading and writing from the process address space
63 * stored in the core file and associated shared libraries. We compute the
64 * appropriate fd and offsets, and let the provided prw function do the rest.
65 */
66 static ssize_t
67 core_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
68 ssize_t (*prw)(int, void *, size_t, off64_t))
69 {
70 ssize_t resid = n;
71
72 while (resid != 0) {
202 if (lwp->lwp_asrs != NULL)
203 free(lwp->lwp_asrs);
204 #endif
205 free(lwp);
206 }
207
208 if (core->core_platform != NULL)
209 free(core->core_platform);
210 if (core->core_uts != NULL)
211 free(core->core_uts);
212 if (core->core_cred != NULL)
213 free(core->core_cred);
214 if (core->core_priv != NULL)
215 free(core->core_priv);
216 if (core->core_privinfo != NULL)
217 __priv_free_info(core->core_privinfo);
218 if (core->core_ppii != NULL)
219 free(core->core_ppii);
220 if (core->core_zonename != NULL)
221 free(core->core_zonename);
222 #if defined(__i386) || defined(__amd64)
223 if (core->core_ldt != NULL)
224 free(core->core_ldt);
225 #endif
226
227 free(core);
228 }
229 }
230
231 /*ARGSUSED*/
232 static char *
233 Pplatform_core(struct ps_prochandle *P, char *s, size_t n, void *data)
234 {
235 core_info_t *core = data;
236
237 if (core->core_platform == NULL) {
238 errno = ENODATA;
239 return (NULL);
240 }
241 (void) strncpy(s, core->core_platform, n - 1);
242 s[n - 1] = '\0';
254 return (-1);
255 }
256 (void) memcpy(u, core->core_uts, sizeof (struct utsname));
257 return (0);
258 }
259
260 /*ARGSUSED*/
261 static char *
262 Pzonename_core(struct ps_prochandle *P, char *s, size_t n, void *data)
263 {
264 core_info_t *core = data;
265
266 if (core->core_zonename == NULL) {
267 errno = ENODATA;
268 return (NULL);
269 }
270 (void) strlcpy(s, core->core_zonename, n);
271 return (s);
272 }
273
274 #if defined(__i386) || defined(__amd64)
275 /*ARGSUSED*/
276 static int
277 Pldt_core(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
278 {
279 core_info_t *core = data;
280
281 if (pldt == NULL || nldt == 0)
282 return (core->core_nldt);
283
284 if (core->core_ldt != NULL) {
285 nldt = MIN(nldt, core->core_nldt);
286
287 (void) memcpy(pldt, core->core_ldt,
288 nldt * sizeof (struct ssd));
289
290 return (nldt);
291 }
292
293 errno = ENODATA;
294 return (-1);
295 }
296 #endif
297
298 static const ps_ops_t P_core_ops = {
299 .pop_pread = Pread_core,
300 .pop_pwrite = Pwrite_core,
301 .pop_cred = Pcred_core,
302 .pop_priv = Ppriv_core,
303 .pop_psinfo = Ppsinfo_core,
304 .pop_fini = Pfini_core,
305 .pop_platform = Pplatform_core,
306 .pop_uname = Puname_core,
307 .pop_zonename = Pzonename_core,
308 #if defined(__i386) || defined(__amd64)
309 .pop_ldt = Pldt_core
310 #endif
311 };
312
313 /*
314 * Return the lwp_info_t for the given lwpid. If no such lwpid has been
315 * encountered yet, allocate a new structure and return a pointer to it.
316 * Create a list of lwp_info_t structures sorted in decreasing lwp_id order.
317 */
318 static lwp_info_t *
319 lwpid2info(struct ps_prochandle *P, lwpid_t id)
320 {
321 core_info_t *core = P->data;
322 lwp_info_t *lwp = list_next(&core->core_lwp_head);
323 lwp_info_t *next;
324 uint_t i;
325
326 for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
327 if (lwp->lwp_id == id) {
328 core->core_lwp = lwp;
414 dprintf("Pgrab_core: failed to add NT_LWPSTATUS\n");
415 return (-1);
416 }
417
418 /*
419 * Erase a useless and confusing artifact of the kernel implementation:
420 * the lwps which did *not* create the core will show SIGKILL. We can
421 * be assured this is bogus because SIGKILL can't produce core files.
422 */
423 if (lps.pr_cursig == SIGKILL)
424 lps.pr_cursig = 0;
425
426 (void) memcpy(&lwp->lwp_status, &lps, sizeof (lps));
427 return (0);
428
429 err:
430 dprintf("Pgrab_core: failed to read NT_LWPSTATUS\n");
431 return (-1);
432 }
433
434 static void
435 lx_prpsinfo32_to_psinfo(lx_prpsinfo32_t *p32, psinfo_t *psinfo)
436 {
437 psinfo->pr_flag = p32->pr_flag;
438 psinfo->pr_pid = p32->pr_pid;
439 psinfo->pr_ppid = p32->pr_ppid;
440 psinfo->pr_uid = p32->pr_uid;
441 psinfo->pr_gid = p32->pr_gid;
442 psinfo->pr_sid = p32->pr_sid;
443 psinfo->pr_pgid = p32->pr_pgrp;
444
445 (void) memcpy(psinfo->pr_fname, p32->pr_fname,
446 sizeof (psinfo->pr_fname));
447 (void) memcpy(psinfo->pr_psargs, p32->pr_psargs,
448 sizeof (psinfo->pr_psargs));
449 }
450
451 static void
452 lx_prpsinfo64_to_psinfo(lx_prpsinfo64_t *p64, psinfo_t *psinfo)
453 {
612 "linux_prstatus\n");
613 return (-1);
614 }
615
616 P->psinfo.pr_nlwp++;
617 P->status.pr_nlwp++;
618
619 lwp->lwp_status.pr_lwpid = tid;
620
621 if (core->core_dmodel == PR_MODEL_ILP32)
622 lx_prstatus32_to_lwp(&prs32, lwp);
623 else
624 lx_prstatus64_to_lwp(&prs64, lwp);
625
626 return (0);
627 err:
628 dprintf("Pgrab_core: failed to read NT_PRSTATUS\n");
629 return (-1);
630 }
631
632 static int
633 note_psinfo(struct ps_prochandle *P, size_t nbytes)
634 {
635 #ifdef _LP64
636 core_info_t *core = P->data;
637
638 if (core->core_dmodel == PR_MODEL_ILP32) {
639 psinfo32_t ps32;
640
641 if (nbytes < sizeof (psinfo32_t) ||
642 read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
643 goto err;
644
645 psinfo_32_to_n(&ps32, &P->psinfo);
646 } else
647 #endif
648 if (nbytes < sizeof (psinfo_t) ||
649 read(P->asfd, &P->psinfo, sizeof (psinfo_t)) != sizeof (psinfo_t))
650 goto err;
651
810
811 if ((pcrp = malloc(nbytes)) == NULL)
812 return (-1);
813
814 if (read(P->asfd, pcrp, nbytes) != nbytes) {
815 dprintf("Pgrab_core: failed to read NT_PRCRED\n");
816 free(pcrp);
817 return (-1);
818 }
819
820 if (pcrp->pr_ngroups > ngroups) {
821 dprintf("pr_ngroups = %d; resetting to %d based on note size\n",
822 pcrp->pr_ngroups, ngroups);
823 pcrp->pr_ngroups = ngroups;
824 }
825
826 core->core_cred = pcrp;
827 return (0);
828 }
829
830 #if defined(__i386) || defined(__amd64)
831 static int
832 note_ldt(struct ps_prochandle *P, size_t nbytes)
833 {
834 core_info_t *core = P->data;
835 struct ssd *pldt;
836 uint_t nldt;
837
838 if (core->core_ldt != NULL || nbytes < sizeof (struct ssd))
839 return (0); /* Already seen or bad size */
840
841 nldt = nbytes / sizeof (struct ssd);
842 nbytes = nldt * sizeof (struct ssd);
843
844 if ((pldt = malloc(nbytes)) == NULL)
845 return (-1);
846
847 if (read(P->asfd, pldt, nbytes) != nbytes) {
848 dprintf("Pgrab_core: failed to read NT_LDT\n");
849 free(pldt);
850 return (-1);
1108 err:
1109 dprintf("Pgrab_core: failed to read NT_SPYMASTER\n");
1110 return (-1);
1111 }
1112
1113 /*ARGSUSED*/
1114 static int
1115 note_notsup(struct ps_prochandle *P, size_t nbytes)
1116 {
1117 dprintf("skipping unsupported note type of size %ld bytes\n",
1118 (ulong_t)nbytes);
1119 return (0);
1120 }
1121
1122 /*
1123 * Populate a table of function pointers indexed by Note type with our
1124 * functions to process each type of core file note:
1125 */
1126 static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
1127 note_notsup, /* 0 unassigned */
1128 note_linux_prstatus, /* 1 NT_PRSTATUS (old) */
1129 note_notsup, /* 2 NT_PRFPREG (old) */
1130 note_linux_psinfo, /* 3 NT_PRPSINFO (old) */
1131 #ifdef __sparc
1132 note_xreg, /* 4 NT_PRXREG */
1133 #else
1134 note_notsup, /* 4 NT_PRXREG */
1135 #endif
1136 note_platform, /* 5 NT_PLATFORM */
1137 note_auxv, /* 6 NT_AUXV */
1138 #ifdef __sparc
1139 note_gwindows, /* 7 NT_GWINDOWS */
1140 #ifdef __sparcv9
1141 note_asrs, /* 8 NT_ASRS */
1142 #else
1143 note_notsup, /* 8 NT_ASRS */
1144 #endif
1145 #else
1146 note_notsup, /* 7 NT_GWINDOWS */
1147 note_notsup, /* 8 NT_ASRS */
1148 #endif
1149 #if defined(__i386) || defined(__amd64)
1150 note_ldt, /* 9 NT_LDT */
1151 #else
1152 note_notsup, /* 9 NT_LDT */
1153 #endif
1154 note_pstatus, /* 10 NT_PSTATUS */
1155 note_notsup, /* 11 unassigned */
1156 note_notsup, /* 12 unassigned */
1157 note_psinfo, /* 13 NT_PSINFO */
1158 note_cred, /* 14 NT_PRCRED */
1159 note_utsname, /* 15 NT_UTSNAME */
1160 note_lwpstatus, /* 16 NT_LWPSTATUS */
1161 note_lwpsinfo, /* 17 NT_LWPSINFO */
1162 note_priv, /* 18 NT_PRPRIV */
1163 note_priv_info, /* 19 NT_PRPRIVINFO */
1164 note_content, /* 20 NT_CONTENT */
1165 note_zonename, /* 21 NT_ZONENAME */
1166 note_fdinfo, /* 22 NT_FDINFO */
1167 note_spymaster, /* 23 NT_SPYMASTER */
1168 };
1169
2184
2185 /*
2186 * Main engine for core file initialization: given an fd for the core file
2187 * and an optional pathname, construct the ps_prochandle. The aout_path can
2188 * either be a suggested executable pathname, or a suggested directory to
2189 * use as a possible current working directory.
2190 */
2191 struct ps_prochandle *
2192 Pfgrab_core(int core_fd, const char *aout_path, int *perr)
2193 {
2194 struct ps_prochandle *P;
2195 core_info_t *core_info;
2196 map_info_t *stk_mp, *brk_mp;
2197 const char *execname;
2198 char *interp;
2199 int i, notes, pagesize;
2200 uintptr_t addr, base_addr;
2201 struct stat64 stbuf;
2202 void *phbuf, *php;
2203 size_t nbytes;
2204 boolean_t from_linux = B_FALSE;
2205
2206 elf_file_t aout;
2207 elf_file_t core;
2208
2209 Elf_Scn *scn, *intp_scn = NULL;
2210 Elf_Data *dp;
2211
2212 GElf_Phdr phdr, note_phdr;
2213 GElf_Shdr shdr;
2214 GElf_Xword nleft;
2215
2216 if (elf_version(EV_CURRENT) == EV_NONE) {
2217 dprintf("libproc ELF version is more recent than libelf\n");
2218 *perr = G_ELF;
2219 return (NULL);
2220 }
2221
2222 aout.e_elf = NULL;
2223 aout.e_fd = -1;
2224
2432
2433 dprintf("Note hdr n_type=%u n_namesz=%u n_descsz=%u\n",
2434 nhdr.n_type, nhdr.n_namesz, nhdr.n_descsz);
2435
2436 off = lseek64(P->asfd, (off64_t)0L, SEEK_CUR);
2437
2438 /*
2439 * Invoke the note handler function from our table
2440 */
2441 if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {
2442 if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {
2443 dprintf("handler for type %d returned < 0",
2444 nhdr.n_type);
2445 *perr = G_NOTE;
2446 goto err;
2447 }
2448 /*
2449 * The presence of either of these notes indicates that
2450 * the dump was generated on Linux.
2451 */
2452 if (nhdr.n_type == NT_PRSTATUS ||
2453 nhdr.n_type == NT_PRPSINFO)
2454 from_linux = B_TRUE;
2455 } else {
2456 (void) note_notsup(P, nhdr.n_descsz);
2457 }
2458
2459 /*
2460 * Seek past the current note data to the next Elf_Nhdr
2461 */
2462 descsz = P2ROUNDUP((off64_t)nhdr.n_descsz, (off64_t)4);
2463 if (lseek64(P->asfd, off + descsz, SEEK_SET) == (off64_t)-1) {
2464 dprintf("Pgrab_core: failed to seek to next nhdr\n");
2465 *perr = G_STRANGE;
2466 goto err;
2467 }
2468
2469 /*
2470 * Subtract the size of the header and its data from what
2471 * we have left to process.
2472 */
2473 nleft -= sizeof (nhdr) + namesz + descsz;
2474 }
2475
2476 if (from_linux) {
2477 size_t tcount, pid;
2478 lwp_info_t *lwp;
2479
2480 P->status.pr_dmodel = core_info->core_dmodel;
2481
2482 lwp = list_next(&core_info->core_lwp_head);
2483
2484 pid = P->status.pr_pid;
2485
2486 for (tcount = 0; tcount < core_info->core_nlwp;
2487 tcount++, lwp = list_next(lwp)) {
2488 dprintf("Linux thread with id %d\n", lwp->lwp_id);
2489
2490 /*
2491 * In the case we don't have a valid psinfo (i.e. pid is
2492 * 0, probably because of gdb creating the core) assume
2493 * lowest pid count is the first thread (what if the
2494 * next thread wraps the pid around?)
2495 */
2509 /*
2510 * Consumers like mdb expect the first thread to actually have
2511 * an id of 1, on linux that is actually the pid. Find the the
2512 * thread with our process id, and set the id to 1
2513 */
2514 if ((lwp = lwpid2info(P, pid)) == NULL) {
2515 dprintf("Couldn't find first thread\n");
2516 *perr = G_STRANGE;
2517 goto err;
2518 }
2519
2520 dprintf("setting representative thread: %d\n", lwp->lwp_id);
2521
2522 lwp->lwp_id = 1;
2523 lwp->lwp_status.pr_lwpid = 1;
2524
2525 /* set representative thread */
2526 (void) memcpy(&P->status.pr_lwp, &lwp->lwp_status,
2527 sizeof (P->status.pr_lwp));
2528 }
2529
2530 if (nleft != 0) {
2531 dprintf("Pgrab_core: note section malformed\n");
2532 *perr = G_STRANGE;
2533 goto err;
2534 }
2535
2536 if ((pagesize = Pgetauxval(P, AT_PAGESZ)) == -1) {
2537 pagesize = getpagesize();
2538 dprintf("AT_PAGESZ missing; defaulting to %d\n", pagesize);
2539 }
2540
2541 /*
2542 * Locate and label the mappings corresponding to the end of the
2543 * heap (MA_BREAK) and the base of the stack (MA_STACK).
2544 */
2545 if ((P->status.pr_brkbase != 0 || P->status.pr_brksize != 0) &&
2546 (brk_mp = Paddr2mptr(P, P->status.pr_brkbase +
2547 P->status.pr_brksize - 1)) != NULL)
2548 brk_mp->map_pmap.pr_mflags |= MA_BREAK;
|
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
27 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
28 * Copyright (c) 2013 by Delphix. All rights reserved.
29 * Copyright 2015 Gary Mills
30 */
31
32 #include <sys/types.h>
33 #include <sys/utsname.h>
34 #include <sys/sysmacros.h>
35 #include <sys/proc.h>
36
37 #include <alloca.h>
38 #include <rtld_db.h>
39 #include <libgen.h>
40 #include <limits.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <gelf.h>
46 #include <stddef.h>
47 #include <signal.h>
48
49 #include "libproc.h"
50 #include "Pcontrol.h"
51 #include "P32ton.h"
52 #include "Putil.h"
53 #ifdef __x86
54 #include "Pcore_linux.h"
55 #endif
56
57 /*
58 * Pcore.c - Code to initialize a ps_prochandle from a core dump. We
59 * allocate an additional structure to hold information from the core
60 * file, and attach this to the standard ps_prochandle in place of the
61 * ability to examine /proc/<pid>/ files.
62 */
63
64 /*
65 * Basic i/o function for reading and writing from the process address space
66 * stored in the core file and associated shared libraries. We compute the
67 * appropriate fd and offsets, and let the provided prw function do the rest.
68 */
69 static ssize_t
70 core_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
71 ssize_t (*prw)(int, void *, size_t, off64_t))
72 {
73 ssize_t resid = n;
74
75 while (resid != 0) {
205 if (lwp->lwp_asrs != NULL)
206 free(lwp->lwp_asrs);
207 #endif
208 free(lwp);
209 }
210
211 if (core->core_platform != NULL)
212 free(core->core_platform);
213 if (core->core_uts != NULL)
214 free(core->core_uts);
215 if (core->core_cred != NULL)
216 free(core->core_cred);
217 if (core->core_priv != NULL)
218 free(core->core_priv);
219 if (core->core_privinfo != NULL)
220 __priv_free_info(core->core_privinfo);
221 if (core->core_ppii != NULL)
222 free(core->core_ppii);
223 if (core->core_zonename != NULL)
224 free(core->core_zonename);
225 #ifdef __x86
226 if (core->core_ldt != NULL)
227 free(core->core_ldt);
228 #endif
229
230 free(core);
231 }
232 }
233
234 /*ARGSUSED*/
235 static char *
236 Pplatform_core(struct ps_prochandle *P, char *s, size_t n, void *data)
237 {
238 core_info_t *core = data;
239
240 if (core->core_platform == NULL) {
241 errno = ENODATA;
242 return (NULL);
243 }
244 (void) strncpy(s, core->core_platform, n - 1);
245 s[n - 1] = '\0';
257 return (-1);
258 }
259 (void) memcpy(u, core->core_uts, sizeof (struct utsname));
260 return (0);
261 }
262
263 /*ARGSUSED*/
264 static char *
265 Pzonename_core(struct ps_prochandle *P, char *s, size_t n, void *data)
266 {
267 core_info_t *core = data;
268
269 if (core->core_zonename == NULL) {
270 errno = ENODATA;
271 return (NULL);
272 }
273 (void) strlcpy(s, core->core_zonename, n);
274 return (s);
275 }
276
277 #ifdef __x86
278 /*ARGSUSED*/
279 static int
280 Pldt_core(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
281 {
282 core_info_t *core = data;
283
284 if (pldt == NULL || nldt == 0)
285 return (core->core_nldt);
286
287 if (core->core_ldt != NULL) {
288 nldt = MIN(nldt, core->core_nldt);
289
290 (void) memcpy(pldt, core->core_ldt,
291 nldt * sizeof (struct ssd));
292
293 return (nldt);
294 }
295
296 errno = ENODATA;
297 return (-1);
298 }
299 #endif
300
301 static const ps_ops_t P_core_ops = {
302 .pop_pread = Pread_core,
303 .pop_pwrite = Pwrite_core,
304 .pop_cred = Pcred_core,
305 .pop_priv = Ppriv_core,
306 .pop_psinfo = Ppsinfo_core,
307 .pop_fini = Pfini_core,
308 .pop_platform = Pplatform_core,
309 .pop_uname = Puname_core,
310 .pop_zonename = Pzonename_core,
311 #ifdef __x86
312 .pop_ldt = Pldt_core
313 #endif
314 };
315
316 /*
317 * Return the lwp_info_t for the given lwpid. If no such lwpid has been
318 * encountered yet, allocate a new structure and return a pointer to it.
319 * Create a list of lwp_info_t structures sorted in decreasing lwp_id order.
320 */
321 static lwp_info_t *
322 lwpid2info(struct ps_prochandle *P, lwpid_t id)
323 {
324 core_info_t *core = P->data;
325 lwp_info_t *lwp = list_next(&core->core_lwp_head);
326 lwp_info_t *next;
327 uint_t i;
328
329 for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
330 if (lwp->lwp_id == id) {
331 core->core_lwp = lwp;
417 dprintf("Pgrab_core: failed to add NT_LWPSTATUS\n");
418 return (-1);
419 }
420
421 /*
422 * Erase a useless and confusing artifact of the kernel implementation:
423 * the lwps which did *not* create the core will show SIGKILL. We can
424 * be assured this is bogus because SIGKILL can't produce core files.
425 */
426 if (lps.pr_cursig == SIGKILL)
427 lps.pr_cursig = 0;
428
429 (void) memcpy(&lwp->lwp_status, &lps, sizeof (lps));
430 return (0);
431
432 err:
433 dprintf("Pgrab_core: failed to read NT_LWPSTATUS\n");
434 return (-1);
435 }
436
437 #ifdef __x86
438
439 static void
440 lx_prpsinfo32_to_psinfo(lx_prpsinfo32_t *p32, psinfo_t *psinfo)
441 {
442 psinfo->pr_flag = p32->pr_flag;
443 psinfo->pr_pid = p32->pr_pid;
444 psinfo->pr_ppid = p32->pr_ppid;
445 psinfo->pr_uid = p32->pr_uid;
446 psinfo->pr_gid = p32->pr_gid;
447 psinfo->pr_sid = p32->pr_sid;
448 psinfo->pr_pgid = p32->pr_pgrp;
449
450 (void) memcpy(psinfo->pr_fname, p32->pr_fname,
451 sizeof (psinfo->pr_fname));
452 (void) memcpy(psinfo->pr_psargs, p32->pr_psargs,
453 sizeof (psinfo->pr_psargs));
454 }
455
456 static void
457 lx_prpsinfo64_to_psinfo(lx_prpsinfo64_t *p64, psinfo_t *psinfo)
458 {
617 "linux_prstatus\n");
618 return (-1);
619 }
620
621 P->psinfo.pr_nlwp++;
622 P->status.pr_nlwp++;
623
624 lwp->lwp_status.pr_lwpid = tid;
625
626 if (core->core_dmodel == PR_MODEL_ILP32)
627 lx_prstatus32_to_lwp(&prs32, lwp);
628 else
629 lx_prstatus64_to_lwp(&prs64, lwp);
630
631 return (0);
632 err:
633 dprintf("Pgrab_core: failed to read NT_PRSTATUS\n");
634 return (-1);
635 }
636
637 #endif /* __x86 */
638
639 static int
640 note_psinfo(struct ps_prochandle *P, size_t nbytes)
641 {
642 #ifdef _LP64
643 core_info_t *core = P->data;
644
645 if (core->core_dmodel == PR_MODEL_ILP32) {
646 psinfo32_t ps32;
647
648 if (nbytes < sizeof (psinfo32_t) ||
649 read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
650 goto err;
651
652 psinfo_32_to_n(&ps32, &P->psinfo);
653 } else
654 #endif
655 if (nbytes < sizeof (psinfo_t) ||
656 read(P->asfd, &P->psinfo, sizeof (psinfo_t)) != sizeof (psinfo_t))
657 goto err;
658
817
818 if ((pcrp = malloc(nbytes)) == NULL)
819 return (-1);
820
821 if (read(P->asfd, pcrp, nbytes) != nbytes) {
822 dprintf("Pgrab_core: failed to read NT_PRCRED\n");
823 free(pcrp);
824 return (-1);
825 }
826
827 if (pcrp->pr_ngroups > ngroups) {
828 dprintf("pr_ngroups = %d; resetting to %d based on note size\n",
829 pcrp->pr_ngroups, ngroups);
830 pcrp->pr_ngroups = ngroups;
831 }
832
833 core->core_cred = pcrp;
834 return (0);
835 }
836
837 #ifdef __x86
838 static int
839 note_ldt(struct ps_prochandle *P, size_t nbytes)
840 {
841 core_info_t *core = P->data;
842 struct ssd *pldt;
843 uint_t nldt;
844
845 if (core->core_ldt != NULL || nbytes < sizeof (struct ssd))
846 return (0); /* Already seen or bad size */
847
848 nldt = nbytes / sizeof (struct ssd);
849 nbytes = nldt * sizeof (struct ssd);
850
851 if ((pldt = malloc(nbytes)) == NULL)
852 return (-1);
853
854 if (read(P->asfd, pldt, nbytes) != nbytes) {
855 dprintf("Pgrab_core: failed to read NT_LDT\n");
856 free(pldt);
857 return (-1);
1115 err:
1116 dprintf("Pgrab_core: failed to read NT_SPYMASTER\n");
1117 return (-1);
1118 }
1119
1120 /*ARGSUSED*/
1121 static int
1122 note_notsup(struct ps_prochandle *P, size_t nbytes)
1123 {
1124 dprintf("skipping unsupported note type of size %ld bytes\n",
1125 (ulong_t)nbytes);
1126 return (0);
1127 }
1128
1129 /*
1130 * Populate a table of function pointers indexed by Note type with our
1131 * functions to process each type of core file note:
1132 */
1133 static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
1134 note_notsup, /* 0 unassigned */
1135 #ifdef __x86
1136 note_linux_prstatus, /* 1 NT_PRSTATUS (old) */
1137 #else
1138 note_notsup, /* 1 NT_PRSTATUS (old) */
1139 #endif
1140 note_notsup, /* 2 NT_PRFPREG (old) */
1141 #ifdef __x86
1142 note_linux_psinfo, /* 3 NT_PRPSINFO (old) */
1143 #else
1144 note_notsup, /* 3 NT_PRPSINFO (old) */
1145 #endif
1146 #ifdef __sparc
1147 note_xreg, /* 4 NT_PRXREG */
1148 #else
1149 note_notsup, /* 4 NT_PRXREG */
1150 #endif
1151 note_platform, /* 5 NT_PLATFORM */
1152 note_auxv, /* 6 NT_AUXV */
1153 #ifdef __sparc
1154 note_gwindows, /* 7 NT_GWINDOWS */
1155 #ifdef __sparcv9
1156 note_asrs, /* 8 NT_ASRS */
1157 #else
1158 note_notsup, /* 8 NT_ASRS */
1159 #endif
1160 #else
1161 note_notsup, /* 7 NT_GWINDOWS */
1162 note_notsup, /* 8 NT_ASRS */
1163 #endif
1164 #ifdef __x86
1165 note_ldt, /* 9 NT_LDT */
1166 #else
1167 note_notsup, /* 9 NT_LDT */
1168 #endif
1169 note_pstatus, /* 10 NT_PSTATUS */
1170 note_notsup, /* 11 unassigned */
1171 note_notsup, /* 12 unassigned */
1172 note_psinfo, /* 13 NT_PSINFO */
1173 note_cred, /* 14 NT_PRCRED */
1174 note_utsname, /* 15 NT_UTSNAME */
1175 note_lwpstatus, /* 16 NT_LWPSTATUS */
1176 note_lwpsinfo, /* 17 NT_LWPSINFO */
1177 note_priv, /* 18 NT_PRPRIV */
1178 note_priv_info, /* 19 NT_PRPRIVINFO */
1179 note_content, /* 20 NT_CONTENT */
1180 note_zonename, /* 21 NT_ZONENAME */
1181 note_fdinfo, /* 22 NT_FDINFO */
1182 note_spymaster, /* 23 NT_SPYMASTER */
1183 };
1184
2199
2200 /*
2201 * Main engine for core file initialization: given an fd for the core file
2202 * and an optional pathname, construct the ps_prochandle. The aout_path can
2203 * either be a suggested executable pathname, or a suggested directory to
2204 * use as a possible current working directory.
2205 */
2206 struct ps_prochandle *
2207 Pfgrab_core(int core_fd, const char *aout_path, int *perr)
2208 {
2209 struct ps_prochandle *P;
2210 core_info_t *core_info;
2211 map_info_t *stk_mp, *brk_mp;
2212 const char *execname;
2213 char *interp;
2214 int i, notes, pagesize;
2215 uintptr_t addr, base_addr;
2216 struct stat64 stbuf;
2217 void *phbuf, *php;
2218 size_t nbytes;
2219 #ifdef __x86
2220 boolean_t from_linux = B_FALSE;
2221 #endif
2222
2223 elf_file_t aout;
2224 elf_file_t core;
2225
2226 Elf_Scn *scn, *intp_scn = NULL;
2227 Elf_Data *dp;
2228
2229 GElf_Phdr phdr, note_phdr;
2230 GElf_Shdr shdr;
2231 GElf_Xword nleft;
2232
2233 if (elf_version(EV_CURRENT) == EV_NONE) {
2234 dprintf("libproc ELF version is more recent than libelf\n");
2235 *perr = G_ELF;
2236 return (NULL);
2237 }
2238
2239 aout.e_elf = NULL;
2240 aout.e_fd = -1;
2241
2449
2450 dprintf("Note hdr n_type=%u n_namesz=%u n_descsz=%u\n",
2451 nhdr.n_type, nhdr.n_namesz, nhdr.n_descsz);
2452
2453 off = lseek64(P->asfd, (off64_t)0L, SEEK_CUR);
2454
2455 /*
2456 * Invoke the note handler function from our table
2457 */
2458 if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {
2459 if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {
2460 dprintf("handler for type %d returned < 0",
2461 nhdr.n_type);
2462 *perr = G_NOTE;
2463 goto err;
2464 }
2465 /*
2466 * The presence of either of these notes indicates that
2467 * the dump was generated on Linux.
2468 */
2469 #ifdef __x86
2470 if (nhdr.n_type == NT_PRSTATUS ||
2471 nhdr.n_type == NT_PRPSINFO)
2472 from_linux = B_TRUE;
2473 #endif
2474 } else {
2475 (void) note_notsup(P, nhdr.n_descsz);
2476 }
2477
2478 /*
2479 * Seek past the current note data to the next Elf_Nhdr
2480 */
2481 descsz = P2ROUNDUP((off64_t)nhdr.n_descsz, (off64_t)4);
2482 if (lseek64(P->asfd, off + descsz, SEEK_SET) == (off64_t)-1) {
2483 dprintf("Pgrab_core: failed to seek to next nhdr\n");
2484 *perr = G_STRANGE;
2485 goto err;
2486 }
2487
2488 /*
2489 * Subtract the size of the header and its data from what
2490 * we have left to process.
2491 */
2492 nleft -= sizeof (nhdr) + namesz + descsz;
2493 }
2494
2495 #ifdef __x86
2496 if (from_linux) {
2497 size_t tcount, pid;
2498 lwp_info_t *lwp;
2499
2500 P->status.pr_dmodel = core_info->core_dmodel;
2501
2502 lwp = list_next(&core_info->core_lwp_head);
2503
2504 pid = P->status.pr_pid;
2505
2506 for (tcount = 0; tcount < core_info->core_nlwp;
2507 tcount++, lwp = list_next(lwp)) {
2508 dprintf("Linux thread with id %d\n", lwp->lwp_id);
2509
2510 /*
2511 * In the case we don't have a valid psinfo (i.e. pid is
2512 * 0, probably because of gdb creating the core) assume
2513 * lowest pid count is the first thread (what if the
2514 * next thread wraps the pid around?)
2515 */
2529 /*
2530 * Consumers like mdb expect the first thread to actually have
2531 * an id of 1, on linux that is actually the pid. Find the the
2532 * thread with our process id, and set the id to 1
2533 */
2534 if ((lwp = lwpid2info(P, pid)) == NULL) {
2535 dprintf("Couldn't find first thread\n");
2536 *perr = G_STRANGE;
2537 goto err;
2538 }
2539
2540 dprintf("setting representative thread: %d\n", lwp->lwp_id);
2541
2542 lwp->lwp_id = 1;
2543 lwp->lwp_status.pr_lwpid = 1;
2544
2545 /* set representative thread */
2546 (void) memcpy(&P->status.pr_lwp, &lwp->lwp_status,
2547 sizeof (P->status.pr_lwp));
2548 }
2549 #endif /* __x86 */
2550
2551 if (nleft != 0) {
2552 dprintf("Pgrab_core: note section malformed\n");
2553 *perr = G_STRANGE;
2554 goto err;
2555 }
2556
2557 if ((pagesize = Pgetauxval(P, AT_PAGESZ)) == -1) {
2558 pagesize = getpagesize();
2559 dprintf("AT_PAGESZ missing; defaulting to %d\n", pagesize);
2560 }
2561
2562 /*
2563 * Locate and label the mappings corresponding to the end of the
2564 * heap (MA_BREAK) and the base of the stack (MA_STACK).
2565 */
2566 if ((P->status.pr_brkbase != 0 || P->status.pr_brksize != 0) &&
2567 (brk_mp = Paddr2mptr(P, P->status.pr_brkbase +
2568 P->status.pr_brksize - 1)) != NULL)
2569 brk_mp->map_pmap.pr_mflags |= MA_BREAK;
|