c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * CDDL HEADER START
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * The contents of this file are subject to the terms of the
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Common Development and Distribution License (the "License").
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * You may not use this file except in compliance with the License.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * or http://www.opensolaris.org/os/licensing.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * See the License for the specific language governing permissions
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * and limitations under the License.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * When distributing Covered Code, include this CDDL HEADER in each
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * If applicable, add the following below this CDDL HEADER, with the
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * fields enclosed by brackets "[]" replaced with your own identifying
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * information: Portions Copyright [yyyy] [name of copyright owner]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * CDDL HEADER END
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Use is subject to license terms.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill/*
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill * Copyright (c) 2015, Joyent, Inc. All rights reserved.
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill */
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * pmadvise
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * ptool wrapper for madvise(3C) to apply memory advice to running processes
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * usage: pmadvise -o option[,option] [-v] [-F] pid ...
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * (Give "advice" about a process's memory)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * -o option[,option]: options are
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * private=<advice>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * shared=<advice>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * heap=<advice>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * stack=<advice>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * <segaddr>[:<length>]=<advice>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * valid <advice> is one of:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * normal, random, sequential, willneed, dontneed,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * free, access_lwp, access_many, access_default
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * -v: verbose output
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * -F: force grabbing of the target process(es)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * -l: show unresolved dynamic linker map names
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * pid: process id list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Advice passed to this tool are organized into various lists described here:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * rawadv_list: includes all specific advice from command line (specific
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * advice being those given to a particular address range rather
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * than a type like "heap" or "stack". In contrast, these
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * types are referred to as generic advice). Duplicates allowed.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * List ordered by addr, then by size (largest size first).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Created once per run.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * merged_list: includes all specific advice from the rawadv_list as well as
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * all generic advice. This must be recreated for each process
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * as the generic advice will apply to different regions for
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * different processes. Duplicates allowed. List ordered by addr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * then by size (largest size first). Created once per pid.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * chopped_list: used for verbose output only. This list parses the merged
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * list such that it eliminates any overlap and combines the
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * advice. Easiest to think of this visually: if you take all
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * the advice in the merged list and lay them down on a memory
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * range of the entire process (laying on top of each other when
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * necessary), then flatten them into one layer, combining advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * in the case of overlap, you get the chopped_list of advice.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Duplicate entries not allowed (since there is no overlap by
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * definition in this list). List ordered by addr. Created once
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * per pid.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Example:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * merged_list: |-----adv1----|---------adv3---------|
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * |--adv2--|--adv4--|-----adv5----|
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * ||
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * \/
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * chopped_list: |adv1|-adv1,2-|-adv3,4-|----adv3,5---|
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * maplist: list of memory mappings for a particular process. Used to create
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * generic advice entries for merged_list and for pmap like verbose
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * output. Created once per pid.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Multiple lists are necessary because the actual advice applied given a set
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * of generic and specific advice changes from process to process, so for each
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * pid pmadvise is passed, it must create a new merged_list from which to apply
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * advice (and a new chopped_list if verbose output is requested).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Pseudo-code:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * I. Input advice from command line
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * II. Create [raw advice list] of specific advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * III. Iterate through PIDs:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * A. Create [map list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * B. Merge generic advice and [raw advice list] into [merged list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * C. Apply advice from [merged list]; upon error:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * i. output madvise error message
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * ii. remove element from [merged list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * D. If verbose output:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * i. Create [chopped list] from [merged list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * ii. Iterate through [map list]:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * a. output advice as given by [merged list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * iii. Delete [chopped list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * E. Delete [merged list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * F. Delete [map list]
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <stdio.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <stdlib.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <unistd.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <ctype.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <fcntl.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <string.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <dirent.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <limits.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <link.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <libelf.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <locale.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <sys/types.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <sys/mman.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <sys/stat.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <sys/mkdev.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <assert.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <libproc.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <libgen.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#include <signal.h>
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include "pmap_common.h"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#ifndef TEXT_DOMAIN /* should be defined by cc -D */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define TEXT_DOMAIN "SYS_TEST" /* use this only if it wasn't */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#endif
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define KILOBYTE 1024
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Round up the value to the nearest kilobyte
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define ROUNDUP_KB(x) (((x) + (KILOBYTE - 1)) / KILOBYTE)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define NO_ADVICE 0
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * The following definitions are used as the third argument in insert_addr()
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * NODUPS = no duplicates are not allowed, thus if the addr being inserted
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * already exists in the list, return without inserting again.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * YESDUPS = yes duplicates are allowed, thus always insert the addr
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * regardless of whether it already exists in the list or not.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define NODUPS 1
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define YESDUPS 0
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Advice that can be passed to madvise fit into three groups that each
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * contain 3 mutually exclusive options. These groups are defined below:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Group 1: normal, random, sequential
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill * Group 2: willneed, dontneed, free, purge
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Group 3: default, accesslwp, accessmany
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Thus, advice that includes (at most) one from each group is valid.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * The following #define's are used as masks to determine which group(s) a
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * particular advice fall under.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define GRP1_ADV (1 << MADV_NORMAL | 1 << MADV_RANDOM | \
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb 1 << MADV_SEQUENTIAL)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define GRP2_ADV (1 << MADV_WILLNEED | 1 << MADV_DONTNEED | \
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill 1 << MADV_FREE | 1 << MADV_PURGE)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb#define GRP3_ADV (1 << MADV_ACCESS_DEFAULT | 1 << MADV_ACCESS_LWP | \
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb 1 << MADV_ACCESS_MANY)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int create_maplist(void *, const prmap_t *, const char *);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int pr_madvise(struct ps_prochandle *, caddr_t, size_t, int);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *mflags(uint_t);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *advtostr(int);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstatic int lflag = 0;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int addr_width, size_width;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *progname;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic struct ps_prochandle *Pr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic lwpstack_t *stacks;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic uint_t nstacks;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *suboptstr[] = {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "private",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "shared",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "heap",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "stack",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb NULL
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb};
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbint generic_adv[] = {NO_ADVICE, NO_ADVICE, NO_ADVICE, NO_ADVICE};
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbint at_map = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbtypedef struct saddr_struct {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb uintptr_t addr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb size_t length;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int adv;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb struct saddr_struct *next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb} saddr_t;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int apply_advice(saddr_t **);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void set_advice(int *, int);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void create_choplist(saddr_t **, saddr_t *);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * The segment address advice from the command line
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbsaddr_t *rawadv_list = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * The rawadv_list + list entries for the generic advice (if any).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * This must be recreated for each PID as the memory maps might be different.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbsaddr_t *merged_list = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * The merged_list cut up so as to remove all overlap
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * e.g. if merged_list contained two entries:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x38000:0x3e000) = adv1
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x3a000:0x3c000) = adv2
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * the chopped list will contain three entries:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x38000:0x3a000) = adv1
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x3a000:0x3c000) = adv1,adv2
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x3c000:0x3e000) = adv1
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbsaddr_t *chopped_list = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbtypedef struct mapnode_struct {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb prmap_t *pmp;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb char label[PATH_MAX];
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int mtypes;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb struct mapnode_struct *next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb} mapnode_t;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbmapnode_t *maplist_head = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbmapnode_t *maplist_tail = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void print_advice(saddr_t *, mapnode_t *);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbint opt_verbose;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *advicestr[] = {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "normal",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "random",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "sequential",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "willneed",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "dontneed",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "free",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "access_default",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "access_lwp",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "access_many"
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb};
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * How many signals caught from terminal
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * We bail out as soon as possible when interrupt is set
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int interrupt = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Interrupt handler
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void intr(int);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Iterative function passed to Plwp_iter to
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * get alt and main stacks for given lwp.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbgetstack(void *data, const lwpstatus_t *lsp)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int *np = (int *)data;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (Plwp_alt_stack(Pr, lsp->pr_lwpid, &stacks[*np].lwps_stack) == 0) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb stacks[*np].lwps_stack.ss_flags |= SS_ONSTACK;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb stacks[*np].lwps_lwpid = lsp->pr_lwpid;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (*np)++;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (Plwp_main_stack(Pr, lsp->pr_lwpid, &stacks[*np].lwps_stack) == 0) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb stacks[*np].lwps_lwpid = lsp->pr_lwpid;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (*np)++;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Prints usage and exits
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbusage()
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz gettext("usage:\t%s [-o option[,option]] [-Flv] pid ...\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb gettext(" (Give \"advice\" about a process's memory)\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " -o option[,option]: options are\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " private=<advice>\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " shared=<advice>\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " heap=<advice>\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " stack=<advice>\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " <segaddr>[:<length>]=<advice>\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " valid <advice> is one of:\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " normal, random, sequential, willneed, dontneed,\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " free, access_lwp, access_many, access_default\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " -v: verbose output\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " -F: force grabbing of the target process(es)\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " -l: show unresolved dynamic linker map names\n"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz " pid: process id list\n"));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb exit(2);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Function to parse advice from options string
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbget_advice(char *optarg)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Determine which advice is given, we use shifted values as
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * multiple pieces of advice may apply for a particular region.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * (See comment above regarding GRP[1,2,3]_ADV definitions for
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * breakdown of advice groups).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (strcmp(optarg, "access_default") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_ACCESS_DEFAULT);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "access_many") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_ACCESS_MANY);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "access_lwp") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_ACCESS_LWP);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "sequential") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_SEQUENTIAL);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "willneed") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_WILLNEED);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "dontneed") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_DONTNEED);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "random") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_RANDOM);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "normal") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_NORMAL);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (strcmp(optarg, "free") == 0)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (1 << MADV_FREE);
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill else if (strcmp(optarg, "purge") == 0)
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill return (1 << MADV_PURGE);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr, gettext("%s: invalid advice: %s\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname, optarg);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (-1);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Function to convert character size indicators into actual size
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * (i.e., 123M => sz = 123 * 1024 * 1024)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic size_t
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbatosz(char *optarg, char **endptr)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb size_t sz = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (optarg == NULL || optarg[0] == '\0')
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz = strtoll(optarg, endptr, 0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb switch (**endptr) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'E':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'e':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz *= KILOBYTE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'P':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'p':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz *= KILOBYTE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'T':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 't':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz *= KILOBYTE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'G':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'g':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz *= KILOBYTE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'M':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'm':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz *= KILOBYTE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'K':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'k':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb sz *= KILOBYTE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'B':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'b':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (*endptr)++;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* FALLTHRU */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb default:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (sz);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Inserts newaddr into list. dups indicates whether we allow duplicate
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * addr entries in the list (valid values are NODUPS and YESDUPS).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbinsert_addr(saddr_t **list, saddr_t *newaddr, int dups)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *prev = *list;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (*list == NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->next = *list;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *list = newaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb for (psaddr = (*list)->next; psaddr != NULL; psaddr = psaddr->next) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if ((dups == NODUPS) && (psaddr->addr == newaddr->addr)) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(newaddr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * primary level of comparison is by address; smaller addr 1st
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * secondary level of comparison is by length; bigger length 1st
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if ((psaddr->addr > newaddr->addr) ||
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (psaddr->addr == newaddr->addr &&
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->length < newaddr->length))
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb prev = psaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb prev->next = newaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->next = psaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Deletes given element from list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbdelete_addr(saddr_t **list, saddr_t *delme)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *prev = *list;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (delme == *list) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *list = delme->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(delme);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (prev != NULL && prev->next != delme) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb prev = prev->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (prev) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb prev->next = delme->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(delme);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Delete entire list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbdelete_list(saddr_t **list)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr = *list;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (psaddr != NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *temp = psaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = psaddr->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(temp);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *list = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic saddr_t *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbparse_suboptions(char *value)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb char *endptr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr = malloc(sizeof (saddr_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * This must (better) be a segment addr
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->addr =
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb strtoull(value, &endptr, 16);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Check to make sure strtoul worked correctly (a properly formatted
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * string will terminate in a ':' (if size is given) or an '=' (if size
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * is not specified). Also check to make sure a 0 addr wasn't returned
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * indicating strtoll was unable to convert).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if ((psaddr->addr == 0) || (*endptr != ':' && *endptr != '=')) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(psaddr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb gettext("%s: invalid option %s\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname, value);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb } else {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* init other fields */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->length = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->adv = NO_ADVICE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->next = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* skip past address */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb value = endptr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* check for length */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (*value == ':') {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* skip the ":" */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb value++;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->length = atosz(value, &endptr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (*endptr != '=') {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb gettext("%s: invalid option %s\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname, value);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * if improperly formatted, free mem, print usage, and
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * exit Note: usage ends with a call to exit()
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(psaddr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /* skip the "=" */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb value = endptr + 1;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb at_map |= (1 << AT_SEG);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->adv =
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb get_advice(value);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (psaddr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Create linked list of mappings for current process
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * In addition, add generic advice and raw advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * entries to merged_list.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/* ARGSUSED */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbcreate_maplist(void *arg, const prmap_t *pmp, const char *object_name)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb const pstatus_t *Psp = Pstatus(Pr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb mapnode_t *newmap = malloc(sizeof (mapnode_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *newaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb char *lname = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int i;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (interrupt)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->pmp = malloc(sizeof (prmap_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->label[0] = '\0';
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->mtypes = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->next = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) memcpy(newmap->pmp, pmp, sizeof (prmap_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * If the mapping is not anon or not part of the heap, make a name
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * for it. We don't want to report the heap as a.out's data.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (!(pmp->pr_mflags & MA_ANON) ||
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (pmp->pr_vaddr + pmp->pr_size <= Psp->pr_brkbase ||
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb pmp->pr_vaddr >= Psp->pr_brkbase + Psp->pr_brksize)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz lname = make_name(Pr, lflag, pmp->pr_vaddr, pmp->pr_mapname,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->label, sizeof (newmap->label));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (pmp->pr_mflags & MA_SHARED)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->mtypes |= 1 << AT_SHARED;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->mtypes |= 1 << AT_PRIVM;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (lname == NULL && (pmp->pr_mflags & MA_ANON)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz lname = anon_name(newmap->label, Psp, stacks, nstacks,
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pmp->pr_vaddr, pmp->pr_size, pmp->pr_mflags, pmp->pr_shmid,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb &newmap->mtypes);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Add raw advice that applies to this mapping to the merged_list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = rawadv_list;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Advance to point in rawadv_list that applies to this mapping
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (psaddr && psaddr->addr < pmp->pr_vaddr)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = psaddr->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Copy over to merged_list, check to see if size needs to be filled in
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (psaddr && psaddr->addr < (pmp->pr_vaddr + pmp->pr_size)) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr = malloc(sizeof (saddr_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) memcpy(newaddr, psaddr, sizeof (saddr_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb insert_addr(&merged_list, newaddr, YESDUPS);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * For raw advice that is given without size, try to default
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * size to size of mapping (only allowed if raw adv addr is
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * equal to beginning of mapping). Don't change the entry
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * in rawadv_list, only in the merged_list as the mappings
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * (and thus the default sizes) will be different for
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * different processes.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if ((pmp->pr_vaddr == psaddr->addr) && (psaddr->length == 0))
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->length = pmp->pr_size;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = psaddr->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Put mapping into merged list with no advice, then
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * check to see if any generic advice applies.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr = malloc(sizeof (saddr_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->addr = pmp->pr_vaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->length = pmp->pr_size;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->adv = NO_ADVICE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb insert_addr(&merged_list, newaddr, YESDUPS);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newmap->mtypes &= at_map;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb for (i = AT_STACK; i >= AT_PRIVM; i--) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (newmap->mtypes & (1 << i)) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb assert(generic_adv[i] != NO_ADVICE);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb newaddr->adv = generic_adv[i];
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Add to linked list of mappings
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (maplist_tail == NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb maplist_head = maplist_tail = newmap;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb } else {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb maplist_tail->next = newmap;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb maplist_tail = newmap;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Traverse advice list and apply all applicable advice to each region
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbapply_advice(saddr_t **advicelist)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr = *advicelist;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int i;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (!interrupt && psaddr != NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Save next pointer since element may be removed before
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * we get a chance to advance psaddr.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb next = psaddr->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Since mappings have been added to the merged list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * even if no generic advice was given for the map,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * check to make sure advice exists before bothering
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * with the for loop.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (psaddr->adv != NO_ADVICE) {
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill for (i = MADV_NORMAL; i <= MADV_PURGE; i++) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if ((psaddr->adv & (1 << i)) &&
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (pr_madvise(Pr, (caddr_t)psaddr->addr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->length, i) < 0)) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * madvise(3C) call failed trying to
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * apply advice output error and remove
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * from advice list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb gettext("Error applying "
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "advice (%s) to memory range "
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "[%lx, %lx):\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb advicestr[i], (ulong_t)psaddr->addr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (ulong_t)psaddr->addr +
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->length);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb perror("madvise");
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Clear this advice from the advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * mask. If no more advice is given
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * for this element, remove element
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * from list.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr->adv &= ~(1 << i);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (psaddr->adv == 0) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb delete_addr(advicelist, psaddr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Set advice but keep mutual exclusive property of advice groupings
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbset_advice(int *combined_adv, int new_adv) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Since advice falls in 3 groups of mutually exclusive options,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * clear previous value if new advice overwrites that group.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * If this is the first advice to be applied, clear invalid value (-1)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (*combined_adv == -1)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *combined_adv = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (new_adv & GRP1_ADV)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *combined_adv &= ~GRP1_ADV;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else if (new_adv & GRP2_ADV)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *combined_adv &= ~GRP2_ADV;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *combined_adv &= ~GRP3_ADV;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *combined_adv |= new_adv;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Create chopped list from merged list for use with verbose output
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbcreate_choplist(saddr_t **choppedlist, saddr_t *mergedlist)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *mlptr, *clptr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb for (mlptr = mergedlist; mlptr != NULL; mlptr = mlptr->next) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr = malloc(sizeof (saddr_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->addr = mlptr->addr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->length = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Initialize the adv to -1 as an indicator for invalid
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * elements in the chopped list (created from gaps between
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * memory maps).
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->adv = -1;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->next = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb insert_addr(choppedlist, clptr, NODUPS);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr = malloc(sizeof (saddr_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->addr = mlptr->addr + mlptr->length;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->length = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Again, initialize to -1 as an indicatorfor invalid elements
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->adv = -1;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->next = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb insert_addr(choppedlist, clptr, NODUPS);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb for (clptr = *choppedlist; clptr != NULL; clptr = clptr->next) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (clptr->next) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->length = clptr->next->addr - clptr->addr;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * must be last element, now that we've calculated
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * all segment lengths, we can remove this node
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb delete_addr(choppedlist, clptr);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb for (mlptr = mergedlist; mlptr != NULL; mlptr = mlptr->next) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb for (clptr = *choppedlist; clptr != NULL; clptr = clptr->next) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (mlptr->addr <= clptr->addr &&
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb mlptr->addr + mlptr->length >=
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->addr + clptr->length)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * set_advice() will take care of conflicting
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * advice by taking only the last advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * applied for each of the 3 groups of advice.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb set_advice(&clptr->adv, mlptr->adv);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (mlptr->addr + mlptr->length <
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb clptr->addr)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Print advice in pmap style for verbose output
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbprint_advice(saddr_t *advlist, mapnode_t *maplist)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr = advlist;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb mapnode_t *pmapnode;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb char *advice;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb pmapnode = maplist;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (psaddr) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Using indicator flag from create_choppedlist, we know
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * which entries in the chopped_list are gaps and should
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * not be printed.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (psaddr->adv == -1) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = psaddr->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb continue;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (pmapnode && (pmapnode->pmp->pr_vaddr +
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb pmapnode->pmp->pr_size <= psaddr->addr))
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb pmapnode = pmapnode->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb advice = advtostr(psaddr->adv);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Print segment mapping and advice if there is any, or just a
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * segment mapping.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (strlen(advice) > 0) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) printf("%.*lX %*uK %6s %s\t%s\n",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb addr_width, (ulong_t)psaddr->addr, size_width - 1,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (int)ROUNDUP_KB(psaddr->length),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb mflags(pmapnode->pmp->pr_mflags), pmapnode->label,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb advice);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb } else {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) printf("%.*lX %*uK %6s %s\n",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb addr_width, (ulong_t)psaddr->addr, size_width - 1,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (int)ROUNDUP_KB(psaddr->length),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb mflags(pmapnode->pmp->pr_mflags), pmapnode->label);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = psaddr->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Call madvise(3c) in the context of the target process
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic int
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbpr_madvise(struct ps_prochandle *Pr, caddr_t addr, size_t len, int advice)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (pr_memcntl(Pr, addr, len, MC_ADVISE,
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (caddr_t)(uintptr_t)advice, 0, 0));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbmflags(uint_t arg)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb static char code_buf[80];
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * rwxsR
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * r - segment is readable
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * w - segment is writable
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * x - segment is executable
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * s - segment is shared
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * R - segment is mapped MAP_NORESERVE
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) snprintf(code_buf, sizeof (code_buf), "%c%c%c%c%c ",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb arg & MA_READ ? 'r' : '-',
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb arg & MA_WRITE ? 'w' : '-',
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb arg & MA_EXEC ? 'x' : '-',
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb arg & MA_SHARED ? 's' : '-',
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb arg & MA_NORESERVE ? 'R' : '-');
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (code_buf);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Convert advice to a string containing a commented list of applicable advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic char *
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbadvtostr(int adv)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb static char buf[50];
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int i;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb *buf = '\0';
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (adv != NO_ADVICE) {
8905f42caceb9f470ffaa19e5f6c9fb6184d12c0Bryan Cantrill for (i = MADV_NORMAL; i <= MADV_PURGE; i++) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (adv & (1 << i)) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * check if it's the first advice entry
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (*buf == '\0')
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) snprintf(buf, sizeof (buf) - 1,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "<= %s", advicestr[i]);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb else
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) snprintf(buf, sizeof (buf) - 1,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb "%s,%s", buf, advicestr[i]);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (buf);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Handler for catching signals from terminal
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb/* ARGSUSED */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbstatic void
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbintr(int sig)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb interrupt++;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbint
c64027834c5ffc60c557c2b12555e0cd4d30320cakolbmain(int argc, char **argv)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb{
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int Fflag = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int rc = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int opt, subopt;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int tmpadv;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb char *options, *value;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb saddr_t *psaddr;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb mapnode_t *pmapnode, *tempmapnode;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) setlocale(LC_ALL, "");
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) textdomain(TEXT_DOMAIN);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Get name of program for error messages
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname = basename(argv[0]);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Not much to do when only name of program given
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (argc == 1)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Catch signals from terminal, so they can be handled asynchronously
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * when we're ready instead of when we're not (;-)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) sigset(SIGHUP, intr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) sigset(SIGINT, intr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) sigset(SIGQUIT, intr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) sigset(SIGPIPE, intr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) sigset(SIGTERM, intr);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Parse options, record generic advice if any and create
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * rawadv_list from specific address advice.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz while ((opt = getopt(argc, argv, "Flo:v")) != EOF) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb switch (opt) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'o':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb options = optarg;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (*options != '\0') {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb subopt = getsubopt(&options, suboptstr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb &value);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb switch (subopt) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case AT_PRIVM:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case AT_HEAP:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case AT_SHARED:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case AT_STACK:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb at_map |= (1 << subopt);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb tmpadv = get_advice(value);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb set_advice(&generic_adv[subopt],
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb tmpadv);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb default:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb at_map |= (1 << AT_SEG);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr = parse_suboptions(value);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (psaddr == NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb } else {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb insert_addr(&rawadv_list,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psaddr, YESDUPS);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'v':
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb opt_verbose = 1;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb case 'F': /* force grabbing (no O_EXCL) */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb Fflag = PGRAB_FORCE;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz case 'l': /* show unresolved link map names */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz lflag = 1;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb default:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb break;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb argc -= optind;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb argv += optind;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (argc <= 0) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb usage();
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb (void) proc_initstdio();
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Iterate through all pid arguments, create new merged_list, maplist,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * (and chopped_list if using verbose output) based on each process'
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * memory map.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (!interrupt && argc-- > 0) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb char *arg;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int gcode;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb psinfo_t psinfo;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb (void) proc_flushstdio();
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_PIDS,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb PGRAB_RETAIN | Fflag, &gcode)) == NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb gettext("%s: cannot examine %s: %s\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname, arg, Pgrab_error(gcode));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb rc++;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb continue;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb addr_width =
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 16 : 8;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb size_width =
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 11 : 8;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (opt_verbose) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb proc_unctrl_psinfo(&psinfo);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) printf("%d:\t%.70s\n",
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (int)psinfo.pr_pid, psinfo.pr_psargs);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Get mappings for a process unless it is a system process.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (!(Pstatus(Pr)->pr_flags & PR_ISSYS)) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb nstacks = psinfo.pr_nlwp * 2;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb stacks = calloc(nstacks, sizeof (stacks[0]));
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (stacks != NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb int n = 0;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) Plwp_iter(Pr, getstack, &n);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb qsort(stacks, nstacks, sizeof (stacks[0]),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb cmpstacks);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (Pgetauxval(Pr, AT_BASE) != -1L &&
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb Prd_agent(Pr) == NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) fprintf(stderr,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb gettext("%s: warning: "
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "librtld_db failed to initialize; "
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "shared library information will not "
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "be available\n"),
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb progname);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Create linked list of mappings for current process
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * In addition, add generic advice and raw advice
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * entries to merged_list.
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * e.g. if rawadv_list contains:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x38000,0x3a000) = adv1
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x3a000,0x3c000) = adv2
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * and there is generic advice:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * heap = adv3
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * where heap corresponds to 0x38000, then merged_list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * will contain:
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * ... (include all other mappings from process)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x38000,0x3c000) = adv3
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x38000,0x3a000) = adv1
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * [0x3a000,0x3c000) = adv2
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * ... (include all other mappings from process)
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb assert(merged_list == NULL);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb maplist_head = maplist_tail = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb rc += Pmapping_iter(Pr, (proc_map_f *)create_maplist,
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb NULL);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Apply advice by iterating through merged list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb (void) apply_advice(&merged_list);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (opt_verbose) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb assert(chopped_list == NULL);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Create chopped_list from merged_list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb create_choplist(&chopped_list, merged_list);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Iterate through maplist and output as
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * given by chopped_list
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb print_advice(chopped_list, maplist_head);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb delete_list(&chopped_list);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb delete_list(&merged_list);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb /*
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb * Clear maplist
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb */
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb pmapnode = maplist_head;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb while (pmapnode) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb tempmapnode = pmapnode;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb pmapnode = pmapnode->next;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(tempmapnode);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb if (stacks != NULL) {
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb free(stacks);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb stacks = NULL;
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb Prelease(Pr, 0);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb }
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb (void) proc_finistdio();
7595fad9bab86562dbe8d6580c4b310bbad949b7akolb
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb return (rc);
c64027834c5ffc60c557c2b12555e0cd4d30320cakolb}