• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012, 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 <cerrno>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 
22 #include <fcntl.h>
23 
24 #include "bcc/Config/Config.h"
25 #include "bcc/Support/Initialization.h"
26 #include "bcc/Support/Log.h"
27 #include "bcc/AndroidBitcode/ABCCompilerDriver.h"
28 
29 #include <cutils/process_name.h>
30 
31 using namespace bcc;
32 
usage()33 static void usage() {
34   fprintf(stderr, "usage: abcc [--fd output_fd|--file output_filename]\n"
35 #ifndef TARGET_BUILD
36                   "            [--triple triple]\n"
37                   "            [--android-sysroot sysroot]\n"
38 #endif
39                   "            input_filename(s) or input_fd(s)...\n");
40   return;
41 }
42 
GetIntArg(const char * arg,int & result)43 static inline bool GetIntArg(const char *arg, int &result) {
44   char *endptr;
45 
46   result = ::strtol(arg, &endptr, 0);
47   if (*endptr != '\0') {
48     return false;
49   } else {
50     return true;
51   }
52 }
53 
54 enum Mode {
55   kUnknownMode,
56   kFdMode,
57   kFileMode
58 };
59 
ParseArguments(int argc,const char * const * argv,Mode & mode,const char * & input,const char * & output,const char * & triple,const char * & sysroot)60 static inline bool ParseArguments(int argc, const char *const *argv, Mode &mode,
61                                   const char *&input, const char *&output,
62                                   const char *&triple, const char *&sysroot) {
63   if (argc < 4) {
64     return false;
65   }
66 
67   // Parse the mode in argv[1].
68   if (::strcmp(argv[1], "--fd") == 0) {
69     mode = kFdMode;
70   } else if (::strcmp(argv[1], "--file") == 0) {
71     mode = kFileMode;
72   } else {
73     ALOGE("Unknown mode '%s'!", argv[1]);
74     return false;
75   }
76 
77   // output is always in argv[2].
78   output = argv[2];
79 
80   // On-device version cannot configure the triple and sysroot.
81   int arg_idx = 3;
82 #ifndef TARGET_BUILD
83   if (::strcmp(argv[arg_idx], "--triple") == 0) {
84     if ((arg_idx + 2 /* --triple [triple] input */) >= argc) {
85       ALOGE("Too few arguments when --triple was given!");
86       return false;
87     }
88 
89     triple = argv[arg_idx + 1];
90     arg_idx += 2;
91   }
92 
93   if (::strcmp(argv[arg_idx], "--android-sysroot") == 0) {
94     if ((arg_idx + 2 /* --android-sysroot [sysroot] input */) >= argc) {
95       ALOGE("Too few arguments when --android-sysroot was given!");
96       return false;
97     }
98 
99     sysroot = argv[arg_idx + 1];
100     arg_idx += 2;
101   }
102 #endif
103 
104   if (triple == NULL) {
105 #ifdef DEFAULT_ARM_CODEGEN
106     // Generate Thumb instead of ARM.
107     triple = DEFAULT_THUMB_TRIPLE_STRING;
108 #else
109      triple = DEFAULT_TARGET_TRIPLE_STRING;
110 #endif
111   }
112 
113   if (sysroot == NULL) {
114     sysroot = "/";
115   }
116 
117   ALOGD("Triple: %s, Android sysroot: %s", triple, sysroot);
118 
119   // input is in argv[arg_idx]
120   // TODO: Support multiple input files.
121   input = argv[arg_idx];
122 
123   return true;
124 }
125 
Build(int input_fd,int output_fd,const char * triple,const char * sysroot)126 static bool Build(int input_fd, int output_fd,
127                   const char *triple, const char *sysroot) {
128   ABCCompilerDriver *driver = ABCCompilerDriver::Create(triple);
129 
130   if (driver == NULL) {
131     return false;
132   }
133 
134   driver->setAndroidSysroot(sysroot);
135 
136   bool build_result = driver->build(input_fd, output_fd);;
137 
138   delete driver;
139 
140   return build_result;
141 }
142 
ProcessFromFd(const char * input,const char * output,const char * triple,const char * sysroot)143 static int ProcessFromFd(const char *input, const char *output,
144                          const char *triple, const char *sysroot) {
145   int output_fd, input_fd;
146 
147   if (!GetIntArg(output, output_fd)) {
148     ALOGE("Bad output fd '%s'", output);
149     return EXIT_FAILURE;
150   }
151 
152   if (!GetIntArg(input, input_fd)) {
153     ALOGE("Bad input fd '%s'", input);
154     return EXIT_FAILURE;
155   }
156 
157   if (!Build(input_fd, output_fd, triple, sysroot)) {
158     return EXIT_FAILURE;
159   }
160 
161   return EXIT_SUCCESS;
162 }
163 
ProcessFromFile(const char * input,const char * output,const char * triple,const char * sysroot)164 static int ProcessFromFile(const char *input, const char *output,
165                            const char *triple, const char *sysroot) {
166   // TODO: Support multiple input files.
167   int output_fd = -1, input_fd = -1;
168 
169   // Open the output file.
170   output_fd = ::open(output, O_RDWR | O_CREAT | O_TRUNC, 0755);
171 
172   if (output_fd < 0) {
173     ALOGE("Failed to open %s for output! (%s)", output, strerror(errno));
174     return EXIT_FAILURE;
175   }
176 
177   // Open the input file.
178   input_fd = ::open(input, O_RDONLY);
179 
180   if (input_fd < 0) {
181     ALOGE("Failed to open %s for input! (%s)", input, strerror(errno));
182     ::close(output_fd);
183     return EXIT_FAILURE;
184   }
185 
186   if (!Build(input_fd, output_fd, triple, sysroot)) {
187     ::close(output_fd);
188     ::close(input_fd);
189     return EXIT_FAILURE;
190   }
191 
192   ::close(output_fd);
193   ::close(input_fd);
194 
195   return EXIT_SUCCESS;
196 }
197 
main(int argc,char ** argv)198 int main(int argc, char **argv) {
199   Mode mode = kUnknownMode;
200   const char *input, *output, *triple = NULL, *sysroot = NULL;
201 
202   set_process_name("abcc");
203 
204   setvbuf(stdout, NULL, _IONBF, 0);
205 
206   init::Initialize();
207 
208   if (ParseArguments(argc, argv, mode, input, output, triple, sysroot)) {
209     switch (mode) {
210       case kFdMode: {
211         return ProcessFromFd(input, output, triple, sysroot);
212       }
213       case kFileMode: {
214         return ProcessFromFile(input, output, triple, sysroot);
215       }
216       default: {
217         // Unknown mode encountered. Fall-through to print usage and return
218         // error.
219         break;
220       }
221     }
222     // fall-through
223   }
224 
225   usage();
226 
227   return EXIT_FAILURE;
228 }
229