[Crash-utility] Miscellaneous fixes/enhancements to crash 4.0-2.10

Castor Fu castor at 3pardata.com
Wed Nov 9 19:51:10 UTC 2005


Hi guys:

We're trying to bring in a newer version of crash, and have 
some changes which we've made since going to version 4.0-2.10
which I'll outline below, and have attached a patch:

1. Makefile,  help.c, extensions.c, new file kw.c
      Add a keyword expansion mechanism to the 'extend' command.
     We did this primarily to let us load different extensions
     based on the dump file itself or the version of crash.

     +"\n  The named <shared-object> is subjected to a simple keyword expansion",
     +"  scheme with the following rules:",
     +"    $(crash_version)       version of crash",
     +"    $(corestr-<varname>)   string named <varname> taken from the core file",
     +"    $(builddir)            build directory for the kernel",

2. defs.h
     Provide nominal recognition of the LKCD V10 dump format which does
     not appear to have changed much.

3. kernel.c
     Make compile under gcc 2.x compilers
     Provide additional information with bad stack addresses.

4. lkcd_common.c
     Handle single-bit errors in LKCD compressed pages by trying out
     all possible single-bit errors.

5. lkcd_v7.c
     If dh_memory_end is set in the dump header, use that to determine the
     index file size.  (Note that this is not initialized in the main-line
     LKCD code yet...)

6.  task.c
     Be more defensive about the value of tc->processor

     Also, try to set the panic string correctly in when decoding dump.

7.  x86.c

     Be a little more liberal deciding that the frame pointer has been included.
     gcc 3.x can re-schedule code so that instead of

         push bp
         mov esp, bp


     we sometimes see

         push bp
         xor eax,eax
         move esp, bp

     so detect both sequences.

If y'all could consider this for inclusion I would appreciate it.

     -castor



-- 
-------------- next part --------------
diff -Nau -X ignorepat crash-4.0-2.10/Makefile crash-4.0-2.10-new/Makefile
--- crash-4.0-2.10/Makefile	2005-11-08 17:28:54 -08:00
+++ crash-4.0-2.10-new/Makefile	2005-11-09 11:29:50 -08:00
@@ -75,7 +75,8 @@
 	extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \
 	lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\
 	lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \
