patch-2.2.4 linux/scripts/ksymoops/oops.c

Next file: linux/scripts/ver_linux
Previous file: linux/scripts/ksymoops/README
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.3/linux/scripts/ksymoops/oops.c linux/scripts/ksymoops/oops.c
@@ -5,6 +5,10 @@
 
 	Copyright Keith Owens <kaos@ocs.com.au>.
 	Released under the GNU Public Licence, Version 2.
+	
+	Sun Jan  7 12:56:12 CET 1999
+	Added SPARC64 support and some SPARC hacks by "Jakub Jelinek"
+	<jj@ultra.linux.cz>
 
 	Mon Jan  4 08:47:55 EST 1999
 	Version 0.6d
@@ -44,6 +48,20 @@
 #include <string.h>
 #include <unistd.h>
 
+enum oops_arch {
+	OOPS_NOARCH,
+	OOPS_I386,
+	OOPS_SPARC,
+	OOPS_SPARC64,
+	OOPS_ARM,
+	OOPS_ALPHA,
+	OOPS_MIPS,
+	OOPS_PPC,
+	OOPS_M68K
+} oops_arch;
+
+char *eip_names[] = { "IP", "EIP", "PC", "PC", "PC", "PC", "PC", "NIP", "PC" };
+
 /* Error detected by bfd */
 static void Oops_bfd_perror(const char *msg)
 {
@@ -187,11 +205,13 @@
 	static char const options[] = "-dhf ";
 	static char const procname[] = "Oops_objdump";
 
-	cmd = malloc(strlen(path_objdump)+1+strlen(options)+strlen(file)+1);
+	cmd = malloc(strlen(path_objdump)+1+13+strlen(options)+strlen(file)+1);
 	if (!cmd)
 		malloc_error(procname);
 	strcpy(cmd, path_objdump);
 	strcat(cmd, " ");
+	if (oops_arch == OOPS_SPARC64)
+		strcat(cmd, "-m sparc:v9a ");
 	strcat(cmd, options);
 	strcat(cmd, file);
 	if (debug > 1)
@@ -205,9 +225,9 @@
 static void Oops_decode_one(SYMBOL_SET *ss, const char *line, elf_addr_t eip,
 			    int adjust)
 {
-	int i;
+	int i, j;
 	elf_addr_t address, eip_relative;
-	char *line2, *map, **string = NULL;
+	char *line2, *map, **string = NULL, *p;
 	static regex_t     re_Oops_objdump;
 	static regmatch_t *re_Oops_objdump_pmatch;
 	static char const procname[] = "Oops_decode_one";
@@ -233,7 +253,9 @@
 			"( <_EIP[^>]*>)?"				/* 2 */
 			":"
 			"("						/* 3 */
-			".* +<_EIP\\+0?x?([0-9a-fA-F]+)>[ \t]*$"	/* 4 */
+			".* +"
+			"(0?x?[0-9a-fA-F]+ +)"				/* 4 */
+			"<_EIP\\+0?x?([0-9a-fA-F]+)>[ \t]*$"		/* 5 */
 			")?"
 			".*"
 			,
@@ -261,34 +283,58 @@
 		address = 0;
 	}
 	address += eip + adjust;
-	if (string[4]) {
+	if (string[5]) {
 		/* EIP relative data to be adjusted */
 		errno = 0;
-		eip_relative = strtoul(string[4], NULL, 16);
+		eip_relative = strtoul(string[5], NULL, 16);
 		if (errno) {
-			fprintf(stderr,
-				"%s Invalid hex value in objdump line, "
-				"treated as zero - '%s'\n"
-				"  objdump line '%s'\n",
-				procname, string[4], line);
-			perror(" ");
-			++errors;
-			eip_relative = 0;
+			/* Try strtoull also, e.g. sparc binutils print <_PC+0xfffffffffffffd58> */
+			errno = 0;
+			eip_relative = strtoull(string[5], NULL, 16);
+			if (errno) {
+				fprintf(stderr,
+					"%s Invalid hex value in objdump line, "
+					"treated as zero - '%s'\n"
+					"  objdump line '%s'\n",
+					procname, string[5], line);
+				perror(" ");
+				++errors;
+				eip_relative = 0;
+			}
 		}
 		eip_relative += eip + adjust;
 		map = map_address(&ss_merged, eip_relative);
 		/* new text is original line, eip_relative in hex, map text */
-		i = strlen(line)+1+2*sizeof(eip_relative)+1+strlen(map)+1;
-		line2 = malloc(i);
+		j = strlen(line);
+		if (string[4])
+			j = re_Oops_objdump_pmatch[4].rm_so;
+		i = j+1+2*sizeof(eip_relative)+1+strlen(map)+1;
+		line2 = malloc(i + 5);
 		if (!line2)
 			malloc_error(procname);
-		snprintf(line2, i, "%s %s %s",
-			line, format_address(eip_relative), map);
-		add_symbol_n(ss, address, 'C', 1, line2);
-		free(line2);
+		snprintf(line2, i, "%.*s %s %s",
+			j, line, format_address(eip_relative), map);
+	} else {
+		line2 = malloc(strlen(line) + 6);
+		if (!line2)
+			malloc_error(procname);
+		strcpy(line2, line);
 	}
-	else
-		add_symbol_n(ss, address, 'C', 1, line);	/* as is */
+	if (oops_arch != OOPS_I386) {
+		p = line2;
+		while ((p = strstr(p, "_EIP"))) {
+			int l = strlen(eip_names[oops_arch]);
+			memcpy(p + 1, eip_names[oops_arch], l);
+			if (l < 3)
+				strcpy(p + 1 + l, p + 4);
+			p += 1 + l;
+		}
+	}
+	if (address == eip)
+		strcat(line2, " <===");			/* This makes it easier to locate visually the
+							   offending instruction */
+	add_symbol_n(ss, address, 'C', 1, line2);	/* as is */
+	free(line2);
 	re_strings_free(&re_Oops_objdump, &string);
 }
 
@@ -435,6 +481,8 @@
 	int i;
 	static regex_t     re_Oops_eip_sparc;
 	static regmatch_t *re_Oops_eip_sparc_pmatch;
+	static regex_t     re_Oops_eip_sparc64;
+	static regmatch_t *re_Oops_eip_sparc64_pmatch;
 	static regex_t     re_Oops_eip_ppc;
 	static regmatch_t *re_Oops_eip_ppc_pmatch;
 	static regex_t     re_Oops_eip_mips;
@@ -442,7 +490,7 @@
 	static regex_t     re_Oops_eip_other;
 	static regmatch_t *re_Oops_eip_other_pmatch;
 	static const char procname[] = "Oops_eip";
-
+	
 	/* Oops 'EIP:' line for sparc, actually PSR followed by PC */
 	re_compile(&re_Oops_eip_sparc,
 			"^PSR: [0-9a-fA-F]+ PC: " UNBRACKETED_ADDRESS,
@@ -458,9 +506,28 @@
 			procname);
 		re_strings(&re_Oops_eip_sparc, line, re_Oops_eip_sparc_pmatch,
 			string);
+		oops_arch = OOPS_SPARC;
 		return((*string)[re_Oops_eip_sparc.re_nsub]);
 	}
 
