From owner-p4-projects@FreeBSD.ORG Fri Jun 24 16:19:41 2005 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0773516A42A; Fri, 24 Jun 2005 16:19:40 +0000 (GMT) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 97D9416A41F for ; Fri, 24 Jun 2005 16:19:39 +0000 (GMT) (envelope-from ps@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 74DE143D53 for ; Fri, 24 Jun 2005 16:19:39 +0000 (GMT) (envelope-from ps@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j5OGJdVj058317 for ; Fri, 24 Jun 2005 16:19:39 GMT (envelope-from ps@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j5OGJddF058314 for perforce@freebsd.org; Fri, 24 Jun 2005 16:19:39 GMT (envelope-from ps@freebsd.org) Date: Fri, 24 Jun 2005 16:19:39 GMT Message-Id: <200506241619.j5OGJddF058314@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ps@freebsd.org using -f From: Paul Saab To: Perforce Change Reviews Cc: Subject: PERFORCE change 78912 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Jun 2005 16:19:41 -0000 http://perforce.freebsd.org/chv.cgi?CH=78912 Change 78912 by ps@butter.corp on 2005/06/24 16:19:25 checkpoint for new elf crashdump parsing. This does not support PAE yet. Affected files ... .. //depot/projects/hammer/lib/libkvm/kvm_i386.c#2 edit Differences ... ==== //depot/projects/hammer/lib/libkvm/kvm_i386.c#2 (text+ko) ==== @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,8 @@ #include #include +#include + #include #include "kvm_private.h" @@ -71,36 +74,98 @@ #endif struct vmstate { + void *mmapbase; + size_t mmapsize; pd_entry_t *PTD; }; +/* + * Map the ELF headers into the process' address space. We do this in two + * steps: first the ELF header itself and using that information the whole + * set of headers. (Taken from kvm_ia64.c) + */ +static int +_kvm_maphdrs(kvm_t *kd, size_t sz) +{ + struct vmstate *vm = kd->vmst; + + /* munmap() previous mmap(). */ + if (vm->mmapbase != NULL) { + munmap(vm->mmapbase, vm->mmapsize); + vm->mmapbase = NULL; + } + + vm->mmapsize = sz; + vm->mmapbase = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0); + if (vm->mmapbase == MAP_FAILED) { + _kvm_err(kd, kd->program, "cannot mmap corefile"); + return (-1); + } + return (0); +} + +/* + * Translate a physical memory address to a file-offset in the crash-dump. + * (Taken from kvm_ia64.c) + */ +static size_t +_kvm_pa2off(kvm_t *kd, uint64_t pa, u_long *ofs) +{ + Elf_Ehdr *e = kd->vmst->mmapbase; + Elf_Phdr *p = (Elf_Phdr*)((char*)e + e->e_phoff); + int n = e->e_phnum; + + while (n && (pa < p->p_paddr || pa >= p->p_paddr + p->p_memsz)) { +printf("%d %.8x %.8x %.8x\n", n, pa, p->p_paddr, p->p_paddr + p->p_memsz); + p++, n--; + } +printf("%d %.8x %.8x %.8x\n", n, pa, p->p_paddr, p->p_paddr + p->p_memsz); + + if (n == 0) + return (0); + + *ofs = (pa - p->p_paddr) + p->p_offset; + return (PAGE_SIZE - ((size_t)pa & PAGE_MASK)); +} + void _kvm_freevtop(kvm_t *kd) { - if (kd->vmst != 0) { - if (kd->vmst->PTD) { - free(kd->vmst->PTD); - } - free(kd->vmst); - } + struct vmstate *vm = kd->vmst; + + if (vm->mmapbase != NULL) + munmap(vm->mmapbase, vm->mmapsize); + + if (vm->PTD) + free(vm->PTD); + free(vm); + kd->vmst = NULL; } int _kvm_initvtop(kvm_t *kd) { - struct vmstate *vm; struct nlist nlist[2]; u_long pa; u_long kernbase; pd_entry_t *PTD; + Elf_Ehdr *ehdr; + size_t hdrsz; - vm = (struct vmstate *)_kvm_malloc(kd, sizeof(*vm)); - if (vm == 0) { + kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst)); + if (kd->vmst == 0) { _kvm_err(kd, kd->program, "cannot allocate vm"); return (-1); } - kd->vmst = vm; - vm->PTD = 0; + kd->vmst->PTD = 0; + + if (_kvm_maphdrs(kd, sizeof(Elf_Ehdr)) == -1) + return (-1); + + ehdr = kd->vmst->mmapbase; + hdrsz = ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum; + if (_kvm_maphdrs(kd, hdrsz) == -1) + return (-1); nlist[0].n_name = "kernbase"; nlist[1].n_name = 0; @@ -127,21 +192,24 @@ _kvm_err(kd, kd->program, "cannot read PTD"); return (-1); } - vm->PTD = PTD; + kd->vmst->PTD = PTD; return (0); } -static int -_kvm_vatop(kvm_t *kd, u_long va, u_long *pa) +int +_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa) { struct vmstate *vm; u_long offset; u_long pte_pa; + u_long pde_pa; pd_entry_t pde; pt_entry_t pte; u_long pdeindex; u_long pteindex; - int i; + size_t s; + u_long a, ofs; + if (ISALIVE(kd)) { _kvm_err(kd, 0, "vatop called in live kernel!"); @@ -156,8 +224,13 @@ * not yet set) then return pa == va to avoid infinite recursion. */ if (vm->PTD == 0) { - *pa = va; - return (PAGE_SIZE - offset); + s = _kvm_pa2off(kd, va, pa); + if (s == 0) { + _kvm_err(kd, kd->program, + "_kvm_kvatop: bootstrap data not in dump"); + goto invalid; + } else + return (PAGE_SIZE - offset); } pdeindex = va >> PDRSHIFT; @@ -174,15 +247,27 @@ */ #define PAGE4M_MASK (NBPDR - 1) #define PG_FRAME4M (~PAGE4M_MASK) - *pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); + pde_pa = ((u_long)pde & PG_FRAME4M) + (va & PAGE4M_MASK); + s = _kvm_pa2off(kd, pde_pa, &ofs); + if (s <= sizeof pde) { + _kvm_syserr(kd, kd->program, "_kvm_kvatop: pde_pa not found"); + goto invalid; + } + *pa = ofs; return (NBPDR - (va & PAGE4M_MASK)); } pteindex = (va >> PAGE_SHIFT) & (NPTEPG-1); pte_pa = ((u_long)pde & PG_FRAME) + (pteindex * sizeof(pt_entry_t)); + s = _kvm_pa2off(kd, pte_pa, &ofs); + if (s <= sizeof pte) { + _kvm_err(kd, kd->program, "_kvm_kvatop: pdpe_pa not found"); + goto invalid; + } + /* XXX This has to be a physical address read, kvm_read is virtual */ - if (lseek(kd->pmfd, pte_pa, 0) == -1) { + if (lseek(kd->pmfd, ofs, 0) == -1) { _kvm_syserr(kd, kd->program, "_kvm_vatop: lseek"); goto invalid; } @@ -193,16 +278,15 @@ if (((u_long)pte & PG_V) == 0) goto invalid; - *pa = ((u_long)pte & PG_FRAME) + offset; - return (PAGE_SIZE - offset); + a = ((u_long)pte & PG_FRAME) + offset; + s =_kvm_pa2off(kd, a, pa); + if (s == 0) { + _kvm_err(kd, kd->program, "_kvm_kvatop: address not in dump"); + goto invalid; + } else + return (PAGE_SIZE - offset); invalid: _kvm_err(kd, 0, "invalid address (%x)", va); return (0); } - -int -_kvm_kvatop(kvm_t *kd, u_long va, u_long *pa) -{ - return (_kvm_vatop(kd, va, pa)); -}