---
 lkcd_fix_mem.c |  118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 lkcd_fix_mem.h |    5 ++
 2 files changed, 121 insertions(+), 2 deletions(-)

Index: crash-4.0-3.17/lkcd_fix_mem.h
===================================================================
--- crash-4.0-3.17.orig/lkcd_fix_mem.h
+++ crash-4.0-3.17/lkcd_fix_mem.h
@@ -285,11 +285,16 @@ typedef struct _dump_header_asm_s {
 	/* smp specific */
 	uint32_t	     dha_smp_num_cpus;
 	uint32_t 	     dha_dumping_cpu;	// v4 changed this
+
+	/* if you change something here, you've to change the logic in fix_addr_v8 */
 	struct pt_regs	     dha_smp_regs[NR_CPUS];
 	uint64_t 	     dha_smp_current_task[NR_CPUS]; // v4 changed this 
 	uint64_t     	     dha_stack[NR_CPUS];  // v4 changed this 
 	uint64_t     	     dha_switch_stack[NR_CPUS]; // v4 changed this 
 
+	/* load address of the kernel (added by sles9 patch) */
+	uint64_t             dha_kernel_addr;
+
 } __attribute__((packed)) dump_header_asm_t;
 
 #endif // IA64
Index: crash-4.0-3.17/lkcd_fix_mem.c
===================================================================
--- crash-4.0-3.17.orig/lkcd_fix_mem.c
+++ crash-4.0-3.17/lkcd_fix_mem.c
@@ -21,9 +21,58 @@
 #define LKCD_COMMON
 #include "defs.h"
 #include "lkcd_fix_mem.h"
+#include <stddef.h>
+#include <stdbool.h>
 
 static int fix_addr(dump_header_asm_t *); 
-    
+
+#ifdef IA64
+#define MAGIC_NUMBER_OFFSET  \
+	(offsetof(dump_header_asm_t, dha_magic_number))
+
+#define VERSION_OFFSET \
+	(offsetof(dump_header_asm_t, dha_version))
+
+#define HEADER_SIZE_OFFSET \
+	(offsetof(dump_header_asm_t, dha_header_size))
+
+#define PT_REGS_OFFSET \
+	(offsetof(dump_header_asm_t, dha_pt_regs))
+
+#define REGS_OFFSET \
+	(offsetof(dump_header_asm_t, dha_regs))
+
+#define RNAT_OFFSET \
+	(offsetof(dump_header_asm_t, dha_rnat))
+
+#define PFS_OFFSET \
+	(offsetof(dump_header_asm_t, dha_pfs))
+
+#define BSPSTORE_OFFSET \
+	(offsetof(dump_header_asm_t, dha_bspstore))
+
+#define SMP_NUM_CPUS_OFFSET \
+	(offsetof(dump_header_asm_t, dha_smp_num_cpus))
+
+#define DUMPING_CPU_OFFSET \
+	(offsetof(dump_header_asm_t, dha_dumping_cpu))
+
+#define SMP_REGS_OFFSET \
+	(offsetof(dump_header_asm_t, dha_smp_regs))
+
+#define CURRENT_TASK_OFFSET(cpun) \
+	(SMP_REGS_OFFSET + sizeof(struct pt_regs) * (cpun))
+
+#define STACK_OFFSET(cpun) \
+	(CURRENT_TASK_OFFSET(cpun) + sizeof(uint64_t) * (cpun))
+
+#define SWITCH_STACK_OFFSET(cpun) \
+	(STACK_OFFSET(cpun) + sizeof(uint64_t) * (cpun))
+
+#define KERNEL_ADDR_OFFSET(cpun) \
+	(SWITCH_STACK_OFFSET(cpun) + sizeof(uint64_t) * (cpun))
+#endif
+
 int
 fix_addr_v8(int fd)
 {
@@ -31,9 +80,74 @@ fix_addr_v8(int fd)
     dump_header_asm_t *dha;
     dha = &dump_header_asm_v8;
     
+#ifdef IA64
+    int cpu_num = 0;
+    int cpunum_specific;
+    size_t size;
+    unsigned char *buffer;
+
+    /*
+     * Dynamically load the data from the header. This addresses the problem
+     * that NR_CPUS should be only the MAXIMUM number of CPUs supported by
+     * crash, not necessarily the same as CONFIG_NR_CPUS
+     */
+    size = HEADER_SIZE_OFFSET + sizeof(uint32_t);
+    if (read(lkcd->fd, dha, size) != size)
+        return -1;
+
+    /* read again the whole header */
+    buffer = (unsigned char *)malloc(dha->dha_header_size);
+    if (!buffer)
+        return -1;
+    if (lseek(lkcd->fd, -size, SEEK_CUR) == -1) {
+        free(buffer);
+        return -1;
+    }
+    if (read(lkcd->fd, buffer, dha->dha_header_size) != dha->dha_header_size) {
+        free(buffer);
+        return -1;
+    }
+
+    /* now try to calculate the number of CPUs */
+    cpunum_specific = dha->dha_header_size - SMP_REGS_OFFSET
+        + sizeof(uint64_t);
+    cpu_num = cpunum_specific / (sizeof(struct pt_regs) + 3*sizeof(uint64_t));
+
+    /* fill the other CPU number independent members */
+    memcpy(&dha->dha_pt_regs, buffer + PT_REGS_OFFSET,
+            sizeof(struct pt_regs *));
+    memcpy(&dha->dha_regs, buffer + REGS_OFFSET,
+            sizeof(struct pt_regs));
+    memcpy(&dha->dha_rnat, buffer + RNAT_OFFSET,
+            sizeof(uint64_t));
+    memcpy(&dha->dha_pfs, buffer + PFS_OFFSET,
+            sizeof(uint64_t));
+    memcpy(&dha->dha_bspstore, buffer + BSPSTORE_OFFSET,
+            sizeof(uint64_t));
+    memcpy(&dha->dha_smp_num_cpus, buffer + SMP_NUM_CPUS_OFFSET,
+            sizeof(uint32_t));
+    memcpy(&dha->dha_dumping_cpu, buffer + DUMPING_CPU_OFFSET,
+            sizeof(uint32_t));
+    memcpy(&dha->dha_kernel_addr, buffer + KERNEL_ADDR_OFFSET(cpu_num),
+            sizeof(uint64_t));
+
+    /* now the CPU number dependent things */
+    memcpy(&dha->dha_smp_regs, buffer + SMP_REGS_OFFSET,
+            sizeof(struct pt_regs) * cpu_num);
+    memcpy(&dha->dha_smp_current_task, buffer + CURRENT_TASK_OFFSET(cpu_num),
+            sizeof(uint64_t) * cpu_num);
+    memcpy(&dha->dha_stack, buffer + STACK_OFFSET(cpu_num),
+            sizeof(uint64_t) * cpu_num);
+    memcpy(&dha->dha_switch_stack, buffer + SWITCH_STACK_OFFSET(cpu_num),
+            sizeof(uint64_t) * cpu_num);
+
+    free(buffer);
+
+#else
     if (read(lkcd->fd, dha, sizeof(dump_header_asm_t)) !=
 	    sizeof(dump_header_asm_t))
 	return -1;
+#endif
     
     fix_addr(dha);
 
@@ -61,7 +175,7 @@ fix_addr(dump_header_asm_t *dha)  
 {
     
 
-    if (dha->dha_header_size != sizeof(dump_header_asm_t)) {
+    if (dha->dha_header_size > sizeof(dump_header_asm_t)) {
 	error(INFO, "LKCD machine specific dump header doesn't match crash version\n");
 	error(INFO, "traceback of currently executing threads may not work\n\n");
     }
