The go c-shared object need the libc to pass them the argc and argv parameters in order to initialize the runtime properly.
This is a preparation patch for this. Signed-off-by: Benoît Canet <[email protected]> --- core/app.cc | 65 ++++++++++++++++++++++++++++-------------------------- include/osv/app.hh | 8 +++++++ 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/core/app.cc b/core/app.cc index ad3145f..515096e 100644 --- a/core/app.cc +++ b/core/app.cc @@ -294,20 +294,31 @@ void application::main() // _entry_point() doesn't return } -void application::run_main(std::string path, int argc, char** argv) +void application::prepare_argc_argv() { - char *c_path = (char *)(path.c_str()); + // C main wants mutable arguments, so we have can't use strings directly + transform(_args, back_inserter(_mut_args), + [](std::string s) { return std::vector<char>(s.data(), s.data() + s.size() + 1); }); + std::vector<char*> argv; + transform(_mut_args.begin(), _mut_args.end(), back_inserter(argv), + [](std::vector<char>& s) { return s.data(); }); + _argc = argv.size(); + argv.push_back(nullptr); + + char **argv_data = argv.data(); + + char *c_path = (char *)(_command.c_str()); // path is guaranteed to keep existing this function program_invocation_name = c_path; program_invocation_short_name = basename(c_path); - auto sz = argc; // for the trailing 0's. - for (int i = 0; i < argc; ++i) { - sz += strlen(argv[i]); + auto sz = _argc; // for the trailing 0's. + for (int i = 0; i < _argc; ++i) { + sz += strlen(argv_data[i]); } - std::unique_ptr<char []> argv_buf(new char[sz]); - char *ab = argv_buf.get(); + _argv_buf.reset(new char[sz]); + char *ab = _argv_buf.get(); // In Linux, the pointer arrays argv[] and envp[] are continguous. // Unfortunately, some programs rely on this fact (e.g., libgo's // runtime_goenvs_unix()) so it is useful that we do this too. @@ -315,44 +326,36 @@ void application::run_main(std::string path, int argc, char** argv) while (environ[envcount]) { envcount++; } - char *contig_argv[argc + 1 + envcount + 1]; + _contig_argv.reset(new char*[_argc + 1 + envcount + 1]); + char **contig_argv = _contig_argv.get(); - for (int i = 0; i < argc; ++i) { - size_t asize = strlen(argv[i]); - memcpy(ab, argv[i], asize); + for (int i = 0; i < _argc; ++i) { + size_t asize = strlen(argv_data[i]); + memcpy(ab, argv_data[i], asize); ab[asize] = '\0'; contig_argv[i] = ab; ab += asize + 1; } - contig_argv[argc] = nullptr; + contig_argv[_argc] = nullptr; for (int i = 0; i < envcount; i++) { - contig_argv[argc + 1 + i] = environ[i]; + contig_argv[_argc + 1 + i] = environ[i]; } - contig_argv[argc + 1 + envcount] = nullptr; - - // make sure to have a fresh optind across calls - // FIXME: fails if run() is executed in parallel - int old_optind = optind; - optind = 0; - _return_code = _main(argc, contig_argv); - optind = old_optind; + contig_argv[_argc + 1 + envcount] = nullptr; } void application::run_main() { trace_app_main(this, _command.c_str()); - // C main wants mutable arguments, so we have can't use strings directly - std::vector<std::vector<char>> mut_args; - transform(_args, back_inserter(mut_args), - [](std::string s) { return std::vector<char>(s.data(), s.data() + s.size() + 1); }); - std::vector<char*> argv; - transform(mut_args.begin(), mut_args.end(), back_inserter(argv), - [](std::vector<char>& s) { return s.data(); }); - auto argc = argv.size(); - argv.push_back(nullptr); - run_main(_command, argc, argv.data()); + prepare_argc_argv(); + + // make sure to have a fresh optind across calls + // FIXME: fails if run() is executed in parallel + int old_optind = optind; + optind = 0; + _return_code = _main(_argc, _contig_argv.get()); + optind = old_optind; if (_return_code) { debug("program %s returned %d\n", _command.c_str(), _return_code); diff --git a/include/osv/app.hh b/include/osv/app.hh index 6fa503a..3ecf1a8 100644 --- a/include/osv/app.hh +++ b/include/osv/app.hh @@ -194,6 +194,7 @@ private: void start_and_join(waiter* setup_waiter); void main(); void run_main(std::string path, int argc, char** argv); + void prepare_argc_argv(); void run_main(); friend void ::__libc_start_main(int(*)(int, char**), int, char**, void(*)(), void(*)(), void(*)(), void*); @@ -214,6 +215,13 @@ private: void (*_entry_point)(); static app_registry apps; + // argc and argv variables + std::vector<std::vector<char>> _mut_args; + std::unique_ptr<char *> _contig_argv; + std::unique_ptr<char []> _argv_buf; + std::vector<char*> _argv; + int _argc; + // Must be destroyed before _lib, because contained function objects may // have destructors which are part of the application's code. std::list<std::function<void()>> _termination_request_callbacks; -- 2.7.4 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
