Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

kl_dump_i386.c

/*
 * $Id: kl_dump_i386.c,v 1.2 2005/02/23 01:09:12 tjm Exp $
 *
 * This file is part of libklib.
 * A library which provides access to Linux system kernel dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, NEC, and others
 *
 * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <klib.h>
#include <linux/stddef.h>     /* offsetof */

static kl_dump_header_i386_t arch_hdr;

/*
 * function declarations
 */
static int kl_write_dha_i386(void*);

/*
 * get_dump_header_i386()
 */
int
kl_get_dump_header_i386(kl_dump_header_i386_t *dha)
{
      kl_dump_header_t dh;
      uint32_t hdr_size, offset, nr_cpus;
      char hdr_buf[KL_DUMP_HEADER_SIZE];

      /* first, make sure this isn't a live system
       */
      if (CORE_IS_KMEM) {
            KL_ERROR = KLE_ACTIVE;
            return(1);
      }

        if (KL_GET_UINT64(&arch_hdr.magic_number)
               == KL_DUMP_MAGIC_NUMBER_I386) {
               /*
                * Already read from the dump file.
                */
               memcpy(dha, &arch_hdr, sizeof(kl_dump_header_i386_t));
                return(0);
        }

      /* get the dump header
       */

      kl_get_dump_header(&dh);

        if (lseek(MIP->core_fd,
               dh.header_size +  offsetof(kl_dump_header_i386_t, header_size),
               SEEK_SET) < 0) {
               KL_ERROR = KLE_INVALID_LSEEK;
               return(1);
       }
       if (read(MIP->core_fd, (char *)&hdr_size, sizeof(hdr_size)) !=
               sizeof(hdr_size)) {
               KL_ERROR = KLE_INVALID_READ;
               return(1);
       }

      if (lseek(MIP->core_fd, dh.header_size, SEEK_SET) < 0) {
            KL_ERROR = KLE_INVALID_LSEEK;
            return(1);
      }

      if (read(MIP->core_fd, (char *)&hdr_buf[0], hdr_size) !=
            hdr_size) {
                  KL_ERROR = KLE_INVALID_READ;
                  return(1);
      }

        /*
         * Though we have KL_NR_CPUS is 128, the header size is different
         * CONFIG_NR_CPUS might be different in the kernel. Hence, need
         * to find out how many CPUs are configured.
         * To do that, calculate the size of pt_regs, task_ptr, stack_addr,
         * and stack_ptr for a single CPU.
         * CPU_size = sizeof(pt_regs) + sizeof(uint64_t) * 3;
         * NR_CPUS = (header_size - offset of smp_regs[0]) / CPU_size
         */
        offset = offsetof(kl_dump_header_i386_t, smp_regs[0]);
        nr_cpus = (hdr_size - offset) / sizeof(struct kl_dump_CPU_info_i386);

        if (nr_cpus > KL_NR_CPUS) {
                /* Not supported > 128 now. Change KL_NR_CPUS value in
                 * klib.h and kl_dump_i386.h */
                KL_ERROR = KLE_INVALID_READ;
                return(1);
        }
 
        memcpy(&arch_hdr, (void *)&hdr_buf, offset);
        memcpy(&arch_hdr.smp_regs[0], (void *)&hdr_buf[offset],
                nr_cpus * sizeof(struct kl_pt_regs_i386));
        offset += nr_cpus * sizeof(struct kl_pt_regs_i386);
        memcpy(&arch_hdr.smp_current_task[0], (void *)&hdr_buf[offset],
                nr_cpus * sizeof(arch_hdr.smp_current_task[0]));
        offset += nr_cpus * sizeof(arch_hdr.smp_current_task[0]);
        memcpy(&arch_hdr.stack[0], (void *)&hdr_buf[offset],
                 nr_cpus * sizeof(arch_hdr.stack[0]));
         offset += nr_cpus * sizeof(arch_hdr.stack[0]);
        memcpy(&arch_hdr.stack_ptr[0], (void *)&hdr_buf[offset],
                 nr_cpus * sizeof(arch_hdr.stack_ptr[0]));

      if (KL_GET_UINT64(&arch_hdr.magic_number) != KL_DUMP_MAGIC_NUMBER_I386) {
            KL_ERROR = KLE_INVALID_DUMP_MAGIC;
            return(1);
      }

      memcpy(dha, &arch_hdr, sizeof(kl_dump_header_i386_t));

      return(0);
}

