Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 1 | #include <ctype.h> |
| 2 | #include <dlfcn.h> |
| 3 | #include <stdarg.h> |
| 4 | #include <stdint.h> |
| 5 | #include <stdio.h> |
| 6 | #include <stdlib.h> |
| 7 | #include <string.h> |
| 8 | #include <getopt.h> |
| 9 | |
| 10 | #if defined(__arm__) |
| 11 | #include <unistd.h> |
| 12 | #endif |
| 13 | |
| 14 | #if defined(__arm__) |
| 15 | #define PROVIDE_ARM_DISASSEMBLY |
| 16 | #endif |
| 17 | |
| 18 | #ifdef PROVIDE_ARM_DISASSEMBLY |
| 19 | #include "disassem.h" |
| 20 | #endif |
| 21 | |
| 22 | #include <bcc/bcc.h> |
| 23 | |
| 24 | typedef int (*MainPtr)(int, char**); |
| 25 | // This is a separate function so it can easily be set by breakpoint in gdb. |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 26 | static int run(MainPtr mainFunc, int argc, char** argv) |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 27 | { |
| 28 | return mainFunc(argc, argv); |
| 29 | } |
| 30 | |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 31 | static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 32 | { |
| 33 | return (BCCvoid*) dlsym(RTLD_DEFAULT, name); |
| 34 | } |
| 35 | |
| 36 | #ifdef PROVIDE_ARM_DISASSEMBLY |
| 37 | |
| 38 | static FILE* disasmOut; |
| 39 | |
| 40 | static u_int |
| 41 | disassemble_readword(u_int address) |
| 42 | { |
| 43 | return(*((u_int *)address)); |
| 44 | } |
| 45 | |
| 46 | static void |
| 47 | disassemble_printaddr(u_int address) |
| 48 | { |
| 49 | fprintf(disasmOut, "0x%08x", address); |
| 50 | } |
| 51 | |
| 52 | static void |
| 53 | disassemble_printf(const char *fmt, ...) { |
| 54 | va_list ap; |
| 55 | va_start(ap, fmt); |
| 56 | vfprintf(disasmOut, fmt, ap); |
| 57 | va_end(ap); |
| 58 | } |
| 59 | |
| 60 | static int disassemble(BCCscript* script, FILE* out) { |
| 61 | disasmOut = out; |
| 62 | disasm_interface_t di; |
| 63 | di.di_readword = disassemble_readword; |
| 64 | di.di_printaddr = disassemble_printaddr; |
| 65 | di.di_printf = disassemble_printf; |
| 66 | |
| 67 | BCCvoid* base; |
| 68 | BCCsizei length; |
| 69 | |
| 70 | BCCsizei numFunctions; |
| 71 | bccGetFunctions(script, &numFunctions, 0, NULL); |
| 72 | if (numFunctions) { |
| 73 | char** labels = new char*[numFunctions]; |
| 74 | bccGetFunctions(script, NULL, numFunctions, labels); |
| 75 | |
| 76 | for(BCCsizei i = 0; i < numFunctions; i++) { |
| 77 | bccGetFunctionBinary(script, labels[i], &base, &length); |
| 78 | |
| 79 | unsigned long* pBase = (unsigned long*) base; |
| 80 | unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length); |
| 81 | |
| 82 | for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) { |
| 83 | fprintf(out, "%08x: %08x ", (int) pInstruction, (int) *pInstruction); |
| 84 | ::disasm(&di, (uint) pInstruction, 0); |
| 85 | } |
| 86 | } |
| 87 | delete[] labels; |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 88 | } |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 89 | |
| 90 | return 1; |
| 91 | } |
| 92 | #else |
| 93 | static int disassemble(BCCscript* script, FILE* out) { |
| 94 | return 1; |
| 95 | } |
| 96 | #endif // PROVIDE_ARM_DISASSEMBLY |
| 97 | |
| 98 | static int reflection(BCCscript* script, FILE* out) { |
| 99 | #if 0 |
| 100 | moduleHandle m = bccGetModuleHandle(script); |
| 101 | |
| 102 | fprintf(out, "#types = %d\n", bccGetNumTypes(m)); |
| 103 | |
| 104 | for (int i = 0; i < bccGetNumTypes(m); i++) { |
| 105 | typeHandle h = bccGetTypeHandleOf(m, i); |
| 106 | |
| 107 | const char *str = bccGetTypeName(m, h); |
| 108 | fprintf(out, "Type #%d:\n -Name: %s\n", i, str); |
| 109 | |
| 110 | // Double-check using bccGetTypeHandle |
| 111 | if (h != bccGetTypeHandle(m, str)) { |
| 112 | fprintf(out, "typeHandle <-> nameHandle not 1:1\n"); |
| 113 | } |
| 114 | |
| 115 | fprintf(out, " -Structural: %s\n", bccGetTypeStruct(h)); |
| 116 | |
| 117 | fprintf(out, " -FieldNames: %s\n", |
| 118 | bccGetTypeFieldNames(m, h)); |
| 119 | |
| 120 | unsigned j = bccGetNumFields(h); |
| 121 | fprintf(out, " -#fields: %d\n", j); |
| 122 | |
| 123 | if (j > 1) { |
| 124 | unsigned k; |
| 125 | for (k = 0; k < j; k++) { |
| 126 | typeHandle f = bccGetFieldType(h, k); |
| 127 | fprintf(out, " Field #%d:\n -Structural: %s\n -Name: %s\n", |
| 128 | k, |
| 129 | bccGetTypeStruct(f), |
| 130 | bccGetFieldName(m, h, k)); |
| 131 | |
| 132 | fprintf(out, " -Size: %d\n -Offst: %d\n", |
| 133 | bccGetFieldSizeInBits(m, h, k), |
| 134 | bccGetFieldOffsetInBits(m, h, k)); |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | bccDeleteModuleHandle(m); |
| 140 | #endif |
| 141 | |
| 142 | return 1; |
| 143 | } |
| 144 | |
| 145 | const char* inFile = NULL; |
| 146 | bool printTypeInformation = false; |
| 147 | bool printListing = false; |
| 148 | bool runResults = false; |
| 149 | |
| 150 | extern int opterr; |
| 151 | extern int optind; |
| 152 | |
| 153 | static int parseOption(int argc, char** argv) |
| 154 | { |
| 155 | int c; |
| 156 | while ((c = getopt (argc, argv, "RST")) != -1) { |
| 157 | opterr = 0; |
| 158 | |
| 159 | switch(c) { |
| 160 | case 'R': |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 161 | runResults = true; |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 162 | break; |
| 163 | |
| 164 | case 'S': |
| 165 | printListing = true; |
| 166 | break; |
| 167 | |
| 168 | case 'T': |
| 169 | printTypeInformation = true; |
| 170 | break; |
| 171 | |
| 172 | case '?': |
| 173 | // ignore any error |
| 174 | break; |
| 175 | |
| 176 | default: |
| 177 | // Critical error occurs |
| 178 | return 0; |
| 179 | break; |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | if(optind >= argc) { |
| 184 | fprintf(stderr, "input file required\n"); |
| 185 | return 0; |
| 186 | } |
| 187 | |
| 188 | inFile = argv[optind]; |
| 189 | |
| 190 | return 1; |
| 191 | } |
| 192 | |
| 193 | static BCCscript* loadScript() { |
| 194 | FILE* in = stdin; |
| 195 | |
| 196 | if (!inFile) { |
| 197 | fprintf(stderr, "input file required\n"); |
| 198 | return NULL; |
| 199 | } |
| 200 | |
| 201 | if (inFile) { |
| 202 | in = fopen(inFile, "r"); |
| 203 | if (!in) { |
| 204 | fprintf(stderr, "Could not open input file %s\n", inFile); |
| 205 | return NULL; |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | fseek(in, 0, SEEK_END); |
| 210 | size_t codeSize = (size_t) ftell(in); |
| 211 | rewind(in); |
| 212 | BCCchar* bitcode = new BCCchar[codeSize + 1]; |
| 213 | size_t bytesRead = fread(bitcode, 1, codeSize, in); |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 214 | if (bytesRead != codeSize) |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 215 | fprintf(stderr, "Could not read all of file %s\n", inFile); |
| 216 | |
| 217 | BCCscript* script = bccCreateScript(); |
| 218 | |
| 219 | bitcode[codeSize] = '\0'; /* must be null-terminated */ |
| 220 | bccScriptBitcode(script, bitcode, codeSize); |
| 221 | delete [] bitcode; |
| 222 | |
| 223 | return script; |
| 224 | } |
| 225 | |
| 226 | static int compile(BCCscript* script) { |
| 227 | bccRegisterSymbolCallback(script, symbolLookup, NULL); |
| 228 | |
| 229 | bccCompileScript(script); |
| 230 | |
| 231 | int result = bccGetError(script); |
| 232 | if (result != 0) { |
| 233 | BCCsizei bufferLength; |
| 234 | bccGetScriptInfoLog(script, 0, &bufferLength, NULL); |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 235 | char* buf = (char*) malloc(bufferLength + 1); |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 236 | if (buf != NULL) { |
| 237 | bccGetScriptInfoLog(script, bufferLength + 1, NULL, buf); |
| 238 | fprintf(stderr, "%s", buf); |
| 239 | free(buf); |
| 240 | } else { |
| 241 | fprintf(stderr, "Out of memory.\n"); |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 242 | } |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 243 | bccDeleteScript(script); |
| 244 | return 0; |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 245 | } |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 246 | |
| 247 | { |
| 248 | BCCsizei numPragmaStrings; |
| 249 | bccGetPragmas(script, &numPragmaStrings, 0, NULL); |
| 250 | if (numPragmaStrings) { |
| 251 | char** strings = new char*[numPragmaStrings]; |
| 252 | bccGetPragmas(script, NULL, numPragmaStrings, strings); |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 253 | for(BCCsizei i = 0; i < numPragmaStrings; i += 2) |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 254 | fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); |
| 255 | delete[] strings; |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | return 1; |
| 260 | } |
| 261 | |
| 262 | static int runMain(BCCscript* script, int argc, char** argv) { |
| 263 | MainPtr mainPointer = 0; |
| 264 | |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 265 | bccGetScriptLabel(script, "root", (BCCvoid**) &mainPointer); |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 266 | |
| 267 | int result = bccGetError(script); |
| 268 | if (result != BCC_NO_ERROR) { |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 269 | fprintf(stderr, "Could not find root: %d\n", result); |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 270 | } else { |
| 271 | fprintf(stderr, "Executing compiled code:\n"); |
| 272 | int codeArgc = argc - optind; |
| 273 | char** codeArgv = argv + optind; |
| 274 | //codeArgv[0] = (char*) (inFile ? inFile : "stdin"); |
| 275 | result = run(mainPointer, codeArgc, codeArgv); |
| 276 | fprintf(stderr, "result: %d\n", result); |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 277 | } |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 278 | |
| 279 | return 1; |
| 280 | |
| 281 | } |
| 282 | |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 283 | int main(int argc, char** argv) |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 284 | { |
| 285 | int result = 0; |
| 286 | BCCscript* script; |
| 287 | |
| 288 | if(!parseOption(argc, argv)) { |
| 289 | result = 1; |
| 290 | fprintf(stderr, "failed to parse option\n"); |
Shih-wei Liao | 5bde66c | 2010-05-07 02:23:29 -0700 | [diff] [blame] | 291 | goto exit; |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | if((script = loadScript()) == NULL) { |
| 295 | result = 2; |
| 296 | fprintf(stderr, "failed to load source\n"); |
| 297 | goto exit; |
| 298 | } |
| 299 | |
| 300 | if(printTypeInformation && !reflection(script, stderr)) { |
| 301 | result = 3; |
| 302 | fprintf(stderr, "failed to retrieve type information\n"); |
| 303 | goto exit; |
| 304 | } |
| 305 | |
| 306 | if(!compile(script)) { |
| 307 | result = 4; |
| 308 | fprintf(stderr, "failed to compile\n"); |
| 309 | goto exit; |
| 310 | } |
| 311 | |
Shih-wei Liao | 77ed614 | 2010-04-07 12:21:42 -0700 | [diff] [blame] | 312 | if(printListing && !disassemble(script, stderr)) { |
| 313 | result = 5; |
| 314 | fprintf(stderr, "failed to disassemble\n"); |
| 315 | goto exit; |
| 316 | } |
| 317 | |
| 318 | if(runResults && !runMain(script, argc, argv)) { |
| 319 | result = 6; |
| 320 | fprintf(stderr, "failed to execute\n"); |
| 321 | goto exit; |
| 322 | } |
| 323 | |
| 324 | exit: |
| 325 | |
| 326 | return result; |
| 327 | } |