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

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 llc and consumed by ld.
36 nacl::string ResourceBaseUrl() {
37 return nacl::string("pnacl_support/") + GetSandboxISA() + "/";
38 }
39
40 nacl::string Random32CharHexString(struct NaClDescRng* rng) {
41 struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(rng);
42 const struct NaClDescVtbl* vtbl =
43 reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl);
44
45 nacl::string hex_string;
46 const int32_t kTempFileNameWords = 4;
47 for (int32_t i = 0; i < kTempFileNameWords; ++i) {
48 int32_t num;
49 CHECK(sizeof num == vtbl->Read(desc,
50 reinterpret_cast<char*>(&num),
51 sizeof num));
52 char frag[16];
53 SNPRINTF(frag, sizeof frag, "%08x", num);
54 hex_string += nacl::string(frag);
55 }
56 return hex_string;
57 }
58
59 // Some constants for PnaclFileDescPair::GetFD readability.
60 const bool kReadOnly = false;
61 const bool kWriteable = true;
29 62
30 } // namespace 63 } // namespace
31 64
32 namespace plugin { 65 //////////////////////////////////////////////////////////////////////
33 66 PnaclFileDescPair::PnaclFileDescPair(Plugin* plugin,
34 class Plugin; 67 pp::FileSystem* file_system,
35 68 PnaclCoordinator* coordinator)
36 void PnaclCoordinator::Initialize(Plugin* plugin) { 69 : plugin_(plugin),
37 PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n", 70 file_system_(file_system),
38 static_cast<void*>(this))); 71 coordinator_(coordinator) {
39 CHECK(plugin != NULL); 72 PLUGIN_PRINTF(("PnaclFileDescPair::PnaclFileDescPair (plugin=%p, "
40 CHECK(plugin_ == NULL); // Can only initialize once. 73 "file_system=%p, coordinator=%p)\n",
41 plugin_ = plugin; 74 static_cast<void*>(plugin), static_cast<void*>(file_system),
75 static_cast<void*>(coordinator)));
42 callback_factory_.Initialize(this); 76 callback_factory_.Initialize(this);
43 resources_.reset(new PnaclResources(plugin, this)); 77 CHECK(NaClDescRngCtor(&rng_desc_));
44 resources_->Initialize(); 78 file_io_trusted_ = static_cast<const PPB_FileIOTrusted*>(
45 } 79 pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE));
46 80 // Get a random temp file name.
47 PnaclCoordinator::~PnaclCoordinator() { 81 filename_ = "/" + Random32CharHexString(&rng_desc_);
48 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n", 82 }
49 static_cast<void*>(this))); 83
50 84 PnaclFileDescPair::~PnaclFileDescPair() {
51 // Join helper threads which will block the page from refreshing while a 85 PLUGIN_PRINTF(("PnaclFileDescPair::~PnaclFileDescPair\n"));
52 // translation is happening. 86 NaClDescUnref(reinterpret_cast<NaClDesc*>(&rng_desc_));
53 if (translate_thread_.get() != NULL || link_thread_.get() != NULL) { 87 }
54 SetSubprocessesShouldDie(true); 88
55 } 89 void PnaclFileDescPair::Open(const pp::CompletionCallback& cb) {
56 if (translate_thread_.get() != NULL) { 90 PLUGIN_PRINTF(("PnaclFileDescPair::Open\n"));
57 NaClThreadJoin(translate_thread_.get()); 91 done_callback_ = cb;
58 } 92
59 if (link_thread_.get() != NULL) { 93 write_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
60 NaClThreadJoin(link_thread_.get()); 94 write_io_.reset(new pp::FileIO(plugin_));
61 } 95 read_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
62 } 96 read_io_.reset(new pp::FileIO(plugin_));
63 97
64 void PnaclCoordinator::ReportLoadAbort() { 98 pp::CompletionCallback open_write_cb =
65 plugin_->ReportLoadAbort(); 99 callback_factory_.NewCallback(&PnaclFileDescPair::WriteFileDidOpen);
66 } 100 // Open the writeable file.
67 101 write_io_->Open(*write_ref_,
68 void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) { 102 PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE,
69 plugin_->ReportLoadError(error); 103 open_write_cb);
70 } 104 }
71 105
72 void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) { 106 int32_t PnaclFileDescPair::GetFD(int32_t pp_error,
73 // Attempt to free all the intermediate callbacks we ever created. 107 const pp::Resource& resource,
74 callback_factory_.CancelAll(); 108 bool is_writable) {
75 translate_notify_callback_.Run(pp_error); 109 PLUGIN_PRINTF(("PnaclFileDescPair::GetFD (pp_error=%"NACL_PRId32
76 } 110 ", is_writable=%d)\n", pp_error, is_writable));
77
78 void PnaclCoordinator::PnaclNonPpapiError() {
79 PnaclPpapiError(PP_ERROR_FAILED);
80 }
81
82 void PnaclCoordinator::PnaclDidFinish(int32_t pp_error,
83 PnaclTranslationUnit* translation_unit) {
84 PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%"
85 NACL_PRId32")\n", pp_error));
86 if (pp_error != PP_OK) { 111 if (pp_error != PP_OK) {
87 ReportLoadError(translation_unit->error_info); 112 PLUGIN_PRINTF(("PnaclFileDescPair::GetFD pp_error != PP_OK\n"));
88 PnaclPpapiError(pp_error); 113 return -1;
89 return; 114 }
90 } 115 int32_t file_desc =
91 // Transfer ownership of the nexe wrapper to the coordinator. 116 file_io_trusted_->GetOSFileDescriptor(resource.pp_resource());
92 translated_fd_.reset(translation_unit->nexe_wrapper.release()); 117 #if NACL_WINDOWS
93 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); 118 // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
94 translate_notify_callback_.Run(pp_error); 119 int32_t open_flags = ((is_writable ? _O_RDWR : _O_RDONLY) | _O_BINARY);
120 int32_t posix_desc = _open_osfhandle(file_desc, open_flags);
121 if (posix_desc == -1) {
122 // Close the Windows HANDLE if it can't be converted.
123 CloseHandle(reinterpret_cast<HANDLE>(file_desc));
124 PLUGIN_PRINTF(("PnaclFileDescPair::GetFD _open_osfhandle failed.\n"));
125 return NACL_NO_FILE_DESC;
126 }
127 file_desc = posix_desc;
128 #endif
129 int32_t file_desc_ok_to_close = DUP(file_desc);
130 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
131 PLUGIN_PRINTF(("PnaclFileDescPair::GetFD dup failed.\n"));
132 return -1;
133 }
134 return file_desc_ok_to_close;
135 }
136
137 void PnaclFileDescPair::WriteFileDidOpen(int32_t pp_error) {
138 PLUGIN_PRINTF(("PnaclFileDescPair::WriteFileDidOpen (pp_error=%"
139 NACL_PRId32")\n", pp_error));
140 // Remember the object temporary file descriptor.
141 int32_t fd = GetFD(pp_error, *write_io_, kWriteable);
142 if (fd < 0) {
143 coordinator_->ReportNonPpapiError("could not open write temp file\n");
144 return;
145 }
146 write_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDWR));
147 pp::CompletionCallback open_read_cb =
148 callback_factory_.NewCallback(&PnaclFileDescPair::ReadFileDidOpen);
149 // Open the read only file.
150 read_io_->Open(*read_ref_, PP_FILEOPENFLAG_READ, open_read_cb);
151 }
152
153 void PnaclFileDescPair::ReadFileDidOpen(int32_t pp_error) {
154 PLUGIN_PRINTF(("PnaclFileDescPair::ReadFileDidOpen (pp_error=%"
155 NACL_PRId32")\n", pp_error));
156 // Remember the object temporary file descriptor.
157 int32_t fd = GetFD(pp_error, *read_io_, kReadOnly);
158 if (fd < 0) {
159 coordinator_->ReportNonPpapiError("could not open read temp file\n");
160 return;
161 }
162 read_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
163 // Run the client's completion callback.
164 pp::Core* core = pp::Module::Get()->core();
165 core->CallOnMainThread(0, done_callback_, PP_OK);
95 } 166 }
96 167
97 ////////////////////////////////////////////////////////////////////// 168 //////////////////////////////////////////////////////////////////////
169 PnaclCoordinator* PnaclCoordinator::BitcodeToNative(
170 Plugin* plugin,
171 const nacl::string& pexe_url,
172 const pp::CompletionCallback& translate_notify_callback) {
173 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n",
174 static_cast<void*>(plugin), pexe_url.c_str()));
175 PnaclCoordinator* coordinator =
176 new PnaclCoordinator(plugin,
177 pexe_url,
178 translate_notify_callback,
179 ResourceBaseUrl());
180 // Load llc and ld.
181 std::vector<nacl::string> resource_urls;
182 resource_urls.push_back(kLlcUrl);
183 resource_urls.push_back(kLdUrl);
184 pp::CompletionCallback resources_cb =
185 coordinator->callback_factory_.NewCallback(
186 &PnaclCoordinator::ResourcesDidLoad);
187 coordinator->resources_.reset(
188 new PnaclResources(plugin,
189 coordinator,
190 coordinator->resource_base_url_,
191 resource_urls,
192 resources_cb));
193 CHECK(coordinator->resources_ != NULL);
194 coordinator->resources_->StartDownloads();
195 // ResourcesDidLoad will be invoked when all resources have been received.
196 return coordinator;
197 }
98 198
99 int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error, 199 int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
100 const nacl::string& url, 200 const nacl::string& url,
101 const nacl::string& component) { 201 const nacl::string& component) {
202 PLUGIN_PRINTF(("PnaclCoordinator::GetLoadedFileDesc (pp_error=%"
203 NACL_PRId32", url=%s, component=%s)\n", pp_error,
204 url.c_str(), component.c_str()));
205 PLUGIN_PRINTF(("PnaclCoordinator::GetLoadedFileDesc (pp_error=%d\n"));
102 ErrorInfo error_info; 206 ErrorInfo error_info;
103 int32_t file_desc = plugin_->GetPOSIXFileDesc(url); 207 int32_t file_desc = plugin_->GetPOSIXFileDesc(url);
104 if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) { 208 if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
105 if (pp_error == PP_ERROR_ABORTED) { 209 if (pp_error == PP_ERROR_ABORTED) {
106 ReportLoadAbort(); 210 plugin_->ReportLoadAbort();
107 } else { 211 } else {
108 // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? 212 ReportPpapiError(pp_error, component + " load failed.\n");
109 error_info.SetReport(ERROR_UNKNOWN,
110 "PNaCl " + component + " load failed.");
111 ReportLoadError(error_info);
112 } 213 }
113 return -1; 214 return -1;
114 } 215 }
115 int32_t file_desc_ok_to_close = DUP(file_desc); 216 int32_t file_desc_ok_to_close = DUP(file_desc);
116 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) { 217 if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
117 // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN? 218 ReportPpapiError(PP_ERROR_FAILED, component + " could not dup fd.\n");
118 error_info.SetReport(ERROR_UNKNOWN,
119 "PNaCl " + component + " load failed: "
120 "could not dup fd.");
121 ReportLoadError(error_info);
122 return -1; 219 return -1;
123 } 220 }
124 return file_desc_ok_to_close; 221 return file_desc_ok_to_close;
125 } 222 }
126 223
127 bool PnaclCoordinator::StartLlcSubProcess() { 224 PnaclCoordinator::PnaclCoordinator(
128 ErrorInfo error_info; 225 Plugin* plugin,
129 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(llc_url_); 226 const nacl::string& pexe_url,
130 NaClSubprocessId llc_id = plugin_->LoadHelperNaClModule(wrapper, &error_info); 227 const pp::CompletionCallback& translate_notify_callback,
131 PLUGIN_PRINTF(("PnaclCoordinator::StartLlcSubProcess (nexe_id=%" 228 const nacl::string& resource_base_url)
132 NACL_PRId32")\n", llc_id)); 229 : plugin_(plugin),
133 if (kInvalidNaClSubprocessId == llc_id) { 230 translate_notify_callback_(translate_notify_callback),
134 error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl compiler nexe"); 231 resource_base_url_(resource_base_url),
135 ReportLoadError(error_info); 232 llc_subprocess_(NULL),
136 PnaclNonPpapiError(); 233 ld_subprocess_(NULL),
234 subprocesses_should_die_(false),
235 pexe_url_(pexe_url) {
236 PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n",
237 static_cast<void*>(this), static_cast<void*>(plugin)));
238 callback_factory_.Initialize(this);
239 NaClXMutexCtor(&subprocess_mu_);
240 // Initialize the file lookup related members.
241 NaClXMutexCtor(&lookup_service_mu_);
242 NaClXCondVarCtor(&lookup_service_cv_);
243 // Open the temporary file system.
244 file_system_.reset(
robertm 2011/12/13 22:12:51 add this to the ":" section and you wont need the
sehr (please use chromium) 2011/12/14 16:34:20 Done.
245 new pp::FileSystem(plugin, PP_FILESYSTEMTYPE_LOCALTEMPORARY));
246 CHECK(file_system_ != NULL);
247 }
248
249 PnaclCoordinator::~PnaclCoordinator() {
250 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n",
251 static_cast<void*>(this)));
252 // Join helper thread which will block the page from refreshing while a
253 // translation is happening.
254 if (translate_thread_.get() != NULL) {
255 SetSubprocessesShouldDie(true);
256 NaClThreadJoin(translate_thread_.get());
257 }
258 NaClCondVarDtor(&lookup_service_cv_);
259 NaClMutexDtor(&lookup_service_mu_);
260 NaClMutexDtor(&subprocess_mu_);
261 }
262
263 void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) {
264 error_info_.SetReport(ERROR_UNKNOWN,
265 nacl::string("PnaclCoordinator: ") + message);
266 ReportPpapiError(PP_ERROR_FAILED);
267 }
268
269 void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
270 const nacl::string& message) {
271 error_info_.SetReport(ERROR_UNKNOWN,
272 nacl::string("PnaclCoordinator: ") + message);
273 ReportPpapiError(pp_error);
274 }
275
276 void PnaclCoordinator::ReportPpapiError(int32_t pp_error) {
277 plugin_->ReportLoadError(error_info_);
278 // Free all the intermediate callbacks we ever created.
279 callback_factory_.CancelAll();
280 translate_notify_callback_.Run(pp_error);
281 }
282
283 void PnaclCoordinator::PnaclDidFinish(int32_t pp_error) {
284 PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%"
285 NACL_PRId32")\n", pp_error));
286 if (pp_error != PP_OK) {
287 ReportPpapiError(pp_error);
288 return;
289 }
290 // Transfer ownership of the nexe wrapper to the coordinator.
291 // TODO(sehr): need to release the translation unit here while transferring.
292 translated_fd_.reset(nexe_file_->read_wrapper());
293 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
294 translate_notify_callback_.Run(pp_error);
295 }
296
297 void PnaclCoordinator::PnaclFailed(const nacl::string& error_string) {
robertm 2011/12/13 22:12:51 rename to translateFailed or similar add comment:
sehr (please use chromium) 2011/12/14 16:34:20 Name changed. Comment is in header.
298 PLUGIN_PRINTF(("PnaclCoordinator::PnaclFailed (error_string=%"
299 NACL_PRId32")\n", error_string.c_str()));
300 pp::Core* core = pp::Module::Get()->core();
301 error_info_.SetReport(ERROR_UNKNOWN,
302 nacl::string("PnaclCoordinator: ") + error_string);
303 core->CallOnMainThread(0, translate_done_cb_, PP_ERROR_FAILED);
304 NaClThreadExit(1);
305 }
306
307 void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) {
308 PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
309 NACL_PRId32")\n", pp_error));
310 if (pp_error != PP_OK) {
311 ReportPpapiError(pp_error, "resources failed to load\n");
312 return;
313 }
314 // Open the local temporary file system to create the temporary files
315 // for the object and nexe.
316 pp::CompletionCallback cb =
317 callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen);
318 if (!file_system_->Open(0, cb)) {
319 ReportNonPpapiError("failed to open file system.\n");
320 }
321 }
322
323 void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) {
324 PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%"
325 NACL_PRId32")\n", pp_error));
326 if (pp_error != PP_OK) {
327 ReportPpapiError(pp_error, "file system didn't open.\n");
328 return;
329 }
330 // Create the object file pair for connecting llc and ld.
331 obj_file_.reset(new PnaclFileDescPair(plugin_, file_system_.get(), this));
332 pp::CompletionCallback cb =
333 callback_factory_.NewCallback(&PnaclCoordinator::ObjectPairDidOpen);
334 obj_file_->Open(cb);
335 }
336
337 void PnaclCoordinator::ObjectPairDidOpen(int32_t pp_error) {
338 PLUGIN_PRINTF(("PnaclCoordinator::ObjectPairDidOpen (pp_error=%"
339 NACL_PRId32")\n", pp_error));
340 if (pp_error != PP_OK) {
341 ReportPpapiError(pp_error);
342 return;
343 }
344 // Create the nexe file pair for connecting ld and sel_ldr.
345 nexe_file_.reset(new PnaclFileDescPair(plugin_, file_system_.get(), this));
346 pp::CompletionCallback cb =
347 callback_factory_.NewCallback(&PnaclCoordinator::NexePairDidOpen);
348 nexe_file_->Open(cb);
349 }
350
351 void PnaclCoordinator::NexePairDidOpen(int32_t pp_error) {
352 PLUGIN_PRINTF(("PnaclCoordinator::NexePairDidOpen (pp_error=%"
353 NACL_PRId32")\n", pp_error));
354 if (pp_error != PP_OK) {
355 ReportPpapiError(pp_error);
356 return;
357 }
358 // Load the pexe file and get the translation started.
359 pp::CompletionCallback cb =
360 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate);
361
362 if (!plugin_->StreamAsFile(pexe_url_, cb.pp_completion_callback())) {
363 ReportNonPpapiError(nacl::string("failed to download ") + pexe_url_ + "\n");
364 }
365 }
366
367 void PnaclCoordinator::RunTranslate(int32_t pp_error) {
368 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
369 NACL_PRId32")\n", pp_error));
370 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url_, "pexe");
371 if (fd < 0) {
372 return;
373 }
374 pexe_wrapper_.reset(plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
375 llc_subprocess_ = StartSubprocess(kLlcUrl);
376 if (llc_subprocess_ == NULL) {
377 ReportPpapiError(PP_ERROR_FAILED);
378 return;
379 }
380 ld_subprocess_ = StartSubprocess(kLdUrl);
381 if (ld_subprocess_ == NULL) {
382 ReportPpapiError(PP_ERROR_FAILED);
383 return;
384 }
385 // Invoke llc followed by ld off the main thread. This allows use of
386 // blocking RPCs that would otherwise block the JavaScript main thread.
387 translate_done_cb_ =
388 callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish);
robertm 2011/12/13 22:12:51 PnaclDidFinish is not a good name, TranslateFinish
sehr (please use chromium) 2011/12/14 16:34:20 Done.
389 translate_thread_.reset(new NaClThread);
390 if (translate_thread_ == NULL) {
391 ReportNonPpapiError("could not allocate thread struct\n");
392 return;
393 }
394 const int32_t kArbitraryStackSize = 128 << 10;
robertm 2011/12/13 22:12:51 128 * 1024 is less "clever".
sehr (please use chromium) 2011/12/14 16:34:20 Done.
395 if (!NaClThreadCreateJoinable(translate_thread_.get(),
396 DoTranslateThread,
397 this,
398 kArbitraryStackSize)) {
399 ReportNonPpapiError("could not create thread\n");
400 }
401 }
402
403 NaClSubprocess* PnaclCoordinator::StartSubprocess(const nacl::string& url) {
robertm 2011/12/13 22:12:51 maybe rename url -> url_for_nexe
sehr (please use chromium) 2011/12/14 16:34:20 Done.
404 PLUGIN_PRINTF(("PnaclCoordinator::StartSubprocess (url=%s)\n", url.c_str()));
405 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url);
406 NaClSubprocessId id = plugin_->LoadHelperNaClModule(wrapper, &error_info_);
407 if (kInvalidNaClSubprocessId == id) {
137 return NULL; 408 return NULL;
robertm 2011/12/13 22:12:51 error message?
sehr (please use chromium) 2011/12/14 16:34:20 Added a PLUGIN_PRINTF. Caller will invoke ReportP
138 } 409 }
139 llc_subprocess_ = plugin_->nacl_subprocess(llc_id); 410 return plugin_->nacl_subprocess(id);
140 return (llc_subprocess_ != NULL); 411 }
141 } 412
142 413 void WINAPI PnaclCoordinator::DoTranslateThread(void* arg) {
143 bool PnaclCoordinator::StartLdSubProcess() { 414 PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>(arg);
144 ErrorInfo error_info; 415 Plugin* plugin = coordinator->plugin_;
robertm 2011/12/13 22:12:51 I the long it would probably best to move this thr
sehr (please use chromium) 2011/12/14 16:34:20 As we discussed on the phone, I completely agree,
145 nacl::DescWrapper* wrapper = resources_->WrapperForUrl(ld_url_); 416 BrowserInterface* browser_interface = plugin->browser_interface();
146 NaClSubprocessId ld_id = plugin_->LoadHelperNaClModule(wrapper, &error_info); 417
147 PLUGIN_PRINTF(("PnaclCoordinator::StartLdSubProcess (nexe_id=%" 418 // Run LLC.
148 NACL_PRId32")\n", ld_id)); 419 SrpcParams params;
149 if (kInvalidNaClSubprocessId == ld_id) { 420 nacl::DescWrapper* llc_out_file = coordinator->obj_file_->write_wrapper();
150 error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl linker nexe"); 421 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
151 ReportLoadError(error_info); 422 coordinator->llc_subprocess_,
152 PnaclNonPpapiError(); 423 "RunWithDefaultCommandLine",
153 return NULL; 424 "hh",
154 } 425 &params,
155 ld_subprocess_ = plugin_->nacl_subprocess(ld_id); 426 coordinator->pexe_wrapper_->desc(),
156 return (ld_subprocess_ != NULL); 427 llc_out_file->desc())) {
428 coordinator->PnaclFailed("compile failed.");
429 }
430 // LLC returns values that are used to determine how linking is done.
431 int is_shared_library = (params.outs()[0]->u.ival != 0);
432 nacl::string soname = params.outs()[1]->arrays.str;
433 nacl::string lib_dependencies = params.outs()[2]->arrays.str;
434 PLUGIN_PRINTF(("PnaclCoordinator: compile (coordinator=%p) succeeded"
435 " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n",
436 arg, is_shared_library, soname.c_str(),
437 lib_dependencies.c_str()));
438 if (coordinator->SubprocessesShouldDie()) {
439 NaClThreadExit(1);
robertm 2011/12/13 22:12:51 maybe printf
sehr (please use chromium) 2011/12/14 16:34:20 Done.
440 }
441 // Set up the lookup service for filename to handle resolution.
442 NaClSrpcService* service =
443 reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service)));
444 if (NULL == service) {
445 coordinator->PnaclFailed("lookup service alloc failed.");
446 }
447 if (!NaClSrpcServiceHandlerCtor(service, lookup_methods)) {
448 free(service);
449 coordinator->PnaclFailed("lookup service constructor failed.");
450 }
451 char* service_string = const_cast<char*>(service->service_string);
452 NaClSubprocess* ld_subprocess = coordinator->ld_subprocess_;
453 ld_subprocess->srpc_client()->AttachService(service, coordinator);
454 nacl::DescWrapper* ld_out_file = coordinator->nexe_file_->write_wrapper();
455 if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
456 ld_subprocess,
457 "RunWithDefaultCommandLine",
458 "ChiCC",
459 &params,
460 service_string,
461 ld_out_file->desc(),
462 is_shared_library,
463 soname.c_str(),
464 lib_dependencies.c_str())) {
465 coordinator->PnaclFailed("link failed.");
466 }
467 PLUGIN_PRINTF(("PnaclCoordinator: link (coordinator=%p) succeeded\n", arg));
468 if (coordinator->SubprocessesShouldDie()) {
robertm 2011/12/13 22:12:51 add a PLUGIN_PRINTF
sehr (please use chromium) 2011/12/14 16:34:20 Done.
469 NaClThreadExit(1);
470 }
471 pp::Core* core = pp::Module::Get()->core();
472 core->CallOnMainThread(0, coordinator->translate_done_cb_, PP_OK);
473 NaClThreadExit(0);
157 } 474 }
158 475
159 bool PnaclCoordinator::SubprocessesShouldDie() { 476 bool PnaclCoordinator::SubprocessesShouldDie() {
160 nacl::MutexLocker ml(&subprocess_mu_); 477 nacl::MutexLocker ml(&subprocess_mu_);
161 return subprocesses_should_die_; 478 return subprocesses_should_die_;
162 } 479 }
163 480
164 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) { 481 void PnaclCoordinator::SetSubprocessesShouldDie(bool subprocesses_should_die) {
165 nacl::MutexLocker ml(&subprocess_mu_); 482 nacl::MutexLocker ml(&subprocess_mu_);
166 subprocesses_should_die_ = subprocesses_should_die; 483 subprocesses_should_die_ = subprocesses_should_die;
167 } 484 }
168 485
169 ////////////////////////////////////////////////////////////////////// 486 void PnaclCoordinator::LoadOneFile(int32_t pp_error,
170 // First few callbacks. 487 const nacl::string& url,
171 488 nacl::DescWrapper** wrapper,
172 ////////////////////////////////////////////////////////////////////// 489 pp::CompletionCallback& done_cb) {
173 490 PLUGIN_PRINTF(("PnaclCoordinator::LoadOneFile (pp_error=%"
174 namespace { 491 NACL_PRId32", url=%s)\n", pp_error, url.c_str()));
175 void AbortTranslateThread(PnaclTranslationUnit* translation_unit, 492 const nacl::string& full_url = resource_base_url_ + url;
176 const nacl::string& error_string) { 493 pp::CompletionCallback callback =
494 callback_factory_.NewCallback(&PnaclCoordinator::DidLoadFile,
495 full_url,
496 wrapper,
497 done_cb);
498 if (!plugin_->StreamAsFile(full_url, callback.pp_completion_callback())) {
499 ReportNonPpapiError(nacl::string("failed to load ") + url + "\n");
500 }
501 }
502
503 void PnaclCoordinator::DidLoadFile(int32_t pp_error,
504 const nacl::string& full_url,
505 nacl::DescWrapper** wrapper,
506 pp::CompletionCallback& done_cb) {
507 PLUGIN_PRINTF(("PnaclCoordinator::DidLoadFile (pp_error=%"
508 NACL_PRId32", url=%s)\n", pp_error, full_url.c_str()));
509 int32_t fd = GetLoadedFileDesc(pp_error, full_url, "resource");
510 if (fd < 0) {
511 return;
robertm 2011/12/13 22:12:51 maybe also a add a PLUGIN_PRINTF here to make the
sehr (please use chromium) 2011/12/14 16:34:20 Done.
512 }
513 *wrapper = plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
514 done_cb.Run(PP_OK);
515 }
516
517 void PnaclCoordinator::ResumeLookup(int32_t pp_error) {
518 PLUGIN_PRINTF(("PnaclCoordinator::ResumeLookup (pp_error=%"
519 NACL_PRId32", url=%s)\n", pp_error));
520 UNREFERENCED_PARAMETER(pp_error);
521 nacl::MutexLocker ml(&lookup_service_mu_);
522 lookup_is_complete_ = true;
523 NaClXCondVarBroadcast(&lookup_service_cv_);
524 }
525
526 // Lookup service called by translator nexes.
527 // TODO(sehr): replace this lookup by ReverseService.
528 void PnaclCoordinator::LookupInputFile(NaClSrpcRpc* rpc,
529 NaClSrpcArg** inputs,
530 NaClSrpcArg** outputs,
531 NaClSrpcClosure* done) {
532 PLUGIN_PRINTF(("PnaclCoordinator::LookupInputFile (url=%s)\n",
533 inputs[0]->arrays.str));
534 NaClSrpcClosureRunner runner(done);
535 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
536 const char* file_name = inputs[0]->arrays.str;
537 PnaclCoordinator* coordinator = reinterpret_cast<PnaclCoordinator*>(
538 rpc->channel->server_instance_data);
539 outputs[0]->u.hval = coordinator->LookupDesc(file_name);
540 rpc->result = NACL_SRPC_RESULT_OK;
541 }
542
543 NaClSrpcHandlerDesc PnaclCoordinator::lookup_methods[] = {
544 { "LookupInputFile:s:h", LookupInputFile },
545 { NULL, NULL }
546 };
547
548 struct NaClDesc* PnaclCoordinator::LookupDesc(const nacl::string& url) {
549 PLUGIN_PRINTF(("PnaclCoordinator::LookupDesc (url=%s)\n", url.c_str()));
550 // This filename is part of the contract with the linker.
551 // TODO(sehr): Pass the FD in, and move lookup for this file to the linker.
552 const nacl::string kGeneratedObjectFileName = "___PNACL_GENERATED";
553 if (url == kGeneratedObjectFileName) {
554 return obj_file_->read_wrapper()->desc();
555 }
556 nacl::DescWrapper* wrapper;
557 // Create the callback used to report when lookup is done.
558 pp::CompletionCallback resume_cb =
559 callback_factory_.NewCallback(&PnaclCoordinator::ResumeLookup);
560 // Run the lookup request on the main thread.
561 lookup_is_complete_ = false;
562 pp::CompletionCallback load_cb =
563 callback_factory_.NewCallback(&PnaclCoordinator::LoadOneFile,
564 url, &wrapper, resume_cb);
177 pp::Core* core = pp::Module::Get()->core(); 565 pp::Core* core = pp::Module::Get()->core();
178 translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string); 566 core->CallOnMainThread(0, load_cb, PP_OK);
179 core->CallOnMainThread(0, translation_unit->translate_done_cb, 567 // Wait for completion (timeout every 10ms to check for process end).
180 PP_ERROR_FAILED); 568 const int32_t kTenMilliseconds = 10 * 1000 * 1000;
181 NaClThreadExit(1); 569 NACL_TIMESPEC_T reltime;
182 } 570 reltime.tv_sec = 0;
183 571 reltime.tv_nsec = kTenMilliseconds;
184 void WINAPI DoTranslateThread(void* arg) { 572 NaClXMutexLock(&lookup_service_mu_);
185 PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg); 573 while (!lookup_is_complete_) {
186 PnaclCoordinator* coordinator = p->coordinator; 574 // Check for termination.
187 NaClSubprocess* llc_subprocess = coordinator->llc_subprocess(); 575 if (SubprocessesShouldDie()) {
188 Plugin* plugin = coordinator->plugin(); 576 NaClXMutexUnlock(&lookup_service_mu_);
189 BrowserInterface* browser = plugin->browser_interface(); 577 NaClThreadExit(0);
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 } 578 }
244 SrpcParams dummy_params; 579 NaClXCondVarTimedWaitRelative(&lookup_service_cv_,
245 if (!PnaclSrpcLib::InvokeSrpcMethod(browser, 580 &lookup_service_mu_,
246 llc_subprocess, 581 &reltime);
247 "AddArg", 582 }
248 "C", 583 NaClXMutexUnlock(&lookup_service_mu_);
249 &dummy_params, 584 return wrapper->desc();
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,
294 const nacl::string& pexe_url,
295 PnaclTranslationUnit* translation_unit) {
296 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
297 NACL_PRId32")\n", pp_error));
298 // pp_error is checked by GetLoadedFileDesc.
299 int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe");
300 if (fd < 0) {
301 PnaclPpapiError(pp_error);
302 return;
303 }
304 translation_unit->pexe_wrapper.reset(
305 plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
306 if (!StartLlcSubProcess()) {
307 ErrorInfo error_info;
308 error_info.SetReport(ERROR_UNKNOWN,
309 "Could not start compiler subprocess\n");
310 ReportLoadError(error_info);
311 PnaclNonPpapiError();
312 return;
313 }
314 // Invoke llvm asynchronously.
315 // RunLink runs on the main thread when llvm is done.
316 translation_unit->translate_done_cb =
317 callback_factory_.NewCallback(&PnaclCoordinator::RunLink,
318 translation_unit);
319 translate_thread_.reset(new NaClThread);
320 if (translate_thread_ == NULL) {
321 ErrorInfo error_info;
322 error_info.SetReport(ERROR_UNKNOWN,
323 "Could not allocate DoTranslateThread()\n");
324 ReportLoadError(error_info);
325 PnaclNonPpapiError();
326 return;
327 }
328 if (!NaClThreadCreateJoinable(translate_thread_.get(),
329 DoTranslateThread,
330 translation_unit,
331 kArbitraryStackSize)) {
332 ErrorInfo error_info;
333 error_info.SetReport(ERROR_UNKNOWN,
334 "Could not create a translator thread.\n");
335 ReportLoadError(error_info);
336 PnaclNonPpapiError();
337 }
338 }
339
340 //////////////////////////////////////////////////////////////////////
341 // Helper functions for loading native libs.
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));
526 if (pp_error != PP_OK) {
527 ReportLoadError(translation_unit->error_info);
528 PnaclPpapiError(pp_error);
529 return;
530 }
531 plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
532 if (!StartLdSubProcess()) {
533 ErrorInfo error_info;
534 error_info.SetReport(ERROR_UNKNOWN,
535 "Could not start linker subprocess\n");
536 ReportLoadError(error_info);
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 }
565 }
566
567 //////////////////////////////////////////////////////////////////////
568
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));
574 if (pp_error != PP_OK) {
575 ReportLoadError(translation->error_info);
576 PnaclPpapiError(pp_error);
577 return;
578 }
579 pp::CompletionCallback cb =
580 callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate,
581 pexe_url,
582 translation);
583
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 }
592 }
593
594 void PnaclCoordinator::BitcodeToNative(
595 const nacl::string& pexe_url,
596 const pp::CompletionCallback& finish_callback) {
597 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s)\n",
598 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;
607
608 // Steps:
609 // (1) Schedule downloads for llc, ld nexes, and native libraries (resources).
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
616 // Set up async callbacks for these steps in reverse order.
617
618 translation_unit_.reset(new PnaclTranslationUnit(this));
619
620 // When resources loading completes, this causes the pexe download.
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 }
634 resources_->RunWhenAllLoaded(resources_cb);
635 resources_->StartDownloads();
636 } 585 }
637 586
638 } // namespace plugin 587 } // namespace plugin
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698