-	netdump.c diskdump.c unwind.c unwind_decoder.c
+	netdump.c diskdump.c unwind.c unwind_decoder.c \
+	kw.c
 
 SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \
 	${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \
@@ -87,7 +88,8 @@
 	extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \
 	lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \
 	lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o \
-	lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o
+	lkcd_x86_trace.o unwind_v1.o unwind_v2.o unwind_v3.o \
+	kw.o
 
 DAEMON_OBJECT_FILES=remote_daemon.o va_server.o va_server_v1.o \
 	lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \
diff -Nau -X ignorepat crash-4.0-2.10/defs.h crash-4.0-2.10-new/defs.h
--- crash-4.0-2.10/defs.h	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/defs.h	2005-11-08 17:28:46 -08:00
@@ -3619,6 +3619,7 @@
 #define LKCD_DUMP_V7                  (0x7)  /* DUMP_VERSION_NUMBER */
 #define LKCD_DUMP_V8                  (0x8)  /* DUMP_VERSION_NUMBER */
 #define LKCD_DUMP_V9                  (0x9)  /* DUMP_VERSION_NUMBER */
+#define LKCD_DUMP_V10                 (0xa)  /* DUMP_VERSION_NUMBER */
 
 #define LKCD_DUMP_VERSION_NUMBER_MASK (0xf)
 #define LKCD_DUMP_RAW                 (0x1)   /* DUMP_[DH_]RAW */ 
@@ -3772,6 +3773,16 @@
 #define BITS64()  (lkcd->bits == 64)
 
 #endif  /* LKCD_COMMON */
+
+/* kw.c */
+typedef char *(*kwr_func_t)(char *, char *);
+
+struct kwr_ruleset;
+typedef struct kwr_ruleset *kwr_ruleset_t;
+
+kwr_ruleset_t kwr_create(char *separator);
+kwr_ruleset_t kwr_add(kwr_ruleset_t ruleset, char *str, kwr_func_t kwr_func);
+int kwr_expand(kwr_ruleset_t rules, char *instring, char *outstring, int len);
 
 /*
  *  gdb_interface.c
diff -Nau -X ignorepat crash-4.0-2.10/extensions.c crash-4.0-2.10-new/extensions.c
--- crash-4.0-2.10/extensions.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/extensions.c	2005-11-07 18:57:19 -08:00
@@ -21,6 +21,9 @@
 static void load_extension(char *);
 static void unload_extension(char *);
 
+static kwr_ruleset_t ext_kwrule = NULL;
+static void init_ext_kwrule(void);
+
 #define DUMP_EXTENSIONS   (0)
 #define LOAD_EXTENSION    (1)
 #define UNLOAD_EXTENSION  (2)
@@ -36,6 +39,10 @@
 
 	flag = DUMP_EXTENSIONS;
 
+        if (ext_kwrule == NULL) {
+            init_ext_kwrule();
+        }
+
         while ((c = getopt(argcnt, args, "lu")) != EOF) {
                 switch(c)
                 {
@@ -177,6 +184,7 @@
 	struct extension_table *ext;
 	char buf[BUFSIZE];
 	size_t size;
+        int rc;
 
 	for (ext = extension_table; ext; ext = ext->next) {
 		if (same_file(ext->filename, lib)) {
@@ -194,14 +202,18 @@
 
 	ext->filename = (char *)((ulong)ext + sizeof(struct extension_table));
 	
+        if ((rc = kwr_expand(ext_kwrule, lib, buf, BUFSIZE)) != 0) {
+                error(FATAL, "Syntax error %d in extension spec %s", rc, lib);
+        }
+
        /*
 	*  If the library is not specified by an absolute pathname, dlopen() 
         *  does not look in the current directory.
         */
-	if ((*lib != '.') && (*lib != '/') && is_elf_file(lib)) 
-		sprintf(ext->filename, "./%s", lib);
+	if ((*buf != '.') && (*buf != '/') && is_elf_file(buf)) 
+		sprintf(ext->filename, "./%s", buf);
 	else
-		strcpy(ext->filename, lib);
+		strcpy(ext->filename, buf);
 
        /*
         *  register_extension() will be called by the shared object's
@@ -343,3 +355,48 @@
 }
 
 
+char *
+extrule_version(char *kw, char *arg)
+{
+    return(strdup(pc->program_version));
+}
+
+char *
+extrule_corestr(char *kw, char *arg)
+{
+    char buf[8192];
+    if (symbol_exists(arg)) {
+            ulong kvaddr;
+            if (get_symbol_type(arg, NULL, NULL) == TYPE_CODE_PTR) {
+                get_symbol_data(arg, sizeof(kvaddr), &kvaddr);
+            } else {
+                kvaddr = symbol_value(arg);
+            }
+            read_string(kvaddr, buf, sizeof(buf));
+            return (strdup(buf));
+    } else {
+            return strdup("");
+    }
+}
+
+char *
+extrule_builddir(char *kw, char *arg)
+{
+    char *rv;
+    rv = malloc(PATH_MAX);
+    if (!rv) {
+        return (NULL);
+    }
+    if (get_build_directory(rv) == NULL) {
+            rv[0] = '\0';
+    }
+    return rv;
+}
+
+static void init_ext_kwrule(void)
+{
+    ext_kwrule = kwr_create("-");
+    kwr_add(ext_kwrule, "crash_version", extrule_version);
+    kwr_add(ext_kwrule, "corestr", extrule_corestr);
+    kwr_add(ext_kwrule, "builddir", extrule_builddir);
+}
Common subdirectories: crash-4.0-2.10/gdb-6.1 and crash-4.0-2.10-new/gdb-6.1
diff -Nau -X ignorepat crash-4.0-2.10/help.c crash-4.0-2.10-new/help.c
--- crash-4.0-2.10/help.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/help.c	2005-11-09 11:28:01 -08:00
@@ -1398,6 +1398,11 @@
 "  \"help\" command screen.",
 "\n  An example of a shared object prototype file, and how to compile it",
 "  into a shared object, is appended below.",
+"\n  The named <shared-object> is subjected to a simple keyword expansion",
+"  scheme with the following rules:",
+"    $(crash_version)       version of crash",
+"    $(corestr-<varname>)   string named <varname> taken from the core file",
+"    $(builddir)            build directory for the kernel",
 "\nEXAMPLES",
 "  Load two shared object files:\n",
 "    %s> extend extlib1.so extlib2.so",
diff -Nau -X ignorepat crash-4.0-2.10/kernel.c crash-4.0-2.10-new/kernel.c
--- crash-4.0-2.10/kernel.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/kernel.c	2005-11-07 18:57:19 -08:00
@@ -52,7 +52,7 @@
 kernel_init(int when)
 {
 	int i;
-	char *p1, *p2, buf[BUFSIZE];;
+	char *p1, *p2, buf[BUFSIZE];
 	struct syment *sp1, *sp2;
 
 	if (pc->flags & KERNEL_DEBUG_QUERY)
@@ -1465,8 +1465,8 @@
 	if (bt->hp) {
 		if (bt->hp->esp && !INSTACK(bt->hp->esp, bt))
 			error(INFO, 
-			    "invalid stack address for this task: %lx\n",
-				bt->hp->esp);
+			    "invalid stack address for this task ( %lx .. %lx ) : %lx\n",
+				bt->stackbase, bt->stacktop, bt->hp->esp);
 		eip = bt->hp->eip;
 		esp = bt->hp->esp;
 
diff -Nau -X ignorepat crash-4.0-2.10/kw.c crash-4.0-2.10-new/kw.c
--- crash-4.0-2.10/kw.c	1969-12-31 16:00:00 -08:00
+++ crash-4.0-2.10-new/kw.c	2005-11-07 18:57:19 -08:00
@@ -0,0 +1,207 @@
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+/*
+ * Keyword ruleset library.
+ *
+ */
+
+// #define TEST
+
+
+typedef char *(*kwr_func_t)(const char *, const char *);
+
+struct kwr_ruleset;
+typedef struct kwr_ruleset *kwr_ruleset_t;
+
+kwr_ruleset_t kwr_create(char *separator);
+kwr_ruleset_t kwr_add(kwr_ruleset_t ruleset, char *str, kwr_func_t kwr_func);
+int kwr_expand(kwr_ruleset_t rules, const char *instring, char *outstring, int len);
+
+struct kwr_rule {
+        char *kwr_kw;
+        kwr_func_t kwr_func;
+        struct kwr_rule *kwr_next;
+};
+
+struct kwr_ruleset {
+        struct kwr_rule *krs_rules;
+        char krs_kwend[25];
+        char krs_argbeg[25];
+};
+
+
+/*
+ * Create a new ruleset
+ */
+kwr_ruleset_t kwr_create(char *separator)
+{
+        kwr_ruleset_t rv;
+
+        rv = malloc(sizeof *rv);
+        if (rv == NULL) {
+                return NULL;
+        }
+        sprintf(rv->krs_kwend, ")%s", separator);
+        sprintf(rv->krs_argbeg, "%s", separator);
+        rv->krs_rules = NULL;
+        return (rv);
+}
+
+/*
+ * Add a rule to a ruleset
+ */
+kwr_ruleset_t kwr_add(kwr_ruleset_t kwr, char *str, kwr_func_t kwr_func)
+{
+        struct kwr_rule *q = kwr->krs_rules, *p;
+
+        p = malloc(sizeof(*p));
+        if (p == NULL) {
+                return (NULL);
+        }
+        p->kwr_kw = str;
+        p->kwr_func = kwr_func;
+        p->kwr_next = kwr->krs_rules;
+        kwr->krs_rules = p;
+        return (kwr);
+}
+
+static char *expand_kw(kwr_ruleset_t kwr, const char *kw, const char *kwargs)
+{
+    char *rv = NULL;
+    struct kwr_rule *p;
+
+    for (p = kwr->krs_rules; p; p = p->kwr_next) {
+        if (strcmp(kw, p->kwr_kw) == 0) {
+            rv = (p->kwr_func)( kw, kwargs);
+            return (rv);
+        }
+    }
+    return (rv);
+}
+
+int
+kwr_expand(kwr_ruleset_t kwr, const char *instring, char *outstring, int len)
+{
+    const char *ip, *nextkey, *closepos, *argstart;
+    char *keyword, *kwargs, *kwval;
+    char *op;
+    int nc, kw_chars, arglen;
+
+    ip = instring;
+    op = outstring;
+    outstring[len - 1] = '\0'; /* Terminate to be safe */
+
+    while (*ip != '\0') {
+        nextkey = strchr(ip, '$');
+        if (nextkey == 0) {
+            strncpy(op, ip, len - (op - outstring));
+            return (0);
+        } else {
+            nc = nextkey - ip;
+            memcpy(op, ip, nc);
+            op += nc;
+            ip += nc;
+            if (nextkey[1] != '(') {
+                return (-1);
+            }
+            closepos = strchr(ip, ')');
+            if (closepos == 0) {
+                return (-2);
+            }
+            kw_chars = strcspn(nextkey + 2, kwr->krs_kwend);
+            if (kw_chars <= 0) {
+                return (-3);
+            }
+            keyword = alloca(kw_chars + 1);
+            memcpy(keyword, nextkey + 2, kw_chars);
+            keyword[kw_chars] = '\0';
+
+            argstart = nextkey + 2 + kw_chars + strspn(nextkey + 2 + kw_chars, kwr->krs_argbeg);
+            arglen = closepos - argstart;
+            assert(arglen >= 0);
+            kwargs = alloca(arglen + 1);
+            memcpy(kwargs, argstart, arglen);
+            kwargs[arglen] = '\0';
+            kwval = expand_kw(kwr, keyword, kwargs);
+            if (kwval == 0) {
+                return (-5);
+            } else {
+                nc = strlen(kwval);
+                if (op + nc + 1 - outstring > len) {
+                    free(kwval);
+                    return (-6);
+                } else {
+                    memcpy(op, kwval, nc);
+                    op += nc;
+                    free(kwval);
+                }
+            }
+            ip = closepos + 1;
+        }
+    }
+    *op = '\0';
+    return (0);
+}
+
+#ifdef TEST
+#include <stdio.h>
+char *teststr[] = {
+    "Hello",
+    "Hello$(a b)",
+    "Hello$(a)",
+    "noargs$",
+    "noclose$(",
+    "a b $(env HOME) c d",
+    "a b $(version HOME) c d",
+    NULL
+};
+
+char *kwr_version(const char *kw, const char *args)
+{
+    return (strdup("2.1"));
+}
+
+char *kwr_env(const char *kw, const char *args)
+{
+    char *p;
+    char *rv = NULL;
+    if (strcmp(kw, "env") != 0) {
+        return rv;
+    }
+    p = getenv(args);
+    if (p) {
+        rv = strdup(p);
+    } else {
+        rv = strdup("");
+    }
+    return (rv);
+}
+
+int
+main(int argc, char **argv)
+{
+    int i = 0;
+    char obuf[512];
+    int rc;
+    char *str;
+    kwr_ruleset_t rules;
+
+
+    rules = kwr_create(" ");
+    kwr_add(rules, "env", kwr_env);
+    kwr_add(rules, "version", kwr_version);
+    while ((str = teststr[i++])) {
+        printf("Trying :%s:\n", str);
+        rc = kwr_expand(rules, str, obuf, sizeof(obuf));
+        if (rc == 0) {
+            printf("ok in:%s: out :%s:\n", str, obuf);
+        } else {
+            printf("err %d in:%s: out :%s:\n", rc, str, obuf);
+        }
+    }
+    return (0);
+}
+#endif /* TEST*/
diff -Nau -X ignorepat crash-4.0-2.10/lkcd_common.c crash-4.0-2.10-new/lkcd_common.c
--- crash-4.0-2.10/lkcd_common.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/lkcd_common.c	2005-11-08 17:28:11 -08:00
@@ -53,6 +53,7 @@
 
 struct lkcd_environment lkcd_environment = { 0 };
 struct lkcd_environment *lkcd = &lkcd_environment;
+static int uncompress_errloc;
 
 ulonglong 
 fix_lkcd_address(ulonglong addr)
@@ -208,6 +209,7 @@
 
 	case LKCD_DUMP_V8:
 	case LKCD_DUMP_V9:
+	case LKCD_DUMP_V10:
 		lkcd->version = LKCD_DUMP_V8;
 		return TRUE;
 
@@ -1164,40 +1166,103 @@
         return 1;
 }
 
