runtime_loader: Rework static initialization handling.

Previously, static initializers were just in ".ctors", which was handled
by GCC's crtbeginS, and that was injected in-between crti and crtn. Now,
however, binutils puts static initializers into init_array/fini_array by
default, which runtime_loader handles, but of course as initialize_after and
terminate_after are supposed to be called *after* all static initializers
are called; and since runtime_loader called init_array after _init, they
were not.

Now, we get rid of the __haiku_init_before/etc. functions, and move their
functionality inside runtime_loader. This is a "soft" ABI breakage,
which is mitigated by adding another ABI breakage (runtime_loader now
returns NULL for the initialize_before/etc. symbols, as otherwise
old applications would have their initialize_before/etc. called twice;
once by runtime_loader, and then once by __haiku_init_before/etc.)

I don't see or know of any reason why an application would want to
get those symbols at runtime, though, so this shouldn't have any
adverse effects.

Change-Id: I42344c63f69c6f8ef260f6c3ca30202b6dfb153e
Reviewed-on: https://review.haiku-os.org/c/907
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2019-01-26 19:47:57 -05:00 committed by waddlesplash
parent d49942867b
commit 354b60af29
17 changed files with 48 additions and 128 deletions

View File

@ -21,10 +21,8 @@
.section .init
FUNCTION(_init):
bl __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
FUNCTION(_fini):
bl __haiku_term_before
// crtbegin.o stuff comes here

View File

@ -10,10 +10,8 @@
.section .init
// the image ID and program args are still on the stack
bl __haiku_init_after
.section .fini
// the image ID and program args are still on the stack
bl __haiku_term_after

View File

@ -21,10 +21,8 @@
.section .init
FUNCTION(_init):
jsr __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
FUNCTION(_fini):
jsr __haiku_term_before
// crtbegin.o stuff comes here

View File

@ -10,10 +10,8 @@
.section .init
// the image ID and program args are still on the stack
jsr __haiku_init_after
rts
.section .fini
// the image ID and program args are still on the stack
jsr __haiku_term_after
rts

View File

@ -21,10 +21,8 @@
.section .init
FUNCTION(_init):
bl __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
FUNCTION(_fini):
bl __haiku_term_before
// crtbegin.o stuff comes here

View File

@ -10,10 +10,8 @@
.section .init
// the image ID and program args are still on the stack
bl __haiku_init_after
blr
.section .fini
// the image ID and program args are still on the stack
bl __haiku_term_after
blr

View File

@ -21,10 +21,8 @@
.section .init
FUNCTION(_init):
jal __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
FUNCTION(_fini):
jal __haiku_term_before
// crtbegin.o stuff comes here

View File

@ -10,10 +10,8 @@
.section .init
// the image ID and program args are still on the stack
jal __haiku_init_after
.section .fini
// the image ID and program args are still on the stack
jal __haiku_term_after

View File

@ -21,10 +21,8 @@
.section .init
FUNCTION(_init):
jal __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
FUNCTION(_fini):
jal __haiku_term_before
// crtbegin.o stuff comes here

View File

@ -10,10 +10,8 @@
.section .init
// the image ID and program args are still on the stack
jal __haiku_init_after
.section .fini
// the image ID and program args are still on the stack
jal __haiku_term_after

View File

@ -25,7 +25,6 @@ FUNCTION(_init):
movl %esp, %ebp
sub $4,%esp // Keep stack aligned
pushl 8(%ebp) // put image ID on the stack again
call __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
@ -34,5 +33,4 @@ FUNCTION(_fini):
movl %esp, %ebp
sub $4,%esp // Keep stack aligned
pushl 8(%ebp)
call __haiku_term_before
// crtend.o stuff comes here

View File

@ -10,14 +10,12 @@
.section .init
// the image ID is still on the stack
call __haiku_init_after
movl %ebp, %esp
popl %ebp
ret
.section .fini
// the image ID is still on the stack
call __haiku_term_after
movl %ebp, %esp
popl %ebp
ret

View File

@ -15,7 +15,6 @@
* stacked together like this:
*
* crti.S entry point
* call to _init_before/_term_before
* crtbegin.S GCC specific: constructors/destructors are called, ...
* crtend.S
* crtn.S call to _init_after/_term_after
@ -28,18 +27,18 @@ FUNCTION(_init):
push %rbp
movq %rsp, %rbp
// Preserve image ID for call to __haiku_init_after.
// Preserve image ID.
push %rdi
sub $0x8, %rsp
call __haiku_init_before
// crtbegin.o stuff comes here
.section .fini
FUNCTION(_fini):
push %rbp
movq %rsp, %rbp
push %rdi
sub $0x8, %rsp
call __haiku_term_before
// crtend.o stuff comes here

View File

@ -15,7 +15,7 @@
// The image ID is preserved on the stack.
add $0x8, %rsp
pop %rdi
call __haiku_init_after
movq %rbp, %rsp
pop %rbp
ret
@ -23,7 +23,7 @@
.section .fini
add $0x8, %rsp
pop %rdi
call __haiku_term_after
movq %rbp, %rsp
pop %rbp
ret

View File

