Edit

IABSD.fr/src/sys/dev/ksyms.c

Branch :

  • Show log

    Commit

  • Author : kettenis
    Date : 2020-07-18 20:21:01
    Hash : 060e6ef1
    Message : Make /dev/ksyms work.

  • sys/dev/ksyms.c
  • /*	$OpenBSD: ksyms.c,v 1.33 2020/07/18 20:21:01 kettenis Exp $	*/
    /*
     * Copyright (c) 1998 Todd C. Miller <millert@openbsd.org>
     * Copyright (c) 2001 Artur Grabowski <art@openbsd.org>
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     * THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include <sys/param.h>
    #include <sys/exec.h>
    #include <sys/systm.h>
    #include <sys/uio.h>
    #include <sys/malloc.h>
    #include <sys/fcntl.h>
    #include <sys/conf.h>
    #include <sys/exec_elf.h>
    
    extern char *esym;				/* end of symbol table */
    #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
        defined(__i386__) || defined(__powerpc64__)
    extern char *ssym;				/* end of kernel */
    #else
    extern long end;				/* end of kernel */
    #endif
    
    static caddr_t ksym_head;
    static caddr_t ksym_syms;
    static size_t ksym_head_size;
    static size_t ksym_syms_size;
    
    void	ksymsattach(int);
    
    /*
     * We assume __LDPGSZ is a multiple of PAGE_SIZE (it is)
     */
    
    void
    ksymsattach(int num)
    {
    
    #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
        defined(__i386__) || defined(__powerpc64__)
    	if (esym <= ssym) {
    		printf("/dev/ksyms: Symbol table not valid.\n");
    		return;
    	}
    #else
    	if (esym <= (char *)&end) {
    		printf("/dev/ksyms: Symbol table not valid.\n");
    		return;
    	}
    #endif
    
    	do {
    #if defined(__sparc64__) || defined(__mips__) || defined(__amd64__) || \
        defined(__i386__) || defined(__powerpc64__)
    		caddr_t symtab = ssym;
    #else
    		caddr_t symtab = (caddr_t)&end;
    #endif
    		Elf_Ehdr *elf;
    		Elf_Shdr *shdr;
    		int i;
    
    		elf = (Elf_Ehdr *)symtab;
    		if (memcmp(elf->e_ident, ELFMAG, SELFMAG) != 0 ||
    		    elf->e_ident[EI_CLASS] != ELFCLASS ||
    		    elf->e_machine != ELF_TARG_MACH)
    			break;
    
    		shdr = (Elf_Shdr *)&symtab[elf->e_shoff];
    		for (i = 0; i < elf->e_shnum; i++) {
    			if (shdr[i].sh_type == SHT_SYMTAB) {
    				break;
    			}
    		}
    
    		/*
    		 * No symbol table found.
    		 */
    		if (i == elf->e_shnum)
    			break;
    
    		/*
    		 * No additional header.
    		 */
    		ksym_head_size = 0;
    		ksym_syms = symtab;
    		ksym_syms_size = (size_t)(esym - symtab);
    
    		return;
    	} while (0);
    }
    
    int
    ksymsopen(dev_t dev, int flag, int mode, struct proc *p)
    {
    
    	/* There are no non-zero minor devices */
    	if (minor(dev) != 0)
    		return (ENXIO);
    
    	/* This device is read-only */
    	if ((flag & FWRITE))
    		return (EPERM);
    
    	/* ksym_syms must be initialized */
    	if (ksym_syms == NULL)
    		return (ENXIO);
    
    	return (0);
    }
    
    int
    ksymsclose(dev_t dev, int flag, int mode, struct proc *p)
    {
    
    	return (0);
    }
    
    int
    ksymsread(dev_t dev, struct uio *uio, int flags)
    {
    	int error;
    	size_t len;
    	caddr_t v;
    	size_t off;
    
    	if (uio->uio_offset < 0)
    		return (EINVAL);
    
    	while (uio->uio_resid > 0) {
    		if (uio->uio_offset >= ksym_head_size + ksym_syms_size)
    			break;
    
    		if (uio->uio_offset < ksym_head_size) {
    			v = ksym_head + uio->uio_offset;
    			len = ksym_head_size - uio->uio_offset;
    		} else {
    			off = uio->uio_offset - ksym_head_size;
    			v = ksym_syms + off;
    			len = ksym_syms_size - off;
    		}
    
    		if (len > uio->uio_resid)
    			len = uio->uio_resid;
    
    		if ((error = uiomove(v, len, uio)) != 0)
    			return (error);
    	}
    
    	return (0);
    }