1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <malloc.h>
18 #include <sys/auxv.h>
19 #include <unistd.h>
20
21 #include <cstdio>
22 #include <cstring>
23 #include <string>
24 #include <tuple>
25
26 #include "berberis/base/bit_util.h"
27 #include "berberis/base/checks.h"
28 #include "berberis/base/file.h"
29 #include "berberis/guest_loader/guest_loader.h"
30 #include "berberis/guest_state/guest_addr.h"
31 #include "berberis/program_runner/program_runner.h"
32 #include "berberis/runtime/berberis.h"
33
34 // Program runner meant for testing and manual invocation.
35
36 namespace berberis {
37
38 namespace {
39
Usage(const char * argv_0)40 void Usage(const char* argv_0) {
41 printf(
42 "Usage: %s [-h] guest_executable [arg1 [arg2 ...]]\n"
43 " -h - print this message\n"
44 " guest_executable - path to the guest executable\n",
45 argv_0);
46 }
47
48 struct Options {
49 bool print_help_and_exit;
50 };
51
ParseArgs(int argc,char * argv[])52 Options ParseArgs(int argc, char* argv[]) {
53 CHECK_GE(argc, 1);
54
55 Options opts{};
56
57 while (true) {
58 int c = getopt(argc, argv, "+h:");
59 if (c < 0) {
60 break;
61 }
62 switch (c) {
63 case 'h':
64 return Options{.print_help_and_exit = true};
65 default:
66 UNREACHABLE();
67 }
68 }
69
70 if (optind >= argc) {
71 return Options{.print_help_and_exit = true};
72 }
73
74 opts.print_help_and_exit = false;
75 return opts;
76 }
77
78 } // namespace
79
80 } // namespace berberis
81
main(int argc,char * argv[],char * envp[])82 int main(int argc, char* argv[], char* envp[]) {
83 #if defined(__GLIBC__)
84 // Disable brk in glibc-malloc.
85 //
86 // By default GLIBC uses brk in malloc which may lead to conflicts with
87 // executables that use brk for their own needs. See http://b/64720148 for
88 // example.
89 mallopt(M_MMAP_THRESHOLD, 0);
90 mallopt(M_TRIM_THRESHOLD, -1);
91 #endif
92
93 berberis::Options opts = berberis::ParseArgs(argc, argv);
94
95 if (opts.print_help_and_exit) {
96 berberis::Usage(argv[0]);
97 return -1;
98 }
99
100 std::string error_msg;
101 if (!berberis::Run(
102 // TODO(b/276787135): Make vdso and loader configurable via command line arguments.
103 /* vdso_path */ nullptr,
104 /* loader_path */ nullptr,
105 argc - optind,
106 const_cast<const char**>(argv + optind),
107 envp,
108 &error_msg)) {
109 fprintf(stderr, "unable to start executable: %s\n", error_msg.c_str());
110 return -1;
111 }
112
113 return 0;
114 }
115