Index: src/IceBrowserCompileServer.cpp |
diff --git a/src/IceBrowserCompileServer.cpp b/src/IceBrowserCompileServer.cpp |
index 3b9dc3fa993e5a91691b6945184adf78d703e356..0b622df696561b9215761a7d9a18ebeea97e9803 100644 |
--- a/src/IceBrowserCompileServer.cpp |
+++ b/src/IceBrowserCompileServer.cpp |
@@ -15,6 +15,7 @@ |
// Can only compile this with the NaCl compiler (needs irt.h, and the |
// unsandboxed LLVM build using the trusted compiler does not have irt.h). |
#include "IceBrowserCompileServer.h" |
+#include "IceRangeSpec.h" |
#if PNACL_BROWSER_TRANSLATOR |
@@ -27,6 +28,7 @@ |
#include "llvm/Support/QueueStreamer.h" |
#include <cstring> |
+#include <fstream> |
#include <irt.h> |
#include <irt_dev.h> |
#include <pthread.h> |
@@ -48,6 +50,60 @@ void getIRTInterfaces() { |
llvm::report_fatal_error("Failed to get translator compile IRT interface"); |
} |
+// Allow pnacl-sz arguments to be supplied externally, instead of coming from |
+// the browser. This is meant to be used for debugging. |
+// |
+// If the SZARGFILE environment variable is set to a file name, arguments are |
+// read from that file, one argument per line. This requires setting 3 |
+// environment variables before starting the browser: |
+// |
+// NACL_ENV_PASSTHROUGH=NACL_DANGEROUS_ENABLE_FILE_ACCESS,NACLENV_SZARGFILE |
+// NACL_DANGEROUS_ENABLE_FILE_ACCESS=1 |
+// NACLENV_SZARGFILE=/path/to/myargs.txt |
+// |
+// In addition, Chrome needs to be launched with the "--no-sandbox" argument. |
+// |
+// If the SZARGLIST environment variable is set, arguments are extracted from |
+// that variable's value, separated by the '|' character (being careful to |
+// escape/quote special shell characters). This requires setting 2 environment |
+// variables before starting the browser: |
+// |
+// NACL_ENV_PASSTHROUGH=NACLENV_SZARGLIST |
+// NACLENV_SZARGLIST=arg |
+// |
+// This does not require the "--no-sandbox" argument, and is therefore much |
+// safer, but does require restarting the browser to change the arguments. |
+// |
+// If external arguments are supplied, the browser's NumThreads specification is |
+// ignored, to allow -threads to be specified as an external argument. Note |
+// that the browser normally supplies the "-O2" argument, so externally supplied |
+// arguments might want to provide an explicit -O argument. |
+std::vector<std::string> getExternalArgs() { |
+ std::vector<std::string> ExternalArgs; |
+ if (BuildDefs::minimal()) |
+ return ExternalArgs; |
+ char ArgsFileVar[] = "SZARGFILE"; |
+ char ArgsListVar[] = "SZARGLIST"; |
+ if (const char *ArgsFilename = getenv(ArgsFileVar)) { |
+ std::ifstream ArgsStream(ArgsFilename); |
+ std::string Arg; |
+ while (ArgsStream >> std::ws, std::getline(ArgsStream, Arg)) { |
+ if (!Arg.empty() && Arg[0] == '#') |
+ continue; |
+ ExternalArgs.emplace_back(Arg); |
+ } |
+ if (ExternalArgs.empty()) { |
+ llvm::report_fatal_error("Failed to read arguments from file '" + |
+ std::string(ArgsFilename) + "'"); |
+ } |
+ } else if (const char *ArgsList = getenv(ArgsListVar)) { |
+ // Leverage the RangeSpec tokenizer. |
+ auto Args = RangeSpec::tokenize(ArgsList, '|'); |
+ ExternalArgs.insert(ExternalArgs.end(), Args.begin(), Args.end()); |
+ } |
+ return ExternalArgs; |
+} |
+ |
char *onInitCallback(uint32_t NumThreads, int *ObjFileFDs, |
size_t ObjFileFDCount, char **CLArgs, size_t CLArgsLen) { |
if (ObjFileFDCount < 1) { |
@@ -65,16 +121,27 @@ char *onInitCallback(uint32_t NumThreads, int *ObjFileFDs, |
return strdup(StrBuf.str().c_str()); |
} |
// CLArgs is almost an "argv", but is missing the argv[0] program name. |
- std::vector<char *> Argv; |
- char ProgramName[] = "pnacl-sz.nexe"; |
+ std::vector<const char *> Argv; |
+ constexpr static char ProgramName[] = "pnacl-sz.nexe"; |
Argv.reserve(CLArgsLen + 1); |
Argv.push_back(ProgramName); |
- for (size_t i = 0; i < CLArgsLen; ++i) { |
- Argv.push_back(CLArgs[i]); |
+ |
+ bool UseNumThreadsFromBrowser = true; |
+ auto ExternalArgs = getExternalArgs(); |
+ if (ExternalArgs.empty()) { |
+ for (size_t i = 0; i < CLArgsLen; ++i) { |
+ Argv.push_back(CLArgs[i]); |
+ } |
+ } else { |
+ for (auto &Arg : ExternalArgs) { |
+ Argv.emplace_back(Arg.c_str()); |
+ } |
+ UseNumThreadsFromBrowser = false; |
} |
// NOTE: strings pointed to by argv are owned by the caller, but we parse |
// here before returning and don't store them. |
- gCompileServer->getParsedFlags(NumThreads, Argv.size(), Argv.data()); |
+ gCompileServer->getParsedFlags(UseNumThreadsFromBrowser, NumThreads, |
+ Argv.size(), Argv.data()); |
gCompileServer->startCompileThread(ObjFileFD); |
return nullptr; |
} |
@@ -162,12 +229,14 @@ void BrowserCompileServer::run() { |
gIRTFuncs.serve_translate_request(&SubzeroCallbacks); |
} |
-void BrowserCompileServer::getParsedFlags(uint32_t NumThreads, int argc, |
- char **argv) { |
+void BrowserCompileServer::getParsedFlags(bool UseNumThreadsFromBrowser, |
+ uint32_t NumThreads, int argc, |
+ const char *const *argv) { |
ClFlags::parseFlags(argc, argv); |
ClFlags::getParsedClFlags(ClFlags::Flags); |
// Set some defaults which aren't specified via the argv string. |
- ClFlags::Flags.setNumTranslationThreads(NumThreads); |
+ if (UseNumThreadsFromBrowser) |
+ ClFlags::Flags.setNumTranslationThreads(NumThreads); |
ClFlags::Flags.setUseSandboxing(true); |
ClFlags::Flags.setOutFileType(FT_Elf); |
ClFlags::Flags.setTargetArch(getTargetArch()); |
@@ -206,8 +275,19 @@ void BrowserCompileServer::endInputStream() { InputStream->SetDone(); } |
void BrowserCompileServer::startCompileThread(int ObjFD) { |
InputStream = new llvm::QueueStreamer(); |
- LogStream = getOutputStream(STDOUT_FILENO); |
+ bool LogStreamFailure = false; |
+ int LogFD = STDOUT_FILENO; |
+ if (getFlags().getLogFilename() == "/dev/stderr") { |
+ LogFD = STDERR_FILENO; |
+ } else { |
+ LogStreamFailure = true; |
+ } |
+ LogStream = getOutputStream(LogFD); |
LogStream->SetUnbuffered(); |
+ if (LogStreamFailure) { |
+ *LogStream |
+ << "Warning: Log file name must be either '-' or '/dev/stderr'\n"; |
+ } |
EmitStream = getOutputStream(ObjFD); |
EmitStream->SetBufferSize(1 << 14); |
std::unique_ptr<StringStream> ErrStrm(new StringStream()); |