blob: 1c66b776506cd64c1607591e956c14ccdb57820c [file] [log] [blame]
/*
* 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.
*/
/*
* NaCl tests for simple syscalls not using newlib
*/
#define CHECK_ERRNO 1
#include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h"
/*
* These must come after <sys/nacl_syscalls.h> when using nacl-newlib
* otherwise we get errors about conflicting types. This is a bug in
* nacl-newlib.
*/
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
/* NOTE: defining CHECK_ERRNO pulls in some newlib magic (reent.h, etc.) */
#if defined(CHECK_ERRNO)
#include <errno.h>
#endif
int mystrlen(const char* s) {
int count = 0;
while(*s++) ++count;
return count;
}
#define myprint(s) write(1, s, mystrlen(s))
void hextochar(int n, char buffer[9]) {
int i;
buffer[8] = 0;
for (i=0; i < 8; ++i) {
int nibble = 0xf & (n >> (4 * (7 - i)));
if (nibble <= 9) {
buffer[i] = nibble + '0';
} else {
buffer[i] = nibble - 10 + 'A';
}
}
}
void PrintInt(int i) {
char buffer[16];
hextochar(i, buffer);
myprint(buffer);
myprint("\n");
}
void Error(const char* message) {
myprint("ERROR: ");
myprint(message);
_exit(-1);
}
#if defined(CHECK_ERRNO)
void CheckErrno(int expected) {
char buffer[16];
myprint("\nerrno\n");
hextochar(errno, buffer);
myprint(buffer);
myprint("\n");
if (expected != errno) Error("bad errno value\n");
}
#else
void CheckErrno(int expected) {
expected = expected;
}
#endif
const int kExitOk = 69;
const int kMmapBase = 0xa00000;
const int kMmapSize = 0x10000;
const int kInvalidFileDescriptor = 100;
/*
* This is defined by the linker as the address of the end of our data segment.
* That's where the break starts out by default.
*/
extern char end;
int main(void) {
/*
* Round up to the end of the page that's our last initial data page.
* Then add 10MB for good measure to be out of the way of any allocations
* that might have been done before we got here.
*/
const int sysbrkBase = ((((intptr_t) &end) + 0xffff) & -0x10000) + (10 << 20);
void *map_result;
int i;
CheckErrno(0);
myprint("\nnull_syscall()\n");
null_syscall();
myprint("\nsysbreak()\n");
i = (int) sysbrk(0);
PrintInt(i);
if (0 == i) Error("bad sysbrk() value\n");
if (sysbrkBase < i) {
Error("INTERNAL ERROR: sysbrkBase too small\n");
}
myprint("\nsysbrk()\n");
i = (int) sysbrk((void *) sysbrkBase);
PrintInt(i);
if (sysbrkBase != i) Error("bad sysbrk() value\n");
myprint("\nmmap()\n");
i = (int) mmap(0, kMmapSize,
PROT_READ, MAP_ANONYMOUS | MAP_SHARED,
-1, 0);
PrintInt(i);
if (-1 == i) Error("bad mmap() value\n");
myprint("\nmunmap()\n");
i = (int) munmap((void *)i, kMmapSize);
PrintInt(i);
if (0 != i) Error("bad munmap() value\n");
myprint("\nmmap()\n");
map_result = mmap((void *)kMmapBase, kMmapSize,
PROT_READ, MAP_ANONYMOUS | MAP_SHARED,
-1, 0);
i = (int) map_result;
PrintInt(i);
/*
* It is an ERROR to expect i to be kMapBase. Since the mmap
* syscall were not made with MAP_FIXED, the kernel is free to use
* the provided address as a hint -- or to ignore it altogether.
* Exactly what behavior we implement may vary from release to
* release -- thus, the only reasonable value to compare this with
* is MAP_FAILED.
*/
if (MAP_FAILED == map_result) Error("bad: mmap() failed\n");
myprint("\nmunmap()\n");
i = (int) munmap(map_result, kMmapSize);
PrintInt(i);
if (0 != i) Error("bad munmap() value\n");
CheckErrno(0);
/* Some expect failures */
myprint("\nclose()\n");
i = (int) close(kInvalidFileDescriptor);
PrintInt(i);
if (~0 != i) Error("bad close value\n");
CheckErrno(EBADF);
myprint("\nclock()\n");
i = clock();
PrintInt(i);
if (0 > i) Error("bad clock value\n");
myprint("before _exit()\n");
_exit(kExitOk);
return 0;
}