genode/repos/base/src/lib/ldso/shared_object.cc

122 lines
2.5 KiB
C++

/**
* \brief Implentation of Genode's shared-object interface
* \author Sebastian Sumpf
* \date 2015-03-11
*/
/*
* 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.
*/
#include <linker.h>
/*************
** Helpers **
*************/
static Linker::Root_object *to_root(void *h)
{
return static_cast<Linker::Root_object *>(h);
}
/**
* Needed during shared object creation and destruction, since global lists are
* manipulated
*/
static Genode::Lock & shared_object_lock()
{
static Genode::Lock _lock;
return _lock;
}
static Linker::Object *find_obj(Genode::addr_t addr)
{
for (Linker::Object *e = Linker::obj_list_head(); e; e = e->next_obj())
if (addr >= e->link_map()->addr && addr < e->link_map()->addr + e->size())
return e;
throw Genode::Address_info::Invalid_address();
}
/*********
** API **
*********/
Genode::Shared_object::Shared_object(char const *file, unsigned flags)
{
using namespace Linker;
if (verbose_shared)
PDBG("open '%s'", file ? file : "binary");
try {
Genode::Lock::Guard guard(shared_object_lock());
/* update bind now variable */
bind_now = (flags & Shared_object::NOW) ? true : false;
_handle = (Root_object *)new (Genode::env()->heap()) Root_object(file ? file : binary_name(), flags);
} catch (...) { throw Invalid_file(); }
}
void *Genode::Shared_object::_lookup(const char *name) const
{
using namespace Linker;
if (verbose_shared)
PDBG("lookup '%s'", name);
try {
Genode::Lock::Guard guard(Object::lock());
Elf::Addr base;
Root_object *root = to_root(_handle);
Elf::Sym const *symbol = lookup_symbol(name, root->dep.head(), &base, true);
return (void *)(base + symbol->st_value);
} catch (...) { throw Shared_object::Invalid_symbol(); }
}
Genode::Shared_object::Link_map const * Genode::Shared_object::link_map() const
{
return (Link_map const *)to_root(_handle)->link_map();
}
Genode::Shared_object::~Shared_object()
{
using namespace Linker;
if (verbose_shared)
PDBG("close");
Genode::Lock::Guard guard(shared_object_lock());
destroy(Genode::env()->heap(), to_root(_handle));
}
Genode::Address_info::Address_info(Genode::addr_t address)
{
using namespace Genode;
if (verbose_shared)
PDBG("request: %lx", address);
Linker::Object *e = find_obj(address);
e->info(address, *this);
if (verbose_shared)
PDBG("Found: obj: %s sym: %s addr: %lx", path, name, addr);
}