• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2010, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <ctype.h>
18 #include <dlfcn.h>
19 #include <stdarg.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <getopt.h>
25 
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 
30 #include <unistd.h>
31 
32 #if defined(__arm__)
33 #define PROVIDE_ARM_DISASSEMBLY
34 #endif
35 
36 #ifdef PROVIDE_ARM_DISASSEMBLY
37 #include "disassem.h"
38 #endif
39 
40 #include <bcc/bcc.h>
41 
42 #include <vector>
43 
44 
45 typedef int (*MainPtr)(int, char**);
46 
47 // This is a separate function so it can easily be set by breakpoint in gdb.
run(MainPtr mainFunc,int argc,char ** argv)48 static int run(MainPtr mainFunc, int argc, char** argv) {
49   return mainFunc(argc, argv);
50 }
51 
lookupSymbol(void * pContext,const char * name)52 static void* lookupSymbol(void* pContext, const char* name) {
53   return (void*) dlsym(RTLD_DEFAULT, name);
54 }
55 
56 #ifdef PROVIDE_ARM_DISASSEMBLY
57 
58 static FILE* disasmOut;
59 
disassemble_readword(u_int address)60 static u_int disassemble_readword(u_int address) {
61   return(*((u_int *)address));
62 }
63 
disassemble_printaddr(u_int address)64 static void disassemble_printaddr(u_int address) {
65   fprintf(disasmOut, "0x%08x", address);
66 }
67 
disassemble_printf(const char * fmt,...)68 static void disassemble_printf(const char *fmt, ...) {
69   va_list ap;
70   va_start(ap, fmt);
71   vfprintf(disasmOut, fmt, ap);
72   va_end(ap);
73 }
74 
disassemble(BCCScriptRef script,FILE * out)75 static int disassemble(BCCScriptRef script, FILE* out) {
76   /* Removed by srhines
77   disasmOut = out;
78   disasm_interface_t  di;
79   di.di_readword = disassemble_readword;
80   di.di_printaddr = disassemble_printaddr;
81   di.di_printf = disassemble_printf;
82 
83   size_t numFunctions = bccGetFuncCount(script);
84   fprintf(stderr, "Function Count: %lu\n", (unsigned long)numFunctions);
85   if (numFunctions) {
86     BCCFuncInfo *infos = new BCCFuncInfo[numFunctions];
87     bccGetFuncInfoList(script, numFunctions, infos);
88 
89     for(size_t i = 0; i < numFunctions; i++) {
90       fprintf(stderr, "-----------------------------------------------------\n");
91       fprintf(stderr, "%s\n", infos[i].name);
92       fprintf(stderr, "-----------------------------------------------------\n");
93 
94       unsigned long* pBase = (unsigned long*) infos[i].addr;
95       unsigned long* pEnd =
96         (unsigned long*) (((unsigned char*) infos[i].addr) + infos[i].size);
97 
98       for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) {
99         fprintf(out, "%08x: %08x  ", (int) pInstruction, (int) *pInstruction);
100         ::disasm(&di, (uint) pInstruction, 0);
101       }
102     }
103     delete [] infos;
104   }
105   */
106 
107   return 1;
108 }
109 #else
disassemble(BCCScriptRef script,FILE * out)110 static int disassemble(BCCScriptRef script, FILE* out) {
111   fprintf(stderr, "Disassembler not supported on this build.\n");
112   return 1;
113 }
114 #endif // PROVIDE_ARM_DISASSEMBLY
115 
116 const char* inFile = NULL;
117 bool printTypeInformation = false;
118 bool printListing = false;
119 bool runResults = false;
120 
121 extern int opterr;
122 extern int optind;
123 
parseOption(int argc,char ** argv)124 static int parseOption(int argc, char** argv)
125 {
126   int c;
127   while ((c = getopt (argc, argv, "RST")) != -1) {
128     opterr = 0;
129 
130     switch(c) {
131       case 'R':
132         runResults = true;
133         break;
134 
135       case 'S':
136         printListing = true;
137         break;
138 
139       case 'T':
140         printTypeInformation = true;
141         break;
142 
143       case '?':
144         // ignore any error
145         break;
146 
147       default:
148         // Critical error occurs
149         return 0;
150         break;
151     }
152   }
153 
154   if(optind >= argc) {
155     fprintf(stderr, "input file required\n");
156     return 0;
157   }
158 
159   inFile = argv[optind];
160   return 1;
161 }
162 
loadScript()163 static BCCScriptRef loadScript() {
164   if (!inFile) {
165     fprintf(stderr, "input file required\n");
166     return NULL;
167   }
168 
169   struct stat statInFile;
170   if (stat(inFile, &statInFile) < 0) {
171     fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno));
172     return NULL;
173   }
174 
175   if (!S_ISREG(statInFile.st_mode)) {
176     fprintf(stderr, "Input file should be a regular file.\n");
177     return NULL;
178   }
179 
180   FILE *in = fopen(inFile, "r");
181   if (!in) {
182     fprintf(stderr, "Could not open input file %s\n", inFile);
183     return NULL;
184   }
185 
186   size_t bitcodeSize = statInFile.st_size;
187 
188   std::vector<char> bitcode(bitcodeSize + 1, '\0');
189   size_t nread = fread(&*bitcode.begin(), 1, bitcodeSize, in);
190 
191   if (nread != bitcodeSize)
192       fprintf(stderr, "Could not read all of file %s\n", inFile);
193 
194   BCCScriptRef script = bccCreateScript();
195 
196   if (bccReadBC(script, "file", &*bitcode.begin(), bitcodeSize, 0) != 0) {
197     fprintf(stderr, "bcc: FAILS to read bitcode");
198     bccDisposeScript(script);
199     return NULL;
200   }
201 
202   bccRegisterSymbolCallback(script, lookupSymbol, NULL);
203 
204   if (bccPrepareExecutable(script, ".", "cache", 0) != 0) {
205     fprintf(stderr, "bcc: FAILS to prepare executable.\n");
206     bccDisposeScript(script);
207     return NULL;
208   }
209 
210   return script;
211 }
212 
printPragma(BCCScriptRef script)213 static void printPragma(BCCScriptRef script) {
214 /* Removed by srhines
215   size_t numPragma = bccGetPragmaCount(script);
216   if (numPragma) {
217     char const ** keyList = new char const *[numPragma];
218     char const ** valueList = new char const *[numPragma];
219 
220     bccGetPragmaList(script, numPragma, keyList, valueList);
221     for(size_t i = 0; i < numPragma; ++i) {
222       fprintf(stderr, "#pragma %s(%s)\n", keyList[i], valueList[i]);
223     }
224 
225     delete [] keyList;
226     delete [] valueList;
227   }
228 */
229 }
230 
runMain(BCCScriptRef script,int argc,char ** argv)231 static int runMain(BCCScriptRef script, int argc, char** argv) {
232   MainPtr mainPointer = (MainPtr)bccGetFuncAddr(script, "root");
233 
234   if (!mainPointer) {
235     fprintf(stderr, "Could not find root.\n");
236     return 0;
237   }
238 
239   fprintf(stderr, "Executing compiled code:\n");
240 
241   int argc1 = argc - optind;
242   char** argv1 = argv + optind;
243 
244   int result = run(mainPointer, argc1, argv1);
245   fprintf(stderr, "result: %d\n", result);
246 
247   return 1;
248 }
249 
main(int argc,char ** argv)250 int main(int argc, char** argv) {
251   if(!parseOption(argc, argv)) {
252     fprintf(stderr, "failed to parse option\n");
253     return 1;
254   }
255 
256   BCCScriptRef script;
257 
258   if((script = loadScript()) == NULL) {
259     fprintf(stderr, "failed to load source\n");
260     return 2;
261   }
262 
263 #if 0
264   if(printTypeInformation && !reflection(script, stderr)) {
265     fprintf(stderr, "failed to retrieve type information\n");
266     return 3;
267   }
268 #endif
269 
270   printPragma(script);
271 
272   if(printListing && !disassemble(script, stderr)) {
273     fprintf(stderr, "failed to disassemble\n");
274     return 5;
275   }
276 
277   if(runResults && !runMain(script, argc, argv)) {
278     fprintf(stderr, "failed to execute\n");
279     return 6;
280   }
281 
282   return 0;
283 }
284