genode/repos/base/src/lib/ldso/include/init.h

111 lines
2.0 KiB
C++

/**
* \brief Initialization list (calls ctors)
* \author Sebastian Sumpf
* \date 2015-03-12
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#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 : Genode::List<Object>
{
bool in_progress = false;
bool restart = false;
static Init *list()
{
static Init _list;
return &_list;
}
Object *contains(char const *file)
{
for (Object *elf = first(); elf; elf = elf->next_init())
if (!Genode::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 */
for (Dynamic::Needed *n = elf->dynamic()->needed.head(); n; n = n->next()) {
char const *path = n->path(elf->dynamic()->strtab);
Object *e;
if ((e = contains(Linker::file(path))))
reorder(e);
}
}
void initialize()
{
Object *obj = first();
/* relocate */
for (; obj; obj = obj->next_init()) {
if (verbose_relocation)
PDBG("Relocate %s", obj->name());
obj->relocate();
}
/*
* Recursive initialization call is not allowed here. This might happend
* when Shared_objects (e.g. dlopen and friends) are constructed from within
* global constructors (ctors).
*/
if (in_progress) {
restart = true;
return;
}
in_progress = true;
/* call static constructors */
obj = first();
while (obj) {
Object *next = obj->next_init();
remove(obj);
if (obj->dynamic()->init_function) {
if (verbose_relocation)
PDBG("%s init func %p", obj->name(), obj->dynamic()->init_function);
obj->dynamic()->init_function();
}
obj = restart ? first() : next;
restart = false;
}
in_progress = false;
}
};
#endif /* _INCLUDE__INIT_H_ */