lkcd
[Top] [All Lists]

module traceback working

To: lkcd@xxxxxxxxxxx
Subject: module traceback working
From: Dave Craft <dcraft@xxxxxxxxxxxxxx>
Date: Thu, 25 Jan 2001 15:57:30 -0600 (CST)
Sender: owner-lkcd@xxxxxxxxxxx
The other day I posted a query regarding how to get trace backs
in kernel module code with lkcd on the i386.  I'm not sure if anyone is
interested in this (since I didn't get any responses) but I have 
made a couple of fixes to the baseline code as well as a minor addition
to get this function to work.  Note this work is just posted herein
and doesn't represent any work by a lkcd maintainer.  I'm not even saying
it's suitable for anything other than my own educational purposes.

I will also append the diff file to the end of this note.  Note that
this diff is just a rough first stab for my own benefit.  The maintainers
of lkcd (given that they know the structure better than I) would
probably want this done differently.

Basically the changes fall into a couple of categories.

1) Bug fixes for page table lookup on the i386:  The KL_PGDIR_SHIFT 
   and KL_PMDIR_SHIFT were wrong for the two level page directory
   case on the i386.  The pmd_offset() function was also wrong for
   this case.

2) Enhancements to kl_virtop() to understand the vmalloc area:
   Essentially linux copies an inserted module to the vmalloc area which
   has an address above the PAGE_OFFSET line (0xc000000 on my machine) 
   but it is also above physical memory.  Thus to get the real physical
   address for these pages you must use the page directory hung off
   the "init_mm" memory map struct.  So the changes in this area
   are just to get the range of the vmalloc area and use the "init_mm"
   info.

After you fix this in lcrash you have to run it with a System.map
that has the additional symbols from your module.  You can get your
modules symbol table at load time by using the -m option on insmod.
Note you have to strip out all the extraneous stuff out of this map.

  cat <module>.map | awk '/ [TtDd] / {print $0}' >> tmp.map

Then append this to a new COPY of the /boot/System.map and do
(sort -u) on the file.   You can give lcrash this file as an 
option or just link /boot/System.map to your new symbol file.

At that point you should be able to do a "bt" on a task that
has a traceback into module routines.

If anyone wants to discuss my poor attempt at getting this working
or the defect fixes, just send me a note.

Enjoy,
Dave Craft

-----------cut here for patch file----------
diff -Naur lkcd/lkcdutils/libklib/arch/i386/kl_kern.c 
lkcdmod/lkcdutils/libklib/arch/i386/kl_kern.c
--- lkcd/lkcdutils/libklib/arch/i386/kl_kern.c  Tue Jan 16 13:52:56 2001
+++ lkcdmod/lkcdutils/libklib/arch/i386/kl_kern.c       Thu Jan 25 14:29:27 2001
@@ -11,6 +11,7 @@
 #ifndef __KERNEL__
 #define __KERNEL__
 #include <asm/page.h>
+#include <asm/fixmap.h>
 #undef __KERNEL__
 #else
 #endif
@@ -28,6 +29,16 @@
 #endif
 kaddr_t MEM_MAP;
 
+kaddr_t INIT_MM;
+kaddr_t KL_VMALLOC_START = 0xFFFFFFFF;
+kaddr_t KL_VMALLOC_END   = 0xFFFFFFFF;
+
+#define VMALLOC_OFFSET  (8*1024*1024)
+#define VMALLOC_START   (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \
+                                                ~(VMALLOC_OFFSET-1))
+#define VMALLOC_END     (FIXADDR_START)
+
+
 /*
  * kl_init_kern_info()
  */
