3347d08b79
This can happen, for example, during 'dlopen' if unresolved symbols are present. * Unload already loaded shared libraries * Delete dependencies * Flush initializer list (ctors) fixes #3073
147 lines
2.7 KiB
C++
147 lines
2.7 KiB
C++
/**
|
|
* \brief Initialization list (calls ctors)
|
|
* \author Sebastian Sumpf
|
|
* \date 2015-03-12
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2015-2017 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
*/
|
|
|
|
#ifndef _INCLUDE__INIT_H_
|
|
#define _INCLUDE__INIT_H_
|
|
|
|
#include <linker.h>
|
|
|
|
|
|
namespace Linker {
|
|
struct Init;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handle static construction and relocation of ELF files
|
|
*/
|
|
struct Linker::Init : List<Object>
|
|
{
|
|
bool in_progress = false;
|
|
bool restart = false;
|
|
|
|
static Init *list()
|
|
{
|
|
static Init _list;
|
|
return &_list;
|
|
}
|
|
|
|
bool contains_deps() const
|
|
{
|
|
for (Object const *obj = first(); obj; obj = obj->next_init()) {
|
|
if (obj->is_linker()) continue;
|
|
if (obj->is_binary()) continue;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Object *contains(char const *file)
|
|
{
|
|
for (Object *elf = first(); elf; elf = elf->next_init())
|
|
if (!strcmp(file, elf->name()))
|
|
return elf;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void reorder(Object *elf)
|
|
{
|
|
/* put in front of initializer list */
|
|
remove(elf);
|
|
insert(elf);
|
|
|
|
/* re-order dependencies */
|
|
elf->dynamic().for_each_dependency([&] (char const *path) {
|
|
|
|
// for (Dynamic::Needed *n = elf->dynamic().needed.head(); n; n = n->next()) {
|
|
// char const *path = n->path(elf->dynamic().strtab);
|
|
|
|
if (Object *e = contains(Linker::file(path)))
|
|
reorder(e);
|
|
});
|
|
}
|
|
|
|
void initialize(Bind bind, Stage stage)
|
|
{
|
|
Object *obj = first();
|
|
|
|
/* relocate */
|
|
for (; obj; obj = obj->next_init()) {
|
|
if (verbose_relocation)
|
|
log("Relocate ", obj->name());
|
|
obj->relocate(bind);
|
|
}
|
|
|
|
/*
|
|
* Recursive initialization call is not allowed here. This might happen
|
|
* when Shared_objects (e.g. dlopen and friends) are constructed from within
|
|
* global constructors (ctors).
|
|
*/
|
|
if (in_progress) {
|
|
restart = true;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* We do not call static constructors in the binary stage as this must
|
|
* be done by the component itself. Later for shared objects, the
|
|
* constructors are executed immediately.
|
|
*/
|
|
if (stage != STAGE_BINARY)
|
|
exec_static_constructors();
|
|
}
|
|
|
|
bool needs_static_construction()
|
|
{
|
|
for (Object *obj = first(); obj; obj = obj->next_init())
|
|
if (obj->needs_static_construction())
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void exec_static_constructors()
|
|
{
|
|
in_progress = true;
|
|
|
|
/* call static constructors */
|
|
Object *obj = first();
|
|
while (obj) {
|
|
|
|
Object *next = obj->next_init();
|
|
remove(obj);
|
|
|
|
obj->dynamic().call_init_function();
|
|
|
|
obj = restart ? first() : next;
|
|
restart = false;
|
|
}
|
|
|
|
in_progress = false;
|
|
}
|
|
|
|
void flush()
|
|
{
|
|
while (Object *obj = first())
|
|
remove(obj);
|
|
|
|
in_progress = false;
|
|
restart = false;
|
|
}
|
|
};
|
|
|
|
#endif /* _INCLUDE__INIT_H_ */
|