/*
This file is part of Darling.
Copyright (C) 2015 Lubos Dolezel
Darling is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Darling is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Darling. If not, see .
*/
#include "NativeObject.h"
#include
#include
#include
#include "MachOMgr.h"
#include
#include
#include
#include
namespace Darling {
static std::regex g_reObjcSymbol("(OBJC_[^\\$]+)\\$_(.+)");
static std::regex g_reObjcEhSymbol("OBJC_EHTYPE_.+");
static NativeObject* g_mainObject = nullptr;
void NativeObject::setMainObject(NativeObject* obj)
{
g_mainObject = obj;
}
NativeObject* NativeObject::mainObject()
{
return g_mainObject;
}
NativeObject::NativeObject(const std::string& path)
: m_path(path), m_name(path)
{
}
NativeObject::NativeObject(void* nativeRef, const std::string& name)
: m_nativeRef(nativeRef), m_path(name), m_name(name)
{
}
void NativeObject::load()
{
int flags = 0;
struct link_map* lm;
flags |= globalExports() ? RTLD_GLOBAL : RTLD_LOCAL;
//flags |= bindAllAtLoad() ? RTLD_NOW : RTLD_LAZY;
flags |= RTLD_LAZY;
if (MachOMgr::instance()->printLibraries())
std::cerr << "dyld: Loading " << m_path << std::endl;
m_nativeRef = ::dlopen(m_path.c_str(), flags);
if (!m_nativeRef)
{
const char* err = ::dlerror();
std::stringstream ss;
ss << "Failed to load native library: " << err;
throw std::runtime_error(ss.str());
}
else
{
updateName();
if (MachOMgr::instance()->printLibraries())
std::cerr << "dyld: Loaded " << m_path << std::endl;
MachOMgr::instance()->add(this);
}
if (::dlinfo(m_nativeRef, RTLD_DI_LINKMAP, &lm) == 0)
m_baseAddress = (void*) lm->l_addr;
transitionState(dyld_image_state_mapped);
transitionState(dyld_image_state_dependents_mapped);
transitionState(dyld_image_state_rebased);
transitionState(dyld_image_state_bound);
transitionState(dyld_image_state_dependents_initialized);
transitionState(dyld_image_state_initialized);
}
void NativeObject::unload()
{
MachOMgr::instance()->remove(this);
if (!MachOMgr::instance()->isDestroying())
{
if (m_path.find('/') != std::string::npos)
::dlclose(m_nativeRef);
}
transitionState(dyld_image_state_terminated);
}
void NativeObject::updateName()
{
struct link_map* map = nullptr;
size_t pos;
dlinfo(m_nativeRef, RTLD_DI_LINKMAP, &map);
if (map)
{
char* real = realpath(map->l_name, nullptr);
if (real)
{
m_path = real;
free(real);
}
}
pos = m_path.rfind('/');
if (pos == std::string::npos)
m_name = m_path;
else
m_name = m_path.substr(pos+1);
}
void* NativeObject::getExportedSymbol(const std::string& symbolName, bool nonWeakOnly) const
{
void* addr;
std::string name;
std::smatch match;
//if (symbolName == "main")
// return nullptr; // Don't return main() from Darling itself
name = symbolName;
if (std::regex_match(name, match, g_reObjcSymbol))
{
std::string newname;
match.format(std::back_inserter(newname), std::string("_$1$2"));
name = newname;
}
else if (std::regex_match(name, match, g_reObjcEhSymbol))
{
static long dummy = 0;
return &dummy;
}
addr = ::dlvsym(m_nativeRef, name.c_str(), "DARWIN");
// if (!addr)
// std::cerr << "Cannot find " << name << " in " << path() << std::endl;
return addr;
}
bool NativeObject::findSymbolInfo(const void* addr, Dl_info* p) const
{
return ::dladdr(addr, p) != 0;
}
const char* NativeObject::name() const
{
return m_name.c_str();
}
const std::string& NativeObject::path() const
{
return m_path;
}
void* NativeObject::baseAddress() const
{
return m_baseAddress;
}
// static int dl_cb(struct dl_phdr_info *info, void* data)
// {
// return 0;
// }
void* NativeObject::getSection(const std::string& segmentName, const std::string& sectionName, uintptr_t* sectionSize)
{
// dl_iterate_phdr(dl_cb, nullptr);
return nullptr;
}
} // namespace Darling