Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* Copyright 2012 The Native Client Authors. All rights reserved. | 1 /* Copyright 2012 The Native Client Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can | 2 * Use of this source code is governed by a BSD-style license that can |
| 3 * be found in the LICENSE file. | 3 * be found in the LICENSE file. |
| 4 * | 4 * |
| 5 * This file provides wrappers to open() to use pre-opened file descriptors | 5 * This file provides wrappers to open() to use pre-opened file descriptors |
| 6 * for the input bitcode and the output file. | 6 * for the input bitcode and the output file. |
| 7 * | 7 * |
| 8 * It also has the SRPC interfaces, but that should probably be refactored | 8 * It also has the SRPC interfaces, but that should probably be refactored |
| 9 * into a separate file. | 9 * into a separate file. |
| 10 */ | 10 */ |
| 11 | 11 |
| 12 #if defined(__native_client__) && defined(NACL_SRPC) | 12 #if defined(__native_client__) && defined(NACL_SRPC) |
| 13 | 13 |
| 14 #include <argz.h> | 14 #include <argz.h> |
| 15 #include <stdio.h> | 15 #include <stdio.h> |
| 16 #include <stdlib.h> | 16 #include <stdlib.h> |
| 17 #include <string.h> | 17 #include <string.h> |
| 18 // Headers which are not properly part of the SDK are included by their | 18 // Headers which are not properly part of the SDK are included by their |
| 19 // path in the nacl tree | 19 // path in the nacl tree |
| 20 #include "native_client/src/shared/srpc/nacl_srpc.h" | 20 #include "native_client/src/shared/srpc/nacl_srpc.h" |
| 21 #ifdef __pnacl__ | 21 #ifdef __pnacl__ |
| 22 #include <nacl/pnacl.h> | 22 #include <nacl/pnacl.h> |
| 23 #endif | 23 #endif |
| 24 #include "SRPCStreamer.h" | 24 #include "SRPCStreamer.h" |
| 25 | 25 |
| 26 | |
| 27 #include <string> | 26 #include <string> |
| 28 #include <map> | 27 #include <map> |
| 29 #include <vector> | 28 #include <vector> |
| 30 | 29 |
| 31 #include "llvm/ADT/OwningPtr.h" | 30 #include "llvm/ADT/OwningPtr.h" |
| 32 #include "llvm/ADT/StringRef.h" | 31 #include "llvm/ADT/StringRef.h" |
| 33 #include "llvm/Support/MemoryBuffer.h" | 32 #include "llvm/Support/MemoryBuffer.h" |
| 34 #include "llvm/Support/system_error.h" | 33 #include "llvm/Support/system_error.h" |
| 35 | 34 |
| 36 | 35 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 return llc_main(static_cast<int>(argc), argv); | 112 return llc_main(static_cast<int>(argc), argv); |
| 114 } | 113 } |
| 115 | 114 |
| 116 string_vector* CommandLineFromArgz(char* str, size_t str_len) { | 115 string_vector* CommandLineFromArgz(char* str, size_t str_len) { |
| 117 char* entry = str; | 116 char* entry = str; |
| 118 string_vector* vec = new string_vector; | 117 string_vector* vec = new string_vector; |
| 119 while (entry != NULL) { | 118 while (entry != NULL) { |
| 120 vec->push_back(entry); | 119 vec->push_back(entry); |
| 121 entry = argz_next(str, str_len, entry); | 120 entry = argz_next(str, str_len, entry); |
| 122 } | 121 } |
| 122 return vec; | |
| 123 } | |
| 124 | |
| 125 void AddFixedArguments(string_vector* vec) { | |
| 123 // Add fixed arguments to the command line. These specify the bitcode | 126 // Add fixed arguments to the command line. These specify the bitcode |
| 124 // and object code filenames, removing them from the contract with the | 127 // and object code filenames, removing them from the contract with the |
| 125 // coordinator. | 128 // coordinator. |
| 126 vec->push_back(kBitcodeFilename); | 129 vec->push_back(kBitcodeFilename); |
| 127 vec->push_back("-o"); | 130 vec->push_back("-o"); |
| 128 vec->push_back(kObjectFilename); | 131 vec->push_back(kObjectFilename); |
| 129 return vec; | 132 } |
| 133 | |
| 134 bool AddDefaultCPU(string_vector* vec) { | |
| 135 #if defined (__pnacl__) | |
| 136 switch (__builtin_nacl_target_arch()) { | |
| 137 case PnaclTargetArchitectureX86_32: { | |
| 138 vec->push_back("-mcpu=pentium4"); | |
| 139 break; | |
| 140 } | |
| 141 case PnaclTargetArchitectureX86_64: { | |
| 142 vec->push_back("-mcpu=core2"); | |
| 143 break; | |
| 144 } | |
| 145 case PnaclTargetArchitectureARM_32: { | |
| 146 vec->push_back("-mcpu=cortex-a8"); | |
| 147 break; | |
| 148 } | |
| 149 default: | |
| 150 printerr("no target architecture match.\n"); | |
| 151 return false; | |
| 152 } | |
| 153 // Some cases for building this with nacl-gcc. | |
| 154 #elif defined (__i386__) | |
| 155 vec->push_back("-mcpu=pentium4"); | |
| 156 #elif defined (__x86_64__) | |
| 157 vec->push_back("-mcpu=core2"); | |
| 158 #elif defined (__arm__) | |
| 159 vec->push_back("-mcpu=cortex-a8"); | |
| 160 #error "Unknown architecture" | |
| 161 #endif | |
| 162 return true; | |
| 163 } | |
| 164 | |
| 165 bool HadCPUOverride(string_vector* vec) { | |
|
Derek Schuff
2013/03/06 17:45:27
s/Had/Has?
jvoung (off chromium)
2013/03/06 18:24:44
Done.
| |
| 166 std::string mcpu = std::string("-mcpu="); | |
| 167 size_t len = mcpu.length(); | |
| 168 for (size_t i = 0; i < vec->size(); ++i) { | |
| 169 std::string prefix = (*vec)[i].substr(0, len); | |
| 170 if (prefix.compare(mcpu) == 0) | |
| 171 return true; | |
| 172 } | |
| 173 return false; | |
| 130 } | 174 } |
| 131 | 175 |
| 132 string_vector* GetDefaultCommandLine() { | 176 string_vector* GetDefaultCommandLine() { |
| 133 string_vector* command_line = new string_vector; | 177 string_vector* command_line = new string_vector; |
| 134 size_t i; | 178 size_t i; |
| 135 // First, those common to all architectures. | 179 // First, those common to all architectures. |
| 136 static const char* common_args[] = { "pnacl_translator", | 180 static const char* common_args[] = { "pnacl_translator", |
| 137 "-filetype=obj", | 181 "-filetype=obj" }; |
| 138 kBitcodeFilename, | |
| 139 "-o", | |
| 140 kObjectFilename }; | |
| 141 for (i = 0; i < ARRAY_SIZE(common_args); ++i) { | 182 for (i = 0; i < ARRAY_SIZE(common_args); ++i) { |
| 142 command_line->push_back(common_args[i]); | 183 command_line->push_back(common_args[i]); |
| 143 } | 184 } |
| 144 // Then those particular to a platform. | 185 // Then those particular to a platform. |
| 145 static const char* llc_args_x8632[] = { "-march=x86", | 186 static const char* llc_args_x8632[] = { "-mtriple=i686-none-nacl-gnu", |
| 146 "-mcpu=pentium4", | |
| 147 "-mtriple=i686-none-nacl-gnu", | |
| 148 NULL }; | 187 NULL }; |
| 149 static const char* llc_args_x8664[] = { "-march=x86-64", | 188 static const char* llc_args_x8664[] = { "-mtriple=x86_64-none-nacl-gnu", |
| 150 "-mcpu=core2", | |
| 151 "-mtriple=x86_64-none-nacl-gnu", | |
| 152 NULL }; | 189 NULL }; |
| 153 static const char* llc_args_arm[] = { "-mcpu=cortex-a8", | 190 static const char* llc_args_arm[] = { "-mtriple=armv7a-none-nacl-gnueabi", |
| 154 "-mtriple=armv7a-none-nacl-gnueabi", | |
| 155 "-arm-reserve-r9", | 191 "-arm-reserve-r9", |
| 156 "-sfi-disable-cp", | 192 "-sfi-disable-cp", |
| 157 "-sfi-store", | 193 "-sfi-store", |
| 158 "-sfi-load", | 194 "-sfi-load", |
| 159 "-sfi-stack", | 195 "-sfi-stack", |
| 160 "-sfi-branch", | 196 "-sfi-branch", |
| 161 "-sfi-data", | 197 "-sfi-data", |
| 162 "-no-inline-jumptables", | 198 "-no-inline-jumptables", |
| 163 "-float-abi=hard", | 199 "-float-abi=hard", |
| 164 NULL }; | 200 NULL }; |
| 165 | 201 |
| 166 const char **llc_args = NULL; | 202 const char **llc_args = NULL; |
| 167 #if defined (__pnacl__) | 203 #if defined (__pnacl__) |
| 168 switch (__builtin_nacl_target_arch()) { | 204 switch (__builtin_nacl_target_arch()) { |
| 169 case PnaclTargetArchitectureX86_32: { | 205 case PnaclTargetArchitectureX86_32: { |
| 170 llc_args = llc_args_x8632; | 206 llc_args = llc_args_x8632; |
| 171 break; | 207 break; |
| 172 } | 208 } |
| 173 case PnaclTargetArchitectureX86_64: { | 209 case PnaclTargetArchitectureX86_64: { |
| 174 llc_args = llc_args_x8664; | 210 llc_args = llc_args_x8664; |
| 175 break; | 211 break; |
| 176 } | 212 } |
| 177 case PnaclTargetArchitectureARM_32: { | 213 case PnaclTargetArchitectureARM_32: { |
| 178 llc_args = llc_args_arm; | 214 llc_args = llc_args_arm; |
| 179 break; | 215 break; |
| 180 } | 216 } |
| 181 default: | 217 default: |
| 182 printerr("no target architecture match.\n"); | 218 printerr("no target architecture match.\n"); |
| 183 delete command_line; | 219 delete command_line; |
| 184 command_line = NULL; | 220 return NULL; |
| 185 break; | |
| 186 } | 221 } |
| 222 // Some cases for building this with nacl-gcc. | |
| 187 #elif defined (__i386__) | 223 #elif defined (__i386__) |
| 188 llc_args = llc_args_x8632; | 224 llc_args = llc_args_x8632; |
| 189 #elif defined (__x86_64__) | 225 #elif defined (__x86_64__) |
| 190 llc_args = llc_args_x8664; | 226 llc_args = llc_args_x8664; |
| 227 #elif defined (__arm__) | |
| 228 llc_args = llc_args_arm; | |
| 191 #else | 229 #else |
| 192 #error | 230 #error "Unknown architecture" |
| 193 #endif | 231 #endif |
| 194 for (i = 0; llc_args[i] != NULL; i++) command_line->push_back(llc_args[i]); | 232 for (i = 0; llc_args[i] != NULL; i++) command_line->push_back(llc_args[i]); |
| 195 return command_line; | 233 return command_line; |
| 196 } | 234 } |
| 197 | 235 |
| 198 // Data passed from main thread to compile thread. | 236 // Data passed from main thread to compile thread. |
| 199 // Takes ownership of the commandline vector. | 237 // Takes ownership of the commandline vector. |
| 200 class StreamingThreadData { | 238 class StreamingThreadData { |
| 201 public: | 239 public: |
| 202 StreamingThreadData(int object_fd, string_vector* cmd_line_vec) : | 240 StreamingThreadData(int object_fd, string_vector* cmd_line_vec) : |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 // Under the hood it forks a new thread at starts the llc_main, which sets | 284 // Under the hood it forks a new thread at starts the llc_main, which sets |
| 247 // up the compilation and blocks when it tries to start reading the bitcode. | 285 // up the compilation and blocks when it tries to start reading the bitcode. |
| 248 // Input arg is a file descriptor to write the output object file to. | 286 // Input arg is a file descriptor to write the output object file to. |
| 249 // Returns a string, containing an error message if the call fails. | 287 // Returns a string, containing an error message if the call fails. |
| 250 void stream_init(NaClSrpcRpc *rpc, | 288 void stream_init(NaClSrpcRpc *rpc, |
| 251 NaClSrpcArg **in_args, | 289 NaClSrpcArg **in_args, |
| 252 NaClSrpcArg **out_args, | 290 NaClSrpcArg **out_args, |
| 253 NaClSrpcClosure *done) { | 291 NaClSrpcClosure *done) { |
| 254 // cmd_line_vec allocated by GetDefaultCommandLine() is freed by the | 292 // cmd_line_vec allocated by GetDefaultCommandLine() is freed by the |
| 255 // translation thread in run_streamed() | 293 // translation thread in run_streamed() |
| 256 do_stream_init(rpc, in_args, out_args, done, GetDefaultCommandLine()); | 294 string_vector* cmd_line_vec = GetDefaultCommandLine(); |
| 295 if (!cmd_line_vec || !AddDefaultCPU(cmd_line_vec)) { | |
| 296 NaClSrpcClosureRunner runner(done); | |
| 297 rpc->result = NACL_SRPC_RESULT_APP_ERROR; | |
| 298 out_args[0]->arrays.str = strdup("Failed to get default commandline."); | |
| 299 return; | |
| 300 } | |
| 301 AddFixedArguments(cmd_line_vec); | |
| 302 do_stream_init(rpc, in_args, out_args, done, cmd_line_vec); | |
| 257 } | 303 } |
| 258 | 304 |
| 259 // Invoked by StreamInitWithCommandLine RPC. Same as stream_init, but | 305 // Invoked by StreamInitWithCommandLine RPC. Same as stream_init, but |
| 260 // provides a command line to use instead of the default. | 306 // provides a command line to use instead of the default. |
| 261 void stream_init_with_command_line(NaClSrpcRpc *rpc, | 307 void stream_init_with_command_line(NaClSrpcRpc *rpc, |
| 262 NaClSrpcArg **in_args, | 308 NaClSrpcArg **in_args, |
| 263 NaClSrpcArg **out_args, | 309 NaClSrpcArg **out_args, |
| 264 NaClSrpcClosure *done) { | 310 NaClSrpcClosure *done) { |
| 265 char* command_line = in_args[1]->arrays.carr; | 311 char* command_line = in_args[1]->arrays.carr; |
| 266 size_t command_line_len = in_args[1]->u.count; | 312 size_t command_line_len = in_args[1]->u.count; |
| 267 string_vector* cmd_line_vec = | 313 string_vector* cmd_line_vec = |
| 268 CommandLineFromArgz(command_line, command_line_len); | 314 CommandLineFromArgz(command_line, command_line_len); |
| 315 AddFixedArguments(cmd_line_vec); | |
| 269 // cmd_line_vec is freed by the translation thread in run_streamed | 316 // cmd_line_vec is freed by the translation thread in run_streamed |
| 270 do_stream_init(rpc, in_args, out_args, done, cmd_line_vec); | 317 do_stream_init(rpc, in_args, out_args, done, cmd_line_vec); |
| 271 } | 318 } |
| 272 | 319 |
| 320 // Invoked by StreamInitWithOverrides RPC. Same as stream_init, but | |
| 321 // provides commandline flag overrides (appended to the default). | |
| 322 void stream_init_with_overrides(NaClSrpcRpc *rpc, | |
| 323 NaClSrpcArg **in_args, | |
| 324 NaClSrpcArg **out_args, | |
| 325 NaClSrpcClosure *done) { | |
| 326 string_vector* cmd_line_vec = GetDefaultCommandLine(); | |
| 327 if (!cmd_line_vec) { | |
| 328 NaClSrpcClosureRunner runner(done); | |
| 329 rpc->result = NACL_SRPC_RESULT_APP_ERROR; | |
| 330 out_args[0]->arrays.str = strdup("Failed to get default commandline."); | |
| 331 return; | |
| 332 } | |
| 333 AddFixedArguments(cmd_line_vec); | |
| 334 | |
| 335 char* command_line = in_args[1]->arrays.carr; | |
| 336 size_t command_line_len = in_args[1]->u.count; | |
| 337 llvm::OwningPtr<string_vector> extra_vec( | |
| 338 CommandLineFromArgz(command_line, command_line_len)); | |
| 339 cmd_line_vec->insert(cmd_line_vec->end(), | |
| 340 extra_vec->begin(), extra_vec->end()); | |
| 341 // Make sure some -mcpu override exists for now to prevent | |
| 342 // auto-cpu feature detection from triggering instructions that | |
| 343 // we do not validate yet. | |
| 344 if (!HadCPUOverride(extra_vec.get())) { | |
| 345 AddDefaultCPU(cmd_line_vec); | |
| 346 } | |
| 347 extra_vec.reset(NULL); | |
| 348 // cmd_line_vec is freed by the translation thread in run_streamed. | |
| 349 do_stream_init(rpc, in_args, out_args, done, cmd_line_vec); | |
| 350 } | |
| 351 | |
| 273 // Invoked by the StreamChunk RPC. Receives a chunk of the bitcode and | 352 // Invoked by the StreamChunk RPC. Receives a chunk of the bitcode and |
| 274 // buffers it for later retrieval by the compilation thread. | 353 // buffers it for later retrieval by the compilation thread. |
| 275 void stream_chunk(NaClSrpcRpc *rpc, | 354 void stream_chunk(NaClSrpcRpc *rpc, |
| 276 NaClSrpcArg **in_args, | 355 NaClSrpcArg **in_args, |
| 277 NaClSrpcArg **out_args, | 356 NaClSrpcArg **out_args, |
| 278 NaClSrpcClosure *done) { | 357 NaClSrpcClosure *done) { |
| 279 NaClSrpcClosureRunner runner(done); | 358 NaClSrpcClosureRunner runner(done); |
| 280 rpc->result = NACL_SRPC_RESULT_APP_ERROR; | 359 rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| 281 size_t len = in_args[0]->u.count; | 360 size_t len = in_args[0]->u.count; |
| 282 unsigned char *bytes = reinterpret_cast<unsigned char*>( | 361 unsigned char *bytes = reinterpret_cast<unsigned char*>( |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 311 } | 390 } |
| 312 | 391 |
| 313 const struct NaClSrpcHandlerDesc srpc_methods[] = { | 392 const struct NaClSrpcHandlerDesc srpc_methods[] = { |
| 314 // Protocol for streaming: | 393 // Protocol for streaming: |
| 315 // (StreamInit(obj_fd) -> error_str | | 394 // (StreamInit(obj_fd) -> error_str | |
| 316 // StreamInitWIthCommandLine(obj_fd, escaped_cmdline) -> error_str) | 395 // StreamInitWIthCommandLine(obj_fd, escaped_cmdline) -> error_str) |
| 317 // StreamChunk(data) + | 396 // StreamChunk(data) + |
| 318 // StreamEnd() -> (is_shared_lib,soname,dependencies,error_str) | 397 // StreamEnd() -> (is_shared_lib,soname,dependencies,error_str) |
| 319 { "StreamInit:h:s", stream_init }, | 398 { "StreamInit:h:s", stream_init }, |
| 320 { "StreamInitWithCommandLine:hC:s:", stream_init_with_command_line }, | 399 { "StreamInitWithCommandLine:hC:s:", stream_init_with_command_line }, |
| 400 { "StreamInitWithOverrides:hC:s:", stream_init_with_overrides }, | |
| 321 { "StreamChunk:C:", stream_chunk }, | 401 { "StreamChunk:C:", stream_chunk }, |
| 322 { "StreamEnd::isss", stream_end }, | 402 { "StreamEnd::isss", stream_end }, |
| 323 { NULL, NULL }, | 403 { NULL, NULL }, |
| 324 }; | 404 }; |
| 325 | 405 |
| 326 } // namespace | 406 } // namespace |
| 327 | 407 |
| 328 int | 408 int |
| 329 main() { | 409 main() { |
| 330 if (!NaClSrpcModuleInit()) { | 410 if (!NaClSrpcModuleInit()) { |
| 331 return 1; | 411 return 1; |
| 332 } | 412 } |
| 333 | 413 |
| 334 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { | 414 if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
| 335 return 1; | 415 return 1; |
| 336 } | 416 } |
| 337 NaClSrpcModuleFini(); | 417 NaClSrpcModuleFini(); |
| 338 return 0; | 418 return 0; |
| 339 } | 419 } |
| 340 | 420 |
| 341 #endif | 421 #endif |
| OLD | NEW |