Blame ipcs.c

Packit bf408e
/* ipcs.c - provide information on ipc facilities
Packit bf408e
 *
Packit bf408e
 * Copyright (C) 2012 FUJITSU LIMITED
Packit bf408e
 * Auther: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
Packit bf408e
 *
Packit bf408e
 * This program is free software; you can redistribute it and/or modify
Packit bf408e
 * it under the terms of the GNU General Public License as published by
Packit bf408e
 * the Free Software Foundation; either version 2 of the License, or
Packit bf408e
 * (at your option) any later version.
Packit bf408e
 *
Packit bf408e
 * This program is distributed in the hope that it will be useful,
Packit bf408e
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bf408e
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bf408e
 * GNU General Public License for more details.
Packit bf408e
 */
Packit bf408e

Packit bf408e
#include "defs.h"    /* From the crash source top-level directory */
Packit bf408e

Packit bf408e
#define SPECIFIED_NOTHING 0x0
Packit bf408e
#define SPECIFIED_ID      0x1
Packit bf408e
#define SPECIFIED_ADDR    0x2
Packit bf408e

Packit bf408e
#define IPCS_INIT  0x1
Packit bf408e
#define IDR_ORIG   0x2
Packit bf408e
#define IDR_RADIX  0x4
Packit bf408e
#define IDR_XARRAY 0x8
Packit bf408e

Packit bf408e
#define MAX_ID_SHIFT (sizeof(int)*8 - 1)
Packit bf408e
#define MAX_ID_BIT (1U << MAX_ID_SHIFT)
Packit bf408e
#define MAX_ID_MASK (MAX_ID_BIT - 1)
Packit bf408e

Packit bf408e
#define SHM_DEST   01000
Packit bf408e
#define SHM_LOCKED 02000
Packit bf408e

Packit bf408e
struct shm_info {
Packit bf408e
	ulong shmid_kernel;
Packit bf408e
	int key;
Packit bf408e
	int shmid;
Packit bf408e
	ulong rss;
Packit bf408e
	ulong swap;
Packit bf408e
	unsigned int uid;
Packit bf408e
	unsigned int perms;
Packit bf408e
	ulong bytes;
Packit bf408e
	ulong nattch;
Packit bf408e
	ulong shm_inode;
Packit bf408e
	int deleted;
Packit bf408e
};
Packit bf408e

Packit bf408e
struct sem_info {
Packit bf408e
	ulong sem_array;
Packit bf408e
	int key;
Packit bf408e
	int semid;
Packit bf408e
	unsigned int uid;
Packit bf408e
	unsigned int perms;
Packit bf408e
	ulong nsems;
Packit bf408e
	int deleted;
Packit bf408e
};
Packit bf408e

Packit bf408e
struct msg_info {
Packit bf408e
	ulong msg_queue;
Packit bf408e
	int key;
Packit bf408e
	int msgid;
Packit bf408e
	unsigned int uid;
Packit bf408e
	unsigned int perms;
Packit bf408e
	ulong bytes;
Packit bf408e
	ulong messages;
Packit bf408e
	int deleted;
Packit bf408e
};
Packit bf408e

Packit bf408e
struct ipcs_table {
Packit bf408e
	int idr_bits;
Packit bf408e
	ulong init_flags;
Packit bf408e
	ulong hugetlbfs_f_op_addr;
Packit bf408e
	ulong shm_f_op_addr;
Packit bf408e
	ulong shm_f_op_huge_addr;
Packit bf408e
	int use_shm_f_op;
Packit bf408e
	int seq_multiplier;
Packit bf408e
	int cnt;
Packit bf408e
	struct list_pair *lp;
Packit bf408e
};
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * function declaration
Packit bf408e
 */
Packit bf408e

