Debugging: Add code to print backtrace for guest on SIGSEGV
[nativeclient.git] / service_runtime / nacl_desc_base.h
blobba2fa1b9dc2c1a4ad29cb7952c90e8e235e108fc
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 Service Runtime. I/O Descriptor / Handle abstraction.
36 #ifndef NATIVE_CLIENT_SERVICE_RUNTIME_NACL_DESC_BASE_H_
37 #define NATIVE_CLIENT_SERVICE_RUNTIME_NACL_DESC_BASE_H_
40 /* defines PATH_MAX */
41 # include "native_client/include/nacl_base.h"
42 # include "native_client/include/portability.h"
44 #include "native_client/service_runtime/nacl_desc_effector.h"
46 #include "native_client/service_runtime/nacl_host_desc.h"
47 #include "native_client/service_runtime/nacl_host_dir.h"
48 #include "native_client/service_runtime/nacl_interruptible_condvar.h"
49 #include "native_client/service_runtime/nacl_interruptible_mutex.h"
50 #include "native_client/service_runtime/nacl_semaphore.h"
51 #include "native_client/service_runtime/nacl_sync.h"
53 #include "native_client/intermodule_comm/nacl_imc_c.h"
55 #include "native_client/service_runtime/include/sys/errno.h"
56 #include "native_client/service_runtime/include/sys/time.h"
58 EXTERN_C_BEGIN
60 struct NaClDesc;
61 struct nacl_abi_stat;
64 * Externalization / internalization state, used by
65 * Externalize/Internalize functions. Externalize convert the
66 * descriptor represented by the self (this) object to an entry in the
67 * handles table in a NaClMessageHeader, and the Internalize function
68 * is a factory that takes a dgram and NaClDescXferState and
69 * constructs a vector of NaClDesc objects.
71 * This is essentially a pair of input/output iterators. The *_end
72 * values are not needed during externalization, since the SendMsg
73 * code will have queried ExternalizeSize to ensure that there is
74 * enough space. During internalization, however, we try to be more
75 * paranoid and check that we do not overrun our buffers.
77 * NB: we must assume that the NaClHandle values passed are the right
78 * type; if not, it is possible to violate invariant properties
79 * required by the various subclasses of NaClDesc.
81 struct NaClDescXferState {
83 * In/out value, used for both serialization and deserialization.
84 * The Externalize method read/write type tags that are part of the
85 * message header as well as data-based capabilities in a
86 * self-describing format.
88 char *next_byte;
89 char *byte_buffer_end;
92 * In/out value. Next handle to work on.
94 NaClHandle *next_handle;
95 NaClHandle *handle_buffer_end;
98 enum NaClDescTypeTag {
99 NACL_DESC_DIR,
100 NACL_DESC_HOST_IO,
101 NACL_DESC_CONN_CAP,
102 NACL_DESC_BOUND_SOCKET,
103 NACL_DESC_CONNECTED_SOCKET,
104 NACL_DESC_SHM,
105 NACL_DESC_MUTEX,
106 NACL_DESC_CONDVAR,
107 NACL_DESC_SEMAPHORE
109 * Add new NaCDesc subclasses here.
111 * NB: when we add new tag types, NaClDescInternalize[] **MUST**
112 * also be updated to add new internalization functions.
115 #define NACL_DESC_TYPE_MAX (NACL_DESC_SEMAPHORE+1)
116 #define NACL_DESC_TYPE_END_TAG (0xff)
118 struct NaClInternalRealHeader {
119 uint32_t xfer_protocol_version;
120 uint32_t descriptor_data_bytes;
123 struct NaClInternalHeader {
124 struct NaClInternalRealHeader h;
126 * We add 0x10 here because pad must have at least one element.
127 * This unfortunately also means that if NaClInternalRealHeader is
128 * already a multiple of 16 in size, we will add in an unnecessary
129 * 16-byte pad. The preprocessor does not have access to sizeof
130 * information, so we cannot just get rid of the pad.
132 char pad[((sizeof(struct NaClInternalRealHeader) + 0x10) & ~0xf)
133 - sizeof(struct NaClInternalRealHeader)];
134 /* total size is a multiple of 16 bytes */
137 #define NACL_HANDLE_TRANSFER_PROTOCOL 0xd3c0de00
138 /* incr from here */
141 * Array of function pointers, indexed by NaClDescTypeTag, any one of
142 * which will extract an externalized representation of the NaClDesc
143 * subclass object from the message, as referenced via
144 * NaClDescXferState, and when successful return the internalized
145 * representation -- a newl created NaClDesc subclass object -- to the
146 * caller via an out parameter. Returns 0 on success, negative errno
147 * value on failure.
149 * NB: we should have atomic failures. The caller is expected to
150 * allocate an array of NaClDesc pointers, and insert into the open
151 * file table of the receiving NaClApp (via the NaClDescEffector
152 * interface) only when all internalizations succeed. Since even the
153 * insertion can fail, the caller must keep track of the descriptor
154 * numbers in case it has to back out and report that the message is
155 * dropped.
157 * Also, when the NaClDesc object is constructed, the NaClHandle
158 * consumed (from the NaClDescXferState) MUST BE replaced with
159 * NACL_INVALID_HANDLE.
161 extern int (*NaClDescInternalize[NACL_DESC_TYPE_MAX])(
162 struct NaClDesc **,
163 struct NaClDescXferState *);
166 * The virtual function table for NaClDesc and its subclasses.
168 * This interface will change when non-blocking I/O and epoll is
169 * added.
172 struct NaClDescVtbl {
173 void (*Dtor)(struct NaClDesc *vself);
174 int (*Map)(struct NaClDesc *vself,
175 struct NaClDescEffector *effp,
176 void *start_addr,
177 size_t len,
178 int prot,
179 int flags,
180 off_t offset);
182 * UnmapUnsafe really unmaps and leaves a hole in the address space.
183 * It is intended for use by Map (through the effector interface) to
184 * clear out memory according to the memory object that is backing
185 * the memory, prior to putting new memory in place. Should not
186 * invoke effp->vtbl->UpdateAddrMap.
188 int (*UnmapUnsafe)(struct NaClDesc *vself,
189 struct NaClDescEffector *effp,
190 void *start_addr,
191 size_t len);
193 * Unmap is the version that removes the mapping but continues to
194 * hold the address space in reserve, preventing it from being used
195 * accidentally by other threads. (Address-space squatting.)
197 * Should invoke effp->vtbl->UpdateAddrMap.
199 int (*Unmap)(struct NaClDesc *vself,
200 struct NaClDescEffector *effp,
201 void *start_addr,
202 size_t len);
203 ssize_t (*Read)(struct NaClDesc *vself,
204 struct NaClDescEffector *effp,
205 void *buf,
206 size_t len);
207 ssize_t (*Write)(struct NaClDesc *vself,
208 struct NaClDescEffector *effp,
209 void const *buf,
210 size_t len);
211 int (*Seek)(struct NaClDesc *vself,
212 struct NaClDescEffector *effp,
213 off_t offset,
214 int whence);
216 * TODO: Need to figure out which requests we support. Also,
217 * request determines arg size and whether it is an input or output arg!
219 int (*Ioctl)(struct NaClDesc *vself,
220 struct NaClDescEffector *effp,
221 int request,
222 void *arg);
223 int (*Fstat)(struct NaClDesc *vself,
224 struct NaClDescEffector *effp,
225 struct nacl_abi_stat *statbuf);
226 int (*Close)(struct NaClDesc *vself,
227 struct NaClDescEffector *effp);
230 * Directory access support. Directories require support for getdents.
232 ssize_t (*Getdents)(struct NaClDesc *vself,
233 struct NaClDescEffector *effp,
234 void *dirp,
235 size_t count);
238 * typeTag is one of the enumeration values from NaClDescTypeTag.
240 * This is not a class variable, since one must access it through an
241 * instance. Having a value in the vtable is not allowed in C++;
242 * instead, we would implement this as a virtual function that
243 * returns the type tag, or RTTI which would typically be done via
244 * examining the vtable pointer.
246 enum NaClDescTypeTag typeTag;
249 * Externalization queries this for how many data bytes and how many
250 * handles are needed to transfer the "this" or "self" descriptor
251 * via IMC. If the descriptor is not transferrable, this should
252 * return -NACL_ABI_EINVAL. Success is indicated by 0, and other
253 * kinds of failure should be the usual negative errno. Should
254 * never have to put the calling thread to sleep or otherwise
255 * manipulate thread or process state.
257 * The nbytes returned do not include any kind of type tag. The
258 * type tag overhead is computed by the MsgSend code, since tagging
259 * format need not be known by the per-descriptor externalization
260 * code.
262 int (*ExternalizeSize)(struct NaClDesc *vself,
263 size_t *nbytes,
264 size_t *nhandles);
266 * Externalize the "this" or "self" descriptor: this will take an
267 * IMC datagram object to which the Nrd will be appended, either as
268 * special control data or as a descriptor/handle to be passed to
269 * the recipient. Should never have to put the calling thread to
270 * sleep or otherwise manipulate thread or process state.
272 int (*Externalize)(struct NaClDesc *vself,
273 struct NaClDescXferState *xfer);
275 * Lock and similar syscalls cannot just indefintely block,
276 * since address space move will require that all other threads are
277 * stopped and in a known
279 int (*Lock)(struct NaClDesc *vself,
280 struct NaClDescEffector *effp);
281 int (*TryLock)(struct NaClDesc *vself,
282 struct NaClDescEffector *effp);
283 int (*Unlock)(struct NaClDesc *vself,
284 struct NaClDescEffector *effp);
285 int (*Wait)(struct NaClDesc *vself,
286 struct NaClDescEffector *effp,
287 struct NaClDesc *mutex);
288 int (*TimedWaitAbs)(struct NaClDesc *vself,
289 struct NaClDescEffector *effp,
290 struct NaClDesc *mutex,
291 struct nacl_abi_timespec *ts);
292 int (*Signal)(struct NaClDesc *vself,
293 struct NaClDescEffector *effp);
294 int (*Broadcast)(struct NaClDesc *vself,
295 struct NaClDescEffector *effp);
297 int (*SendMsg)(struct NaClDesc *vself,
298 struct NaClDescEffector *effp,
299 struct NaClMessageHeader *dgram,
300 int flags);
301 int (*RecvMsg)(struct NaClDesc *vself,
302 struct NaClDescEffector *effp,
303 struct NaClMessageHeader *dgram,
304 int flags);
305 int (*ConnectAddr)(struct NaClDesc *vself,
306 struct NaClDescEffector *effp);
307 int (*AcceptConn)(struct NaClDesc *vself,
308 struct NaClDescEffector *effp);
309 int (*Post)(struct NaClDesc *vself,
310 struct NaClDescEffector *effp);
311 int (*SemWait)(struct NaClDesc *vself,
312 struct NaClDescEffector *effp);
313 int (*GetValue)(struct NaClDesc *vself,
314 struct NaClDescEffector *effp);
316 * Inappropriate methods for the subclass will just return
317 * -NACL_ABI_EINVAL.
321 struct NaClDesc {
322 struct NaClDescVtbl const *vtbl;
323 struct NaClMutex mu;
324 unsigned ref_count;
328 * Placement new style ctor; creates w/ ref_count of 1.
330 * The subclasses' ctor must call this base class ctor during their
331 * contruction.
333 int NaClDescCtor(struct NaClDesc *ndp);
335 /* Typically it is incorrect to call the dtor directly; see NaClDescUnref */
336 void NaClDescDtor(struct NaClDesc *ndp);
338 struct NaClDesc *NaClDescRef(struct NaClDesc *ndp);
340 /* when ref_count reaches zero, will call dtor and free */
341 void NaClDescUnref(struct NaClDesc *ndp);
344 * subclasses
348 * Directory descriptors
350 extern struct NaClDescVtbl const kNaClDescDirDescVtbl;
352 struct NaClDescDirDesc {
353 struct NaClDesc base;
354 struct NaClHostDir *hd;
357 extern int NaClDescDirInternalize(struct NaClDesc **baseptr,
358 struct NaClDescXferState *xfer);
361 * I/O descriptors
363 extern struct NaClDescVtbl const kNaClDescIoDescVtbl;
365 struct NaClDescIoDesc {
366 struct NaClDesc base;
368 * No locks are needed for accessing class members; NaClHostDesc
369 * should ensure thread safety, and uses are read-only.
371 * If we later added state that needs locking, beware lock order.
373 struct NaClHostDesc *hd;
376 extern int NaClDescIoInternalize(struct NaClDesc **baseptr,
377 struct NaClDescXferState *xfer);
379 extern struct NaClDescVtbl const kNaClDescConnCapVtbl;
382 * IMC socket addresses.
384 struct NaClDescConnCap {
385 struct NaClDesc base;
386 struct NaClSocketAddress cap;
389 extern int NaClDescConnCapInternalize(struct NaClDesc **baseptr,
390 struct NaClDescXferState *xfer);
392 extern struct NaClDescVtbl const kNaClDescImcBoundDescVtbl;
395 * IMC bound sockets.
397 struct NaClDescImcBoundDesc {
398 struct NaClDesc base;
399 NaClHandle h;
402 extern int NaClDescImcBoundDescInternalize(struct NaClDesc **baseptr,
403 struct NaClDescXferState *xfer);
405 extern struct NaClDescVtbl const kNaClDescImcDescVtbl;
408 * IMC connected sockets.
410 struct NaClDescImcDesc {
411 struct NaClDesc base;
412 NaClHandle h;
415 extern int NaClDescImcDescInternalize(struct NaClDesc **baseptr,
416 struct NaClDescXferState *xfer);
418 extern struct NaClDescVtbl const kNaClDescImcShmVtbl;
420 struct NaClDescImcShm {
421 struct NaClDesc base;
422 NaClHandle h;
423 off_t size; /* note off_t so struct stat compatible */
426 extern int NaClDescImcShmInternalize(struct NaClDesc **baseptr,
427 struct NaClDescXferState *xfer);
429 extern struct NaClDescVtbl const kNaClDescMutexVtbl;
431 struct NaClDescMutex {
432 struct NaClDesc base;
433 struct NaClIntrMutex mu;
436 extern int NaClDescMutexInternalize(struct NaClDesc **baseptr,
437 struct NaClDescXferState *xfer);
439 extern struct NaClDescVtbl const kNaClDescCondVarVtbl;
441 struct NaClDescCondVar {
442 struct NaClDesc base;
443 struct NaClIntrCondVar cv;
446 extern int NaClDescCondVarInternalize(struct NaClDesc **baseptr,
447 struct NaClDescXferState *xfer);
449 extern struct NaClDescVtbl const kNaClDescSemaphoreVtbl;
451 struct NaClDescSemaphore {
452 struct NaClDesc base;
453 struct NaClSemaphore sem;
456 extern int NaClDescSemaphoreInternalize(struct NaClDesc **baseptr,
457 struct NaClDescXferState *xfer);
459 /* utility routines */
461 struct NaClDescIoDesc *NaClDescIoDescMake(struct NaClHostDesc *nhdp);
463 /* in PLATFORM/nacl_desc.c */
464 void NaClDeallocAddrRange(uintptr_t addr,
465 size_t len);
468 /* default functions for the vtable - return -NACL_ABI_EINVAL */
469 void NaClDescDtorNotImplemented(struct NaClDesc *vself);
471 int NaClDescMapNotImplemented(struct NaClDesc *vself,
472 struct NaClDescEffector *effp,
473 void *start_addr,
474 size_t len,
475 int prot,
476 int flags,
477 off_t offset);
478 int NaClDescUnmapUnsafeNotImplemented(struct NaClDesc *vself,
479 struct NaClDescEffector *effp,
480 void *start_addr,
481 size_t len);
483 int NaClDescUnmapNotImplemented(struct NaClDesc *vself,
484 struct NaClDescEffector *effp,
485 void *start_addr,
486 size_t len);
487 ssize_t NaClDescReadNotImplemented(struct NaClDesc *vself,
488 struct NaClDescEffector *effp,
489 void *buf,
490 size_t len);
491 ssize_t NaClDescWriteNotImplemented(struct NaClDesc *vself,
492 struct NaClDescEffector *effp,
493 void const *buf,
494 size_t len);
495 int NaClDescSeekNotImplemented(struct NaClDesc *vself,
496 struct NaClDescEffector *effp,
497 off_t offset,
498 int whence);
499 int NaClDescIoctlNotImplemented(struct NaClDesc *vself,
500 struct NaClDescEffector *natp,
501 int request,
502 void *arg);
503 int NaClDescFstatNotImplemented(struct NaClDesc *vself,
504 struct NaClDescEffector *effp,
505 struct nacl_abi_stat *statbuf);
506 int NaClDescCloseNotImplemented(struct NaClDesc *vself,
507 struct NaClDescEffector *effp);
509 ssize_t NaClDescGetdentsNotImplemented(struct NaClDesc *vself,
510 struct NaClDescEffector *effp,
511 void *dirp,
512 size_t count);
514 int NaClDescExternalizeSizeNotImplemented(struct NaClDesc *vself,
515 size_t *nbytes,
516 size_t *nhandles);
518 int NaClDescExternalizeNotImplemented(struct NaClDesc *vself,
519 struct NaClDescXferState *xfer);
521 int NaClDescLockNotImplemented(struct NaClDesc *vself,
522 struct NaClDescEffector *effp);
523 int NaClDescTryLockNotImplemented(struct NaClDesc *vself,
524 struct NaClDescEffector *effp);
525 int NaClDescUnlockNotImplemented(struct NaClDesc *vself,
526 struct NaClDescEffector *effp);
527 int NaClDescWaitNotImplemented(struct NaClDesc *vself,
528 struct NaClDescEffector *effp,
529 struct NaClDesc *mutex);
530 int NaClDescTimedWaitAbsNotImplemented(struct NaClDesc *vself,
531 struct NaClDescEffector *effp,
532 struct NaClDesc *mutex,
533 struct nacl_abi_timespec *ts);
534 int NaClDescSignalNotImplemented(struct NaClDesc *vself,
535 struct NaClDescEffector *effp);
536 int NaClDescBroadcastNotImplemented(struct NaClDesc *vself,
537 struct NaClDescEffector *effp);
539 int NaClDescSendMsgNotImplemented(struct NaClDesc *vself,
540 struct NaClDescEffector *effp,
541 struct NaClMessageHeader *dgram,
542 int flags);
543 int NaClDescRecvMsgNotImplemented(struct NaClDesc *vself,
544 struct NaClDescEffector *effp,
545 struct NaClMessageHeader *dgram,
546 int flags);
547 int NaClDescConnectAddrNotImplemented(struct NaClDesc *vself,
548 struct NaClDescEffector *effp);
549 int NaClDescAcceptConnNotImplemented(struct NaClDesc *vself,
550 struct NaClDescEffector *effp);
551 int NaClDescPostNotImplemented(struct NaClDesc *vself,
552 struct NaClDescEffector *effp);
553 int NaClDescSemWaitNotImplemented(struct NaClDesc *vself,
554 struct NaClDescEffector *effp);
555 int NaClDescGetValueNotImplemented(struct NaClDesc *vself,
556 struct NaClDescEffector *effp);
558 EXTERN_C_END
560 #endif /* NATIVE_CLIENT_SERVICE_RUNTIME_NACL_DESC_BASE_H_ */