Skip to content

Commit

Permalink
Add support for init/fini arrays to libc
Browse files Browse the repository at this point in the history
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 [email protected]
  • Loading branch information
akosthekiss committed Apr 10, 2017
1 parent e522e74 commit 3a20c14
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 31 deletions.
12 changes: 12 additions & 0 deletions jerry-libc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
31 changes: 22 additions & 9 deletions jerry-libc/arch/arm-v7.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
42 changes: 28 additions & 14 deletions jerry-libc/arch/x86-32.h
Original file line number Diff line number Diff line change
Expand Up @@ -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])
*
Expand All @@ -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
Expand Down
30 changes: 22 additions & 8 deletions jerry-libc/arch/x86-64.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions jerry-libc/jerry-libc-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
90 changes: 90 additions & 0 deletions jerry-libc/jerry-libc-init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* 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 */
4 changes: 4 additions & 0 deletions jerry-libc/target/posix/jerry-libc-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions tools/cppcheck/suppressions-list
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
wrongmathcall:tests/unit/test-libm.inc.h
variableScope:jerry-libm/*.c
invalidPointerCast:jerry-libm/*.c
arithOperationsOnVoidPointer:jerry-libc/*.c

0 comments on commit 3a20c14

Please sign in to comment.