Packit bf408e
static int dump_shared_memory(int, ulong, int, ulong);
Packit bf408e
static int dump_semaphore_arrays(int, ulong, int, ulong);
Packit bf408e
static int dump_message_queues(int, ulong, int, ulong);
Packit bf408e
static int ipc_search_idr(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
Packit bf408e
static int ipc_search_array(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
Packit bf408e
static int dump_shm_info(ulong, int, ulong, int, int);
Packit bf408e
static int dump_sem_info(ulong, int, ulong, int, int);
Packit bf408e
static int dump_msg_info(ulong, int, ulong, int, int);
Packit bf408e
static void get_shm_info(struct shm_info *, ulong, int);
Packit bf408e
static void get_sem_info(struct sem_info *, ulong, int);
Packit bf408e
static void get_msg_info(struct msg_info *, ulong, int);
Packit bf408e
static void add_rss_swap(ulong, int, ulong *, ulong *);
Packit bf408e
static int is_file_hugepages(ulong);
Packit bf408e
static void gather_radix_tree_entries(ulong);
Packit bf408e
static void gather_xarray_entries(ulong);
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * global data
Packit bf408e
 */
Packit bf408e
static struct ipcs_table ipcs_table = { 0 };
Packit bf408e

Packit bf408e
void
Packit bf408e
ipcs_init(void)
Packit bf408e
{
Packit bf408e
	if (ipcs_table.init_flags & IPCS_INIT) {
Packit bf408e
		return;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	ipcs_table.init_flags |= IPCS_INIT;
Packit bf408e

Packit bf408e
	MEMBER_OFFSET_INIT(file_f_op, "file", "f_op");
Packit bf408e
	MEMBER_OFFSET_INIT(file_private_data, "file", "private_data");
Packit bf408e
	MEMBER_OFFSET_INIT(hstate_order, "hstate", "order");
Packit bf408e
	MEMBER_OFFSET_INIT(hugetlbfs_sb_info_hstate, "hugetlbfs_sb_info",
Packit bf408e
			"hstate");
Packit bf408e
	MEMBER_OFFSET_INIT(idr_layers, "idr", "layers");
Packit bf408e
	MEMBER_OFFSET_INIT(idr_layer_layer, "idr_layer", "layer");
Packit bf408e
	MEMBER_OFFSET_INIT(idr_layer_ary, "idr_layer", "ary");
Packit bf408e
	MEMBER_OFFSET_INIT(idr_top, "idr", "top");
Packit bf408e
	MEMBER_OFFSET_INIT(idr_cur, "idr", "cur");
Packit bf408e
	MEMBER_OFFSET_INIT(ipc_id_ary_p, "ipc_id_ary", "p");
Packit bf408e
	MEMBER_OFFSET_INIT(ipc_ids_entries, "ipc_ids", "entries");
Packit bf408e
	MEMBER_OFFSET_INIT(ipc_ids_max_id, "ipc_ids", "max_id");
Packit bf408e
	MEMBER_OFFSET_INIT(ipc_ids_in_use, "ipc_ids", "in_use");
Packit bf408e
	MEMBER_OFFSET_INIT(ipc_ids_ipcs_idr, "ipc_ids", "ipcs_idr");
Packit bf408e
	MEMBER_OFFSET_INIT(ipc_namespace_ids, "ipc_namespace", "ids");
Packit bf408e
	MEMBER_OFFSET_INIT(kern_ipc_perm_key, "kern_ipc_perm", "key");
Packit bf408e
	MEMBER_OFFSET_INIT(kern_ipc_perm_id, "kern_ipc_perm", "id");
Packit bf408e
	MEMBER_OFFSET_INIT(kern_ipc_perm_uid, "kern_ipc_perm", "uid");
Packit bf408e
	MEMBER_OFFSET_INIT(kern_ipc_perm_mode, "kern_ipc_perm", "mode");
Packit bf408e
	MEMBER_OFFSET_INIT(kern_ipc_perm_deleted, "kern_ipc_perm",
Packit bf408e
			"deleted");
Packit bf408e
	MEMBER_OFFSET_INIT(kern_ipc_perm_seq, "kern_ipc_perm", "seq");
Packit bf408e
	MEMBER_OFFSET_INIT(nsproxy_ipc_ns, "nsproxy", "ipc_ns");
Packit bf408e
	MEMBER_OFFSET_INIT(shmem_inode_info_vfs_inode, "shmem_inode_info",
Packit bf408e
			"vfs_inode");
Packit bf408e
	MEMBER_OFFSET_INIT(shmem_inode_info_swapped, "shmem_inode_info",
Packit bf408e
			"swapped");
Packit bf408e
	if (INVALID_MEMBER(shmem_inode_info_swapped))
Packit bf408e
		ANON_MEMBER_OFFSET_INIT(shmem_inode_info_swapped,
Packit bf408e
				"shmem_inode_info", "swapped");
Packit bf408e
	MEMBER_OFFSET_INIT(shm_file_data_file, "shm_file_data", "file");
Packit bf408e
	MEMBER_OFFSET_INIT(shmid_kernel_shm_perm, "shmid_kernel",
Packit bf408e
			"shm_perm");
Packit bf408e
	MEMBER_OFFSET_INIT(shmid_kernel_shm_segsz, "shmid_kernel",
Packit bf408e
			"shm_segsz");
Packit bf408e
	MEMBER_OFFSET_INIT(shmid_kernel_shm_nattch, "shmid_kernel",
Packit bf408e
			"shm_nattch");
Packit bf408e
	MEMBER_OFFSET_INIT(shmid_kernel_shm_file, "shmid_kernel",
Packit bf408e
			"shm_file");
Packit bf408e
	MEMBER_OFFSET_INIT(shmid_kernel_id, "shmid_kernel", "id");
Packit bf408e
	MEMBER_OFFSET_INIT(sem_array_sem_perm, "sem_array", "sem_perm");
Packit bf408e
	MEMBER_OFFSET_INIT(sem_array_sem_id, "sem_array", "sem_id");
Packit bf408e
	MEMBER_OFFSET_INIT(sem_array_sem_nsems, "sem_array", "sem_nsems");
Packit bf408e
	MEMBER_OFFSET_INIT(msg_queue_q_perm, "msg_queue", "q_perm");
Packit bf408e
	MEMBER_OFFSET_INIT(msg_queue_q_id, "msg_queue", "q_id");
Packit bf408e
	MEMBER_OFFSET_INIT(msg_queue_q_cbytes, "msg_queue", "q_cbytes");
Packit bf408e
	MEMBER_OFFSET_INIT(msg_queue_q_qnum, "msg_queue", "q_qnum");
Packit bf408e
	MEMBER_OFFSET_INIT(super_block_s_fs_info, "super_block",
Packit bf408e
			"s_fs_info");
Packit bf408e

Packit bf408e
	/*
Packit bf408e
	 * struct size
Packit bf408e
	 */
Packit bf408e
	STRUCT_SIZE_INIT(ipc_ids, "ipc_ids");
Packit bf408e
	STRUCT_SIZE_INIT(shmid_kernel, "shmid_kernel");
Packit bf408e
	STRUCT_SIZE_INIT(sem_array, "sem_array");
Packit bf408e
	STRUCT_SIZE_INIT(msg_queue, "msg_queue");
Packit bf408e
	STRUCT_SIZE_INIT(hstate, "hstate");
Packit bf408e

Packit bf408e
	if (symbol_exists("hugetlbfs_file_operations"))
Packit bf408e
		ipcs_table.hugetlbfs_f_op_addr =
Packit bf408e
			symbol_value("hugetlbfs_file_operations");
Packit bf408e
	if (symbol_exists("is_file_shm_hugepages")) {
Packit bf408e
		ipcs_table.use_shm_f_op = TRUE;
Packit bf408e
		ipcs_table.shm_f_op_addr =
Packit bf408e
			symbol_value("shm_file_operations");
Packit bf408e
		if (symbol_exists("shm_file_operations_huge")) {
Packit bf408e
			ipcs_table.shm_f_op_huge_addr =
Packit bf408e
				symbol_value("shm_file_operations_huge");
Packit bf408e
		} else {
Packit bf408e
			ipcs_table.shm_f_op_huge_addr = -1;
Packit bf408e
		}
Packit bf408e
	} else {
Packit bf408e
		ipcs_table.use_shm_f_op = FALSE;
Packit bf408e
		ipcs_table.shm_f_op_addr = -1;
Packit bf408e
		ipcs_table.shm_f_op_huge_addr = -1;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(idr_layer_ary) && 
Packit bf408e
	    get_array_length("idr_layer.ary", NULL, 0) > 64)
Packit bf408e
		ipcs_table.idr_bits = 8;
Packit bf408e
	else if (BITS32())
Packit bf408e
		ipcs_table.idr_bits = 5;
Packit bf408e
	else if (BITS64())
Packit bf408e
		ipcs_table.idr_bits = 6;
Packit bf408e
	else
Packit bf408e
		error(FATAL, "machdep->bits is not 32 or 64");
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(idr_idr_rt)) {
Packit bf408e
		if (STREQ(MEMBER_TYPE_NAME("idr", "idr_rt"), "xarray"))
Packit bf408e
			ipcs_table.init_flags |= IDR_XARRAY;
Packit bf408e
		else {
Packit bf408e
			if (MEMBER_EXISTS("radix_tree_root", "rnode"))
Packit bf408e
				ipcs_table.init_flags |= IDR_RADIX;
Packit bf408e
			else if (MEMBER_EXISTS("radix_tree_root", "xa_head"))
Packit bf408e
				ipcs_table.init_flags |= IDR_XARRAY;
Packit bf408e
		}
Packit bf408e
	} else
Packit bf408e
		ipcs_table.init_flags |= IDR_ORIG;
Packit bf408e

Packit bf408e
	ipcs_table.seq_multiplier = 32768;
Packit bf408e
}
Packit bf408e

Packit bf408e
/* 
Packit bf408e
 *  Arguments are passed to the command functions in the global args[argcnt]
Packit bf408e
 *  array.  See getopt(3) for info on dash arguments.  Check out defs.h and
Packit bf408e
 *  other crash commands for usage of the myriad of utility routines available
Packit bf408e
 *  to accomplish what your task.
Packit bf408e
 */
Packit bf408e
void
Packit bf408e
cmd_ipcs(void)
Packit bf408e
{
Packit bf408e
	int specified;
Packit bf408e
	char *specified_value[MAXARGS];
Packit bf408e
	int value_index;
Packit bf408e
	int c;
Packit bf408e
	int shm, sem, msg, verbose;
Packit bf408e
	int i;
Packit bf408e
	ulong value, task;
Packit bf408e
	int found;
Packit bf408e
	struct task_context *tc;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e

Packit bf408e
	value_index = 0;
Packit bf408e
	specified = SPECIFIED_NOTHING;
Packit bf408e
	shm = 0;
Packit bf408e
	sem = 0;
Packit bf408e
	msg = 0;
Packit bf408e
	verbose = 0;
Packit bf408e
	tc = NULL;
Packit bf408e
	
Packit bf408e
	while ((c = getopt(argcnt, args, "smMqn:")) != EOF) {
Packit bf408e
		switch(c) {
Packit bf408e
			case 's':
Packit bf408e
				sem = 1;
Packit bf408e
				break;
Packit bf408e
			case 'm':
Packit bf408e
				shm = 1;
Packit bf408e
				break;
Packit bf408e
			case 'M':
Packit bf408e
				shm = 1;
Packit bf408e
				verbose = 1;
Packit bf408e
				break;
Packit bf408e
			case 'q':
Packit bf408e
				msg = 1;
Packit bf408e
				break;
Packit bf408e
			case 'n':
Packit bf408e
				switch (str_to_context(optarg, &value, &tc)) {
Packit bf408e
		        	case STR_PID:
Packit bf408e
                        	case STR_TASK:
Packit bf408e
                               		break;
Packit bf408e
                        	case STR_INVALID:
Packit bf408e
                               		error(FATAL, "invalid task or pid value: %s\n",
Packit bf408e
                                        	optarg);
Packit bf408e
                               		break;
Packit bf408e
				}
Packit bf408e
				break;
Packit bf408e
			default:
Packit bf408e
				cmd_usage(pc->curcmd, SYNOPSIS);;
Packit bf408e
				return;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e

Packit bf408e
	while (args[optind]) {
Packit bf408e
		if (value_index >= MAXARGS)
Packit bf408e
			error(FATAL, "too many id/member specified\n");
Packit bf408e
		specified |= SPECIFIED_ID | SPECIFIED_ADDR;
Packit bf408e
		specified_value[value_index] = args[optind];
Packit bf408e
		stol(args[optind], FAULT_ON_ERROR, NULL);
Packit bf408e
		optind++;
Packit bf408e
		value_index++;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (THIS_KERNEL_VERSION < LINUX(2,6,0))
Packit bf408e
		command_not_supported();
Packit bf408e

Packit bf408e
	ipcs_init();
Packit bf408e

Packit bf408e
	if (!shm && !sem && !msg)
Packit bf408e
		shm = sem = msg = 1;
Packit bf408e

Packit bf408e
	task = tc ? tc->task : pid_to_task(0);
Packit bf408e

Packit bf408e
	if (!value_index) {
Packit bf408e
		if (shm)
Packit bf408e
			dump_shared_memory(specified, 0, verbose, task);
Packit bf408e
		if (sem)
Packit bf408e
			dump_semaphore_arrays(specified, 0, 0, task);
Packit bf408e
		if (msg)
Packit bf408e
			dump_message_queues(specified, 0, 0, task);
Packit bf408e
	} else {
Packit bf408e
		open_tmpfile();
Packit bf408e
		i = 0;
Packit bf408e
		while (i < value_index) {
Packit bf408e
			found = 0;
Packit bf408e
			value = stol(specified_value[i], FAULT_ON_ERROR, NULL);
Packit bf408e
			if (shm)
Packit bf408e
				found += dump_shared_memory(specified,
Packit bf408e
					value, verbose, task);
Packit bf408e
			if (sem)
Packit bf408e
				found += dump_semaphore_arrays(specified,
Packit bf408e
					value, 0, task);
Packit bf408e
			if (msg)
Packit bf408e
				found += dump_message_queues(specified,
Packit bf408e
					value, 0, task);
Packit bf408e

Packit bf408e
			if (!found)
Packit bf408e
				fprintf(pc->saved_fp, "invalid id or address: %s\n\n",
Packit bf408e
					specified_value[i]);
Packit bf408e

Packit bf408e
			i++;
Packit bf408e
		}
Packit bf408e
		fflush(fp);
Packit bf408e
		rewind(fp);
Packit bf408e

Packit bf408e
		while (fgets(buf, BUFSIZE, fp))
Packit bf408e
			fprintf(pc->saved_fp, "%s", buf);
Packit bf408e

Packit bf408e
		close_tmpfile();
Packit bf408e
	}
Packit bf408e
}
Packit bf408e

Packit bf408e
static int
Packit bf408e
dump_shared_memory(int specified, ulong specified_value, int verbose, ulong task)
Packit bf408e
{
Packit bf408e
	ulong nsproxy_p, ipc_ns_p;
Packit bf408e
	ulong ipc_ids_p;
Packit bf408e
	int (*ipc_search)(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
Packit bf408e
	int (*dump_shm)(ulong, int, ulong, int, int);
Packit bf408e
	char buf0[BUFSIZE];
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char buf3[BUFSIZE];
Packit bf408e
	char buf4[BUFSIZE];
Packit bf408e
	char buf5[BUFSIZE];
Packit bf408e
	char buf6[BUFSIZE];
Packit bf408e
	char buf7[BUFSIZE];
Packit bf408e

Packit bf408e
	if (!verbose && specified == SPECIFIED_NOTHING) {
Packit bf408e
		fprintf(fp, "%s %s %s %s %s %s %s %s\n",
Packit bf408e
			mkstring(buf0, VADDR_PRLEN<=12?12:VADDR_PRLEN,
Packit bf408e
				LJUST, "SHMID_KERNEL"),
Packit bf408e
			mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
			mkstring(buf2, 10, LJUST, "SHMID"),
Packit bf408e
			mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
			mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
			mkstring(buf5, 10, LJUST, "BYTES"),
Packit bf408e
			mkstring(buf6, 6, LJUST, "NATTCH"),
Packit bf408e
			mkstring(buf7, 6, LJUST, "STATUS"));
Packit bf408e
	}
Packit bf408e

Packit bf408e
	dump_shm = dump_shm_info;
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(kern_ipc_perm_id)) {
Packit bf408e
		ipc_search = ipc_search_idr;
Packit bf408e
	} else {
Packit bf408e
		ipc_search = ipc_search_array;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (symbol_exists("shm_ids")) {
Packit bf408e
		ipc_ids_p = symbol_value("shm_ids");
Packit bf408e
	} else {
Packit bf408e
		readmem(task + OFFSET(task_struct_nsproxy), KVADDR,
Packit bf408e
			&nsproxy_p, sizeof(ulong), "task_struct.nsproxy",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
		if (!readmem(nsproxy_p + OFFSET(nsproxy_ipc_ns), KVADDR,
Packit bf408e
			&ipc_ns_p, sizeof(ulong), "nsproxy.ipc_ns",
Packit bf408e
			RETURN_ON_ERROR|QUIET))
Packit bf408e
			error(FATAL,
Packit bf408e
				"cannot determine ipc_namespace location!\n");
Packit bf408e

Packit bf408e
		if (MEMBER_SIZE("ipc_namespace","ids") == sizeof(ulong) * 3)
Packit bf408e
			readmem(ipc_ns_p + OFFSET(ipc_namespace_ids) +
Packit bf408e
				sizeof(ulong) * 2, KVADDR, &ipc_ids_p,
Packit bf408e
				sizeof(ulong), "ipc_namespace.ids[2]",
Packit bf408e
				FAULT_ON_ERROR);
Packit bf408e
		else
Packit bf408e
			ipc_ids_p = ipc_ns_p + OFFSET(ipc_namespace_ids) +
Packit bf408e
				2 * SIZE(ipc_ids);
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (ipc_search(ipc_ids_p, specified, specified_value, dump_shm, verbose)) {
Packit bf408e
		return 1;
Packit bf408e
	} else {
Packit bf408e
		if (verbose && specified == SPECIFIED_NOTHING) {
Packit bf408e
			fprintf(fp, "%s %s %s %s %s %s %s %s\n",
Packit bf408e
				mkstring(buf0, VADDR_PRLEN<=12?12:VADDR_PRLEN,
Packit bf408e
					LJUST, "SHMID_KERNEL"),
Packit bf408e
				mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
				mkstring(buf2, 10, LJUST, "SHMID"),
Packit bf408e
				mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
				mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
				mkstring(buf5, 10, LJUST, "BYTES"),
Packit bf408e
				mkstring(buf6, 6, LJUST, "NATTCH"),
Packit bf408e
				mkstring(buf7, 6, LJUST, "STATUS"));
Packit bf408e
			fprintf(fp, "(none allocated)\n\n");
Packit bf408e
		}
Packit bf408e
		return 0;
Packit bf408e
	}
Packit bf408e
}
Packit bf408e

Packit bf408e
static int
Packit bf408e
dump_semaphore_arrays(int specified, ulong specified_value, int verbose, ulong task)
Packit bf408e
{
Packit bf408e
	ulong nsproxy_p, ipc_ns_p;
Packit bf408e
	ulong ipc_ids_p;
Packit bf408e
	int (*ipc_search)(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
Packit bf408e
	int (*dump_sem)(ulong, int, ulong, int, int);
Packit bf408e
	char buf0[BUFSIZE];
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char buf3[BUFSIZE];
Packit bf408e
	char buf4[BUFSIZE];
Packit bf408e
	char buf5[BUFSIZE];
Packit bf408e

Packit bf408e
	if (specified == SPECIFIED_NOTHING) {
Packit bf408e
		fprintf(fp, "%s %s %s %s %s %s\n",
Packit bf408e
			mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
Packit bf408e
				LJUST, "SEM_ARRAY"),
Packit bf408e
			mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
			mkstring(buf2, 10, LJUST, "SEMID"),
Packit bf408e
			mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
			mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
			mkstring(buf5, 10, LJUST, "NSEMS"));
Packit bf408e
	}
Packit bf408e

Packit bf408e
	dump_sem = dump_sem_info;
Packit bf408e
	
Packit bf408e
	if (VALID_MEMBER(kern_ipc_perm_id)) {
Packit bf408e
		ipc_search = ipc_search_idr;
Packit bf408e
	} else {
Packit bf408e
		ipc_search = ipc_search_array;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (symbol_exists("sem_ids")) {
Packit bf408e
		ipc_ids_p = symbol_value("sem_ids");
Packit bf408e
	} else {
Packit bf408e
		readmem(task + OFFSET(task_struct_nsproxy), KVADDR,
Packit bf408e
			&nsproxy_p, sizeof(ulong), "task_struct.nsproxy",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
		
Packit bf408e
		if (!readmem(nsproxy_p + OFFSET(nsproxy_ipc_ns), KVADDR,
Packit bf408e
			&ipc_ns_p, sizeof(ulong), "nsproxy.ipc_ns",
Packit bf408e
			FAULT_ON_ERROR|QUIET))
Packit bf408e
			error(FATAL,
Packit bf408e
				"cannot determine ipc_namespace location!\n");
Packit bf408e

Packit bf408e
		if (MEMBER_SIZE("ipc_namespace","ids") == sizeof(ulong) * 3)
Packit bf408e
			readmem(ipc_ns_p + OFFSET(ipc_namespace_ids),
Packit bf408e
				KVADDR,	&ipc_ids_p, sizeof(ulong),
Packit bf408e
				"ipc_namespace.ids[2]",	FAULT_ON_ERROR);
Packit bf408e
		else
Packit bf408e
			ipc_ids_p = ipc_ns_p + OFFSET(ipc_namespace_ids);
Packit bf408e
	}
Packit bf408e

Packit bf408e
	return ipc_search(ipc_ids_p, specified, specified_value, dump_sem, verbose);
Packit bf408e
}
Packit bf408e

Packit bf408e
static int
Packit bf408e
dump_message_queues(int specified, ulong specified_value, int verbose, ulong task)
Packit bf408e
{
Packit bf408e
	ulong nsproxy_p, ipc_ns_p;
Packit bf408e
	ulong ipc_ids_p;
Packit bf408e
	int (*ipc_search)(ulong, int, ulong, int (*)(ulong, int, ulong, int, int), int);
Packit bf408e
	int (*dump_msg)(ulong, int, ulong, int, int);
Packit bf408e
	char buf0[BUFSIZE];
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char buf3[BUFSIZE];
Packit bf408e
	char buf4[BUFSIZE];
Packit bf408e
	char buf5[BUFSIZE];
Packit bf408e
	char buf6[BUFSIZE];
Packit bf408e

Packit bf408e
	if (specified == SPECIFIED_NOTHING) {
Packit bf408e
		fprintf(fp, "%s %s %s %s %s %s %s\n",
Packit bf408e
			mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
Packit bf408e
				LJUST, "MSG_QUEUE"),
Packit bf408e
			mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
			mkstring(buf2, 10, LJUST, "MSQID"),
Packit bf408e
			mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
			mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
			mkstring(buf5, 12, LJUST, "USED-BYTES"),
Packit bf408e
			mkstring(buf6, 12, LJUST, "MESSAGES"));
Packit bf408e
	}
Packit bf408e

Packit bf408e
	dump_msg = dump_msg_info;
Packit bf408e
	
Packit bf408e
	if (VALID_MEMBER(kern_ipc_perm_id)) {
Packit bf408e
		ipc_search = ipc_search_idr;
Packit bf408e
	} else {
Packit bf408e
		ipc_search = ipc_search_array;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (symbol_exists("msg_ids")) {
Packit bf408e
		ipc_ids_p = symbol_value("msg_ids");
Packit bf408e
	} else {
Packit bf408e
		readmem(task + OFFSET(task_struct_nsproxy), KVADDR,
Packit bf408e
			&nsproxy_p, sizeof(ulong), "task_struct.nsproxy",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
		if (!readmem(nsproxy_p + OFFSET(nsproxy_ipc_ns), KVADDR,
Packit bf408e
			&ipc_ns_p, sizeof(ulong), "nsproxy.ipc_ns",
Packit bf408e
			FAULT_ON_ERROR|QUIET))
Packit bf408e
			error(FATAL,
Packit bf408e
				"cannot determine ipc_namespace location!\n");
Packit bf408e

Packit bf408e
		if (MEMBER_SIZE("ipc_namespace","ids") == sizeof(ulong) * 3)
Packit bf408e
			readmem(ipc_ns_p + OFFSET(ipc_namespace_ids) +
Packit bf408e
				sizeof(ulong), KVADDR, &ipc_ids_p,
Packit bf408e
				sizeof(ulong), "ipc_namespace.ids[2]",
Packit bf408e
				FAULT_ON_ERROR);
Packit bf408e
		else
Packit bf408e
			ipc_ids_p = ipc_ns_p + OFFSET(ipc_namespace_ids) +
Packit bf408e
				SIZE(ipc_ids);
Packit bf408e
	}
Packit bf408e

Packit bf408e
	return ipc_search(ipc_ids_p, specified, specified_value, dump_msg, verbose);
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * if shared memory information is stored in an array, use this function.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
ipc_search_array(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(ulong, int, ulong, int, int), int verbose)
Packit bf408e
{
Packit bf408e
	ulong entries_p;
Packit bf408e
	int max_id, i;
Packit bf408e
	ulong *array;
Packit bf408e
	int found = 0;
Packit bf408e
	int allocated = 0;
Packit bf408e

Packit bf408e
	readmem(ipc_ids_p + OFFSET(ipc_ids_entries), KVADDR, &entries_p,
Packit bf408e
		sizeof(ulong), "ipc_ids.entries", FAULT_ON_ERROR);
Packit bf408e
	readmem(ipc_ids_p + OFFSET(ipc_ids_max_id), KVADDR, &max_id,
Packit bf408e
		sizeof(int), "ipc_ids.max_id", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	if (max_id < 0) {
Packit bf408e
		if (specified == SPECIFIED_NOTHING && !verbose)
Packit bf408e
			fprintf(fp, "(none allocated)\n\n");
Packit bf408e
		return 0;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	array = (ulong *)GETBUF(sizeof(ulong *) * (max_id + 1));
Packit bf408e
	if (VALID_MEMBER(ipc_id_ary_p))
Packit bf408e
		readmem(entries_p + OFFSET(ipc_id_ary_p), KVADDR, array,
Packit bf408e
			sizeof(ulong *) * (max_id + 1), "ipc_id_ary.p",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
	else
Packit bf408e
		readmem(entries_p, KVADDR, array, sizeof(ulong *)*(max_id+1),
Packit bf408e
				"ipc_id array", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	for (i=0; i<=max_id; i++) {
Packit bf408e
		if (array[i] == 0)
Packit bf408e
			continue;
Packit bf408e
		if (fn(array[i], specified, specified_value, i, verbose)) {
Packit bf408e
			allocated++;
Packit bf408e
			found = 1;
Packit bf408e
			if (specified != SPECIFIED_NOTHING)
Packit bf408e
				break;
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (specified == SPECIFIED_NOTHING && !verbose) {
Packit bf408e
		if (!allocated)
Packit bf408e
			fprintf(fp, "(none allocated)\n");
Packit bf408e
		fprintf(fp, "\n");
Packit bf408e
	}
Packit bf408e

Packit bf408e
	FREEBUF(array);
Packit bf408e

Packit bf408e
	if (found)
Packit bf408e
		return 1;
Packit bf408e
	else
Packit bf408e
		return 0;
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * if shared memory information is stored by using idr, use this function to
Packit bf408e
 * get data.
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
ipc_search_idr(ulong ipc_ids_p, int specified, ulong specified_value, int (*fn)(ulong, int, ulong, int, int), int verbose)
Packit bf408e
{
Packit bf408e
	int i, in_use;
Packit bf408e
	ulong ipcs_idr_p;
Packit bf408e
	ulong ipc;
Packit bf408e
	int next_id, total;
Packit bf408e
	int found = 0;
Packit bf408e

Packit bf408e
	readmem(ipc_ids_p + OFFSET(ipc_ids_in_use), KVADDR, &in_use, 
Packit bf408e
		sizeof(int), "ipc_ids.in_use", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	ipcs_idr_p = ipc_ids_p + OFFSET(ipc_ids_ipcs_idr);
Packit bf408e

Packit bf408e
	if (!in_use) {
Packit bf408e
		if (specified == SPECIFIED_NOTHING && !verbose)
Packit bf408e
			fprintf(fp, "(none allocated)\n\n");
Packit bf408e
		return 0;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(idr_idr_rt)) {
Packit bf408e
		switch (ipcs_table.init_flags & (IDR_RADIX|IDR_XARRAY))
Packit bf408e
		{
Packit bf408e
		case IDR_RADIX: 
Packit bf408e
			gather_radix_tree_entries(ipcs_idr_p);
Packit bf408e
			break;
Packit bf408e
		case IDR_XARRAY:
Packit bf408e
			gather_xarray_entries(ipcs_idr_p);
Packit bf408e
			break;
Packit bf408e
		}
Packit bf408e

Packit bf408e
		for (i = 0; i < ipcs_table.cnt; i++) {
Packit bf408e
			ipc = (ulong)ipcs_table.lp[i].value;
Packit bf408e
			if (fn(ipc, specified, specified_value, UNUSED, verbose)) {
Packit bf408e
				found = 1;
Packit bf408e
				if (specified != SPECIFIED_NOTHING)
Packit bf408e
					break;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e

Packit bf408e
		if (ipcs_table.lp)
Packit bf408e
			FREEBUF(ipcs_table.lp);
Packit bf408e
	} else {
Packit bf408e
		for (total = 0, next_id = 0; total < in_use; next_id++) {
Packit bf408e
			ipc = idr_find(ipcs_idr_p, next_id);
Packit bf408e
			if (ipc == 0)
Packit bf408e
				continue;
Packit bf408e
			
Packit bf408e
			total++;
Packit bf408e
			if (fn(ipc, specified, specified_value, next_id, verbose)) {
Packit bf408e
				found = 1;
Packit bf408e
				if (specified != SPECIFIED_NOTHING)
Packit bf408e
					break;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e
	
Packit bf408e
	if (!verbose && specified == SPECIFIED_NOTHING)
Packit bf408e
		fprintf(fp, "\n");
Packit bf408e

Packit bf408e
	if (found || specified == SPECIFIED_NOTHING)
Packit bf408e
		return 1;
Packit bf408e
	else
Packit bf408e
		return 0;
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * search every idr_layer
Packit bf408e
 */
Packit bf408e
ulong
Packit bf408e
idr_find(ulong idp, int id)
Packit bf408e
{
Packit bf408e
	ulong idr_layer_p;
Packit bf408e
	int layer;
Packit bf408e
	int idr_layers;
Packit bf408e
	int n;
Packit bf408e
	int index;
Packit bf408e

Packit bf408e
	readmem(idp + OFFSET(idr_top), KVADDR, &idr_layer_p,
Packit bf408e
		sizeof(ulong), "idr.top", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	if (!idr_layer_p)
Packit bf408e
		return 0;
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(idr_layer_layer)) {
Packit bf408e
		readmem(idr_layer_p + OFFSET(idr_layer_layer), KVADDR,
Packit bf408e
			&layer,	sizeof(int), "idr_layer.layer",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
		n = (layer + 1) * ipcs_table.idr_bits;
Packit bf408e
	} else {
Packit bf408e
		readmem(idp + OFFSET(idr_layers), KVADDR, &idr_layers,
Packit bf408e
			sizeof(int), "idr.layers", FAULT_ON_ERROR);
Packit bf408e
		n = idr_layers * ipcs_table.idr_bits;
Packit bf408e
	}
Packit bf408e
	id &= MAX_ID_MASK;
Packit bf408e

Packit bf408e
	if (id >= (1 << n))
Packit bf408e
		return 0;
Packit bf408e

Packit bf408e
	while (n > 0 && idr_layer_p) {
Packit bf408e
		n -= ipcs_table.idr_bits;
Packit bf408e
		index = (id >> n) & ((1 << ipcs_table.idr_bits) - 1);
Packit bf408e
		readmem(idr_layer_p + OFFSET(idr_layer_ary) +
Packit bf408e
			sizeof(ulong) * index, KVADDR, &idr_layer_p,
Packit bf408e
			sizeof(ulong), "idr_layer.ary", FAULT_ON_ERROR);
Packit bf408e
	}
Packit bf408e
	
Packit bf408e
	return idr_layer_p;
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * only specified is not SPECIFIED_NOTHIND, and the specified_value is found,
Packit bf408e
 * then return 1
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
dump_shm_info(ulong shp, int specified, ulong specified_value, int id, int verbose)
Packit bf408e
{
Packit bf408e
	struct shm_info shm_info;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	char buf0[BUFSIZE];
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char buf3[BUFSIZE];
Packit bf408e
	char buf4[BUFSIZE];
Packit bf408e
	char buf5[BUFSIZE];
Packit bf408e
	char buf6[BUFSIZE];
Packit bf408e
	char buf7[BUFSIZE];
Packit bf408e

Packit bf408e
	get_shm_info(&shm_info, shp, id);
Packit bf408e
	
Packit bf408e
	if (shm_info.deleted)
Packit bf408e
		return 0;
Packit bf408e

Packit bf408e
	if (((specified & SPECIFIED_ID) && shm_info.shmid == specified_value) ||
Packit bf408e
		((specified & SPECIFIED_ADDR) && shm_info.shmid_kernel ==
Packit bf408e
		 specified_value) || specified == SPECIFIED_NOTHING) {
Packit bf408e
		if (verbose || specified != SPECIFIED_NOTHING) {
Packit bf408e
			fprintf(fp, "%s %s %s %s %s %s %s %s\n",
Packit bf408e
				mkstring(buf0, VADDR_PRLEN<=12?12:VADDR_PRLEN,
Packit bf408e
					LJUST, "SHMID_KERNEL"),
Packit bf408e
				mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
				mkstring(buf2, 10, LJUST, "SHMID"),
Packit bf408e
				mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
				mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
				mkstring(buf5, 10, LJUST, "BYTES"),
Packit bf408e
				mkstring(buf6, 6, LJUST, "NATTCH"),
Packit bf408e
				mkstring(buf7, 6, LJUST, "STATUS"));
Packit bf408e
		}
Packit bf408e

Packit bf408e
		fprintf(fp, "%s %08x %-10d %-5d %-5o %-10ld %-6ld %-s %-s\n",
Packit bf408e
			mkstring(buf, VADDR_PRLEN <= 12 ? 12 : VADDR_PRLEN,
Packit bf408e
				LJUST|LONG_HEX,	(char *)shm_info.shmid_kernel),
Packit bf408e
			shm_info.key,
Packit bf408e
			shm_info.shmid,
Packit bf408e
			shm_info.uid,
Packit bf408e
			shm_info.perms & 0777,
Packit bf408e
			shm_info.bytes,
Packit bf408e
			shm_info.nattch,
Packit bf408e
			shm_info.perms & SHM_DEST ? "dest" : "",
Packit bf408e
			shm_info.perms & SHM_LOCKED ? "locked" : "");
Packit bf408e

Packit bf408e
		if (verbose) {
Packit bf408e
			fprintf(fp, "PAGES ALLOCATED/RESIDENT/SWAPPED: %ld/%ld/%ld\n",
Packit bf408e
				(shm_info.bytes+PAGESIZE()-1) >> PAGESHIFT(),
Packit bf408e
				shm_info.rss, shm_info.swap);
Packit bf408e
			fprintf(fp, "INODE: %lx\n", shm_info.shm_inode);
Packit bf408e
		}
Packit bf408e

Packit bf408e
		if (verbose || specified != SPECIFIED_NOTHING)
Packit bf408e
			fprintf(fp, "\n");
Packit bf408e

Packit bf408e
		return 1;
Packit bf408e
	} else
Packit bf408e
		return 0;
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * only specified is not SPECIFIED_NOTHIND, and the specified_value is found,
Packit bf408e
 * then return 1
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
dump_sem_info(ulong shp, int specified, ulong specified_value, int id, int verbose)
Packit bf408e
{
Packit bf408e
	struct sem_info sem_info;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	char buf0[BUFSIZE];
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char buf3[BUFSIZE];
Packit bf408e
	char buf4[BUFSIZE];
Packit bf408e
	char buf5[BUFSIZE];
Packit bf408e

Packit bf408e
	get_sem_info(&sem_info, shp, id);
Packit bf408e

Packit bf408e
	if (sem_info.deleted)
Packit bf408e
		return 0;
Packit bf408e

Packit bf408e
	if (((specified & SPECIFIED_ID) && sem_info.semid == specified_value) ||
Packit bf408e
		((specified & SPECIFIED_ADDR) && sem_info.sem_array ==
Packit bf408e
		 specified_value) || specified == SPECIFIED_NOTHING) {
Packit bf408e
		if (specified != SPECIFIED_NOTHING) {
Packit bf408e
			fprintf(fp, "%s %s %s %s %s %s\n",
Packit bf408e
				mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
Packit bf408e
					LJUST, "SEM_ARRAY"),
Packit bf408e
				mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
				mkstring(buf2, 10, LJUST, "SEMID"),
Packit bf408e
				mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
				mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
				mkstring(buf5, 10, LJUST, "NSEMS"));
Packit bf408e
		}
Packit bf408e

Packit bf408e
		fprintf(fp, "%s %08x %-10d %-5d %-5o %-10ld\n",
Packit bf408e
			mkstring(buf, VADDR_PRLEN <= 10 ? 10 : VADDR_PRLEN,
Packit bf408e
				LJUST|LONG_HEX,	(char *)sem_info.sem_array),
Packit bf408e
			sem_info.key,
Packit bf408e
			sem_info.semid,
Packit bf408e
			sem_info.uid,
Packit bf408e
			sem_info.perms & 0777,
Packit bf408e
			sem_info.nsems);
Packit bf408e

Packit bf408e
		if (specified != SPECIFIED_NOTHING)
Packit bf408e
			fprintf(fp, "\n");
Packit bf408e

Packit bf408e
		return 1;
Packit bf408e
	} else
Packit bf408e
		return 0;
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * only specified is not SPECIFIED_NOTHIND, and the specified_value is found,
Packit bf408e
 * then return 1
Packit bf408e
 */
Packit bf408e
static int
Packit bf408e
dump_msg_info(ulong shp, int specified, ulong specified_value, int id, int verbose)
Packit bf408e
{
Packit bf408e
	struct msg_info msg_info;
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	char buf0[BUFSIZE];
Packit bf408e
	char buf1[BUFSIZE];
Packit bf408e
	char buf2[BUFSIZE];
Packit bf408e
	char buf3[BUFSIZE];
Packit bf408e
	char buf4[BUFSIZE];
Packit bf408e
	char buf5[BUFSIZE];
Packit bf408e
	char buf6[BUFSIZE];
Packit bf408e

Packit bf408e
	get_msg_info(&msg_info, shp, id);
Packit bf408e

Packit bf408e
	if (msg_info.deleted)
Packit bf408e
		return 0;
Packit bf408e

Packit bf408e
	if (((specified & SPECIFIED_ID) && msg_info.msgid == specified_value) ||
Packit bf408e
		((specified & SPECIFIED_ADDR) && msg_info.msg_queue ==
Packit bf408e
		 specified_value) || specified == SPECIFIED_NOTHING) {
Packit bf408e
		if (specified != SPECIFIED_NOTHING) {
Packit bf408e
			fprintf(fp, "%s %s %s %s %s %s %s\n",
Packit bf408e
				mkstring(buf0, VADDR_PRLEN<=10?10:VADDR_PRLEN,
Packit bf408e
					LJUST, "MSG_QUEUE"),
Packit bf408e
				mkstring(buf1, 8, LJUST, "KEY"),
Packit bf408e
				mkstring(buf2, 10, LJUST, "MSQID"),
Packit bf408e
				mkstring(buf3, 5, LJUST, "UID"),
Packit bf408e
				mkstring(buf4, 5, LJUST, "PERMS"),
Packit bf408e
				mkstring(buf5, 12, LJUST, "USED-BYTES"),
Packit bf408e
				mkstring(buf6, 12, LJUST, "MESSAGES"));
Packit bf408e
		}
Packit bf408e

Packit bf408e
		fprintf(fp, "%s %08x %-10d %-5d %-5o %-12ld %-12ld\n",
Packit bf408e
			mkstring(buf, VADDR_PRLEN <= 10 ? 10 : VADDR_PRLEN,
Packit bf408e
				LJUST|LONG_HEX,	(char *)msg_info.msg_queue),
Packit bf408e
			msg_info.key,
Packit bf408e
			msg_info.msgid,
Packit bf408e
			msg_info.uid,
Packit bf408e
			msg_info.perms & 0777,
Packit bf408e
			msg_info.bytes,
Packit bf408e
			msg_info.messages);
Packit bf408e

Packit bf408e
		if (specified != SPECIFIED_NOTHING)
Packit bf408e
			fprintf(fp, "\n");
Packit bf408e

Packit bf408e
		return 1;
Packit bf408e
	} else
Packit bf408e
		return 0;
Packit bf408e
}
Packit bf408e

Packit bf408e
static void
Packit bf408e
get_shm_info(struct shm_info *shm_info, ulong shp, int id)
Packit bf408e
{
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	ulong filep, dentryp, inodep;
Packit bf408e

Packit bf408e
	shm_info->shmid_kernel = shp - OFFSET(shmid_kernel_shm_perm);
Packit bf408e

Packit bf408e
	/*
Packit bf408e
	 * cache shmid_kernel
Packit bf408e
	 */
Packit bf408e
	readmem(shm_info->shmid_kernel, KVADDR, buf, SIZE(shmid_kernel),
Packit bf408e
		"shmid_kernel", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	shm_info->key = INT(buf + OFFSET(shmid_kernel_shm_perm) +
Packit bf408e
			OFFSET(kern_ipc_perm_key));
Packit bf408e
	if (VALID_MEMBER(shmid_kernel_id))
Packit bf408e
		shm_info->shmid = INT(buf + OFFSET(shmid_kernel_id));
Packit bf408e
	else
Packit bf408e
		shm_info->shmid = INT(buf +
Packit bf408e
				OFFSET(shmid_kernel_shm_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_id));
Packit bf408e

Packit bf408e
	shm_info->uid = UINT(buf + OFFSET(shmid_kernel_shm_perm) +
Packit bf408e
			OFFSET(kern_ipc_perm_uid));
Packit bf408e

Packit bf408e
	if (BITS32())
Packit bf408e
		shm_info->perms = USHORT(buf +
Packit bf408e
				OFFSET(shmid_kernel_shm_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_mode));
Packit bf408e
	else
Packit bf408e
		shm_info->perms = UINT(buf +
Packit bf408e
				OFFSET(shmid_kernel_shm_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_mode));
Packit bf408e

Packit bf408e
	shm_info->bytes = ULONG(buf + OFFSET(shmid_kernel_shm_segsz));
Packit bf408e

Packit bf408e
	shm_info->nattch = ULONG(buf + OFFSET(shmid_kernel_shm_nattch));
Packit bf408e

Packit bf408e
	filep = ULONG(buf + OFFSET(shmid_kernel_shm_file));
Packit bf408e
	readmem(filep + OFFSET(file_f_dentry), KVADDR, &dentryp, sizeof(ulong),
Packit bf408e
		"file.f_dentry", FAULT_ON_ERROR);
Packit bf408e
	readmem(dentryp + OFFSET(dentry_d_inode), KVADDR, &inodep,
Packit bf408e
		sizeof(ulong), "dentry.d_inode", FAULT_ON_ERROR);
Packit bf408e
	/* 
Packit bf408e
	 * shm_inode here is the vfs_inode of struct shmem_inode_info
Packit bf408e
	 */
Packit bf408e
	shm_info->shm_inode = inodep;
Packit bf408e

Packit bf408e
	shm_info->rss = 0;
Packit bf408e
	shm_info->swap = 0;
Packit bf408e

Packit bf408e
	add_rss_swap(inodep, is_file_hugepages(filep), &shm_info->rss,
Packit bf408e
                 &shm_info->swap);
Packit bf408e

Packit bf408e
	shm_info->deleted = UCHAR(buf + OFFSET(shmid_kernel_shm_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_deleted));
Packit bf408e
}
Packit bf408e

Packit bf408e
static void
Packit bf408e
get_sem_info(struct sem_info *sem_info, ulong shp, int id)
Packit bf408e
{
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e
	
Packit bf408e
	sem_info->sem_array = shp - OFFSET(sem_array_sem_perm);
Packit bf408e

Packit bf408e
	/*
Packit bf408e
	 * cache sem_array
Packit bf408e
	 */
Packit bf408e
	readmem(sem_info->sem_array, KVADDR, buf, SIZE(sem_array),
Packit bf408e
		"sem_array", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	sem_info->key = INT(buf + OFFSET(sem_array_sem_perm) +
Packit bf408e
			OFFSET(kern_ipc_perm_key));
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(sem_array_sem_id))
Packit bf408e
		sem_info->semid = INT(buf + OFFSET(sem_array_sem_id));
Packit bf408e
	else if (VALID_MEMBER(kern_ipc_perm_id))
Packit bf408e
		sem_info->semid = INT(buf + OFFSET(sem_array_sem_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_id));
Packit bf408e
	else {
Packit bf408e
		ulong seq;
Packit bf408e
		seq = ULONG(buf + OFFSET(sem_array_sem_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_seq));
Packit bf408e
		sem_info->semid = ipcs_table.seq_multiplier * seq + id;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	sem_info->uid = UINT(buf + OFFSET(sem_array_sem_perm) +
Packit bf408e
			OFFSET(kern_ipc_perm_uid));
Packit bf408e

Packit bf408e
	if (BITS32())
Packit bf408e
		sem_info->perms = USHORT(buf +
Packit bf408e
				OFFSET(sem_array_sem_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_mode));
Packit bf408e
	else
Packit bf408e
		sem_info->perms = UINT(buf + OFFSET(sem_array_sem_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_mode));
Packit bf408e

Packit bf408e
	sem_info->nsems = ULONG(buf + OFFSET(sem_array_sem_nsems));
Packit bf408e

Packit bf408e
	sem_info->deleted = UCHAR(buf + OFFSET(sem_array_sem_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_deleted));
Packit bf408e
}
Packit bf408e

Packit bf408e
static void
Packit bf408e
get_msg_info(struct msg_info *msg_info, ulong shp, int id)
Packit bf408e
{
Packit bf408e
	char buf[BUFSIZE];
Packit bf408e

Packit bf408e
	msg_info->msg_queue = shp - OFFSET(msg_queue_q_perm);
Packit bf408e

Packit bf408e
	/*
Packit bf408e
	 * cache msg_queue
Packit bf408e
	 */
Packit bf408e
	readmem(msg_info->msg_queue, KVADDR, buf, SIZE(msg_queue),
Packit bf408e
		"msg_queue", FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	msg_info->key = INT(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
			OFFSET(kern_ipc_perm_key));
Packit bf408e

Packit bf408e
	if (VALID_MEMBER(msg_queue_q_id))
Packit bf408e
		msg_info->msgid = INT(buf + OFFSET(msg_queue_q_id));
Packit bf408e
	else if (VALID_MEMBER(kern_ipc_perm_id))
Packit bf408e
		msg_info->msgid = INT(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_id));
Packit bf408e
	else {
Packit bf408e
		ulong seq;
Packit bf408e
		seq = ULONG(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_seq));
Packit bf408e
		msg_info->msgid = ipcs_table.seq_multiplier * seq + id;
Packit bf408e
	}
Packit bf408e

Packit bf408e
	msg_info->uid = UINT(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
			OFFSET(kern_ipc_perm_uid));
Packit bf408e

Packit bf408e
	if (BITS32())
Packit bf408e
		msg_info->perms = USHORT(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_mode));
Packit bf408e
	else
Packit bf408e
		msg_info->perms = UINT(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_mode));
Packit bf408e

Packit bf408e
	msg_info->bytes = ULONG(buf + OFFSET(msg_queue_q_cbytes));
Packit bf408e

Packit bf408e
	msg_info->messages = ULONG(buf + OFFSET(msg_queue_q_qnum));
Packit bf408e
	
Packit bf408e
	msg_info->deleted = UCHAR(buf + OFFSET(msg_queue_q_perm) +
Packit bf408e
				OFFSET(kern_ipc_perm_deleted));
Packit bf408e
}
Packit bf408e

Packit bf408e
/*
Packit bf408e
 * get rss & swap related to every shared memory, and get the total number of rss
Packit bf408e
 * & swap
Packit bf408e
 */
Packit bf408e
static void
Packit bf408e
add_rss_swap(ulong inode_p, int hugepage, ulong *rss, ulong *swap)
Packit bf408e
{
Packit bf408e
	unsigned long mapping_p, nr_pages;
Packit bf408e

Packit bf408e
	readmem(inode_p + OFFSET(inode_i_mapping), KVADDR, &mapping_p,
Packit bf408e
		sizeof(ulong), "inode.i_mapping", FAULT_ON_ERROR);
Packit bf408e
	readmem(mapping_p + OFFSET(address_space_nrpages), KVADDR, &nr_pages,
Packit bf408e
		sizeof(ulong), "address_space.nrpages",
Packit bf408e
		FAULT_ON_ERROR);
Packit bf408e

Packit bf408e
	if (hugepage) {
Packit bf408e
		unsigned long pages_per_hugepage;
Packit bf408e
		if (VALID_SIZE(hstate)) {
Packit bf408e
			unsigned long i_sb_p, hsb_p, hstate_p;
Packit bf408e
			unsigned int order;
Packit bf408e

Packit bf408e
			readmem(inode_p + OFFSET(inode_i_sb), KVADDR, &i_sb_p,
Packit bf408e
				sizeof(ulong), "inode.i_sb",
Packit bf408e
				FAULT_ON_ERROR);
Packit bf408e
			readmem(i_sb_p + OFFSET(super_block_s_fs_info),
Packit bf408e
				KVADDR,	&hsb_p, sizeof(ulong),
Packit bf408e
				"super_block.s_fs_info", FAULT_ON_ERROR);
Packit bf408e
			readmem(hsb_p + OFFSET(hugetlbfs_sb_info_hstate),
Packit bf408e
				KVADDR,	&hstate_p, sizeof(ulong),
Packit bf408e
				"hugetlbfs_sb_info.hstate", FAULT_ON_ERROR);
Packit bf408e
			readmem(hstate_p + OFFSET(hstate_order), KVADDR,
Packit bf408e
				&order,	sizeof(uint), "hstate.order",
Packit bf408e
				FAULT_ON_ERROR);
Packit bf408e
			pages_per_hugepage = 1 << order;
Packit bf408e
		} else {
Packit bf408e
			unsigned long hpage_shift;
Packit bf408e
			/*
Packit bf408e
			 * HPAGE_SHIFT is 21 after commit 83a5101b
Packit bf408e
			 * (kernel > 2.6.24)
Packit bf408e
			 */
Packit bf408e
			if (THIS_KERNEL_VERSION > LINUX(2, 6, 24)) {
Packit bf408e
				hpage_shift = 21;
Packit bf408e
			} else {
Packit bf408e
				/*
Packit bf408e
				 * HPAGE_SHIFT:
Packit bf408e
				 *   x86(PAE): 21
Packit bf408e
				 *   x86(no PAE): 22
Packit bf408e
				 *   x86_64: 21
Packit bf408e
				 */
Packit bf408e
				if ((machine_type("X86") &&
Packit bf408e
					!(machdep->flags & PAE)))
Packit bf408e
					hpage_shift = 22;
Packit bf408e
				else
Packit bf408e
					hpage_shift = 21;
Packit bf408e
			}
Packit bf408e
			pages_per_hugepage = (1 << hpage_shift) / PAGESIZE();
Packit bf408e
		}
Packit bf408e
		*rss += pages_per_hugepage * nr_pages;
Packit bf408e
	} else {
Packit bf408e
		unsigned long swapped;
Packit bf408e

Packit bf408e
		*rss += nr_pages;
Packit bf408e
		readmem(inode_p - OFFSET(shmem_inode_info_vfs_inode) +
Packit bf408e
			OFFSET(shmem_inode_info_swapped), KVADDR,
Packit bf408e
			&swapped, sizeof(ulong), "shmem_inode_info.swapped",
Packit bf408e
			FAULT_ON_ERROR);
Packit bf408e
		*swap += swapped;
Packit bf408e
    }
Packit bf408e
}
Packit bf408e

Packit bf408e
static int
Packit bf408e
is_file_hugepages(ulong file_p)
Packit bf408e
{
Packit bf408e
	unsigned long f_op, sfd_p;
Packit bf408e

Packit bf408e
again:
Packit bf408e
	readmem(file_p + OFFSET(file_f_op), KVADDR, &f_op, sizeof(ulong),
Packit bf408e
		"file.f_op", FAULT_ON_ERROR);
Packit bf408e
	if (f_op == ipcs_table.hugetlbfs_f_op_addr)
Packit bf408e
		return 1;
Packit bf408e

Packit bf408e
	if (ipcs_table.use_shm_f_op) {
Packit bf408e
		if (ipcs_table.shm_f_op_huge_addr != -1) {
Packit bf408e
			if (f_op == ipcs_table.shm_f_op_huge_addr)
Packit bf408e
				return 1;
Packit bf408e
		} else {
Packit bf408e
			if (f_op == ipcs_table.shm_f_op_addr) {
Packit bf408e
				readmem(file_p +
Packit bf408e
					OFFSET(file_private_data),
Packit bf408e
					KVADDR,	&sfd_p, sizeof(ulong),
Packit bf408e
					"file.private_data", FAULT_ON_ERROR);
Packit bf408e
				readmem(sfd_p +
Packit bf408e
					OFFSET(shm_file_data_file),
Packit bf408e
					KVADDR,	&file_p, sizeof(ulong),
Packit bf408e
					"shm_file_data.file", FAULT_ON_ERROR);
Packit bf408e
				goto again;
Packit bf408e
			}
Packit bf408e
		}
Packit bf408e
	}
Packit bf408e

Packit bf408e
	return 0;
Packit bf408e
}
Packit bf408e

Packit bf408e
static void
Packit bf408e
gather_radix_tree_entries(ulong ipcs_idr_p)
Packit bf408e
{
Packit bf408e
	long len;
Packit bf408e

Packit bf408e
	ipcs_table.cnt = do_radix_tree(ipcs_idr_p, RADIX_TREE_COUNT, NULL);
Packit bf408e

Packit bf408e
	if (ipcs_table.cnt) {
Packit bf408e
		len = sizeof(struct list_pair) * (ipcs_table.cnt+1);
Packit bf408e
		ipcs_table.lp = (struct list_pair *)GETBUF(len);
Packit bf408e
		ipcs_table.lp[0].index = ipcs_table.cnt;
Packit bf408e
		ipcs_table.cnt = do_radix_tree(ipcs_idr_p, RADIX_TREE_GATHER, ipcs_table.lp);
Packit bf408e
	} else
Packit bf408e
		ipcs_table.lp = NULL;
Packit bf408e
}
Packit bf408e

Packit bf408e
static void
Packit bf408e
gather_xarray_entries(ulong ipcs_idr_p)
Packit bf408e
{
Packit bf408e
	long len;
Packit bf408e

Packit bf408e
	ipcs_table.cnt = do_xarray(ipcs_idr_p, XARRAY_COUNT, NULL);
Packit bf408e

Packit bf408e
	if (ipcs_table.cnt) {
Packit bf408e
		len = sizeof(struct list_pair) * (ipcs_table.cnt+1);
Packit bf408e
		ipcs_table.lp = (struct list_pair *)GETBUF(len);
Packit bf408e
		ipcs_table.lp[0].index = ipcs_table.cnt;
Packit bf408e
		ipcs_table.cnt = do_xarray(ipcs_idr_p, XARRAY_GATHER, ipcs_table.lp);
Packit bf408e
	} else
Packit bf408e
		ipcs_table.lp = NULL;
Packit bf408e
}
Packit bf408e