Add -E option for setting environment variables
[nativeclient.git] / service_runtime / nacl_app.c
blob6c8856e1acb118061d3bbedc16bd54e5be96e301
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl run time.
35 #include <fcntl.h>
36 #include <stdlib.h>
38 #include "native_client/service_runtime/nacl_config.h"
39 #include "native_client/service_runtime/nacl_check.h"
40 #include "native_client/service_runtime/dyn_array.h"
41 #include "native_client/service_runtime/sel_ldr.h"
42 #include "native_client/service_runtime/sel_rt.h"
43 #include "native_client/service_runtime/nacl_app_thread.h"
44 #include "native_client/service_runtime/nacl_ldt.h"
45 #include "native_client/service_runtime/nacl_log.h"
46 #include "native_client/service_runtime/nacl_desc_base.h"
49 * Allocate ldt for app, without creating the main thread.
51 NaClErrorCode NaClAppPrepareToLaunch(struct NaClApp *nap)
53 uintptr_t code_start;
54 size_t code_bytes;
55 size_t code_pages;
57 uintptr_t data_start;
58 size_t data_pages;
60 uint16_t cs;
61 uint16_t des_seg;
63 int i;
64 struct NaClHostDesc *nhdp;
67 * Determine what region of memory can be accessed as code.
69 code_start = nap->mem_start;
70 code_bytes = NACL_TRAMPOLINE_SIZE + nap->text_region_bytes;
71 VCHECK((code_bytes & ((1 << NACL_PAGESHIFT)-1)) == 0,
72 ("code_bytes (0x%08x) is not page aligned\n",
73 code_bytes));
74 code_pages = code_bytes >> NACL_PAGESHIFT;
76 if (code_pages < 1) {
77 NaClLog(LOG_FATAL, "NaClAppPrepareToLaunch: fewer than one code pages?\n");
79 NaClLog(2, "NaClLdtAllocatePageSelector(code, 1, 0x%08x, 0x%x\n",
80 code_start, code_pages);
81 cs = NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_CODE,
83 (void *) code_start,
84 code_pages);
85 NaClLog(2, "got 0x%x\n", cs);
86 if (0 == cs) {
87 return SRT_NO_SEG_SEL;
91 * Determine what region of memory can be accessed as data.
93 * NB: in our memory model, we roughly follow standard 7th edition
94 * unix but with a >16-bit address space: data and code overlap, and
95 * the start of the data segment is the same as the start of the
96 * code region; and the data segment actually includes the memory
97 * hole between the break and the top of the stack, as well as the
98 * stack and environment variables and other things in memory above
99 * the stack.
101 * The code pages, which is marked read-only via the page protection
102 * mechanism, could be viewed as read-only data. Nothing prevents a
103 * NaCl application from looking at its own code.
105 * The same segment selector is used for ds, es, and ss, and thus
106 * "des_seg". Nuthin' to do with the old Data Encryption Standard.
108 data_start = nap->mem_start;
109 CHECK(nap->addr_bits > NACL_PAGESHIFT);
110 data_pages = 1 << (nap->addr_bits - NACL_PAGESHIFT);
112 if (data_pages < 1) {
113 NaClLog(LOG_FATAL,
114 "NaClAppPrepareToLaunch: address space is fewer than one page?\n");
116 NaClLog(2, "NaClLdtAllocatePageSelector(data, 1, 0x%08x, 0x%x\n",
117 data_start, data_pages - 1);
118 des_seg = NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_DATA,
120 (void *) data_start,
121 data_pages);
123 NaClLog(2, "got 0x%x\n", des_seg);
124 if (0 == des_seg) {
125 NaClLdtDeleteSelector(cs);
126 return SRT_NO_SEG_SEL;
128 nap->code_seg_sel = cs;
129 nap->data_seg_sel = des_seg;
131 * Note that gs is thread-specific and not global, so that is allocated
132 * elsewhere. See nacl_app_thread.c.
136 * We dup the stdin, stdout, and stderr descriptors and wrap them in
137 * NaClHostDesc objects. Those in turn are wrapped by the
138 * NaClDescIoDesc subclass of NaClDesc, and then put into the
139 * open-file table. NaCl app I/O operations will use these shared
140 * descriptors, and if they close one of these descriptors it will
141 * only be a duplicated descriptor. NB: some fcntl/ioctl flags
142 * apply to the descriptor (e.g., O_CLOEXEC) and some apply to the
143 * underlying open file entry (e.g., O_NONBLOCK), so changes by the
144 * NaCl app could affect the service runtime.
146 for (i = 0; i < 3; ++i) {
147 nhdp = malloc(sizeof *nhdp);
148 if (NULL == nhdp) {
149 NaClLog(LOG_FATAL,
150 "NaClAppPrepareToLaunch: no memory for abstract descriptor %d\n",
153 NaClHostDescPosixDup(nhdp, i, (0 == i) ? O_RDONLY : O_WRONLY);
154 NaClSetDesc(nap, i, (struct NaClDesc *) NaClDescIoDescMake(nhdp));
157 return LOAD_OK;