+	/* Oops 'EIP:' line for sparc64, actually TSTATE followed by TPC */
+	re_compile(&re_Oops_eip_sparc64,
+			"^TSTATE: [0-9a-fA-F]{16} TPC: " UNBRACKETED_ADDRESS,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_eip_sparc64_pmatch);
+
+	re_string_check(re_Oops_eip_sparc64.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_eip_sparc64, line, re_Oops_eip_sparc64.re_nsub+1,
+		re_Oops_eip_sparc64_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec sparc64 %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_eip_sparc64, line, re_Oops_eip_sparc64_pmatch,
+			string);
+		oops_arch = OOPS_SPARC64;
+		return((*string)[re_Oops_eip_sparc64.re_nsub]);
+	}
+
 	/* Oops 'EIP:' line for PPC, all over the place */
 	re_compile(&re_Oops_eip_ppc,
 			"("
@@ -482,6 +549,7 @@
 			procname);
 		re_strings(&re_Oops_eip_ppc, line, re_Oops_eip_ppc_pmatch,
 			string);
+		oops_arch = OOPS_PPC;
 		return((*string)[re_Oops_eip_ppc.re_nsub]);
 	}
 
@@ -503,6 +571,7 @@
 			procname);
 		re_strings(&re_Oops_eip_mips, line, re_Oops_eip_mips_pmatch,
 			string);
+		oops_arch = OOPS_MIPS;
 		return((*string)[re_Oops_eip_mips.re_nsub]);
 	}
 
@@ -527,6 +596,7 @@
 			procname);
 		re_strings(&re_Oops_eip_other, line, re_Oops_eip_other_pmatch,
 			string);
+		oops_arch = OOPS_I386;
 		return((*string)[re_Oops_eip_other.re_nsub]);
 	}
 	return(NULL);
@@ -536,6 +606,7 @@
 static void Oops_set_eip(const char *value, elf_addr_t *eip, SYMBOL_SET *ss)
 {
 	static const char procname[] = "Oops_set_eip";
+	char buf[10];
 	errno = 0;
 	*eip = strtoul(value, NULL, 16);
 	if (errno) {
@@ -546,7 +617,8 @@
 		++errors;
 		*eip = 0;
 	}
-	add_symbol_n(ss, *eip, 'E', 1, ">>EIP:");
+	sprintf(buf, ">>%s:", eip_names[oops_arch]);
+	add_symbol_n(ss, *eip, 'E', 1, buf);
 }
 
 /* Look for the MIPS ra line, returns start of the relevant hex value */
