Chromium Code Reviews| 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__) |