blob: e73a8d331afbdad26a1319ca629328d386e491da [file] [log] [blame]
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001#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
24typedef int (*MainPtr)(int, char**);
25// This is a separate function so it can easily be set by breakpoint in gdb.
Shih-wei Liao5bde66c2010-05-07 02:23:29 -070026static int run(MainPtr mainFunc, int argc, char** argv)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070027{
28 return mainFunc(argc, argv);
29}
30
Shih-wei Liao5bde66c2010-05-07 02:23:29 -070031static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)
Shih-wei Liao77ed6142010-04-07 12:21:42 -070032{
33 return (BCCvoid*) dlsym(RTLD_DEFAULT, name);
34}
35
36#ifdef PROVIDE_ARM_DISASSEMBLY
37
38static FILE* disasmOut;
39
40static u_int
41disassemble_readword(u_int address)
42{
43 return(*((u_int *)address));
44}
45
46static void
47disassemble_printaddr(u_int address)
48{
49 fprintf(disasmOut, "0x%08x", address);
50}
51
52static void
53disassemble_printf(const char *fmt, ...) {
54 va_list ap;
55 va_start(ap, fmt);
56 vfprintf(disasmOut, fmt, ap);
57 va_end(ap);
58}
59
60static 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 Liao5bde66c2010-05-07 02:23:29 -070088 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -070089
90 return 1;
91}
92#else
93static int disassemble(BCCscript* script, FILE* out) {
94 return 1;
95}
96#endif // PROVIDE_ARM_DISASSEMBLY
97
98static 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
145const char* inFile = NULL;
146bool printTypeInformation = false;
147bool printListing = false;
148bool runResults = false;
149
150extern int opterr;
151extern int optind;
152
153static 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 Liao5bde66c2010-05-07 02:23:29 -0700161 runResults = true;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700162 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
193static 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 Liao5bde66c2010-05-07 02:23:29 -0700214 if (bytesRead != codeSize)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700215 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
226static 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 Liao5bde66c2010-05-07 02:23:29 -0700235 char* buf = (char*) malloc(bufferLength + 1);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700236 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 Liao5bde66c2010-05-07 02:23:29 -0700242 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700243 bccDeleteScript(script);
244 return 0;
Shih-wei Liao5bde66c2010-05-07 02:23:29 -0700245 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700246
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 Liao5bde66c2010-05-07 02:23:29 -0700253 for(BCCsizei i = 0; i < numPragmaStrings; i += 2)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700254 fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]);
255 delete[] strings;
256 }
257 }
258
259 return 1;
260}
261
262static int runMain(BCCscript* script, int argc, char** argv) {
263 MainPtr mainPointer = 0;
264
Shih-wei Liao5bde66c2010-05-07 02:23:29 -0700265 bccGetScriptLabel(script, "root", (BCCvoid**) &mainPointer);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700266
267 int result = bccGetError(script);
268 if (result != BCC_NO_ERROR) {
Shih-wei Liao5bde66c2010-05-07 02:23:29 -0700269 fprintf(stderr, "Could not find root: %d\n", result);
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700270 } 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 Liao5bde66c2010-05-07 02:23:29 -0700277 }
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700278
279 return 1;
280
281}
282
Shih-wei Liao5bde66c2010-05-07 02:23:29 -0700283int main(int argc, char** argv)
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700284{
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 Liao5bde66c2010-05-07 02:23:29 -0700291 goto exit;
Shih-wei Liao77ed6142010-04-07 12:21:42 -0700292 }
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 Liao77ed6142010-04-07 12:21:42 -0700312 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
324exit:
325
326 return result;
327}