source: gpfs_3.1_ker2.6.20/lpp/mmfs/src/gpl-linux/kdump-kern.c @ 145

Last change on this file since 145 was 16, checked in by rock, 17 years ago
File size: 28.4 KB
Line 
1/***************************************************************************
2 *
3 * Copyright (C) 2001 International Business Machines
4 * All rights reserved.
5 *
6 * This file is part of the GPFS mmfslinux kernel module.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 *  1. Redistributions of source code must retain the above copyright notice,
13 *     this list of conditions and the following disclaimer.
14 *  2. Redistributions in binary form must reproduce the above copyright
15 *     notice, this list of conditions and the following disclaimer in the
16 *     documentation and/or other materials provided with the distribution.
17 *  3. The name of the author may not be used to endorse or promote products
18 *     derived from this software without specific prior written
19 *     permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *************************************************************************** */
33/* @(#)62       1.41.1.3  src/avs/fs/mmfs/ts/kernext/gpl-linux/kdump-kern.c, mmfs, avs_rgpfs24, rgpfs24s011a 3/14/07 10:56:41 */
34/* Code for program to dump kernel memory that needs to include kernel
35   header files. */
36
37/*
38 * Contents:
39 *   KernInit
40 *   GenericGet
41 *   GetDentry
42 *   FreeDentry
43 *   GetInode
44 *   GetVFSMount
45 *   GetSuperBlock
46 *   GetRootSuperBlock
47 *   GetPage
48 *   GetAddressSpace
49 *   GetVMAreaStruct
50 *   GetMMStruct
51 *   GetTaskStruct
52 *   GetTaskStructByPID
53 *   P_HEADER
54 *   PrintDentry
55 *   PrintDentryTree
56 *   PrintInode
57 *   PrintSuperBlock
58 *   PrintPage
59 *   PrintAddressSpace
60 *   PrintVMAreaStruct
61 *   PrintMMStruct
62 *   PrintTaskStruct
63 *   VirtToReal
64 *
65 */
66
67
68#include <Shark-gpl.h>
69#include <linux/vfs.h>
70#include <cxiSystem.h>
71#include <verdep.h>
72
73#include <linux/config.h>
74#include <linux/slab.h>
75#include <linux/vmalloc.h>
76#include <linux/spinlock.h>
77#include <linux/smp_lock.h>
78#include <linux/dcache.h>
79#include <linux/mount.h>
80#include <linux/fs.h>
81#include <linux/mm.h>
82
83#include <linux/elf.h>
84#include <linux/elfcore.h>
85
86#include <kdump-kern.h>
87#include <kdump.h>
88
89#include <stdio.h>
90#include <assert.h>
91
92#ifdef NOSTABS
93/* Address of header of the list of all super_blocks */
94unsigned long super_blocks_addr = 0x103;
95
96/* Address of a task_struct on the list of all tasks */
97unsigned long TaskAddress = 0x104;
98
99/* Address of the struct page of the first page in memory */
100unsigned long MemMapAddr;
101
102extern unsigned long HighSymbolAddr;
103
104/* Maco for printing some number of spaces */
105static char *blanksP =
106"                                                                            ";
107#define BLANKS(n) (blanksP + strlen(blanksP) - (n))
108
109/* A structure to keep track of current position when stepping through
110   all threads. */
111struct threadIter
112{
113  unsigned long taskAddr, threadAddr;
114  struct task_struct *taskP, *threadP;
115};
116
117
118/* initialize thread iterator */
119static void tiInit(struct threadIter *ti)
120{
121  ti->taskAddr = ti->threadAddr = TaskAddress;
122  ti->taskP = ti->threadP = GetTaskStruct(ti->taskAddr);
123}
124
125unsigned long GetOffset(int fMap)
126{
127#if defined(GPFS_ARCH_X86_64) && LINUX_KERNEL_VERSION >= 2061600
128  /* rw_verify_area does not allow kernel addr range,
129     so a read() will fail with EINVAL.  We subtract the base
130     base kernel addr here and add it back in the read file op in
131     tracelin.c */
132  if (fMap)
133    return(__START_KERNEL_map);
134  else
135    return(__PAGE_OFFSET);
136#else
137  return(0);
138#endif
139}
140
141/* Free threadIter memory.  If tiNext returns false, then it isn't necessary
142   to call this. */
143static void tiDone(struct threadIter *ti)
144{
145  kFree(ti->taskP);
146  if (ti->threadP != ti->taskP)
147    kFree(ti->threadP);
148  ti->taskP = ti->threadP = NULL; 
149}
150
151
152/* Step to next thread in current task.  If no more threads, step to
153   next task.  If no more tasks, return false. */
154static Boolean tiNext(struct threadIter *ti)
155{
156#if LINUX_KERNEL_VERSION >= 2060000
157
158#if LINUX_KERNEL_VERSION < 2060900
159  unsigned long pidAddr, headAddr, nextAddr;
160  struct pid_link *linkP;
161
162  assert(ti->taskP != NULL);
163  linkP = &ti->threadP->pids[PIDTYPE_TGID];
164
165  pidAddr = (unsigned long) linkP->pidptr;
166  headAddr = pidAddr + offsetof(struct pid, task_list);
167
168  nextAddr = (unsigned long) linkP->pid_chain.next;
169
170  if (nextAddr == headAddr)
171  {
172    struct pid *pidP = GenericGet(pidAddr, sizeof(struct pid), 0);
173    nextAddr = (unsigned long) pidP->task_list.next;
174    kFree(pidP);
175  }
176#else
177  //unsigned long nextAddr;
178  //nextAddr = (unsigned long) ti->threadP->pids[PIDTYPE_TGID].pid_list.next;
179#endif
180
181  //ti->threadAddr = (unsigned long) pid_task((struct list_head *) nextAddr,
182  //                                          PIDTYPE_TGID);
183  ti->threadAddr = (unsigned long) next_thread(ti->threadP); 
184  if (ti->threadAddr != ti->taskAddr)
185  {
186    if (ti->threadP != ti->taskP)
187      kFree(ti->threadP);
188    ti->threadP = GetTaskStruct(ti->threadAddr);
189  }
190  else
191  {
192    ti->taskAddr = ti->threadAddr = (unsigned long) NEXT_TASK(ti->taskP);
193    kFree(ti->taskP);
194    if (ti->threadP != ti->taskP)
195      kFree(ti->threadP);
196    ti->taskP = ti->threadP = (ti->taskAddr == TaskAddress) ?
197      NULL : GetTaskStruct(ti->taskAddr);
198  }
199
200  return ti->threadP != NULL;
201#else
202  assert(ti->taskP != NULL);
203  ti->taskAddr = ti->threadAddr = (unsigned long) NEXT_TASK(ti->taskP);
204  kFree(ti->taskP);
205  ti->taskP = ti->threadP = (ti->taskAddr == TaskAddress) ?
206    NULL : GetTaskStruct(ti->taskAddr);
207
208  return ti->threadP != NULL;
209#endif
210}
211
212
213/* Routine to initialize stuff needing access to kernel declarations */
214void KernInit()
215{
216  struct Symbol* sP;
217  int rc;
218  struct vm_struct * vmlist;
219  struct vm_struct v;
220  struct vmStruct* aListP;
221  struct vmStruct** prevPP;
222  unsigned long highMem;
223  unsigned long endAddr;
224
225  /* Set bounds of valid kernel memory */
226  sP = LookupSymbolByName("_stext");
227  assert(sP != 0);
228  LowKernelAddr = sP->addr;
229#if defined(GPFS_ARCH_I386) || defined(GPFS_ARCH_X86_64)
230  LowKernelAddr = PAGE_OFFSET;
231#endif
232
233  rc = GetSymbolValue("high_memory", &highMem, sizeof(HighKernelAddr));
234  assert(rc == 0);
235
236  sP = LookupSymbolByName("_end");
237  assert(sP != 0);
238
239  endAddr = sP->addr;
240  if (endAddr > highMem)
241    HighKernelAddr = endAddr;
242  else
243    HighKernelAddr = highMem;
244
245  if (!isCore)
246  {
247    /* Traverse vm_struct list in kernel starting at vmlist and build
248       corresponding list of vmStructs describing valid kernel addresses */
249    rc = GetSymbolValue("vmlist", &vmlist, sizeof(vmlist));
250    assert(rc == 0);
251
252    vmListHeadP = NULL;
253    prevPP = &vmListHeadP;
254    while (vmlist != NULL)
255    {
256      rc = ReadKernel((unsigned long)vmlist, &v, sizeof(v), 0);
257      assert(rc == 0);
258      aListP = (struct vmStruct*) kMalloc(sizeof(struct vmStruct));
259      assert(aListP != NULL);
260      DBG(printf("vm_struct addr 0x%lX size %d\n", v.addr, v.size));
261      aListP->startAddr = (unsigned long) v.addr;
262      aListP->areaLen = (unsigned long) v.size - PAGE_SIZE;
263      aListP->nextAreaP = NULL;
264      *prevPP = aListP;
265      prevPP = &aListP->nextAreaP;
266      vmlist = v.next;
267    }
268  }
269
270  /* Get address of super_blocks, the head of the list of super_blocks
271     threaded through the s_list field */
272  sP = LookupSymbolByName("super_blocks");
273  if (sP != NULL)
274    super_blocks_addr = sP->addr;
275
276  /* Get address of a task_struct on the list of all tasks */
277  sP = LookupSymbolByName("init_task_union");
278  if (sP == NULL)
279    sP = LookupSymbolByName("init_task");
280  assert(sP != NULL);
281  TaskAddress = sP->addr;
282
283  /* Get address of the base of the array of struct pages */
284#ifndef CONFIG_DISCONTIGMEM
285  rc = GetSymbolValue("mem_map", &MemMapAddr, sizeof(MemMapAddr));
286  assert(rc == 0);
287#else
288  MemMapAddr = 0;
289#endif
290}
291
292
293/* Generic get routine for kernel objects.  Mallocs storage of the
294   given size, then reads into the malloc'ed storage from the
295   kernel address.  Frees the object and returns NULL if the address
296   was invalid. */
297void* GenericGet(unsigned long addr, int len, int fMap)
298{
299  int rc;
300  void* p;
301
302  DBG(printf("GenericGet: addr 0x%lX len %d\n", addr, len));
303  p = kMalloc(len);
304  assert(p != NULL);
305  rc = ReadKernel(addr, p, len, fMap);
306  if (rc != 0)
307  {
308    kFree(p);
309    return NULL;
310  }
311  return p;
312}
313
314
315/* Read a dentry from the kernel.  Space may need to be allocated for the
316   name string. */
317void* GetDentry(unsigned long addr)
318{
319  struct dentry* dP;
320  char* nameP;
321  int rc;
322
323  dP = (struct dentry*) GenericGet(addr, sizeof(struct dentry), 0);
324  if (dP != NULL)
325  {
326    if (dP->d_name.len > 1024)
327    {
328      kFree(dP);
329      return NULL;
330    }
331    else if (dname_external(dP))
332      dP->d_name.name = dP->d_iname;
333    else
334    {
335      nameP = (char*) kMalloc(dP->d_name.len+1);
336      assert(nameP != NULL);
337      rc = ReadKernel((unsigned long)dP->d_name.name, nameP, dP->d_name.len+1, 0);
338      if (rc != 0)
339      {
340        kFree(nameP);
341        kFree(dP);
342        return NULL;
343      }
344      dP->d_name.name = nameP;
345    }
346  }
347  return dP;
348}
349
350
351/* Free a dentry, including the name string */
352void FreeDentry(void* p)
353{
354  struct dentry* dP = (struct dentry*) p;
355
356  if (dP == NULL)
357    return;
358  if (dname_external(dP))
359    kFree((void*)dP->d_name.name);
360  kFree(dP);
361}
362
363
364/* Read an inode from the kernel */
365void* GetInode(unsigned long addr)
366{
367  return GenericGet(addr, sizeof(struct inode), 0);
368}
369
370/* Read an vfsmount from the kernel */
371void* GetVFSMount(unsigned long addr)
372{
373  return GenericGet(addr, sizeof(struct vfsmount), 0);
374}
375
376/* Read an fs_struct from the kernel */
377void* GetFSStruct(unsigned long addr)
378{
379  return GenericGet(addr, sizeof(struct fs_struct), 0);
380}
381
382/* Read a superblock from the kernel */
383void* GetSuperBlock(unsigned long addr)
384{
385  return GenericGet(addr, sizeof(struct super_block), 0);
386}
387
388
389/* Read first superblock on the superblock list */
390void * 
391GetRootSuperBlock(unsigned long * addrP)
392{
393  struct list_head *listP;
394
395  listP = (struct list_head *)GenericGet(super_blocks_addr, 
396                                         sizeof(struct list_head), 1);
397  if (listP == NULL)
398  {
399    *addrP = 0;
400    return NULL;
401  }
402
403  if ((unsigned long)listP->next == super_blocks_addr)
404  {
405    /* super block list is empty */
406    *addrP = 0;
407    return NULL;
408  }
409
410  *addrP = (unsigned long)list_entry(listP->next, struct super_block, s_list);
411
412  return GetSuperBlock(*addrP);
413}
414
415
416/* Read a struct page from the kernel */
417void* GetPage(unsigned long addr)
418{
419  return GenericGet(addr, sizeof(struct page), 0);
420}
421
422
423/* Read an address_space from the kernel */
424void* GetAddressSpace(unsigned long addr)
425{
426  return GenericGet(addr, sizeof(struct address_space), 0);
427}
428
429
430/* Read a vm_area_struct from the kernel */
431void* GetVMAreaStruct(unsigned long addr)
432{
433  return GenericGet(addr, sizeof(struct vm_area_struct), 0);
434}
435
436
437/* Read an mm_struct from the kernel */
438void* GetMMStruct(unsigned long addr)
439{
440  return GenericGet(addr, sizeof(struct mm_struct), 0);
441}
442
443
444/* Read a task_struct from the kernel */
445void* GetTaskStruct(unsigned long addr)
446{
447  return GenericGet(addr, sizeof(struct task_struct), addr == TaskAddress?1:0);
448}
449
450
451/* Read a task_struct from the kernel given its pid */
452void* GetTaskStructByPID(unsigned long pid, unsigned long * addrP)
453{
454  struct threadIter ti;
455  struct task_struct *taskP;
456  tiInit(&ti);
457
458  do
459  {
460    if (ti.threadP->pid == pid)
461    {
462      *addrP = ti.threadAddr;
463      taskP = ti.threadP;
464      ti.threadP = NULL;
465      if (ti.taskP == taskP)
466        ti.taskP = NULL;
467      tiDone(&ti);
468      return taskP;
469    }
470  } while (tiNext(&ti));
471
472  fprintf(stderr, "PID %ld not found\n", pid);
473  return NULL;
474}
475
476
477/* Print a dentry.  Parameter may be NULL. */
478void 
479PrintDentry(void* parm, unsigned long addr)
480{
481  struct dentry* dP = (struct dentry*) parm;
482
483  if (dP == NULL)
484  {
485    fprintf(stderr, "NULL dentry\n");
486    return;
487  }
488
489  printf("dentry 0x%lX:\n", addr);
490
491  if (DumpMemoryCast(addr, "dentry"))
492    DumpMemory((char*)dP, sizeof(struct dentry), addr, DUMPMEM_I4);
493}
494
495
496#define FIELD_ADDR(_ptr, _addr, _field) \
497  (_addr + (unsigned long)((char *)&(_ptr)->_field - (char *)(_ptr)))
498
499/* Recursively show given dentry and all its descendants */
500static void PrintDentryTreeRecur(struct dentry* dP, unsigned long addr,
501                                 unsigned long parentAddr, int level)
502{
503  char *indent = BLANKS(2*level);
504  unsigned long h;
505  unsigned long childAddr;
506  unsigned long ipAddr;
507  struct list_head *listP;
508  struct inode *iP = NULL;
509  int nMax = 50;
510
511  ipAddr = (unsigned long)dP->d_inode;
512  if (ipAddr)
513    iP = (struct inode *)GetInode(ipAddr);
514
515#if LINUX_KERNEL_VERSION < 2060000
516  printf("%sdentry 0x%lX: d_inode %d i_count %d "
517         "d_count %d h_next 0x%lX h_prev 0x%lX d_name \"%s\"\n",
518         indent, addr, (iP ? iP->i_ino : 0), 
519         (iP ? atomic_read(&iP->i_count) : 0), dP->d_count, 
520         dP->d_hash.next, dP->d_hash.prev, dP->d_name.name);
521#else
522  printf("%sdentry 0x%lX: d_inode %d i_count %d "
523         "d_count %d h_next 0x%lX h_pprev 0x%lX d_name \"%s\"\n",
524         indent, addr, (iP ? iP->i_ino : 0),
525         (iP ? atomic_read(&iP->i_count) : 0), dP->d_count, 
526         dP->d_hash.next, dP->d_hash.pprev, dP->d_name.name);
527#endif
528
529  if ((unsigned long)dP->d_parent != parentAddr)
530    fprintf(stderr, "%sbad d_parent dentry 0x%lX !!!\n",
531           indent, dP->d_parent);
532
533  /* prevent infinite recursion */
534  if (level > 100)
535  {
536    fprintf(stderr, "%srecursion too deep !!!\n");
537    return;
538  }
539
540  h = FIELD_ADDR(dP, addr, d_subdirs);
541  listP = dP->d_subdirs.next;
542  while ((unsigned long)listP != h)
543  {
544    childAddr = (unsigned long)list_entry(listP, struct dentry, d_child);
545    dP = (struct dentry*)GetDentry(childAddr);
546    if (dP == NULL)
547    {
548      fprintf(stderr, "%s  could not get dentry 0x%lX !!!\n", indent, 
549              childAddr);
550      break;
551    }
552    PrintDentryTreeRecur(dP, childAddr, addr, level + 1);
553    listP = dP->d_child.next;
554
555    /* prevent infinite loop */
556    nMax--;
557    if (nMax == 0)
558    {
559      fprintf(stderr, "%s  too many children !!!\n", indent);
560      break;
561    }
562  }
563}
564
565/* Show given dentry and all its descendants */
566void PrintDentryTree(void* parm, unsigned long addr)
567{
568  if (parm == 0)
569  {
570    fprintf(stderr, "NULL dentry\n");
571    return;
572  }
573  PrintDentryTreeRecur((struct dentry*)parm, addr, 
574                       (unsigned long)(((struct dentry*)parm)->d_parent), 0);
575}
576
577void PrintFSStruct(void *parm, unsigned long addr)
578{
579  if (parm == NULL)
580  {
581    fprintf(stderr, "NULL fs_struct\n");
582    return;
583  }
584  if (DumpMemoryCast(addr, "fs_struct"))
585    DumpMemory((char*)parm, sizeof(struct fs_struct), addr, DUMPMEM_I4);
586}
587
588void PrintVFSMount(void *parm, unsigned long addr)
589{
590  if (parm == NULL)
591  {
592    fprintf(stderr, "NULL vfsmount\n");
593    return;
594  }
595  if (DumpMemoryCast(addr, "vfsmount"))
596    DumpMemory((char*)parm, sizeof(struct vfsmount), addr, DUMPMEM_I4);
597}
598
599void 
600PrintVFSMountList(void *parm, unsigned long addr)
601{
602  struct vfsmount *vfsP = (struct vfsmount *)parm;
603  struct list_head *listP;
604  char *devnameP;
605  unsigned long h;
606  unsigned long next;
607 
608  if (vfsP == NULL)
609  {
610    fprintf(stderr, "NULL vfsmount\n");
611    return;
612  }
613
614  devnameP = (char *)GenericGet((unsigned long)vfsP->mnt_devname, 20, 0);
615  printf("vfsmount 0x%lX: mnt_count %5d mnt_devname %20s\n",
616         addr, vfsP->mnt_count, devnameP);
617
618  h = FIELD_ADDR(vfsP, addr, mnt_list);
619  listP = vfsP->mnt_list.next;
620  while ((unsigned long)listP != h)
621  {
622    next = (unsigned long)list_entry(listP, struct vfsmount, mnt_list);
623    vfsP = (struct vfsmount *)GetVFSMount(next);
624    if (vfsP == NULL)
625    {
626      fprintf(stderr, "Could not get vfsmount 0x%lX !!!\n", next);
627      return;
628    }
629
630    devnameP = (char *)GenericGet((unsigned long)vfsP->mnt_devname, 20, 0);
631    printf("vfsmount 0x%lX: mnt_count %5d mnt_devname %20s\n",
632           next, vfsP->mnt_count, devnameP);
633
634    listP = vfsP->mnt_list.next;
635  }
636}
637
638/* Print an inode.  Parameter may be NULL. */
639void PrintInode(void* parm, unsigned long addr)
640{
641  struct inode* iP = (struct inode*) parm;
642
643  if (iP == NULL)
644  {
645    fprintf(stderr, "NULL inode\n");
646    return;
647  }
648
649  printf("inode 0x%lX:\n", addr);
650
651  if (DumpMemoryCast(addr, "inode"))
652    DumpMemory((char*)iP, sizeof(struct inode), addr, DUMPMEM_I4);
653}
654
655
656/* Print a super_block.  Parameter may be NULL. */
657void PrintSuperBlock(void* parm, unsigned long addr)
658{
659  struct super_block* sP = (struct super_block*) parm;
660  if (sP == NULL)
661  {
662    fprintf(stderr, "NULL super_block\n");
663    return;
664  }
665
666  printf("super_block 0x%lX:\n", addr);
667
668  if (DumpMemoryCast(addr, "super_block"))
669    DumpMemory((char*)sP, sizeof(struct super_block), addr, DUMPMEM_I4);
670}
671
672
673/* Print a page struct.  Parameter may be NULL. */
674void PrintPage(void* parm, unsigned long addr)
675{
676  struct page* pageP = (struct page*) parm;
677
678  if (pageP == NULL)
679  {
680    fprintf(stderr, "NULL page\n");
681    return;
682  }
683  printf("page 0x%lX (frame number 0x%lX):\n",
684         addr, (addr-MemMapAddr)/sizeof(struct page));
685
686  if (DumpMemoryCast(addr, "page"))
687    DumpMemory((char*)pageP, sizeof(struct page), addr, DUMPMEM_I4);
688}
689
690
691/* Print an address_space struct.  Parameter may be NULL. */
692void PrintAddressSpace(void* parm, unsigned long addr)
693{
694  struct address_space* asP = (struct address_space*) parm;
695
696  if (asP == NULL)
697  {
698    fprintf(stderr, "NULL address_space\n");
699    return;
700  }
701
702  printf("address_space 0x%lX:\n", addr);
703
704  if (DumpMemoryCast(addr, "address_space"))
705    DumpMemory((char*)asP, sizeof(struct address_space), addr, DUMPMEM_I4);
706}
707
708
709/* Print a vm_area_struct struct.  Parameter may be NULL. */
710void PrintVMAreaStruct(void* parm, unsigned long addr)
711{
712  struct vm_area_struct* vmP = (struct vm_area_struct*) parm;
713
714  if (vmP == NULL)
715  {
716    fprintf(stderr, "NULL vm_area_struct\n");
717    return;
718  }
719
720  printf("vm_area_struct 0x%lX:\n", addr);
721
722  if (DumpMemoryCast(addr, "vm_area_struct"))
723    DumpMemory((char*)vmP, sizeof(struct vm_area_struct), addr, DUMPMEM_I4);
724}
725
726
727/* Print an mm_struct struct.  Parameter may be NULL. */
728void PrintMMStruct(void* parm, unsigned long addr)
729{
730  struct mm_struct* mmP = (struct mm_struct*) parm;
731
732  if (mmP == NULL)
733  {
734    fprintf(stderr, "NULL mm_struct\n");
735    return;
736  }
737
738  printf("mm_struct 0x%lX:\n", addr);
739
740  if (DumpMemoryCast(addr, "mm_struct"))
741    DumpMemory((char*)mmP, sizeof(struct mm_struct), addr, DUMPMEM_I4);
742}
743
744
745/* Print an task_struct struct.  Parameter may be NULL. */
746void PrintTaskStruct(void* parm, unsigned long addr)
747{
748  struct task_struct* taskP = (struct task_struct*) parm;
749
750  if (taskP == NULL)
751  {
752    fprintf(stderr, "NULL task_struct\n");
753    return;
754  }
755
756  printf("task_struct 0x%lX:\n", addr);
757
758  if (DumpMemoryCast(addr, "task_struct"))
759    DumpMemory((char*)taskP, sizeof(struct task_struct), addr, DUMPMEM_I4);
760}
761
762#ifndef GPFS_ARCH_I386
763void VirtToReal(unsigned long pgdAddr, unsigned long vaddr)
764{
765  fprintf(stderr, "Not implemented.");
766}
767#else
768/* Display page table flag bits */
769static void ShowFlagBits(unsigned long f)
770{
771  if (f & _PAGE_PRESENT)  printf(" present");
772  if (f & _PAGE_RW)       printf(" RW");
773  if (f & _PAGE_USER)     printf(" user");
774  if (f & _PAGE_PWT)      printf(" PWT");
775  if (f & _PAGE_PCD)      printf(" PCD");
776  if (f & _PAGE_ACCESSED) printf(" accessed");
777  if (f & _PAGE_DIRTY)    printf(" dirty");
778  if (f & _PAGE_PSE)      printf(" 4M");
779  if (f & _PAGE_GLOBAL)   printf(" global");
780  printf("\n");
781}
782
783
784/* Translate vaddr using pgd at addr */
785void VirtToReal(unsigned long pgdAddr, unsigned long vaddr)
786{
787  pgd_t* pgdP;
788  unsigned long pgdIndex;
789  pgd_t pgdEntry;
790  unsigned long pgdVal;
791
792  unsigned long pmdAddr;
793  pmd_t* pmdP;
794  pmd_t pmdEntry;
795  unsigned long pmdVal;
796  unsigned long pageNumber;
797
798  unsigned long pteAddr;
799  unsigned long pteIndex;
800  pte_t* pteP;
801  pte_t pteEntry;
802  unsigned long pteVal;
803
804#if defined(CONFIG_X86_PAE)
805  fprintf(stderr, "Could not read pmd\n");
806  return;
807#else
808  pgdIndex = pgd_index(vaddr);
809  pgdAddr = (unsigned long)(((pgd_t*)pgdAddr) + pgdIndex);
810  pgdP = (pgd_t*)GenericGet(pgdAddr, sizeof(*pgdP), 0);
811  if (pgdP == NULL)
812  {
813    fprintf(stderr, "Could not read pgd\n");
814    return;
815  }
816  pgdEntry = *pgdP;
817  CondFree(pgdP);
818  pgdVal = pgd_val(pgdEntry);
819  printf("pgdAddr 0x%lX pgd entry 0x%lX", pgdAddr, pgdVal);
820  ShowFlagBits(pgdVal);
821  if (!(pgdVal & _PAGE_PRESENT))
822  {
823    fprintf(stderr, "PGD not present\n");
824    return;
825  }
826
827  pmdAddr = (unsigned long) pmd_offset((void*)pgdAddr, vaddr);
828  /* Above only works for two level page tables, because the code for
829     3-level tables actually dereferences pgdAddr, which we cannot do
830     from this user-level program. */
831  pmdP = (pmd_t*)GenericGet(pmdAddr, sizeof(*pmdP), 0);
832  if (pmdP == NULL)
833  {
834    fprintf(stderr, "Could not read pmd\n");
835    return;
836  }
837  pmdEntry = *pmdP;
838  CondFree(pmdP);
839  pmdVal = pmd_val(pmdEntry);
840  printf("pmdAddr 0x%lX pmd entry 0x%lX", pmdAddr, pmdVal);
841  ShowFlagBits(pmdVal);
842  if (!(pmdVal & _PAGE_PRESENT))
843  {
844    fprintf(stderr, "PMD not present\n");
845    return;
846  }
847
848  if (pmdVal & _PAGE_PSE)
849  {
850    pageNumber = (pgdVal>>PAGE_SHIFT) + ((vaddr & (PGDIR_SIZE-1))>>PAGE_SHIFT);
851    printf("vaddr 0x%lX pageNumber 0x%lX page 0x%lX\n",
852           vaddr, pageNumber, MemMapAddr + pageNumber*sizeof(struct page));
853    return;
854  }
855
856  pteAddr = (unsigned long) __va(pmdVal & PAGE_MASK);
857#if LINUX_KERNEL_VERSION >= 2060000
858  pteIndex = pte_index(vaddr);
859#else
860  pteIndex = __pte_offset(vaddr);
861#endif
862  pteAddr = (unsigned long)(((pte_t*)pteAddr) + pteIndex);
863  pteP = (pte_t*)GenericGet(pteAddr, sizeof(pte_t), 0);
864  pteEntry = *pteP;
865  CondFree(pteP);
866  pteVal = pte_val(pteEntry);
867  printf("pteAddr 0x%lX pte entry 0x%lX", pteAddr, pteVal);
868  ShowFlagBits(pteVal);
869  if (!pte_present(pteEntry))
870  {
871    fprintf(stderr, "PTE not present\n");
872    return;
873  }
874
875  pageNumber = pteVal >> PAGE_SHIFT;
876  printf("vaddr 0x%lX pageNumber 0x%lX page 0x%lX\n",
877         vaddr, pageNumber, MemMapAddr + pageNumber*sizeof(struct page));
878#endif
879}
880#endif  /* GPFS_ARCH_I386 */
881
882void DoPs(void)
883{
884  struct threadIter ti;
885  tiInit(&ti);
886
887  printf("task addr      PID        state    name\n");
888  do
889  {
890    printf("0x%08lX    %8d    %0lX   %s%s\n",
891           ti.threadAddr, ti.threadP->pid, ti.threadP->state,
892           (ti.threadAddr == ti.taskAddr) ? "" : "    ", ti.threadP->comm);
893  } while (tiNext(&ti));
894}
895
896void PrintTraceback(struct task_struct* taskP)
897{
898#ifdef GPFS_ARCH_I386
899  unsigned long esp, esp2, stackWord, *p, offset, count;
900  struct Symbol* sP;
901
902  esp = taskP->thread.esp;
903
904  printf("\nStack for process %d (%s):\n", taskP->pid, taskP->comm);
905  while ((esp & (THREAD_SIZE-1)))
906  {
907    /* debug kernel may have odd esp offset */
908    for (esp2=esp, count=sizeof(taskP->thread.esp); count > 0;count--, esp2++)
909      if (!(esp2 & (THREAD_SIZE-1)))
910         break;
911    if (count > 0)
912  break;
913
914    p = (unsigned long*)GenericGet(esp++, sizeof(esp), 0);
915    if (p == NULL)
916    {
917      printf(" NULL stackWord pointer\n");
918      break;
919    }
920    stackWord = *p;
921    if (stackWord >= LowKernelAddr && stackWord <= HighSymbolAddr)
922    {
923      sP = LookupSymbolByAddr(stackWord);
924      assert(sP != NULL);
925      if (sP->flags & FL_TEXT)
926      {
927        offset = stackWord - sP->addr;
928        printf(" 0x%0lX  %s + 0x%X\n", stackWord, sP->nameP, offset);
929      }
930    }
931/*
932    else
933      printf(" [%08lX]", stackWord);
934*/
935    kFree(p);
936  }
937  printf("\n");
938#elif defined(GPFS_ARCH_PPC64)
939  struct bt_stack_frame
940  {
941    struct bt_stack_frame* next;
942    long cr;
943    void *ret_addr;
944  };
945  struct bt_stack_frame* frameP = NULL;
946  struct pt_regs *regs;
947  unsigned long ip, *p, offset, frameAddr;
948  struct Symbol* sP;
949  int rc;
950
951  frameAddr = taskP->thread.ksp;
952
953  printf("\nStack for process %d (%s):\n", taskP->pid, taskP->comm);
954  while ( frameAddr > PAGE_OFFSET )
955  {
956    frameP = (struct bt_stack_frame*)GenericGet(frameAddr,
957                                       sizeof(struct bt_stack_frame), 0);
958    if (frameP == NULL)
959    {
960      printf(" NULL stack frame pointer\n");
961      break;
962    }
963    ip = (unsigned long)frameP->ret_addr;
964    if (ip != 0)
965    {
966      sP = LookupSymbolByAddr(ip);
967      if ( (sP->flags & FL_TEXT) )
968      {
969        offset = ip - sP->addr;
970        printf("%0p 0x%016lX  %s + 0x%X\n", frameAddr, ip, sP->nameP, offset);
971      }
972    }
973    frameAddr = (unsigned long)(frameP->next);
974    kFree((unsigned long*)frameP);
975  }
976#elif defined(GPFS_ARCH_X86_64) && LINUX_KERNEL_VERSION >= 2060000
977  unsigned long rsp, stackWord, *p, offset, count;
978  struct Symbol* sP;
979
980  rsp = taskP->thread.rsp;
981
982  printf("\nStack for process %d (%s):\n", taskP->pid, taskP->comm);
983  while ((rsp & (THREAD_SIZE-1)))
984  {
985    p = (unsigned long*)GenericGet(rsp++, sizeof(rsp), 0);
986    if (p == NULL)
987    {
988      printf(" NULL stackWord pointer\n");
989      break;
990    }
991    stackWord = *p;
992    if (stackWord >= LowKernelAddr && stackWord <= HighSymbolAddr)
993    {
994      sP = LookupSymbolByAddr(stackWord);
995      assert(sP != NULL);
996      if (sP->flags & FL_TEXT)
997      {
998        offset = stackWord - sP->addr;
999        printf(" 0x%0lX  %s + 0x%X\n", stackWord, sP->nameP, offset);
1000      }
1001    }
1002/*
1003    else
1004      printf(" [%08lX]", stackWord);
1005*/
1006    kFree(p);
1007  }
1008  printf("\n");
1009#endif
1010}
1011
1012/* Print kernel traceback for a particular process.  pid == -1
1013 * means all processes
1014 */
1015void BacktracePid(unsigned long pid)
1016{
1017  struct threadIter ti;
1018  tiInit(&ti);
1019
1020  do
1021  {
1022    if (pid == -1 || ti.threadP->pid == pid)
1023    {
1024      PrintTraceback(ti.threadP);
1025      if (pid != -1)
1026      {
1027        tiDone(&ti);
1028        return;
1029      }
1030    }
1031  } while (tiNext(&ti));
1032
1033  if (pid != -1)
1034    fprintf(stderr, "PID %ld not found\n", pid);
1035}
1036
1037void BacktraceAll(void)
1038{
1039  BacktracePid(-1);
1040}
1041
1042static struct elf_prstatus prstatus;
1043static struct elf_prpsinfo prpsinfo;
1044
1045struct memelfnote
1046{
1047  char *name;
1048  int type;
1049  unsigned int datasize;
1050  void *data;
1051};
1052
1053#define ROUNDUP(_addr, _align) ( (_addr + (_align - 1))/_align * _align)
1054
1055void ReadElfNote(struct memelfnote* memnote)
1056{
1057  struct elf_note note;
1058  int len;
1059
1060  readCore(&note, sizeof(note));
1061
1062  memnote->type = note.n_type;
1063  len = ROUNDUP(note.n_namesz, 4);
1064  memnote->name = (char*)kMalloc(len);
1065  assert(memnote->name != NULL);
1066  readCore(memnote->name, len);
1067  memnote->name[note.n_namesz] = '\0';
1068
1069  len = ROUNDUP(note.n_descsz, 4);
1070  memnote->datasize = note.n_descsz;
1071  memnote->data = kMalloc(len);
1072  assert(memnote->data != NULL);
1073  memset(memnote->data, 0, len);
1074  readCore(memnote->data, len);
1075}
1076
1077
1078void ReadKernelCore(char* corefile)
1079{
1080  int i; 
1081  struct elfhdr hdr;
1082  struct elf_phdr phdr_note, phdr_load;
1083  struct memelfnote status_note, psinfo_note, taskstruct_note;
1084  struct vmStruct* aListP;
1085  struct vmStruct** prevPP;
1086
1087  printf("Reading ELF core file %s...\n", corefile);
1088  isCore = 1;
1089  openCore(corefile);
1090  readCore(&hdr, sizeof(hdr));
1091
1092  assert(hdr.e_type == ET_CORE);
1093  assert(hdr.e_version == EV_CURRENT);
1094  assert(elf_check_arch(&hdr));
1095  assert(hdr.e_ehsize == sizeof(struct elfhdr));
1096  assert(hdr.e_phentsize == sizeof(struct elf_phdr));
1097
1098  readCore(&phdr_note, sizeof(phdr_note));
1099
1100  vmListHeadP = NULL;
1101  prevPP = &vmListHeadP;
1102  for (i = 0; i < hdr.e_phnum - 1; i++)
1103  {
1104    readCore(&phdr_load, sizeof(phdr_note));
1105    if (phdr_load.p_type & PT_LOAD)
1106    {
1107      aListP = (struct vmStruct*) kMalloc(sizeof(struct vmStruct));
1108      assert(aListP != NULL);
1109      aListP->startAddr = phdr_load.p_vaddr;
1110      aListP->areaLen = phdr_load.p_memsz;
1111      aListP->file_offset = phdr_load.p_offset;
1112      aListP->nextAreaP = NULL;
1113      *prevPP = aListP;
1114      prevPP = &aListP->nextAreaP;
1115    }
1116  }
1117
1118  seekCore(phdr_note.p_offset);
1119  ReadElfNote(&status_note);
1120  assert(status_note.type == NT_PRSTATUS);
1121  cxiMemcpy(&prstatus, status_note.data, sizeof(prstatus));
1122
1123  ReadElfNote(&psinfo_note);
1124  assert(psinfo_note.type == NT_PRPSINFO);
1125  cxiMemcpy(&prpsinfo, psinfo_note.data, sizeof(prpsinfo));
1126
1127  ReadElfNote(&taskstruct_note);
1128  assert(taskstruct_note.type == NT_TASKSTRUCT);
1129
1130#ifdef GPFS_ARCH_I386
1131#define REG(_a) prstatus.pr_reg[_a]
1132  printf("Registers:\n");
1133  printf("eax: %08lX ebx: %08lX ecx: %08lX edx: %08lX\n", 
1134         REG(6), REG(0), REG(1), REG(2));
1135  printf("esi: %08lX edi: %08lX ebp: %08lX esp: %08lX\n", 
1136         REG(3), REG(4), REG(5), REG(15));
1137  printf("eip: %08lX eflags: %08lX\n", 
1138         REG(12), REG(14));
1139#undef REG
1140#endif
1141}
1142#endif
Note: See TracBrowser for help on using the repository browser.