LCOV - code coverage report
Current view: directory - src/trusted/sel_universal - sel_universal.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 151 109 72.2 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : // Second generation sel_universal implemented in C++ and with optional
       8                 : // multimedia support via SDL
       9                 : 
      10                 : #include <stdio.h>
      11                 : 
      12                 : #include <fstream>
      13                 : #include <map>
      14                 : #include <sstream>
      15                 : #include <string>
      16                 : #include <vector>
      17                 : #include "native_client/src/include/nacl_string.h"
      18                 : #include "native_client/src/include/nacl_macros.h"
      19                 : #include "native_client/src/include/nacl_scoped_ptr.h"
      20                 : #include "native_client/src/include/portability.h"
      21                 : #include "native_client/src/include/portability_io.h"
      22                 : #include "native_client/src/shared/platform/nacl_log.h"
      23                 : #include "native_client/src/shared/platform/scoped_ptr_refcount.h"
      24                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      25                 : #include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
      26                 : #include "native_client/src/trusted/desc/nrd_all_modules.h"
      27                 : #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
      28                 : #include "native_client/src/trusted/reverse_service/reverse_service.h"
      29                 : #include "native_client/src/trusted/sel_universal/pepper_emu_handler.h"
      30                 : #include "native_client/src/trusted/sel_universal/pnacl_emu_handler.h"
      31                 : #include "native_client/src/trusted/sel_universal/reverse_emulate.h"
      32                 : #include "native_client/src/trusted/sel_universal/replay_handler.h"
      33                 : #include "native_client/src/trusted/sel_universal/rpc_universal.h"
      34                 : 
      35                 : #if defined(NACL_SEL_UNIVERSAL_INCLUDE_SDL)
      36                 : // NOTE: we need to include this so that it can "hijack" main
      37                 : #include <SDL/SDL.h>
      38                 : #endif
      39                 : 
      40                 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
      41                 : 
      42                 : using std::ifstream;
      43                 : using std::map;
      44                 : using std::string;
      45                 : using std::vector;
      46                 : using nacl::DescWrapper;
      47                 : 
      48                 : // TODO(robertm): add explanation for flags
      49                 : static const char* kUsage =
      50                 :     "Usage:\n"
      51                 :     "\n"
      52                 :     "sel_universal <sel_universal_arg> <sel_ldr_arg>* [-- <nexe> <nexe_arg>*]\n"
      53                 :     "\n"
      54                 :     "Exactly one nexe argument is required.\n"
      55                 :     "After startup the user is prompted for interactive commands.\n"
      56                 :     "For sample commands have a look at: tests/srpc/srpc_basic_test.stdin\n"
      57                 :     "\n"
      58                 :     "sel_universal arguments are:\n"
      59                 :     "\n"
      60                 :     "  --help\n"
      61                 :     "  --event_record <file>\n"
      62                 :     "  --event_replay <file>\n"
      63                 :     "  --debug\n"
      64                 :     "  --abort_on_error\n"
      65                 :     "  --silence_nexe\n"
      66                 :     "  --command_prefix <prefix>\n"
      67                 :     "  --command_file <file>\n"
      68                 :     "  --var <tag> <value>\n"
      69                 :     "  --url_alias <url> <filename>\n"
      70                 :     "  --uses_reverse_service\n"
      71                 :     "\n"
      72                 :     "The following sel_ldr arguments might be useful:\n"
      73                 :     "  -v                    increase verbosity\n"
      74                 :     "  -E NACL_SRPC_DEBUG=1  even more verbosity for srpc debugging\n";
      75                 : 
      76                 : 
      77                 : // NOTE: this used to be stack allocated inside main which cause
      78                 : // problems on ARM (probably a tool chain bug).
      79                 : // NaClSrpcChannel is pretty big (> 256kB)
      80                 : static NaClSrpcChannel command_channel;
      81                 : static NaClSrpcChannel channel;
      82                 : 
      83                 : // variables set via command line
      84              22 : static map<string, string> initial_vars;
      85              22 : static vector<string> initial_commands;
      86                 : static bool abort_on_error = false;
      87                 : static bool silence_nexe = false;
      88              33 : static string command_prefix = "";
      89                 : static bool uses_reverse_service = false;
      90                 : 
      91                 : // When given argc and argv this function (a) extracts the nexe argument,
      92                 : // (b) populates sel_ldr_argv with sel_ldr arguments, and (c) populates
      93                 : // app_argv with nexe module args. Also see kUsage above for details.
      94                 : // It will call exit with codes 0 (help message) and 1 (incorrect args).
      95                 : static nacl::string ProcessArguments(int argc,
      96                 :                                      char* argv[],
      97                 :                                      vector<nacl::string>* const sel_ldr_argv,
      98              11 :                                      vector<nacl::string>* const app_argv) {
      99              11 :   if (argc == 1) {
     100               0 :     printf("%s", kUsage);
     101               0 :     exit(0);
     102                 :   }
     103                 : 
     104              11 :   int debug_level = 0;
     105                 :   // Extract sel_universal arguments and transfer the rest to sel_ldr_argv
     106              11 :   nacl::string app_name;
     107              34 :   for (int i = 1; i < argc; i++) {
     108              23 :     const string flag(argv[i]);
     109              46 :     if (flag == "--help") {
     110               0 :       printf("%s", kUsage);
     111               0 :       exit(0);
     112              23 :     } else if (flag == "--event_record") {
     113               0 :       if (argc <= i + 1) {
     114               0 :         NaClLog(LOG_FATAL, "not enough args for --event_record option\n");
     115                 :       }
     116               0 :       RecordPPAPIEvents(argv[i + 1]);
     117              23 :     } else if (flag == "--event_replay") {
     118               0 :       if (argc <= i + 1) {
     119               0 :         NaClLog(LOG_FATAL, "not enough args for --event_replay option\n");
     120                 :       }
     121               0 :       ReplayPPAPIEvents(argv[i + 1]);
     122              23 :     } else if (flag == "--debug") {
     123               0 :       ++debug_level;
     124              23 :     } else if (flag == "--abort_on_error") {
     125               0 :       abort_on_error = true;
     126              23 :     } else if (flag == "--silence_nexe") {
     127               0 :       silence_nexe = true;
     128              23 :     } else if (flag == "--command_prefix") {
     129               0 :       if (argc <= i + 1) {
     130                 :         NaClLog(LOG_FATAL,
     131               0 :                 "not enough args for --command_prefix option\n");
     132                 :       }
     133               0 :       ++i;
     134               0 :       command_prefix = argv[i];
     135              23 :     } else if (flag == "--command_file") {
     136               4 :       if (argc <= i + 1) {
     137               0 :         NaClLog(LOG_FATAL, "not enough args for --command_file option\n");
     138                 :       }
     139               4 :       NaClLog(LOG_INFO, "reading commands from %s\n", argv[i + 1]);
     140               4 :       ifstream f;
     141               4 :       f.open(argv[i + 1]);
     142               4 :       ++i;
     143              37 :       while (!f.eof()) {
     144              33 :         string s;
     145              33 :         getline(f, s);
     146              33 :         initial_commands.push_back(s);
     147                 :       }
     148               4 :       f.close();
     149                 :       NaClLog(LOG_INFO, "total commands now: %d\n",
     150               4 :               static_cast<int>(initial_commands.size()));
     151              19 :     } else if (flag == "--url_alias") {
     152               0 :       if (argc <= i + 2) {
     153               0 :         NaClLog(LOG_FATAL, "not enough args for --url_alias option\n");
     154                 :       }
     155               0 :       RegisterFileAliasForUrl(argv[i + 1], argv[i + 2]);
     156               0 :       i += 2;
     157              19 :     } else if (flag == "--var") {
     158               2 :       if (argc <= i + 2) {
     159               0 :         NaClLog(LOG_FATAL, "not enough args for --var option\n");
     160                 :       }
     161                 : 
     162               2 :       const string tag = string(argv[i + 1]);
     163               4 :       const string val = string(argv[i + 2]);
     164               2 :       i += 2;
     165               4 :       initial_vars[tag] = val;
     166              17 :     } else if (flag == "--uses_reverse_service") {
     167               2 :       uses_reverse_service = true;
     168              15 :     } else if (flag == "--") {
     169                 :       // Done processing sel_ldr args.  The first argument after '--' is the
     170                 :       // nexe.
     171              11 :       i++;
     172              11 :       if (app_name == "" && i < argc) {
     173              11 :         app_name = argv[i++];
     174                 :       }
     175                 :       // The remaining arguments are passed to the executable.
     176              22 :       for (; i < argc; i++) {
     177               0 :         app_argv->push_back(argv[i]);
     178                 :       }
     179                 :     } else {
     180                 :       // NOTE: most sel_ldr args start with a single hyphen so there is not
     181                 :       // much confusion with sel_universal args. But this remains a hack.
     182               4 :       sel_ldr_argv->push_back(argv[i]);
     183                 :     }
     184                 :   }
     185                 : 
     186              11 :   if (debug_level > 0) {
     187               0 :     NaClLogSetVerbosity(debug_level);
     188                 :   }
     189                 : 
     190              11 :   if (app_name == "") {
     191               0 :     NaClLog(LOG_FATAL, "missing app\n");
     192                 :   }
     193                 : 
     194               0 :   return app_name;
     195                 : }
     196                 : 
     197                 : 
     198              11 : int raii_main(int argc, char* argv[]) {
     199                 :   // Get the arguments to sed_ldr and the nexe module
     200              11 :   vector<nacl::string> sel_ldr_argv;
     201              22 :   vector<nacl::string> app_argv;
     202                 :   nacl::string app_name =
     203              11 :     ProcessArguments(argc, argv, &sel_ldr_argv, &app_argv);
     204                 : 
     205                 :   // Add '-X 5' to sel_ldr arguments to create communication socket
     206              11 :   sel_ldr_argv.push_back("-X");
     207              22 :   sel_ldr_argv.push_back("5");
     208              11 :   if (silence_nexe) {
     209                 :     // redirect stdout/stderr in the nexe to /dev/null
     210               0 :     std::stringstream ss_stdout;
     211               0 :     std::stringstream ss_stderr;
     212                 : 
     213               0 :     int fd = open(PORTABLE_DEV_NULL, O_RDWR);
     214               0 :     sel_ldr_argv.push_back("-w");
     215               0 :     ss_stdout << "1:" << fd;
     216               0 :     sel_ldr_argv.push_back(ss_stdout.str());
     217               0 :     sel_ldr_argv.push_back("-w");
     218               0 :     ss_stderr << "2:" << fd;
     219               0 :     sel_ldr_argv.push_back(ss_stderr.str());
     220                 :   }
     221                 :   // Start sel_ldr with the given application and arguments.
     222              11 :   nacl::SelLdrLauncher launcher;
     223              11 :   nacl::DescWrapperFactory factory;  // DescWrapper "namespace"
     224                 : 
     225              11 :   if (command_prefix != "") {
     226               0 :     launcher.SetCommandPrefix(command_prefix);
     227                 :   }
     228                 : 
     229              11 :   launcher.InitCommandLine(5, sel_ldr_argv, app_argv);
     230              11 :   if (!launcher.LaunchFromCommandLine()) {
     231               0 :     NaClLog(LOG_FATAL, "sel_universal: Failed to launch sel_ldr\n");
     232                 :   }
     233                 : 
     234              11 :   DescWrapper *host_file = factory.OpenHostFile(app_name.c_str(), O_RDONLY, 0);
     235              11 :   if (NULL == host_file) {
     236               0 :     NaClLog(LOG_ERROR, "Could not open %s\n", app_name.c_str());
     237               0 :     exit(1);
     238                 :   }
     239                 : 
     240              11 :   if (!launcher.SetupCommandAndLoad(&command_channel, host_file)) {
     241               0 :     NaClLog(LOG_ERROR, "sel_universal: set up command and load failed\n");
     242               0 :     exit(1);
     243                 :   }
     244                 : 
     245              11 :   delete host_file;
     246                 : 
     247              11 :   if (uses_reverse_service) {
     248               2 :     ReverseEmulateInit(&command_channel, &launcher);
     249                 :   }
     250                 : 
     251              11 :   if (!launcher.StartModuleAndSetupAppChannel(&command_channel, &channel)) {
     252                 :     NaClLog(LOG_ERROR,
     253               1 :             "sel_universal: start module and set up app channel failed\n");
     254               1 :     exit(1);
     255                 :   }
     256                 : 
     257                 :   NaClCommandLoop loop(channel.client,
     258                 :                        &channel,
     259              10 :                        launcher.socket_addr()->desc());
     260                 : 
     261                 :   //
     262                 :   // Pepper sample commands
     263                 :   // initialize_pepper pepper
     264                 :   //   sdl_initialize OR (replay*; replay_activate)
     265                 :   // install_upcalls service
     266                 :   // show_variables
     267                 :   // show_descriptors
     268                 :   // rpc PPP_InitializeModule i(0) l(0) h(pepper) s("${service}") * i(0) i(0)
     269                 : 
     270              10 :   loop.AddHandler("replay_activate", HandlerReplayActivate);
     271              20 :   loop.AddHandler("replay", HandlerReplay);
     272              20 :   loop.AddHandler("replay_unused", HandlerUnusedReplays);
     273                 : 
     274                 :   // possible platform specific stuff
     275              20 :   loop.AddHandler("shmem", HandlerShmem);
     276              20 :   loop.AddHandler("readonly_file", HandlerReadonlyFile);
     277              20 :   loop.AddHandler("readwrite_file", HandlerReadwriteFile);
     278              20 :   loop.AddHandler("readwrite_quota_file", HandlerReadwriteFileQuota);
     279              20 :   loop.AddHandler("sleep", HandlerSleep);
     280              20 :   loop.AddHandler("map_shmem", HandlerMap);
     281              20 :   loop.AddHandler("save_to_file", HandlerSaveToFile);
     282              20 :   loop.AddHandler("load_from_file", HandlerLoadFromFile);
     283              20 :   loop.AddHandler("file_size", HandlerFileSize);
     284              20 :   loop.AddHandler("sync_socket_create", HandlerSyncSocketCreate);
     285              20 :   loop.AddHandler("sync_socket_write", HandlerSyncSocketWrite);
     286                 :   // obsolete names
     287              20 :   loop.AddHandler("sdl_initialize", HandlerPepperEmuInitialize);
     288              20 :   loop.AddHandler("sdl_event_loop", HandlerPepperEmuEventLoop);
     289                 :   // new names
     290              20 :   loop.AddHandler("pnacl_emu_initialize", HandlerPnaclEmuInitialize);
     291                 :   loop.AddHandler("pnacl_emu_add_varname_mapping",
     292              20 :                   HandlerPnaclEmuAddVarnameMapping);
     293                 :   loop.AddHandler("reverse_service_add_manifest_mapping",
     294              20 :                   HandlerReverseEmuAddManifestMapping);
     295                 :   loop.AddHandler("reverse_service_dump_manifest_mappings",
     296              20 :                   HandlerReverseEmuDumpManifestMappings);
     297              20 :   loop.AddHandler("stream_file", HandlerPnaclFileStream);
     298                 : 
     299              20 :   loop.AddHandler("pepper_emu_initialize", HandlerPepperEmuInitialize);
     300              20 :   loop.AddHandler("pepper_emu_event_loop", HandlerPepperEmuEventLoop);
     301                 :   loop.AddHandler("pepper_emu_set_quit_message",
     302              20 :                   HandlerPepperEmuSetQuitMessage);
     303                 : 
     304              10 :   NaClLog(1, "populating initial vars\n");
     305              12 :   for (map<string, string>::iterator it = initial_vars.begin();
     306                 :        it != initial_vars.end();
     307                 :        ++it) {
     308               2 :     loop.SetVariable(it->first, it->second);
     309                 :   }
     310                 : 
     311                 :   const bool success = initial_commands.size() > 0 ?
     312                 :                        loop.ProcessCommands(initial_commands) :
     313              10 :                        loop.StartInteractiveLoop(abort_on_error);
     314                 : 
     315                 :   // Close the connections to sel_ldr.
     316              10 :   NaClSrpcDtor(&command_channel);
     317              10 :   NaClSrpcDtor(&channel);
     318                 : 
     319              10 :   if (uses_reverse_service) {
     320               2 :     ReverseEmulateFini();
     321                 :   }
     322                 : 
     323              10 :   return success ? 0 : -1;
     324                 : }
     325                 : 
     326              11 : int main(int argc, char* argv[]) {
     327                 :   // Descriptor transfer requires the following
     328              11 :   NaClSrpcModuleInit();
     329              11 :   NaClNrdAllModulesInit();
     330                 : 
     331              11 :   int exit_status = raii_main(argc, argv);
     332                 : 
     333              10 :   NaClSrpcModuleFini();
     334              10 :   NaClNrdAllModulesFini();
     335                 : 
     336              10 :   return exit_status;
     337              22 : }

Generated by: LCOV version 1.7