@@ -597,6 +669,80 @@
 	add_symbol_n(ss, ra, 'R', 1, ">>RA :");
 }
 
+/* Look for the SPARC o7/i7 registers line, returns start of the relevant hex value */
+static char *Oops_oi7(const char *line, char ***string, int string_max)
+{
+	int i;
+	static regex_t     re_Oops_oi7;
+	static regmatch_t *re_Oops_oi7_pmatch;
+	static const char procname[] = "Oops_oi7";
+
+	re_compile(&re_Oops_oi7,
+			"^[io][04]: [0-9a-fA-F iosp:]+ ([io]7|ret_pc): "
+			UNBRACKETED_ADDRESS,
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_oi7_pmatch);
+
+	re_string_check(re_Oops_oi7.re_nsub+1, string_max, procname);
+	i = regexec(&re_Oops_oi7, line, re_Oops_oi7.re_nsub+1,
+		re_Oops_oi7_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+	if (i == 0) {
+		re_strings(&re_Oops_oi7, line, re_Oops_oi7_pmatch,
+			string);
+		return((*string)[re_Oops_oi7.re_nsub]);
+	}
+	return(NULL);
+}
+
+/* Set the SPARC o7/i7 from the oi7 line */
+static void Oops_set_oi7(const char *value, char ***string, SYMBOL_SET *ss)
+{
+	static const char procname[] = "Oops_set_oi7";
+	elf_addr_t oi7;
+	int o7 = 1;
+	errno = 0;
+	oi7 = strtoul(value, NULL, 16);
+	if ((*string)[1] && !strcmp((*string)[1], "i7"))
+		o7 = 0;
+	if (errno) {
+		fprintf(stderr,
+			"%s Invalid hex value in oi7 line, ignored - '%s'\n",
+			procname, value);
+		perror(" ");
+		++errors;
+		oi7 = 0;
+	}
+	add_symbol_n(ss, oi7, 'O', 1, o7 ? ">>O7:" : ">>I7:");
+}
+
+/* Look for the SPARC register dump lines end */
+static int Oops_sparc_regdump(const char *line)
+{
+	int i;
+	static regex_t     re_Oops_sparc_regdump;
+	static regmatch_t *re_Oops_sparc_regdump_pmatch;
+	static const char procname[] = "Oops_sparc_regdump";
+
+	re_compile(&re_Oops_sparc_regdump,
+		       "^(i[04]: "
+			"|Instruction DUMP: "
+			"|Caller\\["
+			")",
+		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
+		&re_Oops_sparc_regdump_pmatch);
+
+	i = regexec(&re_Oops_sparc_regdump, line, re_Oops_sparc_regdump.re_nsub+1,
+		re_Oops_sparc_regdump_pmatch, 0);
+	if (debug > 3)
+		fprintf(stderr, "DEBUG: %s regexec %d\n", procname, i);
+	if (i == 0)
+		return 1;
+	return 0;
+}
+
+
 /* Look for the Trace multilines :(.  Returns start of addresses. */
 static const char *Oops_trace(const char *line, char ***string, int string_max)
 {
@@ -619,6 +765,8 @@
 	/* ppc */	"|(Call backtrace:)"			/*  6 */
 	/* ppc */	"|(" UNBRACKETED_ADDRESS ")"		/* 7,8*/
 	/* ARM */	"|(Function entered at (" BRACKETED_ADDRESS "))"	/* 9,10,11 */
+	/* sparc */
+	/* sparc64 */	"|(Caller\\[" UNBRACKETED_ADDRESS "\\])"/*12,13*/
 			")",
 		REG_NEWLINE|REG_EXTENDED|REG_ICASE,
 		&re_Oops_trace_pmatch);
@@ -645,8 +793,11 @@
 		else if (MATCHED(10)){
 			trace_line = 1;		/* ARM */
 			start = line + re_Oops_trace_pmatch[10].rm_so;
-		}
-		else
+		} else if (MATCHED(12)) {
+			trace_line = 0;		/* sparc, sparc64 */
+			start = line + re_Oops_trace_pmatch[13].rm_so;
+			return start;
+		} else
 			trace_line = 0;
 	}
 	else
@@ -819,21 +970,25 @@
 	/* m68k */	"|(baddr=)"
 	/* any other m68K lines to print? */
 
