From 61dd7a5dd926ca951d67e8e1317de4d4b558fc23 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Fri, 1 Aug 2014 15:49:27 +0400 Subject: [PATCH] nostdlib under libc_raw=1 option. --- Makefile | 2 + Makefile.mk | 20 +- src/libruntime/target/linux/asm_x86.h | 1 + src/libruntime/target/linux/jerry-libc.c | 367 ++++++++++++++++++++++ src/libruntime/target/linux/jerry-start.S | 16 + src/main.c | 11 +- 6 files changed, 405 insertions(+), 12 deletions(-) create mode 100644 src/libruntime/target/linux/jerry-start.S diff --git a/Makefile b/Makefile index 2962f0534..7d4e4fb8a 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,8 @@ export todo export fixme export color export sanitize +export musl +export libc_raw all: clean $(TESTS_TARGET) $(CHECK_TARGETS) diff --git a/Makefile.mk b/Makefile.mk index 951fa048c..309c9bd6c 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -99,9 +99,15 @@ else endif ifeq ($(musl),1) - OPTION_MUSL := enable + OPTION_LIBC_MUSL := enable else - OPTION_MUSL := disable + OPTION_LIBC_MUSL := disable +endif + +ifeq ($(libc_raw),1) + OPTION_LIBC_RAW := enable +else + OPTION_LIBC_RAW := disable endif ifeq ($(color),1) @@ -219,7 +225,7 @@ SOURCES_JERRY = \ $(wildcard ./src/liballocator/*.c) \ $(wildcard ./src/libcoreint/*.c) \ $(wildcard ./src/liboptimizer/*.c) ) \ - $(wildcard src/libruntime/target/$(TARGET_SYSTEM)/*.c) + $(wildcard src/libruntime/target/$(TARGET_SYSTEM)/*.[cS]) INCLUDES_JERRY = \ -I src \ @@ -240,14 +246,20 @@ ifeq ($(OPTION_MCU),disable) DEFINES_JERRY += -D__TARGET_HOST_x64 -DJERRY_SOURCE_BUFFER_SIZE=$$((1024*1024)) CFLAGS_COMMON += -fno-stack-protector - ifeq ($(OPTION_MUSL),enable) + ifeq ($(OPTION_LIBC_MUSL),enable) CC := musl-$(CC) DEFINES_JERRY += -DLIBC_MUSL CFLAGS_COMMON += -static else + ifeq ($(OPTION_LIBC_RAW),enable) + DEFINES_JERRY += -DLIBC_RAW + CFLAGS_COMMON += -nostdlib + else + CFLAGS_COMMON += -DLIBC_STD ifeq ($(OPTION_SANITIZE),enable) CFLAGS_COMMON += -fsanitize=address endif + endif endif ifeq ($(OPTION_COLOR),enable) diff --git a/src/libruntime/target/linux/asm_x86.h b/src/libruntime/target/linux/asm_x86.h index d4efd1697..05e0d0fca 100644 --- a/src/libruntime/target/linux/asm_x86.h +++ b/src/libruntime/target/linux/asm_x86.h @@ -17,6 +17,7 @@ #define LINUX_X86_ASM_H FIXME( Implement x86 ABI ); +#error "Not implemented" /* * mov syscall_no -> %rax diff --git a/src/libruntime/target/linux/jerry-libc.c b/src/libruntime/target/linux/jerry-libc.c index f5c861bac..c7ee6ecfa 100644 --- a/src/libruntime/target/linux/jerry-libc.c +++ b/src/libruntime/target/linux/jerry-libc.c @@ -21,6 +21,372 @@ #include "jerry-libc.h" #include + +#ifdef LIBC_RAW + +#ifdef __TARGET_HOST_x64 +# include "asm_x64.h" +#elif defined(__TARGET_HOST_x86) +# include "asm_x86.h" +#endif /* !__TARGET_HOST_x64 && TARGET_HOST_x86 */ + +FIXME( Rename __unused ) +#undef __unused + +#include +#include +#include +#include +#include + +/** + * stdin file descriptor + */ +#define LIBC_STDIN 0 + +/** + * stdout file descriptor + */ +#define LIBC_STDOUT 1 + +/** + * stderr file descriptor + */ +#define LIBC_STDERR 2 + +/** + * Exit program with ERR_SYSCALL if syscall_ret_val is negative + */ +#define LIBC_EXIT_ON_ERROR( syscall_ret_val) \ + if ( unlikely( ( syscall_ret_val ) < 0 ) ) \ + { \ + __exit( -ERR_SYSCALL); \ + } + +static long int syscall_1( long int syscall_no, long int arg1); +static long int syscall_2( long int syscall_no, long int arg1, long int arg2); +static long int syscall_3( long int syscall_no, long int arg1, long int arg2, long int arg3); + +/** + * System call with one argument. + * + * @return syscall's return value + */ +static long int +syscall_1( long int syscall_no, /**< syscall number */ + long int arg1) /**< argument */ +{ + long int ret; + + SYSCALL_1( syscall_no, arg1, ret); + + LIBC_EXIT_ON_ERROR( ret ); + + return ret; +} /* syscall_1 */ + +/** + * System call with two arguments. + * + * @return syscall's return value + */ +static long int +syscall_2( long int syscall_no, /**< syscall number */ + long int arg1, /**< first argument */ + long int arg2) /**< second argument */ +{ + long int ret; + + SYSCALL_2( syscall_no, arg1, arg2, ret); + + LIBC_EXIT_ON_ERROR( ret ); + + return ret; +} /* syscall_2 */ + +/** + * System call with three arguments. + * + * @return syscall's return value + */ +static long int +syscall_3( long int syscall_no, /**< syscall number */ + long int arg1, /**< first argument */ + long int arg2, /**< second argument */ + long int arg3) /**< third argument */ +{ + long int ret; + + SYSCALL_3( syscall_no, arg1, arg2, arg3, ret); + + LIBC_EXIT_ON_ERROR( ret ); + + return ret; +} /* syscall_3 */ + +/** + * printf + * + * @return number of characters printed + */ +int +__printf(const char *format, /**< format string */ + ...) /**< parameters' values */ +{ + va_list args; + + va_start( args, format); + + FIXME( Implement real printf and move it to common part of libruntime ); + long int ret = syscall_3( __NR_write, LIBC_STDOUT, (long int)format, (long int)__strlen(format)); + + va_end( args); + + return (int)ret; +} /* __printf */ + +/** Output of character. Writes the character c, cast to an unsigned char, to stdout. */ +int +__putchar (int c) +{ + syscall_3( __NR_write, LIBC_STDOUT, (long int)&c, 1); + + return c; +} /* __putchar */ + +/** + * Exit - cause normal process termination with specified status code + */ +void __noreturn +__exit (int status) /**< status code */ +{ + syscall_1( __NR_close, LIBC_STDIN); + syscall_1( __NR_close, LIBC_STDOUT); + syscall_1( __NR_close, LIBC_STDERR); + + syscall_1( __NR_exit_group, status); + + while ( true ) + { + /* unreachable */ + } +} /* __exit */ + +/** + * fopen + * + * @return _FILE pointer - upon successful completion, + * NULL - otherwise + */ +_FILE* +__fopen(const char *path, /**< file path */ + const char *mode) /**< file open mode */ +{ + bool may_read = false, + may_write = false, + truncate = false, + create_if_not_exist = false, + position_at_end = false; + + JERRY_ASSERT( path != NULL && mode != NULL ); + JERRY_ASSERT( mode[1] == '+' || mode[1] == '\0' ); + + switch( mode[0] ) + { + case 'r': + may_read = true; + may_write = (mode[1] == '+'); + break; + case 'w': + may_write = true; + truncate = true; + create_if_not_exist = true; + may_read = (mode[1] == '+'); + break; + case 'a': + may_write = true; + position_at_end = true; + create_if_not_exist = true; + if ( mode[1] == '+' ) + { + JERRY_UNIMPLEMENTED(); + } + break; + default: + JERRY_UNREACHABLE(); + } + + int flags = 0; + int access = S_IRUSR | S_IWUSR; + if ( may_read && !may_write ) + { + flags = O_RDONLY; + } + else if ( !may_read && may_write ) + { + flags = O_WRONLY; + } + else + { + JERRY_ASSERT( may_read && may_write ); + + flags = O_RDWR; + } + + if ( truncate ) + { + flags |= O_TRUNC; + } + + if ( create_if_not_exist ) + { + flags |= O_CREAT; + } + + if ( position_at_end ) + { + flags |= O_APPEND; + } + + long int ret = syscall_3( __NR_open, (long int)path, flags, access); + + return (void*)(uintptr_t)(ret); +} /* __fopen */ + +/** + * The rewind() function sets the file position indicator + * for the stream pointed to by STREAM to the beginning of the file. + */ +void +__rewind (_FILE *stream) /**< stream pointer */ +{ + syscall_3( __NR_lseek, (long int)stream, 0, SEEK_SET); +} /* __rewind */ + +/** + * fclose + * + * @return 0 - upon successful completion, + * non-zero value - otherwise. + */ +int +__fclose(_FILE *fp) /**< stream pointer */ +{ + syscall_2( __NR_close, (long int)fp, 0); + + return 0; +} /* __fclose */ + +/** + * fseek + */ +int +__fseek(_FILE * fp, /**< stream pointer */ + long offset, /**< offset */ + _whence_t whence) /**< specifies position type + to add offset to */ +{ + int whence_real = SEEK_CUR; + switch ( whence ) + { + case __SEEK_SET: + whence_real = SEEK_SET; + break; + case __SEEK_CUR: + whence_real = SEEK_CUR; + break; + case __SEEK_END: + whence_real = SEEK_END; + break; + } + + syscall_3( __NR_lseek, (long int)fp, offset, whence_real); + + return 0; +} /* __fseek */ + +/** + * ftell + */ +long +__ftell(_FILE * fp) /**< stream pointer */ +{ + long int ret = syscall_3( __NR_lseek, (long int)fp, 0, SEEK_CUR); + + return ret; +} /* __ftell */ + +/** + * fread + * + * @return number of bytes read + */ +size_t +__fread(void *ptr, /**< address of buffer to read to */ + size_t size, /**< size of elements to read */ + size_t nmemb, /**< number of elements to read */ + _FILE *stream) /**< stream pointer */ +{ + long int ret; + size_t bytes_read = 0; + + do + { + ret = syscall_3( __NR_read, (long int)stream, (long int) ((uint8_t*)ptr + bytes_read), (long int) (size * nmemb - bytes_read)); + + bytes_read += (size_t)ret; + } while (bytes_read != size * nmemb && ret != 0); + + return bytes_read; +} /* __fread */ + +/** + * fwrite + * + * @return number of bytes written + */ +size_t +__fwrite(const void *ptr, /**< data to write */ + size_t size, /**< size of elements to write */ + size_t nmemb, /**< number of elements */ + _FILE *stream) /**< stream pointer */ +{ + long int ret; + size_t bytes_written = 0; + + do + { + ret = syscall_3( __NR_write, (long int)stream, (long int) ((uint8_t*)ptr + bytes_written), (long int) (size * nmemb - bytes_written)); + + bytes_written += (size_t)ret; + } while (bytes_written != size * nmemb); + + return bytes_written; +} /* __fwrite */ + +/** + * fprintf + * + * @return number of characters printed + */ +int +__fprintf(_FILE *stream, /**< stream pointer */ + const char *format, /**< format string */ + ...) /**< parameters' values */ +{ + va_list args; + + va_start( args, format); + + long int ret = syscall_3( __NR_write, (long int)stream, (long int)format, (long int)__strlen(format)); + + va_end( args); + + return (int)ret; +} /* __fprintf */ + +#elif defined(LIBC_STD) || defined(LIBC_MUSL) + #include #include @@ -184,3 +550,4 @@ __fprintf(_FILE *stream, /**< stream pointer */ return ret; } /* __fprintf */ +#endif /* LIBC_STD || LIBC_MUSL */ diff --git a/src/libruntime/target/linux/jerry-start.S b/src/libruntime/target/linux/jerry-start.S new file mode 100644 index 000000000..e81789a85 --- /dev/null +++ b/src/libruntime/target/linux/jerry-start.S @@ -0,0 +1,16 @@ +#ifdef __TARGET_HOST_x64 +# include "asm_x64.h" +#elif defined(__TARGET_HOST_x86) +# include "asm_x86.h" +#else /* !__HOST && !__TARGET_HOST_x86 */ +# error "!__HOST && !__TARGET_HOST_x86" +#endif /* !__HOST && !__TARGET_HOST_x86 */ + +#ifdef LIBC_RAW +.global _start +_start: + _START +1: + jmp 1b +.end _start +#endif /* LIBC_RAW */ diff --git a/src/main.c b/src/main.c index 990d05141..eb934e30d 100644 --- a/src/main.c +++ b/src/main.c @@ -137,15 +137,10 @@ read_sources (const char *script_file_names[], jerry_exit (ERR_MEMORY); } - size_t bytes_read = 0; - while ( bytes_read < current_source_size ) + size_t bytes_read = __fread( source_buffer, 1, current_source_size, file); + if ( bytes_read < current_source_size ) { - bytes_read += __fread( source_buffer_tail + bytes_read, sizeof(uint8_t), current_source_size - bytes_read, file); - - if ( __ferror( file) != 0 ) - { - jerry_exit (ERR_IO); - } + jerry_exit (ERR_IO); } __fclose( file);