+/* Returns the bit offset if it's able to correct, or negative if not */
+int
+uncompress_recover(unsigned char *dest, ulong destlen,
+    unsigned char *source, ulong sourcelen)
+{
+        int byte, bit;
+        ulong retlen = destlen;
+        int good_decomp = 0, good_rv = -1;
+
+        /* Generate all single bit errors */
+        if (sourcelen > 16384) {
+                lkcd_print("uncompress_recover: sourcelen %ld too long\n",
+                    sourcelen);
+                return(-1);
+        }
+        for (byte = 0; byte < sourcelen; byte++) {
+                for (bit = 0; bit < 8; bit++) {
+                        source[byte] ^= (1 << bit);
+
+                        if (uncompress(dest, &retlen, source, sourcelen) == Z_OK &&
+                            retlen == destlen) {
+                                good_decomp++;
+                                lkcd_print("good for flipping byte %d bit %d\n",
+                                    byte, bit);
+                                good_rv = bit + byte * 8;
+                        }
+
+                        /* Put it back */
+                        source[byte] ^= (1 << bit);
+                }
+        }
+        if (good_decomp == 0) {
+                lkcd_print("Could not correct gzip errors.\n");
+                return -2;
+        } else if (good_decomp > 1) {
+                lkcd_print("Too many valid gzip decompressions: %d.\n", good_decomp);
+                return -3;
+        } else {
+                source[good_rv >> 8] ^= 1 << (good_rv % 8);
+                uncompress(dest, &retlen, source, sourcelen);
+                source[good_rv >> 8] ^= 1 << (good_rv % 8);
+                return good_rv;
+        }
+}
+
+
 /*
  *  Uncompress a gzip'd buffer.
+ *
+ *  Returns FALSE on error.  If set, then
+ *    a non-negative value of uncompress_errloc indicates the location of
+ *    a single-bit error, and the data may be used.
  */
 static int 
 lkcd_uncompress_gzip(unsigned char *dest, ulong destlen, 
 	unsigned char *source, ulong sourcelen)
 {
         ulong retlen = destlen;
+        int rc;
 
 	switch (uncompress(dest, &retlen, source, sourcelen)) 
 	{
 	case Z_OK:
 		if (retlen == destlen)
-			return TRUE;
+                        rc = TRUE;
+                        break;
 
 		lkcd_print("uncompress: returned length not page size: %ld\n",
 				retlen);
-		return FALSE;
+                rc = FALSE;
+                break;
 
 	case Z_MEM_ERROR:
 		lkcd_print("uncompress: Z_MEM_ERROR (not enough memory)\n");
-		return FALSE;
+                rc = FALSE;
+                break;
 
 	case Z_BUF_ERROR:
 		lkcd_print("uncompress: "
 			"Z_BUF_ERROR (not enough room in output buffer)\n");
-		return FALSE;
+                rc = FALSE;
+                break;
 
 	case Z_DATA_ERROR:
 		lkcd_print("uncompress: Z_DATA_ERROR (input data corrupted)\n");
-		return FALSE;
+                rc = FALSE;
+                break;
+        default:
+                rc = FALSE;
+                break;
 	}
 
-	return FALSE;
+        if (rc == FALSE) {
+                uncompress_errloc =
+                    uncompress_recover(dest, destlen, source, sourcelen);
+        }
+	return rc;
 }
 
 
