Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Mar 2013 00:19:32 +0100
From:      Jilles Tjoelker <jilles@stack.nl>
To:        freebsd-arm@freebsd.org
Subject:   cross-compilation of sh(1) from x86 to arm
Message-ID:  <20130303231931.GD21318@stack.nl>

next in thread | raw e-mail | index | archive | help
There has long been a bug in sh(1) where it assumes (in mksyntax.c) that
the properties of char are the same between build and run environments.
This assumption does not hold if a cross build is done for arm on an x86
machine. The main effect is that such a miscompiled sh incorrectly
handles characters with bit 7 set. Various tests in
tools/regression/bin/sh start failing, possibly in ways that eat huge
amounts of CPU time and memory.

Christoph Mallon has submitted a fix for this and I have committed it to
head and stable/9. It has, however, only been tested on x86 using the
-funsigned-char compiler option to create the discrepancy.

Below is a backport of the fix to stable/8. It needs r247733 or at least
the bin/sh/mksyntax.c of that revision.

Because I had to fix some conflicts and stable/8's sh differs quite a
bit from head's, I would like to have some testing first before
committing this. I again tested only on amd64 with and without the
-funsigned-char compiler option and tools/regression/bin/sh. If the
cross-compilation need not be supported on stable/8, I am fine with
leaving it unfixed in stable/8.

Index: bin/sh
===================================================================
--- bin/sh	(revision 247733)
+++ bin/sh	(working copy)

Property changes on: bin/sh
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /head/bin/sh:r246522
Index: bin/sh/mksyntax.c
===================================================================
--- bin/sh/mksyntax.c	(revision 247733)
+++ bin/sh/mksyntax.c	(working copy)
@@ -101,23 +101,16 @@
 
 static FILE *cfile;
 static FILE *hfile;
-static const char *syntax[513];
-static int base;
-static int size;	/* number of values which a char variable can have */
-static int nbits;	/* number of bits in a character */
 
-static void filltable(const char *);
-static void init(void);
+static void add_default(void);
+static void finish(void);
+static void init(const char *);
 static void add(const char *, const char *);
-static void print(const char *);
 static void output_type_macros(void);
 
 int
 main(int argc __unused, char **argv __unused)
 {
-	char c;
-	char d;
-	int sign;
 	int i;
 	char buf[80];
 	int pos;
@@ -134,28 +127,9 @@
 	fputs(writer, hfile);
 	fputs(writer, cfile);
 
-	/* Determine the characteristics of chars. */
-	c = -1;
-	sign = (c > 0) ? 0 : 1;
-	for (nbits = 1 ; ; nbits++) {
-		d = (1 << nbits) - 1;
-		if (d == c)
-			break;
-	}
-#if 0
-	printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
-#endif
-	if (nbits > 9) {
-		fputs("Characters can't have more than 9 bits\n", stderr);
-		exit(2);
-	}
-	size = (1 << nbits) + 1;
-	base = 1;
-	if (sign)
-		base += 1 << (nbits - 1);
-
 	fputs("#include <sys/cdefs.h>\n", hfile);
 	fputs("#include <ctype.h>\n", hfile);
+	fputs("#include <limits.h>\n\n", hfile);
 
 	/* Generate the #define statements in the header file */
 	fputs("/* Syntax classes */\n", hfile);
@@ -176,8 +150,8 @@
 		fprintf(hfile, "/* %s */\n", is_entry[i].comment);
 	}
 	putc('\n', hfile);
-	fprintf(hfile, "#define SYNBASE %d\n", base);
-	fprintf(hfile, "#define PEOF %d\n\n", -base);
+	fputs("#define SYNBASE (1 - CHAR_MIN)\n", hfile);
+	fputs("#define PEOF -SYNBASE\n\n", hfile);
 	putc('\n', hfile);
 	fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
 	fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
@@ -188,10 +162,13 @@
 	putc('\n', hfile);
 
 	/* Generate the syntax tables. */
+	fputs("#include \"parser.h\"\n", cfile);
 	fputs("#include \"shell.h\"\n", cfile);
 	fputs("#include \"syntax.h\"\n\n", cfile);
-	init();
+
 	fputs("/* syntax table used when not in quotes */\n", cfile);
+	init("basesyntax");
+	add_default();
 	add("\n", "CNL");
 	add("\\", "CBACK");
 	add("'", "CSQUOTE");
@@ -200,9 +177,11 @@
 	add("$", "CVAR");
 	add("}", "CENDVAR");
 	add("<>();&| \t", "CSPCL");
-	print("basesyntax");
-	init();
+	finish();
+
 	fputs("\n/* syntax table used when in double quotes */\n", cfile);
+	init("dqsyntax");
+	add_default();
 	add("\n", "CNL");
 	add("\\", "CBACK");
 	add("\"", "CENDQUOTE");
