aboutsummaryrefslogtreecommitdiff
path: root/jerry-libc
diff options
context:
space:
mode:
authorAkos Kiss <akiss@inf.u-szeged.hu>2017-04-13 17:18:17 +0200
committerGitHub <noreply@github.com>2017-04-13 17:18:17 +0200
commit4b9e458f4414b663f898384bf74bfb603a84f697 (patch)
tree2a1325712df049abbfb1cf8495d76d1d176b9b60 /jerry-libc
parent950a0f10cd8271241560a93aacc97750abb16862 (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.txt12
-rw-r--r--jerry-libc/arch/arm-v7.h31
-rw-r--r--jerry-libc/arch/x86-32.h42
-rw-r--r--jerry-libc/arch/x86-64.h30
-rw-r--r--jerry-libc/jerry-libc-defs.h6
-rw-r--r--jerry-libc/jerry-libc-init.c98
-rw-r--r--jerry-libc/target/posix/jerry-libc-target.c4
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);