@@ -1252,8 +1317,9 @@
 	dp_flags = lkcd->get_dp_flags();
 	dp_address = lkcd->get_dp_address();
 
-        if (dp_flags & LKCD_DUMP_END)
+        if (dp_flags & LKCD_DUMP_END) {
                 return LKCD_DUMPFILE_END;
+        }
 
 	if ((lkcd->flags & LKCD_VALID) && (page > lkcd->total_pages)) 
 		lkcd->total_pages = page;
diff -Nau -X ignorepat crash-4.0-2.10/lkcd_v7.c crash-4.0-2.10-new/lkcd_v7.c
--- crash-4.0-2.10/lkcd_v7.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/lkcd_v7.c	2005-11-07 18:57:19 -08:00
@@ -89,7 +89,11 @@
 	ifd = 0;
 
 #ifdef LKCD_INDEX_FILE
-	lkcd->memory_pages = (dh->dh_memory_size * (getpagesize()/lkcd->page_size)) * 2;
+        if (dh->dh_memory_end < 0x1000000000LL) {
+            lkcd->memory_pages = dh->dh_memory_end / lkcd->page_size + 1;
+        } else {
+            lkcd->memory_pages = (dh->dh_memory_size * (getpagesize()/lkcd->page_size)) * 2;
+        }
 	dump_index_size = (lkcd->memory_pages * sizeof(off_t));	
 	lkcd->page_offsets = 0;
 	strcpy(dumpfile_index_name, dumpfile);
