11cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich/* 21cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * Android "Almost" C Compiler. 31cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * This is a compiler for a small subset of the C language, intended for use 41cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * in scripting environments where speed and memory footprint are important. 51cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * 61cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * This code is based upon the "unobfuscated" version of the 71cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * Obfuscated Tiny C compiler, see the file LICENSE for details. 81cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich * 91cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich */ 101cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 111cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <ctype.h> 121cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <dlfcn.h> 131cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <stdarg.h> 141cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <stdint.h> 151cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <stdio.h> 161cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <stdlib.h> 171cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <string.h> 181cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 191cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#if defined(__arm__) 201cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <unistd.h> 211cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#endif 221cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 23d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#if defined(__arm__) 24d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#define PROVIDE_ARM_DISASSEMBLY 25d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#endif 26d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 27d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#ifdef PROVIDE_ARM_DISASSEMBLY 28d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#include "disassem.h" 29d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#endif 30d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 311cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich#include <acc/acc.h> 321cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 331cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 341cdef20774b2cd30f1a509227c86845337f63f11Jack Palevichtypedef int (*MainPtr)(int, char**); 351cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich// This is a separate function so it can easily be set by breakpoint in gdb. 361cdef20774b2cd30f1a509227c86845337f63f11Jack Palevichint run(MainPtr mainFunc, int argc, char** argv) { 371cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich return mainFunc(argc, argv); 381cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich} 391cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 408c246a9dc294760f2a981cf5144fe4939d1554e6Jack PalevichACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { 41188a5a7a3af54bd45383c72e452d627d33e63391Jack Palevich return (ACCvoid*) dlsym(RTLD_DEFAULT, name); 428c246a9dc294760f2a981cf5144fe4939d1554e6Jack Palevich} 438c246a9dc294760f2a981cf5144fe4939d1554e6Jack Palevich 44d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#ifdef PROVIDE_ARM_DISASSEMBLY 45d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 46d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichstatic FILE* disasmOut; 47d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 48d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichstatic u_int 49d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichdisassemble_readword(u_int address) 50d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich{ 51d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich return(*((u_int *)address)); 52d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich} 53d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 54d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichstatic void 55d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichdisassemble_printaddr(u_int address) 56d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich{ 57d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich fprintf(disasmOut, "0x%08x", address); 58d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich} 59d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 60d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichstatic void 61d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichdisassemble_printf(const char *fmt, ...) { 62d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich va_list ap; 63d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich va_start(ap, fmt); 64d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich vfprintf(disasmOut, fmt, ap); 65d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich va_end(ap); 66d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich} 67d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 68d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevichstatic int disassemble(ACCscript* script, FILE* out) { 69d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich disasmOut = out; 70d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich disasm_interface_t di; 71d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich di.di_readword = disassemble_readword; 72d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich di.di_printaddr = disassemble_printaddr; 73d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich di.di_printf = disassemble_printf; 74d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 75d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich ACCvoid* base; 76d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich ACCsizei length; 77d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 78d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich accGetProgramBinary(script, &base, &length); 79d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich unsigned long* pBase = (unsigned long*) base; 80d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length); 81d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 82d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) { 831c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich fprintf(out, "%08x: %08x ", (int) pInstruction, (int) *pInstruction); 84d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich ::disasm(&di, (uint) pInstruction, 0); 85d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich } 86d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich return 0; 87d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich} 88d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 89d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#endif // PROVIDE_ARM_DISASSEMBLY 90d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich 911cdef20774b2cd30f1a509227c86845337f63f11Jack Palevichint main(int argc, char** argv) { 921cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich const char* inFile = NULL; 931cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich bool printListing; 9436d9414f72b629dacc2c972e93d16cec08ef44b6Jack Palevich bool runResults = false; 951cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich FILE* in = stdin; 961cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich int i; 971cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich for (i = 1; i < argc; i++) { 981cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich char* arg = argv[i]; 991cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich if (arg[0] == '-') { 1001cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich switch (arg[1]) { 1011cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich case 'S': 1021cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich printListing = true; 1031cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich break; 10436d9414f72b629dacc2c972e93d16cec08ef44b6Jack Palevich case 'R': 10536d9414f72b629dacc2c972e93d16cec08ef44b6Jack Palevich runResults = true; 10636d9414f72b629dacc2c972e93d16cec08ef44b6Jack Palevich break; 1071cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich default: 1081cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich fprintf(stderr, "Unrecognized flag %s\n", arg); 1091cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich return 3; 1101cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1111cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } else if (inFile == NULL) { 1121cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich inFile = arg; 1131cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } else { 1141cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich break; 1151cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1161cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1171cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 1181cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich if (! inFile) { 1191cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich fprintf(stderr, "input file required\n"); 1201cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich return 2; 1211cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1221cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 1231cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich if (inFile) { 1241cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich in = fopen(inFile, "r"); 1251cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich if (!in) { 1261cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich fprintf(stderr, "Could not open input file %s\n", inFile); 1271cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich return 1; 1281cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1291cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1301cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 1311cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich fseek(in, 0, SEEK_END); 1321cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich size_t fileSize = (size_t) ftell(in); 1331cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich rewind(in); 134b7c81e99522fbc5256f20e826eae18f2a33ea76aJack Palevich ACCchar* text = new ACCchar[fileSize + 1]; 1351cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich size_t bytesRead = fread(text, 1, fileSize, in); 1361cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich if (bytesRead != fileSize) { 1371cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich fprintf(stderr, "Could not read all of file %s\n", inFile); 1381cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 1391cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 140b7c81e99522fbc5256f20e826eae18f2a33ea76aJack Palevich text[fileSize] = '\0'; 141b7c81e99522fbc5256f20e826eae18f2a33ea76aJack Palevich 1421cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich ACCscript* script = accCreateScript(); 1431cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 1441cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich const ACCchar* scriptSource[] = {text}; 1451cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich accScriptSource(script, 1, scriptSource, NULL); 1461cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich delete[] text; 1471cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 1488c246a9dc294760f2a981cf5144fe4939d1554e6Jack Palevich accRegisterSymbolCallback(script, symbolLookup, NULL); 1498c246a9dc294760f2a981cf5144fe4939d1554e6Jack Palevich 1501cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich accCompileScript(script); 151ac0e95eb60fc8f8ef3281f9183630d1515bd12a7Jack Palevich int result = accGetError(script); 1521cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich MainPtr mainPointer = 0; 153ac0e95eb60fc8f8ef3281f9183630d1515bd12a7Jack Palevich if (result != 0) { 1541c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich ACCsizei bufferLength; 1551c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich accGetScriptInfoLog(script, 0, &bufferLength, NULL); 1561c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich char* buf = (char*) malloc(bufferLength + 1); 1571c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich if (buf != NULL) { 1581c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich accGetScriptInfoLog(script, bufferLength + 1, NULL, buf); 1591c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich fprintf(stderr, "%s", buf); 1601c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich free(buf); 1611c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich } else { 1621c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich fprintf(stderr, "Out of memory.\n"); 1631c60e46e0e5a20426e235eaede8f1cf7395f4cc0Jack Palevich } 164ac0e95eb60fc8f8ef3281f9183630d1515bd12a7Jack Palevich goto exit; 165ac0e95eb60fc8f8ef3281f9183630d1515bd12a7Jack Palevich } 1661cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 167eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich { 168eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich ACCsizei numPragmaStrings; 169eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich accGetPragmas(script, &numPragmaStrings, 0, NULL); 170eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich if (numPragmaStrings) { 171eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich char** strings = new char*[numPragmaStrings]; 172eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich accGetPragmas(script, NULL, numPragmaStrings, strings); 173eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { 174eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); 175eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich } 176eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich delete[] strings; 177eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich } 178eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich } 179eedf9d20832f1af3a4bd362819be6eace54240b5Jack Palevich 180422972cb127c229a38e79bb5d2d8df44aebeeeea-b master if (printListing) { 181d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#ifdef PROVIDE_ARM_DISASSEMBLY 182d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich disassemble(script, stderr); 183d5315573d792c8441482b1cbe9ac7e93d3f730d1Jack Palevich#endif 184422972cb127c229a38e79bb5d2d8df44aebeeeea-b master } 185422972cb127c229a38e79bb5d2d8df44aebeeeea-b master 1862db168f12feb0e25209b4aee385af074ef87157aJack Palevich if (runResults) { 1872db168f12feb0e25209b4aee385af074ef87157aJack Palevich accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); 1882db168f12feb0e25209b4aee385af074ef87157aJack Palevich 1892db168f12feb0e25209b4aee385af074ef87157aJack Palevich result = accGetError(script); 1902db168f12feb0e25209b4aee385af074ef87157aJack Palevich if (result != ACC_NO_ERROR) { 1912db168f12feb0e25209b4aee385af074ef87157aJack Palevich fprintf(stderr, "Could not find main: %d\n", result); 1922db168f12feb0e25209b4aee385af074ef87157aJack Palevich } else { 1932db168f12feb0e25209b4aee385af074ef87157aJack Palevich fprintf(stderr, "Executing compiled code:\n"); 1942db168f12feb0e25209b4aee385af074ef87157aJack Palevich int codeArgc = argc - i + 1; 1952db168f12feb0e25209b4aee385af074ef87157aJack Palevich char** codeArgv = argv + i - 1; 1962db168f12feb0e25209b4aee385af074ef87157aJack Palevich codeArgv[0] = (char*) (inFile ? inFile : "stdin"); 1972db168f12feb0e25209b4aee385af074ef87157aJack Palevich result = run(mainPointer, codeArgc, codeArgv); 1982db168f12feb0e25209b4aee385af074ef87157aJack Palevich fprintf(stderr, "result: %d\n", result); 1992db168f12feb0e25209b4aee385af074ef87157aJack Palevich } 2001cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich } 2011cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 202ac0e95eb60fc8f8ef3281f9183630d1515bd12a7Jack Palevichexit: 203ac0e95eb60fc8f8ef3281f9183630d1515bd12a7Jack Palevich 2041cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich accDeleteScript(script); 2051cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich 2061cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich return result; 2071cdef20774b2cd30f1a509227c86845337f63f11Jack Palevich} 208