Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(316)

Side by Side Diff: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc

Issue 8786005: Move command line processing out of coordinator (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "native_client/src/trusted/plugin/pnacl_coordinator.h" 5 #include "native_client/src/trusted/plugin/pnacl_coordinator.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "native_client/src/include/portability_io.h" 10 #include "native_client/src/include/portability_io.h"
11 #include "native_client/src/shared/platform/nacl_check.h" 11 #include "native_client/src/shared/platform/nacl_check.h"
12 #include "native_client/src/shared/platform/nacl_sync_raii.h" 12 #include "native_client/src/shared/platform/nacl_sync_raii.h"
13 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" 13 #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
14 #include "native_client/src/trusted/plugin/browser_interface.h" 14 #include "native_client/src/trusted/plugin/browser_interface.h"
15 #include "native_client/src/trusted/plugin/nacl_subprocess.h" 15 #include "native_client/src/trusted/plugin/nacl_subprocess.h"
16 #include "native_client/src/trusted/plugin/nexe_arch.h" 16 #include "native_client/src/trusted/plugin/nexe_arch.h"
17 #include "native_client/src/trusted/plugin/plugin.h" 17 #include "native_client/src/trusted/plugin/plugin.h"
18 #include "native_client/src/trusted/plugin/plugin_error.h" 18 #include "native_client/src/trusted/plugin/plugin_error.h"
19 #include "native_client/src/trusted/plugin/pnacl_srpc_lib.h" 19 #include "native_client/src/trusted/plugin/pnacl_srpc_lib.h"
20 #include "native_client/src/trusted/plugin/scriptable_handle.h"
21 #include "native_client/src/trusted/plugin/utility.h" 20 #include "native_client/src/trusted/plugin/utility.h"
22 21
23 #include "ppapi/c/pp_errors.h" 22 #include "ppapi/c/pp_errors.h"
23 #include "ppapi/c/ppb_file_io.h"
24 #include "ppapi/cpp/file_io.h"
25
26 namespace plugin {
27
28 class Plugin;
24 29
25 namespace { 30 namespace {
26 31
27 typedef std::vector<nacl::string> string_vector; 32 const char kLlcUrl[] = "llc";
28 int32_t kArbitraryStackSize = 128 << 10; 33 const char kLdUrl[] = "ld";
34
35 // Fake filename for the object file generated by llvm.
36 nacl::string ResourceBaseUrl() {
37 return nacl::string("pnacl_support/") + GetSandboxISA() + "/";
38 }
39
40 // Lookup service called by translator nexes.
41 // TODO(sehr): replace this lookup by ReverseService.
42 void LookupInputFile(NaClSrpcRpc* rpc,
43 NaClSrpcArg** inputs,
44 NaClSrpcArg** outputs,
45 NaClSrpcClosure* done) {
46 NaClSrpcClosureRunner runner(done);
47 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
48 const char* file_name = inputs[0]->arrays.str;
49 PnaclTranslationUnit* translation = reinterpret_cast<PnaclTranslationUnit*>(
50 rpc->channel->server_instance_data);
51 PnaclCoordinator* coordinator = translation->coordinator;
52 PnaclResources* resources = coordinator->resources();
53 // This filename is part of the contract with the linker.
54 // TODO(sehr): Pass the FD in, and move lookup for this file to the linker.
55 const nacl::string kGeneratedObjectFileName = "___PNACL_GENERATED";
56 if (nacl::string(file_name) == kGeneratedObjectFileName) {
57 outputs[0]->u.hval = translation->obj_file->read_wrapper()->desc();
58 } else {
59 nacl::DescWrapper* wrapper = translation->LookupDesc(inputs[0]->arrays.str);
60 outputs[0]->u.hval = wrapper->desc();
61 }
62 rpc->result = NACL_SRPC_RESULT_OK;
63 }
64
65 NaClSrpcHandlerDesc lookup_methods[] = {
66 { "LookupInputFile:s:h", LookupInputFile },
67 { NULL, NULL }
68 };
69
70 void AbortTranslateThread(PnaclTranslationUnit* translation_unit,
71 const nacl::string& error_string) {
72 pp::Core* core = pp::Module::Get()->core();
73 translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
74 core->CallOnMainThread(0, translation_unit->translate_done_cb,
75 PP_ERROR_FAILED);
76 NaClThreadExit(1);
77 }
78
79 void WINAPI DoTranslateThread(void* arg) {
80 PnaclTranslationUnit* trans = reinterpret_cast<PnaclTranslationUnit*>(arg);
81 PnaclCoordinator* coordinator = trans->coordinator;
82 NaClSubprocess* llc_subprocess = coordinator->llc_subprocess();
83 Plugin* plugin = coordinator->plugin();
84 BrowserInterface* browser_interface = plugin->browser_interface();
85
86 // Run LLC.
87 SrpcParams params;
88 nacl::DescWrapper* llc_out_file = trans->obj_file->write_wrapper();
89 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
90 llc_subprocess,
91 "RunWithDefaultCommandLine",
92 "hh",
93 &params,
94 trans->pexe_wrapper->desc(),
95 llc_out_file->desc())) {
96 AbortTranslateThread(trans, "PnaclCoordinator compile failed.");
97 }
98 // LLC returns values that are used to determine how linking is cone.
99 int is_shared_library = (params.outs()[0]->u.ival != 0);
100 nacl::string soname = params.outs()[1]->arrays.str;
101 nacl::string lib_dependencies = params.outs()[2]->arrays.str;
102 PLUGIN_PRINTF(("PnaclCoordinator::Compile (trans=%p) succeeded"
103 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n",
104 arg, is_shared_library, soname.c_str(),
105 lib_dependencies.c_str()));
106 if (coordinator->SubprocessesShouldDie()) {
107 NaClThreadExit(1);
108 }
109 // Set up the lookup service for filename to handle resolution.
110 NaClSrpcService* service =
111 reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service)));
112 if (NULL == service) {
113 AbortTranslateThread(trans,
114 "PnaclCoordinator: lookup service alloc failed.");
115 }
116 if (!NaClSrpcServiceHandlerCtor(service, lookup_methods)) {
117 free(service);
118 AbortTranslateThread(trans,
119 "PnaclCoordinator: lookup service ctor failed.");
120 }
121 char* service_string = const_cast<char*>(service->service_string);
122 NaClSubprocess* ld_subprocess = coordinator->ld_subprocess();
123 ld_subprocess->srpc_client()->AttachService(service, trans);
124 nacl::DescWrapper* ld_out_file = trans->nexe_file->write_wrapper();
125 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
126 ld_subprocess,
127 "RunWithDefaultCommandLine",
128 "ChiCC",
129 &params,
130 service_string,
131 ld_out_file->desc(),
132 is_shared_library,
133 soname.c_str(),
134 lib_dependencies.c_str())) {
135 AbortTranslateThread(trans, "PnaclCoordinator link failed.");
136 }
137 PLUGIN_PRINTF(("PnaclCoordinator Link(trans=%p) succeeded", arg));
138 if (coordinator->SubprocessesShouldDie()) {
139 NaClThreadExit(1);
140 }
141 pp::Core* core = pp::Module::Get()->core();
142 core->CallOnMainThread(0, trans->translate_done_cb, PP_OK);
143 NaClThreadExit(0);
144 }
29 145
30 } // namespace 146 } // namespace
31 147
32 namespace plugin { 148 //////////////////////////////////////////////////////////////////////
33 149 PnaclFileDescPair::PnaclFileDescPair(pp::FileSystem* file_system,
34 class Plugin; 150 PnaclCoordinator* coordinator)
35 151 : file_system_(file_system),
152 coordinator_(coordinator) {
153 callback_factory_.Initialize(this);
154 CHECK(NaClDescRngCtor(&rng_desc_));
155 file_io_trusted_= static_cast<const PPB_FileIOTrusted*>(
156 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE));
157 // Get a random temp file name.
158 struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(&rng_desc_);
159 const struct NaClDescVtbl* vtbl =
160 reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl);
161 // Filename consists of a slash then 32 random characters.
162 filename_ = "/";
163 const int32_t kTempFileNameWords = 4;
164 for (int32_t i = 0; i < kTempFileNameWords; ++i) {
165 int32_t num;
166 CHECK(sizeof num == vtbl->Read(desc,
167 reinterpret_cast<char*>(&num),
168 sizeof num));
169 char frag[16];
170 SNPRINTF(frag, sizeof frag, "%08x", num);
171 filename_ += nacl::string(frag);
172 }
173 }
174
175 PnaclFileDescPair::~PnaclFileDescPair() {
176 NaClDescUnref(reinterpret_cast<NaClDesc*>(&rng_desc_));
177 }
178
179 void PnaclFileDescPair::Open(const pp::CompletionCallback& cb) {
180 PLUGIN_PRINTF(("PnaclFileDescPair::Open\n"));
181 done_callback_ = cb;
182
183 write_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
184 write_io_.reset(new pp::FileIO(coordinator_->plugin()));
185 read_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
186 read_io_.reset(new pp::FileIO(coordinator_->plugin()));
187
188 pp::CompletionCallback open_write_cb =
189 callback_factory_.NewCallback(&PnaclFileDescPair::WriteFileDidOpen);
190 // Open the writeable file.
191 write_io_->Open(*write_ref_,
192 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE,
193 open_write_cb);
194 }
195
196 int32_t PnaclFileDescPair::GetFD(int32_t pp_error,
197 const pp::Resource& resource,
198 const nacl::string& component) {
199 if (pp_error != PP_OK) {
200 coordinator_->ReportPpapiError(pp_error,
201 nacl::string("PnaclFileDescPair: Open ") +
202 component + " failed\n");
203 return -1;
204 }
205 int32_t file_desc = file_io_trusted_->GetOSFileDescriptor(
206 resource.pp_resource());
207 #if NACL_WINDOWS
208 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
209 int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY);
210 if (posix_desc == -1) {
211 // Close the Windows HANDLE if it can't be converted.
212 CloseHandle(reinterpret_cast<HANDLE>(file_desc));
213 return NACL_NO_FILE_DESC;
214 }
215 file_desc = posix_desc;
216 #endif
217 int32_t file_desc_ok_to_close = DUP(file_desc);
218 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
219 coordinator_->ReportPpapiError(pp_error,
220 nacl::string("PnaclFileDescPair: FD for ") +
221 component + " failed\n");
222 return -1;
223 }
224 return file_desc_ok_to_close;
225 }
226
227 void PnaclFileDescPair::WriteFileDidOpen(int32_t pp_error) {
228 PLUGIN_PRINTF(("PnaclFileDescPair::WriteFileDidOpen (pp_error=%"
229 NACL_PRId32")\n", pp_error));
230 // Remember the object temporary file descriptor.
231 int32_t fd = GetFD(pp_error, *write_io_, "write");
232 if (fd < 0) {
233 return;
234 }
235 write_wrapper_.reset(
236 coordinator_->plugin()->wrapper_factory()->MakeFileDesc(fd, O_RDWR));
237 pp::CompletionCallback open_read_cb =
238 callback_factory_.NewCallback(&PnaclFileDescPair::ReadFileDidOpen);
239 // Open the read only file.
240 read_io_->Open(*read_ref_, PP_FILEOPENFLAG_READ, open_read_cb);
241 }
242
243 void PnaclFileDescPair::ReadFileDidOpen(int32_t pp_error) {
244 PLUGIN_PRINTF(("PnaclFileDescPair::ReadFileDidOpen (pp_error=%"
245 NACL_PRId32")\n", pp_error));
246 // Remember the object temporary file descriptor.
247 int32_t fd = GetFD(pp_error, *read_io_, "read");
248 if (fd < 0) {
249 return;
250 }
251 read_wrapper_.reset(
252 coordinator_->plugin()->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
253 // Run the client's completion callback.
254 pp::Core* core = pp::Module::Get()->core();
255 core->CallOnMainThread(0, done_callback_, PP_OK);
256 }
257
258 //////////////////////////////////////////////////////////////////////
259 void PnaclTranslationUnit::LoadOneFile(int32_t pp_error,
260 const nacl::string& url,
261 nacl::DescWrapper** wrapper,
262 pp::CompletionCallback& done_cb) {
263 PLUGIN_PRINTF(("PnaclCoordinator::LoadOneFile (pp_error=%"
264 NACL_PRId32", url=%s)\n", pp_error, url.c_str()));
265 Plugin* plugin = coordinator->plugin();
266 const nacl::string& full_url = coordinator->resource_base_url() + url;
267 pp::CompletionCallback callback =
268 callback_factory.NewCallback(&PnaclTranslationUnit::DidLoadFile,
269 full_url,
270 wrapper,
271 done_cb);
272 if (!plugin->StreamAsFile(full_url, callback.pp_completion_callback())) {
273 coordinator->ReportNonPpapiError("PnaclCoordinator: Failed to load: " +
274 url + "\n");
275 }
276 }
277
278 void PnaclTranslationUnit::DidLoadFile(int32_t pp_error,
279 const nacl::string& full_url,
280 nacl::DescWrapper** wrapper,
281 pp::CompletionCallback& done_cb) {
282 PLUGIN_PRINTF(("PnaclCoordinator::DidLoadFile (pp_error=%"
283 NACL_PRId32", url=%s)\n", pp_error, full_url.c_str()));
284 int32_t fd = coordinator->GetLoadedFileDesc(pp_error, full_url, "resource");
285 if (fd < 0) {
286 return;
287 }
288 Plugin* plugin = coordinator->plugin();
289 *wrapper = plugin->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
290 done_cb.Run(PP_OK);
291 }
292
293 void PnaclTranslationUnit::ResumeLookup(int32_t pp_error,
294 PnaclTranslationUnit* trans) {
295 UNREFERENCED_PARAMETER(pp_error);
296 nacl::MutexLocker ml(&mu);
297 trans->lookup_is_complete = true;
298 NaClXCondVarBroadcast(&cv);
299 }
300
301 nacl::DescWrapper* PnaclTranslationUnit::LookupDesc(const nacl::string& url) {
302 nacl::DescWrapper* wrapper;
303 // Create the callback used to report when lookup is done.
304 pp::CompletionCallback resume_cb =
305 callback_factory.NewCallback(&PnaclTranslationUnit::ResumeLookup, this);
306 // Run the lookup request on the main thread.
307 lookup_is_complete = false;
308 pp::CompletionCallback load_cb =
309 callback_factory.NewCallback(&PnaclTranslationUnit::LoadOneFile,
310 url, &wrapper, resume_cb);
311 pp::Core* core = pp::Module::Get()->core();
312 core->CallOnMainThread(0, load_cb, PP_OK);
313 // Wait for completion (timeout every 10ms to check for process end).
314 const int32_t kTenMilliseconds = 10 * 1000 * 1000;
315 NACL_TIMESPEC_T reltime;
316 reltime.tv_sec = 0;
317 reltime.tv_nsec = kTenMilliseconds;
318 NaClXMutexLock(&mu);
319 while (!lookup_is_complete) {
320 // Check for termination.
321 if (coordinator->SubprocessesShouldDie()) {
322 NaClXMutexUnlock(&mu);
323 NaClThreadExit(0);
324 }
325 NaClXCondVarTimedWaitRelative(&cv, &mu, &reltime);
326 }
327 NaClXMutexUnlock(&mu);
328 return wrapper;
329 }
330
331 //////////////////////////////////////////////////////////////////////
36 void PnaclCoordinator::Initialize(Plugin* plugin) { 332 void PnaclCoordinator::Initialize(Plugin* plugin) {
37 PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n", 333 PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n",
38 static_cast<void*>(this))); 334 static_cast<void*>(this)));
39 CHECK(plugin != NULL); 335 CHECK(plugin != NULL);
40 CHECK(plugin_ == NULL); // Can only initialize once. 336 CHECK(plugin_ == NULL); // Can only initialize once.
41 plugin_ = plugin; 337 plugin_ = plugin;
42 callback_factory_.Initialize(this); 338 callback_factory_.Initialize(this);
339 // Open the temporary file system.
340 file_system_.reset(new pp::FileSystem(plugin,
341 PP_FILESYSTEMTYPE_LOCALTEMPORARY));
342 CHECK(file_system_ != NULL);
343 // Preload llc and ld.
344 resource_base_url_ = ResourceBaseUrl();
43 resources_.reset(new PnaclResources(plugin, this)); 345 resources_.reset(new PnaclResources(plugin, this));
346 CHECK(resources_ != NULL);
44 resources_->Initialize(); 347 resources_->Initialize();
348 pp::CompletionCallback resources_cb =
349 callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad);
350 resources_->AddResourceUrl(kLlcUrl);
351 resources_->AddResourceUrl(kLdUrl);
352 resources_->RunWhenAllLoaded(resources_cb);
353 resources_->StartDownloads();
354 // ResourcesDidLoad will be invoked when all resources have been received.
355 // Initialization of the file system continues through that chain.
45 } 356 }
46 357
47 PnaclCoordinator::~PnaclCoordinator() { 358 PnaclCoordinator::~PnaclCoordinator() {
48 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", 359 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n",
49 static_cast<void*>(this))); 360 static_cast<void*>(this)));
50 361 // Join helper thread which will block the page from refreshing while a
51 // Join helper threads which will block the page from refreshing while a
52 // translation is happening. 362 // translation is happening.
53 if (translate_thread_.get() != NULL || link_thread_.get() != NULL) { 363 if (translate_thread_.get() != NULL) {
54 SetSubprocessesShouldDie(true); 364 SetSubprocessesShouldDie(true);
55 }
56 if (translate_thread_.get() != NULL) {
57 NaClThreadJoin(translate_thread_.get()); 365 NaClThreadJoin(translate_thread_.get());
58 } 366 }
59 if (link_thread_.get() != NULL) {
60 NaClThreadJoin(link_thread_.get());
61 }
62 } 367 }
63 368
64 void PnaclCoordinator::ReportLoadAbort() { 369 void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) {
65 plugin_->ReportLoadAbort(); 370 ErrorInfo error_info;
371 error_info.SetReport(ERROR_UNKNOWN, message);
372 ReportPpapiError(PP_ERROR_FAILED, error_info);
66 } 373 }
67 374
68 void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) { 375 void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
69 plugin_->ReportLoadError(error); 376 const nacl::string& message) {
377 ErrorInfo error_info;
378 error_info.SetReport(ERROR_UNKNOWN, message);
379 ReportPpapiError(pp_error, error_info);
70 } 380 }
71 381
72 void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) { 382 void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
73 // Attempt to free all the intermediate callbacks we ever created. 383 const ErrorInfo& error_info) {
384 plugin()->ReportLoadError(error_info);
385 // Free all the intermediate callbacks we ever created.
74 callback_factory_.CancelAll(); 386 callback_factory_.CancelAll();
75 translate_notify_callback_.Run(pp_error); 387 translate_notify_callback_.Run(pp_error);
76 } 388 }
77 389
78 void PnaclCoordinator::PnaclNonPpapiError() {
79 PnaclPpapiError(PP_ERROR_FAILED);
80 }
81
82 void PnaclCoordinator::PnaclDidFinish(int32_t pp_error, 390 void PnaclCoordinator::PnaclDidFinish(int32_t pp_error,
83 PnaclTranslationUnit* translation_unit) { 391 PnaclTranslationUnit* translation_unit) {
84 PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%" 392 PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%"
85 NACL_PRId32")\n", pp_error)); 393 NACL_PRId32")\n", pp_error));
86 if (pp_error != PP_OK) { 394 if (pp_error != PP_OK) {
87 ReportLoadError(translation_unit->error_info); 395 ReportPpapiError(pp_error, translation_unit->error_info);
88 PnaclPpapiError(pp_error);
89 return; 396 return;
90 } 397 }
91 // Transfer ownership of the nexe wrapper to the coordinator. 398 // Transfer ownership of the nexe wrapper to the coordinator.
92 translated_fd_.reset(translation_unit->nexe_wrapper.release()); 399 // TODO(sehr): need to release the translation unit here while transferring.
400 translated_fd_.reset(translation_unit->nexe_file->read_wrapper());
93 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); 401 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
94 translate_notify_callback_.Run(pp_error); 402 translate_notify_callback_.Run(pp_error);
95 } 403 }
96 404
97 //////////////////////////////////////////////////////////////////////
98
99 int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error, 405 int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
100 const nacl::string& url, 406 const nacl::string& url,
101 const nacl::string& component) { 407 const nacl::string& component) {
102 ErrorInfo error_info; 408 ErrorInfo error_info;
103 int32_t file_desc = plugin_->GetPOSIXFileDesc(url); 409 int32_t file_desc = plugin_->GetPOSIXFileDesc(url);
104 if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) { 410 if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
105 if (pp_error == PP_ERROR_ABORTED) { 411 if (pp_error == PP_ERROR_ABORTED) {
106 ReportLoadAbort(); 412 plugin_->ReportLoadAbort();
107 } else { 413 } else {
108 // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? 414 ReportPpapiError(pp_error,
109 error_info.SetReport(ERROR_UNKNOWN, 415 "PnaclCoordinator: " + component + " load failed.\n");
110 "PNaCl " + component + " load failed.");
111 ReportLoadError(error_info);
112 } 416 }
113 return -1; 417 return -1;
114 } 418 }
115 int32_t file_desc_ok_to_close = DUP(file_desc); 419 int32_t file_desc_ok_to_close = DUP(file_desc);
116 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { 420 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
117 // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? 421 ReportPpapiError(PP_ERROR_FAILED,
118 error_info.SetReport(ERROR_UNKNOWN, 422 "PnaclCoordinator: " + component + " could not dup fd.\n");
119 "PNaCl " + component + " load failed: "
120 "could not dup fd.");
121 ReportLoadError(error_info);
122 return -1; 423 return -1;
123 } 424 }
124 return file_desc_ok_to_close; 425 return file_desc_ok_to_close;
125 } 426 }
126 427
127 bool PnaclCoordinator::StartLlcSubProcess() { 428 NaClSubprocess* PnaclCoordinator::StartSubProcess(const nacl::string& url) {
128 ErrorInfo error_info; 429 ErrorInfo error_info;
129 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(llc_url_); 430 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url);
130 NaClSubprocessId llc_id = plugin_->LoadHelperNaClModule(wrapper, &error_info); 431 NaClSubprocessId id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
131 PLUGIN_PRINTF(("PnaclCoordinator::StartLlcSubProcess (nexe_id=%" 432 PLUGIN_PRINTF(("PnaclCoordinator::StartSubProcess (nexe_id=%"
132 NACL_PRId32")\n", llc_id)); 433 NACL_PRId32", url=%s)\n", id, url.c_str()));
133 if (kInvalidNaClSubprocessId == llc_id) { 434 if (kInvalidNaClSubprocessId == id) {
134 error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl compiler nexe");
135 ReportLoadError(error_info);
136 PnaclNonPpapiError();
137 return NULL; 435 return NULL;
138 } 436 }
139 llc_subprocess_ = plugin_->nacl_subprocess(llc_id); 437 return plugin_->nacl_subprocess(id);
140 return (llc_subprocess_ != NULL);
141 }
142
143 bool PnaclCoordinator::StartLdSubProcess() {
144 ErrorInfo error_info;
145 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(ld_url_);
146 NaClSubprocessId ld_id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
147 PLUGIN_PRINTF(("PnaclCoordinator::StartLdSubProcess (nexe_id=%"
148 NACL_PRId32")\n", ld_id));
149 if (kInvalidNaClSubprocessId == ld_id) {
150 error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl linker nexe");
151 ReportLoadError(error_info);
152 PnaclNonPpapiError();
153 return NULL;
154 }
155 ld_subprocess_ = plugin_->nacl_subprocess(ld_id);
156 return (ld_subprocess_ != NULL);
157 } 438 }
158 439
159 bool PnaclCoordinator::SubprocessesShouldDie() { 440 bool PnaclCoordinator::SubprocessesShouldDie() {
160 nacl::MutexLocker ml(&subprocess_mu_); 441 nacl::MutexLocker ml(&subprocess_mu_);
161 return subprocesses_should_die_; 442 return subprocesses_should_die_;
162 } 443 }
163 444
164 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) { 445 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) {
165 nacl::MutexLocker ml(&subprocess_mu_); 446 nacl::MutexLocker ml(&subprocess_mu_);
166 subprocesses_should_die_ = subprocesses_should_die; 447 subprocesses_should_die_ = subprocesses_should_die;
167 } 448 }
168 449
169 //////////////////////////////////////////////////////////////////////
170 // First few callbacks.
171
172 //////////////////////////////////////////////////////////////////////
173
174 namespace {
175 void AbortTranslateThread(PnaclTranslationUnit* translation_unit,
176 const nacl::string& error_string) {
177 pp::Core* core = pp::Module::Get()->core();
178 translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
179 core->CallOnMainThread(0, translation_unit->translate_done_cb,
180 PP_ERROR_FAILED);
181 NaClThreadExit(1);
182 }
183
184 void WINAPI DoTranslateThread(void* arg) {
185 PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
186 PnaclCoordinator* coordinator = p->coordinator;
187 NaClSubprocess* llc_subprocess = coordinator->llc_subprocess();
188 Plugin* plugin = coordinator->plugin();
189 BrowserInterface* browser = plugin->browser_interface();
190
191 // Set up LLC flags first.
192 // TODO(jvoung): Bake these into the llc nexe?
193 // May also want to improve scriptability, but the only thing we need
194 // probably is PIC vs non-PIC and micro-arch specification.
195 const char* llc_args_x8632[] = { "-march=x86",
196 "-mcpu=pentium4",
197 "-mtriple=i686-none-nacl-gnu",
198 "-asm-verbose=false",
199 "-filetype=obj" };
200 const char* llc_args_x8664[] = { "-march=x86-64",
201 "-mcpu=core2",
202 "-mtriple=x86_64-none-nacl-gnu",
203 "-asm-verbose=false",
204 "-filetype=obj" };
205 const char* llc_args_arm[] = { "-march=arm",
206 "-mcpu=cortex-a8",
207 "-mtriple=armv7a-none-nacl-gnueabi",
208 "-asm-verbose=false",
209 "-filetype=obj",
210 "-arm-reserve-r9",
211 "-sfi-disable-cp",
212 "-arm_static_tls",
213 "-sfi-store",
214 "-sfi-load",
215 "-sfi-stack",
216 "-sfi-branch",
217 "-sfi-data",
218 "-no-inline-jumptables" };
219
220 nacl::string sandbox_isa = GetSandboxISA();
221 const char** llc_args;
222 size_t num_args;
223
224 if (sandbox_isa.compare("x86-32") == 0) {
225 llc_args = llc_args_x8632;
226 num_args = NACL_ARRAY_SIZE(llc_args_x8632);
227 } else if (sandbox_isa.compare("x86-64") == 0) {
228 llc_args = llc_args_x8664;
229 num_args = NACL_ARRAY_SIZE(llc_args_x8664);
230 } else if (sandbox_isa.compare("arm") == 0) {
231 llc_args = llc_args_arm;
232 num_args = NACL_ARRAY_SIZE(llc_args_arm);
233 } else {
234 AbortTranslateThread(p,
235 "PnaclCoordinator compiler unhandled ISA " +
236 sandbox_isa + ".");
237 return;
238 }
239
240 for (uint32_t i = 0; i < num_args; i++) {
241 if (coordinator->SubprocessesShouldDie()) {
242 NaClThreadExit(1);
243 }
244 SrpcParams dummy_params;
245 if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
246 llc_subprocess,
247 "AddArg",
248 "C",
249 &dummy_params,
250 llc_args[i])) {
251 AbortTranslateThread(p,
252 "PnaclCoordinator compiler AddArg(" +
253 nacl::string(llc_args[i]) + ") failed.");
254 }
255 }
256
257 if (coordinator->SubprocessesShouldDie()) {
258 NaClThreadExit(1);
259 }
260 SrpcParams params;
261 if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
262 llc_subprocess,
263 "Translate",
264 "h",
265 &params,
266 p->pexe_wrapper->desc())) {
267 AbortTranslateThread(p,
268 "PnaclCoordinator compile failed.");
269 } else {
270 // Grab the outparams.
271 p->obj_wrapper.reset(
272 plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval));
273 p->obj_len = params.outs()[1]->u.ival;
274 p->is_shared_library = params.outs()[2]->u.ival != 0;
275 p->soname = params.outs()[3]->arrays.str;
276 p->lib_dependencies = params.outs()[4]->arrays.str;
277 PLUGIN_PRINTF(("PnaclCoordinator::Translate SRPC succeeded (bytes=%"
278 NACL_PRId32", is_shared_library=%d, soname='%s', "
279 "lib_dependencies='%s')\n", p->obj_len,
280 p->is_shared_library, p->soname.c_str(),
281 p->lib_dependencies.c_str()));
282 }
283 if (coordinator->SubprocessesShouldDie()) {
284 NaClThreadExit(1);
285 }
286 pp::Core* core = pp::Module::Get()->core();
287 core->CallOnMainThread(0, p->translate_done_cb, PP_OK);
288 NaClThreadExit(0);
289 }
290
291 } // namespace
292
293 void PnaclCoordinator::RunTranslate(int32_t pp_error, 450 void PnaclCoordinator::RunTranslate(int32_t pp_error,
294 const nacl::string& pexe_url,
295 PnaclTranslationUnit* translation_unit) { 451 PnaclTranslationUnit* translation_unit) {
296 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" 452 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
297 NACL_PRId32")\n", pp_error)); 453 NACL_PRId32")\n", pp_error));
298 // pp_error is checked by GetLoadedFileDesc. 454 int32_t fd = GetLoadedFileDesc(pp_error, translation_unit->pexe_url, "pexe");
299 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe");
300 if (fd < 0) { 455 if (fd < 0) {
301 PnaclPpapiError(pp_error);
302 return; 456 return;
303 } 457 }
304 translation_unit->pexe_wrapper.reset( 458 translation_unit->pexe_wrapper.reset(
305 plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY)); 459 plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
306 if (!StartLlcSubProcess()) { 460 llc_subprocess_ = StartSubProcess(kLlcUrl);
307 ErrorInfo error_info; 461 if (llc_subprocess_ == NULL) {
308 error_info.SetReport(ERROR_UNKNOWN, 462 ReportNonPpapiError(
309 "Could not start compiler subprocess\n"); 463 "PnaclCoordinator: Could not start compiler subprocess\n");
310 ReportLoadError(error_info);
311 PnaclNonPpapiError();
312 return; 464 return;
313 } 465 }
314 // Invoke llvm asynchronously. 466 ld_subprocess_ = StartSubProcess(kLdUrl);
315 // RunLink runs on the main thread when llvm is done. 467 if (ld_subprocess_ == NULL) {
468 ReportNonPpapiError(
469 "PnaclCoordinator: Could not start linker subprocess\n");
470 return;
471 }
472 // Invoke llc followed by ld off the main thread. This allows use of
473 // blocking RPCs that would otherwise block the JavaScript main thread.
316 translation_unit->translate_done_cb = 474 translation_unit->translate_done_cb =
317 callback_factory_.NewCallback(&PnaclCoordinator::RunLink, 475 callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish,
318 translation_unit); 476 translation_unit);
319 translate_thread_.reset(new NaClThread); 477 translate_thread_.reset(new NaClThread);
320 if (translate_thread_ == NULL) { 478 if (translate_thread_ == NULL) {
321 ErrorInfo error_info; 479 ReportNonPpapiError("PnaclCoordinator: Could not allocate thread struct\n");
322 error_info.SetReport(ERROR_UNKNOWN,
323 "Could not allocate DoTranslateThread()\n");
324 ReportLoadError(error_info);
325 PnaclNonPpapiError();
326 return; 480 return;
327 } 481 }
482 const int32_t kArbitraryStackSize = 128 << 10;
328 if (!NaClThreadCreateJoinable(translate_thread_.get(), 483 if (!NaClThreadCreateJoinable(translate_thread_.get(),
329 DoTranslateThread, 484 DoTranslateThread,
330 translation_unit, 485 translation_unit,
331 kArbitraryStackSize)) { 486 kArbitraryStackSize)) {
332 ErrorInfo error_info; 487 ReportNonPpapiError("PnaclCoordinator: Could not create thread\n");
333 error_info.SetReport(ERROR_UNKNOWN,
334 "Could not create a translator thread.\n");
335 ReportLoadError(error_info);
336 PnaclNonPpapiError();
337 } 488 }
338 } 489 }
339 490
340 ////////////////////////////////////////////////////////////////////// 491 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) {
341 // Helper functions for loading native libs. 492 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
342 // Done here to avoid hacking on the manifest parser further...
343
344 namespace {
345
346 // Fake filename for the object file generated by llvm.
347 nacl::string GeneratedObjectFileName() {
348 return nacl::string("___PNACL_GENERATED");
349 }
350
351 nacl::string ResourceBaseUrl() {
352 nacl::string sandbox_isa = GetSandboxISA();
353 nacl::string base_url = "pnacl_support/" + sandbox_isa + "/";
354 return base_url;
355 }
356
357 string_vector LinkResources(const nacl::string& sandbox_isa,
358 bool withGenerated) {
359 string_vector results;
360 // NOTE: order of items == link order.
361 if (sandbox_isa.compare("x86-64") == 0) {
362 results.push_back("libpnacl_irt_shim.a");
363 }
364 results.push_back("crtbegin.o");
365 if (withGenerated) {
366 results.push_back(GeneratedObjectFileName());
367 }
368 results.push_back("libcrt_platform.a");
369 results.push_back("libgcc.a");
370 results.push_back("libgcc_eh.a");
371 results.push_back("crtend.o");
372 return results;
373 }
374
375 } // namespace
376
377 //////////////////////////////////////////////////////////////////////
378 // Final link callbacks.
379
380 namespace {
381
382 void AbortLinkThread(PnaclTranslationUnit* translation_unit,
383 const nacl::string& error_string) {
384 ErrorInfo error_info;
385 pp::Core* core = pp::Module::Get()->core();
386 translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
387 core->CallOnMainThread(0, translation_unit->link_done_cb, PP_ERROR_FAILED);
388 NaClThreadExit(1);
389 }
390
391 void WINAPI DoLinkThread(void* arg) {
392 PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
393 PnaclCoordinator* coordinator = p->coordinator;
394 NaClSubprocess* ld_subprocess = coordinator->ld_subprocess();
395 Plugin* plugin = coordinator->plugin();
396 BrowserInterface* browser_interface = plugin->browser_interface();
397
398 // Set up command line arguments (flags then files).
399
400 //// Flags.
401 // TODO(jvoung): Be able to handle the dynamic linking flags too,
402 // and don't hardcode so much here.
403 string_vector flags;
404 nacl::string sandbox_isa = GetSandboxISA();
405 flags.push_back("-nostdlib");
406 flags.push_back("-m");
407 if (sandbox_isa.compare("x86-32") == 0) {
408 flags.push_back("elf_nacl");
409 } else if (sandbox_isa.compare("x86-64") == 0) {
410 flags.push_back("elf64_nacl");
411 flags.push_back("-entry=_pnacl_wrapper_start");
412 } else if (sandbox_isa.compare("arm") == 0) {
413 flags.push_back("armelf_nacl");
414 } else {
415 AbortLinkThread(p,
416 "PnaclCoordinator linker unhandled ISA " +
417 sandbox_isa + ".");
418 }
419
420 for (string_vector::iterator i = flags.begin(), e = flags.end();
421 i != e; ++i) {
422 const nacl::string& flag = *i;
423 if (coordinator->SubprocessesShouldDie()) {
424 NaClThreadExit(1);
425 }
426 SrpcParams dummy_params;
427 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
428 ld_subprocess,
429 "AddArg",
430 "C",
431 &dummy_params,
432 flag.c_str())) {
433 AbortLinkThread(p,
434 "PnaclCoordinator linker AddArg(" + flag +
435 ") failed.");
436 }
437 }
438
439 //// Files.
440 string_vector files = LinkResources(sandbox_isa, true);
441 PnaclResources* resources = coordinator->resources();
442 for (string_vector::iterator i = files.begin(), e = files.end();
443 i != e; ++i) {
444 const nacl::string& link_file = *i;
445 if (coordinator->SubprocessesShouldDie()) {
446 NaClThreadExit(1);
447 }
448 // Add as argument.
449 SrpcParams dummy_params;
450 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
451 ld_subprocess,
452 "AddArg",
453 "C",
454 &dummy_params,
455 link_file.c_str())) {
456 AbortLinkThread(p,
457 "PnaclCoordinator linker AddArg(" +
458 link_file + ") failed.");
459 }
460 // Also map the file name to descriptor.
461 if (i->compare(GeneratedObjectFileName()) == 0) {
462 SrpcParams dummy_params2;
463 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
464 ld_subprocess,
465 "AddFileWithSize",
466 "Chi",
467 &dummy_params2,
468 link_file.c_str(),
469 p->obj_wrapper->desc(),
470 p->obj_len)) {
471 AbortLinkThread(p,
472 "PnaclCoordinator linker AddFileWithSize"
473 "(" + link_file + ") failed.");
474 }
475 } else {
476 SrpcParams dummy_params2;
477 NaClDesc* link_file_desc = resources->WrapperForUrl(link_file)->desc();
478 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
479 ld_subprocess,
480 "AddFile",
481 "Ch",
482 &dummy_params2,
483 link_file.c_str(),
484 link_file_desc)) {
485 AbortLinkThread(p,
486 "PnaclCoordinator linker AddFile(" + link_file +
487 ") failed.");
488 }
489 }
490 }
491
492 if (coordinator->SubprocessesShouldDie()) {
493 NaClThreadExit(1);
494 }
495
496 // Finally, do the Link!
497 SrpcParams params;
498 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
499 ld_subprocess,
500 "Link",
501 "",
502 &params)) {
503 AbortLinkThread(p, "PnaclCoordinator link failed.");
504 } else {
505 // Grab the outparams.
506 p->nexe_wrapper.reset(
507 plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval));
508 int32_t nexe_size = params.outs()[1]->u.ival; // only for debug.
509 PLUGIN_PRINTF(("PnaclCoordinator::InvokeLink succeeded (bytes=%"
510 NACL_PRId32")\n", nexe_size));
511 }
512 if (coordinator->SubprocessesShouldDie()) {
513 NaClThreadExit(1);
514 }
515 pp::Core* core = pp::Module::Get()->core();
516 core->CallOnMainThread(0, p->link_done_cb, PP_OK);
517 NaClThreadExit(0);
518 }
519
520 } // namespace
521
522 void PnaclCoordinator::RunLink(int32_t pp_error,
523 PnaclTranslationUnit* translation_unit) {
524 PLUGIN_PRINTF(("PnaclCoordinator::RunLink (pp_error=%"
525 NACL_PRId32")\n", pp_error)); 493 NACL_PRId32")\n", pp_error));
526 if (pp_error != PP_OK) { 494 if (pp_error != PP_OK) {
527 ReportLoadError(translation_unit->error_info); 495 ReportPpapiError(pp_error, "PnaclCoordinator: resources failed to load\n");
528 PnaclPpapiError(pp_error);
529 return; 496 return;
530 } 497 }
531 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); 498 // Open the local temporary file system to create the temporary files
532 if (!StartLdSubProcess()) { 499 // for the object and nexe.
533 ErrorInfo error_info; 500 pp::CompletionCallback cb =
534 error_info.SetReport(ERROR_UNKNOWN, 501 callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen);
535 "Could not start linker subprocess\n"); 502 if (!file_system_->Open(0, cb)) {
536 ReportLoadError(error_info); 503 ReportNonPpapiError("PnaclCoordinator: failed to open file system.\n");
537 PnaclNonPpapiError();
538 return;
539 }
540
541 // Invoke ld asynchronously.
542 // When ld has completed, PnaclDidFinish is run on the main thread.
543 translation_unit->link_done_cb =
544 callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish,
545 translation_unit);
546 link_thread_.reset(new NaClThread);
547 if (link_thread_ == NULL) {
548 ErrorInfo error_info;
549 error_info.SetReport(ERROR_UNKNOWN,
550 "Could not allocate DoLinkThread()\n");
551 ReportLoadError(error_info);
552 PnaclNonPpapiError();
553 return;
554 }
555 if (!NaClThreadCreateJoinable(link_thread_.get(),
556 DoLinkThread,
557 translation_unit,
558 kArbitraryStackSize)) {
559 ErrorInfo error_info;
560 error_info.SetReport(ERROR_UNKNOWN,
561 "Could not create a linker thread.\n");
562 ReportLoadError(error_info);
563 PnaclNonPpapiError();
564 } 504 }
565 } 505 }
566 506
567 ////////////////////////////////////////////////////////////////////// 507 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) {
568 508 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%"
569 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error,
570 const nacl::string& pexe_url,
571 PnaclTranslationUnit* translation) {
572 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
573 NACL_PRId32")\n", pp_error)); 509 NACL_PRId32")\n", pp_error));
574 if (pp_error != PP_OK) { 510 if (pp_error != PP_OK) {
575 ReportLoadError(translation->error_info); 511 ReportPpapiError(pp_error, "PnaclCoordinator: file system didn't open.\n");
576 PnaclPpapiError(pp_error);
577 return; 512 return;
578 } 513 }
579 pp::CompletionCallback cb = 514 file_system_is_initialized_ = true;
580 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate, 515 // If there was a pending translation unit, start translating it.
581 pexe_url, 516 PnaclTranslationUnit* translation_unit = translation_unit_.release();
582 translation); 517 if (translation_unit != NULL) {
583 518 DoStartTranslation(PP_OK, translation_unit);
584 if (!plugin_->StreamAsFile(pexe_url, cb.pp_completion_callback())) {
585 ErrorInfo error_info;
586 error_info.SetReport(ERROR_UNKNOWN,
587 "PnaclCoordinator: Failed to download file: " +
588 pexe_url + "\n");
589 ReportLoadError(error_info);
590 PnaclNonPpapiError();
591 } 519 }
592 } 520 }
593 521
522 void PnaclCoordinator::DoStartTranslation(int32_t pp_error,
523 PnaclTranslationUnit* translation) {
524 PLUGIN_PRINTF(("PnaclCoordinator::DoStartTranslation (pp_error=%"
525 NACL_PRId32")\n", pp_error));
526 if (pp_error != PP_OK) {
527 ReportPpapiError(pp_error, translation->error_info);
528 return;
529 }
530 // Create the object file pair for connecting llc and ld.
531 translation->obj_file.reset(new PnaclFileDescPair(file_system_.get(), this));
532 pp::CompletionCallback cb =
533 callback_factory_.NewCallback(&PnaclCoordinator::ObjectPairDidOpen,
534 translation);
535 translation->obj_file->Open(cb);
536 }
537
538 void PnaclCoordinator::ObjectPairDidOpen(int32_t pp_error,
539 PnaclTranslationUnit* translation) {
540 PLUGIN_PRINTF(("PnaclCoordinator::ObjectPairDidOpen (pp_error=%"
541 NACL_PRId32")\n", pp_error));
542 if (pp_error != PP_OK) {
543 ReportPpapiError(pp_error, translation->error_info);
544 return;
545 }
546 // Create the nexe file pair for connecting ld and sel_ldr.
547 translation->nexe_file.reset(new PnaclFileDescPair(file_system_.get(), this));
548 pp::CompletionCallback cb =
549 callback_factory_.NewCallback(&PnaclCoordinator::NexePairDidOpen,
550 translation);
551 translation->nexe_file->Open(cb);
552 }
553
554 void PnaclCoordinator::NexePairDidOpen(int32_t pp_error,
555 PnaclTranslationUnit* translation) {
556 PLUGIN_PRINTF(("PnaclCoordinator::NexePairDidOpen (pp_error=%"
557 NACL_PRId32")\n", pp_error));
558 if (pp_error != PP_OK) {
559 ReportPpapiError(pp_error, translation->error_info);
560 return;
561 }
562 // Load the pexe file and get the translation started.
563 pp::CompletionCallback cb =
564 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate,
565 translation);
566
567 if (!plugin_->StreamAsFile(translation->pexe_url,
568 cb.pp_completion_callback())) {
569 ReportNonPpapiError("PnaclCoordinator: failed to download file: " +
570 translation->pexe_url + "\n");
571 }
572 }
573
594 void PnaclCoordinator::BitcodeToNative( 574 void PnaclCoordinator::BitcodeToNative(
595 const nacl::string& pexe_url, 575 const nacl::string& pexe_url,
596 const pp::CompletionCallback& finish_callback) { 576 const pp::CompletionCallback& finish_callback) {
597 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s)\n", 577 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s)\n",
598 pexe_url.c_str())); 578 pexe_url.c_str()));
599 // The base URL for finding all the resources will be obtained from the
600 // PNaCl manifest file.
601 // Also, the llc and ld pathnames should be read from the manifest.
602 // TODO(sehr): change to use the manifest file when ready.
603 resource_base_url_ = ResourceBaseUrl();
604 llc_url_ = "llc";
605 ld_url_ = "ld";
606 translate_notify_callback_ = finish_callback; 579 translate_notify_callback_ = finish_callback;
607 580
608 // Steps: 581 PnaclTranslationUnit* translation_unit =
609 // (1) Schedule downloads for llc, ld nexes, and native libraries (resources). 582 new PnaclTranslationUnit(this, pexe_url);
610 // (2) When resources have been downloaded, download pexe.
611 // (3) When pexe download has completed, start translation.
612 // (4) When llc translation has finished do the link.
613 // (5) When the link is done, we are done, call the finish_callback.
614 // Hand off the SHM file descriptor returned by link.
615 583
616 // Set up async callbacks for these steps in reverse order. 584 if (file_system_is_initialized_) {
617 585 DoStartTranslation(PP_OK, translation_unit_.get());
618 translation_unit_.reset(new PnaclTranslationUnit(this)); 586 } else {
619 587 // Hold translation unit until file system initialization is complete.
620 // When resources loading completes, this causes the pexe download. 588 translation_unit_.reset(translation_unit);
621 pp::CompletionCallback resources_cb =
622 callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad,
623 pexe_url,
624 translation_unit_.get());
625 resources_->AddResourceUrl(llc_url_);
626 resources_->AddResourceUrl(ld_url_);
627 string_vector link_resources = LinkResources(GetSandboxISA(), false);
628 for (string_vector::iterator
629 i = link_resources.begin(), e = link_resources.end();
630 i != e;
631 ++i) {
632 resources_->AddResourceUrl(*i);
633 } 589 }
634 resources_->RunWhenAllLoaded(resources_cb);
635 resources_->StartDownloads();
636 } 590 }
637 591
638 } // namespace plugin 592 } // namespace plugin
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698