122 lines
2.5 KiB
C++
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);
|
|
}
|
|
|
|
|