@@ -35,6 +46,7 @@
 kl_init_kern_info()
 {
        syment_t *sp;
+       kaddr_t high_memory;
 
        kl_reset_error();
        if (!(sp = kl_lkup_symname("num_physpages"))) {
@@ -51,6 +63,19 @@
                return(1);
        }
        GET_BLOCK(sp->s_addr, 4, (void*)&MEM_MAP);
+
+       if (!(sp = kl_lkup_symname("init_mm"))) {
+               return(1);
+       }
+        /* init_mm is a structure offset and not a pointer */
+        INIT_MM = sp->s_addr;
+
+       if (!(sp = kl_lkup_symname("high_memory"))) {
+               return(1);
+       }
+       GET_BLOCK(sp->s_addr, 4, (void*)&high_memory);
+       KL_VMALLOC_START = VMALLOC_START;
+       KL_VMALLOC_END = VMALLOC_END;
 
        if (!(sp = kl_lkup_symname("__locore_lmabegin"))) {
                return(1);
diff -Naur lkcd/lkcdutils/libklib/arch/i386/kl_page.c 
lkcdmod/lkcdutils/libklib/arch/i386/kl_page.c
--- lkcd/lkcdutils/libklib/arch/i386/kl_page.c  Thu Nov 30 20:53:44 2000
+++ lkcdmod/lkcdutils/libklib/arch/i386/kl_page.c       Thu Jan 25 14:20:39 2001
@@ -23,8 +23,8 @@
 
 #else /* CONFIG_X86_PAE */
 
-#define KL_PGDIR_SHIFT (KL_PAGE_SHIFT+(KL_PAGE_SHIFT-3)*1)
-#define KL_PMD_SHIFT   (KL_PAGE_SHIFT+(KL_PAGE_SHIFT-3)*1)
+#define KL_PGDIR_SHIFT (KL_PAGE_SHIFT+(KL_PAGE_SHIFT-2)*1)
+#define KL_PMD_SHIFT   (KL_PAGE_SHIFT+(KL_PAGE_SHIFT-2)*1)
 #define KL_PTRS_PER_PGD (1UL<<(KL_PAGE_SHIFT-2)) 
 #define KL_PTRS_PER_PMD 1
 #define KL_PTRS_PER_PTE (1UL<<(KL_PAGE_SHIFT-2))
@@ -56,7 +56,10 @@
 
        return pte_base;
 #else /* CONFIG_X86_PAE */
-       return pmd_base;
+        /* higher level routines are expecting a non virtual address
+         * offset, which they will add KL_PAGE_OFFSET to.
+         */
+       return pmd_base - KL_PAGE_OFFSET;
 #endif /* CONFIG_X86_PAE */
 }
 
diff -Naur lkcd/lkcdutils/libklib/include/klib.h 
lkcdmod/lkcdutils/libklib/include/klib.h
--- lkcd/lkcdutils/libklib/include/klib.h       Wed Dec  6 15:08:13 2000
+++ lkcdmod/lkcdutils/libklib/include/klib.h    Thu Jan 25 14:34:38 2001
@@ -84,6 +84,15 @@
 extern kaddr_t MEM_MAP;
 extern kaddr_t deftask;
 
+#ifdef DEBUG
+#define DPRINTF(x) fprintf x
+#else
+#define DPRINTF(x)
+#endif
+extern kaddr_t INIT_MM;
+extern kaddr_t KL_VMALLOC_START;
+extern kaddr_t KL_VMALLOC_END;
+
 #define KL_ARCH                 lkcdinfo.arch
 #define KL_PTRSZ                lkcdinfo.ptrsz
 #define KL_NBPW                 (KL_PTRSZ/8)
diff -Naur lkcd/lkcdutils/libklib/kl_mem.c lkcdmod/lkcdutils/libklib/kl_mem.c
--- lkcd/lkcdutils/libklib/kl_mem.c     Thu Nov 30 20:52:16 2000
+++ lkcdmod/lkcdutils/libklib/kl_mem.c  Thu Jan 25 14:33:52 2001
@@ -108,9 +108,19 @@
        if ((KL_ARCH == ARCH_I386) && (vaddr >= KL_LOCORE_START)) {
                paddr = (KL_LOCORE_ADDR - KL_PAGE_OFFSET) + 
                                (vaddr - KL_LOCORE_START);
-       } else if (vaddr >= KL_PAGE_OFFSET) {
+       } else if ((vaddr >= KL_PAGE_OFFSET) && (vaddr < KL_VMALLOC_START)) {
                paddr = (vaddr - KL_PAGE_OFFSET);
        } else {
+               if ((vaddr >= KL_VMALLOC_START) && (vaddr < KL_VMALLOC_END)) {
+                       mmp = kl_alloc_block(MM_STRUCT_SZ, K_TEMP);
+                       GET_BLOCK(INIT_MM, MM_STRUCT_SZ, mmp);
+                       if (KL_ERROR) {
+                               kl_free_block(mmp);
+                               mmp = NULL;
+                       } else {
+                               mm_alloced++;
+                       }
+               }
                if (!mmp && deftask) {
                        tsp = kl_alloc_block(TASK_STRUCT_SZ, K_TEMP);
                        if (tsp) {
@@ -149,5 +159,8 @@
        if (mm_alloced) {
                kl_free_block(mmp);
        }       
+
+        DPRINTF((KL_ERRORFP, "kl_virtop: vaddr 0x%X paddr 0x%X error 0x%X\n", 
+                vaddr, paddr, KL_ERROR));
        return(paddr);
 }

<Prev in Thread] Current Thread [Next in Thread>