/*
 * kl_dumpesp_i386()
 */
kaddr_t
kl_dumpesp_i386(kaddr_t tsk)
{
      kl_dump_header_i386_t dha;
      int i;

      if (kl_get_dump_header_i386(&dha)) {
            return((kaddr_t)NULL);
      }

      for (i = 0; i < dha.smp_num_cpus; i++) {
            if ( tsk == (kaddr_t) dha.smp_current_task[i])
                  return (dha.smp_regs[i].esp);
      }

      return((kaddr_t)NULL);
}

/*
 * kl_dumpeip_i386()
 */
kaddr_t
kl_dumpeip_i386(kaddr_t tsk)
{
      kl_dump_header_i386_t dha;
      int i;

      if (kl_get_dump_header_i386(&dha)) {
            return((kaddr_t)NULL);
      }

      for (i = 0; i < dha.smp_num_cpus; i++) {
            if (tsk == (kaddr_t)dha.smp_current_task[i])
                  return (dha.smp_regs[i].eip);
      }

      return((kaddr_t)NULL);
}

/*
 * kl_smp_dumptask_i386()
 */
int
kl_smp_dumptask_i386(kaddr_t tsk)
{
      kl_dump_header_i386_t dha;
      int i;

      if (kl_get_dump_header_i386(&dha)) {
            return((kaddr_t)NULL);
      }
      
      for (i = 0; i < dha.smp_num_cpus; i++) {
            if (tsk == (kaddr_t)dha.smp_current_task[i])
                  return (1);
      }
      return (0); 
 }

/*
 * kl_set_dumparch_i386()
 */
int
kl_set_dumparch_i386(void)
{
      KLP->dump->arch.pageoffset = KL_PAGE_OFFSET_I386;
      KLP->dump->arch.kstacksize = KL_KSTACK_SIZE_I386;
      KLP->dump->arch.pageshift = KL_PAGE_SHIFT_I386;
      KLP->dump->arch.pagesize = KL_PAGE_SIZE_I386;
      KLP->dump->arch.pagemask = KL_PAGE_MASK_I386;
      KLP->dump->arch.pgdshift = KL_PGDIR_SHIFT_I386;
      KLP->dump->arch.pgdsize = KL_PGDIR_SIZE_I386;
      KLP->dump->arch.pgdmask = KL_PGDIR_MASK_I386;
      KLP->dump->arch.pmdshift = KL_PMD_SHIFT_I386;
      KLP->dump->arch.pmdsize = KL_PMD_SIZE_I386;
      KLP->dump->arch.pmdmask = KL_PMD_MASK_I386;
      KLP->dump->arch.ptrsperpgd = KL_PTRS_PER_PGD_I386;
      KLP->dump->arch.ptrsperpmd = KL_PTRS_PER_PMD_I386;
      KLP->dump->arch.ptrsperpte = KL_PTRS_PER_PTE_I386;
      KLP->dump->arch.kernelstack = kl_kernelstack_i386;
      KLP->dump->arch.mmap_virtop = kl_mmap_virtop_i386;
      KLP->dump->arch.fix_vaddr = kl_fix_vaddr_i386;
      KLP->dump->arch.dha_size = sizeof(kl_dump_header_i386_t);
      KLP->dump->arch.write_dha = kl_write_dha_i386;
      return(0);
}


/*
 * kl_write_dump_header_i386()
 */
static int
kl_write_dha_i386(void *buf)
{
      kl_dump_header_i386_t dha;

      memset(&dha, 0, sizeof(dha));

      dha.magic_number = KL_DUMP_MAGIC_NUMBER_I386;
      dha.version = KL_DUMP_VERSION_NUMBER_I386;
      dha.header_size = sizeof(dha);

      memcpy(buf, &dha, dha.header_size);

      return(0);
}

Generated by  Doxygen 1.6.0   Back to index