• 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     triple = DEFAULT_TARGET_TRIPLE_STRING;
106   }
107 
108   if (sysroot == NULL) {
109     sysroot = "/";
110   }
111 
112   ALOGD("Triple: %s, Android sysroot: %s", triple, sysroot);
113 
114   // input is in argv[arg_idx]
115   // TODO: Support multiple input files.
116   input = argv[arg_idx];
117 
118   return true;
119 }
120 
Build(int input_fd,int output_fd,const char * triple,const char * sysroot)121 static bool Build(int input_fd, int output_fd,
122                   const char *triple, const char *sysroot) {
123   ABCCompilerDriver *driver = ABCCompilerDriver::Create(triple);
124 
125   if (driver == NULL) {
126     return false;
127   }
128 
129   driver->setAndroidSysroot(sysroot);
130 
131   bool build_result = driver->build(input_fd, output_fd);;
132 
133   delete driver;
134 
135   return build_result;
136 }
137 
ProcessFromFd(const char * input,const char * output,const char * triple,const char * sysroot)138 static int ProcessFromFd(const char *input, const char *output,
139                          const char *triple, const char *sysroot) {
140   int output_fd, input_fd;
141 
142   if (!GetIntArg(output, output_fd)) {
143     ALOGE("Bad output fd '%s'", output);
144     return EXIT_FAILURE;
145   }
146 
147   if (!GetIntArg(input, input_fd)) {
148     ALOGE("Bad input fd '%s'", input);
149     return EXIT_FAILURE;
150   }
151 
152   if (!Build(input_fd, output_fd, triple, sysroot)) {
153     return EXIT_FAILURE;
154   }
155 
156   return EXIT_SUCCESS;
157 }
158 
ProcessFromFile(const char * input,const char * output,const char * triple,const char * sysroot)159 static int ProcessFromFile(const char *input, const char *output,
160                            const char *triple, const char *sysroot) {
161   // TODO: Support multiple input files.
162   int output_fd = -1, input_fd = -1;
163 
164   // Open the output file.
165   output_fd = ::open(output, O_RDWR | O_CREAT | O_TRUNC, 0755);
166 
167   if (output_fd < 0) {
168     ALOGE("Failed to open %s for output! (%s)", output, strerror(errno));
169     return EXIT_FAILURE;
170   }
171 
172   // Open the input file.
173   input_fd = ::open(input, O_RDONLY);
174 
175   if (input_fd < 0) {
176     ALOGE("Failed to open %s for input! (%s)", input, strerror(errno));
177     ::close(output_fd);
178     return EXIT_FAILURE;
179   }
180 
181   if (!Build(input_fd, output_fd, triple, sysroot)) {
182     ::close(output_fd);
183     ::close(input_fd);
184     return EXIT_FAILURE;
185   }
186 
187   ::close(output_fd);
188   ::close(input_fd);
189 
190   return EXIT_SUCCESS;
191 }
192 
main(int argc,char ** argv)193 int main(int argc, char **argv) {
194   Mode mode = kUnknownMode;
195   const char *input, *output, *triple = NULL, *sysroot = NULL;
196 
197   set_process_name("abcc");
198 
199   setvbuf(stdout, NULL, _IONBF, 0);
200 
201   init::Initialize();
202 
203   if (ParseArguments(argc, argv, mode, input, output, triple, sysroot)) {
204     switch (mode) {
205       case kFdMode: {
206         return ProcessFromFd(input, output, triple, sysroot);
207       }
208       case kFileMode: {
209         return ProcessFromFile(input, output, triple, sysroot);
210       }
211       default: {
212         // Unknown mode encountered. Fall-through to print usage and return
213         // error.
214         break;
215       }
216     }
217     // fall-through
218   }
219 
220   usage();
221 
222   return EXIT_FAILURE;
223 }
224