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) {
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
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 */
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 #if defined(__i386) || defined(__amd64)
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) {
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 #if defined(__i386) || defined(__amd64)
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 /* defined(__i386) || defined(__amd64) */
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
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 #if defined(__i386) || defined(__amd64)
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 #if defined(__i386) || defined(__amd64)
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 #if defined(__i386) || defined(__amd64)
1165 note_ldt, /* 9 NT_LDT */
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 #if defined(__i386) || defined(__amd64)
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 #if defined(__i386) || defined(__amd64)
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 #if defined(__i386) || defined(__amd64)
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 /* defined(__i386) || defined(__amd64) */
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;
|