@@ -211,16 +190,20 @@
 	add("}", "CENDVAR");
 	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
 	add("!*?[=~:/-", "CCTL");
-	print("dqsyntax");
-	init();
+	finish();
+
 	fputs("\n/* syntax table used when in single quotes */\n", cfile);
+	init("sqsyntax");
+	add_default();
 	add("\n", "CNL");
 	add("'", "CENDQUOTE");
 	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
 	add("!*?[=~:/-", "CCTL");
-	print("sqsyntax");
-	init();
+	finish();
+
 	fputs("\n/* syntax table used when in arithmetic */\n", cfile);
+	init("arisyntax");
+	add_default();
 	add("\n", "CNL");
 	add("\\", "CBACK");
 	add("`", "CBQUOTE");
@@ -230,99 +213,94 @@
 	add("}", "CENDVAR");
 	add("(", "CLP");
 	add(")", "CRP");
-	print("arisyntax");
-	filltable("0");
+	finish();
+
 	fputs("\n/* character classification table */\n", cfile);
+	init("is_type");
 	add("0123456789", "ISDIGIT");
 	add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
 	add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
 	add("_", "ISUNDER");
 	add("#?$!-*@", "ISSPECL");
-	print("is_type");
+	finish();
+
 	exit(0);
 }
 
 
-
 /*
- * Clear the syntax table.
+ * Output the header and declaration of a syntax table.
  */
 
 static void
-filltable(const char *dftval)
+init(const char *name)
 {
-	int i;
+	fprintf(hfile, "extern const char %s[];\n", name);
+	fprintf(cfile, "const char %s[SYNBASE + CHAR_MAX + 1] = {\n", name);
+}
 
-	for (i = 0 ; i < size ; i++)
-		syntax[i] = dftval;
+
+static void
+add_one(const char *key, const char *type)
+{
+	fprintf(cfile, "\t[SYNBASE + %s] = %s,\n", key, type);
 }
 
 
 /*
- * Initialize the syntax table with default values.
+ * Add default values to the syntax table.
  */
 
 static void
-init(void)
+add_default(void)
 {
-	filltable("CWORD");
-	syntax[0] = "CEOF";
-	syntax[base + CTLESC] = "CCTL";
-	syntax[base + CTLVAR] = "CCTL";
-	syntax[base + CTLENDVAR] = "CCTL";
-	syntax[base + CTLBACKQ] = "CCTL";
-	syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
-	syntax[base + CTLARI] = "CCTL";
-	syntax[base + CTLENDARI] = "CCTL";
-	syntax[base + CTLQUOTEMARK] = "CCTL";
+	add_one("PEOF",                "CEOF");
+	add_one("CTLESC",              "CCTL");
+	add_one("CTLVAR",              "CCTL");
+	add_one("CTLENDVAR",           "CCTL");
+	add_one("CTLBACKQ",            "CCTL");
+	add_one("CTLBACKQ + CTLQUOTE", "CCTL");
+	add_one("CTLARI",              "CCTL");
+	add_one("CTLENDARI",           "CCTL");
+	add_one("CTLQUOTEMARK",        "CCTL");
 }
 
 
 /*
- * Add entries to the syntax table.
+ * Output the footer of a syntax table.
  */
 
 static void
-add(const char *p, const char *type)
+finish(void)
 {
-	while (*p)
-		syntax[*p++ + base] = type;
+	fputs("};\n", cfile);
 }
 
 
-
 /*
- * Output the syntax table.
+ * Add entries to the syntax table.
  */
 
 static void
-print(const char *name)
+add(const char *p, const char *type)
 {
-	int i;
-	int col;
+	for (; *p; ++p) {
+		char c = *p;
+		switch (c) {
+		case '\t': c = 't';  break;
+		case '\n': c = 'n';  break;
+		case '\'': c = '\''; break;
+		case '\\': c = '\\'; break;
 
-	fprintf(hfile, "extern const char %s[];\n", name);
-	fprintf(cfile, "const char %s[%d] = {\n", name, size);
-	col = 0;
-	for (i = 0 ; i < size ; i++) {
-		if (i == 0) {
-			fputs("      ", cfile);
-		} else if ((i & 03) == 0) {
-			fputs(",\n      ", cfile);
-			col = 0;
-		} else {
-			putc(',', cfile);
-			while (++col < 9 * (i & 03))
-				putc(' ', cfile);
+		default:
+			fprintf(cfile, "\t[SYNBASE + '%c'] = %s,\n", c, type);
+			continue;
 		}
-		fputs(syntax[i], cfile);
-		col += strlen(syntax[i]);
+		fprintf(cfile, "\t[SYNBASE + '\\%c'] = %s,\n", c, type);
 	}
-	fputs("\n};\n", cfile);
 }
 
 
-
 /*
  * Output character classification macros (e.g. is_digit).  If digits are
  * contiguous, we can test for them quickly.

-- 
Jilles Tjoelker



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130303231931.GD21318>