0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-29 08:54:02 +01:00
construct/ircd/mods_ldso.cc

132 lines
2.9 KiB
C++

// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
// This file is platform specific. It is conditionally compiled and included
// in libircd glibc+ELF supporting environments. Do not rely on these
// definitions being available on all platforms.
#include <RB_INC_DLFCN_H
#include <RB_INC_LINK_H
///////////////////////////////////////////////////////////////////////////////
//
// mods/ldso.h
//
bool
ircd::mods::ldso::for_each(const link_name_closure &closure)
{
return !for_each(link_map_closure{[&closure]
(struct link_map &map)
{
return closure(map.l_name);
}});
}
bool
ircd::mods::ldso::for_each(const link_map_closure &closure)
{
auto *map
{
reinterpret_cast<struct link_map *>(::dlopen(NULL, RTLD_NOLOAD|RTLD_LAZY))
};
if(unlikely(!map))
throw error
{
::dlerror()
};
for(; map; map = map->l_next)
if(!closure(*map))
return false;
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// Symbolic dl-error redefinition to throw our C++ exception for the symbol
// lookup failure, during the lazy binding, directly from the callsite. THIS IS
// BETTER than the default glibc/elf/dl behavior of terminating the program.
//
// We probably need asynchronous-unwind-tables for an exception to safely
// transit from here through libdl and out of a random PLT slot. non-call-
// exceptions does not appear to be necessary, at least for FUNC symbols.
//
// glibc/sysdeps/generic/ldsodefs.h
struct dl_exception
{
const char *objname;
const char *errstring;
char *message_buffer;
};
extern "C" void
_dl_exception_free(struct dl_exception *)
__attribute__ ((nonnull(1)));
extern "C" void
__attribute__((noreturn))
_dl_signal_exception(int errcode,
struct dl_exception *e,
const char *occasion)
{
const ircd::unwind free
{
std::bind(_dl_exception_free, e)
};
ircd::log::derror
{
ircd::mods::log, "dynamic linker (%d) %s in `%s' :%s",
errcode,
occasion,
e->objname,
e->errstring
};
throw ircd::mods::error
{
"%s in %s (%d) %s",
occasion,
e->objname,
errcode,
e->errstring,
};
}
///////////////////////////////////////////////////////////////////////////////
//
// symbolic dlsym hook
//
#ifdef IRCD_MODS_HOOK_DLSYM
extern "C" void *
__libc_dlsym(void *, const char *);
extern "C" void *
dlsym(void *const handle,
const char *const symbol)
{
#ifdef RB_DEBUG_MODS_HOOK_DLSYM
ircd::log::debug
{
ircd::mods::log, "handle:%p symbol lookup '%s'",
handle,
symbol
};
#endif
return __libc_dlsym(handle, symbol);
}
#endif IRCD_MODS_HOOK_DLSYM