<|start_filename|>tests/functional/channels/seqwo/seqwo.c<|end_filename|>
/*
 * random write only channel test. tests statistics goes to stdout channel.
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define SEQWO "/dev/seqwo"

int main(int argc, char **argv)
{
  char buf[BIG_ENOUGH];

  /* correct requests */
  FPRINTF(STDERR, "TEST SEQUENTIAL WRITE ONLY CHANNEL\n");
  FPRINTF(STDERR, "channel size = %ld\n", MANIFEST->channels[OPEN(SEQWO)].size);
  ZTEST(MANIFEST->channels[OPEN(SEQWO)].size == 0);
  ZTEST(PWRITE(SEQWO, buf, 0, 0) == 0);
  ZTEST(PWRITE(SEQWO, buf, 0, 1) == 0);
  ZTEST(PWRITE(SEQWO, buf, 1, 0) == 1);
  ZTEST(PWRITE(SEQWO, buf, 1,
      MANIFEST->channels[OPEN(SEQWO)].limits[PutSizeLimit] - 1) == 1);
  ZTEST(PWRITE(SEQWO, buf, 0, -1) == 0);

  /* incorrect requests: NULL buffer */
  ZTEST(PWRITE(SEQWO, NULL, 0, 0) < 0);
  ZTEST(PWRITE(SEQWO, NULL, 0, 1) < 0);
  ZTEST(PWRITE(SEQWO, NULL, 1, 0) < 0);
  ZTEST(PWRITE(SEQWO, NULL, 1,
      MANIFEST->channels[OPEN(SEQWO)].limits[PutSizeLimit] - 1) < 0);
  ZTEST(PWRITE(SEQWO, NULL, 0, -1) < 0);

  /* incorrect requests: size */
  ZTEST(PWRITE(SEQWO, buf, -1, 0) < 0);

  /* incorrect requests: offset */
  ZTEST(PWRITE(SEQWO, buf, 0, -1) == 0);
  ZTEST(PWRITE(SEQWO, buf, 1, -1) == 1);
  ZTEST(PWRITE(SEQWO, buf, 1,
      MANIFEST->channels[OPEN(SEQWO)].limits[PutSizeLimit]) == 1);

  /* correct requests: reading of 0 bytes attempt */
  ZTEST(PREAD(SEQWO, buf, 0, 0) == 0);

  /* incorrect requests: read attempt */
  ZTEST(PREAD(SEQWO, buf, 1, 0) < 0);
  ZTEST(PREAD(SEQWO, buf, 1,
      MANIFEST->channels[OPEN(SEQWO)].limits[PutSizeLimit]) < 0);

  /* incorrect requests: exhausted */
  ZTEST(PWRITE(SEQWO, buf, 30, 0) == 28);
  ZTEST(PWRITE(SEQWO, buf, 10, 0) < 0);

  /* count errors and exit with it */
  ZREPORT;
  return 0;
}


<|start_filename|>tests/security/rdtsc/rdtsc.c<|end_filename|>
/*
 * rdtsc test
 */
#include "api/zvm.h"

void _start()
{
  asm("rdtsc");
  zvm_exit(0);
}


<|start_filename|>src/main/config.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Simple/secure ELF loader (NaCl SEL).
 *
 * NOTE: This header is ALSO included by assembler files and hence
 *       must not include any C code
 */
#ifndef CONFIG_H_
#define CONFIG_H_

/* maximum number of elf program headers allowed. */
#define NACL_MAX_PROGRAM_HEADERS 128

/*
 * macros to provide uniform access to identifiers from assembly due
 * to different C -> asm name mangling conventions and other platform-specific
 * requirements
 */
#define IDENTIFIER(n)  n
#define HIDDEN(n)  .hidden IDENTIFIER(n)

/*
 * this value must be consistent with NaCl compiler flags
 * -falign-functions -falign-labels -and nacl-align.
 */
#define NACL_BLOCK_SHIFT 5
#define NACL_INSTR_BLOCK_SIZE    (1 << NACL_BLOCK_SHIFT)

/* this must be a multiple of the system page size */
#define NACL_PAGESHIFT           12
#define NACL_PAGESIZE            (1U << NACL_PAGESHIFT)

#define NACL_MAP_PAGESHIFT       16
#define NACL_MAP_PAGESIZE        (1U << NACL_MAP_PAGESHIFT)

#if NACL_MAP_PAGESHIFT < NACL_PAGESHIFT
# error "NACL_MAP_PAGESHIFT smaller than NACL_PAGESHIFT"
#endif

/*
 * Macro for the start address of the trampolines
 * The first 64KB (16 pages) are inaccessible.  On x86, this is to prevent
 * addr16/data16 attacks.
 */
#define NACL_SYSCALL_START_ADDR  (16 << NACL_PAGESHIFT)

/*
 * Syscall trampoline code have a block size that may differ from the
 * alignment restrictions of the executable.  The ELF executable's
 * alignment restriction (16 or 32) defines what are potential entry
 * points, so the trampoline region must still respect that.  We
 * prefill the trampoline region with HLT, so non-syscall entry points
 * will not cause problems as long as our trampoline instruction
 * sequence never grows beyond 16 bytes, so the "odd" potential entry
 * points for a 16-byte aligned ELF will not be able to jump into the
 * middle of the trampoline code.
 */
#define NACL_SYSCALL_BLOCK_SHIFT 5
#define NACL_SYSCALL_BLOCK_SIZE  (1 << NACL_SYSCALL_BLOCK_SHIFT)

/*
 * the extra space for the trampoline syscall code and the thread
 * contexts must be a multiple of the page size.
 *
 * The address space begins with a 64KB region that is inaccessible to
 * handle NULL pointers and also to reinforce protection agasint abuse of
 * addr16/data16 prefixes.
 * NACL_TRAMPOLINE_START gives the address of the first trampoline.
 * NACL_TRAMPOLINE_END gives the address of the first byte after the
 * trampolines.
 */
#define NACL_NULL_REGION_SHIFT   16
#define NACL_TRAMPOLINE_START    (1 << NACL_NULL_REGION_SHIFT)
#define NACL_TRAMPOLINE_SHIFT    16
#define NACL_TRAMPOLINE_SIZE     (1 << NACL_TRAMPOLINE_SHIFT)
#define NACL_TRAMPOLINE_END      (NACL_TRAMPOLINE_START + NACL_TRAMPOLINE_SIZE)

/*
 * Extra required space at the end of static text (and dynamic text,
 * if any). The intent is to stop a thread from "walking off the end"
 * of a text region into another.  Four bytes suffices for all
 * currently supported architectures (halt is one byte on x86-32 and
 * x86-64, and 4 bytes on ARM), but for x86 we want to provide
 * paranoia-in-depth: if the NX bit (x86-64, arm) or the %cs segment
 * protection (x86-32) fails on weird borderline cases and the
 * validator also fails to detect a weird instruction sequence, we may
 * have the following situation: a partial multi-byte instruction is
 * placed on the end of the last page, and by "absorbing" the trailing
 * HALT instructions (esp if there are none) as immediate data (or
 * something similar), cause the PC to go outside of the untrusted
 * code space, possibly into data memory.  By requiring 32 bytes of
 * space to fill with HALT instructions, we (attempt to) ensure that
 * such op-code absorption cannot happen, and at least one of these
 * HALTs will cause the untrusted thread to abort, and take down the
 * whole NaCl app.
 */
#define NACL_HALT_SLED_SIZE      32

#define NACL_USERRET_FIX         (0x8)
#define NACL_SYSARGS_FIX         (-0x18)
#define NACL_SYSCALLRET_FIX      (0x10)
/*
 * System V Application Binary Interface, AMD64 Architecture Processor
 * Supplement, at http://www.x86-64.org/documentation/abi.pdf, section
 * 3.2.2 discusses stack alignment.
 * d'b: since zerovm gave up the command line and environment support
 * the user stack has now constant content 56 bytes long
 */
#define STACK_USER_DATA_SIZE     56

/* d'b: macro definitions for the user space allocation */
#define FOURGIG     (((size_t) 1) << 32)
#define GUARDSIZE   (10 * FOURGIG)
#define R15_CONST   ((void*)0x440000000000)
#define RELATIVE_MMAP (MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE)
#define ABSOLUTE_MMAP (RELATIVE_MMAP | MAP_FIXED)
#define START_OF_USER_SPACE ((uintptr_t)R15_CONST)
#define END_OF_USER_SPACE (START_OF_USER_SPACE + FOURGIG + 2 * GUARDSIZE)
#define LEAST_USER_HEAP_SIZE (8*1024*1024)

#endif  /* CONFIG_H_ */


<|start_filename|>tests/functional/channels/charo/charo.c<|end_filename|>
/*
 * sequential read only channel test. tests statistics goes to stdout channel
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define CHARO "/dev/charo"

int main(int argc, char **argv)
{
  char buf[BIG_ENOUGH];

  /* correct requests */
  FPRINTF(STDERR, "TEST SEQUENTIAL (CHARACTER DEVICE) READ ONLY CHANNEL\n");
  FPRINTF(STDERR, "channel size = %d\n", MANIFEST->channels[OPEN(CHARO)].size);
  ZTEST(MANIFEST->channels[OPEN(CHARO)].size == 0);
  ZTEST(PREAD(CHARO, buf, 0, 0) == 0);
  ZTEST(PREAD(CHARO, buf, 0, 1) == 0);
  ZTEST(PREAD(CHARO, buf, 1, 0) == 1);
  ZTEST(PREAD(CHARO, buf, 1, MANIFEST->channels[OPEN(CHARO)].size - 1) == 1);
  ZTEST(PREAD(CHARO, buf, 0, -1) == 0);

  /* incorrect handle */
  ZTEST(zvm_pread(-1, buf, 1, 0) < 0);
  ZTEST(zvm_pread(0xffff, buf, 1, 0) < 0);
  ZTEST(zvm_pread(MANIFEST->channels_count, buf, 1, 0) < 0);

  /* incorrect requests: NULL buffer */
  ZTEST(PREAD(CHARO, NULL, 0, 0) < 0);
  ZTEST(PREAD(CHARO, NULL, 0, 1) < 0);
  ZTEST(PREAD(CHARO, NULL, 1, 0) < 0);
  ZTEST(PREAD(CHARO, NULL, 1, MANIFEST->channels[OPEN(CHARO)].size - 1) < 0);
  ZTEST(PREAD(CHARO, NULL, 0, -1) < 0);

  /* incorrect requests: size */
  ZTEST(PREAD(CHARO, buf, -1, 0) < 0);

  /* incorrect requests: offset */
  ZTEST(PREAD(CHARO, buf, 0, -1) == 0);
  ZTEST(PREAD(CHARO, buf, 1, -1) == 1);
  ZTEST(PREAD(CHARO, buf, 1, MANIFEST->channels[OPEN(CHARO)].size) == 1);

  /* correct requests: writing of 0 bytes attempt */
  ZTEST(PWRITE(CHARO, buf, 0, 0) == 0);

  /* incorrect requests: write attempt */
  ZTEST(PWRITE(CHARO, buf, 1, 0) < 0);
  ZTEST(PWRITE(CHARO, buf, 1, MANIFEST->channels[OPEN(CHARO)].size) < 0);
  ZTEST(PWRITE(CHARO, buf, 1, MANIFEST->channels[OPEN(CHARO)].size - 1) < 0);

  /* incorrect requests: exhausted */
  ZTEST(PREAD(CHARO, buf, 30, 0) == 28);
  ZTEST(PWRITE(STDOUT, buf, 28, 0) == 28);
  ZTEST(PREAD(CHARO, buf, 10, 0) < 0);

  /* count errors and exit with it */
  ZREPORT;
  return 0;
}


<|start_filename|>src/channels/prefetch.h<|end_filename|>
/*
 * preallocate network channel
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PREFETCH_H_
#define PREFETCH_H_

#include "src/channels/channel.h"
#include "src/main/manifest.h"

/* prepare network context */
void NetCtor(const struct Manifest *manifest);

/* deallocate network context */
void NetDtor(struct Manifest *manifest);

/* construct network channel and connect/bind it to specified address */
void PrefetchChannelCtor(struct ChannelDesc *channel, int n);

/*
 * finalize and deallocate network channel resources
 * TODO(d'b): rewrite the code after zmq_term will be fixed
 */
void PrefetchChannelDtor(struct ChannelDesc *channel, int n);

/* return already available data of the channel */
char *MessageData(struct ChannelDesc *channel);

/* receive a new message and update channel with it */
void FetchMessage(struct ChannelDesc *channel, int n);

/*
 * skip obsolete messages/bytes until the source will be in sync with
 * the channel position. works only for channels with sequential read
 */
void SyncSource(struct ChannelDesc *channel, int n);

/* deallocate channel message */
void FreeMessage(struct ChannelDesc *channel);

/*
 * send the data to the network channel
 * return number of sent bytes or negative error code
 */
int32_t SendData(struct ChannelDesc *channel, int n, const char *buf, int32_t count);

#endif /* PREFETCH_H_ */


<|start_filename|>src/loader/elf.h<|end_filename|>
/*
 * Copyright 2008, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* @file
 *
 * Minimal ELF header declaration / constants.  Only Elf values are
 * handled, and constants are defined only for fields that are actualy
 * used.  (Unused constants for used fields are include only for
 * "completeness", though of course in many cases there are more
 * values in use, e.g., the EM_* values for e_machine.)
 *
 * (Re)Created from the ELF specification at
 * http://x86.ddj.com/ftp/manuals/tools/elf.pdf which is referenced
 * from wikipedia article
 * http://en.wikipedia.org/wki/Executable_and_Linkable_Format
 */

#ifndef ELF_H_
#define ELF_H_ 1

#include <inttypes.h>

#define EI_NIDENT     16 /* fwd, see rest of EI_* below */
#define ET_NONE       0  /* no file type */
#define ET_REL        1  /* relocatable file */
#define ET_EXEC       2  /* executable file */
#define ET_DYN        3  /* shared object file */
#define ET_CORE       4  /* core file */

/* all platforms (but x86_64) removed */
#define EM_X86_64     62 /* x86-64 */
#define EM_EXPECTED_BY_NACL EM_X86_64

#define EV_NONE       0  /* invalid version */
#define EV_CURRENT    1  /* current version */
#define EI_MAG0       0  /* file identification */
#define EI_MAG1       1  /* file identification */
#define EI_MAG2       2  /* file identification */
#define EI_MAG3       3  /* file identification */
#define EI_CLASS      4  /* file class */
#define EI_DATA       5  /* data encoding */
#define EI_VERSION    6  /* file version */

/*
 * ELFMAG and SELFMAG are names/values from linux elf.h, for code usage
 * compatibility.
 */
#define ELFMAG        "\177ELF"
#define SELFMAG       4

/* EI_CLASS values */
#define ELFCLASSNONE  0
#define ELFCLASS32    1
#define ELFCLASS64    2

/* EI_DATA values */
#define ELFDATANONE   0
#define ELFDATA2LSB   1
#define ELFDATA2MSB   2

#define PT_NULL       0           /* Unused entry */
#define PT_LOAD       1           /* Loadable segment */
#define PT_DYNAMIC    2           /* Dynamic linking tables */
#define PT_INTERP     3           /* Program interpreter path name */
#define PT_NOTE       4           /* Note section */
#define PT_SHLIB      5           /* Reserved */
#define PT_PHDR       6           /* Program header table */
#define PT_LOOS       0x60000000  /* Environment-specific low */
#define PT_HIOS       0x6fffffff  /* Environment-specific high */
#define PT_LOPROC     0x70000000  /* Processor-specific low */
#define PT_HIPROC     0x7fffffff  /* Processor-specific high */
/*
 * These are from linux elf.h, for code usage
 * compatibility.
 */
#define PT_TLS        7
#define PT_GNU_STACK  0x6474e551
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define PT_GNU_RELRO  0x6474e552   /* Read-only after relocation */

#define PF_X          1
#define PF_W          2
#define PF_R          4

#define SHF_WRITE     0x1        /* Has writable data */
#define SHF_ALLOC     0x2        /* Allocated in memory image of program */
#define SHF_EXECINSTR 0x4        /* Contains executable instructions */
#define SHF_MASKOS    0x0f000000 /* Environment-specific use */
#define SHF_MASKPROC  0xf0000000 /* Processor-specific use */

/* Define 64-bit specific types */
typedef uint64_t  Elf64_Addr;    /* alignment 8 */
typedef uint64_t  Elf64_Off;     /* alignment 8 */
typedef uint16_t  Elf64_Half;    /* alignment 2 */
typedef uint32_t  Elf64_Word;    /* alignment 4 */
typedef int32_t   Elf64_Sword;   /* alignment 4 */
typedef uint64_t  Elf64_Xword;   /* alignment 8 */
typedef int64_t   Elf64_Sxword;  /* alignment 8 */
/* unsigned char, size 1, alignment 1 */

/* Define the structure of the file header for 64 bits. */
typedef struct {
  unsigned char e_ident[EI_NIDENT];
  Elf64_Half    e_type;
  Elf64_Half    e_machine;
  Elf64_Word    e_version;
  Elf64_Addr    e_entry;
  Elf64_Off     e_phoff;
  Elf64_Off     e_shoff;
  Elf64_Word    e_flags;
  Elf64_Half    e_ehsize;
  Elf64_Half    e_phentsize;
  Elf64_Half    e_phnum;
  Elf64_Half    e_shentsize;
  Elf64_Half    e_shnum;
  Elf64_Half    e_shstrndx;
} Elf64_Ehdr;

/* Define the structure of a program header table for 64-bits. */
typedef struct {
  Elf64_Word    p_type;
  Elf64_Word    p_flags;
  Elf64_Off     p_offset;
  Elf64_Addr    p_vaddr;
  Elf64_Addr    p_paddr;
  Elf64_Xword   p_filesz;
  Elf64_Xword   p_memsz;
  Elf64_Xword   p_align;
} Elf64_Phdr;

/* Define 64-bit section headers. */
typedef struct {
  Elf64_Word    sh_name;
  Elf64_Word    sh_type;
  Elf64_Xword   sh_flags;
  Elf64_Addr    sh_addr;
  Elf64_Off     sh_offset;
  Elf64_Xword   sh_size;
  Elf64_Word    sh_link;
  Elf64_Word    sh_info;
  Elf64_Xword   sh_addralign;
  Elf64_Xword   sh_entsize;
} Elf64_Shdr;

/* Define sub architecture neutral types */
typedef Elf64_Addr   Elf_Addr;
typedef Elf64_Off    Elf_Off;
typedef Elf64_Half   Elf_Half;
typedef Elf64_Word   Elf_Word;
typedef Elf64_Sword  Elf_Sword;
typedef Elf64_Xword  Elf_Xword;
typedef Elf64_Sxword Elf_Sxword;

/* Define a neutral form of the file header. */
typedef Elf64_Ehdr Elf_Ehdr;

/* Define a neutral form of a program header. */
typedef Elf64_Phdr Elf_Phdr;

#endif /* ELF_H_ */


<|start_filename|>tests/functional/demo/noise/noise.c<|end_filename|>
/*
 * generate pseudorandom numbers and write it to /dev/stdout
 * note: will generate until timeout or channel limit reached
 */
#include "include/zvmlib.h"

/* A version of Whittle's implementation */
static inline int random(void)
{
  static int seed = 1; /* must not be 0 */
  unsigned hi = 16807 * (seed >> 16);
  unsigned lo = 16807 * (seed & 0xFFFF);

  lo += (hi >> 15) + ((hi & 0x7FFF) << 16);
  return seed = lo > 2147483647 ? lo - 2147483647 : lo;
}

/* populate "buffer" with "size" of random bytes */
static inline void set_random(char *buffer, int size)
{
  while(size)
    buffer[--size] = (char)random();
}

void _start()
{
  char buffer[BIG_ENOUGH];
  int result = 0;

  do {
    set_random(buffer, sizeof buffer);
    result = zvm_pwrite(1, buffer, sizeof buffer, 0);
  } while(result > 0);

  zvm_exit(result);
}


<|start_filename|>tests/functional/signal/signal.c<|end_filename|>
/*
 * invokes the signal specified by the 1st parameter of the command line
 * supported signals: 8, 11, 14, 25
 * todo(d'b): add signals
 * update: it is possible to invoke almost any signal from makefile via pkill.
 *         it would be better to initiate signal from the user code, but zerovm
 *         can be also tested from outside
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define DEFAULT_SIGNAL 11
#define SIGNALS_NUMBER 64
#define BIGFILE "quota.data"

void signal_na()
{
  FPRINTF(STDERR, "not supported signal\n");
}

/* Floating point exception */
void signal_8()
{
  int i = 0;
  FPRINTF(STDERR, "invocation of signal #8\n");
  FPRINTF(STDERR, "falling.. %d\n", 1/i);
}

/* Invalid memory reference */
void signal_11()
{
  FPRINTF(STDERR, "invocation of signal #11\n");
  FPRINTF(STDERR, "falling.. %d\n", *(char*)NULL);
}

/* CPU time limit exceeded */
void signal_14()
{
  FPRINTF(STDERR, "invocation of signal #14\n");
  for(;;);
}

/* disk i/o limit exceeded */
#define MEGABYTE 0x100000
void signal_25()
{
  char buf[MEGABYTE];
  FPRINTF(STDERR, "invocation of signal #25\n");

  for(;;)
    WRITE(BIGFILE, buf, MEGABYTE);
}

/* initialize array of pointers to signal raisers */
void signals_ctor(void (*signals[])())
{
  int i;

  for(i = 0; i < SIGNALS_NUMBER; ++i)
    signals[i] = signal_na;

  signals[8] = signal_8;
  signals[11] = signal_11;
  signals[14] = signal_14;
  signals[25] = signal_25;
}

int main(int argc, char **argv, char **envp)
{
  void (*signals[SIGNALS_NUMBER])();
  uint32_t signum = DEFAULT_SIGNAL;

  /* constructor of signal raisers */
  if(argc == 2)
    signum = STRTOL(argv[1], NULL, 10);
  signals_ctor(signals);
  FPRINTF(STDERR, "signal #%u will be used\n", signum);

  /* provoke the signal */
  if(signum < SIGNALS_NUMBER)
    signals[signum]();

  /* not reached if the signal handler invoked */
  FPRINTF(STDERR, "FAILED on signal #%u\n", signum);
  return ERRCOUNT;
}


<|start_filename|>tests/functional/demo/sort/sort_uint_proper_with_args.c<|end_filename|>
/*
 * program will sort given input file and put sorted elements
 * to the specified output file. no checks will perform
 * usage: sorter <input file name> <output file name>
 *
 * update: usage has been changed. all parameters must be passed via manifest
 *
 * note: input must contain (power of 2) 32-bit unsigned integers
 */
#define _STDLIB_H /* d'b: avoid stdlib.h including */
#include "include/zvmlib.h"
#include <emmintrin.h>
#include <smmintrin.h>

#if 0
#define DEBUG
#endif

#define DEFAULT_CHUNK_SIZE 18
#define ELEMENT_SIZE sizeof(uint32_t)

#define _eoutput(_str)\
  do {\
    FPRINTF(STDERR, "Error in %s() at %u: %s\n", __func__, __LINE__, (_str));\
    zvm_exit(1);\
  } while(0)

#ifdef DEBUG
#define _doutput(...) FPRINTF(STDERR, __VA_ARGS__)

/* print "s" elements array "a" */
#define SHOW_RAW(a, s)\
  do {\
    int i;\
    for(i = 0; i < s; ++i)\
      FPRINTF(STDERR, "%u ", ((uint32_t*)a)[i]);\
    FPRINTF(STDERR, "\n");\
  } while (0)

/* show place and print "s" elements array "a" */
#define SHOW_RAW_FUNC(a, s)\
  do {\
    int i;\
    FPRINTF(STDERR, "%s -- %d: ", __func__, __LINE__);\
    for(i = 0; i < s; ++i)\
      FPRINTF(STDERR, "%u ", ((uint32_t*)a)[i]);\
    FPRINTF(STDERR, "\n");\
  } while (0)

/* check if "s" elements of array "a" are sorted */
#define CHECK_RAW(a, s)\
  do {\
    int i;\
    for(i = 1; i < s; ++i)\
      if(((uint32_t*)a)[i-1] > ((uint32_t*)a)[i]) {\
        SHOW_RAW(a, s);\
        _eoutput("not sorted!");}\
  } while(0)

/* check if "s+s" elements of array "a"+"b" are sorted */
#define CHECK_RAWS(a, b, s)\
  do {\
    CHECK_RAW(a, s);\
    CHECK_RAW(b, s);\
    if(((uint32_t*)a)[s-1] > ((uint32_t*)b)[0]) {\
      SHOW_RAW(a, s);\
      SHOW_RAW(b, s);\
      _eoutput("not sorted!");}\
  } while(0)

#else
#define _doutput(...)
#define SHOW_RAW(a, s)
#define CHECK_RAW(a, s)
#define CHECK_RAWS(a, b, s)
#define SHOW_RAW_FUNC(a, s)
#endif /* DEBUG */

/* sort 8 elements using bitonal method */
/* elements are given in 2 arrays (4 and 4),
 result will be returned in the same arrays with a straight order */
inline void bitonic_sort_kernel4(float *a, float *b)
{
  __m128 ma;
  __m128 mb;
  __m128 map;
  __m128 mbp;
  __m128 lo;
  __m128 hi;

  /* load 8 elements to sse registers */
  ma = _mm_load_ps(a);
  mb = _mm_load_ps(b);

  /* In-Register sort */
  map = _mm_shuffle_ps(ma, mb, _MM_SHUFFLE(2, 0, 2, 0)); /* 0x88: */
  mbp = _mm_shuffle_ps(ma, mb, _MM_SHUFFLE(3, 1, 3, 1)); /* 0xdd: */

  lo = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));
  hi = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));

  map = _mm_shuffle_ps(hi, lo, _MM_SHUFFLE(3, 1, 2, 0)); /* 0xd8: */
  mbp = _mm_shuffle_ps(hi, lo, _MM_SHUFFLE(2, 0, 3, 1)); /* 0x8d: */

  lo = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));
  hi = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));

  map = _mm_shuffle_ps(lo, lo, _MM_SHUFFLE(3, 1, 2, 0)); /* 0xd8: */
  mbp = _mm_shuffle_ps(hi, hi, _MM_SHUFFLE(1, 3, 0, 2)); /* 0x72: */

  lo = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));
  hi = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));

  map = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(1, 0, 0, 1)); /* 0x41: */
  mbp = _mm_shuffle_ps(hi, lo, _MM_SHUFFLE(3, 2, 2, 3)); /* 0xeb: */

  lo = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));
  hi = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));

  map = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(3, 2, 1, 0)); /* 0xe4: */
  mbp = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(1, 0, 3, 2)); /* 0x4e: */

  lo = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));
  hi = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));

  map = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(3, 1, 2, 0)); /* 0xd8: */
  mbp = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(2, 0, 3, 1)); /* 0x8d: */

  lo = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));
  hi = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map), _mm_castps_si128(mbp)));

  map = _mm_shuffle_ps(hi, lo, _MM_SHUFFLE(2, 0, 2, 0)); /* 0x88: */
  mbp = _mm_shuffle_ps(hi, lo, _MM_SHUFFLE(3, 1, 3, 1)); /* 0xdd: */

  map = _mm_shuffle_ps(map, map, _MM_SHUFFLE(1, 3, 0, 2)); /* 0x72: */
  mbp = _mm_shuffle_ps(mbp, mbp, _MM_SHUFFLE(1, 3, 0, 2)); /* 0x72: */

  /* unload sorted elements to memory */
  _mm_store_ps(a, map);
  _mm_store_ps(b, mbp);

  CHECK_RAWS(a, b, 4);
}

/*
 * merge 2 sorted arrays (8 elements each) to 1 sorted array
 * return result (16 elements) in the same arrays
 * TODO(d'b): replace magic numbers with constants
 */
inline void bitonic_merge_kernel8core(float *a, float *b /* must be reversed*/)
{
  __m128 map[2];
  __m128 mbp[2];
  __m128 lo[2];
  __m128 hi[2];

  map[0] = _mm_load_ps(a);
  mbp[0] = _mm_load_ps(b);

  map[1] = _mm_load_ps(a + 4);
  mbp[1] = _mm_load_ps(b + 4);

  lo[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(mbp[0])));
  hi[0] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(mbp[0])));

  lo[1] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map[1]), _mm_castps_si128(mbp[1])));
  hi[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map[1]), _mm_castps_si128(mbp[1])));

  map[0] = lo[0];
  map[1] = lo[1];
  mbp[0] = hi[0];
  mbp[1] = hi[1];

  /* L1 processing */
  lo[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(map[1])));
  lo[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(map[1])));
  hi[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(mbp[0]), _mm_castps_si128(mbp[1])));
  hi[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(mbp[0]), _mm_castps_si128(mbp[1])));

  map[0] = _mm_shuffle_ps(lo[0], lo[1], 0xe4);
  map[1] = _mm_shuffle_ps(lo[0], lo[1], 0x4e);
  mbp[0] = _mm_shuffle_ps(hi[0], hi[1], 0xe4);
  mbp[1] = _mm_shuffle_ps(hi[0], hi[1], 0x4e);

  /* L2 processing */
  lo[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(map[1])));
  lo[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(map[1])));
  hi[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(mbp[0]), _mm_castps_si128(mbp[1])));
  hi[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(mbp[0]), _mm_castps_si128(mbp[1])));

  map[0] = _mm_shuffle_ps(lo[0], lo[1], 0xd8);
  map[1] = _mm_shuffle_ps(lo[0], lo[1], 0x8d);
  mbp[0] = _mm_shuffle_ps(hi[0], hi[1], 0xd8);
  mbp[1] = _mm_shuffle_ps(hi[0], hi[1], 0x8d);

  /* L3 processing */
  lo[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(map[1])));
  lo[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(map[0]), _mm_castps_si128(map[1])));
  hi[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(mbp[0]), _mm_castps_si128(mbp[1])));
  hi[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(mbp[0]), _mm_castps_si128(mbp[1])));

  map[0] = _mm_shuffle_ps(lo[1], lo[0], 0x88);
  map[1] = _mm_shuffle_ps(lo[1], lo[0], 0xdd);
  mbp[0] = _mm_shuffle_ps(hi[1], hi[0], 0x88);
  mbp[1] = _mm_shuffle_ps(hi[1], hi[0], 0xdd);

  map[0] = _mm_shuffle_ps(map[0], map[0], 0x72);
  map[1] = _mm_shuffle_ps(map[1], map[1], 0x72);
  mbp[0] = _mm_shuffle_ps(mbp[0], mbp[0], 0x72);
  mbp[1] = _mm_shuffle_ps(mbp[1], mbp[1], 0x72);

  _mm_store_ps(&a[0], map[0]);
  _mm_store_ps(&a[4], map[1]);
  _mm_store_ps(&b[0], mbp[0]);
  _mm_store_ps(&b[4], mbp[1]);

  CHECK_RAWS(a, b, 8);
}

/*
 * prepare (reverse) 2nd 8 elements of given 16 and call merge sort
 * return result (16 sorted elements) in the same arrays
 */
inline void bitonic_merge_kernel8(float *a, float *b /* must not be reversed */)
{
  __m128 mb[3];

  /* Reverse *b */
  mb[0] = _mm_load_ps(b);
  mb[1] = _mm_load_ps(b + 4);
  mb[2] = _mm_shuffle_ps(mb[1], mb[1], 0x1b);
  mb[1] = _mm_shuffle_ps(mb[0], mb[0], 0x1b);
  _mm_store_ps(b, mb[2]);
  _mm_store_ps(b + 4, mb[1]);

  bitonic_merge_kernel8core(a, b);

  CHECK_RAWS(a, b, 8);
}

/*
 * merge "s+s" elements and return sorted result in "dest" array
 * TODO(d'b): replace magic numbers with macro
 */
inline void bitonic_merge_kernel16n(float *dest, float *a, float *b /* must not be reversed*/,
    uint32_t s)
{
  __m128 ma[4];
  __m128 mb[4];
  __m128 lo[4];
  __m128 hi[4];

#define LOAD16(arg) \
  mb[3] = _mm_load_ps(arg); \
  mb[2] = _mm_load_ps(arg + 4); \
  mb[1] = _mm_load_ps(arg + 8); \
  mb[0] = _mm_load_ps(arg + 12); arg+=16

  float *last_a = a + s;
  float *last_b = b + s;
  float *last_dest = dest + 2 * s;

  ma[0] = _mm_load_ps(a);
  a += 4;
  ma[1] = _mm_load_ps(a);
  a += 4;
  ma[2] = _mm_load_ps(a);
  a += 4;
  ma[3] = _mm_load_ps(a);
  a += 4;

  for(; dest < (last_dest - 16); dest += 16)
  {
    /* Load either a or b */
    if(a < last_a)
    {
      if(b < last_b)
      {
        if(*((uint32_t*) a) < *((uint32_t*) b))
        {
          LOAD16(a);
        }
        else
        {
          LOAD16(b);
        }
      }
      else
      {
        LOAD16(a);
      }
    }
    else
    {
      LOAD16(b);
    }

    /* Reverse *b */
    mb[0] = _mm_shuffle_ps(mb[0], mb[0], 0x1b);
    mb[1] = _mm_shuffle_ps(mb[1], mb[1], 0x1b);
    mb[2] = _mm_shuffle_ps(mb[2], mb[2], 0x1b);
    mb[3] = _mm_shuffle_ps(mb[3], mb[3], 0x1b);

    lo[0] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(ma[0]), _mm_castps_si128(mb[0])));
    hi[0] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(ma[0]), _mm_castps_si128(mb[0])));
    lo[1] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(ma[1]), _mm_castps_si128(mb[1])));
    hi[1] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(ma[1]), _mm_castps_si128(mb[1])));
    lo[2] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(ma[2]), _mm_castps_si128(mb[2])));
    hi[2] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(ma[2]), _mm_castps_si128(mb[2])));
    lo[3] = _mm_castsi128_ps(_mm_min_epu32(_mm_castps_si128(ma[3]), _mm_castps_si128(mb[3])));
    hi[3] = _mm_castsi128_ps(_mm_max_epu32(_mm_castps_si128(ma[3]), _mm_castps_si128(mb[3])));

    _mm_store_ps(&dest[0], lo[0]);
    _mm_store_ps(&dest[4], lo[1]);
    _mm_store_ps(&dest[8], lo[2]);
    _mm_store_ps(&dest[12], lo[3]);
    _mm_store_ps(&dest[16], hi[2]);
    _mm_store_ps(&dest[20], hi[3]);
    _mm_store_ps(&dest[24], hi[0]);
    _mm_store_ps(&dest[28], hi[1]);

    bitonic_merge_kernel8core(dest, dest + 8);
    bitonic_merge_kernel8core(dest + 16, dest + 24);

    ma[0] = _mm_load_ps(&dest[16]);
    ma[1] = _mm_load_ps(&dest[20]);
    ma[2] = _mm_load_ps(&dest[24]);
    ma[3] = _mm_load_ps(&dest[28]);
  }
}

/* merge sorted arrays (32 elements each) and return result in "d" array */
void bitonic_merge(float *d, uint32_t s, float *buf, uint32_t chunk_size)
{
  uint32_t step;
  uint32_t step_size;
  float *source = d;
  float *destination = buf;
  float *temp;

  for(step_size = chunk_size; step_size < s; step_size *= 2)
  {
    for(step = 0; step < s; step += step_size * 2)
    {
      bitonic_merge_kernel16n(destination + step,
          source + step, source + step + step_size, step_size);
    }

    temp = source;
    source = destination;
    destination = temp;
  }

  if(source != d) MEMCPY(d, source, s * sizeof(float));
}

/* sort given 32 elemens */
void inline bitonic_sort32(float *d)
{
  /* sort first 16 */
  bitonic_sort_kernel4(d, d + 4);
  bitonic_sort_kernel4(d + 8, d + 12);
  bitonic_merge_kernel8(d, d + 8);

  /* sort second 16 */
  bitonic_sort_kernel4(d + 16, d + 20);
  bitonic_sort_kernel4(d + 24, d + 28);
  bitonic_merge_kernel8(d + 16, d + 24);

  /* merge */
  bitonic_merge_kernel16n(d, d, d + 16, 16);

  CHECK_RAW(d, 32);
}

/* sort given chunk (2^chunk_size) of data */
void bitonic_sort(float *d, uint32_t s, float *buf)
{
  uint32_t i;

  /* sort individual 32 strips */
  for(i = 0; i < s; i += 32)
    bitonic_sort32(d + i);

  /* merge 32-long strips */
  bitonic_merge(d, s, buf, 32);

  CHECK_RAW(d, s);
}

/* main sort routine. chop all data to chunks, sort and merge */
void bitonic_sort_chunked(float *d, uint32_t s, float *buf, uint32_t chunk_size)
{
  uint32_t i;
  for(i = 0; i < s; i += chunk_size)
    bitonic_sort(d + i, chunk_size, buf + i);
  bitonic_merge(d, s, buf, chunk_size);
}

/* need for SSE aligned memory access */
void *aligned_malloc(size_t size, size_t align)
{
  void *mem = MALLOC(size + align + sizeof(void*));
  void **ptr = (void**) (((size_t) mem + align + sizeof(void*)) & ~(align - 1));
  ptr[-1] = mem;
  return ptr;
}

/* replaces free() */
void aligned_free(void *ptr)
{
  FREE(((void**) ptr)[-1]);
}

int main(int argc, char **argv)
{
  uint32_t chunk_size = DEFAULT_CHUNK_SIZE;
  uint32_t cnt; /* elements count */
  uint32_t *d; /* data to sort */
  uint32_t *buf; /* extra space to sort */
  int64_t filesize;

  /* check command line */
  if(argc != 2) _eoutput("usage: sort number_of_elements\n");

  /* allocate data buffer */
  filesize = STRTOL(argv[1], NULL, 10);
  cnt = filesize / sizeof(*d);
  d = aligned_malloc(filesize, 16);
  if(d == NULL) _eoutput("cannot allocate data buffer\n");

  /* allocate extra memory for the sort */
  buf = aligned_malloc(filesize, 16);
  if(buf == NULL) _eoutput("cannot allocate extra buffer\n");

  /* elements count should be the power of 2 */
  FPRINTF(STDERR, "number of elements = %d\n", cnt);
  if(cnt & (cnt - 1)) _eoutput("wrong number of elements specified\n");

  /* read data */
  if(READ(STDIN, (char*)d, sizeof *d * cnt) != cnt * sizeof *d)
    _eoutput("cannot read data from the input channel\n");

  /* Bitonic sort */
  FPRINTF(STDERR, "data sorting.. ");
  bitonic_sort_chunked((float*)d, cnt, (float*)buf, 1u << chunk_size);
  FPRINTF(STDERR, "done\n");

  /* save results */
  WRITE(STDOUT, (const char*)d, sizeof(*d) * cnt);
  FPRINTF(STDERR, "sorted data is written\n");

  return 0;
}


<|start_filename|>src/platform/gio.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Generic I/O interface implementation: memory buffer-based I/O.
 */
#include "src/platform/gio.h"

/*
 * Memory file is just read/write from/to an in-memory buffer.  Once
 * the buffer is consumed, there is no refilling/flushing.
 */
struct GioVtbl const kGioMemoryFileVtbl = {
  GioMemoryFileRead,
  GioMemoryFileWrite,
  GioMemoryFileSeek,
  GioMemoryFileFlush,
  GioMemoryFileClose,
  GioMemoryFileDtor,
};

void GioMemoryFileCtor(struct GioMemoryFile *self, char *buffer, size_t len)
{
  self->buffer = buffer;
  self->len = len;
  self->curpos = 0;

  self->base.vtbl = &kGioMemoryFileVtbl;
}

ssize_t GioMemoryFileRead(struct Gio *vself, void *buf, size_t count)
{
  struct GioMemoryFile *self = (struct GioMemoryFile *) vself;
  size_t remain;
  size_t newpos;

  /* 0 <= self->curpos && self->curpos <= self->len */
  remain = self->len - self->curpos;

  /* 0 <= remain <= self->len */
  if(count > remain) count = remain;

  /* 0 <= count && count <= remain */
  if(0 == count) return 0;

  /* self->curpos <= newpos && newpos <= self->len */
  newpos = self->curpos + count;
  memcpy(buf, self->buffer + self->curpos, count);
  self->curpos = newpos;
  return count;
}

ssize_t GioMemoryFileWrite(struct Gio *vself, const void *buf, size_t count)
{
  struct GioMemoryFile *self = (struct GioMemoryFile *) vself;
  size_t remain;
  size_t newpos;

  /* 0 <= self->curpos && self->curpos <= self->len */
  remain = self->len - self->curpos;

  /* 0 <= remain <= self->len */
  if(count > remain) count = remain;

  /* 0 <= count && count <= remain */
  if(0 == count) return 0;

  /* self->curpos <= newpos && newpos <= self->len */
  newpos = self->curpos + count;
  memcpy(self->buffer + self->curpos, buf, count);
  self->curpos = newpos;

  /* we never extend a memory file */
  return count;
}

off_t GioMemoryFileSeek(struct Gio *vself, off_t offset, int whence)
{
  struct GioMemoryFile *self = (struct GioMemoryFile *) vself;
  size_t new_pos = (size_t) -1;

  switch (whence) {
    case SEEK_SET:
      new_pos = offset;
      break;
    case SEEK_CUR:
      new_pos = self->curpos + offset;
      break;
    case SEEK_END:
      new_pos = (size_t) (self->len + offset);
      break;
    default:
      errno = EINVAL;
      break;
  }

  /**
   * on error, new_pos should be SIZE_T_MAX. On overflow it will either
   * be greater than self->len, or will have wrapped around.
   * TODO(ilewis): Detect wraparound and return an error.
   */
  if(new_pos > self->len)
  {
    errno = EINVAL;
    return (off_t) -1;
  }
  self->curpos = new_pos;
  return (off_t) new_pos;
}

int GioMemoryFileClose(struct Gio *vself)
{
  UNREFERENCED_PARAMETER(vself);
  return 0;
}

int GioMemoryFileFlush(struct Gio *vself)
{
  UNREFERENCED_PARAMETER(vself);
  return 0;
}

void GioMemoryFileDtor(struct Gio *vself)
{
  UNREFERENCED_PARAMETER(vself);
  return;
}


<|start_filename|>tests/security/computed_goto/computed_goto.c<|end_filename|>
/*
 * Copyright 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
#include "include/zvmlib.h"
#include <stdio.h>

#define assert(cond) \
  if(!(cond)) \
  { \
    fprintf(STDERR, "assert failed at %d\n", __LINE__); \
    zvm_exit(-1); \
  }

/* This tests for two former nacl-gcc bugs:
   Bug 1:  gcc outputs "jmp *%eax", which fails to validate.
   Bug 2:  gcc outputs "nacljmp *%eax", which fails to assemble.
   This correct assembly output is "nacljmp %eax". */

int test_computed_goto(int index) {
  void *addr[] = { &&label1, &&label2 };
  printf("Jumping to address %p\n", addr[index]);
  goto *addr[index];
 label1:
  return 1234;
 label2:
  return 4567;
}

int main() {
  assert(test_computed_goto(0) == 1234);
  assert(test_computed_goto(1) == 4567);
  return 0;
}


<|start_filename|>src/loader/tramp.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Simple/secure ELF loader (NaCl SEL).
 */

#ifndef TRAMP_H__
#define TRAMP_H__

/*
 * text addresses, not word aligned; these are .globl symbols from the
 * assembler source, and there is no type information associated with
 * them.  we could declare these to be (void (*)(void)), i suppose,
 * but it doesn't really matter since we convert their addresses to
 * uintptr_t at every use.
 */
extern char NaCl_trampoline_code;
extern char NaCl_trampoline_code_end;
extern char NaCl_trampoline_call_target;

extern char NaClDispatchThunk;
extern char NaClDispatchThunk_jmp_target;
extern char NaClDispatchThunkEnd;

#endif /* TRAMP_H__ */


<|start_filename|>tests/functional/demo/argv_envp/argv_envp.c<|end_filename|>
/*
 * argv and envp test. almost deprecated
 */
#include "include/zvmlib.h"

int main(int argc, char **argv, char **envp)
{
  int i;

  /* command line */
  printf("argc = %d\n", argc);
  for(i = 0; argv[i] != NULL; ++i)
    printf("argv[%d] = %s\n", i, argv[i]);
  printf("argv[%d] = %s\n", i, argv[i] == NULL ? "NULL" : argv[i]);

  /* environment */
  for(i = 0; envp[i] != NULL; ++i)
    printf("envp[%d] = %s\n", i, envp[i]);
  printf("envp[%d] = %s\n", i, envp[i] == NULL ? "NULL" : envp[i]);

  return 0;
}


<|start_filename|>tests/functional/memory/memory.c<|end_filename|>
/*
 * it is more zvmlib test rather than the zerovm one. however
 * it is still needed to test memory allocation
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define LOOP_SIZE 0x10000
#define MAX_CHUNK_SIZE 0x100000LL
#define PATTERN(x) ((uintptr_t)(x) % 0x100)

/*
 * allocate memory by small portions until its possible
 * populating each chunk with particular data
 * test all chunks and deallocate them 1 by 1
 * return 0 if everything is ok
 */
static int random_test()
{
  int count;
  int result = 0;
  uint32_t fullness = 0;
  struct
  {
    uint32_t size;
    void *ptr;
  } p[BIG_ENOUGH];

  /* allocate and set chunks until memory end */
  for(count = 0; count < LOOP_SIZE; ++count)
  {
    p[count].size = 1 + (0x123 * RAND()) % MAX_CHUNK_SIZE;
    p[count].ptr = MALLOC(p[count].size);
    if(p[count].ptr == NULL) break;

    FPRINTF(STDERR, "successful allocation: 0x%X %d\n", p[count].ptr, p[count].size);

    fullness += p[count].size;
    MEMSET(p[count].ptr, PATTERN(p[count].ptr), p[count].size);
  }

  FPRINTF(STDERR, "%u bytes where allocated\n", fullness);

  /* check for errors and release each chunk */
  while(--count >= 0)
  {
    register char control = PATTERN(p[count].ptr);
    register uint32_t i;
    register uint32_t limit = p[count].size;

    for(i = 0; i < limit; ++i)
    {
      if(((char*)p[count].ptr)[i] == control) continue;
      ++result;
      break;
    }

    FREE(p[count].ptr);
  }

  return result;
}

/* fragmentation test */
static int fragmentation_test()
{
  return 0;
}

int main()
{
  /* try to get more memory then available */
  char *p = MALLOC(268435456);
  FREE(p);

  /*
   * new plan
   * 1. get the heap start via nacl setbreak. compare with malloc() returning
   * 2. calculate maximum available space and try to allocate it
   * 3. fill it with pattern (not 0s) and free the memory
   * 4. calloc same amount and check if it is 0s
   * 5. if the heap touches stack test for the overlap
   */

  /*
   * allocate all memory by the random size chunks,
   * check for corruption in the chunks data and release
   */
  ZTEST(random_test() == 0);

  /*
   * make fragmentaion and try allocate chunk of different sizes
   * TODO: implement it
   */
  fragmentation_test();
  ZTEST(fragmentation_test() == 0);

  /*
   * todo: calloc test
   */

  /*
   * todo: realloc test
   */

  /* count errors and exit with it */
  ZREPORT;
  return 0;
}


<|start_filename|>tests/functional/accounting/accounting.c<|end_filename|>
/*
 * test accounting. measure both network and local mounted channels
 * returns the number of failed tests
 *
 * note: not fully functional. network part should be updated in manifest
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

static uint64_t *acgets;
static uint64_t *acputs;
static uint64_t *acgetsizes;
static uint64_t *acputsizes;

/* allocates memory and resets counters */
static int counters_ctor()
{
  acgets = CALLOC(MANIFEST->channels_count, sizeof *acgets);
  acputs = CALLOC(MANIFEST->channels_count, sizeof *acputs);
  acgetsizes = CALLOC(MANIFEST->channels_count, sizeof *acgetsizes);
  acputsizes = CALLOC(MANIFEST->channels_count, sizeof *acputsizes);

  /* check allocation */
  ZFAIL(acgets && acputs && acgetsizes && acputsizes);

  return 0;
}

/* free counters and print accounting data */
static void counters_dtor()
{
  int i;

  for(i = 0; i < MANIFEST->channels_count; ++i)
  {
    FPRINTF(STDERR, "channel %d: gets = %u, "
        "getsizes = %u\n", i, acgets[i], acgetsizes[i]);
    FPRINTF(STDERR, "channel %d: puts = %u, "
        "putsizes = %u\n", i, acputs[i], acputsizes[i]);
  }

  FREE(acgets);
  FREE(acputs);
  FREE(acgetsizes);
  FREE(acputsizes);
}

/* copies all data from in to out */
static void copy_channel(const char *out, const char *in)
{
  char buf[BIG_ENOUGH];
  int code;

  /* check channels availability */
  ZFAIL(OPEN(in) >= 0);
  ZFAIL(OPEN(out) >= 0);

  /* copy data */
  for(;;)
  {
    code = READ(in, buf, BIG_ENOUGH);
    if(code == 0) break;
    acgetsizes[OPEN(in)] += code;
    ++acgets[OPEN(in)];

    code = WRITE(out, buf, code);
    if(code == 0) break;
    acputsizes[OPEN(out)] += code;
    ++acputs[OPEN(out)];
  }
}

int main(int argc, char **argv)
{
  /* allocate counters */
  ZTEST(counters_ctor() == 0);

  /* read data from stdin and write to stdout */
  copy_channel(STDOUT, STDIN);

  /* temporary disabled */
#if 0
  /* read data from input and write to output */
  copy_channel(OUTPUT, INPUT);
#endif

  /* free counters and print accounting data */
  counters_dtor();

  /* count errors and exit with it */
  ZREPORT;
  return 0; /* prevent warning */
}


<|start_filename|>tests/unit/manifest_parser_test.cc<|end_filename|>
/*
 * manifest_parser_test.c
 * functions to test: ManifestCtor(), ManifestDtor(), GetValuByKey(),
 *
 *  Created on: Nov 12, 2011
 *      Author: d'b
 */
#include <stdio.h>
#include <stdlib.h>
#include "gtest/gtest.h"
#include "src/main/manifest.h"
#include "src/main/tools.h"

#define BIG_ENOUGH 0x10000
#define MANIFEST_FILE "killme.manifest.txt"
#define MANIFEST_DATA \
      "-=-=-=-=-=-=-=-=-=-=-=- just a test -=-=-=-=-=-=-=-=-=-=-=-\n"\
      "== this is manifest example\n\n"\
      "key01 = value01\n"\
      "  key02  =  value02\n"\
      "key03=value03 \r"\
      "       key 014=value 014\n"\
      "key05 =value05\n"\
      "      key06= value06\n"\
      "key =\n"\
      "  = value_a\n"\
      "  =\r"\
      "key value_b\n"\
      "\t \t key07\t\t\t\t= \t\t\tvalue07   \n"\
      "key_with_multivalues1 = value1, value2, value3,value4\n"\
      "key_with_multivalues2 = value1 value2   value3\tvalue4\n"\
      "multikey = value1, value2\n"\
      "multikey = value3,  value4 \n"

// test whole manifest processing and get value by key
#if 0 // temporarily disabled
TEST(ManifestTests, ManifestParserTest)
{
  FILE *f;

  // prepare mock
  if((f = fopen(MANIFEST_FILE, "w")) == NULL) return;
  fprintf(f, MANIFEST_DATA);
  fclose(f);
  EXPECT_EQ(0, ManifestCtor(MANIFEST_FILE));

  // go through manifest data
  EXPECT_STREQ("value 014", GetValueByKey((char*)"key 014"));
  EXPECT_STREQ("value01", GetValueByKey((char*)"key01"));
  EXPECT_STREQ("value07", GetValueByKey((char*)"key07"));
  EXPECT_STREQ("value05", GetValueByKey((char*)"key05"));
  EXPECT_STREQ("value02", GetValueByKey((char*)"key02"));
  EXPECT_STREQ("value03", GetValueByKey((char*)"key03"));
  EXPECT_STREQ("value06", GetValueByKey((char*)"key06"));

  // check the multikey case
  char buf[BIG_ENOUGH], **tokens = (char**)buf;
  int code = 0;
  code = GetValuesByKey("multikey", tokens, BIG_ENOUGH);
  EXPECT_EQ(2, code);
  EXPECT_STREQ("value1, value2", tokens[0]);
  EXPECT_STREQ("value3,  value4", tokens[1]);

  // check the multivalues case
  char str1[] = "value1, value2, value3,value4\n";
  code = ParseValue(str1, " ,\r\n", tokens, 4);
  EXPECT_STREQ(tokens[0], "value1");
  EXPECT_STREQ(tokens[1], "value2");
  EXPECT_STREQ(tokens[2], "value3");
  EXPECT_STREQ(tokens[3], "value4");

  char str2[] = "value1 value2   value3\tvalue4";
  code = ParseValue(str2, " \t", tokens, 4);
  EXPECT_STREQ(tokens[0], "value1");
  EXPECT_STREQ(tokens[1], "value2");
  EXPECT_STREQ(tokens[2], "value3");
  EXPECT_STREQ(tokens[3], "value4");

  // test manifest destructor
  // todo(d'b): put the death test here
  ManifestDtor();
  remove(MANIFEST_FILE);
//  EXPECT_STREQ(NULL, GetValueByKey((char*)"key 014"));
}
#endif

int main(int argc, char *argv[]) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


<|start_filename|>src/main/zerovm.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/*
 * ZeroVM main
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include "src/platform/signal.h"
#include "src/main/setup.h"
#include "src/main/report.h"
#include "src/platform/qualify.h"
#include "src/main/accounting.h"
#include "src/main/tools.h"
#include "src/channels/preload.h"

#define BADCMDLINE(msg) \
  do { \
    printf(HELP_SCREEN, msg == NULL ? "" : msg, \
        msg == NULL ? "" : "\n", TAG_ENCRYPTION); exit(EINVAL); \
  } while(0)

static int skip_qualification = 0;
static int skip_validation = 0;
static int quit_after_load = 0;

/* log zerovm command line. note: delegates g_string_free to report */
static void CommandLine(int argc, char **argv)
{
  GString *cmd = g_string_new("command =");

  g_string_append_printf(cmd, " %s[%d]", *argv++, getpid());
  while(*argv != NULL)
    g_string_append_printf(cmd, " %s", *argv++);

  SetCmdString(cmd);
  ZLOGS(LOG_DEBUG, "%s", cmd);
}

/* parse given command line, manifest and initialize NaClApp object */
static void ParseCommandLine(struct NaClApp *nap, int argc, char **argv)
{
  int opt;
  char *manifest_name = NULL;
  int64_t psize;

  /* construct logger with default verbosity */
  ZLogCtor(LOG_ERROR);
  CommandLine(argc, argv);

  while((opt = getopt(argc, argv, "-PFQst:v:M:T:")) != -1)
  {
    switch(opt)
    {
      case 1:
      case 'M':
        if(manifest_name != NULL)
          BADCMDLINE("2nd manifest encountered");
        manifest_name = optarg;
        break;
      case 's':
        skip_validation = 1;
        ZLOGS(LOG_ERROR, "VALIDATION DISABLED");
        break;
      case 'F':
        quit_after_load = 1;
        break;
      case 't':
        ReportMode(ToInt(optarg));
        break;
      case 'v':
        ZLogDtor();
        ZLogCtor(ToInt(optarg));
        break;
      case 'Q':
        skip_qualification = 1;
        ZLOGS(LOG_ERROR, "PLATFORM QUALIFICATION DISABLED");
        break;
      case 'P':
        ZLOGS(LOG_ERROR, "DISK SPACE PREALLOCATION DISABLED");
        PreloadAllocationDisable();
        break;
      case 'T':
        ZTraceCtor(optarg);
        break;
      default:
        BADCMDLINE(NULL);
        break;
    }
  }

  /* parse manifest file specified in command line */
  if(manifest_name == NULL) BADCMDLINE(NULL);
  nap->manifest = ManifestCtor(manifest_name);

  /* set available nap and manifest fields */
  ZLOGFAIL(nap->manifest->program == NULL, EFAULT, "program not specified");
  psize = GetFileSize(nap->manifest->program);
  ZLOGFAIL(psize < 0, ENOENT, "program open error");
}

static void ValidateProgram(struct NaClApp *nap)
{
  int status = 0; /* 0 = failed, 1 = successful */
  int64_t static_size;
  int64_t dynamic_size;
  uint8_t* static_addr;
  uint8_t* dynamic_addr;

  assert((nap->static_text_end | nap->dynamic_text_start
      | nap->dynamic_text_end | nap->mem_start) > 0);

  /* static and dynamic text address / length */
  static_size = nap->static_text_end -
      NaClSysToUser(nap, nap->mem_start + NACL_TRAMPOLINE_END);
  dynamic_size = nap->dynamic_text_end - nap->dynamic_text_start;
  static_addr = (uint8_t*)NaClUserToSys(nap, NACL_TRAMPOLINE_END);
  dynamic_addr = (uint8_t*)NaClUserToSys(nap, nap->dynamic_text_start);

  /* validate static and dynamic text */
  if(static_size > 0)
    status = NaClSegmentValidates(static_addr, static_size, nap->initial_entry_pt);
  if(dynamic_size > 0)
    status &= NaClSegmentValidates(dynamic_addr, dynamic_size, nap->initial_entry_pt);

  /* set results */
  SetValidationState(1);
  ZLOGFAIL(status == 0, ENOEXEC, "validation failed");
  SetValidationState(0);
}

int main(int argc, char **argv)
{
  struct NaClApp state = {0}, *nap = &state;
  struct GioMemoryFileSnapshot main_file;

  /* initialize globals and set nap fields to default values */
  ReportCtor();
  NaClAppCtor(nap);
  ParseCommandLine(nap, argc, argv);

  /* We use the signal handler to verify a signal took place. */
  if(skip_qualification == 0) RunSelQualificationTests();
  SignalHandlerInit();

  /* read elf into memory */
  ZLOGFAIL(0 == GioMemoryFileSnapshotCtor(&main_file, nap->manifest->program),
      ENOENT, "Cannot open '%s'. %s", nap->manifest->program, strerror(errno));
  ZTrace("[memory snapshot]");

  /* validate program structure (check elf header and segments) */
  ZLOGS(LOG_DEBUG, "Loading %s", nap->manifest->program);
  AppLoadFile((struct Gio *) &main_file, nap);
  ZTrace("[user module loading]");

  /* validate given program (ensure that text segment is safe) */
  ZLOGS(LOG_DEBUG, "Validating %s", nap->manifest->program);
  if(!skip_validation) ValidateProgram(nap);
  ZTrace("[user module validation]");

  /* free snapshot */
  if(-1 == (*((struct Gio *)&main_file)->vtbl->Close)((struct Gio *)&main_file))
    ZLOG(LOG_ERROR, "Error while closing '%s'", nap->manifest->program);
  (*((struct Gio *) &main_file)->vtbl->Dtor)((struct Gio *) &main_file);
  ZTrace("[snapshot deallocation]");

  /* initialize all channels */
  ChannelsCtor(nap->manifest);
  ZLOGS(LOG_DEBUG, "channels constructed");
  ZTrace("[channels mounting]");

  /*
   * allocate user heap. should be the last allocation in raw because
   * after heap allocated there will be no free user memory
   */
  PreallocateUserMemory(nap);
  ZLOGS(LOG_DEBUG, "user memory preallocated");
  ZTrace("[user memory preallocation]");

  /* set user manifest in user space */
  SetSystemData(nap);
  ZLOGS(LOG_DEBUG, "system data set");
  ZTrace("[user manifest construction]");

  /* "defense in depth" call */
  ZLOGS(LOG_DEBUG, "Last preparations");
  LastDefenseLine(nap->manifest);

  /* quit if fuzz testing specified */
  if(quit_after_load)
  {
    SetExitState(OK_STATE);
    ReportDtor(0);
  }
  ZTrace("[last preparations]");

  /* switch to the user code flushing all buffers */
  fflush(NULL);
  CreateSession(nap);
  return EFAULT; /* unreachable */
}


<|start_filename|>tests/functional/include/ztest.h<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ZTEST_H_
#define ZTEST_H_

static int errcount = 0;
#ifndef ERRCOUNT
#define ERRCOUNT errcount
#endif

#define PAGESIZE 0x10000
#define ROUNDDOWN_64K(a) ((a) & ~(PAGESIZE - 1LLU))
#define ROUNDUP_64K(a) ROUNDDOWN_64K((a) + PAGESIZE - 1LLU)

#define UNREFERENCED_VAR(a) do { (void)a; } while(0)
#define UNREFERENCED_FUNCTION(f) do {if(0) f();} while(0)

#define ZTEST(cond) \
  do {\
    if(cond)\
      FPRINTF(STDERR, "succeed on %3d: %s\n", __LINE__, #cond);\
    else\
    {\
      FPRINTF(STDERR, "failed on %4d: %s\n", __LINE__, #cond);\
      ++ERRCOUNT;\
    }\
  } while(0)

/* count errors and exit with it */
#define ZREPORT \
  do { \
    if(ERRCOUNT > 0) \
      FPRINTF(STDERR, "TEST FAILED with %d errors\n", ERRCOUNT); \
    else \
      FPRINTF(STDERR, "TEST SUCCEED\n\n"); \
    exit(ERRCOUNT); \
  } while(0)

/* works like ZTEST but ends the test execution after error */
#define ZFAIL(cond) \
  do { \
    ZTEST(cond); \
    if(!(cond)) ZREPORT; \
  } while(0)

#endif /* ZTEST_H_ */


<|start_filename|>src/platform/signal.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SIGNAL_H__
#define SIGNAL_H__ 1

/*
 * The nacl_signal module provides a platform independent mechanism for
 * trapping signals encountered while running a Native Client executable.
 * Signal handlers can be installed which will receive a POSIX signal number
 * and a platform dependent signal object. Accessors are provided to convert
 * to and from architecture dependent CPU state structures.
 */

#include "src/loader/sel_rt.h"

EXTERN_C_BEGIN

struct NaClApp;

enum SignalResult {
  NACL_SIGNAL_SEARCH,   /* Try our handler or OS */
  NACL_SIGNAL_SKIP,     /* Skip our handlers and try OS */
  NACL_SIGNAL_RETURN    /* Skip all other handlers and return */
};
#define SIGNAL_STRLEN 64

/*
 * Prototype for a signal handler.  The handler will receive the POSIX
 * signal number and an opaque platform dependent signal object.
 */
typedef enum SignalResult (*SignalHandler)(int sig_num, void *ctx);

/*
 * Register process-wide signal handlers.
 */
void SignalHandlerInit(void);

/* Undoes the effect of SignalHandlerInit() */
void SignalHandlerFini(void);

/*
 * Traverse handler list, until a handler returns
 * NACL_SIGNAL_RETURN, or the list is exhausted, in which case
 * the signal is passed to the OS.
 */
enum SignalResult SignalHandlerFind(int signal_number, void *ctx);

/* Platform specific code. Do not call directly */
void SignalHandlerInitPlatform(void);
void SignalHandlerFiniPlatform(void);

EXTERN_C_END

#endif /* SIGNAL_H__ */


<|start_filename|>src/channels/channel.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <glib.h>
#include "src/loader/sel_ldr.h"
#include "src/main/report.h"
#include "src/main/accounting.h"
#include "src/channels/preload.h"
#include "src/channels/prefetch.h"
#include "src/channels/nservice.h"
#include "src/channels/channel.h"

/*
 * array of read buffers. WARNING: buffers[0] should not be allocated
 * since it always will point to the user buffer for optimization reason
 */
static GPtrArray *buffers = NULL;
static uint32_t buffers_size = 0; /* size of buffers */
static GTree *aliases;
static int tree_reset = 0;
static uint32_t binds = 0; /* "bind" sources number */
static uint32_t connects = 0; /* "connect" sources number */

/* if the function called there is duplicate */
static void DuplicateKey(gpointer key)
{
  ZLOGFAIL(tree_reset == 0, EFAULT, "%s is already allocated", key);
}

/* reset aliases tree */
static void ResetAliases()
{
  if(aliases == NULL) return;
  tree_reset = 1; /* we want to remove data from the tree */
  g_tree_destroy(aliases);
  tree_reset = 0; /* set it back to "check mode" */
  aliases = NULL;
}

/* get chunk of data from source. data will be put to "buffers" */
static int32_t GetDataChunk(struct ChannelDesc *channel, int n,
    size_t size, off_t offset)
{
  int32_t result = 0;

  switch(CH_PROTO(channel, n))
  {
    case ProtoRegular:
      result = pread(GPOINTER_TO_INT(CH_HANDLE(channel, n)),
          buffers->pdata[n], size, offset);
      if(result == -1) result = -errno;
      break;
    case ProtoCharacter:
    case ProtoFIFO:
      result = fread(buffers->pdata[n], 1, size, CH_HANDLE(channel, n));
      if(result == -1) result = -errno;
      break;
    case ProtoTCP:
      /* get another message if it already exhausted */
      if(channel->bufend - channel->bufpos == 0)
      {
        channel->bufpos = size; /* workaround for udt to get full message */
        FetchMessage(channel, n);
      }

      /* copy data from the message to buffers */
      if(channel->eof == 0)
      {
        result = MIN(size, channel->bufend - channel->bufpos);
        memcpy(buffers->pdata[n], MessageData(channel) + channel->bufpos, result);
        channel->bufpos += result;
      }
      break;
    default: /* design error */
      ZLOGFAIL(1, EFAULT, "invalid channel source %s;n", channel->alias, n);
      break;
  }

  /* update the source position */
  if(result > 0)
    CH_FILE(channel, n)->pos += result;

  if(result == 0)
    if(CH_SEQ_READABLE(channel)) channel->eof = 1;
  return result;
}

/* check EOF digest for network source */
static void TestEOFDigest(struct ChannelDesc *channel, int n)
{
  if(channel->tag != NULL && channel->bufend > 0)
  {
    char digest[TAG_DIGEST_SIZE + 1];
    char *control = MessageData(channel);

    assert(channel->bufend == TAG_DIGEST_SIZE);

    TagDigest(channel->tag, digest);
    if(0 != memcmp(control, digest, TAG_DIGEST_SIZE))
    {
      char msg[BIG_ENOUGH_STRING];
      g_snprintf(msg, BIG_ENOUGH_STRING,
          "%s;%d corrupted upon eof", channel->alias, n);
      SetExitState(msg);
      SetExitCode(EPIPE);
      ZLOG(LOG_ERROR, msg);
    }
  }
}

/*
 * return the 1st valid source in the raw or -1
 * TODO(d'b): implement a new logic to choose the 1st available source
 */
static int GetFirstSource(struct ChannelDesc *channel)
{
  int n;

  for(n = 0; n < channel->source->len; ++n)
    if(IS_VALID(CH_FILE(channel, n))) return n;
  return -1;
}

int32_t ChannelRead(struct ChannelDesc *channel,
    char *buffer, size_t size, off_t offset)
{
  int32_t result = -1;
  int good = -1; /* index of buffer with proper data */
  int readrest = size;
  int toread;
  int n;

  assert(buffers != NULL);
  assert(channel != NULL);
  assert(channel->source->len > 0);

  /* read "size" bytes or until channel EOF */
  while(readrest > 0 && !channel->eof)
  {
    int first = GetFirstSource(channel);
    toread = MIN(readrest, BUFFER_SIZE);
    good = -1;

    ZLOGFAIL(first < 0, EIO, "all %s sources failed", channel->alias);
    for(n = first; n < channel->source->len && good < 0 && !channel->eof; ++n)
    {
      int j;

      /* choose "zero copy" source */
      buffers->pdata[first] = buffer;

      /* get next data portion */
      if(!IS_VALID(CH_FILE(channel, n))) continue;
      SyncSource(channel, n);
      result = GetDataChunk(channel, n, toread, offset);
      if(result < 0)
      {
        CH_FLAGS(channel, n) |= FLAG_VALID_MASK;
        continue;
      }

      /* compare buffers */
      for(j = first; j < n; ++j)
      {
        /* skip invalid source buffer */
        if(!IS_VALID(CH_FILE(channel, n))) continue;
        if(memcmp(buffers->pdata[j], buffers->pdata[n], result) == 0)
        {
          good = j;
          break;
        }
      }

      /* accounting */
      CountGet(CH_CONN(channel, n), result);
    }

    /* fail session if chunk broken and cannot be restored */
    ZLOGFAIL(!channel->eof && good < 0 && channel->source->len > 1,
        EIO, "%s failed to read", channel->alias);
    ZLOGFAIL(result < 0 && channel->source->len == 1,
        EIO, "%s failed to read", channel->alias);

    /* copy verified data to buffer and shift the position */
    if(good > first)
      memcpy(buffer, buffers->pdata[good], result);
    buffer += result;
    offset += result;
    readrest -= result;

    /* update get position and put position (except CDR) */
    if(CH_RND_WRITEABLE(channel)) channel->putpos = offset;
    channel->getpos = offset;
  }

  /* update tag and return actual data size */
  result = size - readrest;
  buffer -= result;
  TagUpdate(channel->tag, buffer, result);

  /* extra corruption check for network source on EOF */
  good = GetFirstSource(channel);
  if(channel->eof && IS_NETWORK(CH_FILE(channel, good)))
    TestEOFDigest(channel, good);

  /* update user i/o counters */
  ++channel->counters[GetsLimit];
  if(result > 0)
    channel->counters[GetSizeLimit] += result;
  return result;
}

int32_t ChannelWrite(struct ChannelDesc *channel,
    const char *buffer, size_t size, off_t offset)
{
  int n;
  int32_t result = -1;

  for(n = 0; n < channel->source->len; ++n)
  {
    switch(CH_PROTO(channel, n))
    {
      case ProtoRegular:
        result = pwrite(GPOINTER_TO_INT(CH_HANDLE(channel, n)), buffer, size, offset);
        break;
      case ProtoCharacter:
      case ProtoFIFO:
        result = fwrite(buffer, 1, size, CH_HANDLE(channel, n));
        break;
      case ProtoTCP:
        result = SendData(channel, n, buffer, size);
        break;
      default: /* design error */
        ZLOGFAIL(1, EFAULT, "invalid channel source %s;%d", channel->alias, n);
        break;
    }

    /* accounting */
    ZLOGFAIL(result < 0, EIO, "%s;%d failed to write: %s",
        channel->alias, n, strerror(errno));
    CountPut(CH_CONN(channel, n), result);
  }

  /* update cursors and size */
  channel->putpos = offset + result;
  channel->size = (channel->type == SGetRPut) || (channel->type == RGetRPut) ?
      MAX(channel->size, channel->putpos) : channel->putpos;
  channel->getpos = channel->putpos;
  TagUpdate(channel->tag, buffer, result);

  /* update user i/o counters */
  ++channel->counters[PutsLimit];
  if(result > 0)
    channel->counters[PutSizeLimit] += result;
  return result;
}

/* get network sources statistics (RO - binds, WO - connects) */
static void CountNetSources(const struct ChannelDesc *channel,
    uint32_t *binds_number, uint32_t *connects_number)
{
  int i;

  for(i = 0; i < channel->source->len; ++i)
  {
    struct Connection *c = CH_CONN(channel, i);

    /* update binds/connects statistics */
    if(IS_NETWORK(c))
    {
      if(IS_WO(channel)) ++*connects_number;
      else ++*binds_number;
    }
  }
}

/*
 * order channels to mounting sequence
 * compares 2 channels in a distinct way: place "connect" ones after
 * "binds" and channels without network sources at the end
 */
static int OrderMount(const struct ChannelDesc **a, const struct ChannelDesc **b)
{
  uint32_t a_binds = 0;
  uint32_t b_binds = 0;
  uint32_t a_connects = 0;
  uint32_t b_connects = 0;

  CountNetSources(*a, &a_binds, &a_connects);
  CountNetSources(*b, &b_binds, &b_connects);

  /* compare */
  if(a_binds != 0 || b_binds != 0)
    return b_binds - a_binds;
  else
    if(a_connects != 0 || b_connects != 0)
      return b_connects - a_connects;

  return 0; /* local sources does not matter */
}

/* order channels to dismounting sequence ("connects" before "binds") */
static int OrderDismount(const struct ChannelDesc **a, const struct ChannelDesc **b)
{
  return OrderMount(b, a);
}

/*
 * order channels for user manifest
 * 1st 3 channels should be stdin, stdout, stderr
 */
static int OrderUser(const struct ChannelDesc **a, const struct ChannelDesc **b)
{
  if(g_strcmp0((*a)->alias, STDIN) == 0) return -1;
  if(g_strcmp0((*b)->alias, STDIN) == 0) return 1;
  if(g_strcmp0((*a)->alias, STDOUT) == 0) return -1;
  if(g_strcmp0((*b)->alias, STDOUT) == 0) return 1;
  if(g_strcmp0((*a)->alias, STDERR) == 0) return -1;
  if(g_strcmp0((*b)->alias, STDERR) == 0) return 1;

  return 0; /* the order for other channels does not matter */
}

/* to sort sources, network sources before local */
static int OrderSources(const struct Connection **a, const struct Connection **b)
{
  return IS_FILE(*a) - IS_FILE(*b);
}

/* to sort channels alphabetically by alias */
static int OrderAlias(const struct ChannelDesc **a, const struct ChannelDesc **b)
{
  return g_strcmp0((*a)->alias, (*b)->alias);
}

void SortChannels(GPtrArray *channels)
{
  g_ptr_array_sort(channels, (GCompareFunc)OrderAlias);
  g_ptr_array_sort(channels, (GCompareFunc)OrderUser);
}

/* get numbers of "binds" and "connects" sources */
static void GetNetworkStatistics(const struct Manifest *manifest)
{
  int i;

  for(i = 0; i < manifest->channels->len; ++i)
    CountNetSources(CH_CH(manifest, i), &binds, &connects);
}

/* mount the channel sources */
static void ChannelCtor(struct ChannelDesc *channel)
{
  int i;

  assert(channel != NULL);

  /* check alias for duplicates and update the list */
  g_tree_insert(aliases, channel->alias, NULL);

  ZLOGFAIL(channel->type > RGetRPut, EFAULT,
      "%s has invalid type %d", channel->alias, channel->type);

  /* mount given channel sources */
  for(i = 0; i < channel->source->len; ++i)
    if(IS_FILE(CH_FILE(channel, i)))
      PreloadChannelCtor(channel, i);
    else
      PrefetchChannelCtor(channel, i);

  /* sort sources if channel is RO */
  if(IS_RO(channel))
    g_ptr_array_sort(channel->source, (GCompareFunc)OrderSources);

  /* update "buffers" size for "read" channels */
  if(IS_RO(channel) || IS_RW(channel))
    if(channel->source->len > buffers_size)
      buffers_size = channel->source->len;
}

/* close channel and deallocate its resources */
static void ChannelDtor(struct ChannelDesc *channel)
{
  int i;

  assert(channel != NULL);

  /* quit if channel isn't mounted (no handles added) */
  if(channel->source->len == 0) return;

  /* free channel */
  for(i = 0; i < channel->source->len; ++i)
    if(IS_FILE(CH_FILE(channel, i)))
      PreloadChannelDtor(channel, i);
    else
      PrefetchChannelDtor(channel, i);

  /*
   * message cannot be safely deallocated until 0mq context closed
   * since message can still be in use
   */
  FreeMessage(channel);
}

void ChannelsCtor(struct Manifest *manifest)
{
  int i = 0;

#ifdef udt /* TODO(d'b): remove it after "channels" re-design */
  extern void PrefetchAccept(struct ChannelDesc *channel);
#endif

  /* allocate list to detect duplicate channels aliases */
  assert(manifest != NULL);
  assert(aliases == NULL);
  aliases = g_tree_new_full((GCompareDataFunc)strcmp,
      NULL, (GDestroyNotify)DuplicateKey, NULL);

  /*
   * calculate channels count. maximum allowed (MAX_CHANNELS_NUMBER - 1)
   * channels, minimum - RESERVED_CHANNELS
   */
  ZLOGFAIL(manifest->channels->len >= MAX_CHANNELS_NUMBER,
      ENFILE, "channels number reached maximum");
  ZLOGFAIL(manifest->channels->len < MIN_CHANNELS_NUMBER,
      EFAULT, "not enough channels: %d", manifest->channels->len);

  /* sort channels. then count "binds" / "connects" number */
  g_ptr_array_sort(manifest->channels, (GCompareFunc)OrderMount);
  GetNetworkStatistics(manifest);

  /* construct prefetch class before usage */
  if(binds + connects > 0)
    NetCtor(manifest);

  /* mount RO channels */
  while(IS_RO(CH_CH(manifest, i)))
    ChannelCtor(CH_CH(manifest, i++));

  /* ask for name service */
  NameServiceCtor(manifest, binds, connects);
  NameServiceDtor();

  /* mount the rest of channels */
  for(; i < manifest->channels->len; ++i)
    ChannelCtor(CH_CH(manifest, i));

#ifdef udt /* TODO(d'b): remove it after "channels" re-design */
  /* accept after binds (to avoid hanging on accept) */
  for(i = 0; i < manifest->channels->len; ++i)
    PrefetchAccept(CH_CH(manifest, i));
#endif

  /* reorder channels for user manifest */
  SortChannels(manifest->channels);

  /* check if all standard channels are specified */
  ZLOGFAIL(manifest->channels->len <= STDERR_FILENO
      || g_strcmp0(CH_CH(manifest, STDERR_FILENO)->alias, STDERR),
      EFAULT, "missing standard channels in manifest");
  ResetAliases();

  /* allocate read buffers reserving index 0 for "zero copy" */
  buffers = g_ptr_array_new();
  g_ptr_array_add(buffers, NULL);
  for(i = 1; i < buffers_size; ++i)
    g_ptr_array_add(buffers, g_malloc(BUFFER_SIZE));
}

void ChannelsDtor(struct Manifest *manifest)
{
  int i;

  /* exit if channels are not constructed */
  if(manifest == NULL || manifest->channels == NULL) return;

  /* reverse the sort order and close channels */
  g_ptr_array_sort(manifest->channels, (GCompareFunc)OrderDismount);
  for(i = 0; i < manifest->channels->len; ++i)
  {
    struct ChannelDesc *channel = CH_CH(manifest, i);
    ReportTag(channel->alias, channel->tag);
    ChannelDtor(channel);
  }
  ResetAliases();

  /* release read buffers */
  if(buffers != NULL)
    g_ptr_array_free(buffers, TRUE);

  /* release prefetch class */
  if(binds + connects > 0)
    NetDtor(manifest);
}


<|start_filename|>debian/samples/disort/Makefile<|end_filename|>
PNACL_TOOL=/usr/lib/nacl/default-sdk/toolchain/linux_x86_glibc

CC=${PNACL_TOOL}/bin/x86_64-nacl-gcc

#DEBUG=-g
CFLAGS = -I/usr/include/zerovm -I/usr/include/zerovm/networking -I.
CFLAGS += -Wall -std=c99 -Wno-long-long -O2 -msse4.1 -m64 $(DEBUG)
LDFLAGS = -s -static -T $(PNACL_TOOL)/x86_64-nacl/lib64/ldscripts/elf64_nacl.x.static -melf64_nacl \
	-L/usr/lib/zerovm -lzrt -lnetworking -lfs -lstdc++

GENNODE=generator.uint32_t
MANNODE=nodeman
SRCNODE=nodesrc
DSTNODE=nodedst

NEXES = $(GENNODE).nexe $(MANNODE).nexe $(SRCNODE).nexe $(DSTNODE).nexe
GENNODE_OBJECTS = generator.uint32_t.o
MANNODE_OBJECTS = comm.o bitonic_sort.o manager/main_man.o manager/histanlz.o manager/comm_man.o dsort.o sort.o
SRCNODE_OBJECTS = comm.o source/comm_src.o source/main_src.o cpuid.o bitonic_sort.o dsort.o sort.o
DSTNODE_OBJECTS = dest/main_dst.o dest/comm_dst.o comm.o dsort.o sort.o

all: cleanlog prepare $(NEXES) 

$(GENNODE).nexe: $(GENNODE_OBJECTS)
	$(CC) -o $@ $^ $(LDFLAGS)

$(MANNODE).nexe: $(MANNODE_OBJECTS)
	$(CC) -o $@ $^ $(LDFLAGS)

$(SRCNODE).nexe: $(SRCNODE_OBJECTS)
	$(CC) -o $@ $^ $(LDFLAGS)

$(DSTNODE).nexe: $(DSTNODE_OBJECTS)
	$(CC) -o $@ $^ $(LDFLAGS)

cleanlog:
	@rm -f log/*.log
	
prepare: createdirs
	@./genmanifest.sh
 	
createdirs:
	@mkdir -p log data

clean: cleanlog 
	@rm -f $(NEXES)
	@rm -f $(GENNODE_OBJECTS) $(MANNODE_OBJECTS) $(SRCNODE_OBJECTS) $(DSTNODE_OBJECTS)
	@rm -f manifest/*.manifest
	@rm -f data/*.data




<|start_filename|>src/main/etag.h<|end_filename|>
/*
 * routines to calculate hashes. should be constructed from the command
 * line parser
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ETAG_H_
#define ETAG_H_

#include <stdint.h>
#include <glib.h>

/* compile time check if TAG_ENCRYPTION is specified and has sane value */
typedef char _1[TAG_ENCRYPTION];
typedef int _2[-(sizeof(_1) > G_CHECKSUM_SHA256)];

/* glib instead of macro have function returning digest size */
#define TAG_DIGEST_SIZE (8 * sizeof(_1) * sizeof(_1) + 32)
#define TAG_ENGINE_DISABLED "disabled"

/*
 * initialize and return the hash context or abort if failed
 * to avoid memory leak context must be freed after usage
 */
void *TagCtor();

/* deallocate tag context */
void TagDtor(void *ctx);

/*
 * calculates digest from the context. can be used consequently
 * note: "digest" must have enough space to hold the digest
 */
void TagDigest(void *ctx, char *digest);

/* update etag with the given buffer */
void TagUpdate(void *ctx, const char *buffer, int64_t size);

#endif /* ETAG_H_ */


<|start_filename|>src/loader/sel_addrspace.h<|end_filename|>
/*
 * Copyright 2008 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* NaCl Simple/secure ELF loader (NaCl SEL) */

#ifndef SEL_ADDRSPACE_H_
#define SEL_ADDRSPACE_H_ 1

struct NaClApp; /* fwd */

/* deallocate all user memory (84gb) */
void FreeAddrSpace(struct NaClApp *nap);

/* allocate user memory chunk (84gb) */
void AllocAddrSpace(struct NaClApp *nap);

/* Apply memory protection to memory regions */
void MemoryProtection(struct NaClApp *nap);

#endif


<|start_filename|>tests/functional/fork/fork.c<|end_filename|>
/*
 * zvm trap fork test
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

int main()
{
  UNREFERENCED_VAR(errcount);
  fprintf(STDERR, "before fork()\n");
  zvm_fork();

  /* this part will be run in forked session */
  printf("stdout: after fork()\n");
  fprintf(STDERR, "after fork()\n");
  return 0;
}


<|start_filename|>src/syscalls/syscall_hook.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * restore trusted context and call trap()
 */
#include "src/syscalls/switch_to_app.h"
#include "src/syscalls/trap.h"

/* serve trap invoked from the untrusted code */
NORETURN void SyscallHook()
{
  struct NaClApp *nap;
  uintptr_t tramp_ret;
  size_t sysnum;
  uintptr_t sp_user;
  uintptr_t sp_sys;

  /* restore trusted side environment */
  nap = gnap; /* restore NaClApp object */
  sp_user = GetThreadCtxSp(nacl_user);
  sp_sys = sp_user;

  /*
   * sp_sys points to the top of user stack where there is a retaddr to
   * trampoline slot
   */
  tramp_ret = *(uintptr_t *)sp_sys;
  sysnum = (tramp_ret - (nap->mem_start + NACL_SYSCALL_START_ADDR))
      >> NACL_SYSCALL_BLOCK_SHIFT;

  /*
   * getting user return address (the address where we need to return after
   * system call) from the user stack. (see stack layout above)
   */
  nacl_user->prog_ctr = *(uintptr_t *)(sp_sys + NACL_USERRET_FIX);

  /*
   * Fix the user stack, throw away return addresses from the top of the stack.
   * After this fix, the first argument to a system call must be on the top of
   * the user stack (see user stack layout above)
   */
  sp_sys += NACL_SYSARGS_FIX;
  sp_user += NACL_SYSCALLRET_FIX;
  SetThreadCtxSp(nacl_user, sp_user);

  /* fail if nacl syscall received */
  ZLOGFAIL(sysnum != 0, EINVAL, "nacl syscall #%d received", sysnum);

  /*
   * syscall_args must point to the first argument of a system call.
   * System call arguments are placed on the untrusted user stack.
   */
  nacl_user->sysret = TrapHandler(nap, *(uint32_t*)sp_sys);

  /*
   * before switching back to user module, we need to make sure that the
   * user_ret is properly sandboxed.
   */
  nacl_user->prog_ctr = NaClSandboxCodeAddr(nap, nacl_user->prog_ctr);

  /* d'b: give control to the user side */
  ContextSwitch(nacl_user);
  ZLOGFAIL(1, EFAULT, "the unreachable has been reached");
}


<|start_filename|>tests/functional/demo/sizeof/sizeof.c<|end_filename|>
/*
 * sizeof of main types
 * differences between host (x86-64) and guest (nacl_x86-64)
 * type           host guest
 * long           8    4
 * long double    16   8
 * void*          8    4 (any pointer)
 */
#ifdef __ZEROVM__
#include "include/zvmlib.h"
#else
#include <stdio.h>
#endif

#define DUMP(s) printf("%24s = %lu\n", #s, s)
#define REM(s) printf("\n/* %22s */\n", #s)

typedef enum {_} ENUM;
typedef struct {int _;} STRUCT;
typedef union {int _;} UNION;

int main()
{
  REM(pointers);
  DUMP(sizeof(char*));
  DUMP(sizeof(unsigned char*));
  DUMP(sizeof(int*));
  DUMP(sizeof(unsigned int*));
  DUMP(sizeof(long*));
  DUMP(sizeof(unsigned long*));
  DUMP(sizeof(void*));
  DUMP(sizeof(float*));
  DUMP(sizeof(double*));
  DUMP(sizeof(long double*));
  DUMP(sizeof(long long*));

  REM(main types);
  DUMP(sizeof(char));
  DUMP(sizeof(unsigned char));
  DUMP(sizeof(int));
  DUMP(sizeof(unsigned int));
  DUMP(sizeof(long));
  DUMP(sizeof(unsigned long));
  DUMP(sizeof(void));
  DUMP(sizeof(float));
  DUMP(sizeof(double));
  DUMP(sizeof(long double));
  DUMP(sizeof(long long));

  REM(custom examples);
  DUMP(sizeof(ENUM));
  DUMP(sizeof(STRUCT));
  DUMP(sizeof(UNION));
  DUMP(sizeof(main));
  DUMP(sizeof(&main));
  DUMP(sizeof(&&label));
  DUMP(sizeof("1234567"));
  DUMP(sizeof('1'));
  DUMP(sizeof(1));
  DUMP(sizeof(1LL));
  DUMP(sizeof(char[0]));
label:
  return 0;
}


<|start_filename|>src/main/setup.c<|end_filename|>
/*
 * construct system manifest and host manifest
 * system/channels resources counters are also here
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <sys/resource.h>
#include <sys/mman.h>
#include "src/loader/sel_ldr.h"
#include "src/platform/sel_memory.h"
#include "src/main/setup.h"
#include "src/channels/channel.h"

static char *ztrace_name = NULL;
static GTimer *timer = NULL;
static FILE *ztrace_log = NULL;
static GString *ztrace_buf = NULL;
static double ztrace_chrono = 0;

void ZTraceCtor(const char *name)
{
  /* set ztrace file name */
  if(ztrace_name == NULL && name == NULL) return;
  if(ztrace_name == NULL)
  {
    ZLOGFAIL(!g_path_is_absolute(name), EFAULT,
        "ztrace path should be absolute: %s", name);
    ztrace_name = g_strdup(name);
  }

  /* open ztrace file */
  ztrace_log = fopen(ztrace_name, "a");
  ZLOGFAIL(ztrace_log == NULL, errno, "cannot open %s", ztrace_name);

  /* initialize ztrace buffer */
  ztrace_buf = g_string_sized_new(BIG_ENOUGH_STRING);
  g_string_append_printf(ztrace_buf, "[%d] %048o\n", getpid(), 0);

  /* set timer */
  ztrace_chrono = 0;
  timer = g_timer_new();
}

void ZTraceDtor(int mode)
{
  int result;

  if(timer == NULL || ztrace_log == NULL || ztrace_buf == NULL) return;

  /* drop buffer to log */
  if(mode != 0)
  {
    g_string_append_printf(ztrace_buf, "\n");
    result = fwrite(ztrace_buf->str, 1, ztrace_buf->len, ztrace_log);
    ZLOGIF(result != ztrace_buf->len, "only %d written to ztrace", result);
    fflush(ztrace_log);
    fclose(ztrace_log);
  }

  /* free resources */
  g_string_free(ztrace_buf, TRUE);
  g_timer_destroy(timer);
}

void ZTraceNameDtor()
{
  g_free(ztrace_name);
  ztrace_name = NULL;
}

void ZTrace(const char *msg)
{
  double timing;

  if(timer == NULL || ztrace_log == NULL || ztrace_buf == NULL) return;

  timing = g_timer_elapsed(timer, NULL);
  ztrace_chrono += timing;
  g_string_append_printf(ztrace_buf, "%.6f [%.6f]: %s\n", ztrace_chrono, timing, msg);
  g_timer_start(timer);
}

/* set timeout. by design timeout must be specified in manifest */
static void SetTimeout(struct Manifest *manifest)
{
  assert(manifest != NULL);

  ZLOGFAIL(manifest->timeout < 1, EFAULT, "invalid timeout %d", manifest->timeout);
  alarm(manifest->timeout);
}

/* lower zerovm priority */
static void LowerOwnPriority()
{
  ZLOGFAIL(setpriority(PRIO_PROCESS, 0, ZEROVM_PRIORITY) != 0,
      errno, "cannot set zerovm priority");
}

/*
 * give up privileges
 * TODO(d'b): instead of fail set group/user to nogroup/nobody
 */
static void GiveUpPrivileges()
{
  ZLOGFAIL(getuid() == 0, EPERM, "zerovm is not permitted to run as root");
}

void LastDefenseLine(struct Manifest *manifest)
{
  SetTimeout(manifest);
  LowerOwnPriority();
  GiveUpPrivileges();
}

void PreallocateUserMemory(struct NaClApp *nap)
{
  uintptr_t i;
  int64_t heap;
  void *p;

  assert(nap != NULL);
  assert(nap->manifest != NULL);

  /* quit function if "Memory" is not specified or invalid */
  ZLOGFAIL(nap->manifest->mem_size <= 0 || nap->manifest->mem_size > FOURGIG,
      ENOMEM, "invalid memory size");

  /* calculate user heap size (must be allocated next to the data_end) */
  p = (void*)ROUNDUP_64K(nap->data_end);
  heap = nap->manifest->mem_size - nap->stack_size;
  heap = ROUNDUP_64K(heap) - ROUNDUP_64K(nap->data_end);
  ZLOGFAIL(heap <= LEAST_USER_HEAP_SIZE, ENOMEM, "user heap size is too small");

  /* since 4gb of user space is already allocated just set protection to the heap */
  p = (void*)NaClUserToSys(nap, (uintptr_t)p);
  i = NaCl_mprotect(p, heap, PROT_READ | PROT_WRITE);
  ZLOGFAIL(0 != i, -i, "cannot set protection on user heap");
  nap->heap_end = NaClSysToUser(nap, (uintptr_t)p + heap);

  nap->mem_map[HeapIdx].size += heap;
  nap->mem_map[HeapIdx].end += heap;
}

/* TODO(d'b): move it to sel_addrspace */
/* should be kept in sync with api/zvm.h*/
struct ChannelSerialized
{
  int64_t limits[LimitsNumber];
  int64_t size;
  uint32_t type;
  uint32_t name;
};

/* should be kept in sync with api/zvm.h*/
struct UserManifestSerialized
{
  uint32_t heap_ptr;
  uint32_t heap_size;
  uint32_t stack_size;
  int32_t channels_count;
  uint32_t channels;
};

#define USER_PTR_SIZE sizeof(int32_t)
#define CHANNEL_STRUCT_SIZE sizeof(struct ChannelSerialized)
#define USER_MANIFEST_STRUCT_SIZE sizeof(struct UserManifestSerialized)

/* set pointer to user manifest */
static void SetUserManifestPtr(struct NaClApp *nap, void *mft)
{
  uintptr_t *p;

  p = (void*)NaClUserToSys(nap, FOURGIG - nap->stack_size - USER_PTR_SIZE);
  *p = NaClSysToUser(nap, (uintptr_t)mft);
}

/* align area to page(s) both bounds an protect. return pointer to (new) area */
static uintptr_t AlignAndProtect(uintptr_t area, int64_t size, int prot)
{
  uintptr_t page_ptr;
  uint64_t aligned_size;
  int code;

  page_ptr = ROUNDDOWN_64K(area);
  aligned_size = ROUNDUP_64K(size + (area - page_ptr));

  code = NaCl_mprotect((void*)page_ptr, aligned_size, prot);
  ZLOGFAIL(0 != code, code, "cannot protect 0x%x of %d bytes with %d",
      page_ptr, aligned_size, prot);
  return page_ptr;
}

/*
 * copy given name before the given area making it writable 1st
 * return a new pointer to name preceding area
 */
static void *CopyDown(void *area, char *name)
{
  int size = strlen(name) + 1;

  /* when the page crossed, append the new one */
  if((uintptr_t) area - ROUNDDOWN_64K((uintptr_t)area) < size)
    AlignAndProtect((uintptr_t) area - size, size, PROT_READ | PROT_WRITE);

  /* copy name down */
  return memcpy((char*)area - size, name, size);
}

/* protect user manifest and update mem_map */
static void ProtectUserManifest(struct NaClApp *nap, void *mft)
{
  uintptr_t page_ptr;
  uint64_t size;

  size = FOURGIG - nap->stack_size - NaClSysToUser(nap, (uintptr_t)mft);
  page_ptr = AlignAndProtect((uintptr_t) mft, size, PROT_READ);

  /* update mem_map */
  SET_MEM_MAP_IDX(nap->mem_map[SysDataIdx], "UserManifest",
      page_ptr, ROUNDUP_64K(size + ((uintptr_t)mft - page_ptr)), PROT_READ);

  /* its time to add hole to memory map */
  page_ptr = nap->mem_map[HeapIdx].end;
  size = nap->mem_map[SysDataIdx].start - nap->mem_map[HeapIdx].end;
  SET_MEM_MAP_IDX(nap->mem_map[HoleIdx], "Hole", page_ptr, size, PROT_NONE);

  /*
   * patch: change the heap size to correct value. the user manifest
   * contains the different heap start (it does not include r/w data)
   * TODO(d'b): fix it by adding a new memory region
   */
  nap->mem_map[HeapIdx].size =
      nap->mem_map[HeapIdx].end - nap->mem_map[HeapIdx].start;
}

void SetSystemData(struct NaClApp *nap)
{
  struct Manifest *manifest;
  struct ChannelSerialized *channels;
  struct UserManifestSerialized *user_manifest;
  void *ptr; /* pointer to the user manifest area */
  int64_t size;
  int i;

  assert(nap != NULL);
  assert(nap->manifest != NULL);
  assert(nap->manifest->channels != NULL);

  manifest = nap->manifest;

  /*
   * 1. calculate channels array size (w/o aliases)
   * 2. calculate user manifest size (w/o aliases)
   * 3. calculate pointer to user manifest
   * 4. calculate pointer to channels array
   */
  size = manifest->channels->len * CHANNEL_STRUCT_SIZE;
  size += USER_MANIFEST_STRUCT_SIZE + USER_PTR_SIZE;
  ptr = (void*)(FOURGIG - nap->stack_size - size);
  user_manifest = (void*)NaClUserToSys(nap, (uintptr_t)ptr);
  channels = (void*)((uintptr_t)&user_manifest->channels + USER_PTR_SIZE);

  /* make the 1st page of user manifest writable */
  CopyDown((void*)NaClUserToSys(nap, FOURGIG - nap->stack_size), "");
  ptr = user_manifest;

  /* initialize pointer to user manifest */
  SetUserManifestPtr(nap, user_manifest);

  /* serialize channels */
  for(i = 0; i < manifest->channels->len; ++i)
  {
    /* limits */
    int j;
    for(j = 0; j < LimitsNumber; ++j)
      channels[i].limits[j] = CH_CH(manifest, i)->limits[j];

    /* type and size */
    channels[i].type = (int32_t)CH_CH(manifest, i)->type;
    channels[i].size = channels[i].type == SGetSPut
        ? 0 : CH_CH(manifest, i)->size;

    /* alias */
    ptr = CopyDown(ptr, CH_CH(manifest, i)->alias);
    channels[i].name = NaClSysToUser(nap, (uintptr_t)ptr);
  }

  /* update heap_size in the user manifest */
  size = ROUNDDOWN_64K(NaClSysToUser(nap, (uintptr_t)ptr));
  size = MIN(nap->heap_end, size);
  user_manifest->heap_size = size - nap->break_addr;

  /* note that rw data merged with heap! */

  /* update memory map */
  nap->mem_map[HeapIdx].end = NaClUserToSys(nap, size);
  nap->mem_map[HeapIdx].size = user_manifest->heap_size;

  /* serialize the rest of the user manifest records */
  user_manifest->heap_ptr = nap->break_addr;
  user_manifest->stack_size = nap->stack_size;
  user_manifest->channels_count = manifest->channels->len;
  user_manifest->channels = NaClSysToUser(nap, (uintptr_t)channels);

  /* make the user manifest read only */
  ProtectUserManifest(nap, ptr);
}
/* }} */


<|start_filename|>src/main/etag.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include "src/main/zlog.h"
#include "src/main/etag.h"

void *TagCtor()
{
  GChecksum *ctx;

  ctx = g_checksum_new(TAG_ENCRYPTION);
  ZLOGFAIL(ctx == NULL, EFAULT, "error initializing tag context");
  return ctx;
}

void TagDtor(void *ctx)
{
  g_checksum_free(ctx);
}

void TagDigest(void *ctx, char *digest)
{
  const char *hex;
  GChecksum *tmp;

  tmp = g_checksum_copy(ctx);
  hex = g_checksum_get_string(tmp);
  strcpy(digest, hex);
  g_checksum_free(tmp);
}

void TagUpdate(void *ctx, const char *buffer, int64_t size)
{
  assert(buffer != NULL);

  if(ctx == NULL || size <= 0) return;
  g_checksum_update(ctx, (const guchar*)buffer, size);
}


<|start_filename|>tests/unit/manifest_setup_test.cc<|end_filename|>
/*
 * manifest_setup_test.cc
 *
 *  Created on: Nov 30, 2011
 *      Author: d'b
 */
#include <stdio.h>
#include <stdlib.h>
#include "gtest/gtest.h"
#include "api/zvm.h"
#include "src/loader/sel_ldr.h"

#include "src/main/manifest.h"
#include "src/main/manifest_setup.h"

/*
 * plan:
 * 1. construct maninfest from the file (write hardcoded data)
 * 2. call SystemManifestCtor() (main work is here, channels, memory manager e.t.c.)
 * 3. call HostManifestCtor()
 * 4. try UpdateSyscallsCount()
 * 5. try UpdateIOCounter()
 * 6. call SystemManifestDtor() (check files)
 * 7. call HostManifestDtor() (check report)
 */

#define MANIFEST_FILE "killme.manifest.txt"
#define NEXE_FILE "manifest.nexe"
#define INPUT_FILE "full.input.data"
#define FAKE_DATA "fake data just to extend a file over the zero size"
#define MANIFEST_DATA \
    "Nexe = test.nexe"\
    "NexeEtag = 12345678"\
    "CommandLine = arg1 arg2 arg3"\
    "Environment = key1, value1, key2, value2"\
    "NodeName = test_node, 1"\
    "NameServer = udp:127.0.0.1:54321"\
    \
    "== the channels section ============================================="\
    "Channel = /folder/debug, /dev/debug, 0, 0, 0, 999999, 999999"\
    "Channel = /dev/null, /dev/stdin, 0, 99999999, 99999999, 0, 0"\
    "Channel = /folder/stdout.log, /dev/stdout, 0, 0, 0, 99999999, 99999999"\
    "Channel = /folder/stderr.log, /dev/stderr, 0, 0, 0, 99999999, 99999999"\
    "Channel = tcp:2:, /dev/out/out, 0, 0, 0, 99999999, 99999999"\
    "Channel = tcp:2:, /dev/in/in, 0, 99999999, 99999999, 0, 0"\
    \
    "== the limits section ==============================================="\
    "MaxMem = 100663296"\
    "Timeout = 5"\
    "Version = 09082012"

// construct manifest, setup system_manifest and host_manifest
// todo(d'b): under construction
TEST(ManifestSetupTest, FullCase)
{
  struct NaClApp stat, *nap = &stat;

  // initialize nap
  int code = 1;
  memset(nap, 0, sizeof(*nap));
//  code &= DynArrayCtor(&nap->desc_tbl, 2);
//  code &= DynArrayCtor(&nap->threads, 2);
  code &= NaClVmmapCtor(&nap->mem_map);
  // todo(d'b): prepare memory: load nexe, allocate stack e.t.c
  if(code == 0) exit(1);

#define CREATE_FILE(name, data) \
  do {\
    FILE *f;\
    if((f = fopen(name, "w")) == NULL) return;\
    fprintf(f, data);\
    fclose(f);\
  } while(0)

  // initialize manifest
  CREATE_FILE(MANIFEST_FILE, MANIFEST_DATA);
  ManifestCtor(MANIFEST_FILE);
  EXPECT_EQ(0, ManifestCtor(MANIFEST_FILE));

  // several files from manifest must exist before setup
  CREATE_FILE(INPUT_FILE, FAKE_DATA);
  CREATE_FILE(NEXE_FILE, FAKE_DATA);

#undef CREATE_FILE

  // ### check constructed manifest validity
  EXPECT_STREQ("full.input.data", GetValueByKey((char*)"Input"));

  SystemManifestCtor(nap);

  // check constructed channels, and other fields one by one
}

//void AnswerManifestPut(struct NaClApp *nap, char *report)
//note: this test will fail when report form will change
//TEST(AnswerManifestPut_test, full_case)
//{
//  struct NaClApp *nap = allocate_nap();
//  char report[1024];
//
//  nap->host_manifest->ret_code = 0;
//  nap->host_manifest->etag = (char*)"0";
//  nap->host_manifest->user_ret_code = 0;
//  nap->host_manifest->content_type = (char*)"0";
//  nap->host_manifest->x_object_meta_tag = (char*)"0";
//
//  AnswerManifestPut(nap, report);
//  EXPECT_STREQ(
//      "ReportRetCode        =0\n"
//      "ReportEtag           =0\n"
//      "ReportUserRetCode    =0\n"
//      "ReportContentType    =0\n"
//      "ReportXObjectMetaTag =0\n", report);
//
//  free_nap(nap);

  // open report file
  // compare to expected string
//}

// main. no need to change
int main(int argc, char *argv[]) {
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}


<|start_filename|>src/loader/sel_rt.c<|end_filename|>
/*
 * Copyright 2009 The Native Client Authors.  All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "src/loader/sel_ldr.h"

nacl_reg_t GetStackPtr(void)
{
  nacl_reg_t rsp;

  asm("mov %%rsp, %0" : "=r" (rsp) : );
  return rsp;
}

uintptr_t GetThreadCtxSp(struct ThreadContext *th_ctx)
{
  return (uintptr_t)th_ctx->rsp;
}

void SetThreadCtxSp(struct ThreadContext *th_ctx, uintptr_t sp)
{
  th_ctx->rsp = (nacl_reg_t)sp;
}

int ThreadContextCtor(struct ThreadContext *ntcp,
                      struct NaClApp       *nap,
                      nacl_reg_t           prog_ctr,
                      nacl_reg_t           stack_ptr)
{
  ntcp->rax = 0;
  ntcp->rbx = 0;
  ntcp->rcx = 0;
  ntcp->rdx = 0;

  ntcp->rbp = stack_ptr; /* must be a valid stack addr! */
  ntcp->rsi = 0;
  ntcp->rdi = 0;
  ntcp->rsp = stack_ptr;

  ntcp->r8 = 0;
  ntcp->r9 = 0;
  ntcp->r10 = 0;
  ntcp->r11 = 0;

  ntcp->r12 = 0;
  ntcp->r13 = 0;
  ntcp->r14 = 0;
  ntcp->r15 = nap->mem_start;

  ntcp->prog_ctr = NaClUserToSys(nap, prog_ctr);
  ntcp->sysret = 0;

  return 1;
}


<|start_filename|>tests/functional/jail/jail.c<|end_filename|>
/*
 * functional test of trap functions jail / unjail
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

/*
 * should be large enough to hold one small function and
 * small enough to be less or equal than text segment size
 */
#define SIZE 0x10000

/* should pass validation */
static void good()
{
  ZTEST("good function");
}

/* should not pass validation */
static char bad[] = {0xf, 0x31, 0xc3};

static int test_function(void(*func)())
{
  char *p, *g;
  int i, result;

  /* allocate and align buffer */
  p = malloc(SIZE + PAGESIZE);
  ZFAIL(p != NULL);
  g = p;
  p = (char*)(uintptr_t)(ROUNDUP_64K((uintptr_t)p));

  /* store a good function to buffer */
  memcpy(p, func, SIZE);

  /* validate it */
  result = zvm_jail(p, SIZE);

  /* run it */
  if(result == 0) ((void(*)())p)();

  /*
   * release resources and check if they really available
   * warning: "for" can produce signal #11
   */
  ZFAIL(zvm_unjail(p, SIZE) == 0);
  for(i = 0; i < SIZE; ++i)
    p[i] = 0xdb;

  free(g);
  return result;
}

int main()
{
  ZTEST(test_function(good) == 0);
  ZTEST(test_function((void (*)())bad) != 0);

  ZREPORT;
  return 0; /* prevent warning */
}


<|start_filename|>tests/functional/demo/primal/primal.c<|end_filename|>
#include"include/zvmlib.h"
#define F for
#define I int
I P(I a){WRITE(STDOUT,&a,1);return a;}I m=1711276033,N=1,t[1<<25]={2},a,*p,i,s,c
,e=39717691,U=1;void g(I d, I h){F(i=s;i<1<<24;i*=2)d=d*1LL*d%m;F(p=t;p<t+N;p+=s
)F(i=s,c=1;i;i--)a=p[s]*(h?c:1LL)%m,p[s]=(m*1U+*p-a)*(h?1LL:c)%m,*p=(a*1U+*p)%m,
p++,c=c*1LL*d%m;}I main(){while(e/=2){N*=2;U=U*1LL*(m+1)/2%m;F(s=N;s/=2;)g(40,0)
;F(p=t;p<t+N;p++)*p=*p*1LL**p%m*U%m;F(s=1;s<N;s*=2)g(983983719,1);F(a=0,p=t;p<t+
N;)a+=*p<<(e&1),*p++=a%10,a/=10;}while(!*--p);F(t[0]--;p>=t;)P(48+*p--);return 0;}


<|start_filename|>src/main/setup.h<|end_filename|>
/*
 * zerovm help screen, "last line" defense and user manifest serializer
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SETUP_H__
#define SETUP_H__ 1

EXTERN_C_BEGIN

#include "src/loader/sel_ldr.h"

#define HELP_SCREEN /* update command line switches here */\
    "%s%s\033[1m\033[37mZeroVM tag%d\033[0m lightweight VM manager, build 2013-12-02\n"\
    "Usage: <manifest> [-v#] [-T#] [-stFPQ]\n\n"\
    " -s skip validation\n"\
    " -t <0..2> report to stdout/log/fast (default 0)\n"\
    " -v <0..3> log verbosity (default 0)\n"\
    " -F quit right before starting user session\n"\
    " -P disable channels space preallocation\n"\
    " -Q disable platform qualification\n"\
    " -T enable time/call tracing\n"

#define ZEROVM_PRIORITY 19

/* validator function from libvalidator.so */
int NaClSegmentValidates(uint8_t* mbase, size_t size, uint32_t vbase);

/*
 * "defense in depth". the last frontier of defense.
 * zerovm limits itself as much as possible
 */
void LastDefenseLine();

/* preallocate memory area of given size. abort if fail */
void PreallocateUserMemory(struct NaClApp *nap);

/* serialize system data to user space */
void SetSystemData(struct NaClApp *nap);

/* initialize "ztrace" service. if name == NULL exit silently */
void ZTraceCtor(const char *name);

/* close "ztrace" service. mode = 0 designed for "spawned" sessions */
void ZTraceDtor(int mode);

/* free ztrace file name */
void ZTraceNameDtor();

/* log the string with the next time delta */
void ZTrace(const char *msg);

EXTERN_C_END

#endif


<|start_filename|>tests/functional/channels/netcopy/Makefile<|end_filename|>
NAME=netcopy
CCFLAGS=-n -s -nostartfiles -nostdlib -fno-builtin

all: $(NAME).c
	@x86_64-nacl-gcc -o $(NAME).nexe $(CCFLAGS) -Wall -msse4.1 \
	-O2 -I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional $^ \
	$(ZEROVM_ROOT)/tests/functional/include/libzvmlib.a
	@python $(ZEROVM_ROOT)/ns_server.py 3 54321&
	@sed 's#PWD#$(PWD)#g' $(NAME)1.template > $(NAME)1.manifest
	@sed 's#PWD#$(PWD)#g' $(NAME)2.template > $(NAME)2.manifest
	@sed 's#PWD#$(PWD)#g' $(NAME)3.template > $(NAME)3.manifest
	@echo copier1 > nvram1
	@echo copier2 > nvram2
	@echo copier3 > nvram3
	@dd if=/dev/urandom of=input.data bs=1048576 count=32 2> /dev/null
	@$(ZEROVM_ROOT)/zerovm $(NAME)1.manifest&
	@$(ZEROVM_ROOT)/zerovm $(NAME)2.manifest&
	@$(ZEROVM_ROOT)/zerovm $(NAME)3.manifest

clean:
	rm -f $(NAME).nexe $(NAME).o *.log *.data *.manifest nvram* ztrace*


<|start_filename|>src/main/zlog.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include "src/main/report.h"
#include "src/main/zlog.h"

#define ZLOG_NAME "ZeroVM"
#define ZLOG_OPTIONS (LOG_PID)
#define ZLOG_FACILITY LOG_USER
#define ZLOG_PRIORITY LOG_ERROR
#define TAG_FORMAT "%s %d: "
#define LOG_MSG_LIMIT 0x1000

static int verbosity = 0;
static int zline = 0;
static const char *zfile = NULL;

void ZLogCtor(int v)
{
  verbosity = MAX(v, 0);
  openlog(ZLOG_NAME, ZLOG_OPTIONS, ZLOG_FACILITY);
}

void ZLogDtor()
{
  verbosity = 0;
  closelog();
}

void ZLogTag(const char *file, int line)
{
  zline = line;
  zfile = file;
}

#define ZLO(cond) \
  char msg[LOG_MSG_LIMIT];\
  int offset = 0;\
  va_list ap;\
\
  if(cond) return;\
\
  /* construct log message */\
  va_start(ap, fmt);\
  if(zfile != NULL)\
    offset = g_snprintf(msg, LOG_MSG_LIMIT, TAG_FORMAT, zfile, zline);\
  g_vsnprintf(msg + offset, LOG_MSG_LIMIT - offset, fmt, ap);\
  va_end(ap);\
\
  /* log the message */\
  syslog(ZLOG_PRIORITY, "%s", msg);

void ZLog(int priority, char *fmt, ...)
{
  ZLO(priority > verbosity);
  assert(priority != LOG_FATAL);
}

void LogIf(int cond, char const *fmt, ...)
{
  ZLO(!cond);
}

void FailIf(int cond, int err, char const *fmt, ...)
{
  ZLO(!cond);
  SetExitState(msg);
  ReportDtor(err);
}


<|start_filename|>debian/samples/hello/Makefile<|end_filename|>
PNACL_TOOL=/usr/lib/nacl/default-sdk/toolchain/linux_x86_glibc
NAME=hello
INCLUDE_FLAGS=-I/usr/include/zerovm

all: $(NAME).o
	$(PNACL_TOOL)/bin/x86_64-nacl-gcc -o $(NAME).nexe -s -static -T \
	$(PNACL_TOOL)/x86_64-nacl/lib64/ldscripts/elf64_nacl.x.static -melf64_nacl -m64 \
	$(DEBUG) $(NAME).o -L/usr/lib/zerovm -lzrt -lfs -lstdc++
	sed s@{ABS_PATH}@${CURDIR}/@g hello.manifest.template > hello.manifest
	zerovm -M$(NAME).manifest -v2

$(NAME).o:
	$(PNACL_TOOL)/bin/x86_64-nacl-gcc -o $(NAME).o -Wall \
	$(INCLUDE_FLAGS) $(MACROS_FLAGS) $(DEBUG) -c -Wno-long-long -O2 -msse4.1 -m64 $(NAME).c

clean:
	@rm -f $(NAME).nexe $(NAME).o *.log *.data *.back


<|start_filename|>src/loader/sel_rt.h<|end_filename|>
/*
 * Copyright 2009 The Native Client Authors.  All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Secure Runtime
 */
#ifndef SEL_RT_H__
#define SEL_RT_H__ 1

#include <inttypes.h>
#include "src/main/tools.h"

typedef uint64_t  nacl_reg_t;  /* general purpose register type */

struct ThreadContext {
  nacl_reg_t  rax,  rbx,  rcx,  rdx,  rbp,  rsi,  rdi,  rsp;
  /*          0x0,  0x8, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38 */
  nacl_reg_t  r8,     r9,  r10,  r11,  r12,  r13,  r14,  r15;
  /*          0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 */
  nacl_reg_t  prog_ctr;  /* rip */
  /*          0x80 */
  nacl_reg_t  sysret;
  /*          0x88 */
};

uintptr_t GetThreadCtxSp(struct ThreadContext *th_ctx);

void SetThreadCtxSp(struct ThreadContext *th_ctx, uintptr_t sp);

/*
 * Argument passing convention in AMD64, from
 *
 *   http://www.x86-64.org/documentation/abi.pdf
 *
 * for system call parameters, are as follows.  All syscall arguments
 * are of INTEGER type (section 3.2.3).  They are assigned, from
 * left-to-right, to the registers
 *
 *   rdi, rsi, rdx, rcx, r8, r9
 *
 * and any additional arguments are passed on the stack, pushed onto
 * the stack in right-to-left order.  Note that this means that the
 * syscall with the maximum number of arguments, mmap, passes all its
 * arguments in registers.
 *
 * Argument passing convention for Microsoft, from wikipedia, is
 * different.  The first four arguments go in
 *
 *   rcx, rdx, r8, r9
 *
 * respectively, with the caller responsible for allocating 32 bytes
 * of "shadow space" for the first four arguments, an additional
 * arguments are on the stack.  Presumably this is to make stdargs
 * easier to implement: the callee can always write those four
 * registers to 8(%rsp), ..., 24(%rsp) resp (%rsp value assumed to be
 * at fn entry/start of prolog, before push %rbp), and then use the
 * effective address of 8(%rsp) as a pointer to an in-memory argument
 * list.  However, because this is always done, presumably called code
 * might treat this space as if it's part of the red zone, and it
 * would be an error to not allocate this stack space, even if the
 * called function is declared to take fewer than 4 arguments.
 *
 * Caller/callee saved
 *
 * - AMD64:
 *   - caller saved: rax, rcx, rdx, rdi, rsi, r8, r9, r10, r11
 *   - callee saved: rbx, rbp, r12, r13, r14, r15
 *
 * - Microsoft:
 *   - caller saved: rax, rcx, rdx, r8, r9, r10, r11
 *   - callee saved: rbx, rbp, rdi, rsi, r12, r13, r14, r15
 *
 * A conservative approach might be to follow microsoft and save more
 * registers, but the presence of shadow space will make assembly code
 * incompatible anyway, assembly code that calls must allocate shadow
 * space, but then in-memory arguments will be in the wrong location
 * wrt %rsp.
 */

nacl_reg_t GetStackPtr(void);

#endif /* SEL_RT_H__ */


<|start_filename|>tests/functional/include/zvmlib.c<|end_filename|>
/*
 * replacement for the glibc library (not portable, should be used with gcc)
 *
 * perhaps it would be wise to get rid of glibc usage completely.
 * by that and -nostdlib resulting nexe will contain no extra code
 * or fail to build.
 *
 * update: if NOSTDLIB defined library will not use standard
 *         functions (glibc)
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Copyright (C) 2002 <NAME>. All rights reserved.
 * (full (c) stuff see below)
 */
#define LONG_MAX 2147483647L
#define LONG_MIN (-LONG_MAX - 1L)
#define ULONG_MAX (LONG_MAX * 2UL + 1UL)

#include "api/zvm.h" /* todo: change it to zvm.h */
#include "zvmlib.h"
#include "bget.h"
#include "printf.h"

/*
 * zerovm library functions. some of functions are wrappers over
 * glibc ones. it is safe since they are not using nacl syscalls
 */

/* safe to use glibc version */
inline void *memset(void *s, int c, size_t n)
{
  unsigned char* p = s;

  while(n--)
    *p++ = (unsigned char)c;
  return s;
}

inline void *malloc(size_t size)
{
  return bget(size);
}

inline void *calloc(size_t n, size_t size)
{
  return bgetz((long long int)n * size);
}

inline void *realloc(void *p, size_t size)
{
  return bgetr(p, size);
}

inline void free(void *p)
{
  /* prevent crash */
  if(p == NULL) return;

  brel(p);
}

inline void *memcpy(void *dst, const void *src, size_t n)
{
  char* d = dst;
  char* s = (char*)src;
  --s;
  --d;

  while(n--) *++d = *++s;
  return dst;
}

/* safe to use glibc version */
inline int memcmp(const void *s1, const void *s2, size_t n)
{
  if(!n) return 0;
  while(--n && *(char*)s1 == *(char*)s2)
  {
    s1 = (char*)s1 + 1;
    s2 = (char*)s2 + 1;
  }
  return (*((unsigned char*)s1) - *((unsigned char*)s2));
}

inline char *strchr(const char *s, int c)
{
  while(*s != (char)c)
    if(!*s++)
      return 0;
  return (char *)s;
}

inline char *strrchr(const char *s, int c)
{
  char *ret = 0;

  do {
    if(*s == (char)c)
      ret = (char*)s;
  } while(*s++);

  return ret;
}

inline int strcmp(const void *s1, const void *s2)
{
  while(*(char*)s1 && (*(char*)s1 == *(char*)s2))
    s1++, s2++;
  return *(const unsigned char*) s1 - *(const unsigned char*) s2;
}

inline char *strcpy(char *dst, const char *src)
{
  char *ret = dst;
  while ((*dst++ = *src++))
    ;
  return ret;
}

inline char *strcat(char *dst, const char *src)
{
  char *ret = dst;
  while (*dst)
    dst++;
  while ((*dst++ = *src++))
    ;
  return ret;
}

/* safe to use glibc version */
inline size_t strlen(const char *s)
{
  const char *p = s;
  while(*s)
    ++s;
  return s - p;
}

inline size_t strspn(const char *s1, const char *s2)
{
  size_t ret = 0;

  while(*s1 && strchr(s2, *s1++))
    ret++;
  return ret;
}

inline size_t strcspn(const char *s1, const char *s2)
{
  size_t ret = 0;

  while(*s1)
    if(strchr(s2, *s1))
      return ret;
    else
      s1++, ret++;
  return ret;
}

inline char *strtok(char *str, const char *delim)
{
  static char* p = 0;

  if(str)
    p = str;
  else if(!p)
    return 0;

  str = p + strspn(p, delim);
  p = str + strcspn(str, delim);
  if(p == str)
    return p = 0;

  p = *p ? *p = 0, p + 1 : 0;
  return str;
}

inline int isupper(int c)
{
  return (c >= 'A' && c <= 'Z');
}

inline int islower(int c)
{
  return (c >= 'a' && c <= 'z');
}

inline int toupper(int c)
{
  return islower(c) ? c - 'a' + 'A' : c;
}

inline int isalpha(int c)
{
  return (isupper(c) || islower(c));
}

inline int isspace(int c)
{
  return (c == ' ' || c == '\t' || c == '\v'
      || c == '\f' || c == '\n' || c == '\r');
}

inline int isdigit(int c)
{
  return (c >= '0' && c <= '9');
}

#define FL_UNSIGNED   1
#define FL_NEG        2
#define FL_OVERFLOW   4
#define FL_READDIGIT  8
static unsigned long strtoxl(const char *nptr, char **endptr, int ibase, int flags)
{
  const unsigned char *p;
  char c;
  unsigned long number;
  unsigned digval;
  unsigned long maxval;

  p = (const unsigned char *) nptr;
  number = 0;

  c = *p++;
  while(isspace(c))
    c = *p++;

  if(c == '-')
  {
    flags |= FL_NEG;
    c = *p++;
  }
  else if(c == '+')
  {
    c = *p++;
  }

  if(ibase < 0 || ibase == 1 || ibase > 36)
  {
    if(endptr)
      *endptr = (char *) nptr;
    return 0L;
  }
  else if(ibase == 0)
  {
    if(c != '0')
    {
      ibase = 10;
    }
    else if(*p == 'x' || *p == 'X')
    {
      ibase = 16;
    }
    else
    {
      ibase = 8;
    }
  }

  if(ibase == 16)
  {
    if(c == '0' && (*p == 'x' || *p == 'X'))
    {
      ++p;
      c = *p++;
    }
  }

  maxval = ULONG_MAX / ibase;

  for(;;)
  {
    if(isdigit(c))
    {
      digval = c - '0';
    }
    else if(isalpha(c))
    {
      digval = toupper(c) - 'A' + 10;
    }
    else
    {
      break;
    }

    if(digval >= (unsigned) ibase)
      break;

    flags |= FL_READDIGIT;

    if(number < maxval || (number == maxval && (unsigned long) digval <= ULONG_MAX % ibase))
    {
      number = number * ibase + digval;
    }
    else
    {
      flags |= FL_OVERFLOW;
    }

    c = *p++;
  }

  --p;

  if(!(flags & FL_READDIGIT))
  {
    if(endptr)
      p = (const unsigned char*)nptr;
    number = 0;
  }
  else if((flags & FL_OVERFLOW)
      || (!(flags & FL_UNSIGNED)
          && (((flags & FL_NEG) && (number < LONG_MIN))
              || (!(flags & FL_NEG) && (number > LONG_MAX)))))
  {

    if(flags & FL_UNSIGNED)
    {
      number = ULONG_MAX;
    }
    else if(flags & FL_NEG)
    {
      number = LONG_MIN;
    }
    else
    {
      number = LONG_MAX;
    }
  }

  if(endptr)
    *endptr = (char *) p;

  if(flags & FL_NEG)
    number = (unsigned long) (-(long) number);

  return number;
}

inline long int strtol(const char *p, char **end, int base)
{
  return (long) strtoxl(p, end, base, 0);
}

inline unsigned long strtoul(const char *p, char **end, int base)
{
  return strtoxl(p, end, base, FL_UNSIGNED);
}

inline long atol(const char *nptr)
{
  int c;
  int sign;
  long total;
  const unsigned char *p = (const unsigned char *) nptr;

  while(isspace(*p))
    ++p;

  c = *p++;
  sign = c;
  if(c == '-' || c == '+')
    c = *p++;

  total = 0;
  while(isdigit(c))
  {
    total = 10 * total + (c - '0');
    c = *p++;
  }

  if(sign == '-')
  {
    return -total;
  }
  else
  {
    return total;
  }
}

inline int atoi(const char *s)
{
  return (int)atol(s);
}

static unsigned long int seed = 1;
inline void srand(unsigned int s)
{
  seed = s;
}

inline int rand()
{
  seed = seed * 1103515245 + 12345;
  return (unsigned int)(seed/65536) % 32768;
}

/*
 * get handle by the channel alias. return -1 if failed
 * todo: replace it with open(), change dependent functions
 */
inline int handle(const char *alias)
{
  if(alias != NULL && *alias != '\0')
  {
    int i;
    for(i = 0; i < MANIFEST->channels_count; ++i)
      if(STRCMP(MANIFEST->channels[i].name, alias) == 0)
        return i;
  }

  return -1;
}

/* get command line and environment data from the channel */
static int get_nvram_data(char *buffer)
{
  int i = OPEN(ENVIRONMENT);

  if(i >= 0)
    i = zvm_pread(i, buffer, ENVIRONMENT_MAX_SIZE, 0);
  return i == ENVIRONMENT_MAX_SIZE || i < 1 ? -1 : i;
}

#define FAILIF(cond) if(cond) {free(strings); free(info); return (void*)0xFFFFFFD8;}
#define PARSE(buf) \
  for(buffer = strtok(buf, EOL); buffer; ++i)\
  {\
    /* check for end of section */\
    if(strcmp(buffer, END_OF_SECTION) == 0) break;\
    strcpy(strings, buffer);\
    info[i] = (uintptr_t)strings;\
    strings += strlen(buffer) + 1; /* +1 for '\0' */\
    buffer = strtok(NULL, EOL);\
  }

uint32_t *get_start_info()
{
  char buf[ENVIRONMENT_MAX_SIZE], *buffer = buf;
  char *strings = NULL;
  uint32_t *info = NULL;
  int i;

  /* get the data */
  i = get_nvram_data(buffer);
  FAILIF(i <= 0);

  /* allocate area to hold nvram information */
  info = calloc(i, sizeof strings);
  strings = calloc(i, sizeof *strings);
  FAILIF(info == NULL || strings == NULL);

  /* parse command line arguments */
  i = 1;
  PARSE(buffer);
  info[i] = 0;
  info[0] = i - 1;

  /* parse environment */
  ++i;
  PARSE(NULL);

  /* todo: buffers sizes adjustment disabled since bget reallocate is lame */
  return info;
}
#undef PARSE
#undef FAILIF

/* initializer of zlib (replaces glibc prologue) */
static void _init()
{
  /* setup memory manager */
  bpool(MANIFEST->heap_ptr, MANIFEST->heap_size);
}

/* the standard glibc prologue replacement */
/*
 * the standard glibc prologue replacement. command line arguments
 * and environment will be read from the "/dev/nvram" channel instead
 * of "info" passed as _start argument
 */
int main(int argc, char **argv, char **envp);
void _start(uint32_t *info)
{
  /* initialize zerovm library */
  _init();

  uint32_t *p = get_start_info();
  int argc = p[0];
  char **argv = (void*)&p[1];
  char **envp = (void*)&p[argc + 2];

  /* put marker to the bottom of the stack */
  *(uint64_t*)0xFF000000 = 0x716f74726f622764LLU;

  /* call the user main and exit to zerovm */
  zvm_exit(main(argc, argv, envp));
}

/*
 * strtol.c
 *
 * String to number conversion
 *
 * Copyright (C) 2002 <NAME>. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


<|start_filename|>api/zvm.h<|end_filename|>
/*
 * ZeroVM API. contains function prototypes, data structures,
 * macro definitions, types and constants
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ZVM_API_H__
#define ZVM_API_H__ 1

#include <stdint.h>

/* zerovm system calls */
enum TrapCalls
{
  TrapRead = 0x64616552,
  TrapWrite = 0x74697257,
  TrapJail = 0x6c69614a,
  TrapUnjail = 0x6c6a6e55,
  TrapExit = 0x74697845,
  TrapFork = 0x6b726f46
};

/* channel types */
enum ChannelType {
  SGetSPut, /* sequential read, sequential write */
  RGetSPut, /* random read, sequential write */
  SGetRPut, /* sequential read, random write */
  RGetRPut /* random read, random write */
};

/* channel limits */
enum ChannelLimits {
  GetsLimit,
  GetSizeLimit,
  PutsLimit,
  PutSizeLimit,
  LimitsNumber
};

/* channel descriptor */
struct ZVMChannel
{
  int64_t limits[LimitsNumber];
  int64_t size; /* 0 for sequential channels */
  enum ChannelType type;
  char *name;
};

/* system data available for the user */
struct UserManifest
{
  void *heap_ptr;
  uint32_t heap_size;
  uint32_t stack_size;
  int32_t channels_count;
  struct ZVMChannel *channels;
};

/* pointer to the user manifest (read only memory area) */
#define MANIFEST ((const struct UserManifest const *)*((uintptr_t*)0xFEFFFFFC))

/* trap pointer. internal helper. DO NOT use it! */
#define TRAP ((int32_t (*)(uint64_t*))0x10000)

/*
 * trap functions
 *
 * zvm_pread
 *   read from "offset" position of "desc" channel "size" bytes to "buffer"
 * zvm_pwrite
 *   write to "offset" position of "desc" channel "size" bytes from "buffer"
 * zvm_jail
 *   validate "size" bytes from "buffer" and (if ok) protect it with read/exec
 *   "buffer" should be 64kb aligned and point to heap
 * zvm_unjail
 *   protect "size" bytes from "buffer" with read/write
 *   "buffer" should be 64kb aligned and point to heap
 * zvm_exit
 *   terminate program with "code"
 * zvm_fork
 *   ask for fork (for further details see "daemon mode")
 *
 * all trap functions return -errno code if error encountered, otherwise
 * result equal to processed bytes or 0 (for (un)jail). exit does not return
 */
#define zvm_pread(desc, buffer, size, offset) \
  TRAP((uint64_t[]){TrapRead, 0, desc, (uintptr_t)buffer, size, offset})
#define zvm_pwrite(desc, buffer, size, offset) \
  TRAP((uint64_t[]){TrapWrite, 0, desc, (uintptr_t)buffer, size, offset})
#define zvm_jail(buffer, size) \
  TRAP((uint64_t[]){TrapJail, 0, (uintptr_t)buffer, size})
#define zvm_unjail(buffer, size) \
  TRAP((uint64_t[]){TrapUnjail, 0, (uintptr_t)buffer, size})
#define zvm_exit(code) TRAP((uint64_t[]){TrapExit, 0, code})
#define zvm_fork() TRAP((uint64_t[]){TrapFork})

#endif /* ZVM_API_H__ */


<|start_filename|>src/platform/signal.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <sys/mman.h>
#include "src/platform/signal.h"
#include "src/main/report.h"
#include "src/main/tools.h"
#include "src/loader/sel_ldr.h"

/*
 * This module is based on the Posix signal model. See:
 * http://www.opengroup.org/onlinepubs/009695399/functions/sigaction.html
 */

#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif

/*
 * TODO(noelallen) split these macros and conditional compiles
 * into architecture specific files. Bug #955
 */

/* Use 4K more than the minimum to allow breakpad to run. */
#define SIGNAL_STACK_SIZE (SIGSTKSZ + 4096)
#define STACK_GUARD_SIZE NACL_PAGESIZE

#define SIGNAL_COUNT ARRAY_SIZE(s_Signals)
static int s_Signals[] = {
  SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGFPE,
  SIGSEGV, SIGSTKFLT, SIGABRT, SIGXFSZ, SIGXCPU,
  /* in the future SIGHUP will be used to restart session */
  SIGHUP,
  /*
   * for sake of determinism zvm makes all possible to prevent any
   * i/o errors
   */
  SIGPIPE,
  /* reserved for the future */
  SIGALRM,
  SIGTERM,
  /* reserved for the snapshot engine */
  SIGPWR
};

static struct sigaction s_OldActions[SIGNAL_COUNT];
static void *signal_stack;
static int busy = 1;

static void SignalStackRegister(void *stack)
{
  /*
   * If we set up signal handlers, we must ensure that any thread that
   * runs untrusted code has an alternate signal stack set up.  The
   * default for a new thread is to use the stack pointer from the
   * point at which the fault occurs, but it would not be safe to use
   * untrusted code's %esp/%rsp value.
   */
  stack_t st;
  st.ss_size = SIGNAL_STACK_SIZE;
  st.ss_sp = ((uint8_t *) stack) + STACK_GUARD_SIZE;
  st.ss_flags = 0;
  ZLOGFAIL(sigaltstack(&st, NULL) == -1, errno, "Failed to register signal stack");
}

static void SignalStackUnregister(void)
{
  /*
   * Unregister the signal stack in case a fault occurs between the
   * thread deallocating the signal stack and exiting.  Such a fault
   * could be unsafe if the address space were reallocated before the
   * fault, although that is unlikely.
   */
  stack_t st;
  st.ss_size = 0;
  st.ss_sp = NULL;
  st.ss_flags = SS_DISABLE;
  ZLOGFAIL(sigaltstack(&st, NULL) == -1, errno, "Failed to unregister signal stack");
}

/*
 * Allocates a stack suitable for passing to SignalStackRegister(),
 * for use as a stack for signal handlers. This can be called in any
 * thread. Stores the result in *result;
 */
static void SignalStackAllocate(void **result)
{
  /*
   * We use mmap() to allocate the signal stack for two reasons:
   *
   * 1) By page-aligning the memory allocation (which malloc() does
   * not do for small allocations), we avoid allocating any real
   * memory in the common case in which the signal handler is never
   * run.
   *
   * 2) We get to create a guard page, to guard against the unlikely
   * occurrence of the signal handler both overrunning and doing so in
   * an exploitable way.
   */
  uint8_t *stack = mmap(NULL, SIGNAL_STACK_SIZE + STACK_GUARD_SIZE,
      PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  ZLOGFAIL(stack == MAP_FAILED, errno, "failed to allocate signal stack");

  /* We assume that the stack grows downwards. */
  ZLOGFAIL(-1 == mprotect(stack, STACK_GUARD_SIZE, PROT_NONE),
      errno, "Failed to mprotect() the stack guard page");

  *result = stack;
}

static void SignalStackFree(void *stack)
{
  assert(stack != NULL);
  ZLOGFAIL(munmap(stack, SIGNAL_STACK_SIZE + STACK_GUARD_SIZE) == -1,
      errno, "Failed to munmap() signal stack");
}

static void FindAndRunHandler(int sig, siginfo_t *info, void *uc)
{
  int i;

  if(SignalHandlerFind(sig, uc) != NACL_SIGNAL_SEARCH) return;

  /* If we need to keep searching, try the old signal handler */
  for(i = 0; i < SIGNAL_COUNT; i++)
  {
    /* signal cannot be handled */
    if(s_Signals[i] != sig)
    {
      char msg[SIGNAL_STRLEN];
      g_snprintf(msg, SIGNAL_STRLEN, "Signal %d failed to be handled", sig);
      SetExitState(msg);
      ReportDtor(EINTR);
    }

    /* If this is a real sigaction pointer call the old handler */
    if(s_OldActions[i].sa_flags & SA_SIGINFO)
    {
      s_OldActions[i].sa_sigaction(sig, info, uc);
      break;
    }

    /* otherwise check if it is a real signal pointer and call the old signal */
    if((s_OldActions[i].sa_handler != SIG_DFL) && (s_OldActions[i].sa_handler != SIG_IGN))
    {
      s_OldActions[i].sa_handler(sig);
      break;
    }
  }
}

static void SignalCatch(int sig, siginfo_t *info, void *uc)
{
  busy = 1;
  FindAndRunHandler(sig, info, uc);
}

/* Assert that no signal handlers are registered */
static void SignalAssertNoHandlers()
{
  int i;

  for(i = 0; i < SIGNAL_COUNT; i++)
  {
    int signum = s_Signals[i];
    struct sigaction sa;

    ZLOGFAIL(-1 == sigaction(signum, NULL, &sa), errno, "sigaction() call failed");

    ZLOGFAIL((sa.sa_flags & SA_SIGINFO) != 0 ? sa.sa_sigaction != NULL
        : (sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN), EFAULT,
        "A signal handler is registered for signal %d. Did Breakpad register this?", signum);
  }
}

void SignalHandlerInitPlatform()
{
  struct sigaction sa;
  int i;

  /* fail if another handler(s) already registered */
  SignalAssertNoHandlers();

  memset(&sa, 0, sizeof(sa));
  sigemptyset(&sa.sa_mask);
  sa.sa_sigaction = SignalCatch;
  sa.sa_flags = SA_ONSTACK | SA_SIGINFO;

  /* Mask all exceptions we catch to prevent re-entry */
  for(i = 0; i < SIGNAL_COUNT; i++)
    sigaddset(&sa.sa_mask, s_Signals[i]);

  /* Install all handlers */
  for(i = 0; i < SIGNAL_COUNT; i++)
    ZLOGFAIL(0 != sigaction(s_Signals[i], &sa, &s_OldActions[i]),
        errno, "Failed to install handler for %d", s_Signals[i]);

  /* allocate and register signal stack */
  SignalStackAllocate(&signal_stack);
  SignalStackRegister(signal_stack);
  busy = 0;
}

void SignalHandlerFiniPlatform()
{
  int i;

  /* Remove all handlers */
  for(i = 0; i < SIGNAL_COUNT; i++)
    sigaction(s_Signals[i], &s_OldActions[i], NULL);

  /* release signal stack if not busy */
  if(!busy)
  {
    SignalStackUnregister();
    SignalStackFree(signal_stack);
  }
}


<|start_filename|>src/loader/sel_ldr-inl.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * DO NOT INCLUDE EXCEPT FROM sel_ldr.h
 * THERE CANNOT BE ANY MULTIPLE INCLUSION GUARDS IN ORDER FOR
 * sel_ldr-inl.c TO WORK.
 */

/*
 * Routines to translate addresses between user and "system" or
 * service runtime addresses.  the *Addr* versions will return
 * kNaClBadAddress if the user address is outside of the user address
 * space, e.g., if the input addresses for *UserToSys* is outside of
 * (1<<nap->addr_bits), and correspondingly for *SysToUser* if the
 * input system address does not correspond to a user address.
 * Generally, the *Addr* versions are used when the addresses come
 * from untrusted usre code, and kNaClBadAddress would translate to an
 * EINVAL return from a syscall.  The *Range code ensures that the
 * entire address range is in the user address space.
 *
 * Note that just because an address is within the address space, it
 * doesn't mean that it is safe to acceess the memory: the page may be
 * protected against access.
 *
 * The non-*Addr* versions abort the program rather than return an
 * error indication.
 *
 * 0 is not a good error indicator, since 0 is a valid user address
 */

#include "src/main/zlog.h"

/* d'b: no checks, just does the work */
static INLINE uintptr_t NaClUserToSysAddrNullOkay
    (struct NaClApp *nap, uintptr_t uaddr)
{
  return uaddr + nap->mem_start;
}

static INLINE uintptr_t NaClUserToSys(struct NaClApp *nap, uintptr_t uaddr)
{
  ZLOGFAIL(0 == uaddr || ((uintptr_t) 1U << nap->addr_bits) <= uaddr, EFAULT,
      "uaddr 0x%08lx, addr space %d bits", uaddr, nap->addr_bits);
  return uaddr + nap->mem_start;
}

static INLINE uintptr_t NaClSysToUser(struct NaClApp *nap, uintptr_t sysaddr)
{
  ZLOGFAIL(sysaddr < nap->mem_start || nap->mem_start
      + ((uintptr_t) 1U << nap->addr_bits) <= sysaddr, EFAULT,
      "sysaddr 0x%08lx, mem_start 0x%08lx, addr space %d bits",
      sysaddr, nap->mem_start, nap->addr_bits);
  return sysaddr - nap->mem_start;
}

static INLINE uintptr_t NaClEndOfStaticText(struct NaClApp *nap)
{
  return nap->static_text_end;
}

static INLINE uintptr_t NaClSandboxCodeAddr(struct NaClApp *nap, uintptr_t addr)
{
  return (((addr & ~(((uintptr_t)NACL_INSTR_BLOCK_SIZE) - 1))
           & ((((uintptr_t) 1) << 32) - 1)) + nap->mem_start);
}


<|start_filename|>src/loader/sel_ldr.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Simple/secure ELF loader (NaCl SEL).
 *
 * notice: "NaCl" is here by historical reasons. in fact zvm only can
 * use binaries built with ZeroVM toolchain (former NaCl toolchain)
 *
 * This loader can only process ZeroVM object files as produced using
 * the ZeroVM toolchain.  Other ELF files will be rejected.
 *
 * The primary function, NaClAppLoadFile, parses an ELF file,
 * allocates memory, loads the relocatable image from the ELF file
 * into memory, and performs relocation.  NaClAppRun runs the
 * resultant program.
 */

#ifndef SEL_LDR_H_
#define SEL_LDR_H_ 1

#include <stdint.h>

/* from sel_ldr_x86.h */
#define NACL_DEFAULT_STACK_MAX (16 << 20) /* untrusted stack */
#define NACL_MAX_ADDR_BITS (32)
#define NACL_HALT_OPCODE   0xf4
#define NACL_HALT_LEN      1 /* length of halt instruction */

#include "src/platform/gio.h"
#include "src/main/config.h"
#include "src/loader/sel_rt.h"
#include "src/main/manifest.h"

EXTERN_C_BEGIN

/*
 * helper macro. _element should be nap->mem_map[index], _addr - block
 * address (bytes), _size - block size (bytes), _prot - block protection
 */
#define SET_MEM_MAP_IDX(_element, _name, _addr, _size, _prot) \
  do {\
    _element.name = _name;\
    _element.start = (_addr);\
    _element.end = (_addr) + (_size);\
    _element.size = (_size);\
    _element.prot = _prot;\
  } while(0)

enum MemMapIndices {
  LeftBumperIdx, /* includes NULL protector */
  TextIdx, /* includes trampoline */
  RODataIdx,
  HeapIdx, /* includes r/w data */
  HoleIdx,
  SysDataIdx,
  StackIdx,
  RightBumperIdx,
  MemMapSize
};

struct MemBlock {
  char      *name; /* block name */
  uintptr_t start; /* block start. system virtual address */
  uintptr_t end;   /* block end (for ease). system virtual address */
  size_t    size;  /* number of bytes */
  int       prot;  /* mprotect attribute */
};

struct NaClApp {
  /*
   * public, user settable prior to app start.
   */
  uint8_t                   addr_bits;
  uintptr_t                 stack_size;
  /*
   * stack_size is the maximum size of the (main) stack.  The stack
   * memory is eager allocated (mapped in w/o MAP_NORESERVE) so
   * there must be enough swap space; page table entries are not
   * populated (no MAP_POPULATE), so actual accesses will likely
   * incur page faults.
   */

  /*
   * Determined at load time; OS-determined.
   * Read-only after load, so accesses do not require locking.
   */
  uintptr_t                 mem_start;

  /* only used for ET_EXEC:  for CS restriction */
  uintptr_t                 static_text_end;  /* relative to mem_start */
  /* ro after app starts. memsz from phdr */

  /*
   * The dynamic code area follows the static code area.  These fields
   * are both set to static_text_end if the dynamic code area has zero
   * size.
   */
  uintptr_t                 dynamic_text_start;
  uintptr_t                 dynamic_text_end;

  /*
   * rodata_start and data_start may be 0 if these segments are not
   * present in the executable.
   */
  uintptr_t                 rodata_start;  /* initialized data, ro */
  uintptr_t                 data_start;    /* initialized data/bss, rw */
  /*
   * Various region sizes must be a multiple of NACL_MAP_PAGESIZE
   * before the NaCl app can run.  The sizes from the ELF file
   * (p_filesz field) might not be -- that would waste space for
   * padding -- and while we could use p_memsz to specify padding, but
   * we will record the virtual addresses of the start of the segments
   * and figure out the gap between the p_vaddr + p_filesz of one
   * segment and p_vaddr of the next to determine padding.
   */

  uintptr_t                 data_end;
  /* see break_addr below */

  /*
   * initial_entry_pt is the first address in untrusted code to jump
   * to.  When using the IRT (integrated runtime), this is provided by
   * the IRT library, and user_entry_pt is the entry point in the user
   * executable.  Otherwise, initial_entry_pt is in the user
   * executable and user_entry_pt is zero.
   */
  uintptr_t                 initial_entry_pt;
  uintptr_t                 user_entry_pt;

  /* user memory map */
  struct MemBlock           mem_map[MemMapSize];

  uintptr_t                 break_addr; /* user addr */
  /* data_end <= break_addr is an invariant */

  uintptr_t                 heap_end; /* end of user heap */
  struct Manifest           *manifest;
};

/* global variables */
struct ThreadContext    *nacl_user; /* user registers storage */
struct ThreadContext    *nacl_sys;  /* zerovm registers storage */
struct NaClApp              *gnap;      /* pointer to global NaClApp object */

/*
 * Initializes a NaCl application with the default parameters.
 * nap is a pointer to the NaCl object that is being filled in.
 * assumes all fields already set to zeroes
 */
void NaClAppCtor(struct NaClApp *nap);

/* free app memory and globals */
void NaClAppDtor(struct NaClApp *nap);

/*
 * Loads a NaCl ELF file into memory in preparation for running it.
 *
 * gp is a pointer to a generic I/O object and should be a GioMem with
 * a memory buffer containing the file read entirely into memory if
 * the file system might be subject to race conditions (e.g., another
 * thread / process might modify a downloaded NaCl ELF file while we
 * are loading it here).
 *
 * nap is a pointer to the NaCl object that is being filled in.  it
 * should be properly constructed via NaClAppCtor.
 *
 * note: it may be necessary to flush the icache if the memory
 * allocated for use had already made it into the icache from another
 * NaCl application instance, and the icache does not detect
 * self-modifying code / data writes and automatically invalidate the
 * cache lines.
 */
void AppLoadFile(struct Gio *gp, struct NaClApp *nap);

/* TODO(d'b): replace spaces with format options and use macro */
void PrintAppDetails(struct NaClApp *nap, int verbosity);

/*
 * set an empty user stack and other context, then pass
 * control to user code
 */
void CreateSession(struct NaClApp *nap);

/*
 * Install syscall trampolines at all possible well-formed entry points
 * within the trampoline pages.  Many of these syscalls will correspond
 * to unimplemented system calls and will just abort the program.
 */
void LoadTrampoline(struct NaClApp *nap);

static const uintptr_t kNaClBadAddress = (uintptr_t) -1;

#include "src/loader/sel_ldr-inl.h"

void FillMemoryRegionWithHalt(void *start, size_t size);

void FreeDispatchThunk();

int ThreadContextCtor(struct ThreadContext  *ntcp,
                      struct NaClApp        *nap,
                      nacl_reg_t            prog_ctr,
                      nacl_reg_t            stack_ptr);

EXTERN_C_END

#endif  /* SEL_LDR_H_ */


<|start_filename|>src/loader/elf_util.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/main/tools.h"
#include "src/loader/elf.h"
#include "src/loader/elf_util.h"

/* private */
struct ElfImage {
  Elf_Ehdr  ehdr;
  Elf_Phdr  phdrs[NACL_MAX_PROGRAM_HEADERS];
  int       loadable[NACL_MAX_PROGRAM_HEADERS];
};

enum PhdrCheckAction {
  PCA_NONE,
  PCA_TEXT_CHECK,
  PCA_RODATA,
  PCA_DATA,
  PCA_IGNORE  /* ignore this segment. */
};

struct PhdrChecks {
  Elf_Word                  p_type;
  Elf_Word                  p_flags;  /* rwx */
  enum PhdrCheckAction  action;
  int                       required;  /* only for text for now */
  Elf_Addr                  p_vaddr;  /* if non-zero, vaddr must be this */
};

/*
 * Other than empty segments, these are the only ones that are allowed.
 */
static const struct PhdrChecks phdr_check_data[] = {
  /* phdr */
  { PT_PHDR, PF_R, PCA_IGNORE, 0, 0, },
  /* text */
  { PT_LOAD, PF_R|PF_X, PCA_TEXT_CHECK, 1, NACL_TRAMPOLINE_END, },
  /* rodata */
  { PT_LOAD, PF_R, PCA_RODATA, 0, 0, },
  /* data/bss */
  { PT_LOAD, PF_R|PF_W, PCA_DATA, 0, 0, },
  /* tls */
  { PT_TLS, PF_R, PCA_IGNORE, 0, 0},

  /*
   * allow optional GNU stack permission marker, but require that the
   * stack is non-executable.
   */
  { PT_GNU_STACK, PF_R|PF_W, PCA_NONE, 0, 0, },
  /* ignored segments */
  { PT_DYNAMIC, PF_R, PCA_IGNORE, 0, 0},
  { PT_INTERP, PF_R, PCA_IGNORE, 0, 0},
  { PT_NOTE, PF_R, PCA_IGNORE, 0, 0},
  { PT_GNU_EH_FRAME, PF_R, PCA_IGNORE, 0, 0},
  { PT_GNU_RELRO, PF_R, PCA_IGNORE, 0, 0},
  { PT_NULL, PF_R, PCA_IGNORE, 0, 0},
};

#define DUMP(m, f) ZLOGS(loglevel, #m " = %" f, elf_hdr->m)
static void DumpElfHeader(int loglevel, const Elf_Ehdr *elf_hdr)
{
  ZLOGS(loglevel, "%020o (Elf header) %020o", 0, 0);

  DUMP(e_ident+1, ".3s");
  DUMP(e_type, "#x");
  DUMP(e_machine, "#x");
  DUMP(e_version, "#x");
  DUMP(e_entry, "#x");
  DUMP(e_phoff, "#x");
  DUMP(e_shoff, "#x");
  DUMP(e_flags, "#x");
  DUMP(e_ehsize, "#x");
  DUMP(e_phentsize, "#x");
  DUMP(e_phnum, "#x");
  DUMP(e_shentsize, "#x");
  DUMP(e_shnum, "#x");
  DUMP(e_shstrndx, "#x");
 ZLOGS(loglevel, "sizeof(Elf32_Ehdr) = 0x%x", (int) sizeof *elf_hdr);
}
#undef DUMP

#define DUMP(mem, f) ZLOGS(loglevel, "%s: %" f, #mem, phdr->mem)
static void DumpElfProgramHeader(int loglevel, const Elf_Phdr *phdr)
{
  DUMP(p_type, "x");
  DUMP(p_offset, "x");
  DUMP(p_vaddr, "x");
  DUMP(p_paddr, "x");
  DUMP(p_filesz, "x");
  DUMP(p_memsz, "x");
  DUMP(p_flags, "x");
  ZLOGS(loglevel, " (%s %s %s)",
      (phdr->p_flags & PF_R) ? "PF_R" : "",
      (phdr->p_flags & PF_W) ? "PF_W" : "",
      (phdr->p_flags & PF_X) ? "PF_X" : "");
  DUMP(p_align, "x");
}
#undef  DUMP

void ValidateElfHeader(const struct ElfImage *image)
{
  const Elf_Ehdr *hdr = &image->ehdr;

  ZLOGFAIL(memcmp(hdr->e_ident, ELFMAG, SELFMAG), ENOEXEC, "bad elf magic");
  ZLOGFAIL(ELFCLASS64 != hdr->e_ident[EI_CLASS], ENOEXEC, "bad elf class");
  ZLOGFAIL(ET_EXEC != hdr->e_type, ENOEXEC, "non executable");
  ZLOGFAIL(EM_EXPECTED_BY_NACL != hdr->e_machine, ENOEXEC,
      "bad machine: %x", hdr->e_machine);
  ZLOGFAIL(EV_CURRENT != hdr->e_version, ENOEXEC, "bad elf version: %x", hdr->e_version);
}

void ValidateProgramHeaders(
  struct ElfImage     *image,
  uint8_t             addr_bits,
  uintptr_t           *static_text_end,
  uintptr_t           *rodata_start,
  uintptr_t           *rodata_end,
  uintptr_t           *data_start,
  uintptr_t           *data_end,
  uintptr_t           *max_vaddr) {
    /*
     * Scan phdrs and do sanity checks in-line.  Verify that the load
     * address is NACL_TRAMPOLINE_END, that we have a single text
     * segment.  Data and TLS segments are not required, though it is
     * hard to avoid with standard tools, but in any case there should
     * be at most one each.  Ensure that no segment's vaddr is outside
     * of the address space.  Ensure that PT_GNU_STACK is present, and
     * that x is off.
     */
  const Elf_Ehdr      *hdr = &image->ehdr;
  int seen_seg[ARRAY_SIZE(phdr_check_data)] = {0};
  int                 segnum;
  const Elf_Phdr      *php;
  size_t              j;

  *max_vaddr = NACL_TRAMPOLINE_END;

  /* phdr_check_data is small, so O(|check_data| * nap->elf_hdr.e_phum) is ok */
  ZLOGS(LOG_DEBUG, "Validating program headers");
  for(segnum = 0; segnum < hdr->e_phnum; ++segnum)
  {
    php = &image->phdrs[segnum];
    ZLOGS(LOG_INSANE, "Looking at segment %d, type 0x%x, p_flags 0x%x",
        segnum, php->p_type, php->p_flags);

    if(0 == php->p_memsz)
    {
      /* We will not load this segment */
      ZLOGS(LOG_INSANE, "Ignoring empty segment");
      continue;
    }

    for(j = 0; j < ARRAY_SIZE_SAFE(phdr_check_data); ++j)
    {
      if(php->p_type == phdr_check_data[j].p_type
          && php->p_flags == phdr_check_data[j].p_flags) break;
    }

    ZLOGFAIL(j == ARRAY_SIZE_SAFE(phdr_check_data), ENOEXEC, "Segment %d "
        "is of unexpected type 0x%x, flag 0x%x", segnum, php->p_type, php->p_flags);

    ZLOGS(LOG_INSANE, "Matched phdr_check_data[%d]", j);
    ZLOGFAIL(seen_seg[j], ENOEXEC, "Segment %d is a type that has been seen", segnum);
    seen_seg[j] = 1;

    if(PCA_IGNORE == phdr_check_data[j].action)
    {
      ZLOGS(LOG_INSANE, "Ignoring");
      continue;
    }

    /* We will load this segment later. Do the sanity checks. */
    ZLOGFAIL(0 != phdr_check_data[j].p_vaddr && (phdr_check_data[j].p_vaddr
        != php->p_vaddr), ENOEXEC, "Segment %d: bad virtual address: 0x%08x, "
        "expected 0x%08x", segnum, php->p_vaddr, phdr_check_data[j].p_vaddr);

    ZLOGFAIL(php->p_vaddr < NACL_TRAMPOLINE_END, ENOEXEC,
        "Segment %d: virtual address 0x%08x too low", segnum, php->p_vaddr);

    /*
     * integer overflow?  Elf_Addr and Elf_Word are uint32_t or
     * uint64_t, so the addition/comparison is well defined.
     */
    ZLOGFAIL(php->p_vaddr + php->p_memsz < php->p_vaddr, ENOEXEC,
        "Segment %d: p_memsz caused integer overflow", segnum);

    ZLOGFAIL(php->p_vaddr + php->p_memsz >= ((Elf_Addr)1U << addr_bits), ENOEXEC,
        "Segment %d: too large, ends at 0x%08x", segnum, php->p_vaddr + php->p_memsz);

    ZLOGFAIL(php->p_filesz > php->p_memsz, ENOEXEC, "Segment %d: file size 0x%08x "
        "larger than memory size 0x%08x", segnum, php->p_filesz, php->p_memsz);

    /* record our decision that we will load this segment */
    image->loadable[segnum] = 1;

    /*
     * NACL_TRAMPOLINE_END <= p_vaddr
     *                     <= p_vaddr + p_memsz
     *                     < ((uintptr_t) 1U << nap->addr_bits)
     */
    if(*max_vaddr < php->p_vaddr + php->p_memsz)
      *max_vaddr = php->p_vaddr + php->p_memsz;

    switch(phdr_check_data[j].action)
    {
      case PCA_TEXT_CHECK:
        ZLOGFAIL(0 == php->p_memsz, ENOEXEC, FAILED_MSG);
        *static_text_end = NACL_TRAMPOLINE_END + php->p_filesz;
        break;
      case PCA_RODATA:
        *rodata_start = php->p_vaddr;
        *rodata_end = php->p_vaddr + php->p_memsz;
        break;
      case PCA_DATA:
        *data_start = php->p_vaddr;
        *data_end = php->p_vaddr + php->p_memsz;
        break;
      case PCA_NONE:
      case PCA_IGNORE:
        break;
    }
  }

  /* check if ELF executable missing a required segment (text) */
  for(j = 0; j < ARRAY_SIZE_SAFE(phdr_check_data); ++j)
    ZLOGFAIL(phdr_check_data[j].required && !seen_seg[j], ENOEXEC, FAILED_MSG);

  /*
   * Memory allocation will use NaClRoundPage(nap->break_addr), but
   * the system notion of break is always an exact address.  Even
   * though we must allocate and make accessible multiples of pages,
   * the linux-style brk system call (which returns current break on
   * failure) permits an arbitrarily aligned address as argument.
   */
}

struct ElfImage *ElfImageNew(struct Gio *gp)
{
  struct ElfImage *result;
  struct ElfImage image;
  int             cur_ph;

  memset(image.loadable, 0, sizeof image.loadable);

  /* fail if could not seek to beginning of Gio object containing program */
  ZLOGFAIL(-1 == (*gp->vtbl->Seek)(gp, 0, 0), EIO, FAILED_MSG);

  /* fail if could not load elf headers*/
  ZLOGFAIL((*gp->vtbl->Read)(gp, &image.ehdr, sizeof image.ehdr) != sizeof image.ehdr,
      EIO, FAILED_MSG);

  DumpElfHeader(LOG_INSANE, &image.ehdr);

  /* read program headers. fail if too many prog headers */
  ZLOGFAIL(image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS, ENOEXEC, FAILED_MSG);

  /* fail if ELF program header size too small */
  ZLOGFAIL(image.ehdr.e_phentsize < sizeof image.phdrs[0], ENOEXEC,
      "bad prog headers size. image.ehdr.e_phentsize = 0x%x, sizeof "
      "image.phdrs[0] = 0x%x", image.ehdr.e_phentsize, sizeof image.phdrs[0]);

  /*
   * NB: cast from e_phoff to off_t may not be valid, since off_t can be
   * smaller than Elf64_off, but since invalid values will be rejected
   * by Seek() the cast is safe (cf bsy). fail if cannot seek tp prog headers
   */
  ZLOGFAIL((*gp->vtbl->Seek)(gp, (off_t)image.ehdr.e_phoff, SEEK_SET) == (off_t)-1,
      EIO, FAILED_MSG);

  /* fail if cannot load tp prog headers */
  ZLOGFAIL((size_t)(*gp->vtbl->Read)(gp, &image.phdrs[0], image.ehdr.e_phnum * sizeof
      image.phdrs[0]) != (image.ehdr.e_phnum * sizeof image.phdrs[0]), EIO, FAILED_MSG);

  ZLOGS(LOG_INSANE, "%020o (elf segments) %020o", 0, 0);
  for(cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph)
    DumpElfProgramHeader(LOG_INSANE, &image.phdrs[cur_ph]);

  /* we delay allocating till the end to avoid cleanup code */
  /* fail if not enough memory for image meta data */
  result = g_malloc(sizeof image);
  ZLOGFAIL(result == NULL, ENOMEM, FAILED_MSG);

  memcpy(result, &image, sizeof image);
  return result;
}

void ElfImageLoad(const struct ElfImage *image,
    struct Gio *gp, uint8_t addr_bits, uintptr_t mem_start)
{
  int               segnum;
  uintptr_t         paddr;
  uintptr_t         end_vaddr;

  for(segnum = 0; segnum < image->ehdr.e_phnum; ++segnum)
  {
    const Elf_Phdr *php = &image->phdrs[segnum];

    /* did we decide that we will load this segment earlier? */
    if(!image->loadable[segnum]) continue;

    ZLOGS(LOG_INSANE, "loading segment %d", segnum);

    if(0 == php->p_filesz)
    {
      ZLOGS(LOG_INSANE, "zero-sized segment. ignoring...");
      continue;
    }
    end_vaddr = php->p_vaddr + php->p_filesz;

    /* integer overflow? */
    ZLOGFAIL(end_vaddr < php->p_vaddr, EFAULT,
        "parameter error should have been detected already");

    /*
     * is the end virtual address within the NaCl application's
     * address space?  if it is, it implies that the start virtual
     * address is also.
     */
    ZLOGFAIL(end_vaddr >= ((uintptr_t)1U << addr_bits), EFAULT,
        "parameter error should have been detected already");

    paddr = mem_start + php->p_vaddr;

    ZLOGS(LOG_INSANE, "Seek to position %d (0x%x)", php->p_offset, php->p_offset);

    /*
     * NB: php->p_offset may not be a valid off_t on 64-bit systems, but
     * in that case Seek() will error out.
     * d'b: fail if ELF executable segment header parameter error
     */
    ZLOGFAIL((*gp->vtbl->Seek)(gp, (off_t)php->p_offset, SEEK_SET) == (off_t)-1,
        ENOEXEC, "seek failure segment %d", segnum);

    ZLOGS(LOG_INSANE, "Reading %d (0x%x) bytes to address 0x%x",
        php->p_filesz, php->p_filesz, paddr);

    ZLOGFAIL((Elf_Word)(*gp->vtbl->Read)(gp, (void *)paddr, php->p_filesz) != php->p_filesz,
        ENOEXEC, "load failure segment %d", segnum);
    /* region from p_filesz to p_memsz should already be zero filled */
  }
}

void ElfImageDelete(struct ElfImage *image)
{
  g_free(image);
}

uintptr_t ElfImageGetEntryPoint(const struct ElfImage *image)
{
  return image->ehdr.e_entry;
}


<|start_filename|>src/syscalls/snapshot.h<|end_filename|>
/*
 * (re)store session engine
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SNAPSHOT_H_
#define SNAPSHOT_H_

/* load session from given image. 0: success, -1: failed */
int LoadSession(struct NaClApp *nap, const char *name);

/* store session to image "Save". 0: success, -1: failed */
int SaveSession(struct NaClApp *nap);

#endif /* SNAPSHOT_H_ */


<|start_filename|>tests/functional/demo/calloc/calloc.c<|end_filename|>
/*
 * calloc test (it is not hypervisor test, but zvmlib)
 */
#include "include/zvmlib.h"

#define SIZE 256*1024*1024 /* 256mb */
#define PATTERN 0xDB
#define FAILIF(cond, msg) if(cond) { printf("%s\n", msg); return 1; }

int main(int argc, char **argv)
{
  int i;
  uint8_t *p = calloc(SIZE, sizeof *p);

  /* memory allocated? */
  FAILIF(p == NULL, "memory allocation error");

  /* heap info */
  printf("memory allocated at 0x%X\n", (uintptr_t)p);
  printf("heap_ptr = 0x%X, heap_size = %d\n",
      (uintptr_t)MANIFEST->heap_ptr, MANIFEST->heap_size);

  /* set allocated buffer to pattern */
  memset(p, PATTERN, SIZE);
  printf("memory set to 0x%X pattern\n", PATTERN);

  /* free and calloc again */
  free(p);
  p = calloc(SIZE, sizeof *p);

  /* check if buffer is populated with 0s again */
  for(i = 0; i < SIZE; ++i)
    FAILIF(p[i] != 0, "test failed. invalid pattern found");

  printf("pattern tested successfully\n");
  free(p);
  return 0;
}


<|start_filename|>tests/functional/include/bget.c<|end_filename|>
/*

 B G E T

 Buffer allocator

 Designed and implemented in April of 1972 by <NAME>, based on the
 Case Algol OPRO$ algorithm implemented in 1966.

 Reimplemented in 1975 by <NAME> for the Interdata 70.
 Reimplemented in 1977 by <NAME> for the Marinchip 9900.
 Reimplemented in 1982 by <NAME> for the Intel 8080.

 Portable C version implemented in September of 1990 by an older, wiser
 instance of the original implementor.

 Souped up and/or weighed down  slightly  shortly  thereafter  by  <NAME>.

 AMIX  edition, including the new compaction call-back option, prepared
 by <NAME> in July of 1992.

 Bug in built-in test program fixed, ANSI compiler warnings eradicated,
 buffer pool validator  implemented,  and  guaranteed  repeatable  test
 added by <NAME> in October of 1995.

 This program is in the public domain.

 d'b: settings ifdefs changed to ifs. 0 or undefined means disabled setting.
 doc removed. tests related code removed. the code customized for embedded
 applications. not so funny shit removed.

 BGET CONFIGURATION
 ==================
 */

#define SizeQuant   4 /* Buffer allocation size quantum:
           all buffers allocated are a
           multiple of this size.  This
           MUST be a power of two. */

#define BufStats    1 /* Define this symbol to enable the
           bstats() function which calculates
           the total free space in the buffer
           pool, the largest available
           buffer, and the total space
           currently allocated. */

#define FreeWipe    0 /* Wipe free buffers to a guaranteed
           pattern of garbage to trip up
           miscreants who attempt to use
           pointers into released buffers. */


#define BestFit     0 /* Use a best fit algorithm when
           searching for space for an
           allocation request.  This uses
           memory more efficiently, but
           allocation will be much slower. */

#include <stdio.h>

/*  Declare the interface, including the requested buffer size type,
 bufsize.  */

#include "bget.h"

/* d'b: {{ */
void *memset(void *s, int c, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
#define NDEBUG /* get rid of asserts, since it pools a lot of code from glibc */
#define assert(a) /* prevent compiler warning */
/* }} */

#define MemSize     int         /* Type for size arguments to memxxx()
           functions such as memcmp(). */

/* Queue links */

struct qlinks
{
  struct bfhead *flink; /* Forward link */
  struct bfhead *blink; /* Backward link */
};

/* Header in allocated and free buffers */

struct bhead
{
  bufsize prevfree; /* Relative link back to previous
   free buffer in memory or 0 if
   previous buffer is allocated.  */
  bufsize bsize; /* Buffer size: positive if free,
   negative if allocated. */
};
#define BH(p) ((struct bhead *) (p))

/*  Header in directly allocated buffers (by acqfcn) */

struct bdhead
{
  bufsize tsize; /* Total size, including overhead */
  struct bhead bh; /* Common header */
};
#define BDH(p)  ((struct bdhead *) (p))

/* Header in free buffers */

struct bfhead
{
  struct bhead bh; /* Common allocated/free header */
  struct qlinks ql; /* Links on free list */
};
#define BFH(p)  ((struct bfhead *) (p))

static struct bfhead freelist =
{ /* List of free buffers */
{ 0, 0 },
{ &freelist, &freelist } };

#if BufStats > 0
static bufsize totalloc = 0; /* Total space currently allocated */
static long numget = 0, numrel = 0; /* Number of bget() and brel() calls */
#endif /* BufStats */

/*  Minimum allocation quantum: */

#define QLSize  (sizeof(struct qlinks))
#define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize)

#define V   (void)          /* To denote unwanted returned values */

/* End sentinel: value placed in bsize field of dummy block delimiting
 end of pool block.  The most negative number which will  fit  in  a
 bufsize, defined in a way that the compiler will accept. */

#define ESent ((bufsize) (-(((1LL << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2)) /* d'b: patched to int64 */

/*  BGET  --  Allocate a buffer.  */

void *bget(requested_size)
  bufsize requested_size;
{
  bufsize size = requested_size;
  struct bfhead *b;
#if BestFit > 0
  struct bfhead *best;
#endif
  void *buf;

  assert(size > 0);

  if(size < SizeQ)
  { /* Need at least room for the */
    size = SizeQ; /*    queue links.  */
  }
#if SizeQuant > 1
  size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1));
#endif

  size += sizeof(struct bhead); /* Add overhead in allocated buffer
   to size required. */

  b = freelist.ql.flink;
#if BestFit > 0
  best = &freelist;
#endif

  /* Scan the free list searching for the first buffer big enough
   to hold the requested size buffer. */

#if BestFit > 0
  while(b != &freelist)
  {
    if(b->bh.bsize >= size)
    {
      if((best == &freelist) || (b->bh.bsize < best->bh.bsize))
      {
        best = b;
      }
    }
    b = b->ql.flink; /* Link to next buffer */
  }
  b = best;
#endif /* BestFit */

  while(b != &freelist)
  {
    if((bufsize)b->bh.bsize >= size)
    {

      /* Buffer  is big enough to satisfy  the request.  Allocate it
       to the caller.  We must decide whether the buffer is  large
       enough  to  split  into  the part given to the caller and a
       free buffer that remains on the free list, or  whether  the
       entire  buffer  should  be  removed  from the free list and
       given to the caller in its entirety.   We  only  split  the
       buffer if enough room remains for a header plus the minimum
       quantum of allocation. */

      if((b->bh.bsize - size) > (SizeQ + (sizeof(struct bhead))))
      {
        struct bhead *ba, *bn;

        ba = BH(((char *) b) + (b->bh.bsize - size));
        bn = BH(((char *) ba) + size);
        assert(bn->prevfree == b->bh.bsize);
        /* Subtract size from length of free block. */
        b->bh.bsize -= size;
        /* Link allocated buffer to the previous free buffer. */
        ba->prevfree = b->bh.bsize;
        /* Plug negative size into user buffer. */
        ba->bsize = -(bufsize)size;
        /* Mark buffer after this one not preceded by free block. */
        bn->prevfree = 0;

#if BufStats > 0
        totalloc += size;
        numget++; /* Increment number of bget() calls */
#endif
        buf = (void *)((((char *)ba) + sizeof(struct bhead)));
        return buf;
      }
      else
      {
        struct bhead *ba;

        ba = BH(((char *) b) + b->bh.bsize);
        assert(ba->prevfree == b->bh.bsize);

        /* The buffer isn't big enough to split.  Give  the  whole
         shebang to the caller and remove it from the free list. */

        assert(b->ql.blink->ql.flink == b);
        assert(b->ql.flink->ql.blink == b);
        b->ql.blink->ql.flink = b->ql.flink;
        b->ql.flink->ql.blink = b->ql.blink;

#if BufStats > 0
        totalloc += b->bh.bsize;
        numget++; /* Increment number of bget() calls */
#endif
        /* Negate size to mark buffer allocated. */
        b->bh.bsize = -(b->bh.bsize);

        /* Zero the back pointer in the next buffer in memory
         to indicate that this buffer is allocated. */
        ba->prevfree = 0;

        /* Give user buffer starting at queue links. */
        buf = (void *)&(b->ql);
        return buf;
      }
    }
    b = b->ql.flink; /* Link to next buffer */
  }

  return NULL;
}

/*  BGETZ  --  Allocate a buffer and clear its contents to zero.  We clear
 the  entire  contents  of  the buffer to zero, not just the
 region requested by the caller. */

void *bgetz(size)
  bufsize size;
{
  char *buf = (char *) bget(size);

  if(buf != NULL)
  {
    struct bhead *b;
    bufsize rsize;

    b = BH(buf - sizeof(struct bhead));
    rsize = -(b->bsize);
    if(rsize == 0)
    {
      struct bdhead *bd;

      bd = BDH(buf - sizeof(struct bdhead));
      rsize = bd->tsize - sizeof(struct bdhead);
    }
    else
    {
      rsize -= sizeof(struct bhead);
    }
    assert(rsize >= size);
    V memset(buf, 0, (MemSize) rsize);
    V memset(buf, 0, (MemSize) size);
  }
  return ((void *) buf);
}

/*  BGETR  --  Reallocate a buffer.  This is a minimal implementation,
 simply in terms of brel()  and  bget().   It  could  be
 enhanced to allow the buffer to grow into adjacent free
 blocks and to avoid moving data unnecessarily.  */

void *bgetr(buf, size)
  void *buf;bufsize size;
{
  void *nbuf;
  bufsize osize; /* Old size of buffer */
  struct bhead *b;

  if((nbuf = bget(size)) == NULL)
  { /* Acquire new buffer */
    return NULL;
  }
  if(buf == NULL)
  {
    return nbuf;
  }
  b = BH(((char *) buf) - sizeof(struct bhead));
  osize = -b->bsize;
  osize -= sizeof(struct bhead);
  assert(osize > 0);
  V memcpy((char *) nbuf, (char *) buf, /* Copy the data */
           (MemSize) ((size < osize) ? size : osize));
  brel(buf);
  return nbuf;
}

/*  BREL  --  Release a buffer.  */

void brel(buf)
  void *buf;
{
  struct bfhead *b, *bn;

  b = BFH(((char *) buf) - sizeof(struct bhead));
#if BufStats > 0
  numrel++; /* Increment number of brel() calls */
#endif
  assert(buf != NULL);

  /* Buffer size must be negative, indicating that the buffer is
   allocated. */

  if(b->bh.bsize >= 0)
  {
    bn = NULL;
  }
  assert(b->bh.bsize < 0);

  /*  Back pointer in next buffer must be zero, indicating the
   same thing: */

  assert(BH((char *) b - b->bh.bsize)->prevfree == 0);

#if BufStats > 0
  totalloc += b->bh.bsize;
  assert(totalloc >= 0);
#endif

  /* If the back link is nonzero, the previous buffer is free.  */

  if(b->bh.prevfree != 0)
  {

    /* The previous buffer is free.  Consolidate this buffer  with  it
     by  adding  the  length  of  this  buffer  to the previous free
     buffer.  Note that we subtract the size  in  the  buffer  being
     released,  since  it's  negative to indicate that the buffer is
     allocated. */

    register bufsize size = b->bh.bsize;

    /* Make the previous buffer the one we're working on. */
    assert(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree);
    b = BFH(((char *) b) - b->bh.prevfree);
    b->bh.bsize -= size;
  }
  else
  {

    /* The previous buffer isn't allocated.  Insert this buffer
     on the free list as an isolated free block. */

    assert(freelist.ql.blink->ql.flink == &freelist);
    assert(freelist.ql.flink->ql.blink == &freelist);
    b->ql.flink = &freelist;
    b->ql.blink = freelist.ql.blink;
    freelist.ql.blink = b;
    b->ql.blink->ql.flink = b;
    b->bh.bsize = -b->bh.bsize;
  }

  /* Now we look at the next buffer in memory, located by advancing from
   the  start  of  this  buffer  by its size, to see if that buffer is
   free.  If it is, we combine  this  buffer  with  the  next  one  in
   memory, dechaining the second buffer from the free list. */

  bn = BFH(((char *) b) + b->bh.bsize);
  if(bn->bh.bsize > 0)
  {

    /* The buffer is free.  Remove it from the free list and add
     its size to that of our buffer. */

    assert(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize);
    assert(bn->ql.blink->ql.flink == bn);
    assert(bn->ql.flink->ql.blink == bn);
    bn->ql.blink->ql.flink = bn->ql.flink;
    bn->ql.flink->ql.blink = bn->ql.blink;
    b->bh.bsize += bn->bh.bsize;

    /* Finally,  advance  to   the  buffer  that   follows  the  newly
     consolidated free block.  We must set its  backpointer  to  the
     head  of  the  consolidated free block.  We know the next block
     must be an allocated block because the process of recombination
     guarantees  that  two  free  blocks will never be contiguous in
     memory.  */

    bn = BFH(((char *) b) + b->bh.bsize);
  }
#if FreeWipe > 0
  V memset(((char *) b) + sizeof(struct bfhead), 0x55,
           (MemSize) (b->bh.bsize - sizeof(struct bfhead)));
#endif
  assert(bn->bh.bsize < 0);

  /* The next buffer is allocated.  Set the backpointer in it  to  point
   to this buffer; the previous free buffer in memory. */

  bn->bh.prevfree = b->bh.bsize;
}

/*  BPOOL  --  Add a region of memory to the buffer pool.  */

void bpool(buf, len)
  void *buf;bufsize len;
{
  struct bfhead *b = BFH(buf);
  struct bhead *bn;

#if SizeQuant > 0
  len &= ~(SizeQuant - 1);
#endif

  /* Since the block is initially occupied by a single free  buffer,
   it  had  better  not  be  (much) larger than the largest buffer
   whose size we can store in bhead.bsize. */

  assert(len - sizeof(struct bhead) <= -((bufsize) ESent + 1));

  /* Clear  the  backpointer at  the start of the block to indicate that
   there  is  no  free  block  prior  to  this   one.    That   blocks
   recombination when the first block in memory is released. */

  b->bh.prevfree = 0;

  /* Chain the new block to the free list. */

  assert(freelist.ql.blink->ql.flink == &freelist);
  assert(freelist.ql.flink->ql.blink == &freelist);
  b->ql.flink = &freelist;
  b->ql.blink = freelist.ql.blink;
  freelist.ql.blink = b;
  b->ql.blink->ql.flink = b;

  /* Create a dummy allocated buffer at the end of the pool.  This dummy
   buffer is seen when a buffer at the end of the pool is released and
   blocks  recombination  of  the last buffer with the dummy buffer at
   the end.  The length in the dummy buffer  is  set  to  the  largest
   negative  number  to  denote  the  end  of  the pool for diagnostic
   routines (this specific value is  not  counted  on  by  the  actual
   allocation and release functions). */

  len -= sizeof(struct bhead);
  b->bh.bsize = (bufsize) len;

#if FreeWipe > 0
  V memset(((char *) b) + sizeof(struct bfhead), 0x55, (MemSize) (len - sizeof(struct bfhead)));
#endif

  bn = BH(((char *) b) + len);
  bn->prevfree = (bufsize) len;
  /* Definition of ESent assumes two's complement! */
  assert((~0) == -1);
  bn->bsize = ESent;
}

#if BufStats > 0

/*  BSTATS  --  Return buffer allocation free space statistics.  */

void bstats(curalloc, totfree, maxfree, nget, nrel)
  bufsize *curalloc, *totfree, *maxfree; long *nget, *nrel;
{
  struct bfhead *b = freelist.ql.flink;

  *nget = numget;
  *nrel = numrel;
  *curalloc = totalloc;
  *totfree = 0;
  *maxfree = -1;
  while(b != &freelist)
  {
    assert(b->bh.bsize > 0);
    *totfree += b->bh.bsize;
    if(b->bh.bsize > *maxfree)
    {
      *maxfree = b->bh.bsize;
    }
    b = b->ql.flink; /* Link to next buffer */
  }
}

#endif


<|start_filename|>src/syscalls/switch_to_app.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include "src/main/tools.h"
#include "src/syscalls/switch_to_app.h"

/* AMD instruction sets */
#ifdef __XOP__
# include <x86intrin.h> /* AMD XOP (GNU) */
#elif defined (__SSE4A__) /* AMD SSE4A */
# include <ammintrin.h>
#endif

/* CPUID. "r" should be int[4], "func" = eax */
#define CPUID(r, func) \
    asm("cpuid" : "=a"(r[0]), "=b"(r[1]), "=c"(r[2]), "=d"(r[3]) : "a"(func), "c"(0))

/*
 * find supported instruction set, return value:
 * 0           = 80386 instruction set
 * 1  or above = SSE (XMM) (not testing for O.S. support)
 * 2  or above = SSE2
 * 3  or above = SSE3
 * 4  or above = SSSE3 (Supplementary SSE3)
 * 5  or above = SSE4.1
 * 6  or above = SSE4.2
 * 7  or above = AVX
 * 8  or above = AVX2
 */
static int CPUTest(void)
{
  uint32_t a, d;
  int r[4] = {0};

  CPUID(r, 0);
  if(r[0] == 0) return 0;
  CPUID(r, 1);

#define TEST_CPU(reg, bit, result) \
  do {if((r[(reg)] & (1 << (bit))) == 0) return(result);} while(0)

  TEST_CPU(3, 0, 0);
  TEST_CPU(3, 23, 0);
  TEST_CPU(3, 15, 0);
  TEST_CPU(3, 24, 0);
  TEST_CPU(3, 25, 0);
  TEST_CPU(3, 26, 1);
  TEST_CPU(2, 0, 2);
  TEST_CPU(2, 9, 3);
  TEST_CPU(2, 19, 4);
  TEST_CPU(2, 23, 5);
  TEST_CPU(2, 20, 5);
  TEST_CPU(2, 27, 6);

  asm("xgetbv" : "=a"(a),"=d"(d) : "c"(0));
  if(((a | (((uint64_t)d) << 32)) & 6) != 6) return 6;

  TEST_CPU(2, 28, 6);
  CPUID(r, 7);
  TEST_CPU(1, 5, 7);

  return 8;
#undef TEST_CPU
}

void InitSwitchToApp(struct NaClApp *nap)
{
  int cpu = CPUTest();
  char *name[] = {"no SSE", "SSE", "SSE2", "SSE3", "Supplementary SSE3",
                  "SSE4.1", "SSE4.2", "AVX", "AVX2 or better"};

  UNREFERENCED_PARAMETER(nap);
  assert((unsigned)cpu < ARRAY_SIZE_SAFE(name));

  ZLOGS(LOG_DEBUG, "%s cpu detected", name[cpu]);
  ZLOGFAIL(cpu == 0, EFAULT, "zerovm needs at least SSE CPU");
  ZLOGIF(cpu > 7, "zerovm running on CPU with partial support. UNSAFE!");
  ContextSwitch = cpu < 7 ? SwitchSSE : SwitchAVX;
}


<|start_filename|>src/loader/sel.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <sys/mman.h>
#include "src/loader/elf_util.h"
#include "src/syscalls/switch_to_app.h"
#include "src/platform/sel_memory.h"
#include "src/loader/sel_addrspace.h"

/*
 * Fill from static_text_end to end of that page with halt
 * instruction, which is at least NACL_HALT_LEN in size when no
 * dynamic text is present.  Does not touch dynamic text region, which
 * should be pre-filled with HLTs.
 *
 * By adding NACL_HALT_SLED_SIZE, we ensure that the code region ends
 * with HLTs, just in case the CPU has a bug in which it fails to
 * check for running off the end of the x86 code segment.
 */
void static FillEndOfTextRegion(struct NaClApp *nap)
{
  size_t page_pad;

  /*
   * NOTE: make sure we are not silently overwriting data.  It is the
   * toolchain's responsibility to ensure that a NACL_HALT_SLED_SIZE
   * gap exists.
   */
  ZLOGFAIL(0 != nap->data_start && nap->static_text_end
      + NACL_HALT_SLED_SIZE > nap->data_start, EFAULT,
      "Missing gap between text and data for halt_sled");

  ZLOGFAIL(0 != nap->rodata_start && nap->static_text_end
      + NACL_HALT_SLED_SIZE > nap->rodata_start, EFAULT,
      "Missing gap between text and rodata for halt_sled");

  /* No dynamic text exists.  Space for NACL_HALT_SLED_SIZE must exist */
  page_pad = ROUNDUP_64K(nap->static_text_end + NACL_HALT_SLED_SIZE)
      - nap->static_text_end;
  ZLOGFAIL(page_pad < NACL_HALT_SLED_SIZE, EFAULT, FAILED_MSG);
  ZLOGFAIL(page_pad >= NACL_MAP_PAGESIZE + NACL_HALT_SLED_SIZE, EFAULT, FAILED_MSG);

  ZLOGS(LOG_INSANE, "Filling with halts: %08lx, %08lx bytes",
          nap->mem_start + nap->static_text_end, page_pad);

  FillMemoryRegionWithHalt((void*)(nap->mem_start + nap->static_text_end), page_pad);
  nap->static_text_end += page_pad;
}

/* Basic address space layout sanity check */
static void CheckAddressSpaceLayoutSanity(struct NaClApp *nap,
    uintptr_t rodata_end, uintptr_t data_end, uintptr_t max_vaddr)
{
  /* fail if Data segment exists, but is not last segment */
  if(0 != nap->data_start)
    ZLOGFAIL(data_end != max_vaddr, ENOEXEC, FAILED_MSG);
  /*
   * This should be unreachable, but we include it just for completeness
   *
   * Here is why it is unreachable:
   *
   * PhdrChecks checks the test segment starting address.  The
   * only allowed loaded segments are text, data, and rodata.
   * Thus unless the rodata is in the trampoline region, it must
   * be after the text.  And ValidateProgramHeaders ensures that
   * all segments start after the trampoline region.
   *
   * d'b: fail if no data segment. read-only data segment exists
   * but is not last segment
   */
  else if(0 != nap->rodata_start)
    ZLOGFAIL(ROUNDUP_64K(rodata_end) != max_vaddr, ENOEXEC, FAILED_MSG);

  /* fail if Read-only data segment overlaps data segment */
  if(0 != nap->rodata_start && 0 != nap->data_start)
    ZLOGFAIL(rodata_end > nap->data_start, ENOEXEC, FAILED_MSG);

  /* fail if Text segment overlaps rodata segment */
  if(0 != nap->rodata_start)
    ZLOGFAIL(ROUNDUP_64K(NaClEndOfStaticText(nap)) > nap->rodata_start,
        ENOEXEC, FAILED_MSG);
  /* fail if No rodata segment, and text segment overlaps data segment */
  else if(0 != nap->data_start)
    ZLOGFAIL(ROUNDUP_64K(NaClEndOfStaticText(nap)) > nap->data_start,
        ENOEXEC, FAILED_MSG);

  /* fail if rodata_start not a multiple of allocation size */
  ZLOGFAIL(0 != nap->rodata_start && ROUNDUP_64K(nap->rodata_start)
    != nap->rodata_start, ENOEXEC, FAILED_MSG);

  /* fail if data_start not a multiple of allocation size */
  ZLOGFAIL(0 != nap->data_start && ROUNDUP_64K(nap->data_start)
    != nap->data_start, ENOEXEC, FAILED_MSG);
}

#define DUMP(a) ZLOGS(LOG_INSANE, "%-24s = 0x%016x", #a, a)
static void LogAddressSpaceLayout(struct NaClApp *nap)
{
  ZLOGS(LOG_INSANE, "NaClApp addr space layout:");
  DUMP(nap->static_text_end);
  DUMP(nap->dynamic_text_start);
  DUMP(nap->dynamic_text_end);
  DUMP(nap->rodata_start);
  DUMP(nap->data_start);
  DUMP(nap->data_end);
  DUMP(nap->break_addr);
  DUMP(nap->initial_entry_pt);
  DUMP(nap->user_entry_pt);
}

static int AddrIsValidEntryPt(struct NaClApp *nap, uintptr_t addr)
{
  if(0 != (addr & (NACL_INSTR_BLOCK_SIZE - 1))) return 0;
  return addr < nap->static_text_end;
}

void AppLoadFile(struct Gio *gp, struct NaClApp *nap)
{
  uintptr_t rodata_end;
  uintptr_t data_end;
  uintptr_t max_vaddr;
  struct ElfImage *image = NULL;
  int err;

  /* fail if Address space too big */
  ZLOGFAIL(nap->addr_bits > NACL_MAX_ADDR_BITS, EFAULT, FAILED_MSG);

  nap->stack_size = ROUNDUP_64K(nap->stack_size);

  /* temporay object will be deleted at end of function */
  image = ElfImageNew(gp);
  ValidateElfHeader(image);

  ValidateProgramHeaders(image, nap->addr_bits, &nap->static_text_end,
      &nap->rodata_start, &rodata_end, &nap->data_start, &data_end, &max_vaddr);

  /*
   * if no rodata and no data, we make sure that there is space for
   * the halt sled. else if no data, but there is rodata.  this means
   * max_vaddr is just where rodata ends.  this might not be at an
   * allocation boundary, and in this the page would not be writable.
   * round max_vaddr up to the next allocation boundary so that bss
   * will be at the next writable region.
   */
  if(0 == nap->data_start)
  {
    if(0 == nap->rodata_start)
    {
      if(ROUNDUP_64K(max_vaddr) - max_vaddr < NACL_HALT_SLED_SIZE)
        max_vaddr += NACL_MAP_PAGESIZE;
    }
    max_vaddr = ROUNDUP_64K(max_vaddr);
  }

  /*
   * max_vaddr -- the break or the boundary between data (initialized
   * and bss) and the address space hole -- does not have to be at a
   * page boundary.
   */
  nap->break_addr = max_vaddr;
  nap->data_end = max_vaddr;

  ZLOGS(LOG_INSANE, "Values from ValidateProgramHeaders:");
  DUMP(nap->rodata_start);
  DUMP(rodata_end);
  DUMP(nap->data_start);
  DUMP(data_end);
  DUMP(max_vaddr);

  nap->initial_entry_pt = ElfImageGetEntryPoint(image);
  LogAddressSpaceLayout(nap);

  /* Bad program entry point address */
  ZLOGFAIL(!AddrIsValidEntryPt(nap, nap->initial_entry_pt), ENOEXEC, FAILED_MSG);

  CheckAddressSpaceLayoutSanity(nap, rodata_end, data_end, max_vaddr);

  ZLOGS(LOG_DEBUG, "Allocating address space");
  AllocAddrSpace(nap);

  /*
   * Make sure the static image pages are marked writable before we try
   * to write them.
   */
  ZLOGS(LOG_DEBUG, "Loading into memory");
  err = NaCl_mprotect((void *)(nap->mem_start + NACL_TRAMPOLINE_START),
      ROUNDUP_64K(nap->data_end) - NACL_TRAMPOLINE_START,
      PROT_READ | PROT_WRITE);
  ZLOGFAIL(0 != err, EFAULT, "Failed to make image pages writable. errno = %d", err);

  ElfImageLoad(image, gp, nap->addr_bits, nap->mem_start);

  /* d'b: shared memory for the dynamic text disabled */
  nap->dynamic_text_start = ROUNDUP_64K(NaClEndOfStaticText(nap));
  nap->dynamic_text_end = nap->dynamic_text_start;

  /*
   * FillEndOfTextRegion will fill with halt instructions the
   * padding space after the static text region.
   *
   * Shm-backed dynamic text space was filled with halt instructions
   * in NaClMakeDynamicTextShared.  This extends to the rodata.  For
   * non-shm-backed text space, this extend to the next page (and not
   * allocation page).  static_text_end is updated to include the
   * padding.
   */
  FillEndOfTextRegion(nap);

  ZLOGS(LOG_DEBUG, "Initializing arch switcher");
  InitSwitchToApp(nap);

  ZLOGS(LOG_DEBUG, "Installing trampoline");
  LoadTrampoline(nap);

  /*
   * NaClMemoryProtect also initializes the mem_map w/ information
   * about the memory pages and their current protection value.
   *
   * The contents of the dynamic text region will get remapped as
   * non-writable.
   */
  ZLOGS(LOG_DEBUG, "Applying memory protection");
  MemoryProtection(nap);

  ZLOGS(LOG_DEBUG, "AppLoadFile done");
  LogAddressSpaceLayout(nap);

  ElfImageDelete(image);
}
#undef DUMP

NORETURN void CreateSession(struct NaClApp *nap)
{
  uintptr_t stack_ptr;

  assert(nap != NULL);

  /* set up user stack */
  stack_ptr = nap->mem_start + ((uintptr_t)1U << nap->addr_bits);
  stack_ptr -= STACK_USER_DATA_SIZE;
  memset((void*)stack_ptr, 0, STACK_USER_DATA_SIZE);
  ((uint32_t*)stack_ptr)[4] = 1;
  ((uint32_t*)stack_ptr)[5] = 0xfffffff0;

  /*
   * construct "nacl_user" and "nacl_sys" globals
   * note: nacl_sys->prog_ctr meaningless but should not be 0
   */
  ThreadContextCtor(nacl_user, nap, nap->initial_entry_pt, stack_ptr);
  ThreadContextCtor(nacl_sys, nap, 1, GetStackPtr());

  /* pass control to the user side */
  ZLOGS(LOG_DEBUG, "SESSION %d STARTED", nap->manifest->node);
  ContextSwitch(nacl_user);
  ZLOGFAIL(1, EFAULT, "the unreachable has been reached");
}


<|start_filename|>tests/functional/channels/ranwo/ranwo.c<|end_filename|>
/*
 * random write only channel test. tests statistics goes to stdout channel.
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define RANWO "/dev/ranwo"

int main(int argc, char **argv)
{
  char buf[BIG_ENOUGH];

  /* correct requests */
  FPRINTF(STDERR, "TEST RANDOM WRITE ONLY CHANNEL\n");
  FPRINTF(STDERR, "channel size = %ld\n", MANIFEST->channels[OPEN(RANWO)].size);
  ZTEST(MANIFEST->channels[OPEN(RANWO)].size == 0);
  ZTEST(PWRITE(RANWO, buf, 0, 0) == 0);

  ZTEST(PWRITE(RANWO, buf, 0, 0) == 0);
  ZTEST(PWRITE(RANWO, buf, 0, 1) == 0);
  ZTEST(PWRITE(RANWO, buf, 1, 0) == 1);
  ZTEST(PWRITE(RANWO, buf, 1,
      MANIFEST->channels[OPEN(RANWO)].limits[PutSizeLimit] - 1) == 1);
  ZTEST(PWRITE(RANWO, buf, 0, -1) == 0);

  /* incorrect requests: NULL buffer */
  ZTEST(PWRITE(RANWO, NULL, 0, 0) < 0);
  ZTEST(PWRITE(RANWO, NULL, 0, 1) < 0);
  ZTEST(PWRITE(RANWO, NULL, 1, 0) < 0);
  ZTEST(PWRITE(RANWO, NULL, 1,
      MANIFEST->channels[OPEN(RANWO)].limits[PutSizeLimit] - 1) < 0);
  ZTEST(PWRITE(RANWO, NULL, 0, -1) < 0);

  /* incorrect requests: size */
  ZTEST(PWRITE(RANWO, buf, -1, 0) < 0);

  /* incorrect requests: offset */
  ZTEST(PWRITE(RANWO, buf, 0, -1) == 0);
  ZTEST(PWRITE(RANWO, buf, 1, -1) < 0);
  ZTEST(PWRITE(RANWO, buf, 1, MANIFEST->channels[OPEN(RANWO)].limits[PutSizeLimit]) < 0);

  /* correct requests: reading of 0 bytes attempt */
  ZTEST(PREAD(RANWO, buf, 0, 0) == 0);

  /* incorrect requests: read attempt */
  ZTEST(PREAD(RANWO, buf, 1, 0) < 0);
  ZTEST(PREAD(RANWO, buf, 1, MANIFEST->channels[OPEN(RANWO)].limits[PutSizeLimit]) < 0);

  /* incorrect requests: exhausted */
  ZTEST(PWRITE(RANWO, buf, 31, 0) == 30);
  ZTEST(PWRITE(RANWO, buf, 10, 0) < 0);

  /* count errors and exit with it */
  ZREPORT;
  return 0;
}


<|start_filename|>src/syscalls/trap.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <sys/mman.h>
#include "src/channels/channel.h"
#include "src/main/report.h"
#include "src/platform/sel_memory.h"
#include "src/main/setup.h"
#include "src/syscalls/daemon.h"

static int idx[] = {TrapRead, TrapWrite, TrapJail, TrapUnjail, TrapExit, TrapFork};
static char *function[] =
  {"TrapRead", "TrapWrite", "TrapJail", "TrapUnjail", "TrapExit", "TrapFork", "n/a"};

/*
 * check "prot" access for user area (start, size)
 * if failed return -1, otherwise - 0
 */
static int CheckRAMAccess(struct NaClApp *nap, uintptr_t start, int64_t size, int prot)
{
  int i;

  start = NaClUserToSysAddrNullOkay(nap, start);
  for(i = LeftBumperIdx; i < MemMapSize; ++i)
  {
    /* skip until start hit block in mem_map */
    if(start >= nap->mem_map[i].end) continue;

    /* fail if block protection doesn't meat prot */
    if((prot & nap->mem_map[i].prot) == 0) return -1;

    /* subtract checked space from given area */
    size -= (nap->mem_map[i].end - start);
    if(size <= 0) return 0;

    start = nap->mem_map[i].end;
  }
  return -1;
}

/*
 * read specified amount of bytes from given desc/offset to buffer
 * return amount of read bytes or negative error code if call failed
 */
static int32_t ZVMReadHandle(struct NaClApp *nap,
    int ch, char *buffer, int32_t size, int64_t offset)
{
  struct ChannelDesc *channel;
  int64_t tail;
  char *sys_buffer;

  assert(nap != NULL);
  assert(nap->manifest != NULL);
  assert(nap->manifest->channels != NULL);

  /* check the channel number */
  if(ch < 0 || ch >= nap->manifest->channels->len)
  {
    ZLOGS(LOG_DEBUG, "channel_id=%d, buffer=%p, size=%d, offset=%ld",
        ch, buffer, size, offset);
    return -EINVAL;
  }
  channel = CH_CH(nap->manifest, ch);
  ZLOGS(LOG_INSANE, "channel %s, buffer=%p, size=%d, offset=%ld",
      channel->alias, buffer, size, offset);

  /* check buffer and convert address */
  if(CheckRAMAccess(nap, (uintptr_t)buffer, size, PROT_WRITE) == -1) return -EINVAL;
  sys_buffer = (char*)NaClUserToSys(nap, (uintptr_t)buffer);

  /* ignore user offset for sequential access read */
  if(CH_SEQ_READABLE(channel))
    offset = channel->getpos;
  else
  /* prevent reading beyond the end of the random access channels */
    size = MIN(channel->size - offset, size);

  /* check arguments sanity */
  if(size == 0) return 0; /* success. user has read 0 bytes */
  if(size < 0) return -EFAULT;
  if(offset < 0) return -EINVAL;

  /* check for eof */
  if(channel->eof) return 0;

  /* check limits */
  if(channel->counters[GetsLimit] >= channel->limits[GetsLimit])
    return -EDQUOT;
  if(CH_RND_READABLE(channel))
    if(offset >= channel->limits[PutSizeLimit] - channel->counters[PutSizeLimit]
      + channel->size) return -EINVAL;

  /* calculate i/o leftovers */
  tail = channel->limits[GetSizeLimit] - channel->counters[GetSizeLimit];
  if(size > tail) size = tail;
  if(size < 1) return -EDQUOT;

  /* read data */
  return ChannelRead(channel, sys_buffer, (size_t)size, (off_t)offset);
}

/*
 * write specified amount of bytes from buffer to given desc/offset
 * return amount of read bytes or negative error code if call failed
 */
static int32_t ZVMWriteHandle(struct NaClApp *nap,
    int ch, const char *buffer, int32_t size, int64_t offset)
{
  struct ChannelDesc *channel;
  int64_t tail;
  const char *sys_buffer;

  assert(nap != NULL);
  assert(nap->manifest != NULL);
  assert(nap->manifest->channels != NULL);

  /* check the channel number */
  if(ch < 0 || ch >= nap->manifest->channels->len)
  {
    ZLOGS(LOG_DEBUG, "channel_id=%d, buffer=%p, size=%d, offset=%ld",
        ch, buffer, size, offset);
    return -EINVAL;
  }
  channel = CH_CH(nap->manifest, ch);
  ZLOGS(LOG_INSANE, "channel %s, buffer=%p, size=%d, offset=%ld",
      channel->alias, buffer, size, offset);

  /* check buffer and convert address */
  if(CheckRAMAccess(nap, (uintptr_t)buffer, size, PROT_READ) == -1) return -EINVAL;
  sys_buffer = (char*)NaClUserToSys(nap, (uintptr_t) buffer);

  /* ignore user offset for sequential access write */
  if(CH_SEQ_WRITEABLE(channel)) offset = channel->putpos;

  /* check arguments sanity */
  if(size == 0) return 0; /* success. user has read 0 bytes */
  if(size < 0) return -EFAULT;
  if(offset < 0) return -EINVAL;

  /* check limits */
  if(channel->counters[PutsLimit] >= channel->limits[PutsLimit])
    return -EDQUOT;
  tail = channel->limits[PutSizeLimit] - channel->counters[PutSizeLimit];
  if(offset >= channel->limits[PutSizeLimit] &&
      !((CH_RW_TYPE(channel) & 1) == 1)) return -EINVAL;

  if(offset >= channel->size + tail) return -EINVAL;
  if(size > tail) size = tail;
  if(size < 1) return -EDQUOT;

  /* write data */
  return ChannelWrite(channel, sys_buffer, (size_t)size, (off_t)offset);
}

#define JAIL_CHECK \
    uintptr_t sysaddr; \
    int result; \
\
    assert(nap != NULL); \
    assert(nap->manifest != NULL); \
\
    sysaddr = NaClUserToSysAddrNullOkay(nap, addr); \
\
    /* sanity check */ \
    if(size <= 0) return -EINVAL; \
    if(sysaddr < nap->mem_map[HeapIdx].start || \
        sysaddr >= nap->mem_map[HeapIdx].end) return -EINVAL; \
    if(sysaddr != ROUNDDOWN_64K(sysaddr)) return -EINVAL

/*
 * validate given buffer and, if successful, change protection to
 * read / execute and return 0
 */
static int32_t ZVMJailHandle(struct NaClApp *nap, uintptr_t addr, int32_t size)
{
  JAIL_CHECK;

  /* validate */
  result = NaClSegmentValidates((uint8_t*)sysaddr, size, sysaddr);
  if(result == 0) return -EPERM;

  /* protect */
  result = NaCl_mprotect((void*)sysaddr, size, PROT_READ | PROT_EXEC);
  if(result != 0) return -EACCES;

  return 0;
}

/* change protection to read / write and return 0 if successful */
static int32_t ZVMUnjailHandle(struct NaClApp *nap, uintptr_t addr, int32_t size)
{
  JAIL_CHECK;

  /* protect */
  result = NaCl_mprotect((void*)sysaddr, size, PROT_READ | PROT_WRITE);
  if(result != 0) return -EACCES;

  return 0;
}
#undef JAIL_CHECK

/* return index of function id in "function" */
static int FunctionIndexById(int id)
{
  int i;

  for(i = 0; i < ARRAY_SIZE(idx); ++i)
    if(idx[i] == id) return i;
  return ARRAY_SIZE(idx);
}

static void SyscallZTrace(int i, ...)
{
  char *msg;
  va_list ap;
  char *fmt[] = {"%s(%d, %p, %d, %ld) = %d", "%s(%d, %p, %d, %ld) = %d",
      "%s(%p, %d) = %d", "%s(%p, %d) = %d", "%s(%d) = %d", "%s()"};

  va_start(ap, i);
  msg = g_strdup_vprintf(fmt[i], ap);
  va_end(ap);
  ZTrace(msg);
  g_free(msg);
}

/* user exit. session is finished */
static void ZVMExitHandle(struct NaClApp *nap, int32_t code)
{
  assert(nap != NULL);

  SetUserCode(code);
  if(GetExitCode() == 0)
    SetExitState(OK_STATE);
  ZLOGS(LOG_DEBUG, "SESSION %d RETURNED %d", nap->manifest->node, code);
  SyscallZTrace(4, function[4], code);
  ReportDtor(0);
}

int32_t TrapHandler(struct NaClApp *nap, uint32_t args)
{
  uint64_t *sargs;
  int retcode = 0;
  int i;

  assert(nap != NULL);
  assert(nap->manifest != NULL);

  /*
   * translate address from user space to system
   * note: cannot set "trap error"
   */
  sargs = (uint64_t*)NaClUserToSys(nap, (uintptr_t)args);
  i = FunctionIndexById(*sargs);
  ZLOGS(LOG_DEBUG, "%s called", function[i]);
  ZTrace("untrusted code");

  switch(*sargs)
  {
    case TrapFork:
      if(Daemon(nap) == 0)
      {
        SyscallZTrace(5, function[5]);
        ZVMExitHandle(nap, 0);
      }
      break;
    case TrapExit:
      ZVMExitHandle(nap, (int32_t)sargs[2]);
      break;
    case TrapRead:
      retcode = ZVMReadHandle(nap,
          (int)sargs[2], (char*)sargs[3], (int32_t)sargs[4], sargs[5]);
      break;
    case TrapWrite:
      retcode = ZVMWriteHandle(nap,
          (int)sargs[2], (char*)sargs[3], (int32_t)sargs[4], sargs[5]);
      break;
    case TrapJail:
      retcode = ZVMJailHandle(nap, (uint32_t)sargs[2], (int32_t)sargs[3]);
      break;
    case TrapUnjail:
      retcode = ZVMUnjailHandle(nap, (uint32_t)sargs[2], (int32_t)sargs[3]);
      break;
    default:
      retcode = -EPERM;
      ZLOG(LOG_ERROR, "function %ld is not supported", *sargs);
      break;
  }

  /* report, ztrace and return */
  FastReport();
  ZLOGS(LOG_DEBUG, "%s returned %d", function[i], retcode);
  SyscallZTrace(i, function[i], sargs[2], sargs[3], sargs[4], sargs[5], retcode);
  return retcode;
}


<|start_filename|>tests/functional/demo/copy/copy.c<|end_filename|>
/*
 * copy /dev/stdin to /dev/stdout
 */
#include "include/zvmlib.h"

void _start()
{
  char buf[BIG_ENOUGH];
  int i;

  do {
    i = zvm_pread(0, buf, BIG_ENOUGH, 0);
    if(i > 0) i = zvm_pwrite(1, buf, i, 0);
  } while(i > 0);

  zvm_exit(i);
}


<|start_filename|>src/syscalls/daemon.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include "src/main/report.h"
#include "src/main/setup.h"
#include "src/main/accounting.h"
#include "src/platform/signal.h"
#include "src/channels/channel.h"
#include "src/syscalls/daemon.h"

#define DAEMON_NAME "zvm."
#define TASK_SIZE 0x10000 /* limited by protocol (server <-> zerovm ) */
#define QUEUE_SIZE 16
#define CMD_SIZE (sizeof(uint64_t))

static int client = -1;

/*
 * child: get command from inherited command socket. current version can
 * only have one command and therefore the command format will only contain
 * one (pascal) string: 4-bytes length and data of "length" size. the data
 * is manifest (reduced form of it). WARNING: result should be freed
 */
static char *GetCommand()
{
  int len;
  char *cmd = g_malloc0(TASK_SIZE);

  assert(client >= 0);

  ZLOGFAIL(read(client, cmd, CMD_SIZE) < 0, EIO, "%s", strerror(errno));
  len = ToInt(cmd);
  ZLOGFAIL(read(client, cmd, len) < 0, EIO, "%s", strerror(errno));

  return cmd;
}

/* child: update "nap" with the new manifest */
static void UpdateSession(struct Manifest *manifest)
{
  int i;
  char *cmd = GetCommand();
  struct Manifest *tmp = ManifestTextCtor(cmd);

  /* re-initialize signals handling, accounting and the report handle */
  g_free(cmd);
  SignalHandlerFini();
  SignalHandlerInit();
  ResetAccounting();
  ReportMode(3);
  SetReportHandle(client);
  ZLogDtor();
  ZLogCtor(0);
  ZTraceCtor(NULL);

  /* copy needful fields from the new manifest */
  manifest->timeout = tmp->timeout;
  manifest->name_server = tmp->name_server;
  manifest->node = tmp->node;
  manifest->job = tmp->job;

  /* reset timeout, i/o limit, privileges e.t.c. */
  LastDefenseLine(manifest);

  /* check and partially copy channels */
  SortChannels(manifest->channels);
  SortChannels(tmp->channels);

  for(i = 0; i < manifest->channels->len; ++i)
  {
#define CHECK(a) ZLOGFAIL(CH_CH(manifest, i)->a != CH_CH(tmp, i)->a, \
    EFAULT, "difference in %s", CH_CH(manifest, i)->a)

    ZLOGFAIL(strcmp(CH_CH(manifest, i)->alias, CH_CH(tmp, i)->alias) != 0,
        EFAULT, "difference in %s", CH_CH(manifest, i)->alias);
    CHECK(type);
    CHECK(limits[0]);
    CHECK(limits[1]);
    CHECK(limits[2]);
    CHECK(limits[3]);

    CH_CH(manifest, i)->source = CH_CH(tmp, i)->source;
    CH_CH(manifest, i)->tag = CH_CH(tmp, i)->tag;
  }
  ChannelsCtor(manifest);
}

/* daemon: get the next task: return when accept()'ed */
static int Job(int sock)
{
  struct sockaddr_un remote;
  socklen_t len = sizeof remote;
  return accept(sock, &remote, &len);
}

/* convert to the daemon mode */
static int Daemonize(struct NaClApp *nap)
{
  char *bname;
  char *name;
  int sock;
  struct sigaction sa;
  struct sockaddr_un remote = {AF_UNIX, ""};

  /* unmount channels, reset timeout */
  ChannelsDtor(nap->manifest);
  nap->manifest->timeout = 0;
  alarm(0);

  /* Become a session leader to lose controlling TTY */
  setsid();

  /* Ensure future opens won't allocate controlling TTYs */
  sa.sa_handler = SIG_IGN;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  ZLOGFAIL(sigaction(SIGHUP, &sa, NULL) < 0, EFAULT, "can't ignore SIGHUP");

  /*
   * Change the current working directory to the root so
   * we won't prevent file systems from being unmounted.
   */
  ZLOGFAIL(chdir("/") < 0, EFAULT, "can't change directory to /");

  /* finalize modules with handles before handles down */
  ZTraceDtor(0);

  /* close standard descriptors */
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);

  /* Attach standard channels to /dev/null */
  ZLOGFAIL(open("/dev/null", O_RDWR) != 0, EFAULT, "can't set stdin to /dev/null");
  ZLOGFAIL(dup(0) != 1, EFAULT, "can't set stdout to /dev/null");
  ZLOGFAIL(dup(0) != 2, EFAULT, "can't set stderr to /dev/null");

  /* open the command channel */
  unlink(nap->manifest->job);
  sock = socket(AF_UNIX, SOCK_STREAM, 0);
  strcpy(remote.sun_path, nap->manifest->job);
  ZLOGFAIL(bind(sock, &remote, sizeof remote) < 0, EIO, "%s", strerror(errno));
  ZLOGFAIL(listen(sock, QUEUE_SIZE) < 0, EIO, "%s", strerror(errno));

  /* set name for daemon */
  bname = g_path_get_basename(nap->manifest->job);
  name = g_strdup_printf("%s%s", DAEMON_NAME, bname);
  prctl(PR_SET_NAME, name);
  g_free(bname);
  g_free(name);

  /* TODO(d'b): free needless resources */
  SetCmdString(g_string_new("command = daemonic"));
  return sock;
}

int Daemon(struct NaClApp *nap)
{
  pid_t pid;
  siginfo_t info;
  int sock;

  /* can the daemon be started? */
  if(nap->manifest->job == NULL) return -1;
  ZLOGFAIL(GetExitCode(), EFAULT, "broken session");

  /* report the daemon mode launched */
  SetDaemonState(1);

  /* finalize user session */
  umask(0);
  pid = fork();
  if(pid != 0) return 0;

  /* forked sessions are not in daemon mode */
  SetDaemonState(0);
  sock = Daemonize(nap);

  for(;;)
  {
    /* get the next job */
    if((client = Job(sock)) < 0)
    {
      ZLOG(LOG_ERROR, "%s", strerror(errno));
      continue;
    }

    /* release waiting child sessions */
    do
      if(waitid(P_ALL, 0, &info, WEXITED | WNOHANG) < 0) break;
    while(info.si_code);

    /* child: update manifest, continue to the trap */
    pid = fork();
    if(pid == 0)
    {
      UpdateSession(nap->manifest);
      break;
    }

    /* daemon: close command socket and wait for a new job */
    close(client);
    ZLOGIF(pid < 0, "fork failed: %s", strerror(errno));
  }

  return -1;
}


<|start_filename|>src/platform/qualify.h<|end_filename|>
/*
 * Copyright 2010 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * POSIX-specific routines for verifying that Data Execution Prevention is
 * functional.
 */

#ifndef QUALIFY_H_
#define QUALIFY_H_

EXTERN_C_BEGIN

/*
 * Runs the Platform Qualification tests required for safe sel startup.  This
 * may be a subset of the full set of PQ tests: it includes the tests that are
 * important enough to check at every startup, and tests that check aspects of
 * the system that may be subject to change.
 */
void RunSelQualificationTests();

EXTERN_C_END

#endif  /* QUALIFY_H_ */


<|start_filename|>Makefile<|end_filename|>
PREFIX ?= /usr/local
prefix = $(PREFIX)
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
nacl_includedir = $(prefix)/x86_64-nacl/include

LDFLAGS=-L $(libdir)
FLAGS0=-fPIE -Wall -Wno-long-long -fvisibility=hidden -fstack-protector --param ssp-buffer-size=4
GLIB=`pkg-config --cflags glib-2.0`
TAG_ENCRYPTION ?= G_CHECKSUM_SHA1
# PREFETCH: zmq, udt
PREFETCH ?= zmq
CCFLAGS0=-c -m64 -fPIC -D$(PREFETCH) -D_GNU_SOURCE -DTAG_ENCRYPTION=$(TAG_ENCRYPTION) -I. $(GLIB)

CXXFLAGS0=-m64 -Wno-variadic-macros $(GLIB)
LIBS=-l$(PREFETCH) -lglib-2.0 -lvalidator -pthread
TESTLIBS=-Llib/gtest -lgtest $(LIBS)

CCFLAGS1=-std=gnu89 -Wdeclaration-after-statement $(FLAGS0) $(CCFLAGS0)
CCFLAGS2=-Wextra -Wswitch-enum -Wsign-compare $(CCFLAGS0)
CXXFLAGS1=-c -std=c++98 -D_GNU_SOURCE=1 -I. -Ilib $(CXXFLAGS0) $(FLAGS0)
CXXFLAGS2=-Wl,-z,noexecstack $(CXXFLAGS0) -Lobj -pie -Wl,-z,relro -Wl,-z,now

all: CCFLAGS1 += -DNDEBUG -O2 -s
all: CCFLAGS2 += -DNDEBUG -O2 -s
all: CXXFLAGS1 := -DNDEBUG -O2 -s $(CXXFLAGS1)
all: CXXFLAGS2 := -DNDEBUG -O2 -s $(CXXFLAGS2)
all: create_dirs zerovm

debug: CCFLAGS1 += -DDEBUG -g
debug: CCFLAGS2 += -DDEBUG -g
debug: CXXFLAGS1 := -DDEBUG -g $(CXXFLAGS1)
debug: CXXFLAGS2 := -DDEBUG -g $(CXXFLAGS2)
debug: create_dirs zerovm tests

OBJS=obj/elf_util.o obj/gio.o obj/gio_snapshot.o obj/manifest.o obj/setup.o obj/channel.o obj/qualify.o obj/report.o obj/zlog.o obj/signal_common.o obj/signal.o obj/to_app.o obj/switch_to_app.o obj/to_trap.o obj/syscall_hook.o obj/prefetch.o obj/nservice.o obj/preload.o obj/sel_addrspace.o obj/sel_ldr.o obj/sel.o obj/sel_memory.o obj/sel_rt.o obj/tramp.o obj/trap.o obj/etag.o obj/accounting.o obj/daemon.o obj/snapshot.o

create_dirs:
	@mkdir obj -p

zerovm: obj/zerovm.o $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $(CXXFLAGS2) $^ $(LIBS)

tests: test_compile
	@printf "UNIT TESTS %048o\n" 0
	@cd tests/unit;\
	./manifest_parser_test;\
	./service_runtime_tests;\
	cd ..

test_compile: tests/unit/manifest_parser_test tests/unit/service_runtime_tests

obj/manifest_parser_test.o: tests/unit/manifest_parser_test.cc
	$(CXX) $(CXXFLAGS1) -o $@ $^
tests/unit/manifest_parser_test: obj/manifest_parser_test.o $(OBJS)
	$(CXX) $(CXXFLAGS2) -o $@ $^ $(TESTLIBS)

obj/sel_ldr_test.o: tests/unit/sel_ldr_test.cc
	$(CXX) $(CXXFLAGS1) -o $@ $^
obj/sel_memory_unittest.o: tests/unit/sel_memory_unittest.cc
	$(CXX) $(CXXFLAGS1) -o $@ $^
obj/unittest_main.o: tests/unit/unittest_main.cc
	$(CXX) $(CXXFLAGS1) -o $@ $^
tests/unit/service_runtime_tests: obj/sel_ldr_test.o obj/sel_memory_unittest.o obj/unittest_main.o $(OBJS)
	$(CXX) $(CXXFLAGS2) -o $@ $^ $(TESTLIBS)

.PHONY: clean clean_intermediate install

clean: clean_intermediate
	@rm -f zerovm
	@echo ZeroVM has been deleted

clean_intermediate:
	@rm -f tests/unit/manifest_parser_test tests/unit/service_runtime_tests obj/*
	@echo intermediate files has been deleted
	@echo unit tests has been deleted

install:
	install -D -m 0755 zerovm $(DESTDIR)$(bindir)/zerovm
	install -D -m 0644 api/zvm.h $(DESTDIR)$(nacl_includedir)/zvm.h

obj/channel.o: src/channels/channel.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/prefetch.o: src/channels/prefetch.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/nservice.o: src/channels/nservice.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/preload.o: src/channels/preload.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/trap.o: src/syscalls/trap.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/setup.o: src/main/setup.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/manifest.o: src/main/manifest.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/to_app.o: src/syscalls/to_app.S
	$(CC) $(CCFLAGS2) -o $@ $^

obj/to_trap.o: src/syscalls/to_trap.S
	$(CC) $(CCFLAGS2) -o $@ $^

obj/tramp.o: src/syscalls/tramp.S
	$(CC) $(CCFLAGS2) -o $@ $^

obj/zerovm.o: src/main/zerovm.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/elf_util.o: src/loader/elf_util.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/signal_common.o: src/platform/signal_common.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/syscall_hook.o: src/syscalls/syscall_hook.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/sel_addrspace.o: src/loader/sel_addrspace.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/sel_ldr.o: src/loader/sel_ldr.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/sel.o: src/loader/sel.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/switch_to_app.o: src/syscalls/switch_to_app.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/sel_rt.o: src/loader/sel_rt.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/sel_memory.o: src/platform/sel_memory.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/signal.o: src/platform/signal.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/qualify.o: src/platform/qualify.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/report.o: src/main/report.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/zlog.o: src/main/zlog.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/gio.o: src/platform/gio.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/gio_snapshot.o: src/platform/gio_snapshot.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/etag.o: src/main/etag.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/accounting.o: src/main/accounting.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/daemon.o: src/syscalls/daemon.c
	$(CC) $(CCFLAGS1) -o $@ $^

obj/snapshot.o: src/syscalls/snapshot.c
	$(CC) $(CCFLAGS1) -o $@ $^


<|start_filename|>src/loader/sel_addrspace.c<|end_filename|>
/*
 * Copyright 2008 The Native Client Authors.  All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <sys/mman.h>
#include "src/loader/sel_ldr.h"
#include "src/platform/sel_memory.h"

/* user memory size (84gb) */
static size_t request_sz = 0;

/* protect bumpers (guarding space) */
static void MprotectGuards(struct NaClApp *nap)
{
  int err;

  ZLOGS(LOG_DEBUG, "Protecting bumpers");

  /*
   * make bumpers (guard pages) with "inaccessible" protection. the "left"
   * bumper size is 40gb + 64kb, the "right" one - 40gb
   */
  err = NaCl_mprotect((void *)(nap->mem_start - GUARDSIZE),
      GUARDSIZE + NACL_SYSCALL_START_ADDR, PROT_NONE);
  ZLOGFAIL(err != 0, err, FAILED_MSG);
  err = NaCl_mprotect((void *)(nap->mem_start + FOURGIG), GUARDSIZE, PROT_NONE);
  ZLOGFAIL(err != 0, err, FAILED_MSG);

  /* put information to the memory map */
  SET_MEM_MAP_IDX(nap->mem_map[LeftBumperIdx], "LeftBumper",
      nap->mem_start - GUARDSIZE, GUARDSIZE + NACL_SYSCALL_START_ADDR, PROT_NONE);
  SET_MEM_MAP_IDX(nap->mem_map[RightBumperIdx], "RightBumper",
      nap->mem_start + FOURGIG, GUARDSIZE, PROT_NONE);
}

/*
 * allocate a large amount of memory of mem_sz bytes that must
 * be address aligned
 */
static void AllocatePow2AlignedMemory(size_t mem_sz)
{
  void *mem_ptr;

  assert(mem_sz % NACL_MAP_PAGESIZE == 0);

  request_sz = mem_sz;
  ZLOGS(LOG_INSANE, "%25s %016lx", " Ask:", request_sz);

  /* d'b: try to get the fixed address r15 (user base register) */
  mem_ptr = mmap(R15_CONST, request_sz, PROT_NONE, ABSOLUTE_MMAP, -1, (off_t)0);
  ZLOGFAIL(R15_CONST != mem_ptr, errno, "cannot allocate user memory");
}

/*
 * Platform-specific routine to allocate memory space for the NaCl
 * module.  mem is an out argument; addrsp_size is the requested
 * address space size, currently always ((size_t) 1) <<
 * nap->addr_bits.  On x86-64, there's a further requirement that this
 * is 4G.
 *
 * The actual amount of memory allocated is larger than requested on
 * x86-64 and on the ARM, since guard pages are also allocated to be
 * contiguous with the allocated address space.
 *
 * If successful, the guard pages are not yet memory protected.  The
 * function MprotectGuards must be called for the guard pages to be
 * active.
 */
static void AllocateSpace(void **mem, size_t addrsp_size)
{
  assert(addrsp_size == FOURGIG);

  /* 4gb + 40gb guard on each side */
  ZLOGS(LOG_INSANE, "AllocateSpace(*, 0x%016lx bytes)", addrsp_size);
  AllocatePow2AlignedMemory(2 * GUARDSIZE + FOURGIG);

  /*
   * The module lives in the middle FOURGIG of the allocated region --
   * we skip over an initial 40G guard.
   */
  *mem = (char*)R15_CONST + GUARDSIZE;
  ZLOGS(LOG_INSANE, "addr space at 0x%016lx", (uintptr_t)*mem);
}

void FreeAddrSpace(struct NaClApp *nap)
{
  /* exit if memory was not allocated */
  if(request_sz == 0) return;
  ZLOGIF(munmap(R15_CONST, request_sz) == -1,
      "user memory deallocation failed with errno %d", errno);
}

void AllocAddrSpace(struct NaClApp *nap)
{
  void        *mem;
  uintptr_t   hole_start;
  size_t      hole_size;
  uintptr_t   stack_start;

  ZLOGS(LOG_INSANE, "calling AllocateSpace(*,0x%016x)", ((size_t)1 << nap->addr_bits));
  AllocateSpace(&mem, (uintptr_t) 1U << nap->addr_bits);

  nap->mem_start = (uintptr_t) mem;
  ZLOGS(LOG_INSANE, "allocated memory at 0x%08x", nap->mem_start);

  hole_start = ROUNDUP_64K(nap->data_end);

  ZLOGFAIL(nap->stack_size >= ((uintptr_t) 1U) << nap->addr_bits,
      EFAULT, "AllocAddrSpace: stack too large!");
  stack_start = (((uintptr_t) 1U) << nap->addr_bits) - nap->stack_size;
  stack_start = ROUNDUP_64K(stack_start);

  ZLOGFAIL(stack_start < hole_start, EFAULT,
      "Memory 'hole' between end of BSS and start of stack is negative in size");

  hole_size = stack_start - hole_start;
  hole_size = ROUNDUP_64K(hole_size);

  /*
   * mprotect and madvise unused data space to "free" it up, but
   * retain mapping so no other memory can be mapped into those
   * addresses.
   */
  if(hole_size != 0)
  {
    ZLOGS(LOG_INSANE, "madvising 0x%08x, 0x%08x, MADV_DONTNEED",
        nap->mem_start + hole_start, hole_size);

    ZLOGFAIL(0 != NaCl_madvise((void*)(nap->mem_start + hole_start), hole_size,
        MADV_DONTNEED), errno, "madvise failed. cannot release unused data segment");

    ZLOGS(LOG_INSANE, "mprotecting 0x%08x, 0x%08x, PROT_NONE",
        nap->mem_start + hole_start, hole_size);

    ZLOGFAIL(0 != NaCl_mprotect((void *)(nap->mem_start + hole_start), hole_size,
        PROT_NONE), errno, "mprotect failed. cannot protect pages");
  }
  else
    ZLOGS(LOG_INSANE, "there is no hole between end of data and the beginning of stack");
}

void MemoryProtection(struct NaClApp *nap)
{
  uintptr_t start_addr;
  size_t    region_size;
  int       err;

  /*
   * The first NACL_SYSCALL_START_ADDR bytes are mapped as PROT_NONE.
   * This enables NULL pointer checking, and provides additional protection
   * against addr16/data16 prefixed operations being used for attacks.
   *
   * MprotectGuards also sets up guard pages outside of the
   * virtual address space of the NaClApp -- for the ARM and x86-64
   * where data sandboxing only sandbox memory writes and not reads,
   * we need to ensure that certain addressing modes that might
   * otherwise allow the NaCl app to write outside its address space
   * (given how we using masking / base registers to implement data
   * write sandboxing) won't affect the trusted data structures.
   */

  ZLOGS(LOG_INSANE, "Protecting guard pages for 0x%08x", nap->mem_start);
  MprotectGuards(nap);

  start_addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
  /*
   * The next pages up to NACL_TRAMPOLINE_END are the trampolines.
   * Immediately following that is the loaded text section.
   * These are collectively marked as PROT_READ | PROT_EXEC.
   */
  region_size = ROUNDUP_4K(nap->static_text_end - NACL_SYSCALL_START_ADDR);
  ZLOGS(LOG_INSANE, "Trampoline/text region start 0x%08x, size 0x%08x, end 0x%08x",
          start_addr, region_size, start_addr + region_size);

  err = NaCl_mprotect((void *)start_addr, region_size, PROT_READ | PROT_EXEC);
  ZLOGFAIL(0 != err, err, FAILED_MSG);

  SET_MEM_MAP_IDX(nap->mem_map[TextIdx], "Text",
      start_addr, region_size, PROT_READ | PROT_EXEC);

  /* zerovm does not support dynamic text directly (see trap (un)jail) */
  region_size = nap->dynamic_text_end - nap->dynamic_text_start;
  ZLOGFAIL(0 != region_size, ENOEXEC, "zerovm does not support dynamic text");

  if(0 != nap->rodata_start)
  {
    uintptr_t rodata_end;

    /*
     * TODO(mseaborn): Could reduce the number of cases by ensuring
     * that nap->data_start is always non-zero, even if
     * nap->rodata_start == nap->data_start == nap->break_addr.
     */
    if(0 != nap->data_start)
      rodata_end = nap->data_start;
    else rodata_end = nap->break_addr;

    start_addr = NaClUserToSys(nap, nap->rodata_start);
    region_size = ROUNDUP_4K(ROUNDUP_64K(rodata_end)
        - NaClSysToUser(nap, start_addr));
    ZLOGS(LOG_INSANE, "RO data region start 0x%08x, size 0x%08x, end 0x%08x",
        start_addr, region_size, start_addr + region_size);

    err = NaCl_mprotect((void *)start_addr, region_size, PROT_READ);
    ZLOGFAIL(0 != err, err, FAILED_MSG);

    SET_MEM_MAP_IDX(nap->mem_map[RODataIdx], "ROData",
        start_addr, region_size, PROT_READ);
  }

  /*
   * data_end is max virtual addr seen, so start_addr <= data_end
   * must hold.
   */
  if(0 != nap->data_start)
  {
    start_addr = NaClUserToSys(nap, nap->data_start);
    region_size = ROUNDUP_4K(ROUNDUP_64K(nap->data_end)
        - NaClSysToUser(nap, start_addr));
    ZLOGS(LOG_INSANE, "RW data region start 0x%08x, size 0x%08x, end 0x%08x",
        start_addr, region_size, start_addr + region_size);

    err = NaCl_mprotect((void *)start_addr, region_size, PROT_READ | PROT_WRITE);
    ZLOGFAIL(0 != err, err, FAILED_MSG);

    SET_MEM_MAP_IDX(nap->mem_map[HeapIdx], "Heap",
        start_addr, region_size, PROT_READ | PROT_WRITE);
  }

  /* stack is read/write but not execute */
  region_size = nap->stack_size;
  start_addr = NaClUserToSys(nap,
      ROUNDUP_64K(((uintptr_t) 1U << nap->addr_bits) - nap->stack_size));
  ZLOGS(LOG_INSANE, "RW stack region start 0x%08x, size 0x%08lx, end 0x%08x",
          start_addr, region_size, start_addr + region_size);

  err = NaCl_mprotect((void *)start_addr, ROUNDUP_64K(nap->stack_size),
      PROT_READ | PROT_WRITE);
  ZLOGFAIL(0 != err, err, FAILED_MSG);

  SET_MEM_MAP_IDX(nap->mem_map[StackIdx], "Stack",
      start_addr, ROUNDUP_64K(nap->stack_size), PROT_READ | PROT_WRITE);
}


<|start_filename|>src/main/zlog.h<|end_filename|>
/*
 * zerovm log system. uses syslog to output messages.
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ZLOG_H_
#define ZLOG_H_

#include <syslog.h>
#include "src/main/tools.h"

EXTERN_C_BEGIN

/*
 * ZLOG(format, ...) - add file and line info to given message and put it to syslog
 * ZLOGS(format, ...) - put given message to syslog
 * ZLOGIF(condition, format, ...) - check condition and, if true, ZLOG it
 * ZLOGFAIL(condition, code, format, ...) - check condition, if true, ZLOG it and exit with code
 */
#define ZLOG ZLogTag(__FILE__, __LINE__), ZLog
#define ZLOGIF ZLogTag(__FILE__, __LINE__), LogIf
#define ZLOGFAIL ZLogTag(__FILE__, __LINE__), FailIf
#define ZLOGS ZLogTag(NULL, 0), ZLog
#define FAILED_MSG "check failed"

/* develop fix for verbosity level names */
#undef LOG_DEBUG

#define LOG_INSANE 3 /* shows everything, slows down logging */
#define LOG_DEBUG  2 /* shows calls history */
#define LOG_ERROR  1 /* mandatory message */
#define LOG_FATAL  0 /* for completeness. not used */

/* initialize syslog with verbosity */
void ZLogCtor(int v);

/* close the log, reset verbosity level */
void ZLogDtor();

/*
 * store file and line information to the log tag
 * should be used from ZLOG, ZLOGS, ZLOGIF, ZLOGFAIL
 */
void ZLogTag(const char *file, int line);

/*
 * append stored debug information and log given message
 * should be used from ZLOG, ZLOGS
 */
void ZLog(int priority, char *fmt, ...);

/* if condition is true, log and abort. should be used from ZLOGFAIL */
void FailIf(int cond, int err, char const *fmt, ...);

/* if condition is true, log and continue. should be used from ZLOGIF */
void LogIf(int cond, char const *fmt, ...);

EXTERN_C_END

#endif /* ZLOG_H_ */


<|start_filename|>tests/functional/demo/dummy/dummy.c<|end_filename|>
/*
 * dummy
 */
#include "api/zvm.h"

void _start()
{
  zvm_exit(0);
}


<|start_filename|>src/platform/sel_memory.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Simple/secure ELF loader (NaCl SEL) memory protection / allocation
 * abstractions.
 */

#ifndef SEL_MEMORY_H_
#define SEL_MEMORY_H_ 1

#include "src/main/tools.h"

EXTERN_C_BEGIN

/* d'b: a global function now */
int NaCl_page_alloc_intern_flags(void **p, size_t size, int map_flags);

int NaCl_page_free(void *p, size_t num_bytes);

/*
 * This is critical to make the text region non-writable, and the data
 * region read/write but no exec.  Of course, some kernels do not
 * respect the lack of PROT_EXEC.
 */
int NaCl_mprotect(void *addr, size_t len, int prot) NACL_WUR;

int NaCl_madvise(void *start, size_t length, int advice) NACL_WUR;

EXTERN_C_END

#endif /*  SEL_MEMORY_H_ */


<|start_filename|>src/main/report.h<|end_filename|>
/*
 * finalizer, report and exit
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef EXIT_H_
#define EXIT_H_ 1

#include "src/main/tools.h"
#include "src/loader/sel_ldr.h"

#define UNKNOWN_STATE "unknown error, see syslog"
#define OK_STATE "ok"

EXTERN_C_BEGIN

/* assign file handle to put report */
void SetReportHandle(int handle);

/* put report to syslog instead of stdout */
void ReportMode(int mode);

/* set the text for "exit state" in report */
void SetExitState(const char *state);

/* set zerovm exit code */
void SetExitCode(int code);

/* get zerovm exit code */
int GetExitCode();

/* set user session exit code */
void SetUserCode(int code);

/* set validation state (0 - passed, 1 - failed, 2 - disabled) */
void SetValidationState(int state);

/* set daemon state (0: regualr session, 1: daemon mode started)*/
void SetDaemonState(int state);

/* set zerovm command line for debug purposes */
void SetCmdString(GString *s);

/* add tag digest with given name */
void ReportTag(char *name, void *tag);

/* initialize report internals */
void ReportCtor();

/*
 * report intermediate session statistics as often as defined by QUANT
 * TODO(d'b): self-initializing. move it to ReportCtor()
 * note: will not drop reports if waiting time is more than QUANT,
 *       however reports number can be lesser than run time in seconds
 */
void FastReport();

/* full report (declared for daemon) */
void Report(struct NaClApp *nap);

/*
 * exit zerovm. if code != 0 log it and show dump. release resources
 * note: use global nap because can be invoked from signal handler
 */
void ReportDtor(int code);

EXTERN_C_END

#endif /* EXIT_H_ */


<|start_filename|>src/platform/qualify.c<|end_filename|>
/*
 * Copyright 2010 The Native Client Authors.  All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <setjmp.h>
#include <stdint.h>
#include "src/main/zlog.h"
#include "src/main/tools.h"

/*
 * A void nullary function.  We generate functions of this type in the heap and
 * stack to prove that we cannot call them.  See GenerateThunk, below.
 */
typedef void (*nacl_void_thunk)();

/* Assembled equivalent of "ret" */
#define INST_RET 0xC3
#define EXPECTED_SIGNAL SIGSEGV

static struct sigaction previous_sigaction;
static struct sigaction try_sigaction;
static sigjmp_buf try_state;

static void signal_catch(int sig)
{
  siglongjmp(try_state, sig);
}

static void setup_signals()
{
  try_sigaction.sa_handler = signal_catch;
  sigemptyset(&try_sigaction.sa_mask);
  try_sigaction.sa_flags = SA_RESETHAND;

  (void) sigaction(EXPECTED_SIGNAL, &try_sigaction, &previous_sigaction);
}

static void restore_signals()
{
  (void) sigaction(EXPECTED_SIGNAL, &previous_sigaction, 0);
}

/*
 * Generates an architecture-specific void thunk sequence into the provided
 * buffer.  Returns a pointer to the thunk (which may be offset into the
 * buffer, depending on alignment constraints etc.).
 *
 * If the buffer is too small for the architecture's thunk sequence, returns
 * NULL.  In general the buffer should be more than 4 bytes.
 *
 * NOTE: the implementation of this function is architecture-specific, and can
 * be found beneath arch/ in this directory.
 */
static nacl_void_thunk GenerateThunk(char *buf, size_t size_in_bytes)
{
  /* Place a "ret" at buf */
  if (size_in_bytes < 1) return 0;

  *buf = (char) INST_RET;

  /*
   * ISO C prevents a direct data->function cast, because the pointers aren't
   * guaranteed to be the same size.  For our platforms this is fine, but we
   * verify at compile time anyway before tricking the compiler:
   */
  ASSERT_SAME_SIZE(char *, nacl_void_thunk);
  return (nacl_void_thunk) (uintptr_t) buf;
}

/* Returns 1 if Data Execution Prevention is present and working */
static int AttemptToExecuteData()
{
  int result;
  char *thunk_buffer = g_malloc(64);
  nacl_void_thunk thunk;

  /* d'b: small fixes */
  if(thunk_buffer == NULL) return 0;
  thunk = GenerateThunk(thunk_buffer, 64);
  setup_signals();

  if(0 == sigsetjmp(try_state, 1))
  {
    thunk();
    result = 0;
  }
  else
  {
    result = 1;
  }

  restore_signals();
  g_free(thunk_buffer);
  return result;
}

void RunSelQualificationTests()
{
  ZLOGFAIL(!AttemptToExecuteData(), EFAULT, "dep not supported");
}


<|start_filename|>src/main/accounting.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <time.h>
#include "src/loader/sel_ldr.h"
#include "src/main/accounting.h"
#include "src/main/manifest.h"

#define FMT "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu %lu %lu"

static int64_t network_stats[LimitsNumber] = {0};
static int64_t local_stats[LimitsNumber] = {0};
static float user_time = 0;
static float sys_time = 0;

/* count i/o statistics */
static void CountBytes(struct Connection *c, int size, int index)
{
  int64_t *acc;

  assert(c != NULL);
  assert(size >= 0);

  /* update statistics */
  acc = IS_FILE(c) ? local_stats : network_stats;
  acc[index + 1] += size;
  ++acc[index];
}

void CountGet(struct Connection *c, int size)
{
  CountBytes(c, size, GetsLimit);
}

void CountPut(struct Connection *c, int size)
{
  CountBytes(c, size, PutsLimit);
}

/* get I/O and CPU time */
static void SystemAccounting()
{
  FILE *f;
  int code;
  uint64_t t[4];
  char *path;
  float ticks = sysconf(_SC_CLK_TCK);

  /* get system information */
  path = g_strdup_printf("/proc/%d/stat", getpid());
  f = fopen(path, "r");
  if(f == NULL) return;
  code = fscanf(f, FMT, &t[0], &t[1], &t[2], &t[3]);
  ZLOGIF(code != 4, "error %d occurred while reading '%s'", errno, path);

  /* set I/O and CPU time */
  sys_time = (t[1] + t[3]) / ticks;
  user_time = (t[0] + t[2]) / ticks;
  g_free(path);
  fclose(f);
}

/* returns string i/o statistics */
static char *Accounting(int fast)
{
  return g_strdup_printf("%.2f %.2f %ld %ld %ld %ld %ld %ld %ld %ld",
      fast ? 0 : sys_time /* TODO(d'b): put I/O time instead of 0 */,
      fast ? clock() / (float)CLOCKS_PER_SEC : user_time,
      local_stats[GetsLimit], local_stats[GetSizeLimit],
      local_stats[PutsLimit], local_stats[PutSizeLimit],
      network_stats[GetsLimit], network_stats[GetSizeLimit],
      network_stats[PutsLimit], network_stats[PutSizeLimit]);
}

char *FastAccounting()
{
  return Accounting(1);
}

char *FinalAccounting()
{
  SystemAccounting();
  return Accounting(0);
}

void ResetAccounting()
{
  memset(network_stats, 0, sizeof network_stats);
  memset(local_stats, 0, sizeof network_stats);
}


<|start_filename|>src/channels/channel.h<|end_filename|>
/*
 * channels constructor / destructor API
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef CHANNEL_H_
#define CHANNEL_H_

#include <sys/un.h>
#include "api/zvm.h"
#include "src/main/etag.h"
#include "src/main/manifest.h"

EXTERN_C_BEGIN

/* net buffer size depends on it */
#define BUFFER_SIZE 0x10000
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif

/* zerovm channels names */
#define STDIN "/dev/stdin"
#define STDOUT "/dev/stdout"
#define STDERR "/dev/stderr"
#define STDRAM "/dev/memory"

#define FLAG_VALID_MASK 8
#define IS_NETWORK(c) ((c)->protocol < ProtoRegular)
#define IS_FILE(c) (!IS_NETWORK(c))
#define IS_IPHOST(c) ((c)->flags & 1)
#define IS_VALID(c) (!((c)->flags & FLAG_VALID_MASK))

/* CH_RW_TYPE returns 0..3 */
#define IS_NIL(channel) (CH_RW_TYPE(channel) == 0)
#define IS_RO(channel) (CH_RW_TYPE(channel) == 1)
#define IS_WO(channel) (CH_RW_TYPE(channel) == 2)
#define IS_RW(channel) (CH_RW_TYPE(channel) == 3)
#define CH_RW_TYPE(channel) \
    (((channel)->limits[GetsLimit] && (channel)->limits[GetSizeLimit]) \
    | ((channel)->limits[PutsLimit] && (channel)->limits[PutSizeLimit]) << 1)

#define CH_CH(manifest, n) ((struct ChannelDesc*)manifest->channels->pdata[n])
#define CH_FILE(channel, n) ((struct File*)channel->source->pdata[n])
#define CH_CONN(channel, n) ((struct Connection*)channel->source->pdata[n])
#define CH_HANDLE(channel, n) (CH_FILE(channel, n))->handle
#define CH_PROTO(channel, n) (CH_FILE(channel, n))->protocol
#define CH_FLAGS(channel, n) (CH_FILE(channel, n))->flags
#define CH_NAME(channel, n) (CH_FILE(channel, n))->name
#define CH_HOST(channel, n) (CH_CONN(channel, n))->host
#define CH_PORT(channel, n) (CH_CONN(channel, n))->port
#define CH_BACKUP(channel, n) (CH_CONN(channel, n))->backup

#define CH_SEQ_READABLE(channel) (((channel)->type & 1) == 0)
#define CH_SEQ_WRITEABLE(channel) (((channel)->type & 2) == 0)
#define CH_RND_READABLE(channel) (((channel)->type & 1) == 1)
#define CH_RND_WRITEABLE(channel) (((channel)->type & 2) == 2)

/* sort channels */
void SortChannels(GPtrArray *channels);

/* construct all channels, initialize it and update system_manifest */
void ChannelsCtor(struct Manifest *manifest);

/* free channels resources */
void ChannelsDtor(struct Manifest *manifest);

/* read channel data through multiple sources */
int32_t ChannelRead(struct ChannelDesc *channel,
    char *buffer, size_t size, off_t offset);

/* write channel data through multiple sources */
int32_t ChannelWrite(struct ChannelDesc *channel,
    const char *buffer, size_t size, off_t offset);

EXTERN_C_END

#endif /* CHANNEL_H_ */


<|start_filename|>tests/functional/exit/exit.c<|end_filename|>
/*
 * trap exit test
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

int main()
{
  UNREFERENCED_VAR(errcount);
  fprintf(STDERR, "TEST SUCCEED\n");
  zvm_exit(1234);

  /* to prevent falling into endless loop provoke SIGSEGV */
  fprintf(STDERR, "OVERALL TEST FAILED with 1 error\n");
  asm("hlt");
  return 0;
}


<|start_filename|>tests/functional/channels/ranro/ranro.c<|end_filename|>
/*
 * random read only channel test. tests statistics goes to stdout channel.
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define RANRO "/dev/ranro"

int main(int argc, char **argv)
{
  char buf[BIG_ENOUGH];

  /* correct requests */
  FPRINTF(STDERR, "TEST RANDOM READ ONLY CHANNEL\n");
  FPRINTF(STDERR, "channel size = %d\n", MANIFEST->channels[OPEN(RANRO)].size);
  ZTEST(MANIFEST->channels[OPEN(RANRO)].size != 0);
  ZTEST(PREAD(RANRO, buf, 0, 0) == 0);
  ZTEST(PREAD(RANRO, buf, 0, 1) == 0);
  ZTEST(PREAD(RANRO, buf, 1, 0) == 1);
  ZTEST(PREAD(RANRO, buf, 1, MANIFEST->channels[OPEN(RANRO)].size - 1) == 1);
  ZTEST(PREAD(RANRO, buf, 0, -1) == 0);

  /* incorrect requests: NULL buffer */
  ZTEST(PREAD(RANRO, NULL, 0, 0) < 0);
  ZTEST(PREAD(RANRO, NULL, 0, 1) < 0);
  ZTEST(PREAD(RANRO, NULL, 1, 0) < 0);
  ZTEST(PREAD(RANRO, NULL, 1, MANIFEST->channels[OPEN(RANRO)].size - 1) < 0);
  ZTEST(PREAD(RANRO, NULL, 0, -1) < 0);

  /* incorrect requests: size */
  ZTEST(PREAD(RANRO, buf, -1, 0) < 0);

  /* incorrect requests: offset */
  ZTEST(PREAD(RANRO, buf, 0, -1) == 0);
  ZTEST(PREAD(RANRO, buf, 1, -1) < 0);
  ZTEST(PREAD(RANRO, buf, 1, MANIFEST->channels[OPEN(RANRO)].size) == 0);

  /* correct requests: writing of 0 bytes attempt */
  ZTEST(PWRITE(RANRO, buf, 0, 0) == 0);

  /* incorrect requests: write attempt */
  ZTEST(PWRITE(RANRO, buf, 1, 0) < 0);
  ZTEST(PWRITE(RANRO, buf, 1, MANIFEST->channels[OPEN(RANRO)].size) < 0);
  ZTEST(PWRITE(RANRO, buf, 1, MANIFEST->channels[OPEN(RANRO)].size - 1) < 0);

  /* incorrect requests: exhausted */
  ZTEST(PREAD(RANRO, buf, 31, 0) == 30);
  ZTEST(PREAD(RANRO, buf, 10, 0) < 0);

  /* count errors and exit with it */
  ZREPORT;
  return 0;
}


<|start_filename|>src/syscalls/switch_to_app.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Service Runtime, C-level context switch code.
 */

#ifndef SWITCH_TO_APP_H__
#define SWITCH_TO_APP_H__ 1

#include "src/loader/sel_ldr.h"

EXTERN_C_BEGIN

void InitSwitchToApp(struct NaClApp *nap);

extern NORETURN void SwitchAVX(struct ThreadContext *context);
extern NORETURN void SwitchSSE(struct ThreadContext *context);
NORETURN void (*ContextSwitch)(struct ThreadContext *context);

EXTERN_C_END

#endif /* SWITCH_TO_APP_H__ */


<|start_filename|>tests/functional/demo/debug/hello.c<|end_filename|>
/*
 * this sample is a simple demonstration of zerovm.
 * the "hello world" program as usual.
 */
#include "include/zvmlib.h"

int main()
{
  /* write to stdout channel */
  PRINTF("\033[1mhello from dev/stdout!\033[0m\n");

  /* write to stderr channel */
  FPRINTF(STDERR, "\033[36mhello from dev/stderr!\033[0m\n");

  return 0;
}


<|start_filename|>src/channels/nservice.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <arpa/inet.h> /* ip <-> int */
#include <assert.h>
#include <errno.h>
#include "src/channels/channel.h"
#include "src/channels/nservice.h"

/*
 * name server expects all data in the big endian. but on the big
 * endian platform name service data doesn't need to be converted
 */
#if BYTE_ORDER == BIG_ENDIAN
#define bswap_16(a)
#define bswap_32(a)
#define bswap_64(a)
#else
#include <byteswap.h>
#endif

#define RETRY 3 /* poll retries */
#define TIMEOUT 1200000 /* poll timeout in microseconds */
#define PARCEL_SIZE 65507 /* maximum size of an UDP packet */

/*
 * parcel will have at least 1 record or will not send
 * TODO(d'b): to prevent the structure padding the pragma was used
 * develop some more portable way (casting to array is ugly)
 */

/* host is node id when sending to NS and ip when receiving */
#pragma pack(push, 1)
struct NSRecord
{
  uint32_t host;
  uint16_t port;
};

struct NSParcel
{
  uint32_t node;
  uint32_t bind_number;
  uint32_t connect_number;
  struct NSRecord records[1];
};
#pragma pack(pop)

/* get next bind/connect source */
#define NEXT_SRC() \
    do { \
      c = CH_CONN(CH_CH(manifest, m), n++); \
      if(n == CH_CH(manifest, m)->source->len) \
      { \
        ++m; \
        n = 0; \
        continue; \
      } \
    } while(c->protocol != ProtoTCP && IS_IPHOST(c))

/* serialize channels data to the parcel. return parcel and its "size" */
static void *ParcelCtor(const struct Manifest *manifest,
    uint32_t *size, uint32_t binds, uint32_t connects)
{
  struct NSParcel *p;
  int64_t end = binds + connects;
  int64_t m = 0, n = 0;
  int64_t i;

  /* allocate parcel */
  *size = sizeof *p + (end - 1) * sizeof(struct NSRecord);
  p = g_malloc(*size);

  /* parcel header */
  p->node = bswap_32(manifest->node);
  p->bind_number = bswap_32(binds);
  p->connect_number = bswap_32(connects);

  /* populate parcel with bind/connect records */
  for(i = 0; i < end; ++i)
  {
    struct Connection *c;
    NEXT_SRC();
    p->records[i].host = bswap_32(c->host);
    p->records[i].port = bswap_16(c->port);
  }

  return (void*)p;
}

/* de-serialize channels data from the parcel. return number of sources */
static int ParcelDtor(struct Manifest *manifest, char *parcel)
{
  struct NSParcel *p = (void*)parcel;
  int64_t end = bswap_32(p->bind_number) + bswap_32(p->connect_number);
  int64_t m = 0, n = 0;
  int64_t i;

  /* update channels sources from the parcel */
  for(i = 0; i < end; ++i)
  {
    struct Connection *c;
    NEXT_SRC();

    /* skip "binds" */
    if(i < bswap_32(p->bind_number)) continue;

    /* ip is already in network format for inet_ntoa */
    c->host = p->records[i].host;
    c->port = bswap_16(p->records[i].port);
  }

  g_free(parcel);
  return end;
}
#undef NEXT_SRC

/*
 * send the parcel to the name server and get it back
 * return the received parcel size
 */
static int32_t PollServer(const struct Connection *server, char *parcel, uint32_t size)
{
  int i;
  int s;
  int32_t result;
  struct sockaddr_in addr;
  uint32_t len = sizeof addr;
  struct timeval timeout = {TIMEOUT / MICRO_PER_SEC, TIMEOUT % MICRO_PER_SEC};

  /* connect to the name server */
  s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  addr.sin_addr.s_addr = server->host;
  addr.sin_port = bswap_16(server->port);
  addr.sin_family = AF_INET;

  /* set timeout on socket i/o */
  result = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof timeout);
  ZLOGFAIL(result == -1, errno, "cannot set receiving timeout");
  result = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout);
  ZLOGFAIL(result == -1, errno, "cannot set sending timeout");

  /* poll server */
  for(i = 0; i < RETRY; ++i)
  {
    result = sendto(s, parcel, size, 0, &addr, sizeof addr);
    if(result < 0) continue;
    result = recvfrom(s, parcel, size, 0, &addr, &len);
    if(result > 0) break;
  }

  ZLOGIF(i && result > 0, "name service polled with %d retries", i);
  ZLOGFAIL(result == -1, errno, "name service failed");
  close(s);
  return result;
}

void NameServiceCtor(struct Manifest *manifest, uint32_t b, uint32_t c)
{
  char *parcel;
  uint32_t psize;
  uint32_t control_psize;
  uint32_t control_nsources;

  assert(manifest != NULL);
  assert(manifest->channels != NULL);
  assert(b + c <= MAX_CHANNELS_NUMBER);

  /* return if there is no name service or network sources */
  if(manifest->name_server == NULL) return;
  if(b + c < 1) return;

  /* create parcel */
  ZLOGFAIL(manifest->node < 1, EFAULT, "invalid node: %d", manifest->node);
  ZLOGFAIL(manifest->name_server->protocol != ProtoUDP,
      EFAULT, "name server only support udp protocol");
  parcel = ParcelCtor(manifest, &psize, b, c);

  /* exchange parcels with name server */
  control_psize = PollServer(manifest->name_server, parcel, psize);
  ZLOGFAIL(control_psize != psize, EFAULT,
      "received parcel size %u is not equal to sent one %u",
      control_psize, psize);

  /* decode received parcel to channels */
  control_nsources = ParcelDtor(manifest, parcel);
  ZLOGFAIL(control_nsources != b + c, EFAULT,
      "received parcel records %u is not equal to sent ones %u",
      control_nsources, b + c);
}

void NameServiceDtor()
{
}


<|start_filename|>tests/security/execute_data/execute_data.c<|end_filename|>
/*
 * Copyright 2010 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
#include "include/zvmlib.h"

/*
 * We put the buffer in the data segment (low address) rather than on
 * the stack (high address) so that the address is not affected by the
 * ARM sandbox's 0xf000000f address masking.  However, ARM's mask
 * should be relaxed -- see
 * http://code.google.com/p/nativeclient/issues/detail?id=462.
 * -- and then this comment can be removed (TODO(mseaborn)).
 */
#if defined(__i386__) || defined(__x86_64__)
uint8_t code[] __attribute__((aligned(32)))= { 0xc3 /* ret */ };
#elif defined(__arm__)
uint32_t code[] __attribute__((aligned(32)))= { 0xe12fff1e /* BX LR */ };
#else
# error Unknown architecture
#endif

int main() 
{
  void (*func)();

  /* Double cast required to stop gcc complaining. */
  func = (void (*)()) (uintptr_t) code;

  FPRINTF(STDOUT, "This should fault...\n");
  func();
  FPRINTF(STDOUT, "We're still running. This is bad.\n");
  return 1;
}


<|start_filename|>tests/functional/demo/lz4/Makefile<|end_filename|>
NAME=lz4demo
CCFLAGS=-n -g -nostartfiles -nostdlib -fno-builtin

all: $(NAME).c lz4.c
	@x86_64-nacl-gcc -o $(NAME).nexe $(CCFLAGS) -Wall -msse4.1 \
	-O6 -I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional $^ \
	$(ZEROVM_ROOT)/tests/functional/include/libzvmlib.a
	@dd if=/dev/zero of=input.data bs=1048576 count=256 2> /dev/null
	@sed 's#PWD#$(PWD)#g' $(NAME).template > $(NAME).manifest
	@echo lz4\\n/dev/stdin\\n/dev/stdout > nvram
	@$(ZEROVM_ROOT)/zerovm -PQs $(NAME).manifest
	@./lz4demo -t output.lz4

clean:
	rm -f $(NAME).nexe $(NAME).o lz4.o *.log *.lz4 *.data *.manifest nvram*


<|start_filename|>tests/functional/channels/seqro/seqro.c<|end_filename|>
/*
 * sequential read only channel test. tests statistics goes to stdout channel
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define SEQRO "/dev/seqro"

/* TODO: replace it by the right include */
#define EINVAL 22

const char* target = "It is the read only target for the read";

int main(int argc, char **argv)
{
  char buf[BIG_ENOUGH];

  /* correct requests */
  FPRINTF(STDERR, "TEST SEQUENTIAL READ ONLY CHANNEL\n");
  FPRINTF(STDERR, "channel size = %ld\n", MANIFEST->channels[OPEN(SEQRO)].size);
  ZTEST(MANIFEST->channels[OPEN(SEQRO)].size == 0);
  ZTEST(PREAD(SEQRO, buf, 0, 0) == 0);
  ZTEST(PREAD(SEQRO, buf, 0, 1) == 0);
  ZTEST(PREAD(SEQRO, buf, 1, 0) == 1);
  ZTEST(PREAD(SEQRO, buf, 1, MANIFEST->channels[OPEN(SEQRO)].size - 1) == 1);
  ZTEST(PREAD(SEQRO, buf, 0, -1) == 0);

  /* incorrect requests: NULL buffer */
  ZTEST(PREAD(SEQRO, NULL, 0, 0) < 0);
  ZTEST(PREAD(SEQRO, NULL, 0, 1) < 0);
  ZTEST(PREAD(SEQRO, NULL, 1, 0) < 0);
  ZTEST(PREAD(SEQRO, NULL, 1, MANIFEST->channels[OPEN(SEQRO)].size - 1) < 0);
  ZTEST(PREAD(SEQRO, NULL, 0, -1) < 0);

  /* incorrect requests: read only buffer */
  ZTEST(PREAD(SEQRO, target, 0, 0) == -EINVAL);
  ZTEST(PREAD(SEQRO, target, 0, 1) == -EINVAL);
  ZTEST(PREAD(SEQRO, target, 1, 0) == -EINVAL);
  ZTEST(PREAD(SEQRO, target, 1,
              MANIFEST->channels[OPEN(SEQRO)].size - 1) == -EINVAL);
  ZTEST(PREAD(SEQRO, target, 0, -1) == -EINVAL);

  /* incorrect requests: read only memory: MANIFEST */
  ZTEST(PREAD(SEQRO, MANIFEST->channels[OPEN(SEQRO)].name, 0, 0) == -EINVAL);
  ZTEST(PREAD(SEQRO, MANIFEST->channels[OPEN(SEQRO)].name, 0, 1) == -EINVAL);
  ZTEST(PREAD(SEQRO, MANIFEST->channels[OPEN(SEQRO)].name, 1, 0) == -EINVAL);

  /* incorrect requests: size */
  ZTEST(PREAD(SEQRO, buf, -1, 0) < 0);

  /* incorrect requests: offset */
  ZTEST(PREAD(SEQRO, buf, 0, -1) == 0);
  ZTEST(PREAD(SEQRO, buf, 1, -1) == 1);
  ZTEST(PREAD(SEQRO, buf, 1, MANIFEST->channels[OPEN(SEQRO)].size) == 1);

  /* correct requests: writing of 0 bytes attempt */
  ZTEST(PWRITE(SEQRO, buf, 0, 0) == 0);

  /* incorrect requests: write attempt */
  ZTEST(PWRITE(SEQRO, buf, 1, 0) < 0);
  ZTEST(PWRITE(SEQRO, buf, 1, MANIFEST->channels[OPEN(SEQRO)].size) < 0);
  ZTEST(PWRITE(SEQRO, buf, 1, MANIFEST->channels[OPEN(SEQRO)].size - 1) < 0);

  /* incorrect requests: exhausted */
  ZTEST(PREAD(SEQRO, buf, 30, 0) == 28);
  ZTEST(PREAD(SEQRO, buf, 10, 0) < 0);

  /* count errors and exit with it */
  ZREPORT;
  return 0;
}


<|start_filename|>src/syscalls/trap.h<|end_filename|>
/*
 * "single syscall" engine. this is the replacement for nacl multiple syscalls
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TRAP_H_
#define TRAP_H_

EXTERN_C_BEGIN

/*
 * 1st parameter is a pointer to the command (function, arg1, argv2,..)
 * 2nd parameter is a pointer to return value(s)
 * return 0 if successful, otherwise -errno
 *
 * notice about args: since nacl patches two 1st arguments if they are pointers,
 * arg[1] should not be used
 */
int32_t TrapHandler(struct NaClApp *nap, uint32_t args);

EXTERN_C_END

#endif /* TRAP_H_ */


<|start_filename|>tests/functional/demo/big1/big1.c<|end_filename|>
/*
 * the big one
 */
#ifdef __ZEROVM__
#include "include/zvmlib.h"
#else
#include <stdio.h>
#include <stdint.h>
#define STDERR stderr
#endif

int main()
{
  long long i = 0;

#include "big1.h"

  return i;
}


<|start_filename|>src/syscalls/snapshot.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * TODO(d'b): design (under construction)
 * image consist of 4 main parts:
 * 1. user memory map (for mprotect()'ion)
 * 2. user memory dump
 * 3. user context (registers) + user_ret (user entry point)
 * 4. manifest (text file, variable size, ends with eof)
 *
 * to save image
 * - check session status (should be "ok")
 * - check "Save" value
 * - catch TrapSave (drop, hold, shot, snap)
 * - store all mentioned above data into the file
 *
 * to restore image (zerovm initialization as usual)
 * - allocate user space
 * - read (to user space) memory map (it is 64kb)
 * - read (to user space) memory dump until hole (infer from map)
 * - read (to user space) the rest (user manifest and stack)
 * - read user context and initialize nacl_sys
 * - reconstruct nap from data above (nap->sysret to TrapSave retcode)
 * - return to user code (user_ret from image contain entry point)
 *
 * CHANGES IN ZEROVM DESIGN
 * - main() loading of program with all checks allocations should be wrapped and carried out
 * - CreateSession() should not set user stack and affected things
 * - add manifest text to nap or manifest
 */
#include <stdio.h>
#include <assert.h>
#include "src/loader/sel_ldr.h"
#include "src/main/zlog.h"
#include "src/syscalls/snapshot.h"

static int image = -1;

/*
 * return 0: given file contains session, -1: random file
 * note: initializes image handler
 */
#define MAGIC 0x3030474d494d565aULL
static int IsImage(const char *name)
{
  uint64_t magic = 0;
  int code;

  /* open image */
  if(image < 0)
    image = open(name, O_RDONLY);
  if(image < 0) return -1;

  /* read "magic" */
  code = read(image, &magic, sizeof magic);
  return code == sizeof magic ? magic == MAGIC ? 0 : -1 : -1;
}

/* get memory map from system */
static void *GetSystemMemoryMap()
{
  return NULL;
}

/* save memory map to image */
static int SaveMemoryMap(void *map)
{
  return -1;
}

/* save 1st part of user memory dump to image */
static int SaveMemory1(struct NaClApp *nap, void *map)
{
  return -1;
}

/* save 2nd part of user memory dump to image */
static int SaveMemory2(struct NaClApp *nap, void *map)
{
  return -1;
}

/* save user context to image */
static int SaveUserContext(struct NaClApp *nap)
{
  return -1;
}

/* save text manifest to image */
static int SaveManifest(struct NaClApp *nap)
{
  return -1;
}

/* .. */

/* load memory map from image to user space */
static void *LoadMemoryMap(struct NaClApp *nap)
{
  return NULL;
}

/* load 1st part of memory dump from image to user space */
static void LoadMemory1(struct NaClApp *nap, void *map)
{
}

/* load 2nd part of memory dump from image to user space */
static void LoadMemory2(struct NaClApp *nap, void *map)
{
}

/* load user context from image to user space */
static void LoadUserContext(struct NaClApp *nap)
{
}

/* read old manifest from image, and check it up against the new one */
static void CheckManifest(struct NaClApp *nap)
{
}

int SaveSession(struct NaClApp *nap)
{
  int code;
  void *map;

  map = GetSystemMemoryMap();
  if(map == NULL) return -1;

  code = SaveMemoryMap(map);
  if(code < 0) return -1;

  code = SaveMemory1(nap, map);
  if(code < 0) return -1;

  code = SaveMemory2(nap, map);
  if(code < 0) return -1;

  code = SaveUserContext(nap);
  if(code < 0) return -1;

  code = SaveManifest(nap);
  if(code < 0) return -1;

  return 0;
}

int LoadSession(struct NaClApp *nap, const char *name)
{
  void *map;
  if(IsImage(name) < 0) return -1;

  map = LoadMemoryMap(nap);
  LoadMemory1(nap, map);
  LoadMemory2(nap, map);
  LoadUserContext(nap);
  CheckManifest(nap);

  return 0;
}


<|start_filename|>tests/unit/sel_ldr_test.cc<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * update(d'b): i think this test can be removed (or should be rewritten)
 */

#include "src/loader/sel_ldr.h"
#include "gtest/gtest.h"

//
// There are several problems in how these tests are set up.
//
// 1. NaCl modules such as the Log module are supposed to be
// initialized at process startup and finalized at shutdown.  In
// particular, there should not be any threads other than the main
// thread running when the Log module initializes, since the verbosity
// level is set then -- and thereafter it is assumed to be invariant
// and read without acquring locks.  If any threads are left running
// (e.g., NaClApp internal service threads), then race detectors would
// legitimately report an error which is inappropriate because the
// test is ignoring the API contract.
//
// 2. NaClApp objects, while they don't have a Dtor, are expected to
// have a lifetime equal to that of the process that contain them.  In
// particular, when the untrusted thread invokes the exit syscall, it
// expects to be able to use _exit to exit, killing all other
// untrusted threads as a side effect.  Furthermore, once a NaClApp
// object is initialized and NaClAppLaunchServiceThreads invoked,
// system service threads are running holding references to the
// NaClApp object.  If the NaClApp object goes out of scope or is
// otherwise destroyed and its memory freed, then these system thread
// may access memory that is no longer valid.  Tests cannot readily be
// written to cleanly exercise the state space of a NaClApp after
// NaClAppLaunchServiceThreads unless the test process exits---thereby
// killing the service threads as a side-effect---when each individual
// test is complete.
//
// These tests do not invoke NaClAppLaunchServiceThreads, so there
// should be no service threads left running between tests.

class SelLdrTest : public testing::Test {
 protected:
  virtual void SetUp();
  virtual void TearDown();
};

void SelLdrTest::SetUp() {
}

void SelLdrTest::TearDown() {
}

// set, get, setavail operations on the descriptor table
// todo: test is almost useless and should be removed or updated
TEST_F(SelLdrTest, DescTable) {
  struct NaClApp app = {0};

  NaClAppCtor(&app);
  ASSERT_EQ(NACL_MAX_ADDR_BITS, app.addr_bits);
  ASSERT_EQ((uintptr_t)NACL_DEFAULT_STACK_MAX, app.stack_size);
  ASSERT_EQ(0u, app.mem_start);
  ASSERT_EQ(0u, app.static_text_end);
  ASSERT_EQ(0u, app.dynamic_text_start);
  ASSERT_EQ(0u, app.dynamic_text_end);
  ASSERT_EQ(0u, app.rodata_start);
  ASSERT_EQ(0u, app.data_start);
  ASSERT_EQ(0u, app.data_end);
  ASSERT_EQ(0u, app.initial_entry_pt);
  ASSERT_EQ(0u, app.user_entry_pt);
}


<|start_filename|>tests/functional/channels/charo/Makefile<|end_filename|>
NAME=charo
CCFLAGS=-n -s -nostartfiles -nostdlib -fno-builtin

all: $(NAME).c
	@x86_64-nacl-gcc -o $(NAME).nexe $(CCFLAGS) -Wall -msse4.1 \
	-O2 -I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional $^ \
	$(ZEROVM_ROOT)/tests/functional/include/libzvmlib.a
	@sed 's#PWD#$(PWD)#g' $(NAME).template > $(NAME).manifest
	@echo 1111111111111111111111111111111 | $(ZEROVM_ROOT)/zerovm $(NAME).manifest

clean:
	rm -f $(NAME).nexe $(NAME).o *.log *.data *.manifest


<|start_filename|>tests/functional/include/Makefile<|end_filename|>
NAME=zvmlib

all: $(NAME).o bget.o printf.o
	x86_64-nacl-ar r lib$(NAME).a $^

$(NAME).o: $(NAME).c
	x86_64-nacl-gcc -c -Wall -O2 -msse4.1 $(DEFS) \
	-I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional -o $@ $^

bget.o: bget.c
	x86_64-nacl-gcc -c -Wall -O2 -msse4.1 $(DEFS) \
	-I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional -o $@ $^

printf.o: printf.c
	x86_64-nacl-gcc -c -Wall -O2 -msse4.1 $(DEFS) \
	-I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional -o $@ $^

clean:
	rm -f lib$(NAME).a $(NAME).o bget.o printf.o


<|start_filename|>src/syscalls/daemon.h<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef DAEMON_H_
#define DAEMON_H_

#include "src/loader/sel_ldr.h"

/*
 * convert current session to daemon mode. after each new session spawning
 * this function will return to trap to serve the new session. if there is
 * no "Job" in manifest just continue current session. return user session
 * code (0: finalize session , -1: continue session)
 */
int Daemon(struct NaClApp *nap);

#endif /* DAEMON_H_ */


<|start_filename|>debian/samples/zshell/Makefile<|end_filename|>
GTEST_CFLAGS=-DGTEST_HAS_PTHREAD=0
DEBUG=-g -DDEBUG
PNACL_TOOL=/usr/lib/nacl/default-sdk/toolchain/linux_x86_glibc
NACL_GCC=$(PNACL_TOOL)/bin/x86_64-nacl-gcc
INCLUDE_FLAGS=-I/usr/include/zerovm -I/usr/include/zerovm/lua -I/usr/include/zerovm/sqlite3 -I.
CFLAGS=-Wall -Wno-long-long -m64 -std=c99

all: createdirs clean zshell.nexe

zshell.nexe: obj/luaexec.o obj/main.o obj/sqlitequery.o
	$(NACL_GCC) -o zshell.nexe -s -static -T $(PNACL_TOOL)/x86_64-nacl/lib64/ldscripts/elf64_nacl.x.static \
	-melf64_nacl -m64 obj/luaexec.o obj/main.o obj/sqlitequery.o \
	-Wall -std=c99 -L/usr/lib/zerovm -lzrt -llua -lm -lsqlite3 -lfs -lstdc++ $(DEBUG)  

obj/main.o: main.c
	$(NACL_GCC) -c -o obj/main.o     $(INCLUDE_FLAGS) ${CFLAGS} $(DEBUG) main.c -DUSER_SIDE -D_GNU_SOURCE

obj/luaexec.o: luaexec.c
	$(NACL_GCC) -c -o obj/luaexec.o  $(INCLUDE_FLAGS) ${CFLAGS} $(DEBUG) luaexec.c -DUSER_SIDE

obj/sqlitequery.o: sqlitequery.c
	@$(PNACL_TOOL)/bin/x86_64-nacl-gcc -o obj/sqlitequery.o -Wall -std=c99 \
	$(INCLUDE_FLAGS) $(DEBUG) -c -Wno-long-long -O2 -m64 sqlitequery.c 

createdirs:
	@mkdir -p obj log

clean: 
	@rm -f obj/*.o
	@rm -f log/*.log log/*.stdout
	@rm -f sqlite/*.manifest
	@rm -f lua/*.manifest
	@rm -f zshell.nexe zshell_gcc



<|start_filename|>src/channels/prefetch_zmq.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <arpa/inet.h> /* convert ip <-> int */
#include <zmq.h>
#include "src/channels/prefetch.h"
#include "src/main/accounting.h"
#include "src/main/report.h"

#define NET_BUFFER_SIZE BUFFER_SIZE
#define ZMQ_ERR(code) ZLOGIF(code < 0, "failed: %s", zmq_strerror(zmq_errno()))

/* TODO(d'b): find more neat solution than put it twice */
#define XARRAY(a) static char *ARRAY_##a[] = {a};
#define X(a) #a,
  XARRAY(PROTOCOLS)
#undef X

static void *context = NULL; /* zeromq context */

/* return connection url. returned string must be freed with g_free */
static char *MakeURL(struct ChannelDesc *channel, int n)
{
  char *host = NULL;
  char *url = NULL;

  /* take host if specified */
  if(IS_WO(channel) || IS_IPHOST(CH_CONN(channel, n)))
  {
    struct in_addr ip;
    ip.s_addr = CH_HOST(channel, n);
    host = g_strdup_printf("%s", inet_ntoa(ip));
  }

  /* construct url */
  url = g_strdup_printf("%s://%s:%u",
      g_ascii_strdown(XSTR(PROTOCOLS, CH_PROTO(channel, n)), -1),
      host == NULL ? "*" : host, CH_PORT(channel, n));

  ZLOGS(LOG_INSANE, "url = %s", url);
  g_free(host);
  return url;
}

/* bind the RO source */
static void Bind(struct ChannelDesc *channel, int n)
{
  int result = -1;
  char port[BIG_ENOUGH_STRING];
  size_t size = sizeof port;
  char *url = MakeURL(channel, n);

  /* bind to 1st available port */
  result = zmq_bind(CH_HANDLE(channel, n), url);
  g_free(url);
  ZLOGFAIL(result != 0, EFAULT, "cannot bind %s;%d: %s", channel->alias, n,
      strerror(errno));
  result = zmq_getsockopt(CH_HANDLE(channel, n), ZMQ_LAST_ENDPOINT, &port, &size);
  ZLOGFAIL(result != 0, EFAULT, "cannot get port %s;%d: %s", channel->alias, n,
      strerror(errno));

  /* extract port to connection structure */
  CH_PORT(channel, n) = ToInt(g_strrstr(port, ":") + 1);
  ZLOGS(LOG_DEBUG, "bind(): host = %u, port = %u", CH_HOST(channel, n), CH_PORT(channel, n));
}

/* connect the WO source */
static void Connect(struct ChannelDesc *channel, int n)
{
  char *url;
  int hwm = 1;
  void *h = CH_HANDLE(channel, n);

  ZMQ_ERR(zmq_setsockopt(h, ZMQ_SNDHWM, &hwm, sizeof hwm));
  url = MakeURL(channel, n);
  ZLOGS(LOG_DEBUG, "connect url %s to %s;%d", url, channel->alias, n);
  ZMQ_ERR(zmq_connect(h, url));
  g_free(url);
}

void NetCtor(const struct Manifest *manifest)
{
  /* get zmq context */
  context = zmq_ctx_new();
  ZLOGFAIL(context == NULL, EFAULT, "cannot initialize zeromq context");
}

void NetDtor(struct Manifest *manifest)
{
  /* don't terminate if session is broken */
  if(GetExitCode() != 0) return;

  /*
   * it is possible to use zmq_term() from the old api, but i am not sure if it
   *  will work without hangups. note that zmq_ctx_term() is libzmq 4.0.1 only
   */
  zmq_ctx_term(context);
  context = NULL;
}

char *MessageData(struct ChannelDesc *channel)
{
  return (char*)zmq_msg_data(channel->msg);
}

void FreeMessage(struct ChannelDesc *channel)
{
  int result;

  /* prevent 0mq crash */
  if(GetExitCode() != 0) return;
  if(channel->msg == NULL) return;

  ZLOGS(LOG_DEBUG, "FreeMessage of %s", channel->alias);
  result = zmq_msg_close(channel->msg);
  g_free(channel->msg);
  channel->msg = NULL;
  ZMQ_ERR(result);
}

/* get the next message. updates channel->msg (and indices) */
static void GetMessage(struct ChannelDesc *channel, int n)
{
  ZLOGS(LOG_INSANE, "GetMessage of %s;%d", channel->alias, n);

  /* receive the next message and rewind buffer */
  ZMQ_ERR(zmq_msg_recv(channel->msg, CH_HANDLE(channel, n), 0));
  channel->bufend = zmq_msg_size(channel->msg);
  channel->bufpos = 0;
}

void FetchMessage(struct ChannelDesc *channel, int n)
{
  ZLOGS(LOG_INSANE, "FetchMessage of %s;%d", channel->alias, n);

  /* get message */
  if(channel->eof) return;
  GetMessage(channel, n);

  /* if EOF detected get the 2nd part */
  if(channel->bufend > 0) return;
  GetMessage(channel, n);
  channel->eof = 1;

  /* check EOF digest size */
  if(channel->bufend > 0)
    ZLOGFAIL(channel->bufend != TAG_DIGEST_SIZE, EFAULT,
        "invalid EOF size = %d", channel->bufend);
}

/* send message "channel->msg" */
static void SendMessage(struct ChannelDesc *channel, int n)
{
  ZLOGS(LOG_INSANE, "SendMessage to %s;%d", channel->alias, n);
  ZMQ_ERR(zmq_msg_send(channel->msg, CH_HANDLE(channel, n), 0));
}

int32_t SendData(struct ChannelDesc *channel, int n, const char *buf, int32_t count)
{
  int32_t writerest;

  assert(channel != NULL);
  assert(channel->msg != NULL);
  assert(buf != NULL);

  /* send a buffer through the multiple messages */
  ZLOGS(LOG_INSANE, "send(): channel %s;%d, buffer=0x%lx, size=%d",
      channel->alias, n, (intptr_t)buf, count);
  for(writerest = count; writerest > 0; writerest -= NET_BUFFER_SIZE)
  {
    int32_t towrite = MIN(writerest, NET_BUFFER_SIZE);

    /* create the message */
    ZMQ_ERR(zmq_msg_init_size(channel->msg, towrite));
    memcpy(MessageData(channel), buf, towrite);

    /* send the message */
    SendMessage(channel, n);
    buf += towrite;
  }

  return count;
}

void SyncSource(struct ChannelDesc *channel, int n)
{
  if(!CH_SEQ_READABLE(channel)) return;

  ZLOGS(LOG_INSANE, "%s;%d before skip pos = %ld, getpos = %ld",
      channel->alias, n, CH_CONN(channel, n)->pos, channel->getpos);

  /* if source is a pipe read (*->getpos - *->pos) bytes */
  if(CH_PROTO(channel, n) == ProtoFIFO || CH_PROTO(channel, n) == ProtoCharacter)
  {
    int result;
    while(CH_CONN(channel, n)->pos < channel->getpos)
    {
      char buf[BUFFER_SIZE];
      result = fread(buf, 1, channel->getpos - CH_CONN(channel, n)->pos,
          CH_HANDLE(channel, n));
      ZLOGFAIL(result < 0, EIO, "%s;%d: %s", channel->alias, n, strerror(errno));
      CH_CONN(channel, n)->pos += result;
    }
  }

  /* if source is a network get over (*->getpos - *->pos) bytes */
  else if(IS_NETWORK(CH_CONN(channel, n)))
  {
    while(CH_CONN(channel, n)->pos < channel->getpos && !channel->eof)
    {
      FetchMessage(channel, n);
      CH_CONN(channel, n)->pos += channel->bufend;
    }
  }

  /* no need to sync with regular files, just set (*->getpos to *->pos) */
  else
    CH_CONN(channel, n)->pos = channel->getpos;

  ZLOGS(LOG_INSANE, "%s;%d skipped pos = %ld, getpos = %ld",
      channel->alias, n, CH_CONN(channel, n)->pos, channel->getpos);
  ZLOGFAIL(CH_CONN(channel, n)->pos != channel->getpos,
      EPIPE, "%s;%d is out of sync", channel->alias, n);
}

void PrefetchChannelCtor(struct ChannelDesc *channel, int n)
{
  int sock_type;
  struct Connection *c;

  assert(context != NULL);
  assert(channel != NULL);
  assert(n < channel->source->len);

  /* log parameters and channel internals */
  c = CH_CONN(channel, n);
  ZLOGS(LOG_DEBUG, "prefetch %s;%d", channel->alias, n);

  /* choose socket type */
  ZLOGFAIL((uint32_t)CH_RW_TYPE(channel) - 1 > 1, EFAULT, "invalid i/o type");
  CH_FLAGS(channel, n) |= (CH_RW_TYPE(channel) - 1) << 1;
  sock_type = IS_RO(channel) ? ZMQ_PULL : ZMQ_PUSH;

  /* open source (0mq socket) */
  c->handle = zmq_socket(context, sock_type);
  ZLOGFAIL(c->handle == NULL, EFAULT,
      "cannot get socket for %s;%d", channel->alias, n);

  /* allocate one message per channel */
  if(channel->msg == NULL)
  {
    channel->msg = g_malloc(sizeof(zmq_msg_t));
    ZMQ_ERR(zmq_msg_init(channel->msg));
  }

  /* bind or connect the channel */
  sock_type == ZMQ_PULL ? Bind(channel, n) : Connect(channel, n);
}

void PrefetchChannelDtor(struct ChannelDesc *channel, int n)
{
  char *url; /* debug purposes only */
  char buf[TAG_DIGEST_SIZE + 1] = "disabled", *digest = buf;
  int dsize = 0;

  /* skip source closing if session is broken */
  if(GetExitCode() != 0) return;

  assert(context != NULL);
  assert(channel != NULL);
  assert(n < channel->source->len);
  assert(CH_HANDLE(channel, n) != NULL);

  /* log parameters and channel internals */
  url = MakeURL(channel, n);
  ZLOGS(LOG_DEBUG, "closing %s;%d with url %s", channel->alias, n, url);

  /* close WO source (send EOF) */
  if(IS_WO(channel))
  {
    /* 1st EOF part */
    channel->eof = 1;
    ZMQ_ERR(zmq_msg_init_data(channel->msg, digest, 0, NULL, NULL));
    SendMessage(channel, n);

    /* last EOF part */
    if(channel->tag != NULL)
    {
      TagDigest(channel->tag, digest);
      dsize = TAG_DIGEST_SIZE;
    }
    ZMQ_ERR(zmq_msg_init_data(channel->msg, digest, dsize, NULL, NULL));
    SendMessage(channel, n);

    /* dummy message to avoid #197 */
    ZMQ_ERR(zmq_msg_init_data(channel->msg, digest, 0, NULL, NULL));
    SendMessage(channel, n);
    CountPut(CH_CONN(channel, n), 0);

    /* only for the last source */
    if(n == channel->source->len - 1)
      FreeMessage(channel);
  }
  /* close RO source, "fast forward" to EOF if needed */
  else
  {
    /*
     * TODO(d'b): this is a temporary solution. complete solution can be
     * implemented when daemon/proxy will be able to terminate zerovm by
     * request for instance when cluster is already done except "sending"
     * reserve node (reported as useless by "receiving" node(s))
     */
    if(CH_CONN(channel, n)->pos < channel->getpos)
      channel->eof = 0;

    /* read until EOF (to avoid hanging sending session) */
    for(; channel->eof == 0; FetchMessage(channel, n))
    {
      if(n == 0) channel->getpos += channel->bufend;
      CH_CONN(channel, n)->pos += channel->bufend;
      CountGet(CH_CONN(channel, n), channel->bufend);
    }

    /* get dummy message (#197) */
    channel->eof = 0;
    GetMessage(channel, n);
    channel->eof = 1;
    /* message will be deallocated later */
  }

  /* close source */
  ZMQ_ERR(zmq_close(CH_HANDLE(channel, n)));
  CH_HANDLE(channel, n) = NULL;
  ZLOGS(LOG_DEBUG, "%s closed", url);
  g_free(url);
}


<|start_filename|>src/channels/prefetch_udt.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <arpa/inet.h> /* convert ip <-> int */
#include <netdb.h>
#include <udt/udtc.h>
#include "src/channels/prefetch.h"
#include "src/main/accounting.h"
#include "src/main/report.h"

#define NET_BUFFER_SIZE BUFFER_SIZE
#define ERROR(code) ZLOGIF(code, "failed: %s", udt_getlasterror_desc())
#define MAX_CONN 1

/*
 * accept "bind" channels. since udt_accept() is a blocking thing
 * the function should be used *only* after other channels are mounted
 * TODO(d'b): remove it after "channels" re-design
 */
void PrefetchAccept(struct ChannelDesc *channel)
{
  int n;
  int result;
  struct sockaddr_in incoming;

  /* skip inappropriate channels */
  if(!IS_RO(channel)) return;

  for(n = 0; n < channel->source->len; ++n)
  {
    if(IS_FILE(CH_CONN(channel, n))) continue;

    result = udt_accept(GPOINTER_TO_INT(CH_HANDLE(channel, n)),
        (struct sockaddr*)&incoming, &result);
    CH_HANDLE(channel, n) = GINT_TO_POINTER(result);
    ZLOGFAIL(GPOINTER_TO_INT(CH_HANDLE(channel, n)) == UDT_INVALID_SOCK, EFAULT,
        "bind %s;%d: %s", channel->alias, n, udt_getlasterror_desc());
  }
}

/* bind the RO source */
static void Bind(struct ChannelDesc *channel, int n, struct addrinfo *local)
{
  int result;
  struct sockaddr_in incoming;
  int i = sizeof incoming;

  ZLOG(LOG_DEBUG, "Bind: %s;%d", channel->alias, n);

  /* bind */
  result = udt_bind(GPOINTER_TO_INT(CH_HANDLE(channel, n)),
      local->ai_addr, local->ai_addrlen);
  ZLOGFAIL(result != 0, EFAULT, "bind %s;%d: %s",
      channel->alias, n, udt_getlasterror_desc());

  /* listen */
  result = udt_listen(GPOINTER_TO_INT(CH_HANDLE(channel, n)), MAX_CONN);
  ZLOGFAIL(result == UDT_ERROR, EFAULT, "listen: %s", udt_getlasterror_desc());
  CH_BACKUP(channel, n) = CH_HANDLE(channel, n);

  /* get port */
  result = udt_getsockname(GPOINTER_TO_INT(CH_HANDLE(channel, n)),
      (struct sockaddr*)&incoming, &i);
  ZLOGFAIL(result == UDT_ERROR, EFAULT, "getsockname: %s", udt_getlasterror_desc());
  CH_PORT(channel, n) = ntohs(incoming.sin_port);
}

/* connect the WO source */
static void Connect(struct ChannelDesc *channel, int n, struct addrinfo *local)
{
  char *ip;
  char *port;
  int result;
  struct addrinfo *peer;
  struct in_addr ip_int;

  ZLOG(LOG_DEBUG, "Connect: %s;%d", channel->alias, n);

  /* update connection information (do we really need it?) */
  ip_int.s_addr = CH_HOST(channel, n);
  ip = inet_ntoa(ip_int);
  port = g_strdup_printf("%d", CH_PORT(channel, n));
  ZLOGFAIL(getaddrinfo(ip, port, local, &peer) != 0, EFAULT,
      "%s;%d has incorrect network address", channel->alias, n);

  /* connect */
  result = udt_connect(GPOINTER_TO_INT(CH_HANDLE(channel, n)),
      peer->ai_addr, peer->ai_addrlen);
  freeaddrinfo(peer);
  ZLOGFAIL(result != 0, EFAULT, "connect %s;%d: %s",
      channel->alias, n, udt_getlasterror_desc());
}

void NetCtor(const struct Manifest *manifest)
{
  ZLOG(LOG_DEBUG, "NetCtor: udt");
  ZLOGFAIL(udt_startup() != 0, EFAULT, "udt: %s", udt_getlasterror_desc());
}

void NetDtor(struct Manifest *manifest)
{
  ZLOG(LOG_DEBUG, "NetDtor: udt");
  ZLOGFAIL(udt_cleanup() != 0, EFAULT, "udt: %s", udt_getlasterror_desc());
}

char *MessageData(struct ChannelDesc *channel)
{
  ZLOG(LOG_DEBUG, "MessageData: %s", channel->alias);
  return channel->msg;
}

void FreeMessage(struct ChannelDesc *channel)
{
  ZLOG(LOG_DEBUG, "FreeMessage: %s", channel->alias);
  if(IS_RO(channel)) g_free(channel->msg);
  channel->msg = NULL;
}

/* get the next message. updates channel->msg (and indices) */
static void GetMessage(struct ChannelDesc *channel, int n, int size)
{
  ZLOGS(LOG_INSANE, "GetMessage: %s;%d", channel->alias, n);
  channel->bufpos = 0;
  channel->bufend = 0;

  while(channel->bufend < size && !channel->eof)
  {
    int i = udt_recv(GPOINTER_TO_INT(CH_HANDLE(channel, n)),
        channel->msg + channel->bufend, size - channel->bufend, 0);
    if(i < 0) break;
    else
      channel->bufend += i;
  }

  /* only set EOF if this read returned nothing */
  if(channel->bufend == 0)
    channel->eof = 1;
}

void FetchMessage(struct ChannelDesc *channel, int n)
{
  ZLOGS(LOG_INSANE, "FetchMessage: %s;%d", channel->alias, n);

  /*
   * ->bufpos contains read size to workaround problem with
   * incomplete messages (usual case for udt).
   * TODO(d'b): rewrite it when 0mq support will be removed
   */
  assert(channel->bufpos <= NET_BUFFER_SIZE);
  assert(channel->bufpos > 0);

  /* get message */
  if(!channel->eof)
    GetMessage(channel, n, channel->bufpos);
}

int32_t SendData(struct ChannelDesc *channel, int n, const char *buf, int32_t count)
{
  int i;
  int pos;

  assert(channel != NULL);
  assert(buf != NULL);
  assert(count >= 0);

  ZLOGS(LOG_INSANE, "SendData: channel %s;%d, buffer=0x%lx, size=%d",
      channel->alias, n, (intptr_t)buf, count);

  /* send a buffer through the multiple messages */
  for(pos = 0; pos < count; pos += i)
  {
    i = MIN(NET_BUFFER_SIZE, count - pos);
    i = udt_send(GPOINTER_TO_INT(CH_HANDLE(channel, n)), buf + pos, i, 0);
    ZLOGFAIL(i < 0, EFAULT, "send: %s", udt_getlasterror_desc());
  }

  return count;
}

void SyncSource(struct ChannelDesc *channel, int n)
{
  if(!CH_SEQ_READABLE(channel)) return;

  ZLOGS(LOG_INSANE, "SyncSource: %s;%d before skip pos = %ld, getpos = %ld",
      channel->alias, n, CH_CONN(channel, n)->pos, channel->getpos);

  /* if source is a pipe read (*->getpos - *->pos) bytes */
  if(CH_PROTO(channel, n) == ProtoFIFO || CH_PROTO(channel, n) == ProtoCharacter)
  {
    int result;
    while(CH_CONN(channel, n)->pos < channel->getpos)
    {
      char buf[BUFFER_SIZE];
      result = fread(buf, 1, channel->getpos - CH_CONN(channel, n)->pos,
          CH_HANDLE(channel, n));
      ZLOGFAIL(result < 0, EIO, "%s;%d: %s", channel->alias, n, strerror(errno));
      CH_CONN(channel, n)->pos += result;
    }
  }

  /* if source is a network get over (*->getpos - *->pos) bytes */
  else if(IS_NETWORK(CH_CONN(channel, n)))
  {
    channel->eof = 0;
    while(CH_CONN(channel, n)->pos < channel->getpos && !channel->eof)
    {
      int size = channel->getpos - CH_CONN(channel, n)->pos;
      GetMessage(channel, n, size < NET_BUFFER_SIZE ? size : NET_BUFFER_SIZE);
      CH_CONN(channel, n)->pos += channel->bufend;
    }
  }

  /* no need to sync with regular files, just set (*->getpos to *->pos) */
  else
    CH_CONN(channel, n)->pos = channel->getpos;

  ZLOGS(LOG_INSANE, "%s;%d skipped pos = %ld, getpos = %ld",
      channel->alias, n, CH_CONN(channel, n)->pos, channel->getpos);
  ZLOGFAIL(CH_CONN(channel, n)->pos != channel->getpos, EPIPE,
      "%s;%d is out of sync: %ld:%ld", channel->alias, n,
      CH_CONN(channel, n)->pos, channel->getpos);
}

void PrefetchChannelCtor(struct ChannelDesc *channel, int n)
{
  int i;
  char *ip;
  char *port;
  struct addrinfo hint = {0};
  struct addrinfo *local;
  struct in_addr ip_int;

  assert(channel != NULL);
  assert(n < channel->source->len);
  ZLOGS(LOG_DEBUG, "PrefetchChannelCtor %s;%d", channel->alias, n);

  /* choose socket type */
  ZLOGFAIL((uint32_t)CH_RW_TYPE(channel) - 1 > 1, EFAULT, "invalid i/o type");
  CH_FLAGS(channel, n) |= (CH_RW_TYPE(channel) - 1) << 1;

  /* get address structure via "hint" to "local" */
  hint.ai_flags = AI_PASSIVE;
  hint.ai_family = AF_INET;
  hint.ai_socktype = SOCK_STREAM;

  ip_int.s_addr = CH_HOST(channel, n);
  ip = IS_RO(channel) ? NULL : inet_ntoa(ip_int);
  port = g_strdup_printf("%d", CH_PORT(channel, n));
  ZLOGFAIL(getaddrinfo(ip, port, &hint, &local) != 0, EFAULT,
      "%s;%d has incorrect network address", channel->alias, n);

  /* open socket */
  i = udt_socket(local->ai_family, local->ai_socktype, local->ai_protocol);
  ZLOGFAIL(i == UDT_INVALID_SOCK, EFAULT, "%s;%d: %s",
      channel->alias, n, udt_getlasterror_desc());
  CH_HANDLE(channel, n) = GINT_TO_POINTER(i);

  /* do NOT reuse an existing address */
  i = 0;
  ZLOGFAIL(udt_setsockopt(GPOINTER_TO_INT(CH_HANDLE(channel, n)), 0, UDT_UDT_REUSEADDR,
      &i, sizeof i) == UDT_ERROR, EFAULT, "%s", udt_getlasterror_desc());

  /*
   * TODO(d'b): remove this when code will be re-factored to use the user
   * provided buffer
   */
  channel->msg = IS_RO(channel) ? g_malloc(NET_BUFFER_SIZE) : NULL;

  /* bind or connect the channel */
  IS_RO(channel) ? Bind(channel, n, local) : Connect(channel, n, local);
  freeaddrinfo(local);
}

void PrefetchChannelDtor(struct ChannelDesc *channel, int n)
{
  /* skip source closing if session is broken */
  if(GetExitCode() != 0) return;

  assert(channel != NULL);
  assert(n < channel->source->len);
  assert(CH_HANDLE(channel, n) != NULL);
  ZLOGS(LOG_DEBUG, "closing %s;%d", channel->alias, n);

  /*
   * TODO(d'b): this is the 1st version of UDT EOF. the channel source
   * does not have digest. the digest will be added later
   */
  /* close WO source (send EOF) */
  if(IS_WO(channel))
  {
    /* <...> EOF removed */
  }
  /* close RO source, "fast forward" to EOF if needed */
  else
  {
    /* <...> EOF and source "rewinding" removed */
    channel->eof = 1;
  }

  /* close source */
  udt_close(GPOINTER_TO_INT(CH_HANDLE(channel, n)));
  udt_close(GPOINTER_TO_INT(CH_BACKUP(channel, n)));
  CH_HANDLE(channel, n) = NULL;
  CH_BACKUP(channel, n) = NULL;
  ZLOGS(LOG_DEBUG, "%s;%d closed", channel->alias, n);
}


<|start_filename|>src/platform/sel_memory.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/mman.h>
#include "src/main/zlog.h"

int NaCl_page_alloc_intern_flags(void **p, size_t size, int map_flags)
{
  void *addr;

  map_flags |= MAP_PRIVATE | MAP_ANONYMOUS;

  ZLOGS(LOG_INSANE, "mmap(%p, %lX, %#x, %#x, %d, %d)", *p, size, PROT_NONE, map_flags, -1, 0);

  addr = mmap(*p, size, PROT_NONE, map_flags, -1, (off_t)0);
  if(MAP_FAILED == addr) addr = NULL;
  if(NULL != addr) *p = addr;
  return (NULL == addr) ? -ENOMEM : 0;
}

int NaCl_page_free(void *p, size_t size)
{
  int ret = munmap(p, size);

  return ret == -1 ? -errno : ret;
}

int NaCl_mprotect(void *addr, size_t len, int prot)
{
  int ret = mprotect(addr, len, prot);

  return ret == -1 ? -errno : ret;
}

int NaCl_madvise(void *start, size_t length, int advice)
{
  int ret = madvise(start, length, advice);

  /* MADV_DONTNEED and MADV_NORMAL are needed */
  return ret == -1 ? -errno : ret;
}


<|start_filename|>tests/functional/demo/lz4/lz4demo.c<|end_filename|>
/*
 LZ4Demo - Demo CLI program using LZ4 compression
 Copyright (C) <NAME> 2011-2012
 GPL v2 License

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 You can contact the author at :
 - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html
 - LZ4 source repository : http://code.google.com/p/lz4/
 */
/*
 Note : this is *only* a demo program, an example to show how LZ4 can be used.
 It is not considered part of LZ4 compression library.
 The license of LZ4 is BSD.
 The license of the demo program is GPL.
 */
 /* d'b: ported to zerovm platform */

//**************************************
// Compiler Options
//**************************************
// Disable some Visual warning messages
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE     // VS2005

//****************************
// Includes
//****************************
#include "lz4.h"

/* d'b */
#include "include/zvmlib.h"

#define fprintf FPRINTF
#define read READ
#define write WRITE
#undef stderr
#define stderr STDERR

//**************************************
// Compiler-specific functions
//**************************************
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)

#if GCC_VERSION >= 403
#define swap32 __builtin_bswap32
#else
static inline unsigned int swap32(unsigned int x)
{
  return ((x << 24) & 0xff000000 ) |
  ((x << 8) & 0x00ff0000 ) |
  ((x >> 8) & 0x0000ff00 ) |
  ((x >> 24) & 0x000000ff );
}
#endif

//****************************
// Constants
//****************************
#define COMPRESSOR_NAME "Compression CLI using LZ4 algorithm"
#define COMPRESSOR_VERSION ""
#define COMPILED __DATE__
#define AUTHOR "<NAME>"
#define EXTENSION ".lz4"
#define WELCOME_MESSAGE "*** %s %s, by %s (%s) ***\n", COMPRESSOR_NAME, COMPRESSOR_VERSION, AUTHOR, COMPILED

#define CHUNKSIZE (8<<20)    // 8 MB
#define CACHELINE 64
#define ARCHIVE_MAGICNUMBER 0x184C2102
#define ARCHIVE_MAGICNUMBER_SIZE 4

//**************************************
// Architecture Macros
//**************************************
static const int one = 1;
#define CPU_LITTLE_ENDIAN  (*(char*)(&one))
#define CPU_BIG_ENDIAN     (!CPU_LITTLE_ENDIAN)
#define LITTLE_ENDIAN32(i) if (CPU_BIG_ENDIAN) { i = swap32(i); }

//**************************************
// Macros
//**************************************
#define DISPLAY(...) fprintf(stderr, __VA_ARGS__)

//****************************
// Functions
//****************************
int usage(char* exename)
{
  DISPLAY( "Usage :\n");
  DISPLAY( "      %s [arg] input output\n", exename);
  DISPLAY( "Arguments :\n");
  DISPLAY( " -c0: Fast compression (default) \n");
  DISPLAY( " -c1: High compression \n");
  DISPLAY( " -d : decompression \n");
  DISPLAY( " -b#: Benchmark files, using # compression level\n");
  DISPLAY( " -t : check compressed file \n");
  DISPLAY( " -h : help (this text)\n");
  DISPLAY( "input  : can be 'stdin' (pipe) or a filename\n");
  DISPLAY( "output : can be 'stdout'(pipe) or a filename or 'null'\n");
  return 0;
}

int badusage(char* exename)
{
  DISPLAY("Wrong parameters\n");
  usage(exename);
  return 0;
}

int compress_file(char* input_filename, char* output_filename, int compressionlevel)
{
  int (*compressionFunction)(const char*, char*, int);
  unsigned long long filesize = 0;
  unsigned long long compressedfilesize = ARCHIVE_MAGICNUMBER_SIZE;
  unsigned int u32var;
  char* in_buff;
  char* out_buff;
  int displayLevel = (compressionlevel > 0);
  size_t sizeCheck;

  // Init
  compressionFunction = LZ4_compress;

  // Allocate Memory
  in_buff = (char*) malloc(CHUNKSIZE);
  out_buff = (char*) malloc(LZ4_compressBound(CHUNKSIZE));
  if(!in_buff || !out_buff)
  {
    DISPLAY("Allocation error : not enough memory\n");
    return 8;
  }

  // Write Archive Header
  u32var = ARCHIVE_MAGICNUMBER;
  LITTLE_ENDIAN32(u32var);
  *(unsigned int*) out_buff = u32var;
  sizeCheck = write(output_filename, out_buff, ARCHIVE_MAGICNUMBER_SIZE);

  if(sizeCheck != ARCHIVE_MAGICNUMBER_SIZE)
  {
    DISPLAY("write error\n");
    return 10;
  }

  // Main Loop
  while(1)
  {
    int outSize;
    // Read Block
    int inSize = (int) read(input_filename, in_buff, (size_t)CHUNKSIZE);

    if(inSize <= 0)
      break;
    filesize += inSize;
    if(displayLevel)
      DISPLAY("Read :   %i MB  \r", (int)(filesize>>20));

    // Compress Block
    outSize = compressionFunction(in_buff, out_buff + 4, inSize);
    compressedfilesize += outSize + 4;
    if(displayLevel)
      DISPLAY(
          "Read : %i MB  ==> %.2f%%\r", (int)(filesize>>20), (double)compressedfilesize/filesize*100);

    // Write Block
    LITTLE_ENDIAN32(outSize);
    *(unsigned int*) out_buff = outSize;
    LITTLE_ENDIAN32(outSize);
    sizeCheck = write(output_filename, out_buff, outSize+4);

    if(sizeCheck != (size_t) (outSize + 4))
    {
      DISPLAY("write error\n");
      return 11;
    }
  }

  // Status
  DISPLAY(
      "Compressed %u bytes into %u bytes ==> %2d%%\n", (unsigned long long) filesize, (unsigned long long) compressedfilesize, 100*compressedfilesize/filesize);

  // Close & Free
  free(in_buff);
  free(out_buff);

  return 0;
}

int decode_file(char* input_filename, char* output_filename)
{
  unsigned long long filesize = 0;
  char* in_buff;
  char* out_buff;
  size_t uselessRet;
  int sinkint;
  unsigned int chunkSize;
  size_t sizeCheck;

  // Allocate Memory
  in_buff = (char*) malloc(LZ4_compressBound(CHUNKSIZE));
  out_buff = (char*) malloc(CHUNKSIZE);
  if(!in_buff || !out_buff)
  {
    DISPLAY("Allocation error : not enough memory\n");
    return 7;
  }

  // Check Archive Header
  chunkSize = 0;
  uselessRet = read(input_filename, &chunkSize, ARCHIVE_MAGICNUMBER_SIZE);

  LITTLE_ENDIAN32(chunkSize);
  if(chunkSize != ARCHIVE_MAGICNUMBER)
  {
    DISPLAY("Unrecognized header : file cannot be decoded\n");
    return 6;
  }

  // Main Loop
  while(1)
  {
    // Block Size
    uselessRet = read(input_filename, &chunkSize, 4);

    if(uselessRet == 0)
      break; // Nothing to read : file read is completed
    LITTLE_ENDIAN32(chunkSize);
    if(chunkSize == ARCHIVE_MAGICNUMBER)
      continue; // appended compressed stream

    // Read Block
    uselessRet = read(input_filename, in_buff, chunkSize);

    // Decode Block
    sinkint = LZ4_uncompress_unknownOutputSize(in_buff, out_buff, chunkSize, CHUNKSIZE);
    if(sinkint < 0)
    {
      DISPLAY("Decoding Failed ! Corrupted input !\n");
      return 9;
    }
    filesize += sinkint;

    // Write Block
    sizeCheck = write(output_filename, out_buff, sinkint);

    if(sizeCheck != (size_t) sinkint)
    {
      DISPLAY("write error\n");
      return 12;
    }
  }

  // Status
  DISPLAY( "Successfully decoded %u bytes \n", (unsigned long long)filesize);

  // Close & Free
  free(in_buff);
  free(out_buff);

  return 0;
}

int main(int argc, char** argv)
{
  int i, cLevel = 0, decode = 0, bench = 0, filenamesStart = 2;
  char* exename = argv[0];
  char* input_filename = 0;
  char* output_filename = 0;
  char nulmark[] = "/dev/null";
  char nullinput[] = "null";

  // Welcome message
  DISPLAY( WELCOME_MESSAGE);

  if(argc < 2)
  {
    badusage(exename);
    return 1;
  }

  for(i = 1; i < argc; i++)
  {
    char* argument = argv[i];

    if(!argument)
      continue; // Protection if argument empty

    // Select command
    if(argument[0] == '-')
    {
      argument++;

      // Display help on usage
      if(argument[0] == 'h')
      {
        usage(exename);
        return 0;
      }

      // Compression (default)
      if(argument[0] == 'c')
      {
        if(argument[1] >= '0')
          cLevel = argument[1] - '0';
        continue;
      }

      // Decoding
      if(argument[0] == 'd')
      {
        decode = 1;
        continue;
      }

      // Bench
      if(argument[0] == 'b')
      {
        bench = 1;
        if(argument[1] >= '0')
          cLevel = argument[1] - '0';
        continue;
      }

      // Test
      if(argument[0] == 't')
      {
        decode = 1;
        output_filename = nulmark;
        continue;
      }
    }

    // first provided filename is input
    if(!input_filename)
    {
      input_filename = argument;
      filenamesStart = i;
      continue;
    }

    // second provided filename is output
    if(!output_filename)
    {
      output_filename = argument;
      if(!strcmp (output_filename, nullinput))
        output_filename = nulmark;
      continue;
    }
  }

  // No input filename ==> Error
  if(!input_filename)
  {
    badusage(exename);
    return 1;
  }

  // No output filename ==> Error
  if(!output_filename)
  {
    badusage(exename);
    return 1;
  }

  if(decode)
    return decode_file(input_filename, output_filename);

  return compress_file(input_filename, output_filename, cLevel); // Compression is 'default' action
}


<|start_filename|>tests/functional/demo/zhello/zhello.c<|end_filename|>
/*
 * hello world through zerovm api (main is omitted, _start used instead)
 */
#include "api/zvm.h"

/* constants */
#define stdout 1
#define stderr 2

/* functions */
#define fput(handle, msg) zvm_pwrite(handle, msg, sizeof msg, 0)
#define exit(c) zvm_exit(c)

void _start()
{
  fput(stdout, "\033[1mhello from dev/stdout!\033[0m\n");
  fput(stderr, "\033[36mhello from dev/stderr!\033[0m\n");
  
  exit(0);
}


<|start_filename|>src/main/manifest.c<|end_filename|>
/*
 * the manifest file format: key = value. parser ignores white spaces
 * each line can only contain single key=value
 *
 * the api is very simple: just call GetValuByKey() after
 * manifest is constructed
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * manifest parser. input: manifest file name. output: manifest structure
 */
#include <assert.h>
#include <arpa/inet.h> /* convert ip to int */
#include "src/main/manifest.h"
#include "src/channels/channel.h"

#define MFTFAIL ZLogTag("MANIFEST", cline), FailIf

/* general */
#define PTR_SIZE (sizeof(void*))
#define MANIFEST_VERSION "20130611"
#define MANIFEST_SIZE_LIMIT 0x80000
#define MANIFEST_LINES_LIMIT 0x2000
#define MANIFEST_TOKENS_LIMIT 0x10

/* delimiters */
#define LINE_DELIMITER "\n"
#define KEY_DELIMITER "="
#define VALUE_DELIMITER ","
#define TOKEN_DELIMITER ";"
#define CONNECTION_DELIMITER ":"

#define XARRAY(a) static char *ARRAY_##a[] = {a};
#define X(a) #a,
  XARRAY(PROTOCOLS)
#undef X

/* key/value tokens */
typedef enum {
  Key,
  Value,
  KeyValueTokensNumber
} KeyValueTokens;

/* memory tokens */
typedef enum {
  MemorySize,
  MemoryTag,
  MemoryTokensNumber
} MemoryTokens;

/* connection tokens */
typedef enum {
  Protocol,
  Host,
  Port,
  ConnectionTokensNumber
} ConnectionTokens;

/* channel tokens */
typedef enum {
  Name,
  Alias,
  Type,
  Tag,
  Gets,
  GetSize,
  Puts,
  PutSize,
  ChannelTokensNumber
} ChannelTokens;

/* (x-macro): manifest keywords (name, obligatory, singleton) */
#define KEYWORDS \
  X(Channel, 1, 0) \
  X(Version, 1, 1) \
  X(Program, 1, 1) \
  X(Memory, 1, 1) \
  X(Timeout, 1, 1) \
  X(NameServer, 0, 1) \
  X(Node, 0, 1) \
  X(Job, 0, 1) \
  X(Etag, 0, 1)

/* (x-macro): manifest enumeration, array and statistics */
#define XENUM(a) enum ENUM_##a {a};
#define X(a, o, s) Key ## a,
  XENUM(KEYWORDS)
#undef X

#define XARRAY(a) static char *ARRAY_##a[] = {a};
#define X(a, o, s) #a,
  XARRAY(KEYWORDS)
#undef X

#define XCHECK(a) static uint8_t CHECK_##a[] = {a};
#define X(a, o, s) o | (s << 1),
  XCHECK(KEYWORDS)
#undef X

/*
 * LOCAL variables and functions
 */
static int cline = 0;

/* get manifest data */
static void GetManifestData(const char *name, char *buf)
{
  FILE *h = fopen(name, "r");

  ZLOGFAIL(h == NULL, ENOENT, "manifest open error");
  ZLOGFAIL(fread(buf, 1, MANIFEST_SIZE_LIMIT, h) < 1, EIO, "manifest read error");
  fclose(h);
}

int64_t ToInt(char *a)
{
  int64_t result;

  errno = 0;
  a = g_strstrip(a);
  result = g_ascii_strtoll(a, &a, 0);
  MFTFAIL(*a != '\0' || errno != 0, EFAULT,
      "invalid numeric value '%s'", a);

  return result;
}

/*
 * return keyword and update given "value" with extracted value
 * spaces will be trimmed from "value"
 */
static XTYPE(KEYWORDS) GetKey(char *key)
{
  XTYPE(KEYWORDS) k;

  key = g_strstrip(key);
  for(k = 0; k < XSIZE(KEYWORDS); ++k)
    if(g_strcmp0(XSTR(KEYWORDS, k), key) == 0) return k;
  return -1;
}

/* test manifest version */
static void Version(struct Manifest *manifest, char *value)
{
  MFTFAIL(g_strcmp0(MANIFEST_VERSION, g_strstrip(value)) != 0,
      EFAULT, "invalid manifest version");
}

/* set program field (should be g_free later) */
static void Program(struct Manifest *manifest, char *value)
{
  manifest->program = g_strdup(g_strstrip(value));
}

/* set mem_size and mem_tag field */
static void Memory(struct Manifest *manifest, char *value)
{
  char **tokens;
  int tag;

  /* parse value */
  tokens = g_strsplit(value, VALUE_DELIMITER, MemoryTokensNumber);
  MFTFAIL(tokens[MemoryTokensNumber] != NULL || tokens[MemoryTag] == NULL,
      EFAULT, "invalid memory token");

  manifest->mem_size = ToInt(tokens[MemorySize]);
  tag = ToInt(tokens[MemoryTag]);

  /* initialize manifest field */
  MFTFAIL(tag != 0 && tag != 1, EFAULT, "invalid memory etag token");

  manifest->mem_tag = tag == 0 ? NULL : TagCtor();
  g_strfreev(tokens);
}

static void Timeout(struct Manifest *manifest, char *value)
{
  manifest->timeout = ToInt(value);
}

static void Node(struct Manifest *manifest, char *value)
{
  manifest->node = ToInt(value);
}

static void Job(struct Manifest *manifest, char *value)
{
  MFTFAIL(strlen(value) > UNIX_PATH_MAX, EFAULT, "too long Job name");
  manifest->job = g_strdup(g_strstrip(value));
}

static void Etag(struct Manifest *manifest, char *value)
{
  manifest->etag = g_strdup(g_strstrip(value));
}

/* convert ip address (or node id) to integer */
static uint32_t ExtractHost(char *host, uint8_t *flags)
{
  uint32_t result;

  *flags = 0;
  if(strchr(host, '.') != NULL)
  {
    struct sockaddr_in sa;
    *flags = 1;
    result = inet_pton(AF_INET, g_strstrip(host), &sa.sin_addr);
    result = result == 1 ? sa.sin_addr.s_addr : 0;
    MFTFAIL(result == 0, EFAULT, "malformed ip token");
  }
  else
    result = ToInt(host);

  return result;
}

/* analyze given string and return protocol id */
static XTYPE(PROTOCOLS) GetChannelProtocol(char *proto)
{
  XTYPE(PROTOCOLS) p;

  proto = g_strstrip(proto);
  for(p = 0; p < XSIZE(PROTOCOLS); ++p)
    if(g_ascii_strcasecmp(XSTR(PROTOCOLS, p), proto) == 0) return p;
  return -1;
}

/* parse the name and append to given array of names as connection or string */
static void ParseName(char *name, GPtrArray *names)
{
  char **tokens;
  XTYPE(PROTOCOLS) proto;

  name = g_strstrip(name);
  tokens = g_strsplit(name, CONNECTION_DELIMITER, ConnectionTokensNumber);
  proto = GetChannelProtocol(tokens[Protocol]);

  if(proto == -1)
  {
    struct File *f;
    MFTFAIL(tokens[1] != NULL, EFAULT, "invalid channel name");
    MFTFAIL(!g_path_is_absolute(name), EFAULT,
        "only absolute path channels are allowed");


    f = g_malloc0(sizeof *f);
    f->protocol = ProtoRegular; /* just in case (will be set later) */
    f->name = g_strdup(name);
    f->handle = NULL;
    g_ptr_array_add(names, f);
  }
  else
  {
    struct Connection *c = g_malloc0(sizeof *c);
    MFTFAIL(tokens[ConnectionTokensNumber] != NULL || tokens[Host] == NULL,
        EFAULT, "invalid channel url");

    c->protocol = proto;
    c->host = ExtractHost(tokens[Host], &c->flags);
    c->port = ToInt(tokens[Port]);
    c->handle = NULL;
    g_ptr_array_add(names, c);
  }

  g_strfreev(tokens);
}

/* TODO(d'b): it is ugly. solution needed */
static void NameServer(struct Manifest *manifest, char *value)
{
  GPtrArray *dummy = g_ptr_array_new();
  ParseName(value, dummy);
  manifest->name_server = g_ptr_array_index(dummy, 0);
  g_ptr_array_free(dummy, TRUE);
}

/* set channels field */
static void Channel(struct Manifest *manifest, char *value)
{
  char **tokens;
  char **names;
  int i;
  struct ChannelDesc *channel;

  /* allocate a new channel */
  channel = g_malloc0(sizeof *channel);
  channel->source = g_ptr_array_new();

  /* get tokens from channel description */
  tokens = g_strsplit(value, VALUE_DELIMITER, ChannelTokensNumber);

  /* TODO(d'b): fix "invalid numeric value ', 0'" bug here */
  MFTFAIL(tokens[ChannelTokensNumber] != NULL || tokens[PutSize] == NULL,
      EFAULT, "invalid channel tokens number");

  /* parse alias and name(s) */
  channel->alias = g_strdup(g_strstrip(tokens[Alias]));
  names = g_strsplit(tokens[Name], TOKEN_DELIMITER, MANIFEST_TOKENS_LIMIT);
  for(i = 0; names[i] != NULL; ++i)
    ParseName(names[i], channel->source);

  channel->type = ToInt(tokens[Type]);

  i = ToInt(tokens[Tag]);
  MFTFAIL(i != 0 && i != 1, EFAULT, "invalid channel numeric token");

  channel->tag = i == 0 ? NULL : TagCtor();

  for(i = 0; i < LimitsNumber; ++i)
  {
    channel->limits[i] = ToInt(tokens[i + Gets]);
    MFTFAIL(channel->limits[i] < 0, EFAULT,
        "negative limits for %s", channel->alias);
  }

  /* append a new channel */
  g_ptr_array_add(manifest->channels, channel);
  g_strfreev(names);
  g_strfreev(tokens);
}

/*
 * check if obligatory keywords appeared and check if the fields
 * which should appear only once did so
 */
static void CheckCounters(int *counters, int n)
{
  while(--n)
  {
    ZLOGFAIL(counters[n] == 0 && (CHECK_KEYWORDS[n] & 1),
        EFAULT, "%s not specified", XSTR(KEYWORDS, n));
    ZLOGFAIL(counters[n] > 1 && (CHECK_KEYWORDS[n] & 2),
        EFAULT, "duplicate %s keyword", XSTR(KEYWORDS, n));
  }
}

struct Manifest *ManifestTextCtor(char *text)
{
  struct Manifest *manifest = g_malloc0(sizeof *manifest);
  int counters[XSIZE(KEYWORDS)] = {0};
  char **lines;
  int i;

  /* initialize channels */
  manifest->channels = g_ptr_array_new();

  /* extract all lines */
  lines = g_strsplit(text, LINE_DELIMITER, MANIFEST_LINES_LIMIT);

  /* parse each line */
  for(i = 0; lines[i] != NULL; ++i)
  {
    char **tokens;
    cline = i + 1;

    tokens = g_strsplit(lines[i], KEY_DELIMITER, MANIFEST_TOKENS_LIMIT);
    if(strlen(lines[i]) > 0 && tokens[Key] != NULL
        && tokens[Value] != NULL && tokens[KeyValueTokensNumber] == NULL)
    {
      /* switch invoking functions by the keyword */
#define XSWITCH(a) switch(GetKey(tokens[Key])) {a};
#define X(a, o, s) case Key##a: ++counters[Key##a]; a(manifest, tokens[Value]); break;
      XSWITCH(KEYWORDS)
#undef X
    }
    g_strfreev(tokens);
  }

  /* check obligatory and singleton keywords */
  g_strfreev(lines);
  CheckCounters(counters, XSIZE(KEYWORDS));

  return manifest;
}

struct Manifest *ManifestCtor(const char *name)
{
  char buf[MANIFEST_SIZE_LIMIT] = {0};
  GetManifestData(name, buf);
  return ManifestTextCtor(buf);
}

void ManifestDtor(struct Manifest *manifest)
{
  int i;
  int j;

  if(manifest == NULL) return;

  /* channels */
  for(i = 0; i < manifest->channels->len; ++i)
  {
    struct ChannelDesc *channel = g_ptr_array_index(manifest->channels, i);

    /* sources */
    for(j = 0; j < channel->source->len; ++j)
    {
      struct File *file = g_ptr_array_index(channel->source, j);
      if(IS_FILE(file))
        g_free(file->name);
      g_free(file);
    }
    g_ptr_array_free(channel->source, TRUE);
    g_free(channel->alias);
    TagDtor(channel->tag);
    g_free(channel);
  }
  g_ptr_array_free(manifest->channels, TRUE);

  /* other */
  g_free(manifest->etag);
  TagDtor(manifest->mem_tag);
  g_free(manifest->name_server);
  g_free(manifest->program);
  g_free(manifest);
}


<|start_filename|>src/channels/preload.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include "src/channels/preload.h"

#define CHANNEL_RIGHTS S_IRUSR | S_IWUSR
#define DEV_NULL "/dev/null"

static int disable_preallocation = 0;

void PreloadAllocationDisable()
{
  disable_preallocation = 1;
}

/* detect and set source type */
#define SET(f, p) if(f(fs.st_mode)) CH_PROTO(channel, n) = Proto##p; else
static void SetChannelSource(struct ChannelDesc *channel, int n)
{
  struct stat fs;

  assert(channel != NULL);
  assert(CH_NAME(channel, n) != NULL);

  /*
   * get the file statistics and calculate the source type (if file
   * is not exist it will be regular)
   */
  if(stat(CH_NAME(channel, n), &fs) < 0) CH_PROTO(channel, n) = ProtoRegular; else
  SET(S_ISREG, Regular)
  SET(S_ISDIR, Directory)
  SET(S_ISCHR, Character)
  SET(S_ISBLK, Block)
  SET(S_ISFIFO, FIFO)
  SET(S_ISLNK, Link)
  SET(S_ISSOCK, Socket)
  ZLOGFAIL(1, EFAULT, "cannot detect source type of %s", CH_NAME(channel, n));
}

int PreloadChannelDtor(struct ChannelDesc *channel, int n)
{
  int code = 0;
  int handle;

  assert(channel != NULL);
  assert(n < channel->source->len);

  /* adjust the size of writable channels */
  handle = GPOINTER_TO_INT(CH_HANDLE(channel, n));
  if(channel->limits[PutSizeLimit] && channel->limits[PutsLimit]
     && CH_PROTO(channel, n) == ProtoRegular)
    code = ftruncate(handle, channel->size);

  ZLOGS(LOG_DEBUG,
      "%s closed with getsize = %ld, putsize = %ld", channel->alias,
      channel->counters[GetSizeLimit], channel->counters[PutSizeLimit]);

  if(handle != 0)
  {
    if(CH_PROTO(channel, n) == ProtoRegular)
      close(handle);
    else
      fclose(CH_HANDLE(channel, n));
  }

  g_ptr_array_remove(channel->source, CH_FILE(channel, n));
  return -(code != 0);
}

/* preallocate channel space if not disabled with "-P" */
static void PreallocateChannel(const struct ChannelDesc *channel, int n)
{
  int code;
  int handle = GPOINTER_TO_INT(CH_HANDLE(channel, n));

  if(disable_preallocation) return;
  code = ftruncate(handle, channel->limits[PutSizeLimit]);
  ZLOGFAIL(code == -1, errno, "cannot preallocate %s", channel->alias);
}

/* preload given character/FIFO device to channel */
static void CharacterChannel(struct ChannelDesc* channel, int n)
{
  char *mode[] = {NULL, "rb", "wb"};
  int flags[] = {0, O_RDONLY, O_RDWR};
  int h;

  ZLOGS(LOG_DEBUG, "preload character %s", channel->alias);
  ZLOGFAIL(!IS_RO(channel) && !IS_WO(channel), EINVAL,
      "%s has invalid i/o type", channel->alias);

  /* open file */
  h = open(CH_NAME(channel, n), flags[CH_RW_TYPE(channel)]);
  CH_HANDLE(channel, n) = fdopen(h, mode[CH_RW_TYPE(channel)]);
  ZLOGFAIL(CH_HANDLE(channel, n) == NULL, errno,
      "cannot open %s", CH_NAME(channel, n));

  /* set channel attributes */
  channel->size = 0;
}

/* preload given regular device to channel */
static void RegularChannel(struct ChannelDesc* channel, int n)
{
  int h;
  ZLOGS(LOG_DEBUG, "preload regular %s", channel->alias);

  switch(CH_RW_TYPE(channel))
  {
    case 1: /* read only */
      h = open(CH_NAME(channel, n), O_RDONLY, CHANNEL_RIGHTS);
      CH_HANDLE(channel, n) = GINT_TO_POINTER(h);
      channel->size = GetFileSize(CH_NAME(channel, n));
      ZLOGFAIL(channel->size < 0, EFAULT, "cannot open %s", CH_NAME(channel, n));
      break;

    case 2: /* write only. existing file will be overwritten */
      h = open(CH_NAME(channel, n), O_WRONLY|O_CREAT|O_TRUNC, CHANNEL_RIGHTS);
      CH_HANDLE(channel, n) = GINT_TO_POINTER(h);
      channel->size = 0;
      if(g_strcmp0(CH_NAME(channel, n), DEV_NULL) != 0)
        PreallocateChannel(channel, n);
      break;

    case 3: /* cdr or full random access */
      ZLOGFAIL(channel->type == SGetSPut, EFAULT,
          "sequential channels cannot have r/w access");
      ZLOGFAIL(channel->type == SGetRPut, EFAULT,
          "sequential read / random write channels not supported");

      /* open the file and ensure that putpos is not greater than the file size */
      h = open(CH_NAME(channel, n), O_RDWR | O_CREAT, CHANNEL_RIGHTS);
      CH_HANDLE(channel, n) = GINT_TO_POINTER(h);
      channel->size = GetFileSize(CH_NAME(channel, n));
      ZLOGFAIL(channel->size < 0, EFAULT, "cannot open %s", CH_NAME(channel, n));
      ZLOGFAIL(channel->putpos > channel->size, EFAULT,
          "%s size is less then specified append position", CH_NAME(channel, n));

      /* file does not exist */
      if(channel->size == 0 && g_strcmp0(CH_NAME(channel, n), DEV_NULL) != 0)
        PreallocateChannel(channel, n);
      /* existing file */
      else
        channel->putpos = channel->type == RGetSPut ? channel->size : 0;
      break;

    default:
      ZLOGFAIL(1, EINVAL, "%s has invalid i/o type", channel->alias);
      break;
  }

  ZLOGFAIL(GPOINTER_TO_INT(CH_HANDLE(channel, n)) < 0,
      errno, "%s open error", CH_NAME(channel, n));
}

void PreloadChannelCtor(struct ChannelDesc *channel, int n)
{
  assert(channel != NULL);
  assert(n < channel->source->len);

  /* check the given channel */
  ZLOGS(LOG_DEBUG, "mounting file %s to alias %s",
      CH_NAME(channel, n), channel->alias);

  SetChannelSource(channel, n);

  switch(CH_PROTO(channel, n))
  {
    case ProtoRegular:
      RegularChannel(channel, n);
      break;
    case ProtoCharacter:
    case ProtoFIFO:
      CharacterChannel(channel, n);
      break;
    default:
      ZLOGFAIL(1, EPROTONOSUPPORT, "invalid %s source type %d",
          channel->alias, channel->type);
      break;
  }
}


<|start_filename|>tests/functional/demo/sort/Makefile<|end_filename|>
NAME_1=generator.uint32_t
NAME_2=sort_uint_proper_with_args
NAME_3=tester.uint32_t
CCFLAGS=-n -s -nostartfiles -nostdlib -fno-builtin

all: $(NAME_1).c $(NAME_2).c $(NAME_3).c
	@x86_64-nacl-gcc -o $(NAME_1).nexe $(CCFLAGS) -Wall -msse4.1 \
	-O2 -I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional $(NAME_1).c \
	$(ZEROVM_ROOT)/tests/functional/include/libzvmlib.a
	@x86_64-nacl-gcc -o $(NAME_2).nexe $(CCFLAGS) -Wall -msse4.1 \
	-O3 -I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional $(NAME_2).c \
	$(ZEROVM_ROOT)/tests/functional/include/libzvmlib.a
	@x86_64-nacl-gcc -o $(NAME_3).nexe $(CCFLAGS) -Wall -msse4.1 \
	-O2 -I$(ZEROVM_ROOT) -I$(ZEROVM_ROOT)/tests/functional $(NAME_3).c \
	$(ZEROVM_ROOT)/tests/functional/include/libzvmlib.a
	@sed 's#PWD#$(PWD)#g' $(NAME_1).template > $(NAME_1).manifest
	@sed 's#PWD#$(PWD)#g' $(NAME_2).template > $(NAME_2).manifest
	@sed 's#PWD#$(PWD)#g' $(NAME_3).template > $(NAME_3).manifest
	@echo generator\\n268435456 > nvram_generator
	@echo sort\\n268435456 > nvram_sort
	@echo tester\\n268435456 > nvram_tester
	@printf "GENERATING %053o\n" 0
	@$(ZEROVM_ROOT)/zerovm generator.uint32_t.manifest
	@cat generator.stderr.log
	@printf "SORTING %056o\n" 0
	@$(ZEROVM_ROOT)/zerovm sort_uint_proper_with_args.manifest
	@cat sort.stderr.log
	@printf "TESTING %056o\n" 0
	@$(ZEROVM_ROOT)/zerovm tester.uint32_t.manifest
	@cat tester.stderr.log

clean:
	rm -f $(NAME_1).nexe $(NAME_1).o $(NAME_2).nexe $(NAME_2).o \
	$(NAME_3).nexe $(NAME_3).o *.log *.data *.manifest nvram*


<|start_filename|>tests/functional/demo/malloc/malloc.c<|end_filename|>
/*
 * this sample is a simple demonstration of zerovm.
 * the "hello world" program as usual.
 */
#include "include/zvmlib.h"

#define SIZE 256
#define PATTERN 0xDB

int main(int argc, char **argv)
{
  uint8_t *p = MALLOC(SIZE);
  int i;

  /* heap info */
  PRINTF("heap_ptr = 0x%X, heap_size = %d\n",
      (uintptr_t)MANIFEST->heap_ptr, MANIFEST->heap_size);

  /* memory allocated? */
  if(p == NULL)
  {
    PRINTF("memory allocation error\n");
  }
  else
  {
    PRINTF("memory allocated at 0x%X\n", (uintptr_t)p);
  }

  /* set allocated buffer to pattern */
  MEMSET(p, PATTERN, SIZE);
  PRINTF("memory set to 0x%X pattern\n", PATTERN);

  /* check pattern */
  for(i = 0; i < SIZE; ++i)
  {
    if(p[i] != PATTERN)
      PRINTF("invalid pattern 0x%X at 0x%X\n", p[i], (uintptr_t)p + i);
  }
  PRINTF("pattern tested\n");

  FREE(p);

  return 0;
}


<|start_filename|>src/platform/signal_common.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/platform/signal.h"
#include "src/main/report.h"
#include "src/loader/sel_ldr.h"

#define MAX_HANDLERS 16

struct SignalNode {
  struct SignalNode *next;
  SignalHandler func;
  int id;
};

/*
 * Architecture specific context object.  Register order matches that
 * found in src/src/gdb_rsp/abi.cc, which allows us to use an
 * abi context (GDB ordered context), and a signal context interchangably.
 * In addition, we use common names for the stack and program counter to
 * allow functions which use them to avoid conditional compilation.
 * TODO(d'b): it almost the duplicate of struct ThreadContext. there can be only one.
 */
struct SignalContext {
  uint64_t rax;
  uint64_t rbx;
  uint64_t rcx;
  uint64_t rdx;
  uint64_t rsi;
  uint64_t rdi;
  uint64_t rbp;
  uint64_t stack_ptr;
  uint64_t r8;
  uint64_t r9;
  uint64_t r10;
  uint64_t r11;
  uint64_t r12;
  uint64_t r13;
  uint64_t r14;
  uint64_t r15;
  uint64_t prog_ctr;
  uint32_t flags;
  uint32_t cs;
  uint32_t ss;
  uint32_t ds;
  uint32_t es;
  uint32_t fs;
  uint32_t gs;
};

static struct SignalNode *s_FirstHandler = NULL;
static struct SignalNode *s_FreeList = NULL;
static struct SignalNode s_SignalNodes[MAX_HANDLERS];

/*
 * Return non-zero if the signal context is currently executing in an
 * untrusted environment.
 */
static int SignalContextIsUntrusted(const struct SignalContext *sigCtx)
{
  if(sigCtx->prog_ctr >= START_OF_USER_SPACE
      && sigCtx->prog_ctr < END_OF_USER_SPACE) return 1;
  return 0;
}

/*
 * Fill a signal context structure from the raw platform dependent
 * signal information.
 */
static void SignalContextFromHandler(
    struct SignalContext *sigCtx, const void *rawCtx)
{
  const ucontext_t *uctx = (const ucontext_t *)rawCtx;
  const mcontext_t *mctx = &uctx->uc_mcontext;

#ifdef __USE_GNU
  sigCtx->prog_ctr = mctx->gregs[REG_RIP];
  sigCtx->stack_ptr = mctx->gregs[REG_RSP];

  sigCtx->rax = mctx->gregs[REG_RAX];
  sigCtx->rbx = mctx->gregs[REG_RBX];
  sigCtx->rcx = mctx->gregs[REG_RCX];
  sigCtx->rdx = mctx->gregs[REG_RDX];
  sigCtx->rsi = mctx->gregs[REG_RSI];
  sigCtx->rdi = mctx->gregs[REG_RDI];
  sigCtx->rbp = mctx->gregs[REG_RBP];
  sigCtx->r8 = mctx->gregs[REG_R8];
  sigCtx->r9 = mctx->gregs[REG_R9];
  sigCtx->r10 = mctx->gregs[REG_R10];
  sigCtx->r11 = mctx->gregs[REG_R11];
  sigCtx->r12 = mctx->gregs[REG_R12];
  sigCtx->r13 = mctx->gregs[REG_R13];
  sigCtx->r14 = mctx->gregs[REG_R14];
  sigCtx->r15 = mctx->gregs[REG_R15];
  sigCtx->flags = mctx->gregs[REG_EFL];

  /* Linux stores CS, GS, FS, PAD into one 64b word. */
  sigCtx->cs = (uint32_t)(mctx->gregs[REG_CSGSFS] & 0xFFFF);
  sigCtx->gs = (uint32_t)((mctx->gregs[REG_CSGSFS] >> 16) & 0xFFFF);
  sigCtx->fs = (uint32_t)((mctx->gregs[REG_CSGSFS] >> 32) & 0xFFFF);
#endif

  /* TODO(noelallen) Pull from current context, since they must be the same */
  sigCtx->ds = 0;
  sigCtx->ss = 0;
}

/* exit zerovm with "interrupted syscall" code and the message */
static enum SignalResult SignalHandleAll(int signum, void *ctx)
{
  struct SignalContext sigCtx;
  char msg[SIGNAL_STRLEN];

  /* TODO(d'b): is it a proper solution? */
  static int busy = 0;
  if(busy) return NACL_SIGNAL_RETURN;
  busy = 1;

  /*
   * Return an 8 bit error code which is -signal to
   * simulate normal OS behavior
   */
  SignalContextFromHandler(&sigCtx, ctx);

  /* set zerovm state */
  if(signum == SIGALRM)
    g_snprintf(msg, SIGNAL_STRLEN, "session timeout");
  else if(signum == SIGXFSZ)
    g_snprintf(msg, SIGNAL_STRLEN, "disk quota exceeded");
  else
    g_snprintf(msg, SIGNAL_STRLEN,
        "Signal %d from %strusted code: Halting at 0x%012lX", signum,
        SignalContextIsUntrusted(&sigCtx) ? "un" : "", sigCtx.prog_ctr);

  SetExitState(msg);
  ReportDtor(EINTR);
  return NACL_SIGNAL_RETURN; /* unreachable */
}

/*
 * Add a signal handler to the front of the list.
 * Returns an id for the handler or returns 0 on failure.
 * This function is not thread-safe and should only be
 * called at startup.
 */
static int SignalHandlerAdd(SignalHandler func)
{
  int id = 0;

  ZLOGFAIL(func == NULL, EFAULT, FAILED_MSG);

  /* If we have room... */
  if(s_FreeList)
  {
    /* Update the free list. */
    struct SignalNode *add = s_FreeList;
    s_FreeList = add->next;

    /* Construct the node. */
    add->func = func;
    add->next = s_FirstHandler;

    /* Add node to the head. */
    s_FirstHandler = add;
    id = add->id;
  }

  return id;
}

enum SignalResult SignalHandlerFind(int signal, void *ctx)
{
  enum SignalResult result = NACL_SIGNAL_SEARCH;
  struct SignalNode *pNode;

  /* Iterate through handlers */
  pNode = s_FirstHandler;
  while (pNode) {
    result = pNode->func(signal, ctx);

    /* If we are not asking for the search to continue... */
    if (NACL_SIGNAL_SEARCH != result) break;

    pNode = pNode->next;
  }

  return result;
}

void SignalHandlerInit()
{
  int a;

  /* Build the free list */
  for(a = 0; a < MAX_HANDLERS; a++)
  {
    s_SignalNodes[a].next = s_FreeList;
    s_SignalNodes[a].id = a + 1;
    s_FreeList = &s_SignalNodes[a];
  }

  SignalHandlerInitPlatform();

  /* In stand-alone mode (sel_ldr) we handle all signals. */
  SignalHandlerAdd(SignalHandleAll);
}

/* We try to lock, but since we are shutting down, we ignore failures */
void SignalHandlerFini()
{
  SignalHandlerFiniPlatform();
}


<|start_filename|>tests/functional/demo/dump/dump.c<|end_filename|>
/*
 * dumps whole available memory. from the trampoline start to
 * the stack end. creates the memory map.
 */
#include <limits.h>
#include "include/zvmlib.h"

/* pointer to the array of CHANNELS */
#define CHANNELS ((struct ZVMChannel*)MANIFEST->channels)

/* regions (uintptr_t) */
/* null prot: none */
#define NULL_START 0x0
#define NULL_SIZE PAGESIZE
#define NULL_END (NULL_START + NULL_SIZE)

/* trampoline prot: rx */
#define TRAMPOLINE_START NULL_END
#define TRAMPOLINE_SIZE PAGESIZE
#define TRAMPOLINE_END (TRAMPOLINE_START + TRAMPOLINE_SIZE)

/* data from user module (synthetic size) prot: rx */
#define TEXT_START TRAMPOLINE_END
#define TEXT_SIZE (TEXT_END - TEXT_START)
#define TEXT_END HEAP_START

/* user heap prot: rw */
#define HEAP_START ((uintptr_t)MANIFEST->heap_ptr)
#define HEAP_SIZE ((uintptr_t)MANIFEST->heap_size)
#define HEAP_END (HEAP_START + HEAP_SIZE)

/* unavailable area between heap and manifest (synthetic size) prot: none */
#define HOLE_START HEAP_END
#define HOLE_SIZE (HOLE_END - HOLE_START)
#define HOLE_END MANIFEST_START

/* user maninifest prot: r */
#define MANIFEST_START ((uintptr_t)CHANNELS[MANIFEST->channels_count - 1].name)
#define MANIFEST_SIZE (STACK_END - MANIFEST_START)
#define MANIFEST_END STACK_END

/* user stack prot: rw */
#define STACK_END ((uintptr_t)(-MANIFEST->stack_size))
#define STACK_SIZE ((uintptr_t)MANIFEST->stack_size)
#define STACK_START (STACK_END + STACK_SIZE)

/* units */
#define CHUNK_SIZE (0x100000 /*1mb*/)
#define FOURGIG (0x100000000UL)
#define PAGESIZE ((uintptr_t)0x10000)
#define PAINT 0xff

/* utils */
#define ROUNDDOWN_64K(a) ((a) & ~(PAGESIZE - 1))
#define ROUNDUP_64K(a) ROUNDDOWN_64K((a) + PAGESIZE - 1)
#define DUMP(m) do { FPRINTF(STDERR, "%24s = 0x%08X\n", #m, m); } while (0)

/*
 * write buffer to given "file" channel
 * if "buf" == NULL just output "size" of "PAINT" to the "file"
 */
int64_t zwrite_all(char *file, uintptr_t buf, int64_t size, int prot)
{
  /* check arguments */
  if(size < 1) return size;
  if(file == NULL) return -1;

#define OUT_LOOP(buffer) \
  do {\
    int64_t pos;\
    int64_t rest;\
    int64_t code;\
    for(pos = 0; pos < size; pos += rest)\
    {\
      rest = MIN(CHUNK_SIZE, size - pos);\
      if((code = WRITE(file, buffer, rest)) != rest)\
        return code;\
    }\
    return pos; /* return amount of written bytes */ \
  } while(0)

  /* output painting */
  if(prot == 0)
  {
    char dummy[CHUNK_SIZE];
    memset(dummy, PAINT, CHUNK_SIZE);
    OUT_LOOP(dummy);
  }
  /* output real data */
  else
    OUT_LOOP(buf + pos);
}

/* prints the user memory map (all regions) */
/* todo: print it to the string */
#define FULLDUMP(a) DUMP(a ## _START); DUMP(a ## _SIZE); DUMP(a ## _END)
static void printf_map()
{
  DUMP(MANIFEST);
  DUMP(MANIFEST->channels_count);

  FULLDUMP(NULL);
  FULLDUMP(TRAMPOLINE);
  FULLDUMP(TEXT);
  FULLDUMP(HEAP);
  FULLDUMP(HOLE);
  FULLDUMP(MANIFEST);

  /* stack have back orientation */
  DUMP(STACK_END);
  DUMP(STACK_SIZE);
  DUMP(STACK_START);
}
#undef FULLDUMP

/* todo: print it to the string */
static void print_channels()
{
  int64_t i;

  FPRINTF(STDERR, "\n");
  for(i = 0; i < MANIFEST->channels_count; ++i)
    FPRINTF(STDERR, "%02d: %12s type = %d, size = %u, %u:%u:%u:%u\n",
        i, CHANNELS[i].name, CHANNELS[i].type, CHANNELS[i].size,
        CHANNELS[i].limits[0], CHANNELS[i].limits[1],
        CHANNELS[i].limits[2], CHANNELS[i].limits[3]);
}

int main(int argc, char **argv)
{
  uint32_t code;

  /* print memory map */
  printf_map();

  /* print channels records */
  print_channels();

  FPRINTF(STDERR, "\ndump log:\n");

  /* paint NULL */
  code = zwrite_all(STDOUT, NULL_START, NULL_SIZE, 0);
  FPRINTF(STDERR, "%s written  %u bytes\n", "NULL", code);

  /* dump TRAMPOLINE */
  code = zwrite_all(STDOUT, TRAMPOLINE_START, TRAMPOLINE_SIZE, 1);
  FPRINTF(STDERR, "%s written  %u bytes\n", "TRAMPOLINE", code);

  /* dump TEXT */
  code = zwrite_all(STDOUT, TEXT_START, TEXT_SIZE, 1);
  FPRINTF(STDERR, "%s written  %u bytes\n", "TEXT", code);

  /* dump HEAP */
  code = zwrite_all(STDOUT, HEAP_START, HEAP_SIZE, 1);
  FPRINTF(STDERR, "%s written  %u bytes\n", "HEAP", code);

  /* paint HOLE */
  code = zwrite_all(STDOUT, HOLE_START, HOLE_SIZE, 0);
  FPRINTF(STDERR, "%s written  %u bytes\n", "HOLE", code);

  /* dump MANIFEST */
  code = zwrite_all(STDOUT, MANIFEST_START, MANIFEST_SIZE, 1);
  FPRINTF(STDERR, "%s written  %u bytes\n", "MANIFEST", code);

  /* dump STACK */
  code = zwrite_all(STDOUT, STACK_END, STACK_SIZE, 1);
  FPRINTF(STDERR, "%s written  %u bytes\n", "STACK", code);

  return 0;
}


<|start_filename|>src/main/accounting.h<|end_filename|>
/*
 * accounting of the user resources: local i/o, network i/o and cpu
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ACCOUNTING_H_
#define ACCOUNTING_H_

#include "src/channels/channel.h"

/* update get statistics */
void CountGet(struct Connection *c, int size);

/* update put statistics */
void CountPut(struct Connection *c, int size);

/*
 * returns string with intermediate time and i/o statistics
 * WARNING: returned string should be deallocated with g_free
 */
char *FastAccounting();

/*
 * returns string with final time and i/o statistics
 * WARNING: returned string should be deallocated with g_free
 * and the function should be called only once
 */
char *FinalAccounting();

/* reset accounting internals */
void ResetAccounting();

#endif /* ACCOUNTING_H_ */


<|start_filename|>src/channels/nservice.h<|end_filename|>
/*
 * name service for network channels
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef NSERVICE_H_
#define NSERVICE_H_

/*
 * TODO(d'b): find the neat solution to calculate (10915)
 * ((PARCEL_SIZE - sizeof(struct NSParcel)) / sizeof(struct NSRecord) + 1)
 */
#define MAX_CHANNELS_NUMBER 10915
#define MIN_CHANNELS_NUMBER 3

/* initialize name service and update channels information */
void NameServiceCtor(struct Manifest *manifest, uint32_t b, uint32_t c);

/* close name service */
void NameServiceDtor();

#endif


<|start_filename|>src/main/manifest.h<|end_filename|>
/*
 * zerovm manifest (de)serializer
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MANIFEST_H__
#define MANIFEST_H__ 1

#include "api/zvm.h"
#include "src/loader/sel_ldr.h"
#include "src/main/tools.h"

EXTERN_C_BEGIN

/* x-macro helpers */
#define XTYPE(a) enum ENUM_##a
#define XSIZE(a) ARRAY_SIZE(ARRAY_##a)
#define XSTR(a, c) ARRAY_##a[c]

/* (x-macro): channels protocols */
#define PROTOCOLS \
    X(TCP) \
    X(UDP) \
    X(IPC) \
    X(INPROC) \
    X(PGM) \
    X(EPGM) \
    X(Regular) \
    X(Directory) \
    X(Character) \
    X(Block) \
    X(FIFO) \
    X(Link) \
    X(Socket)

/* (x-macro): manifest enumeration and array */
#define XENUM(a) enum ENUM_##a {a};
#define X(a) Proto ## a,
  XENUM(PROTOCOLS)
#undef X

/*
 * short "flags" description:
 * 0:    id/ip. 0 means id specified by "Channel" field, 1 - ip4
 * 1..2: r/w source type: 0 - inaccessible, 1 - RO, 2 - WO, 3 - RW
 * 3:    0 means channel is valid, 1 - invalid
 */
/* network channel description */
struct Connection {
  uint8_t protocol; /* XTYPE(PROTOCOLS) */
  void *handle; /* pointer to (0mq) socket */
  int64_t pos; /* position */
  uint8_t flags;
  uint16_t port;
  uint32_t host;
  void *backup; /* for udt it is stored original handle */
};

/* local channel description */
struct File {
  uint8_t protocol; /* XTYPE(PROTOCOLS) */
  void *handle; /* (int*) or (FILE*) */
  int64_t pos; /* position */
  uint8_t flags;
  char *name;
};

/* channel structure */
struct ChannelDesc {
  /* manifest parser initialize it (partially) */
  GPtrArray *source; /* (Connection*) or (File*) */
  char *alias; /* name for untrusted */
  enum ChannelType type; /* type of access sequential/random */
  void *tag; /* tag context */
  int64_t limits[LimitsNumber];
  int8_t eof;

  /* constructor initialize it */
  void *msg; /* network message container */
  int64_t size; /* file size (or 0) */
  int64_t getpos; /* channel read position */
  int64_t putpos; /* channel write position */
  int32_t bufpos; /* index of the 1st available byte in the buffer */
  int32_t bufend; /* index of the 1st unavailable byte in the buffer */
  int64_t counters[LimitsNumber];
};

/* zerovm manifest structure */
struct Manifest {
  int node; /* own node id from manifest */
  char *program; /* program file name */
  char *etag; /* signature. reserved for a future */
  char *job; /* daemon: job file name. child: manifest file name */
  int32_t timeout; /* time user module allowed to run */
  int64_t mem_size; /* user specified memory */
  void *mem_tag; /* tag context */
  struct Connection *name_server;
  GPtrArray *channels; /* all elements are (ChannelDesc*) */
};

/* de-serialize manifest from the given file */
struct Manifest *ManifestCtor(const char *name);

/* de-serialize manifest from the given text */
struct Manifest *ManifestTextCtor(char *text);

/*
 * release manifest resources. all elements initialized by another classes
 * must be deallocated by those classes
 */
void ManifestDtor(struct Manifest *manifest);

/* convert string to integer, fail if string is invalid */
int64_t ToInt(char *a);

EXTERN_C_END

#endif


<|start_filename|>src/loader/sel_ldr.c<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <sys/mman.h>
#include <assert.h>
#include "src/loader/sel_ldr.h"
#include "src/loader/sel_addrspace.h"
#include "src/platform/sel_memory.h"
#include "src/loader/tramp.h"

#define THUNK_ADDR ((void*)0x5AFECA110000)

/*
 * target is an absolute address in the source region.  the patch code
 * will figure out the corresponding address in the destination region
 * and modify as appropriate.  this makes it easier to specify, since
 * the target is typically the address of some symbol from the source
 * template.
 */
struct Patch {
  uintptr_t    target;
  uint64_t     value;
};

struct PatchInfo {
  uintptr_t    dst;
  uintptr_t    src;
  size_t       nbytes;

  struct Patch *abs16;
  size_t       num_abs16;

  struct Patch *abs32;
  size_t       num_abs32;

  struct Patch *abs64;
  size_t       num_abs64;
};

extern int SyscallSeg(); /* d'b: defined in to_trap.S */
static uintptr_t dispatch_thunk = 0;

static struct PatchInfo *PatchInfoCtor(struct PatchInfo *self)
{
  if(NULL != self)
  {
    memset(self, 0, sizeof *self);
  }
  return self;
}

/* unaligned little-endian store */
static void StoreMem(uintptr_t addr, size_t nbytes, uint64_t value)
{
  size_t i;

  ZLOGFAIL(nbytes > 8, EFAULT, FAILED_MSG);

  for(i = 0; i < nbytes; ++i)
  {
    ((uint8_t *)addr)[i] = (uint8_t)value;
    value = value >> 8;
  }
}

#define GENERIC_STORE(bits) \
  static void Store ## bits(uintptr_t addr, uint ## bits ## _t v) { \
    StoreMem(addr, sizeof(uint ## bits ## _t), v); \
  }

GENERIC_STORE(16)
GENERIC_STORE(32)
GENERIC_STORE(64)

#undef GENERIC_STORE

/*
 * This function is called by NaClLoadTrampoline and NaClLoadSpringboard to
 * patch a single memory location specified in NaClPatchInfo structure.
 */
static void ApplyPatchToMemory(struct PatchInfo *patch)
{
  size_t i;
  size_t offset;
  uintptr_t target_addr;

  memcpy((void *) patch->dst, (void *) patch->src, patch->nbytes);

  for(i = 0; i < patch->num_abs64; ++i)
  {
    offset = patch->abs64[i].target - patch->src;
    target_addr = patch->dst + offset;
    Store64(target_addr, patch->abs64[i].value);
  }

  for(i = 0; i < patch->num_abs32; ++i)
  {
    offset = patch->abs32[i].target - patch->src;
    target_addr = patch->dst + offset;
    Store32(target_addr, (uint32_t) patch->abs32[i].value);
  }

  for(i = 0; i < patch->num_abs16; ++i)
  {
    offset = patch->abs16[i].target - patch->src;
    target_addr = patch->dst + offset;
    Store16(target_addr, (uint16_t) patch->abs16[i].value);
  }
}

static void MakeDispatchThunk()
{
  int                   error;
  void                  *thunk_addr = THUNK_ADDR;
  struct PatchInfo  patch_info;
  struct Patch      jmp_target;

  assert(dispatch_thunk == 0);

  /* d'b: replaced with not randomized version */
  error = NaCl_page_alloc_intern_flags(&thunk_addr, NACL_MAP_PAGESIZE, 0);
  ZLOGFAIL(error < 0, errno, "thunk allocation failed");

  error = NaCl_mprotect(thunk_addr, NACL_MAP_PAGESIZE, PROT_READ | PROT_WRITE);
  ZLOGFAIL(error != 0, errno, "thunk r/w protection failed");

  FillMemoryRegionWithHalt(thunk_addr, NACL_MAP_PAGESIZE);

  jmp_target.target = ((uintptr_t)&NaClDispatchThunk_jmp_target) - sizeof(uintptr_t);
  jmp_target.value = (uintptr_t) SyscallSeg;

  PatchInfoCtor(&patch_info);
  patch_info.abs64 = &jmp_target;
  patch_info.num_abs64 = 1;

  patch_info.dst = (uintptr_t) thunk_addr;
  patch_info.src = (uintptr_t) &NaClDispatchThunk;
  patch_info.nbytes = (uintptr_t)&NaClDispatchThunkEnd - (uintptr_t)&NaClDispatchThunk;
  ApplyPatchToMemory(&patch_info);

  error = NaCl_mprotect(thunk_addr, NACL_MAP_PAGESIZE, PROT_EXEC | PROT_READ);
  ZLOGFAIL(error != 0, errno, "thunk r/x protection failed");

  dispatch_thunk = (uintptr_t)thunk_addr;
}

/* Install a syscall trampoline at target_addr. NB: Thread-safe. */
static void PatchOneTrampoline(uintptr_t target_addr)
{
  struct PatchInfo patch_info;
  struct Patch call_target;
  uintptr_t call_target_addr;

  call_target_addr = dispatch_thunk;

  ZLOGS(LOG_INSANE, "call_target_addr = 0x%lx", call_target_addr);
  ZLOGFAIL(0 == call_target_addr, EFAULT, FAILED_MSG);

  call_target.target = ((uintptr_t)&NaCl_trampoline_call_target) - sizeof(uintptr_t);
  call_target.value = call_target_addr;

  PatchInfoCtor(&patch_info);

  patch_info.abs64 = &call_target;
  patch_info.num_abs64 = 1;

  patch_info.dst = target_addr;
  patch_info.src = (uintptr_t)&NaCl_trampoline_code;
  patch_info.nbytes = (uintptr_t)&NaCl_trampoline_code_end - (uintptr_t)&NaCl_trampoline_code;

  ApplyPatchToMemory(&patch_info);
}

void FreeDispatchThunk()
{
  if((void*)dispatch_thunk == NULL) return;
  NaCl_page_free((void*)dispatch_thunk, NACL_MAP_PAGESIZE);
  dispatch_thunk = (uintptr_t)NULL;
}

void FillMemoryRegionWithHalt(void *start, size_t size)
{
  ZLOGFAIL(size % NACL_HALT_LEN, EFAULT, FAILED_MSG);
  memset(start, NACL_HALT_OPCODE, size);
}

static void FillTrampolineRegion(struct NaClApp *nap)
{
  FillMemoryRegionWithHalt
    ((void *)(nap->mem_start + NACL_TRAMPOLINE_START), NACL_TRAMPOLINE_SIZE);
}

void NaClAppCtor(struct NaClApp *nap)
{
  nap->addr_bits = NACL_MAX_ADDR_BITS;
  nap->stack_size = NACL_DEFAULT_STACK_MAX;

  gnap = nap;
  nacl_user = g_malloc(sizeof *nacl_user);
  nacl_sys = g_malloc(sizeof *nacl_sys);
}

void NaClAppDtor(struct NaClApp *nap)
{
  FreeAddrSpace(nap);
  g_free(nacl_sys);
  g_free(nacl_user);
  nacl_sys = NULL;
  nacl_user = NULL;
}

void LoadTrampoline(struct NaClApp *nap)
{
  int         num_syscalls;
  int         i;
  uintptr_t   addr;

  MakeDispatchThunk();
  FillTrampolineRegion(nap);

  /*
   * Do not bother to fill in the contents of page 0, since we make it
   * inaccessible later (see sel_addrspace.c, NaClMemoryProtection)
   * anyway to help detect NULL pointer errors, and we might as well
   * not dirty the page.
   *
   * The last syscall entry point is reserved (nacl springboard code)
   */
  num_syscalls = ((NACL_TRAMPOLINE_END - NACL_SYSCALL_START_ADDR) / NACL_SYSCALL_BLOCK_SIZE) - 1;
  ZLOGS(LOG_INSANE, "num_syscalls = %d (0x%x)", num_syscalls, num_syscalls);

  addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
  for (i = 0; i < num_syscalls; ++i)
  {
    PatchOneTrampoline(addr);
    addr += NACL_SYSCALL_BLOCK_SIZE;
  }
}

void PrintAppDetails(struct NaClApp *nap, int verbosity)
{
  ZLOGS(verbosity, "NaClAppPrintDetails((struct NaClApp*) 0x%08lx,", (uintptr_t)nap);
  ZLOGS(verbosity, "addr space size:         2**%d", nap->addr_bits);
  ZLOGS(verbosity, "stack size:              0x%08d", nap->stack_size);
  ZLOGS(verbosity, "mem start addr:          0x%08lx", nap->mem_start);
  ZLOGS(verbosity, "static_text_end:         0x%08lx", nap->static_text_end);
  ZLOGS(verbosity, "end-of-text:             0x%08lx", NaClEndOfStaticText(nap));
  ZLOGS(verbosity, "rodata:                  0x%08lx", nap->rodata_start);
  ZLOGS(verbosity, "data:                    0x%08lx", nap->data_start);
  ZLOGS(verbosity, "data_end:                0x%08lx", nap->data_end);
  ZLOGS(verbosity, "break_addr:              0x%08lx", nap->break_addr);
  ZLOGS(verbosity, "ELF initial entry point: 0x%08x", nap->initial_entry_pt);
  ZLOGS(verbosity, "ELF user entry point:    0x%08x", nap->user_entry_pt);
}


<|start_filename|>tests/functional/channels/ranrw/ranrw.c<|end_filename|>
/*
 * read/write (full access) channel test. tests statistics goes to stdout channel
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define STDRW_EMPTY "/dev/empty"
#define STDRW_STUBBED "/dev/stubbed"
#define STDRW_GOAT "/dev/scapegoat"

static char data_start = 0;

int main(int argc, char **argv)
{
  int overall_errors = 0;
  char buf[BIG_ENOUGH];

  /*
   * todo: add more cases for
   * (un)successfull writes to not empty channel
   * (un)successfull reads from not empty channel
   */

  /* test (in)valid write cases */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST (IN)VALID CDR WRITE CASES\n");
  ZTEST(PWRITE(STDRW_GOAT, buf, 0, 0) == 0); /* accessing 0 bytes is always ok */
  ZTEST(PWRITE(STDRW_GOAT, buf, -1, -1) < 0); /* invalid size, offset ignored = fail */
  ZTEST(PWRITE(STDRW_GOAT, buf, -1, 0) < 0); /* invalid size, offset ignored = fail */
  ZTEST(PWRITE(STDRW_GOAT, buf, -1, 1) < 0); /* invalid size, offset ignored = fail */
  ZTEST(PWRITE(STDRW_GOAT, buf, 0, -1) == 0); /* accessing of 0 bytes is always ok */
  ZTEST(PWRITE(STDRW_GOAT, buf, 1, -1) < 0); /* size = 1, offset invalid */
  ZTEST(PWRITE(STDRW_GOAT, buf, 0, MANIFEST->channels[OPEN(STDRW_GOAT)].limits[PutSizeLimit] + 1) == 0);
  ZTEST(PWRITE(STDRW_GOAT, buf, 1, MANIFEST->channels[OPEN(STDRW_GOAT)].limits[PutSizeLimit] + 1) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test (in)valid reead cases */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST (IN)VALID CDR READ CASES\n");
  ZTEST(PREAD(STDRW_GOAT, buf, 0, 0) == 0); /* accessing 0 bytes is always ok */
  ZTEST(PREAD(STDRW_GOAT, buf, -1, -1) < 0); /* invalid size, invalid offset = fail */
  ZTEST(PREAD(STDRW_GOAT, buf, -1, 0) < 0); /* invalid size, invalid offset = fail */
  ZTEST(PREAD(STDRW_GOAT, buf, -1, 1) < 0); /* invalid size, invalid offset = fail */
  ZTEST(PREAD(STDRW_GOAT, buf, 0, -1) == 0); /* accessing 0 bytes is always ok */
  ZTEST(PREAD(STDRW_GOAT, buf, 1, -1) < 0); /* valid size, invalid offset = fail */
  ZTEST(PREAD(STDRW_GOAT, buf, 0, MANIFEST->channels[OPEN(STDRW_GOAT)].limits[PutSizeLimit] + 1) < 0);
  ZTEST(PREAD(STDRW_GOAT, buf, 1, MANIFEST->channels[OPEN(STDRW_GOAT)].limits[PutSizeLimit] + 1) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test NULL buffer cases */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST NULL BUFFER CASES\n");
  ZTEST(PWRITE(STDRW_GOAT, NULL, 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, NULL, 0, 0) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other invalid buffer address/size cases for pwrite */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER INVALID BUFFER/SIZE CASES FOR PWRITE\n");
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x1, 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0xffff, 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x10000, -1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, MANIFEST->heap_ptr, MANIFEST->heap_size + 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size, 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x100000000LL - 0x1000001 - 0x10000, 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x100000000LL, 1, 0) < 0);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x100000000LL - 0x1000000, 0x1000001, 0) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other valid buffer address/size cases for pwrite */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER VALID BUFFER/SIZE CASES FOR PWRITE\n");
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x10000, 1, 0) == 1);
  ZTEST(PWRITE(STDRW_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size - 1, 1, 0) == 1);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x100000000LL - 0x1000000, 1, 0) == 1);
  ZTEST(PWRITE(STDRW_GOAT, (void*)0x100000000LL - 0x1, 1, 0) == 1);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other invalid buffer address/size cases for pread */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER INVALID BUFFER/SIZE CASES FOR PREAD\n");
  ZTEST(PREAD(STDRW_GOAT, (char*)main, 1, 0) < 0);
  ZTEST(PREAD(STDRW_GOAT, MANIFEST->heap_ptr, MANIFEST->heap_size + 1, 0) < 0);
  ZTEST(PREAD(STDRW_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size, 1, 0) < 0);
  ZTEST(PREAD(STDRW_GOAT, (void*)0x100000000LL - 0x1000001, 1, 0) < 0);
  ZTEST(PREAD(STDRW_GOAT, (void*)0x100000000LL, 1, 0) < 0);
  ZTEST(PREAD(STDRW_GOAT, (void*)0x100000000LL - 0x1000000, 0x1000001, 0) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other valid buffer address/size cases for pread */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER VALID BUFFER/SIZE CASES FOR PREAD\n");
  ZTEST(PREAD(STDRW_GOAT, &data_start, 1, 0) == 1);
  ZTEST(PREAD(STDRW_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size - 1, 1, 0) == 1);
  ZTEST(PREAD(STDRW_GOAT, (void*)0x100000000LL - 0x1000000, 1, 0) == 1);
  ZTEST(PREAD(STDRW_GOAT, (void*)0x100000000LL - 0x1, 1, 0) == 1);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* exit with code */
  if(overall_errors > 0)
    FPRINTF(STDERR, "OVERALL TEST FAILED with %d errors\n", overall_errors);
  else
    FPRINTF(STDERR, "OVERALL TEST SUCCEED\n\n");

  return overall_errors;
}


<|start_filename|>src/channels/preload.h<|end_filename|>
/*
 * preload given file to channel
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PRELOAD_H_
#define PRELOAD_H_

#include "api/zvm.h"
#include "src/channels/channel.h"

/* disable space preallocation */
void PreloadAllocationDisable();

/*
 * preload given file to channel.
 * return 0 if success, otherwise negative errcode
 */
void PreloadChannelCtor(struct ChannelDesc* channel, int n);

/* (adjust and) close file associated with the channel */
int PreloadChannelDtor(struct ChannelDesc* channel, int n);

#endif


<|start_filename|>tests/functional/channels/netcopy/netcopy.c<|end_filename|>
/*
 * this sample demonstrates working with the network channels
 * via file abstraction. specifically this sample copies data
 * from one channel (stdin) to another (stdout). returns 0 if
 * there were no errors.
 *
 * note: to simulate the "real" channel work the program reads
 * "random" amount of bytes
 *
 * update: to test 0mq put/get the program tries to slow down
 * twice each next node
 */
#include "include/zvmlib.h"

#define CHUNK_SIZE 0x100000
#define BREAKIF(cond, ...) if(cond) {FPRINTF(STDERR, __VA_ARGS__); break;}

/* zerovm platform does not have a real sleep */
#define LOOP_SIZE 0x20000LLU
static void busy_loop(int factor)
{
  static uint64_t dummy = 0;
  uint64_t loop = LOOP_SIZE * factor + 1;
  while(--loop)
    dummy *= loop;
}

int main(int argc, char **argv)
{
  int rsize = 0;
  int wsize = 0;
  int factor = atoi(argv[0] + 6);

  SRAND(factor);
  FPRINTF(STDERR, "seeded with %d\n", factor);

  /* copy all data from STDIN to STDOUT */
  for(;;)
  {
    char buffer[CHUNK_SIZE];
//    int plan = RAND() % sizeof buffer + 1;
    int plan = (rand() * rand()) % sizeof buffer + 1;

    /* read */
    int count = READ(STDIN, buffer, plan);
    BREAKIF(count < 0, "read error %d\n", count);
    busy_loop(factor);

    /* eof */
    if(count == 0) break;

    /* the read log */
    rsize += count;
    FPRINTF(STDERR, "%5d(of %5d) read, ", count, plan);

    /* write */
    count = WRITE(STDOUT, buffer, count);
    BREAKIF(count < 0, "write error %d\n", count);

    /* the write log */
    FPRINTF(STDERR, "%5d written\n", count);
    wsize += count;
  }

  /* report results */
  FPRINTF(STDERR, "\n%d bytes has been read\n", rsize);
  FPRINTF(STDERR, "%d bytes has been written\n", wsize);

  return rsize == wsize ? 0 : 1;
}


<|start_filename|>tests/functional/demo/romb/romb.c<|end_filename|>
#include "api/zvm.h"
#define SIZE 13

/* repeat given symbol n times */
static inline void repeat(int n, char a)
{
  while(n-- > 0)
    zvm_pwrite(1, &a, 1, 0);
}

/* draw full line of the figure */
static void draw_line(int n, int size)
{
  char endl = '\n';
  repeat(size - n, ' ');
  repeat(2 * n - 1, 'X');
  zvm_pwrite(1, &endl, 1, 0);
}

void _start()
{
  int i;

  /* top + middle */
  for(i = 1; i <= SIZE; ++i)
    draw_line(i, SIZE);

  /* bottom */
  for(i = SIZE - 1; i >= 0; --i)
    draw_line(i, SIZE);

  zvm_exit(0);
}


<|start_filename|>src/main/report.c<|end_filename|>
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <sys/time.h>
#include <sys/mman.h>
#include "src/main/report.h"
#include "src/platform/signal.h"
#include "src/main/accounting.h"
#include "src/main/setup.h"
#include "src/channels/channel.h"

#define QUANT MICRO_PER_SEC

#ifdef DEBUG
#define REPORT_VALIDATOR "validator state = "
#define REPORT_DAEMON "daemon = "
#define REPORT_RETCODE "user return code = "
#define REPORT_ETAG "etag(s) = "
#define REPORT_ACCOUNTING "accounting = "
#define REPORT_STATE "exit state = "
#define REPORT_CMD cmd->str
#define EOL "\r"
#else
#define REPORT_VALIDATOR ""
#define REPORT_DAEMON ""
#define REPORT_RETCODE ""
#define REPORT_ETAG ""
#define REPORT_ACCOUNTING ""
#define REPORT_STATE ""
#define REPORT_CMD ""
#define EOL "\n"
#endif

/*
 * 0: to /dev/stdout, 1: to syslog, 2: (0) + fast reports, 3: to socket
 * TODO(d'b): fast reports should be cut from report output
 * TODO(d'b): report outputs should be enumerated (magic numbers to remove)
 */
static int report_mode = 0;
static int zvm_code = 0;
static int user_code = 0;
static int validation_state = 2;
static int daemon_state = 0;
static char *zvm_state = NULL;
static GString *digests = NULL; /* cumulative etags */
static GString *cmd = NULL;
static int report_handle = STDOUT_FILENO;

void SetReportHandle(int handle)
{
  report_handle = handle;
}

void ReportMode(int mode)
{
  report_mode = mode;
}

void SetExitState(const char *state)
{
  g_free(zvm_state);
  zvm_state = g_strdup(state);
}

void SetExitCode(int code)
{
  /* only the 1st error matters */
  if(zvm_code == 0) zvm_code = code;
}

int GetExitCode()
{
  return zvm_code;
}

void SetUserCode(int code)
{
  user_code = code;
}

void SetValidationState(int state)
{
  validation_state = state;
}

void SetDaemonState(int state)
{
  daemon_state = state;
}

void SetCmdString(GString *s)
{
  cmd = s;
}

/* log user memory map */
static void LogMemMap(struct NaClApp *nap, int verbosity)
{
  int i;

  ZLOGS(verbosity, "user memory map (in pages):");

  for(i = 0; i < MemMapSize; ++i)
    ZLOGS(verbosity, "%s: address = 0x%08x, size = 0x%08x, protection = x",
        nap->mem_map[i].name, (uint32_t) nap->mem_map[i].start,
        (uint32_t) nap->mem_map[i].size, nap->mem_map[i].prot);
}

static void FinalDump(struct NaClApp *nap)
{
  ZLOGS(LOG_INSANE, "exiting -- printing NaClApp details");
  PrintAppDetails(nap, LOG_INSANE);
  LogMemMap(nap, LOG_INSANE);

  SignalHandlerFini();
}

void ReportTag(char *name, void *tag)
{
  char digest[TAG_DIGEST_SIZE + 1];

  assert(name != NULL);
  if(tag == NULL) return;

  TagDigest(tag, digest);
  g_string_append_printf(digests, "%s %s ", name, digest);
}

/* calculate user memory tag, and return pointer to it */
static void *GetMemoryDigest(struct NaClApp *nap)
{
  int i;

  assert(nap != NULL);

  /* calculate overall memory tag */
  for(i = 0; i < MemMapSize; ++i)
  {
    uintptr_t addr = nap->mem_map[i].start;
    int64_t size = nap->mem_map[i].size;

    /* update user_etag skipping inaccessible pages */
    if(nap->mem_map[i].prot & PROT_READ)
      TagUpdate(nap->manifest->mem_tag, (const char*)addr, size);
  }

  return nap->manifest->mem_tag;
}

void ReportCtor()
{
  digests = g_string_sized_new(BIG_ENOUGH_STRING);
}

/* output report */
/* TODO(d'b): rework "-t" and update the function */
static void OutputReport(char *r)
{
  char *p = NULL;
  int size = strlen(r);

#define REPORT(p) ZLOGIF(write(report_handle, p, size) != size, \
  "report write error %d: %s", errno, strerror(errno))

  switch(report_mode)
  {
    case 3: /* unix socket */
      p = g_strdup_printf("0x%06x%s", size, r);
      size = strlen(p);
      REPORT(p);
      g_free(p);
      break;
    case 0: /* stdout */
      REPORT(r);
      break;
    case 1: /* syslog */
      ZLOGS(LOG_ERROR, "%s", r);
      break;
    default:
      ZLOG(LOG_ERROR, "invalid report mode %d", report_mode);
      break;
  }
#undef REPORT
}

void FastReport()
{
  char *eol = report_mode == 1 ? "; " : EOL;
  static int64_t start = 0;
  int64_t now = 0;
  struct timeval t;
  char *acc = NULL;
  char *r = NULL;

  /* skip fast report if specified */
  if(report_mode != 2) return;

  /* check if it is time to report */
  gettimeofday(&t, NULL);
  now = MICRO_PER_SEC * t.tv_sec + t.tv_usec;
  if(now - start < QUANT) return;
  start += start == 0 ? now : QUANT;

  /* create and output report */
  acc = FastAccounting();
  r = g_strdup_printf("%s%s%s", REPORT_ACCOUNTING, acc, eol);
  OutputReport(r);

  g_free(acc);
  g_free(r);
}

/* part of report class dtor */
#define REPORT g_string_append_printf
void Report(struct NaClApp *nap)
{
  GString *r = g_string_sized_new(BIG_ENOUGH_STRING);
  char *eol = report_mode == 1 ? "; " : "\n";
  char *acc = FinalAccounting();

  /* report validator state and user return code */
  REPORT(r, "%s%d%s", REPORT_VALIDATOR, validation_state, eol);
  REPORT(r, "%s%d%s", REPORT_DAEMON, daemon_state, eol);
  REPORT(r, "%s%d%s", REPORT_RETCODE, user_code, eol);

  /* add memory digest to cumulative digests if asked */
  if(nap != NULL && nap->manifest != NULL)
    if(nap->manifest->mem_tag != NULL)
      ReportTag(STDRAM, GetMemoryDigest(nap));

  /* report tags digests and remove ending " " if exist */
  REPORT(r, "%s", REPORT_ETAG);
  REPORT(r, "%s", digests->len == 0
      ? TAG_ENGINE_DISABLED : digests->str);
  g_string_truncate(r, r->len - 1);

  /* report accounting and session message */
  if(zvm_state == NULL) zvm_state = UNKNOWN_STATE;
  REPORT(r, "%s%s%s%s", eol, REPORT_ACCOUNTING, acc, eol);
  REPORT(r, "%s%s%s", REPORT_STATE,
      zvm_state == NULL ? UNKNOWN_STATE : zvm_state, eol);
  REPORT(r, "%s%s", REPORT_CMD, eol);
  OutputReport(r->str);

  g_string_free(r, TRUE);
  g_free(acc);
}

void ReportDtor(int zvm_ret)
{
  SetExitCode(zvm_ret);

  /* broken session */
  if(zvm_code != 0)
  {
    ZLOGS(LOG_ERROR, "SESSION %d FAILED WITH ERROR %d: %s",
        gnap->manifest == NULL ? 0 : gnap->manifest->node,
        zvm_code, strerror(zvm_code));
    FinalDump(gnap);
    ZTrace("[final dump]");
  }

  ChannelsDtor(gnap->manifest);
  ZTrace("[channels destruction]");
  Report(gnap);
  ZTrace("[report]");
  NaClAppDtor(gnap); /* free user space and globals */
  ZTrace("[untrusted context closing]");
  ManifestDtor(gnap->manifest); /* dispose manifest and channels */
  ZTrace("[manifest deallocating]");
  FreeDispatchThunk();
  ZTrace("[thunk deallocating]");
  ZLogDtor();
  ZTrace("[zlog deallocating]");

  /* free local resources and exit */
  g_string_free(digests, TRUE);
  g_string_free(cmd, TRUE);
  g_free(zvm_state);

  ZTrace("[exit]");
  ZTraceDtor(1);
  ZTraceNameDtor();
  _exit(zvm_code);
}


<|start_filename|>src/platform/gio_snapshot.c<|end_filename|>
/*
 * Copyright 2008 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * NaCl Generic I/O interface implementation: in-memory snapshot of a file.
 */

#include "src/platform/gio.h"

struct GioVtbl const  kGioMemoryFileSnapshotVtbl = {
  GioMemoryFileRead,
  GioMemoryFileWrite,
  GioMemoryFileSeek,
  GioMemoryFileFlush,
  GioMemoryFileClose,
  GioMemoryFileSnapshotDtor,
};

int64_t GetFileSize(const char *name)
{
  struct stat fs;
  int handle = open(name, O_RDONLY);
  return fstat(handle, &fs), close(handle) ? -1 : fs.st_size;
}

int GioMemoryFileSnapshotCtor(struct GioMemoryFileSnapshot *self, char *fn)
{
  FILE *iop;
  char *buffer;
  size_t size = GetFileSize(fn);

  ((struct Gio *) self)->vtbl = NULL;
  if(size == (size_t)-1) return 0;
  iop = fopen(fn, "rb");
  buffer = g_malloc(size);

  if(fread(buffer, 1, size, iop) != size)
  {
    g_free(buffer);
    fclose(iop);
    return 0;
  }

  fclose(iop);
  GioMemoryFileCtor(&self->base, buffer, size);
  ((struct Gio *) self)->vtbl = &kGioMemoryFileSnapshotVtbl;
  return 1;
}

void GioMemoryFileSnapshotDtor(struct Gio *vself)
{
  struct GioMemoryFileSnapshot *self = (struct GioMemoryFileSnapshot *) vself;
  g_free(self->base.buffer);
  GioMemoryFileDtor(vself);
}


<|start_filename|>tests/functional/demo/sort/generator.uint32_t.c<|end_filename|>
/*
 * generate 32-bit random unique numbers and store it to stdout
 * usage: generator <size of data in mb>
 */

#include <errno.h>
#include "include/zvmlib.h"

inline void swap(uint32_t *a, uint32_t *b)
{
  uint32_t temp = *a;
  *a = *b;
  *b = temp;
}

int main(int argc, char **argv)
{
  uint32_t i;
  uint32_t index;
  uint32_t *buf;
  uint32_t seq_size;
  uint32_t inc;

  /* check the command line */
  if(argc != 2)
  {
    FPRINTF(STDERR, "usage: generator number_of_elements [file_name]\n");
    return EPERM;
  }

  /* get buffer for the output channel */
  seq_size = STRTOL(argv[1], NULL, 10) / sizeof *buf;
  inc = -1U / seq_size; /* increment */
  buf = MALLOC(seq_size * sizeof *buf);

  /* check output buffer */
  if(buf == NULL || seq_size < 1)
  {
    FPRINTF(STDERR, "OutputChannel is not initialized "
        "addr = 0x%X, size = %d\n", (intptr_t) buf, seq_size);
    return ENOMEM;
  }

  /* populate array with sequence of numbers */
  FPRINTF(STDERR, "generating %u of %u-bit numbers..\n", seq_size, 8 * sizeof *buf);
  for(i = 0; i < seq_size; ++i)
    buf[i] = i * inc;

  /* make a mess in the array */
  for(i = 0; i < seq_size; ++i)
  {
    index = ((uint32_t) (RAND() << 22 ^ RAND() << 11 ^ RAND())) % seq_size;
    swap(&buf[i], &buf[index]);
  }
  FPRINTF(STDERR, "numbers generated\n");

  /* write data to the output channel */
  i = WRITE(STDOUT, (const char*)buf, seq_size * sizeof *buf) / sizeof *buf;
  FPRINTF(STDERR, "%u elements is written\n", i);
  if(i != seq_size)
  {
    FPRINTF(STDERR, "ERROR: couldn't write generated elements!\n");
    return EIO;
  }

  FPRINTF(STDERR, "success\n");
  return 0;
}


<|start_filename|>tests/functional/demo/sort/tester.uint32_t.c<|end_filename|>
/*
 * test array with 32-bit elements using algorithm from "generator"
 * return 0 if data is sorted, otherwise - 1
 */
#include "include/zvmlib.h"

#define ELEMENT_SIZE sizeof(uint32_t)
#define BUFFER_SIZE 0x4000

/* return 0 if all elements delta equal to inc */
int check_data(uint32_t inc, uint32_t *buf, uint32_t size)
{
  uint32_t i;

  for(i = 1; i < size; ++i)
    if(buf[i] - buf[i - 1] != inc) return 1;
  return 0;
}

int main(int argc, char **argv)
{
  uint32_t i;
  uint32_t buf[BUFFER_SIZE];
  uint32_t seq_size = 2; /* take in account the probe elements */
  uint32_t inc;

  /* get 2 elements and calculate the increment */
  i = READ(STDIN, buf, 2 * ELEMENT_SIZE);
  inc = i != 2 * ELEMENT_SIZE ? 0 : buf[1] - buf[0];

  /* exit on error */
  if(inc == 0) return 1;

  /*
   * read and check elements one by one, making the last element
   * the beginning one (to make ring buffer)
   */
  FPRINTF(STDERR, "checking..\n");
  for(i = 0; i == 0; buf[0] = buf[i])
  {
    /* get the next portion of data */
    i = READ(STDIN, buf, ELEMENT_SIZE * BUFFER_SIZE);
    if(i < 0)
      FPRINTF(STDERR, "errno = %d\n", i);
    if(i <= 0) break;

    i /= ELEMENT_SIZE;
    seq_size += i;
    i = check_data(inc, buf, i);
  }

  i = i || -1U / seq_size != inc;
  FPRINTF(STDERR, "the data %ssorted\n", i ? "UN" : "");
  return i;
}


<|start_filename|>tests/functional/channels/cdr/cdr.c<|end_filename|>
/*
 * cdr channel test. tests statistics goes to stdout channel.
 * returns the number of failed tests
 */
#include "include/zvmlib.h"
#include "include/ztest.h"

#define STDCDR_EMPTY "/dev/cdr_empty"
#define STDCDR_STUBBED "/dev/cdr_stubbed"
#define STDCDR_GOAT "/dev/cdr_scapegoat"

static int64_t eofpos = 0;
static char data_start = 0;

/* put unique bytes to cdr channel. preparing channel for put_and_test() */
static void initial_put(const char *alias)
{
  WRITE(alias, "\0", 1);
  ++eofpos;
}

/*
 * write the data and check if the data written to the proper position
 * return 0 if position as expected, otherwise -1
 */
static int put_and_test(const char *alias, const char *buf, int size)
{
  int code;
  char test_buf[BIG_ENOUGH];

  /* check arguments for sanity */
  if(size < 0 || buf == NULL || alias == NULL) return -1;
  
  /* put the data and update the channel size */
  code = WRITE(alias, buf, size);
  if(code != size) return code;
  eofpos += code;

  /* read from the start channel position (0) */
  code = PREAD(alias, test_buf, size, 0);
  ZTEST(code == size);
  ZTEST(MEMCMP(buf, test_buf, size) != 0);

  /* read from the current channel position (eofpos) */
  code = PREAD(alias, test_buf, size, eofpos);
  ZTEST(code == 0);

  /* read from the proper alias position (eofpos - size) */
  code = PREAD(alias, test_buf, size, eofpos - size);
  ZTEST(code == size);
  ZTEST(MEMCMP(buf, test_buf, size) == 0);

  return 0;
}

#define MSG_OK(alias, buf) ZTEST(put_and_test((alias), buf, sizeof(buf) - 1) == 0)
#define MSG_ERR(alias, buf) ZTEST(put_and_test((alias), buf, sizeof(buf) - 1) != 0)
int main(int argc, char **argv)
{
  int overall_errors = 0;
  char buf[BIG_ENOUGH];

  /* test an empty cdr channel */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST AN EMPTY CDR\n");
  initial_put(STDCDR_EMPTY);
  MSG_OK(STDCDR_EMPTY, "01234");
  MSG_OK(STDCDR_EMPTY, "567");
  MSG_OK(STDCDR_EMPTY, "89abcdefg");
  MSG_OK(STDCDR_EMPTY, "zyx");
  MSG_OK(STDCDR_EMPTY, "this is the end");
  MSG_ERR(STDCDR_EMPTY, "this write should fail");
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test stubbed cdr channel */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST STUBBED CDR\n");
  eofpos = MANIFEST->channels[OPEN(STDCDR_STUBBED)].size;
  FPRINTF(STDERR, "%s size = %ld\n",
      MANIFEST->channels[OPEN(STDCDR_STUBBED)].name, eofpos);
  MSG_OK(STDCDR_STUBBED, "01234");
  MSG_OK(STDCDR_STUBBED, "567");
  MSG_OK(STDCDR_STUBBED, "89abcdefg");
  MSG_OK(STDCDR_STUBBED, "zyx");
  MSG_OK(STDCDR_STUBBED, "this is the end");
  MSG_ERR(STDCDR_STUBBED, "this write should fail");
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test (in)valid write cases */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST (IN)VALID CDR WRITE CASES\n");
  ZTEST(PWRITE(STDCDR_GOAT, buf, 0, 0) == 0); /* accessing 0 bytes is always ok */
  ZTEST(PWRITE(STDCDR_GOAT, buf, -1, -1) < 0); /* invalid size, offset ignored = fail */
  ZTEST(PWRITE(STDCDR_GOAT, buf, -1, 0) < 0); /* invalid size, offset ignored = fail */
  ZTEST(PWRITE(STDCDR_GOAT, buf, -1, 1) < 0); /* invalid size, offset ignored = fail */
  ZTEST(PWRITE(STDCDR_GOAT, buf, 0, -1) == 0); /* accessing of 0 bytes is always ok */
  ZTEST(PWRITE(STDCDR_GOAT, buf, 1, -1) == 1); /* size = 1, offset ignored = 1 byte written */
  ZTEST(PWRITE(STDCDR_GOAT, buf, 0, MANIFEST->channels[OPEN(STDCDR_GOAT)].limits[PutSizeLimit] + 1) == 0);
  ZTEST(PWRITE(STDCDR_GOAT, buf, 1, MANIFEST->channels[OPEN(STDCDR_GOAT)].limits[PutSizeLimit] + 1) == 1);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test (in)valid read cases */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST (IN)VALID CDR READ CASES\n");
  ZTEST(PREAD(STDCDR_GOAT, buf, 0, 0) == 0); /* accessing 0 bytes is always ok */
  ZTEST(PREAD(STDCDR_GOAT, buf, -1, -1) < 0); /* invalid size, invalid offset = fail */
  ZTEST(PREAD(STDCDR_GOAT, buf, -1, 0) < 0); /* invalid size, invalid offset = fail */
  ZTEST(PREAD(STDCDR_GOAT, buf, -1, 1) < 0); /* invalid size, invalid offset = fail */
  ZTEST(PREAD(STDCDR_GOAT, buf, 0, -1) == 0); /* accessing 0 bytes is always ok */
  ZTEST(PREAD(STDCDR_GOAT, buf, 1, -1) < 0); /* valid size, invalid offset = fail */
  ZTEST(PREAD(STDCDR_GOAT, buf, 0, MANIFEST->channels[OPEN(STDCDR_GOAT)].limits[PutSizeLimit] + 1) < 0);
  ZTEST(PREAD(STDCDR_GOAT, buf, 1, MANIFEST->channels[OPEN(STDCDR_GOAT)].limits[PutSizeLimit] + 1) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test NULL buffer cases */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST NULL BUFFER CASES\n");
  ZTEST(PWRITE(STDCDR_GOAT, NULL, 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, NULL, 0, 0) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other invalid buffer address/size cases for pwrite */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER INVALID BUFFER/SIZE CASES FOR PWRITE\n");
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x1, 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0xffff, 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x10000, -1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, MANIFEST->heap_ptr, MANIFEST->heap_size + 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size, 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x100000000LL - 0x1000001 - 0x10000, 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x100000000LL, 1, 0) < 0);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x100000000LL - 0x1000000, 0x1000001, 0) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other valid buffer address/size cases for pwrite */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER VALID BUFFER/SIZE CASES FOR PWRITE\n");
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x10000, 1, 0) == 1);
  ZTEST(PWRITE(STDCDR_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size - 1, 1, 0) == 1);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x100000000LL - 0x1000000, 1, 0) == 1);
  ZTEST(PWRITE(STDCDR_GOAT, (void*)0x100000000LL - 0x1, 1, 0) == 1);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other invalid buffer address/size cases for pread */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER INVALID BUFFER/SIZE CASES FOR PREAD\n");
  ZTEST(PREAD(STDCDR_GOAT, (char*)main, 1, 0) < 0);
  ZTEST(PREAD(STDCDR_GOAT, MANIFEST->heap_ptr, MANIFEST->heap_size + 1, 0) < 0);
  ZTEST(PREAD(STDCDR_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size, 1, 0) < 0);
  ZTEST(PREAD(STDCDR_GOAT, (void*)0x100000000LL - 0x1000001, 1, 0) < 0);
  ZTEST(PREAD(STDCDR_GOAT, (void*)0x100000000LL, 1, 0) < 0);
  ZTEST(PREAD(STDCDR_GOAT, (void*)0x100000000LL - 0x1000000, 0x1000001, 0) < 0);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* test other valid buffer address/size cases for pread */
  ERRCOUNT = 0;
  FPRINTF(STDERR, "TEST OTHER VALID BUFFER/SIZE CASES FOR PREAD\n");
  ZTEST(PREAD(STDCDR_GOAT, &data_start, 1, 0) == 1);
  ZTEST(PREAD(STDCDR_GOAT, MANIFEST->heap_ptr + MANIFEST->heap_size - 1, 1, 0) == 1);
  ZTEST(PREAD(STDCDR_GOAT, (void*)0x100000000LL - 0x1000000, 1, 0) == 1);
  ZTEST(PREAD(STDCDR_GOAT, (void*)0x100000000LL - 0x1, 1, 0) == 1);
  overall_errors += ERRCOUNT;
  FPRINTF(STDERR, ERRCOUNT ? "TEST FAILED\n\n" : "TEST SUCCEED\n\n");

  /* exit with code */
  if(overall_errors > 0)
    FPRINTF(STDERR, "OVERALL TEST FAILED with %d errors\n", overall_errors);
  else
    FPRINTF(STDERR, "OVERALL TEST SUCCEED\n\n");

  return overall_errors;
}


<|start_filename|>src/loader/elf_util.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * NaCl helper functions to deal with elf images
 */

#ifndef ELF_UTIL_H_
#define ELF_UTIL_H_ 1

#include "src/loader/sel_ldr.h"

struct ElfImage;
struct Gio;

uintptr_t ElfImageGetEntryPoint(const struct ElfImage *image);

struct ElfImage *ElfImageNew(struct Gio *gp);

void ValidateElfHeader(const struct ElfImage *image);

/*
 * TODO(robertm): decouple validation from computation of static_text_end
 * and max_vaddr
 * TODO(d'b): the function is too large, rewrite it
 */
void ValidateProgramHeaders(
  struct ElfImage *image,
  uint8_t         addr_bits,
  uintptr_t       *static_text_end,
  uintptr_t       *rodata_start,
  uintptr_t       *rodata_end,
  uintptr_t       *data_start,
  uintptr_t       *data_end,
  uintptr_t       *max_vaddr);

/*
 * Loads an ELF executable before the address space's memory
 * protections have been set up by NaClMemoryProtection().
 */
void ElfImageLoad(const struct ElfImage *image,
    struct Gio *gp, uint8_t addr_bits, uintptr_t mem_start);

void ElfImageDelete(struct ElfImage *image);

#endif  /* ELF_UTIL_H_ */


<|start_filename|>tests/functional/include/zvmlib.h<|end_filename|>
/*
 * zero library is a small set of functions to replace standard library
 * (zvm api need to be tested w/o glibc)
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ZLIB_H_
#define ZLIB_H_

#include <stdint.h>
#include <stdio.h> /* todo: get rid of it */
#include "api/zvm.h" /* zerovm api */

/***************************************************
 * zlib constants, macros and types
 ***************************************************/

/* standart channels */
#define STDIN "/dev/stdin"
#define STDOUT "/dev/stdout"
#define STDERR "/dev/stderr"

#define EOL "\r\n"
#define END_OF_SECTION ";"
#define ENVIRONMENT "/dev/nvram"
#define ENVIRONMENT_MAX_SIZE 0x1000

#define BIG_ENOUGH 0x10000

/***************************************************
 * zero library helper macros
 ***************************************************/
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

/***************************************************
 * zero library functionality available via macros
 ***************************************************/
#define MALLOC(size) malloc(size)
#define CALLOC(n, size) calloc(n, size)
#define REALLOC(p, size) realloc(p, size)
#define FREE(p) free(p)
#define MEMSET(s, c, n) memset(s, c, n)
#define MEMCPY(dst, src, n) memcpy(dst, src, n)
#define MEMCMP(s1, s2, n) memcmp(s1, s2, n)
#define ISUPPER(c) isupper(c)
#define TOUPPER(c) toupper(c)
#define ISLOWER(c) islower(c)
#define ISALPHA(c) isalpha(c)
#define ISSPACE(c) isspace(c)
#define ISDIGIT(c) isdigit(c)
#define STRCHR(s, c) strchr(s, c)
#define STRRCHR(s, c) strchr(s, c)
#define STRSPN(s1, s2) strspn(s1, s2)
#define STRCSPN(s1, s2) strcspn(s1, s2)
#define STRCPY(dst, src) strcpy(dst, src)
#define STRCAT(dst, src) strcat(dst, src)
#define STRCMP(s1, s2) strcmp(s1, s2)
#define STRLEN(s) strlen(s)
#define STRTOK(s, delim) strtok(s, delim)
#define ATOI(s) atoi(s)
#define STRTOL(p, end, base) strtol(p, end, base)
#define STRTOUL(p, end, base) strtoul(p, end, base)
#define RAND() rand()
#define SRAND(s) srand(s)
#define OPEN(alias) handle(alias) /* will be fixed */
#define CLOSE(handle)
#define EXIT(code) zvm_exit(code)
#define exit(code) zvm_exit(code)
#define READ(alias, buf, size) zvm_pread(handle(alias), buf, size, 0)
#define WRITE(alias, buf, size) zvm_pwrite(handle(alias), buf, size, 0)
#define PREAD(alias, buf, size, offset) zvm_pread(handle(alias), buf, size, offset)
#define PWRITE(alias, buf, size, offset) zvm_pwrite(handle(alias), buf, size, offset)
#define SPRINTF tfp_sprintf
#define FPRINTF(alias, ...) \
  do {\
    char _buf[BIG_ENOUGH];\
    int _size;\
    SPRINTF(_buf, __VA_ARGS__);\
    _size = STRLEN(_buf);\
    WRITE(alias, _buf, _size);\
  } while(0)
#define PRINTF(...) FPRINTF(STDOUT, __VA_ARGS__)
#define fprintf FPRINTF
#define printf PRINTF
#define sprintf SPRINTF

/***************************************************
 * zero library functions. it is recommended to use
 * above macros instead
 ***************************************************/
inline void *malloc(size_t size);
inline void *calloc(size_t n, size_t size);
inline void *realloc(void *p, size_t size);
inline void free(void *p);
inline void *memset(void *s, int c, size_t n);
inline void *memcpy(void *dst, const void *src, size_t n);
inline int memcmp(const void *s1, const void *s2, size_t n);
inline int isupper(int c);
inline int toupper(int c);
inline int islower(int c);
inline int isalpha(int c);
inline int isspace(int c);
inline int isdigit(int c);
inline char *strchr(const char *s, int c);
inline char *strrchr(const char *s, int c);
inline size_t strspn(const char *s1, const char *s2);
inline size_t strcspn(const char *s1, const char *s2);
inline char *strcpy(char *dst, const char *src);
inline char *strcat(char *dst, const char *src);
inline int strcmp(const void *s1, const void *s2);
inline size_t strlen(const char *s);
inline char *strtok(char *s, const char *delim);
inline int atoi(const char *s);
inline long int strtol(const char *p, char **end, int base);
inline unsigned long strtoul(const char *p, char **end, int base);
inline int rand();
inline void srand(unsigned int s);
inline int handle(const char *alias);
void tfp_sprintf(char *s, char *fmt, ...);

#endif /* ZLIB_H_ */


<|start_filename|>src/main/tools.h<|end_filename|>
/*
 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
/*
 * all macros, definitions and small functions which
 * not fit to other header and often used are here
 *
 * Copyright (c) 2012, LiteStack, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TOOLS_H_
#define TOOLS_H_

#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <glib.h>
#include <unistd.h>
#include <sys/stat.h>

/*
 * putting extern "C" { } in header files make emacs want to indent
 * everything, which looks odd.  rather than putting in fancy syntax
 * recognition in c-mode, we just use the following macros.
 */
#ifdef __cplusplus
# define EXTERN_C_BEGIN extern "C" {
# define EXTERN_C_END }

/* Mark this function as not throwing beyond */
#else
# define EXTERN_C_BEGIN
# define EXTERN_C_END
#endif

/* gcc only */
#define INLINE __inline__
#define UNREFERENCED_PARAMETER(P) do {(void) P;} while (0)
#define NORETURN __attribute__((noreturn))
#define NACL_WUR __attribute__((__warn_unused_result__))

/* size of the random biggest string */
#define BIG_ENOUGH_STRING 1024
#define MICROS_PER_MILLI 1000
#define MICRO_PER_SEC 1000000

#define ROUNDDOWN_64K(a) ((a) & ~(NACL_MAP_PAGESIZE - 1LLU))
#define ROUNDUP_64K(a) ROUNDDOWN_64K((a) + NACL_MAP_PAGESIZE - 1LLU)
#define ROUNDDOWN_4K(a) ((a) & ~(NACL_PAGESIZE - 1LLU))
#define ROUNDUP_4K(a) ROUNDDOWN_4K((a) + NACL_PAGESIZE - 1LLU)

/* from nacl_macros.h */
#define ARRAY_SIZE(arr) ((sizeof arr)/sizeof arr[0])
#define ARRAY_SIZE_SAFE(arr) (NaClArrayCheckHelper( \
    __builtin_types_compatible_p(__typeof__(&arr[0]), \
    __typeof__(arr))), ARRAY_SIZE(arr))

/*
 * Doing runtime checks is not really necessary -- this code is in
 * fact unreachable code that gets optimized out when used with the
 * ARRAY_SIZE_SAFE definition below.
 *
 * The runtime check is only useful when the build system is using
 * the inappropriate flags (e.g., missing -pedantic -Werror or
 * -pedantic-error), in which case instead of a compile-time error,
 * we'd get a runtime error.
 */
static INLINE void *NaClArrayCheckHelper(void *arg)
{
  if(NULL != arg) abort();
  return arg;
}

/*
 * ASSERT_SAME_SIZE(t1, t2) verifies that the two types have the same size
 * (as reported by sizeof).  When the check fails it generates a somewhat
 * opaque warning, mitigated by the variable's name.
 *
 * Examples:
 *   ASSERT_SAME_SIZE(void*, char*); // Likely to succeed!
 *   ASSERT_SAME_SIZE(char, long); // Unlikely to succeed
 */
#define ASSERT_SAME_SIZE(t1, t2) \
  do {char tested_types_are_not_the_same_size[sizeof(t1) == sizeof(t2)]; \
      (void) tested_types_are_not_the_same_size;} while (0)

/* return size of given file or negative error code */
int64_t GetFileSize(const char *name);

#endif /* TOOLS_H_ */


<|start_filename|>debian/samples/readdir/Makefile<|end_filename|>
NAME=readdir
PNACL_TOOL=/usr/lib/nacl/default-sdk/toolchain/linux_x86_glibc
INCLUDE_FLAGS=-I/usr/include/zerovm 

all: $(NAME).nexe run 

$(NAME).nexe: $(NAME).o
	$(PNACL_TOOL)/bin/x86_64-nacl-gcc -o $(NAME).nexe -s -static -T \
	$(PNACL_TOOL)/x86_64-nacl/lib64/ldscripts/elf64_nacl.x.static -melf64_nacl -m64 \
	$(DEBUG) $(NAME).o -L/usr/lib/zerovm -lzrt -lfs -lstdc++

$(NAME).o:
	$(PNACL_TOOL)/bin/x86_64-nacl-gcc -o $(NAME).o -Wall \
	$(INCLUDE_FLAGS) $(MACROS_FLAGS) $(DEBUG) -c -Wno-long-long -O2 -msse4.1 -m64 $(NAME).c

run:
	./run_tests.sh

clean:
	@rm -f some.input
	@rm -f $(NAME).nexe $(NAME).o *.log *.data
