Make otcc code work in x64 based system with 32-bit chroot.
Set execute permission on code before running it.
Handle negative relative offsets for global variables.
Add printfs to report the progress of nested compiles.
Change way we detect whether we can run the host compiler
or not. We used to check if we were running on a 32-bit
Linux. Now we check if the executable is a 32-bit Linux
executable.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index db37ee2..e0043ef 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -10,6 +10,7 @@
#include <ctype.h>
#include <dlfcn.h>
+#include <errno.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stdint.h>
@@ -18,6 +19,10 @@
#include <string.h>
#include <cutils/hashmap.h>
+#if defined(__i386__)
+#include <sys/mman.h>
+#endif
+
#if defined(__arm__)
#include <unistd.h>
#endif
@@ -989,7 +994,14 @@
}
virtual int finishCompile() {
- return 0;
+ size_t pagesize = 4096;
+ size_t base = (size_t) getBase() & ~ (pagesize - 1);
+ size_t top = ((size_t) getPC() + pagesize - 1) & ~ (pagesize - 1);
+ int err = mprotect((void*) base, top - base, PROT_READ | PROT_WRITE | PROT_EXEC);
+ if (err) {
+ error("mprotect() failed: %d", errno);
+ }
+ return err;
}
private:
@@ -1031,7 +1043,7 @@
void gmov(int l, int t) {
o(l + 0x83);
- oad((t < LOCAL) << 7 | 5, t);
+ oad((t > -LOCAL && t < LOCAL) << 7 | 5, t);
}
};
@@ -2165,7 +2177,7 @@
inp();
next();
globalDeclarations();
- pGen->finishCompile();
+ result = pGen->finishCompile();
}
return result;
}
diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c
index 069514b..5b75879 100644
--- a/libacc/tests/data/otcc-ansi.c
+++ b/libacc/tests/data/otcc-ansi.c
@@ -50,7 +50,7 @@
o();
}
C = 0;
- d = h;
+ d = h;
if (X()) {
E(32);
M = D;
@@ -162,7 +162,7 @@
void N(int j, int e) {
ae(j + 131);
- s((e < 512) << 7 | 5, e);
+ s((e > -512 && e < 512) << 7 | 5, e);
}
void T (int j) {
@@ -404,7 +404,7 @@
v=v +4;
}
ad();
- if( d == 44)ad();
+ if( d == 44)ad() ;
}
ad();
}
@@ -432,7 +432,12 @@
}
}
+int run(int g, int e) {
+ return (*(int(*)()) *(int*) (P + 592))(g, e);
+}
+
int main(int g, int e) {
+ int result;
Q = stdin;
if (g-- > 1) {
e = e + 4;
@@ -445,5 +450,13 @@
o();
ad();
ab(0);
- return (*(int(*)()) *(int*) (P + 592))(g, e);
+ if (mprotect((ac + 592) & (~ 4095), (99999 + 4095) & (~ 4095), 7)) {
+ printf("Mprotect failed. %d\n", errno);
+ return -1;
+ }
+ fprintf(stderr, "otcc-ansi.c: About to execute compiled code:\n");
+ result = run(g, e);
+ fprintf(stderr, "atcc-ansi.c: result: %d\n", result);
+ return result;
}
+
diff --git a/libacc/tests/data/otcc.c b/libacc/tests/data/otcc.c
index 577fcf3..433ae2e 100644
--- a/libacc/tests/data/otcc.c
+++ b/libacc/tests/data/otcc.c
@@ -441,6 +441,8 @@
o f;
c;
ab(0);
+mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7);
+fprintf(stderr, "otcc.c: about to execute compiled code.\n");
J(*(int(*)f)k(P+592))(g,n;
}
diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c
index e386009..6b53fd5 100644
--- a/libacc/tests/data/returnval-ansi.c
+++ b/libacc/tests/data/returnval-ansi.c
@@ -1,10 +1,8 @@
-#define VALUE (2*FOO)
-#define FOO 12
int main(int argc, char** argv) {
return f();
}
int f() {
- return VALUE;
+ return 42;
}
diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c
index 1b9dd81..1cf5bae 100644
--- a/libacc/tests/data/returnval.c
+++ b/libacc/tests/data/returnval.c
@@ -1,6 +1,3 @@
-#pragma foo3(bar) //sdfsfd
-#pragma a(b)
-
main() {
return 42;
}
diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal
index 2989e11..1650bf9 100755
--- a/libacc/tests/testlocal
+++ b/libacc/tests/testlocal
@@ -2,17 +2,20 @@
SCRIPT_DIR=`dirname $BASH_SOURCE`
DATA=$SCRIPT_DIR/data
+ACC=`which acc`
echo "Compiling returnval-ansi.c"
-acc -S $DATA/returnval-ansi.c
+$ACC -S $DATA/returnval-ansi.c
echo "Compiling whole compiler."
-acc -S "$DATA/otcc-ansi.c"
+$ACC -S "$DATA/otcc-ansi.c"
-if (( "$(uname)" = "Linux" )) && (( "$(uname -m)" = "i686" )); then
- echo "Linux i686. Testing otcc-ansi.c"
- acc -R "$DATA/otcc-ansi.c" "$DATA/returnval.c"
- acc -R $DATA/otcc-ansi.c $DATA/otcc.c $DATA/returnval.c
+if file $ACC | grep -q "ELF 32-bit LSB executable, Intel 80386"; then
+ echo "Linux 32bit Intel."
+ $ACC -R $DATA/returnval-ansi.c
+ echo Testing otcc-ansi.c
+ $ACC -R "$DATA/otcc-ansi.c" "$DATA/returnval.c"
+ $ACC -R $DATA/otcc-ansi.c $DATA/otcc.c $DATA/returnval.c
fi
echo "Done with tests."