Remove use of setjmp/longjmp from libacc compiler.

It makes it harder to deal with memory allocation.

Also fix bug in the otcc-ansi.c test, where the wrong part of the
code buffer was being mprotected, so that if the code buffer happened
to be allocated across a page boundary, some code would no receive
execute permission.
This commit is contained in:
Jack Palevich 2009-06-11 10:53:51 -07:00
parent 6f5fb6fda1
commit 0a280a0dde
2 changed files with 47 additions and 34 deletions

View File

@ -11,7 +11,6 @@
#include <ctype.h>
#include <dlfcn.h>
#include <errno.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@ -69,6 +68,7 @@ class Compiler : public ErrorSink {
char* pProgramBase;
ErrorSink* mErrorSink;
int mSize;
bool mOverflowed;
void release() {
if (pProgramBase != 0) {
@ -77,13 +77,16 @@ class Compiler : public ErrorSink {
}
}
void check(int n) {
bool check(int n) {
int newSize = ind - pProgramBase + n;
if (newSize > mSize) {
bool overflow = newSize > mSize;
if (overflow && !mOverflowed) {
mOverflowed = true;
if (mErrorSink) {
mErrorSink->error("Code too large: %d bytes", newSize);
}
}
return overflow;
}
public:
@ -92,6 +95,7 @@ class Compiler : public ErrorSink {
ind = 0;
mErrorSink = 0;
mSize = 0;
mOverflowed = false;
}
~CodeBuf() {
@ -110,7 +114,9 @@ class Compiler : public ErrorSink {
}
int o4(int n) {
check(4);
if(check(4)) {
return 0;
}
intptr_t result = (intptr_t) ind;
* (int*) ind = n;
ind += 4;
@ -121,7 +127,9 @@ class Compiler : public ErrorSink {
* Output a byte. Handles all values, 0..ff.
*/
void ob(int n) {
check(1);
if(check(1)) {
return;
}
*ind++ = n;
}
@ -1037,6 +1045,7 @@ class Compiler : public ErrorSink {
int decodeOp(int op) {
if (op < 0 || op > OP_COUNT) {
error("Out-of-range operator: %d\n", op);
op = 0;
}
return operatorHelper[op];
}
@ -1363,8 +1372,6 @@ class Compiler : public ErrorSink {
String mErrorBuf;
jmp_buf mErrorRecoveryJumpBuf;
String mPragmas;
int mPragmaStringCount;
@ -1430,6 +1437,7 @@ class Compiler : public ErrorSink {
void pdef(int t) {
if (dstk - sym_stk >= ALLOC_SIZE) {
error("Symbol table exhausted");
return;
}
*dstk++ = t;
}
@ -1475,7 +1483,6 @@ class Compiler : public ErrorSink {
} else {
error("Unsupported preprocessor directive \"%s\"", last_id);
}
}
inp();
}
@ -1609,6 +1616,7 @@ class Compiler : public ErrorSink {
if (ch == '(') {
delete pName;
error("Defines with arguments not supported");
return;
}
while (isspace(ch)) {
inp();
@ -1669,7 +1677,6 @@ class Compiler : public ErrorSink {
mErrorBuf.printf("%ld: ", file->getLine());
mErrorBuf.vprintf(fmt, ap);
mErrorBuf.printf("\n");
longjmp(mErrorRecoveryJumpBuf, 1);
}
void skip(intptr_t c) {
@ -2053,6 +2060,7 @@ class Compiler : public ErrorSink {
char* allocGlobalSpace(int bytes) {
if (glo - pGlobalBase + bytes > ALLOC_SIZE) {
error("Global space exhausted");
return NULL;
}
char* result = glo;
glo += bytes;
@ -2132,8 +2140,9 @@ class Compiler : public ErrorSink {
}
if (pGen == NULL) {
error("No code generator defined.");
} else {
pGen->setErrorSink(this);
}
pGen->setErrorSink(this);
}
public:
@ -2154,30 +2163,34 @@ public:
int compile(const char* text, size_t textLength) {
int result;
if (! (result = setjmp(mErrorRecoveryJumpBuf))) {
cleanup();
clear();
codeBuf.init(ALLOC_SIZE);
setArchitecture(NULL);
if (!pGen) {
return -1;
cleanup();
clear();
codeBuf.init(ALLOC_SIZE);
setArchitecture(NULL);
if (!pGen) {
return -1;
}
pGen->init(&codeBuf);
file = new TextInputStream(text, textLength);
sym_stk = (char*) calloc(1, ALLOC_SIZE);
static const char* predefinedSymbols =
" int char void"
" if else while break return for"
" pragma define main ";
dstk = strcpy(sym_stk, predefinedSymbols)
+ strlen(predefinedSymbols);
pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
glo = pGlobalBase;
pVarsBase = (char*) calloc(1, ALLOC_SIZE);
inp();
next();
globalDeclarations();
result = pGen->finishCompile();
if (result == 0) {
if (mErrorBuf.len()) {
result = -2;
}
pGen->init(&codeBuf);
file = new TextInputStream(text, textLength);
sym_stk = (char*) calloc(1, ALLOC_SIZE);
static const char* predefinedSymbols =
" int char void"
" if else while break return for"
" pragma define main ";
dstk = strcpy(sym_stk, predefinedSymbols)
+ strlen(predefinedSymbols);
pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
glo = pGlobalBase;
pVarsBase = (char*) calloc(1, ALLOC_SIZE);
inp();
next();
globalDeclarations();
result = pGen->finishCompile();
}
return result;
}

View File

@ -450,7 +450,7 @@ int main(int g, int e) {
o();
ad();
ab(0);
if (mprotect((ac + 592) & (~ 4095), (99999 + 4095) & (~ 4095), 7)) {
if (mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7)) {
printf("Mprotect failed. %d\n", errno);
return -1;
}