diff -Nau -X ignorepat crash-4.0-2.10/task.c crash-4.0-2.10-new/task.c
--- crash-4.0-2.10/task.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/task.c	2005-11-07 18:57:19 -08:00
@@ -2942,7 +2942,7 @@
 			fprintf(fp, "(SYSRQ)");
 		else if (machdep->flags & INIT)
 			fprintf(fp, "(INIT)");
-		else if (kt->cpu_flags[tc->processor] & NMI)
+		else if (verify_task(tc, 2) && kt->cpu_flags[tc->processor] & NMI)
 			fprintf(fp, "(NMI)");
 		else if (tc->task == tt->panic_task)
 			fprintf(fp, "(PANIC)");
@@ -3460,7 +3460,10 @@
 		get_lkcd_panicmsg(buf);
 		msg_found = TRUE;
 	}
-	
+
+        if (msg_found == TRUE)
+                return(buf);
+
 	open_tmpfile();
 	dump_log(FALSE);
 
@@ -4337,7 +4340,8 @@
 
         tc = FIRST_CONTEXT();
         for (i = 0; i < RUNNING_TASKS(); i++, tc++) {
-		if (task_has_cpu(tc->task, NULL)) {
+		if (task_has_cpu(tc->task, NULL)
+                    && tc->processor >= 0 && tc->processor < NR_CPUS) {
 			tt->panic_threads[tc->processor] = tc->task;
 			found++;
 		}
diff -Nau -X ignorepat crash-4.0-2.10/x86.c crash-4.0-2.10-new/x86.c
--- crash-4.0-2.10/x86.c	2005-11-07 07:44:06 -08:00
+++ crash-4.0-2.10-new/x86.c	2005-11-07 18:57:19 -08:00
@@ -683,8 +683,7 @@
 
         if ((machdep->flags & OMIT_FRAME_PTR) || 
 	    bt->debug || 
-	    (bt->flags & BT_FRAMESIZE_DEBUG) ||
-	    !(bt->flags & BT_OLD_BACK_TRACE)) {
+	    (bt->flags & BT_FRAMESIZE_DEBUG)) {
                 lkcd_x86_back_trace(bt, 0, fp);
                 return;
         }
@@ -3104,31 +3103,31 @@
  *  with the -fomit-frame-pointer flag.
  */
 #define PUSH_BP_MOV_ESP_BP 0xe58955
+#define PUSH_BP_CLR_EAX_MOV_ESP_BP 0xe589c03155LL
 
 static int
 x86_omit_frame_pointer(void)
 {
-	ulong push_bp_mov_esp_bp[3];
+	ulonglong push_bp_mov_esp_bp;
+        int i;
+        char *checkfuncs[] = {"sys_open", "sys_fork", "sys_read"};
 
 	if (pc->flags & KERNEL_DEBUG_QUERY)
 		return FALSE;
 
-	if (!readmem(symbol_value("sys_open"), KVADDR, &push_bp_mov_esp_bp[0], 
-	    sizeof(ulong), "x86_omit_frame_pointer", RETURN_ON_ERROR))
-		return TRUE;
-	if (!readmem(symbol_value("sys_fork"), KVADDR, &push_bp_mov_esp_bp[1], 
-	    sizeof(ulong), "x86_omit_frame_pointer", RETURN_ON_ERROR))
-		return TRUE;
-	if (!readmem(symbol_value("sys_read"), KVADDR, &push_bp_mov_esp_bp[2], 
-	    sizeof(ulong), "x86_omit_frame_pointer", RETURN_ON_ERROR))
-		return TRUE;
-
-	if (((push_bp_mov_esp_bp[0] & 0xffffff) == PUSH_BP_MOV_ESP_BP) &&
-	    ((push_bp_mov_esp_bp[1] & 0xffffff) == PUSH_BP_MOV_ESP_BP) &&
-	    ((push_bp_mov_esp_bp[2] & 0xffffff) == PUSH_BP_MOV_ESP_BP))
-		return FALSE;
+        for (i = 0; i < 2; i++) {
+                if (!readmem(symbol_value(checkfuncs[i]), KVADDR,
+                    &push_bp_mov_esp_bp, sizeof(ulonglong),
+                    "x86_omit_frame_pointer", RETURN_ON_ERROR))
+                        return TRUE;
+                if ( !((push_bp_mov_esp_bp & 0x0000ffffff) == PUSH_BP_MOV_ESP_BP
+                    || (push_bp_mov_esp_bp & 0xffffffffffLL) ==
+                    PUSH_BP_CLR_EAX_MOV_ESP_BP)) {
+                        return TRUE;
+                }
+        }
 
-	return TRUE;
+	return FALSE;
 }
 
 /*


More information about the Crash-utility mailing list