diff options
author | Akos Kiss <akiss@inf.u-szeged.hu> | 2017-04-13 17:18:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-13 17:18:17 +0200 |
commit | 4b9e458f4414b663f898384bf74bfb603a84f697 (patch) | |
tree | 2a1325712df049abbfb1cf8495d76d1d176b9b60 /jerry-libc | |
parent | 950a0f10cd8271241560a93aacc97750abb16862 (diff) |
Add support for init/fini arrays to libc (#1725)
The arrays contain the addresses of functions annotated with
constructor or destructor attributes. The support is optional,
requires FEATURE_INIT_FINI cmake option to be set. As of now, the
option is _not_ available in tools/build.py directly, only via
`--cmake-param="-DFEATURE_INIT_FINI=ON"`.
JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
Diffstat (limited to 'jerry-libc')
-rw-r--r-- | jerry-libc/CMakeLists.txt | 12 | ||||
-rw-r--r-- | jerry-libc/arch/arm-v7.h | 31 | ||||
-rw-r--r-- | jerry-libc/arch/x86-32.h | 42 | ||||
-rw-r--r-- | jerry-libc/arch/x86-64.h | 30 | ||||
-rw-r--r-- | jerry-libc/jerry-libc-defs.h | 6 | ||||
-rw-r--r-- | jerry-libc/jerry-libc-init.c | 98 | ||||
-rw-r--r-- | jerry-libc/target/posix/jerry-libc-target.c | 4 |
7 files changed, 192 insertions, 31 deletions
diff --git a/jerry-libc/CMakeLists.txt b/jerry-libc/CMakeLists.txt index 8b30af5b..b594e74e 100644 --- a/jerry-libc/CMakeLists.txt +++ b/jerry-libc/CMakeLists.txt @@ -16,6 +16,18 @@ cmake_minimum_required (VERSION 2.8.12) set(JERRY_LIBC_NAME jerry-libc) project (${JERRY_LIBC_NAME} C ASM) +# Optional features +set(FEATURE_INIT_FINI OFF CACHE BOOL "Enable init/fini arrays?") + +# Status messages +message(STATUS "FEATURE_INIT_FINI " ${FEATURE_INIT_FINI}) + +# Checks the optional features +# Enable init/fini arrays +if(FEATURE_INIT_FINI) + set(DEFINES_LIBC ${DEFINES_LIBC} ENABLE_INIT_FINI) +endif() + # Architecture-specific configuration if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") set(DEFINES_LIBC ${DEFINES_LIBC} __TARGET_HOST_x64) diff --git a/jerry-libc/arch/arm-v7.h b/jerry-libc/arch/arm-v7.h index ba0743ef..bfe28194 100644 --- a/jerry-libc/arch/arm-v7.h +++ b/jerry-libc/arch/arm-v7.h @@ -80,24 +80,37 @@ \ pop {r4-r12, pc}; +#ifdef ENABLE_INIT_FINI /* + * bl libc_init_array + */ +#define _INIT \ + bl libc_init_array; +#else /* !ENABLE_INIT_FINI */ +#define _INIT +#endif /* ENABLE_INIT_FINI */ + +/* + * bl libc_init_array + * * ldr argc ([sp + 0x0]) -> r0 * add argv (sp + 0x4) -> r1 - * * bl main * * bl exit * * infinite loop */ -#define _START \ - ldr r0, [sp, #0]; \ - add r1, sp, #4; \ - bl main; \ - \ - bl exit; \ - 1: \ - b 1b +#define _START \ + _INIT; \ + \ + ldr r0, [sp, #0]; \ + add r1, sp, #4; \ + bl main; \ + \ + bl exit; \ + 1: \ + b 1b; /** * If hard-float mode: diff --git a/jerry-libc/arch/x86-32.h b/jerry-libc/arch/x86-32.h index eb8d0e39..c674f4a9 100644 --- a/jerry-libc/arch/x86-32.h +++ b/jerry-libc/arch/x86-32.h @@ -92,7 +92,19 @@ pop %edi; \ ret; +#ifdef ENABLE_INIT_FINI /* + * call libc_init_array + */ +#define _INIT \ + call libc_init_array; +#else /* !ENABLE_INIT_FINI */ +#define _INIT +#endif /* ENABLE_INIT_FINI */ + +/* + * call libc_init_array + * * push argv (%esp + 4) * push argc ([%esp + 0x4]) * @@ -103,20 +115,22 @@ * * infinite loop */ -#define _START \ - mov %esp, %eax; \ - add $4, %eax; \ - push %eax; \ - mov 0x4 (%esp), %eax; \ - push %eax; \ - \ - call main; \ - \ - push %eax; \ - call exit; \ - \ - 1: \ - jmp 1b +#define _START \ + _INIT; \ + \ + mov %esp, %eax; \ + add $4, %eax; \ + push %eax; \ + mov 0x4 (%esp), %eax; \ + push %eax; \ + \ + call main; \ + \ + push %eax; \ + call exit; \ + \ + 1: \ + jmp 1b; /* * setjmp diff --git a/jerry-libc/arch/x86-64.h b/jerry-libc/arch/x86-64.h index 2b36fbc9..5a35d021 100644 --- a/jerry-libc/arch/x86-64.h +++ b/jerry-libc/arch/x86-64.h @@ -64,7 +64,19 @@ syscall; \ ret; +#ifdef ENABLE_INIT_FINI /* + * call libc_init_array + */ +#define _INIT \ + call libc_init_array; +#else /* !ENABLE_INIT_FINI */ +#define _INIT +#endif /* ENABLE_INIT_FINI */ + +/* + * call libc_init_array + * * mov argc ([%rsp]) -> %rdi * mov argv (%rsp + 0x8) -> %rsi * @@ -76,15 +88,17 @@ * infinite loop */ #define _START \ - mov (%rsp), %rdi; \ - mov %rsp, %rsi; \ - add $8, %rsi; \ - callq main; \ + _INIT; \ + \ + mov (%rsp), %rdi; \ + mov %rsp, %rsi; \ + add $8, %rsi; \ + callq main; \ \ - mov %rax, %rdi; \ - callq exit; \ - 1: \ - jmp 1b + mov %rax, %rdi; \ + callq exit; \ + 1: \ + jmp 1b; /* * setjmp diff --git a/jerry-libc/jerry-libc-defs.h b/jerry-libc/jerry-libc-defs.h index 73feae34..3a61a936 100644 --- a/jerry-libc/jerry-libc-defs.h +++ b/jerry-libc/jerry-libc-defs.h @@ -27,5 +27,11 @@ #define __attr_used___ __attribute__((used)) #define __attr_noreturn___ __attribute__((noreturn)) #define __attr_noinline___ __attribute__((noinline)) +#define __attr_weak___ __attribute__((weak)) + +#ifdef ENABLE_INIT_FINI +void libc_init_array (void); +void libc_fini_array (void); +#endif /* ENABLE_INIT_FINI */ #endif /* !DEFS_H */ diff --git a/jerry-libc/jerry-libc-init.c b/jerry-libc/jerry-libc-init.c new file mode 100644 index 00000000..712359b5 --- /dev/null +++ b/jerry-libc/jerry-libc-init.c @@ -0,0 +1,98 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * 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. + * + * This file is based on work under the following copyright and permission + * notice: + * + * Copyright (C) 2004 CodeSourcery, LLC + * + * Permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies. + * + * This file is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "jerry-libc-defs.h" + +#ifdef ENABLE_INIT_FINI + +/* These magic symbols are provided by the linker. */ +typedef void (*libc_init_fn_t) (void); + +extern libc_init_fn_t __preinit_array_start[] __attr_weak___; +extern libc_init_fn_t __preinit_array_end[] __attr_weak___; +extern libc_init_fn_t __init_array_start[] __attr_weak___; +extern libc_init_fn_t __init_array_end[] __attr_weak___; +extern libc_init_fn_t __fini_array_start[] __attr_weak___; +extern libc_init_fn_t __fini_array_end[] __attr_weak___; +extern void _init (void); +extern void _fini (void); + + +/** + * No-op default _init. + */ +void __attr_weak___ +_init (void) +{ +} /* _init */ + +/** + * No-op default _fini. + */ +void __attr_weak___ +_fini (void) +{ +} /* _fini */ + +/** + * Iterate over all the init routines. + */ +void +libc_init_array (void) +{ + size_t count = (size_t) (__preinit_array_end - __preinit_array_start); + for (size_t i = 0; i < count; i++) + { + __preinit_array_start[i] (); + } + + _init (); + + count = (size_t) (__init_array_end - __init_array_start); + for (size_t i = 0; i < count; i++) + { + __init_array_start[i] (); + } +} /* libc_init_array */ + +/** + * Run all the cleanup routines. + */ +void +libc_fini_array (void) +{ + size_t count = (size_t) (__fini_array_end - __fini_array_start); + for (size_t i = count; i > 0; i--) + { + __fini_array_start[i - 1] (); + } + + _fini (); +} /* libc_fini_array */ + +#endif /* ENABLE_INIT_FINI */ diff --git a/jerry-libc/target/posix/jerry-libc-target.c b/jerry-libc/target/posix/jerry-libc-target.c index 263ff510..c1cdc759 100644 --- a/jerry-libc/target/posix/jerry-libc-target.c +++ b/jerry-libc/target/posix/jerry-libc-target.c @@ -51,6 +51,10 @@ long int syscall_3 (long int syscall_no, long int arg1, long int arg2, long int void __attr_noreturn___ __attr_used___ exit (int status) /**< status code */ { +#ifdef ENABLE_INIT_FINI + libc_fini_array (); +#endif /* ENABLE_INIT_FINI */ + syscall_1 (SYSCALL_NO (close), (long int) stdin); syscall_1 (SYSCALL_NO (close), (long int) stdout); syscall_1 (SYSCALL_NO (close), (long int) stderr); |