2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
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
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.
38 #include "native_client/service_runtime/dyn_array.h"
39 #include "native_client/service_runtime/nacl_app_thread.h"
40 #include "native_client/service_runtime/nacl_check.h"
41 #include "native_client/service_runtime/nacl_config.h"
42 #include "native_client/service_runtime/nacl_desc_base.h"
43 #include "native_client/service_runtime/nacl_ldt.h"
44 #include "native_client/service_runtime/nacl_log.h"
45 #include "native_client/service_runtime/nacl_sync_checked.h"
46 #include "native_client/service_runtime/sel_ldr.h"
47 #include "native_client/service_runtime/sel_rt.h"
50 * Allocate ldt for app, without creating the main thread.
52 NaClErrorCode
NaClAppPrepareToLaunch(struct NaClApp
*nap
,
68 struct NaClHostDesc
*nhdp
;
72 NaClErrorCode retval
= LOAD_INTERNAL
;
78 NaClXMutexLock(&nap
->mu
);
80 data_start
= nap
->data_mem_start
;
81 CHECK(nap
->addr_bits
> NACL_PAGESHIFT
);
82 data_pages
= 1 << (nap
->addr_bits
- NACL_PAGESHIFT
);
85 * Determine what region of memory can be accessed as code.
87 code_start
= nap
->code_mem_start
;
88 if (nap
->data_mem_start
== nap
->code_mem_start
)
90 code_bytes
= nap
->text_region_end
;
91 VCHECK((code_bytes
& ((1 << NACL_PAGESHIFT
)-1)) == 0,
92 ("code_bytes (0x%08"PRIxS
") is not page aligned\n",
94 code_pages
= code_bytes
>> NACL_PAGESHIFT
;
97 code_pages
= data_pages
;
100 NaClLog(LOG_FATAL
, "NaClAppPrepareToLaunch: fewer than one code pages?\n");
103 "NaClLdtAllocatePageSelector(code, 1, 0x%08"PRIxPTR
", 0x%"PRIxS
"\n",
104 code_start
, code_pages
);
105 cs
= NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_CODE
,
109 NaClLog(2, "got 0x%x\n", cs
);
111 retval
= SRT_NO_SEG_SEL
;
116 * Determine what region of memory can be accessed as data.
118 * NB: in our memory model, we roughly follow standard 7th edition
119 * unix but with a >16-bit address space: data and code overlap, and
120 * the start of the data segment is the same as the start of the
121 * code region; and the data segment actually includes the memory
122 * hole between the break and the top of the stack, as well as the
123 * stack and environment variables and other things in memory above
126 * The code pages, which is marked read-only via the page protection
127 * mechanism, could be viewed as read-only data. Nothing prevents a
128 * NaCl application from looking at its own code.
130 * The same segment selector is used for ds, es, and ss, and thus
131 * "des_seg". Nuthin' to do with the old Data Encryption Standard.
134 if (data_pages
< 1) {
136 "NaClAppPrepareToLaunch: address space is fewer than one page?\n");
139 "NaClLdtAllocatePageSelector(data, 1, 0x%08"PRIxPTR
", 0x%"PRIxS
"\n",
140 data_start
, data_pages
- 1);
141 des_seg
= NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_DATA
,
146 NaClLog(2, "got 0x%x\n", des_seg
);
148 NaClLdtDeleteSelector(cs
);
149 retval
= SRT_NO_SEG_SEL
;
152 nap
->code_seg_sel
= cs
;
153 nap
->data_seg_sel
= des_seg
;
155 * Note that gs is thread-specific and not global, so that is allocated
156 * elsewhere. See nacl_app_thread.c.
160 * We dup the stdin, stdout, and stderr descriptors and wrap them in
161 * NaClHostDesc objects. Those in turn are wrapped by the
162 * NaClDescIoDesc subclass of NaClDesc, and then put into the
163 * open-file table. NaCl app I/O operations will use these shared
164 * descriptors, and if they close one of these descriptors it will
165 * only be a duplicated descriptor. NB: some fcntl/ioctl flags
166 * apply to the descriptor (e.g., O_CLOEXEC) and some apply to the
167 * underlying open file entry (e.g., O_NONBLOCK), so changes by the
168 * NaCl app could affect the service runtime.
170 for (i
= 0; i
< 3; ++i
) {
171 nhdp
= malloc(sizeof *nhdp
);
174 "NaClAppPrepareToLaunch: no memory for abstract descriptor %d\n",
177 NaClHostDescPosixDup(nhdp
, descs
[i
], (0 == i
) ? O_RDONLY
: O_WRONLY
);
178 NaClSetDesc(nap
, i
, (struct NaClDesc
*) NaClDescIoDescMake(nhdp
));
182 NaClXMutexUnlock(&nap
->mu
);