Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: native_client_sdk/src/libraries/nacl_io/kernel_wrap_irt_ext.cc

Issue 608913003: Added support for NaCl IO to use the IRT Extension API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changed assert checks to a macro Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/libraries/nacl_io/kernel_wrap_irt_ext.cc
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_irt_ext.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_irt_ext.cc
new file mode 100644
index 0000000000000000000000000000000000000000..89e8bacaab57afb31997237ea5f2754ceb117f9f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_irt_ext.cc
@@ -0,0 +1,458 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
Sam Clegg 2014/09/30 20:49:03 You're not going to like this but... do you think
David Yen 2014/09/30 21:37:36 Okay, I will do this as separate patches so as to
David Yen 2014/10/01 20:01:44 Done.
+// found in the LICENSE file.
+
+#include <sys/types.h> // Include something that will define __GLIBC__.
+#include "nacl_io/kernel_wrap.h" // IRT_EXT is turned on in this header.
+
+// The entire file is wrapped in this #if. We do this so this .cc file can
+// always be compiled.
+#if defined(__NACL_IO_IRT_EXT__)
+
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "nacl_io/kernel_intercept.h"
+#include "nacl_io/log.h"
+#include "native_client/src/untrusted/irt/irt.h"
+#include "native_client/src/untrusted/irt/irt_dev.h"
+#include "native_client/src/untrusted/irt/irt_extension.h"
+
+#define CHECK_CALL(call) \
+ do { \
+ const bool ret = call; \
+ (void) ret; \
Sam Clegg 2014/09/30 20:49:03 Use __attribute__ unused?
David Yen 2014/09/30 21:37:36 Done.
+ assert(ret); \
+ } while(false)
+
+template<typename T>
+struct nacl_irt_interface {
+ bool initialized;
+ const char* query_string;
+ T interface;
+
+ nacl_irt_interface(const char* query)
+ : initialized(false),
+ query_string(query) {
+ memset(&interface, 0, sizeof(interface));
+ }
+
+ bool Initialized() const {
+ return initialized;
+ }
+
+ bool Initialize() {
+ if (Initialized())
+ return true;
+
+ size_t bytes = nacl_interface_query(query_string,
+ &interface,
+ sizeof(interface));
+ initialized = (bytes == sizeof(interface));
+ return initialized;
+ }
+
+ bool IRTExtSupply(const T& new_interface) const {
+ size_t bytes = nacl_interface_ext_supply(query_string,
+ &new_interface,
+ sizeof(new_interface));
+ return (bytes == sizeof(interface));
+ }
+
+ bool RevertIRTExtSupply(bool force_revert = false) {
+ if (!Initialize() && !force_revert)
+ return false;
+
+ size_t bytes = nacl_interface_ext_supply(query_string,
+ &interface,
+ sizeof(interface));
+ return (bytes == sizeof(interface));
+ }
+};
+
+// IRT interfaces as declared in irt.h.
+static nacl_irt_interface<nacl_irt_basic> s_irt_basic(NACL_IRT_BASIC_v0_1);
+static nacl_irt_interface<nacl_irt_fdio> s_irt_fdio(NACL_IRT_FDIO_v0_1);
+static nacl_irt_interface<nacl_irt_memory> s_irt_memory(NACL_IRT_MEMORY_v0_3);
+static nacl_irt_interface<nacl_irt_resource_open> s_irt_resource_open(
+ NACL_IRT_RESOURCE_OPEN_v0_1);
+
+// IRT Dev interfaces as declared in irt_dev.h.
+static nacl_irt_interface<nacl_irt_dev_fdio> s_irt_dev_fdio(
+ NACL_IRT_DEV_FDIO_v0_3);
+static nacl_irt_interface<nacl_irt_dev_filename> s_irt_dev_filename(
+ NACL_IRT_DEV_FILENAME_v0_3);
+
+static bool s_wrapped = false;
+
+// Functions for the nacl_irt_dev_fdio interface.
+static int ext_close(int fd) {
+ ERRNO_RTN(ki_close(fd));
+}
+
+static int ext_dup(int fd, int *newfd) {
+ *newfd = ki_dup(fd);
+ ERRNO_RTN(*newfd);
+}
+
+static int ext_dup2(int fd, int newfd) {
+ newfd = ki_dup2(fd, newfd);
+ ERRNO_RTN(newfd);
+}
+
+static int ext_read(int fd, void *buf, size_t count, size_t *nread) {
+ ssize_t signed_nread = ki_read(fd, buf, count);
+ *nread = static_cast<size_t>(signed_nread);
+ ERRNO_RTN(signed_nread);
+}
+
+static int ext_write(int fd, const void *buf, size_t count, size_t *nwrote) {
+ ssize_t signed_nwrote = ki_write(fd, buf, count);
+ *nwrote = static_cast<size_t>(signed_nwrote);
+ ERRNO_RTN(signed_nwrote);
+}
+
+static int ext_seek(int fd, nacl_irt_off_t offset, int whence,
+ nacl_irt_off_t *new_offset) {
+ *new_offset = ki_lseek(fd, offset, whence);
+ ERRNO_RTN(*new_offset);
+}
+
+static int ext_fstat(int fd, struct stat *buf) {
+ ERRNO_RTN(ki_fstat(fd, buf));
+}
+
+static int ext_getdents(int fd, struct dirent *ents, size_t count,
+ size_t *nread) {
+ int rtn = ki_getdents(fd, ents, count);
+ RTN_ERRNO_IF(rtn < 0);
+ *nread = rtn;
+ return 0;
+}
+
+// Functions for the nacl_irt_memory interface.
+static int ext_mmap(void **addr, size_t len, int prot, int flags, int fd,
+ nacl_irt_off_t off) {
+ if (flags & MAP_ANONYMOUS)
+ return s_irt_memory.interface.mmap(addr, len, prot, flags, fd, off);
+
+ *addr = ki_mmap(*addr, len, prot, flags, fd, off);
+ RTN_ERRNO_IF(*addr == (void*)-1);
+ return 0;
+}
+
+// Extra functions for the nacl_irt_fdio interface.
+static int ext_fchdir(int fd) {
+ ERRNO_RTN(ki_fchdir(fd));
+}
+
+static int ext_fchmod(int fd, mode_t mode) {
+ ERRNO_RTN(ki_fchmod(fd, mode));
+}
+
+static int ext_fsync(int fd) {
+ ERRNO_RTN(ki_fsync(fd));
+}
+
+static int ext_fdatasync(int fd) {
+ ERRNO_RTN(ki_fdatasync(fd));
+}
+
+static int ext_ftruncate(int fd, nacl_irt_off_t length) {
+ ERRNO_RTN(ki_ftruncate(fd, length));
+}
+
+static int ext_isatty(int fd, int *result) {
+ *result = ki_isatty(fd);
+ RTN_ERRNO_IF(*result == 0);
+ return 0;
+}
+
+static int ext_munmap(void *addr, size_t length) {
+ // Always let the real munmap run on the address range. It is not an error if
+ // there are no mapped pages in that range.
+ ki_munmap(addr, length);
+ return s_irt_memory.interface.munmap(addr, length);
+}
+
+static int ext_mprotect(void *addr, size_t len, int prot) {
+ return ENOSYS;
+}
+
+// Functions for the nacl_irt_dev_filename interface.
+static int ext_open(const char *pathname, int oflag, mode_t cmode, int *newfd) {
+ *newfd = ki_open(pathname, oflag, cmode);
+ ERRNO_RTN(*newfd);
+}
+
+static int ext_stat(const char *pathname, struct stat *buf) {
+ ERRNO_RTN(ki_stat(pathname, buf));
+}
+
+static int ext_mkdir(const char *pathname, mode_t mode) {
+ ERRNO_RTN(ki_mkdir(pathname, mode));
+}
+
+static int ext_rmdir(const char *pathname) {
+ ERRNO_RTN(ki_rmdir(pathname));
+}
+
+static int ext_chdir(const char *pathname) {
+ ERRNO_RTN(ki_chdir(pathname));
+}
+
+static int ext_getcwd(char *pathname, size_t len) {
+ char* rtn = ki_getcwd(pathname, len);
+ RTN_ERRNO_IF(NULL == rtn);
+ return 0;
+}
+
+static int ext_unlink(const char *pathname) {
+ ERRNO_RTN(ki_unlink(pathname));
+}
+
+static int ext_truncate(const char *pathname, nacl_irt_off_t length) {
+ ERRNO_RTN(ki_truncate(pathname, length));
+}
+
+static int ext_lstat(const char *pathname, struct stat *buf) {
+ ERRNO_RTN(ki_lstat(pathname, buf));
+}
+
+static int ext_link(const char *pathname, const char *newpath) {
+ ERRNO_RTN(ki_link(pathname, newpath));
+}
+
+static int ext_rename(const char *pathname, const char *newpath) {
+ ERRNO_RTN(ki_rename(pathname, newpath));
+}
+
+static int ext_symlink(const char *pathname, const char *newpath) {
+ ERRNO_RTN(ki_symlink(pathname, newpath));
+}
+
+static int ext_chmod(const char *pathname, mode_t mode) {
+ ERRNO_RTN(ki_chmod(pathname, mode));
+}
+
+static int ext_access(const char *pathname, int amode) {
+ ERRNO_RTN(ki_access(pathname, amode));
+}
+
+static int ext_readlink(const char *pathname, char *buf, size_t count,
+ size_t *nread) {
+ int rtn = ki_readlink(pathname, buf, count);
+ RTN_ERRNO_IF(rtn < 0);
+ *nread = rtn;
+ return 0;
+}
+
+static int ext_utimes(const char *pathname, const struct timeval *times) {
+ ERRNO_RTN(ki_utimes(pathname, times));
+}
+
+// Functions declared inside of kernel_wrap_real.h.
+EXTERN_C_BEGIN
+
+int _real_close(int fd) {
+ if (!s_irt_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_fdio.interface.close(fd);
+}
+
+void _real_exit(int status) {
+ CHECK_CALL(s_irt_basic.Initialize());
+ return s_irt_basic.interface.exit(status);
+}
+
+int _real_fstat(int fd, struct stat* buf) {
+ if (!s_irt_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_fdio.interface.fstat(fd, buf);
+}
+
+int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t* nread) {
+ if (!s_irt_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_fdio.interface.getdents(fd, static_cast<dirent*>(nacl_buf),
+ nacl_count, nread);
+}
+
+int _real_isatty(int fd, int* result) {
+ if (!s_irt_dev_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_dev_fdio.interface.isatty(fd, result);
+}
+
+int _real_lseek(int fd, int64_t offset, int whence, int64_t* new_offset) {
+ if (!s_irt_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_fdio.interface.seek(fd, offset, whence, new_offset);
+}
+
+int _real_mkdir(const char* pathname, mode_t mode) {
+ if (!s_irt_dev_filename.Initialize())
+ return ENOSYS;
+ return s_irt_dev_filename.interface.mkdir(pathname, mode);
+}
+
+int _real_mmap(void** addr,
+ size_t length,
+ int prot,
+ int flags,
+ int fd,
+ int64_t offset) {
+ if (!s_irt_memory.Initialize())
+ return ENOSYS;
+ return s_irt_memory.interface.mmap(addr, length, prot, flags, fd, offset);
+}
+
+int _real_munmap(void* addr, size_t length) {
+ if (!s_irt_memory.Initialize())
+ return ENOSYS;
+ return s_irt_memory.interface.munmap(addr, length);
+}
+
+int _real_open(const char* pathname, int oflag, mode_t mode, int* newfd) {
+ if (!s_irt_dev_filename.Initialize())
+ return ENOSYS;
+ return s_irt_dev_filename.interface.open(pathname, oflag, mode, newfd);
+}
+
+int _real_open_resource(const char* file, int* fd) {
+ if (!s_irt_resource_open.Initialize())
+ return ENOSYS;
+ return s_irt_resource_open.interface.open_resource(file, fd);
+}
+
+int _real_read(int fd, void* buf, size_t count, size_t* nread) {
+ if (!s_irt_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_fdio.interface.read(fd, buf, count, nread);
+}
+
+int _real_rmdir(const char* pathname) {
+ if (!s_irt_dev_filename.Initialize())
+ return ENOSYS;
+ return s_irt_dev_filename.interface.rmdir(pathname);
+}
+
+int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
+ if (!s_irt_fdio.Initialize())
+ return ENOSYS;
+ return s_irt_fdio.interface.write(fd, buf, count, nwrote);
+}
+
+int _real_getcwd(char* pathname, size_t len) {
+ if (!s_irt_dev_filename.Initialize())
+ return ENOSYS;
+ return s_irt_dev_filename.interface.getcwd(pathname, len);
+}
+
+// Kernel Wrap init/uninit functions declared in kernel_wrap.h.
+void kernel_wrap_init() {
+ if (!s_wrapped) {
+ LOG_TRACE("kernel_wrap_init");
+
+ // Register interfaces as listed in irt.h.
+
+ // Register nacl_irt_basic interface.
+ CHECK_CALL(s_irt_basic.Initialize());
+ struct nacl_irt_basic basic_calls = {
+ ki_exit,
+ s_irt_basic.interface.gettod,
+ s_irt_basic.interface.clock,
+ s_irt_basic.interface.nanosleep,
+ s_irt_basic.interface.sched_yield,
+ s_irt_basic.interface.sysconf,
+ };
+ CHECK_CALL(s_irt_basic.IRTExtSupply(basic_calls));
+
+ // Register nacl_irt_fdio interface.
+ struct nacl_irt_fdio fdio = {
+ ext_close,
+ ext_dup,
+ ext_dup2,
+ ext_read,
+ ext_write,
+ ext_seek,
+ ext_fstat,
+ ext_getdents,
+ };
+ CHECK_CALL(s_irt_fdio.IRTExtSupply(fdio));
+
+ // Register nacl_irt_memory interface.
+ struct nacl_irt_memory mem = {
+ ext_mmap,
+ ext_munmap,
+ ext_mprotect,
+ };
+ CHECK_CALL(s_irt_memory.IRTExtSupply(mem));
+
+ // Register interfaces as listed in irt_dev.h.
+
+ // Register nacl_irt_dev_fdio interface.
+ struct nacl_irt_dev_fdio dev_fdio = {
+ ext_close,
+ ext_dup,
+ ext_dup2,
+ ext_read,
+ ext_write,
+ ext_seek,
+ ext_fstat,
+ ext_getdents,
+ ext_fchdir,
+ ext_fchmod,
+ ext_fsync,
+ ext_fdatasync,
+ ext_ftruncate,
+ ext_isatty,
+ };
+ CHECK_CALL(s_irt_dev_fdio.IRTExtSupply(dev_fdio));
+
+ // Register nacl_irt_dev_filename interface.
+ struct nacl_irt_dev_filename dev_filename = {
+ ext_open,
+ ext_stat,
+ ext_mkdir,
+ ext_rmdir,
+ ext_chdir,
+ ext_getcwd,
+ ext_unlink,
+ ext_truncate,
+ ext_lstat,
+ ext_link,
+ ext_rename,
+ ext_symlink,
+ ext_chmod,
+ ext_access,
+ ext_readlink,
+ ext_utimes,
+ };
+ CHECK_CALL(s_irt_dev_filename.IRTExtSupply(dev_filename));
+
+ s_wrapped = true;
+ }
+}
+
+void kernel_wrap_uninit() {
+ if (s_wrapped) {
+ LOG_TRACE("kernel_wrap_uninit");
+
+ // Register original IRT interfaces in irt.h.
+ CHECK_CALL(s_irt_basic.RevertIRTExtSupply());
+ CHECK_CALL(s_irt_fdio.RevertIRTExtSupply());
+ CHECK_CALL(s_irt_memory.RevertIRTExtSupply());
+
+ // Register optional original IRT dev interfaces in irt_dev.h.
+ s_irt_dev_fdio.RevertIRTExtSupply(true);
+ s_irt_dev_filename.RevertIRTExtSupply(true);
+
+ s_wrapped = false;
+ }
+}
+
+EXTERN_C_END
+
+#endif // defined(__NACL_IO_IRT_EXT__)

Powered by Google App Engine
This is Rietveld 408576698