Home | History | Annotate | Line # | Download | only in uvm
uvm_coredump.c revision 1.7.6.1
      1  1.7.6.1     ad /*	$NetBSD: uvm_coredump.c,v 1.7.6.1 2020/02/29 20:21:11 ad Exp $	*/
      2      1.1     ad 
      3      1.1     ad /*
      4      1.1     ad  * Copyright (c) 1997 Charles D. Cranor and Washington University.
      5      1.1     ad  * Copyright (c) 1991, 1993, The Regents of the University of California.
      6      1.1     ad  *
      7      1.1     ad  * All rights reserved.
      8      1.1     ad  *
      9      1.1     ad  * This code is derived from software contributed to Berkeley by
     10      1.1     ad  * The Mach Operating System project at Carnegie-Mellon University.
     11      1.1     ad  *
     12      1.1     ad  * Redistribution and use in source and binary forms, with or without
     13      1.1     ad  * modification, are permitted provided that the following conditions
     14      1.1     ad  * are met:
     15      1.1     ad  * 1. Redistributions of source code must retain the above copyright
     16      1.1     ad  *    notice, this list of conditions and the following disclaimer.
     17      1.1     ad  * 2. Redistributions in binary form must reproduce the above copyright
     18      1.1     ad  *    notice, this list of conditions and the following disclaimer in the
     19      1.1     ad  *    documentation and/or other materials provided with the distribution.
     20      1.2  chuck  * 3. Neither the name of the University nor the names of its contributors
     21      1.1     ad  *    may be used to endorse or promote products derived from this software
     22      1.1     ad  *    without specific prior written permission.
     23      1.1     ad  *
     24      1.1     ad  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25      1.1     ad  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26      1.1     ad  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27      1.1     ad  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28      1.1     ad  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29      1.1     ad  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30      1.1     ad  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31      1.1     ad  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32      1.1     ad  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33      1.1     ad  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34      1.1     ad  * SUCH DAMAGE.
     35      1.1     ad  *
     36      1.1     ad  *	@(#)vm_glue.c	8.6 (Berkeley) 1/5/94
     37      1.1     ad  * from: Id: uvm_glue.c,v 1.1.2.8 1998/02/07 01:16:54 chs Exp
     38      1.1     ad  *
     39      1.1     ad  *
     40      1.1     ad  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
     41      1.1     ad  * All rights reserved.
     42      1.1     ad  *
     43      1.1     ad  * Permission to use, copy, modify and distribute this software and
     44      1.1     ad  * its documentation is hereby granted, provided that both the copyright
     45      1.1     ad  * notice and this permission notice appear in all copies of the
     46      1.1     ad  * software, derivative works or modified versions, and any portions
     47      1.1     ad  * thereof, and that both notices appear in supporting documentation.
     48      1.1     ad  *
     49      1.1     ad  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     50      1.1     ad  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     51      1.1     ad  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     52      1.1     ad  *
     53      1.1     ad  * Carnegie Mellon requests users of this software to return to
     54      1.1     ad  *
     55      1.1     ad  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     56      1.1     ad  *  School of Computer Science
     57      1.1     ad  *  Carnegie Mellon University
     58      1.1     ad  *  Pittsburgh PA 15213-3890
     59      1.1     ad  *
     60      1.1     ad  * any improvements or extensions that they make and grant Carnegie the
     61      1.1     ad  * rights to redistribute these changes.
     62      1.1     ad  */
     63      1.1     ad 
     64      1.1     ad #include <sys/cdefs.h>
     65  1.7.6.1     ad __KERNEL_RCSID(0, "$NetBSD: uvm_coredump.c,v 1.7.6.1 2020/02/29 20:21:11 ad Exp $");
     66      1.1     ad 
     67      1.1     ad /*
     68      1.1     ad  * uvm_coredump.c: glue functions for coredump
     69      1.1     ad  */
     70      1.1     ad 
     71      1.1     ad #include <sys/param.h>
     72      1.1     ad #include <sys/systm.h>
     73      1.1     ad #include <sys/proc.h>
     74      1.1     ad 
     75      1.1     ad #include <uvm/uvm.h>
     76      1.1     ad 
     77      1.1     ad /*
     78      1.1     ad  * uvm_coredump_walkmap: walk a process's map for the purpose of dumping
     79      1.1     ad  * a core file.
     80      1.4    dsl  * XXX: I'm not entirely sure the locking is this function is in anyway
     81      1.4    dsl  * correct.  If the process isn't actually stopped then the data passed
     82      1.4    dsl  * to func() is at best stale, and horrid things might happen if the
     83      1.4    dsl  * entry being processed is deleted (dsl).
     84      1.1     ad  */
     85      1.1     ad 
     86      1.1     ad int
     87      1.5    dsl uvm_coredump_walkmap(struct proc *p, int (*func)(struct uvm_coredump_state *),
     88      1.5    dsl     void *cookie)
     89      1.1     ad {
     90      1.1     ad 	struct uvm_coredump_state state;
     91      1.1     ad 	struct vmspace *vm = p->p_vmspace;
     92      1.1     ad 	struct vm_map *map = &vm->vm_map;
     93      1.1     ad 	struct vm_map_entry *entry;
     94      1.1     ad 	int error;
     95      1.1     ad 
     96      1.1     ad 	entry = NULL;
     97      1.1     ad 	vm_map_lock_read(map);
     98      1.1     ad 	state.end = 0;
     99      1.1     ad 	for (;;) {
    100      1.1     ad 		if (entry == NULL)
    101      1.1     ad 			entry = map->header.next;
    102      1.1     ad 		else if (!uvm_map_lookup_entry(map, state.end, &entry))
    103      1.1     ad 			entry = entry->next;
    104      1.1     ad 		if (entry == &map->header)
    105      1.1     ad 			break;
    106      1.1     ad 
    107      1.1     ad 		state.cookie = cookie;
    108      1.1     ad 		if (state.end > entry->start) {
    109      1.1     ad 			state.start = state.end;
    110      1.1     ad 		} else {
    111      1.1     ad 			state.start = entry->start;
    112      1.1     ad 		}
    113      1.1     ad 		state.realend = entry->end;
    114      1.1     ad 		state.end = entry->end;
    115      1.1     ad 		state.prot = entry->protection;
    116      1.1     ad 		state.flags = 0;
    117      1.1     ad 
    118      1.1     ad 		/*
    119      1.1     ad 		 * Dump the region unless one of the following is true:
    120      1.1     ad 		 *
    121      1.1     ad 		 * (1) the region has neither object nor amap behind it
    122      1.1     ad 		 *     (ie. it has never been accessed).
    123      1.1     ad 		 *
    124      1.1     ad 		 * (2) the region has no amap and is read-only
    125      1.1     ad 		 *     (eg. an executable text section).
    126      1.1     ad 		 *
    127      1.1     ad 		 * (3) the region's object is a device.
    128      1.1     ad 		 *
    129      1.1     ad 		 * (4) the region is unreadable by the process.
    130      1.1     ad 		 */
    131      1.1     ad 
    132      1.1     ad 		KASSERT(!UVM_ET_ISSUBMAP(entry));
    133      1.7    rin #ifdef VM_MAXUSER_ADDRESS
    134      1.1     ad 		KASSERT(state.start < VM_MAXUSER_ADDRESS);
    135      1.1     ad 		KASSERT(state.end <= VM_MAXUSER_ADDRESS);
    136      1.7    rin #endif
    137      1.1     ad 		if (entry->object.uvm_obj == NULL &&
    138      1.1     ad 		    entry->aref.ar_amap == NULL) {
    139      1.1     ad 			state.realend = state.start;
    140      1.1     ad 		} else if ((entry->protection & VM_PROT_WRITE) == 0 &&
    141      1.1     ad 		    entry->aref.ar_amap == NULL) {
    142      1.1     ad 			state.realend = state.start;
    143      1.1     ad 		} else if (entry->object.uvm_obj != NULL &&
    144      1.1     ad 		    UVM_OBJ_IS_DEVICE(entry->object.uvm_obj)) {
    145      1.1     ad 			state.realend = state.start;
    146      1.1     ad 		} else if ((entry->protection & VM_PROT_READ) == 0) {
    147      1.1     ad 			state.realend = state.start;
    148      1.1     ad 		} else {
    149      1.1     ad 			if (state.start >= (vaddr_t)vm->vm_maxsaddr)
    150      1.1     ad 				state.flags |= UVM_COREDUMP_STACK;
    151      1.1     ad 
    152      1.1     ad 			/*
    153      1.1     ad 			 * If this an anonymous entry, only dump instantiated
    154      1.1     ad 			 * pages.
    155      1.1     ad 			 */
    156      1.1     ad 			if (entry->object.uvm_obj == NULL) {
    157      1.1     ad 				vaddr_t end;
    158      1.1     ad 
    159  1.7.6.1     ad 				amap_lock(entry->aref.ar_amap, RW_READER);
    160      1.1     ad 				for (end = state.start;
    161      1.1     ad 				     end < state.end; end += PAGE_SIZE) {
    162      1.1     ad 					struct vm_anon *anon;
    163      1.1     ad 					anon = amap_lookup(&entry->aref,
    164      1.1     ad 					    end - entry->start);
    165      1.1     ad 					/*
    166      1.1     ad 					 * If we have already encountered an
    167      1.1     ad 					 * uninstantiated page, stop at the
    168      1.1     ad 					 * first instantied page.
    169      1.1     ad 					 */
    170      1.1     ad 					if (anon != NULL &&
    171      1.1     ad 					    state.realend != state.end) {
    172      1.1     ad 						state.end = end;
    173      1.1     ad 						break;
    174      1.1     ad 					}
    175      1.1     ad 
    176      1.1     ad 					/*
    177      1.1     ad 					 * If this page is the first
    178      1.1     ad 					 * uninstantiated page, mark this as
    179      1.1     ad 					 * the real ending point.  Continue to
    180      1.1     ad 					 * counting uninstantiated pages.
    181      1.1     ad 					 */
    182      1.1     ad 					if (anon == NULL &&
    183      1.1     ad 					    state.realend == state.end) {
    184      1.1     ad 						state.realend = end;
    185      1.1     ad 					}
    186      1.1     ad 				}
    187      1.1     ad 				amap_unlock(entry->aref.ar_amap);
    188      1.1     ad 			}
    189      1.1     ad 		}
    190      1.4    dsl 
    191      1.1     ad 		vm_map_unlock_read(map);
    192      1.5    dsl 		error = (*func)(&state);
    193      1.1     ad 		if (error)
    194      1.1     ad 			return (error);
    195      1.1     ad 		vm_map_lock_read(map);
    196      1.1     ad 	}
    197      1.1     ad 	vm_map_unlock_read(map);
    198      1.1     ad 
    199      1.1     ad 	return (0);
    200      1.1     ad }
    201      1.4    dsl 
    202      1.4    dsl static int
    203      1.5    dsl count_segs(struct uvm_coredump_state *s)
    204      1.4    dsl {
    205      1.4    dsl     (*(int *)s->cookie)++;
    206      1.4    dsl 
    207      1.4    dsl     return 0;
    208      1.4    dsl }
    209      1.4    dsl 
    210      1.4    dsl int
    211      1.4    dsl uvm_coredump_count_segs(struct proc *p)
    212      1.4    dsl {
    213      1.4    dsl 	int count = 0;
    214      1.4    dsl 
    215      1.4    dsl 	uvm_coredump_walkmap(p, count_segs, &count);
    216      1.4    dsl 	return count;
    217      1.4    dsl }
    218