pmap.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <limits.h>
#include <link.h>
#include <libelf.h>
#include <libproc.h>
struct totals {
};
typedef int proc_xmap_f(void *, const prxmap_t *, const char *, int, int);
int);
static int look_xmap_nopgsz(void *, const prxmap_t *, const char *,
int, int);
static int gather_map(void *, const prmap_t *, const char *);
static int gather_xmap(void *, const prxmap_t *, const char *, int, int);
static int iter_map(proc_map_f *, void *);
static int iter_xmap(proc_xmap_f *, void *);
static int perr(char *);
static void printK(long, int);
static int lflag = 0;
static int aflag = 0;
static int addr_width, size_width;
static char *command;
static char *procname;
static struct ps_prochandle *Pr;
typedef struct lwpstack {
} lwpstack_t;
typedef struct {
char *md_objname;
int md_last;
int md_doswap;
} mapdata_t;
static int map_count;
static int map_alloc;
#define MAX_TRIES 5
static int
{
(*np)++;
}
(*np)++;
}
return (0);
}
/*
* We compare the high memory addresses since stacks are faulted in from
* high memory addresses to low memory addresses, and our prmap_t
* structures identify only the range of addresses that have been faulted
* in so far.
*/
static int
{
if (a < b)
return (1);
if (a > b)
return (-1);
return (0);
}
int
{
int rc = 0;
int opt;
const char *bar8 = "-------";
const char *bar16 = "----------";
const char *bar;
char buf[128];
int mapfd;
command++;
else
switch (opt) {
case 'a': /* include shared mappings in -[xS] */
aflag = 1;
break;
case 'r': /* show reserved mappings */
rflag = 1;
break;
case 's': /* show hardware page sizes */
sflag = 1;
break;
case 'S': /* show swap reservations */
Sflag = 1;
break;
case 'x': /* show extended mappings */
xflag = 1;
break;
case 'l': /* show unresolved link map names */
lflag = 1;
break;
case 'F':
/*
* Since we grab the process readonly now, the -F flag
* is meaningless. Consume it anyway it for backwards
* compatbility.
*/
break;
default:
errflg = 1;
break;
}
}
errflg = 1;
}
"usage:\t%s [-rslF] { pid | core } ...\n", command);
"\t\t(report process address maps)\n");
"\t%s -x [-aslF] pid ...\n", command);
"\t%s -S [-alF] { pid | core } ...\n", command);
"\t\t(show swap reservations)\n\n");
"\t-a: include shared mappings in -[xS] summary\n");
"\t-r: show reserved address maps\n");
"\t-s: show hardware page sizes\n");
"\t-l: show unresolved dynamic linker map names\n");
"\t-F: force grabbing of the target process\n");
return (2);
}
/*
* Make sure we'll have enough file descriptors to handle a target
* that has many many mappings.
*/
}
while (argc-- > 0) {
char *arg;
int gcode;
int tries = 0;
rc++;
continue;
}
"examine %s: lost control of "
rc++;
continue;
}
} else {
mapfd = -1;
}
map_count = 0;
(void) printf("core '%s' of %d:\t%.70s\n",
(void) printf(" -%c option is not compatible "
rc++;
continue;
}
} else {
(void) printf("%d:\t%.70s\n",
}
struct totals t;
/*
* Since we're grabbing the process readonly, we need
* to make sure the address space doesn't change during
* execution.
*/
"examine %s: address space is "
continue;
}
"examine %s: lost control of "
continue;
}
}
int n = 0;
}
(void) memset(&t, 0, sizeof (t));
"librtld_db failed to initialize; "
"shared library information will not be "
"available\n", command);
}
/*
* Gather data
*/
if (xflag)
else if (Sflag)
else {
if (rflag)
NULL);
else if (sflag)
NULL, 0);
else
NULL);
}
/*
* Ensure mappings are consistent.
*/
}
goto again;
}
}
/*
* Display data.
*/
if (xflag) {
(void) printf("%*s%*s%*s%*s%*s "
"%sMode Mapped File\n",
addr_width, "Address",
size_width, "Kbytes",
size_width, "RSS",
size_width, "Anon",
size_width, "Locked",
look_xmap_nopgsz, &t);
(void) printf("%s%s %s %s %s %s\n",
" " : "");
(void) printf("\n");
} else if (Sflag) {
(void) printf("%*s%*s%*s Mode Mapped File\n",
addr_width, "Address",
size_width, "Kbytes",
size_width, "Swap");
(void) printf("%s%s %s %s\n",
" " : "");
(void) printf("\n");
} else {
if (rflag) {
} else if (sflag) {
(void) printf("%*s %*s %4s %-6s %s\n",
"Bytes", "Pgsz", "Mode ",
"Mapped File");
} else {
}
(void) printf(" %stotal %*luK\n",
addr_width == 16 ?
" " : "",
size_width, t.total_size);
}
}
}
if (mapfd != -1)
}
return (rc);
}
static char *
{
char fname[100];
int len;
return (buf);
if (lflag)
return (buf);
return (buf);
}
}
return (buf);
}
}
return (NULL);
}
static char *
{
if (shmid == -1)
else
if (shmid == -1)
else
} else {
if (nstacks > 0 &&
"altstack" : "stack",
stk->lwps_lwpid);
} else {
return (NULL);
}
}
return (name);
}
static int
{
ssize_t n;
if (mapfd >= 0)
}
return (perr("read rmap"));
}
return (rc);
}
}
return (0);
}
static int
{
ssize_t n;
if (mapfd >= 0)
}
nmap *= 2;
return (perr("read xmap"));
}
nmap *= 2;
goto again;
}
return (rc);
}
}
return (0);
}
/*ARGSUSED*/
static int
{
/*
* If the mapping is not anon or not part of the heap, make a name
* for it. We don't want to report the heap as a.out's data.
*/
}
}
t->total_size += size;
return (0);
}
static void
{
if (value == 0)
else
}
static const char *
{
static char buf[32];
if (pagesize == 0) {
return ("-"); /* no underlying HAT mapping */
}
else
pagesize / 1024);
} else
return (buf);
}
/*ARGSUSED*/
static int
const char *object_name,
{
const char *format;
/*
* If the mapping is not anon or not part of the heap, make a name
* for it. We don't want to report the heap as a.out's data.
*/
}
}
format = "%.*lX %*luK %4s %-6s %s\n";
else
format = "%.*lX %*luK %4s %s\n";
t->total_size += size;
return (0);
}
((x)->pr_anon) : 0)
/*ARGSUSED*/
static int
const char *object_name,
{
char *ln;
/*
* If the mapping is not anon or not part of the heap, make a name
* for it. We don't want to report the heap as a.out's data.
*/
}
}
return (0);
}
/*ARGSUSED*/
static int
look_xmap_nopgsz(void *data,
const char *object_name,
{
char *ln;
static uintptr_t prev_vaddr;
static offset_t prev_offset;
static int prev_mflags;
static char *prev_lname;
static char prev_mname[PATH_MAX];
static ulong_t prev_locked;
int merged = 0;
static int first = 1;
int kperpage;
/*
* Calculate swap reservations
*/
/* Swap reserved for entire non-ism SHM */
}
/* Swap reserved on fault for each anon page */
/* Swap reserve for entire writable segment */
}
/*
* If the mapping is not anon or not part of the heap, make a name
* for it. We don't want to report the heap as a.out's data.
*/
}
}
if (first == 1) {
first = 0;
prev_lname = NULL;
} else {
}
if (last == 0) {
return (0);
}
merged = 1;
((prev_mflags & MA_ISM) ||
if (last == 0) {
return (0);
}
merged = 1;
}
if (doswap)
else {
}
if (last == 0) {
prev_lname = NULL;
} else {
}
} else if (merged == 0) {
if (doswap)
else {
}
}
if (last != 0)
first = 1;
return (0);
}
static int
perr(char *s)
{
if (s)
else
s = procname;
perror(s);
return (1);
}
static char *
{
static char code_buf[80];
/*
* rwxsR
*
* r - segment is readable
* w - segment is writable
* x - segment is executable
* s - segment is shared
* R - segment is mapped MAP_NORESERVE
*
*/
return (str);
}
static mapdata_t *
nextmap(void)
{
int next;
if (map_alloc == 0)
next = 16;
else
(void) perr("failed to allocate maps");
exit(1);
}
}
}
/*ARGSUSED*/
static int
{
return (0);
}
/*ARGSUSED*/
static int
{
return (0);
}
static int
{
int i;
int ret;
for (i = 0; i < map_count; i++) {
maps[i].md_objname)) != 0)
return (ret);
}
return (0);
}
static int
{
int i;
int ret;
for (i = 0; i < map_count; i++) {
return (ret);
}
return (0);
}