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

Side by Side Diff: chrome/browser/nacl_host/nacl_process_host.cc

Issue 9950055: Enable --nacl-gdb flag on Linux. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: style nit Created 8 years, 8 months 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/nacl_host/nacl_process_host.h" 5 #include "chrome/browser/nacl_host/nacl_process_host.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/memory/mru_cache.h" 12 #include "base/memory/mru_cache.h"
13 #include "base/memory/singleton.h" 13 #include "base/memory/singleton.h"
14 #include "base/message_loop.h"
14 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
15 #include "base/path_service.h" 16 #include "base/path_service.h"
17 #include "base/string_number_conversions.h"
18 #include "base/string_split.h"
16 #include "base/string_util.h" 19 #include "base/string_util.h"
17 #include "base/rand_util.h" 20 #include "base/rand_util.h"
18 #include "base/stringprintf.h" 21 #include "base/stringprintf.h"
19 #include "base/utf_string_conversions.h" 22 #include "base/utf_string_conversions.h"
20 #include "base/win/windows_version.h" 23 #include "base/win/windows_version.h"
21 #include "build/build_config.h" 24 #include "build/build_config.h"
22 #include "chrome/browser/extensions/extension_info_map.h" 25 #include "chrome/browser/extensions/extension_info_map.h"
23 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" 26 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
24 #include "chrome/common/chrome_constants.h" 27 #include "chrome/common/chrome_constants.h"
25 #include "chrome/common/chrome_paths.h" 28 #include "chrome/common/chrome_paths.h"
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 return (base::win::OSInfo::GetInstance()->wow64_status() == 265 return (base::win::OSInfo::GetInstance()->wow64_status() ==
263 base::win::OSInfo::WOW64_ENABLED); 266 base::win::OSInfo::WOW64_ENABLED);
264 } 267 }
265 #endif 268 #endif
266 269
267 NaClProcessHost::NaClProcessHost(const std::wstring& url) 270 NaClProcessHost::NaClProcessHost(const std::wstring& url)
268 : 271 :
269 #if defined(OS_WIN) 272 #if defined(OS_WIN)
270 process_launched_by_broker_(false), 273 process_launched_by_broker_(false),
271 #endif 274 #endif
275 #if defined(OS_LINUX)
Mark Seaborn 2012/04/03 21:57:44 #elif for neatness.
halyavin 2012/04/04 09:23:15 Done.
276 wait_for_nacl_gdb_(false),
277 #endif
272 reply_msg_(NULL), 278 reply_msg_(NULL),
273 internal_(new NaClInternal()), 279 internal_(new NaClInternal()),
274 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 280 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
275 enable_exception_handling_(false) { 281 enable_exception_handling_(false) {
276 process_.reset(content::BrowserChildProcessHost::Create( 282 process_.reset(content::BrowserChildProcessHost::Create(
277 content::PROCESS_TYPE_NACL_LOADER, this)); 283 content::PROCESS_TYPE_NACL_LOADER, this));
278 process_->SetName(WideToUTF16Hack(url)); 284 process_->SetName(WideToUTF16Hack(url));
279 285
280 // We allow untrusted hardware exception handling to be enabled via 286 // We allow untrusted hardware exception handling to be enabled via
281 // an env var for consistency with the standalone build of NaCl. 287 // an env var for consistency with the standalone build of NaCl.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 internal_->sockets_for_sel_ldr.push_back(pair[1]); 407 internal_->sockets_for_sel_ldr.push_back(pair[1]);
402 SetCloseOnExec(pair[0]); 408 SetCloseOnExec(pair[0]);
403 SetCloseOnExec(pair[1]); 409 SetCloseOnExec(pair[1]);
404 } 410 }
405 411
406 // Launch the process 412 // Launch the process
407 if (!LaunchSelLdr()) { 413 if (!LaunchSelLdr()) {
408 delete this; 414 delete this;
409 } 415 }
410 } 416 }
411 417 #if defined(OS_WIN)
412 scoped_ptr<CommandLine> NaClProcessHost::LaunchWithNaClGdb( 418 scoped_ptr<CommandLine> NaClProcessHost::LaunchWithNaClGdb(
413 const FilePath& nacl_gdb, 419 const FilePath& nacl_gdb,
414 CommandLine* line, 420 CommandLine* line) {
415 const FilePath& manifest_path) {
416 CommandLine* cmd_line = new CommandLine(nacl_gdb); 421 CommandLine* cmd_line = new CommandLine(nacl_gdb);
417 // We can't use PrependWrapper because our parameters contain spaces. 422 // We can't use PrependWrapper because our parameters contain spaces.
418 cmd_line->AppendArg("--eval-command"); 423 cmd_line->AppendArg("-ex");
Mark Seaborn 2012/04/03 21:57:44 Please stick with --eval-command since it's more o
halyavin 2012/04/04 09:23:15 Done.
419 const FilePath::StringType& irt_path = 424 const FilePath::StringType& irt_path =
420 NaClBrowser::GetInstance()->GetIrtFilePath().value(); 425 NaClBrowser::GetInstance()->GetIrtFilePath().value();
421 cmd_line->AppendArgNative(FILE_PATH_LITERAL("nacl-irt ") + irt_path); 426 cmd_line->AppendArgNative(FILE_PATH_LITERAL("nacl-irt ") + irt_path);
427 FilePath manifest_path = GetManifestPath();
422 if (!manifest_path.empty()) { 428 if (!manifest_path.empty()) {
423 cmd_line->AppendArg("--eval-command"); 429 cmd_line->AppendArg("-ex");
Mark Seaborn 2012/04/03 21:57:44 ditto
424 cmd_line->AppendArgNative(FILE_PATH_LITERAL("nacl-manifest ") + 430 cmd_line->AppendArgNative(FILE_PATH_LITERAL("nacl-manifest ") +
425 manifest_path.value()); 431 manifest_path.value());
426 } 432 }
427 cmd_line->AppendArg("--args"); 433 cmd_line->AppendArg("--args");
428 const CommandLine::StringVector& argv = line->argv(); 434 const CommandLine::StringVector& argv = line->argv();
429 for (size_t i = 0; i < argv.size(); i++) { 435 for (size_t i = 0; i < argv.size(); i++) {
430 cmd_line->AppendArgNative(argv[i]); 436 cmd_line->AppendArgNative(argv[i]);
431 } 437 }
432 return scoped_ptr<CommandLine>(cmd_line); 438 return scoped_ptr<CommandLine>(cmd_line);
433 } 439 }
440 #elif defined(OS_LINUX)
441 namespace {
442 class NaClGdbWatchDelegate : public MessageLoopForIO::Watcher {
443 public:
444 NaClGdbWatchDelegate(int fds_read, int fds_write,
445 const base::Closure& reply)
446 : fds_read_(fds_read),
447 fds_write_(fds_write),
Mark Seaborn 2012/04/03 21:57:44 Why are you passing fds_write through? It's not u
halyavin 2012/04/04 09:23:15 It is used by nacl-gdb. It opens fds_write in our
448 reply_(reply) {}
449
450 ~NaClGdbWatchDelegate() {
451 close(fds_read_);
Mark Seaborn 2012/04/03 21:57:44 Please do LOG(ERROR) on error from close(), otherw
halyavin 2012/04/04 09:23:15 Done.
452 close(fds_write_);
453 }
454
455 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
456 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
457
458 private:
459 int fds_read_;
Mark Seaborn 2012/04/03 21:57:44 Should be "fd" not "fds".
halyavin 2012/04/04 09:23:15 Done.
460 int fds_write_;
461 base::Closure reply_;
462 };
463
464 void NaClGdbWatchDelegate::OnFileCanReadWithoutBlocking(int fd) {
465 char buf;
466 if (read(fds_read_, &buf, 1) != 1)
467 LOG(ERROR) << "Failed to sync with nacl-gdb";
Mark Seaborn 2012/04/03 21:57:44 Suggestion: you might also want to sanity check th
halyavin 2012/04/04 09:23:15 I added sanity check but I don't think using non-z
468 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, reply_);
469 }
470 } // namespace
471
472 bool NaClProcessHost::LaunchNaClGdb(base::ProcessId pid) {
473 CommandLine::StringType nacl_gdb =
474 CommandLine::ForCurrentProcess()->GetSwitchValueNative(
475 switches::kNaClGdb);
476 CommandLine::StringVector argv;
477 base::SplitString(nacl_gdb, static_cast<CommandLine::CharType>(' '), &argv);
Mark Seaborn 2012/04/03 21:57:44 Can you put a comment in here to say that we don't
halyavin 2012/04/04 09:23:15 Done.
478 CommandLine cmd_line(argv);
479 cmd_line.AppendArg("-ex");
Mark Seaborn 2012/04/03 21:57:44 Please use --eval-command here and below.
480 const FilePath::StringType& irt_path =
481 NaClBrowser::GetInstance()->GetIrtFilePath().value();
Mark Seaborn 2012/04/03 21:57:44 Indent -2
halyavin 2012/04/04 09:23:15 Done.
482 cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-irt ") + irt_path);
483 FilePath manifest_path = GetManifestPath();
484 if (!manifest_path.empty()) {
485 cmd_line.AppendArg("-ex");
486 cmd_line.AppendArgNative(FILE_PATH_LITERAL("nacl-manifest ") +
487 manifest_path.value());
488 }
489 cmd_line.AppendArg("-ex");
490 cmd_line.AppendArg("attach " + base::IntToString(pid));
491 int fds[2];
492 if (pipe(fds) != 0)
493 return false;
494 cmd_line.AppendArg("-ex");
495 cmd_line.AppendArg("dump binary value /proc/" +
496 base::IntToString(base::GetCurrentProcId()) +
497 "/fd/" + base::IntToString(fds[1]) + " (char)0");
498 // wait on fds[0]
499 nacl_gdb_watcher_delegate_.reset(
500 new NaClGdbWatchDelegate(
501 fds[0], fds[1],
502 base::Bind(&NaClProcessHost::OnNaClGdbAttached,
503 weak_factory_.GetWeakPtr())));
504 MessageLoopForIO::current()->WatchFileDescriptor(
505 fds[0],
506 true,
507 MessageLoopForIO::WATCH_READ,
508 &nacl_gdb_watcher_,
509 nacl_gdb_watcher_delegate_.get());
510 return base::LaunchProcess(cmd_line, base::LaunchOptions(), NULL);
Mark Seaborn 2012/04/03 21:57:44 This seems to suggest that all FDs, including fds[
halyavin 2012/04/04 09:23:15 nacl-gdb opens file descriptor in our process. I e
Mark Seaborn 2012/04/04 15:46:12 I missed that. It's totally non-obvious. It defi
511 }
512
513 void NaClProcessHost::OnNaClGdbAttached() {
514 wait_for_nacl_gdb_ = false;
515 nacl_gdb_watcher_.StopWatchingFileDescriptor();
516 nacl_gdb_watcher_delegate_.reset();
517 OnProcessLaunched();
518 }
519 #endif
520
521 FilePath NaClProcessHost::GetManifestPath() {
522 GURL manifest_url = GURL(process_->GetData().name);
523 const Extension* extension = extension_info_map_->extensions()
524 .GetExtensionOrAppByURL(ExtensionURLInfo(manifest_url));
525 if (extension != NULL && manifest_url.SchemeIs(chrome::kExtensionScheme)) {
526 std::string path = manifest_url.path();
527 TrimString(path, "/", &path); // Remove first slash
528 return extension->path().AppendASCII(path);
529 }
530 return FilePath();
531 }
434 532
435 bool NaClProcessHost::LaunchSelLdr() { 533 bool NaClProcessHost::LaunchSelLdr() {
436 std::string channel_id = process_->GetHost()->CreateChannel(); 534 std::string channel_id = process_->GetHost()->CreateChannel();
437 if (channel_id.empty()) 535 if (channel_id.empty())
438 return false; 536 return false;
439 537
440 CommandLine::StringType nacl_loader_prefix; 538 CommandLine::StringType nacl_loader_prefix;
441 #if defined(OS_POSIX) 539 #if defined(OS_POSIX)
442 nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative( 540 nacl_loader_prefix = CommandLine::ForCurrentProcess()->GetSwitchValueNative(
443 switches::kNaClLoaderCmdPrefix); 541 switches::kNaClLoaderCmdPrefix);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); 580 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
483 if (logging::DialogsAreSuppressed()) 581 if (logging::DialogsAreSuppressed())
484 cmd_line->AppendSwitch(switches::kNoErrorDialogs); 582 cmd_line->AppendSwitch(switches::kNoErrorDialogs);
485 583
486 if (!nacl_loader_prefix.empty()) 584 if (!nacl_loader_prefix.empty())
487 cmd_line->PrependWrapper(nacl_loader_prefix); 585 cmd_line->PrependWrapper(nacl_loader_prefix);
488 586
489 FilePath nacl_gdb = CommandLine::ForCurrentProcess()->GetSwitchValuePath( 587 FilePath nacl_gdb = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
490 switches::kNaClGdb); 588 switches::kNaClGdb);
491 if (!nacl_gdb.empty()) { 589 if (!nacl_gdb.empty()) {
492 GURL manifest_url = GURL(process_->GetData().name); 590 #if defined(OS_WIN)
493 FilePath manifest_path;
494 const Extension* extension = extension_info_map_->extensions().
495 GetExtensionOrAppByURL(ExtensionURLInfo(manifest_url));
496 if (extension != NULL && manifest_url.SchemeIs(chrome::kExtensionScheme)) {
497 std::string path = manifest_url.path();
498 TrimString(path, "/", &path); // Remove first slash
499 manifest_path = extension->path().AppendASCII(path);
500 }
501 cmd_line->AppendSwitch(switches::kNoSandbox); 591 cmd_line->AppendSwitch(switches::kNoSandbox);
502 scoped_ptr<CommandLine> gdb_cmd_line( 592 scoped_ptr<CommandLine> gdb_cmd_line(
503 LaunchWithNaClGdb(nacl_gdb, cmd_line.get(), manifest_path)); 593 LaunchWithNaClGdb(nacl_gdb, cmd_line.get()));
504 // We can't use process_->Launch() because OnProcessLaunched will be called 594 // We can't use process_->Launch() because OnProcessLaunched will be called
505 // with process_->GetData().handle filled by handle of gdb process. This 595 // with process_->GetData().handle filled by handle of gdb process. This
506 // handle will be used to duplicate handles for NaCl process and as 596 // handle will be used to duplicate handles for NaCl process and as
507 // a result NaCl process will not be able to use them. 597 // a result NaCl process will not be able to use them.
508 // 598 //
509 // So we don't fill process_->GetData().handle and wait for 599 // So we don't fill process_->GetData().handle and wait for
510 // OnChannelConnected to get handle of NaCl process from its pid. Then we 600 // OnChannelConnected to get handle of NaCl process from its pid. Then we
511 // call OnProcessLaunched. 601 // call OnProcessLaunched.
512 return base::LaunchProcess(*gdb_cmd_line, base::LaunchOptions(), NULL); 602 return base::LaunchProcess(*gdb_cmd_line, base::LaunchOptions(), NULL);
603 #elif defined(OS_LINUX)
604 wait_for_nacl_gdb_ = true;
605 #endif
513 } 606 }
514 607
515 // On Windows we might need to start the broker process to launch a new loader 608 // On Windows we might need to start the broker process to launch a new loader
516 #if defined(OS_WIN) 609 #if defined(OS_WIN)
517 if (RunningOnWOW64()) { 610 if (RunningOnWOW64()) {
518 return NaClBrokerService::GetInstance()->LaunchLoader(this, channel_id); 611 return NaClBrokerService::GetInstance()->LaunchLoader(this, channel_id);
519 } else { 612 } else {
520 process_->Launch(FilePath(), cmd_line.release()); 613 process_->Launch(FilePath(), cmd_line.release());
521 } 614 }
522 #elif defined(OS_POSIX) 615 #elif defined(OS_POSIX)
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 NULL, 710 NULL,
618 &error_code); 711 &error_code);
619 if (error_code != base::PLATFORM_FILE_OK) { 712 if (error_code != base::PLATFORM_FILE_OK) {
620 LOG(ERROR) << "Failed to open NaCl IRT file \"" 713 LOG(ERROR) << "Failed to open NaCl IRT file \""
621 << irt_filepath_.LossyDisplayName() 714 << irt_filepath_.LossyDisplayName()
622 << "\": " << error_code; 715 << "\": " << error_code;
623 } 716 }
624 } 717 }
625 718
626 void NaClProcessHost::OnProcessLaunched() { 719 void NaClProcessHost::OnProcessLaunched() {
720 #if defined(OS_LINUX)
721 if (wait_for_nacl_gdb_) {
722 if (LaunchNaClGdb(base::GetProcId(process_->GetData().handle))) {
723 // OnProcessLaunched will be called with wait_for_nacl_gdb_ = false once
724 // debugger is attached to the program.
725 return;
726 }
727 LOG(ERROR) << "Cannot launch debugger";
Mark Seaborn 2012/04/03 21:57:44 "Failed to launch debugger" might be better
halyavin 2012/04/04 09:23:15 Done.
728 // Continue execution without debugger.
729 }
730 #endif
627 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); 731 NaClBrowser* nacl_browser = NaClBrowser::GetInstance();
628 732
629 if (nacl_browser->IrtAvailable()) { 733 if (nacl_browser->IrtAvailable()) {
630 // The IRT is already open. Away we go. 734 // The IRT is already open. Away we go.
631 SendStart(); 735 SendStart();
632 } else { 736 } else {
633 // We're waiting for the IRT to be open. 737 // We're waiting for the IRT to be open.
634 if (!nacl_browser->MakeIrtAvailable( 738 if (!nacl_browser->MakeIrtAvailable(
635 base::Bind(&NaClProcessHost::IrtReady, 739 base::Bind(&NaClProcessHost::IrtReady,
636 weak_factory_.GetWeakPtr()))) 740 weak_factory_.GetWeakPtr())))
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 bool handled = true; 1018 bool handled = true;
915 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) 1019 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg)
916 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, 1020 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate,
917 OnQueryKnownToValidate) 1021 OnQueryKnownToValidate)
918 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, 1022 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate,
919 OnSetKnownToValidate) 1023 OnSetKnownToValidate)
920 IPC_MESSAGE_UNHANDLED(handled = false) 1024 IPC_MESSAGE_UNHANDLED(handled = false)
921 IPC_END_MESSAGE_MAP() 1025 IPC_END_MESSAGE_MAP()
922 return handled; 1026 return handled;
923 } 1027 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698