Index: crash-4.0-2.33/lkcd_fix_mem.h
===================================================================
--- crash-4.0-2.33.orig/lkcd_fix_mem.h	2006-07-13 20:51:50.000000000 +0200
+++ crash-4.0-2.33/lkcd_fix_mem.h	2007-01-10 15:48:18.000000000 +0100
@@ -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-2.33/lkcd_fix_mem.c
===================================================================
--- crash-4.0-2.33.orig/lkcd_fix_mem.c	2006-07-13 20:51:50.000000000 +0200
+++ crash-4.0-2.33/lkcd_fix_mem.c	2007-01-10 16:04:16.000000000 +0100
@@ -21,19 +21,143 @@
 #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(x)  \
+	(offsetof(dump_header_asm_t, dha_magic_number) + (x))
+
+#define VERSION_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_version) + (x))
+
+#define HEADER_SIZE_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_header_size) + (x))
+
+#define PT_REGS_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_pt_regs) + (x))
+
+#define REGS_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_regs) + (x))
+
+#define RNAT_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_rnat) + (x))
+
+#define PFS_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_pfs) + (x))
+
+#define BSPSTORE_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_bspstore) + (x))
+
+#define SMP_NUM_CPUS_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_smp_num_cpus) + (x))
+
+#define DUMPING_CPU_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_dumping_cpu) + (x))
+
+#define SMP_REGS_OFFSET(x) \
+	(offsetof(dump_header_asm_t, dha_smp_regs) + (x))
+
+#define CURRENT_TASK_OFFSET(x, cpun) \
+	(SMP_REGS_OFFSET(x) + sizeof(struct pt_regs) * (cpun))
+
+#define STACK_OFFSET(x, cpun) \
+	(CURRENT_TASK_OFFSET(x, cpun) + sizeof(uint64_t) * (cpun))
+
+#define SWITCH_STACK_OFFSET(x, cpun) \
+	(STACK_OFFSET(x, cpun) + sizeof(uint64_t) * (cpun))
+
+#define KERNEL_ADDR_OFFSET(x, cpun) \
+	(SWITCH_STACK_OFFSET(x, cpun) + sizeof(uint64_t) * (cpun))
+#endif
+
 int
 fix_addr_v8(int fd)
 {
     static dump_header_asm_t dump_header_asm_v8 = { 0 };
     dump_header_asm_t *dha;
     dha = &dump_header_asm_v8;
-    
+
+#ifdef IA64
+    int cpu_num = 0;
+    int cpunum_specific;
+    size_t size;
+    bool dha_kernel_addr_end = false;
+    unsigned char *buffer;
+    int offset = 0;
+
+    /* 
+     * Dynamically load the data from the header. This addresses two 
+     * problems:
+     * 
+     *  o support both the SLES10 and the SLES9 kernel. The difference is the
+     *    position of the dha_kernel_addr field (SLES9: after dha_header_size,
+     *    SLES10: at the and as in crash)
+     *
+     *  o 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)
+        return -1;
+    if (read(lkcd->fd, buffer, dha->dha_header_size) != dha->dha_header_size)
+        return -1;
+
+    /* check if the dha_kernel_addr is at the end */
+    if ( ((dump_header_asm_t *)buffer)->dha_smp_num_cpus <= NR_CPUS &&
+            ((dump_header_asm_t *)buffer)->dha_dumping_cpu <
+            ((dump_header_asm_t *)buffer)->dha_smp_num_cpus)
+        dha_kernel_addr_end = true;
+    else
+        offset = sizeof(uint64_t);
+
+    /* now try to calculate the number of CPUs */
+    cpunum_specific = dha->dha_header_size - SMP_REGS_OFFSET(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(offset),
+            sizeof(struct pt_regs *));
+    memcpy(&dha->dha_regs, buffer + REGS_OFFSET(offset),
+            sizeof(struct pt_regs));
+    memcpy(&dha->dha_rnat, buffer + RNAT_OFFSET(offset),
+            sizeof(uint64_t));
+    memcpy(&dha->dha_pfs, buffer + PFS_OFFSET(offset),
+            sizeof(uint64_t));
+    memcpy(&dha->dha_bspstore, buffer + BSPSTORE_OFFSET(offset),
+            sizeof(uint64_t));
+    memcpy(&dha->dha_smp_num_cpus, buffer + SMP_NUM_CPUS_OFFSET(offset),
+            sizeof(uint32_t));
+    memcpy(&dha->dha_dumping_cpu, buffer + DUMPING_CPU_OFFSET(offset),
+            sizeof(uint32_t));
+    memcpy(&dha->dha_kernel_addr, buffer + KERNEL_ADDR_OFFSET(offset, cpu_num),
+            sizeof(uint64_t));
+
+    /* now the CPU number dependent things */
+    memcpy(&dha->dha_smp_regs, buffer + SMP_REGS_OFFSET(offset),
+            sizeof(struct pt_regs) * cpu_num);
+    memcpy(&dha->dha_smp_current_task, buffer + CURRENT_TASK_OFFSET(offset, cpu_num),
+            sizeof(uint64_t) * cpu_num);
+    memcpy(&dha->dha_stack, buffer + STACK_OFFSET(offset, cpu_num),
+            sizeof(uint64_t) * cpu_num);
+    memcpy(&dha->dha_switch_stack, buffer + SWITCH_STACK_OFFSET(offset, cpu_num),
+            sizeof(uint64_t) * cpu_num);
+
+#else
     if (read(lkcd->fd, dha, sizeof(dump_header_asm_t)) !=
 	    sizeof(dump_header_asm_t))
 	return -1;
+#endif
     
     fix_addr(dha);
 
@@ -61,7 +185,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");
     }