@ -1,81 +1,6 @@
/*
* Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2019, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <user_runtime.h>
#include <image.h>
#include "init_term_dyn.h"
// include the version glue -- it's separate for the kernel add-ons only
#include "haiku_version_glue.c"
/*! These functions are called from _init()/_fini() (in crti.S, crtn.S)
__haiku_{init,term}_before() is called before crtbegin/end code is
executed, __haiku_{init,term}_after() after this. crtbegin contains
code to initialize all global constructors and other GCC related things
(like exception frames).
*/
#define HIDDEN_FUNCTION(function) asm volatile(".hidden " #function)
void
__haiku_init_before(image_id id)
{
void (*before)(image_id);
HIDDEN_FUNCTION(__haiku_init_before);
if (get_image_symbol(id, B_INIT_BEFORE_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT,
(void**)&before) == B_OK) {
before(id);
}
}
void
__haiku_init_after(image_id id)
{
void (*after)(image_id);
HIDDEN_FUNCTION(__haiku_init_after);
if (get_image_symbol(id, B_INIT_AFTER_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT,
(void**)&after) == B_OK) {
after(id);
}
}
void
__haiku_term_before(image_id id)
{
void (*before)(image_id);
HIDDEN_FUNCTION(__haiku_term_before);
if (get_image_symbol(id, B_TERM_BEFORE_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT,
(void**)&before) == B_OK) {
before(id);
}
}
void
__haiku_term_after(image_id id)
{
void (*after)(image_id);
HIDDEN_FUNCTION(__haiku_term_after);
if (get_image_symbol(id, B_TERM_AFTER_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT,
(void**)&after) == B_OK) {
after(id);
}
}

View File

@ -1,18 +0,0 @@
/*
* Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef INIT_TERM_DYN_H
#define INIT_TERM_DYN_H
#include <image.h>
void __haiku_init_before(image_id id);
void __haiku_init_after(image_id id);
void __haiku_term_before(image_id id);
void __haiku_term_after(image_id id);
#endif /* INIT_TERM_DYN_H */

View File

@ -42,6 +42,7 @@ static const char* const kLockName = "runtime loader";
typedef void (*init_term_function)(image_id);
typedef void (*initfini_array_function)();
bool gProgramLoaded = false;
image_t* gProgramImage;
@ -260,7 +261,14 @@ init_dependencies(image_t *image, bool initHead)
if (image->preinit_array) {
uint count_preinit = image->preinit_array_len / sizeof(addr_t);
for (uint j = 0; j < count_preinit; j++)
((init_term_function)image->preinit_array[j])(image->id);
((initfini_array_function)image->preinit_array[j])();
}
init_term_function before;
if (find_symbol(image,
SymbolLookupInfo(B_INIT_BEFORE_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT),
(void**)&before) == B_OK) {
before(image->id);
}
if (image->init_routine != 0)
@ -269,12 +277,19 @@ init_dependencies(image_t *image, bool initHead)
if (image->init_array) {
uint count_init = image->init_array_len / sizeof(addr_t);
for (uint j = 0; j < count_init; j++)
((init_term_function)image->init_array[j])(image->id);
((initfini_array_function)image->init_array[j])();
}
init_term_function after;
if (find_symbol(image,
SymbolLookupInfo(B_INIT_AFTER_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT),
(void**)&after) == B_OK) {
after(image->id);
}
image_event(image, IMAGE_EVENT_INITIALIZED);
}
TRACE(("%ld: init done.\n", find_thread(NULL)));
TRACE(("%ld: init done.\n", find_thread(NULL)));
free(initList);
}
@ -645,15 +660,29 @@ unload_library(void* handle, image_id imageID, bool addOn)
image_event(image, IMAGE_EVENT_UNINITIALIZING);
init_term_function before;
if (find_symbol(image,
SymbolLookupInfo(B_TERM_BEFORE_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT),
(void**)&before) == B_OK) {
before(image->id);
}
if (image->term_array) {
uint count_term = image->term_array_len / sizeof(addr_t);
for (uint i = count_term; i-- > 0;)
((init_term_function)image->term_array[i])(image->id);
((initfini_array_function)image->term_array[i])();
}
if (image->term_routine)
((init_term_function)image->term_routine)(image->id);
init_term_function after;
if (find_symbol(image,
SymbolLookupInfo(B_TERM_AFTER_FUNCTION_NAME, B_SYMBOL_TYPE_TEXT),
(void**)&after) == B_OK) {
after(image->id);
}
TLSBlockTemplates::Get().Unregister(image->dso_tls_id);
dequeue_disposable_image(image);
@ -812,6 +841,15 @@ get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
if (symbolName == NULL)
return B_BAD_VALUE;
// Previously, these functions were called in __haiku_init_before
// and __haiku_init_after. Now we call them inside runtime_loader,
// so we prevent applications from fetching them.
if (strcmp(symbolName, B_INIT_BEFORE_FUNCTION_NAME) == 0
|| strcmp(symbolName, B_INIT_AFTER_FUNCTION_NAME) == 0
|| strcmp(symbolName, B_TERM_BEFORE_FUNCTION_NAME) == 0
|| strcmp(symbolName, B_TERM_AFTER_FUNCTION_NAME) == 0)
return B_BAD_VALUE;
rld_lock();
// for now, just do stupid simple global locking