-	/* sparc */	"|(Bad unaligned kernel)"
-	/* sparc */	"|(Forwarding unaligned exception)"
-	/* sparc */	"|(: unhandled unaligned exception)"
-	/* sparc */	"|(<sc)"
-	/* sparc */	"|(pc *=)"
-	/* sparc */	"|(r[0-9]+ *=)"
-	/* sparc */	"|(gp *=)"
-	/* any other sparc lines to print? */
-
-	/* alpha */	"|(tsk->)"
-	/* alpha */	"|(PSR: )"
-	/* alpha */	"|([goli]0: )"
-	/* alpha */	"|(Instruction DUMP: )"
+	/* alpha */	"|(Bad unaligned kernel)"
+	/* alpha */	"|(Forwarding unaligned exception)"
+	/* alpha */	"|(: unhandled unaligned exception)"
+	/* alpha */	"|(<sc)"
+	/* alpha */	"|(pc *=)"
+	/* alpha */	"|(r[0-9]+ *=)"
+	/* alpha */	"|(gp *=)"
 	/* any other alpha lines to print? */
 
+	/* sparc */	"|(tsk->)"
+	/* sparc */	"|(PSR: )"
+	/* sparc */	"|([goli][04]: )"
+	/* sparc */	"|(Instruction DUMP: )"
+	/* sparc */	"|(Caller\\[)"
+	/* any other sparc lines to print? */
+	
+	/* sparc64 */	"|(TSTATE: )"
+	/* any other sparc64 lines to print? */
+
 	/* ppc */	"|(MSR: )"
 	/* ppc */	"|(TASK = )"
 	/* ppc */	"|(last math )"
@@ -908,13 +1063,13 @@
 	/* various */	"|(Aiee)"      /* anywhere in text is a bad sign (TM) */
 	/* various */	"|(die_if_kernel)"	/* ditto */
 
-	/* sparc */	"|(\\([0-9]\\): Oops )"
-	/* sparc */	"|(: memory violation)"
-	/* sparc */	"|(: Exception at)"
-	/* sparc */	"|(: Arithmetic fault)"
-	/* sparc */	"|(: Instruction fault)"
-	/* sparc */	"|(: arithmetic trap)"
-	/* sparc */	"|(: unaligned trap)"
+	/* alpha */	"|(\\([0-9]\\): Oops )"
+	/* alpha */	"|(: memory violation)"
+	/* alpha */	"|(: Exception at)"
+	/* alpha */	"|(: Arithmetic fault)"
+	/* alpha */	"|(: Instruction fault)"
+	/* alpha */	"|(: arithmetic trap)"
+	/* alpha */	"|(: unaligned trap)"
 
 	/* sparc      die_if_kernel has no fixed text, identify by (pid): text.
 	 *            Somebody has been playful with the texts.
@@ -1114,8 +1269,9 @@
 {
 	char *line = NULL, **string = NULL;
 	const char *start, *text;
-	int i, size = 0, lineno = 0, lastprint = 0;
+	int i, size = 0, lineno = 0, lastprint = 0, print = 0;
 	elf_addr_t eip = 0;
+	int sparc_regdump = 0;
 	FILE *f;
 	SYMBOL_SET ss_format;
 	static const char procname[] = "Oops_read";
@@ -1138,7 +1294,19 @@
 				fprintf(stderr,
 					"DEBUG: %s - %s\n", procname, line);
 			++lineno;
-			if (Oops_print(line, &text, &string, MAX_STRINGS)) {
+			print = Oops_print(line, &text, &string, MAX_STRINGS);
+			if (Oops_sparc_regdump (text)) {
+				sparc_regdump = 1;
+			} else {
+				if ((oops_arch == OOPS_SPARC || 
+				     oops_arch == OOPS_SPARC64) &&
+				    sparc_regdump && ss_format.used) {
+					Oops_format(&ss_format);
+					ss_free(&ss_format);
+				}
+				sparc_regdump = 0;
+			}
+			if (print) {
 				puts(line);
 				lastprint = lineno;
 				if ((start = Oops_eip(text,
@@ -1147,6 +1315,10 @@
 				if ((start = Oops_ra(text,
 					&string, MAX_STRINGS)))
 					Oops_set_ra(start, &ss_format);
+				if ((start = Oops_oi7(text,
+					&string, MAX_STRINGS)))
+					Oops_set_oi7(start, &string, 
+						&ss_format);
 				if ((start = Oops_trace(text,
 					&string, MAX_STRINGS)))
 					Oops_trace_line(text, start,
@@ -1178,10 +1350,13 @@
 			}
 		}
 		if (ss_format.used) {
-			fprintf(stderr,
-				"Warning, Code line not seen, dumping "
-				"what data is available\n");
-			++warnings;
+			if ((oops_arch != OOPS_SPARC &&
+			     oops_arch != OOPS_SPARC64) || !sparc_regdump) {
+				fprintf(stderr,
+					"Warning, Code line not seen, dumping "
+					"what data is available\n");
+				++warnings;
+			}
 			Oops_format(&ss_format);
 			ss_free(&ss_format);
 			if (one_shot)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)