mirror of
https://github.com/darlinghq/darling.git
synced 2024-11-26 22:00:29 +00:00
Loads of work on dyld and BSD functions
This commit is contained in:
parent
6a563706cd
commit
45a369fdf9
2
.gdbinit
2
.gdbinit
@ -27,7 +27,7 @@
|
||||
|
||||
set follow-fork-mode child
|
||||
|
||||
python sys.path.insert(0, '.')
|
||||
python sys.path.insert(0, './tools/')
|
||||
python import gdb_maloader
|
||||
|
||||
define mreload
|
||||
|
@ -53,7 +53,7 @@ set(fatmacho-extract_SRCS
|
||||
|
||||
add_executable(fatmacho-extract ${fatmacho-extract_SRCS})
|
||||
|
||||
target_link_libraries(fatmacho-extract -ldl -lpthread mach-o)
|
||||
target_link_libraries(fatmacho-extract -ldl -lpthread mach-o -Wl,-export-dynamic)
|
||||
|
||||
install(TARGETS dyld fatmacho-extract DESTINATION bin)
|
||||
|
||||
|
@ -165,8 +165,13 @@ void MachOLoader::loadDylibs(const MachO& mach)
|
||||
// __darwin_dlopen checks if already loaded
|
||||
// automatically adds a reference if so
|
||||
|
||||
if (!__darwin_dlopen(dylib.c_str(), DARWIN_RTLD_GLOBAL))
|
||||
throw std::runtime_error("Cannot load " + dylib + "!");
|
||||
if (!__darwin_dlopen(dylib.c_str(), DARWIN_RTLD_GLOBAL|DARWIN_RTLD_NOW))
|
||||
{
|
||||
LOG << "Failed to dlopen " << dylib << ", throwing an exception\n";
|
||||
std::stringstream ss;
|
||||
ss << "Cannot load " << dylib << ": " << __darwin_dlerror();
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,12 +385,21 @@ void MachOLoader::doBind(const MachO& mach, intptr slide)
|
||||
sym = reinterpret_cast<char*>(__darwin_dlsym(DARWIN_RTLD_DEFAULT, name.c_str()));
|
||||
if (!sym)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Undefined symbol: " << name;
|
||||
throw std::runtime_error(ss.str());
|
||||
const char* ign_sym = getenv("DYLD_IGN_MISSING_SYMS");
|
||||
if (ign_sym && atoi(ign_sym))
|
||||
{
|
||||
std::cerr << "!!! Undefined symbol: " << name << std::endl;
|
||||
sym = reinterpret_cast<char*>(undefinedFunction);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Undefined symbol: " << name;
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
sym += bind->addend;
|
||||
else
|
||||
sym += bind->addend;
|
||||
}
|
||||
|
||||
LOG << "bind " << name << ": "
|
||||
|
@ -1,25 +1,35 @@
|
||||
#include "MachO.h"
|
||||
#include "MachOLoader.h"
|
||||
#include "arch.h"
|
||||
#include "log.h"
|
||||
#include <iostream>
|
||||
#include <limits.h>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
char g_darwin_executable_path[PATH_MAX];
|
||||
char g_loader_path[PATH_MAX];
|
||||
char g_sysroot[PATH_MAX] = "";
|
||||
|
||||
MachO* g_mainBinary = 0;
|
||||
MachOLoader* g_loader = 0;
|
||||
int g_argc;
|
||||
char** g_argv;
|
||||
|
||||
static void autoSysrootSearch();
|
||||
|
||||
int main(int argc, char** argv, char** envp)
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
std::cerr << "This is Darwin dyld for " ARCH_NAME ". ";
|
||||
std::cerr << "Usage: " << argv[0] << " program-path [arguments...]\n";
|
||||
std::cerr << "Usage: " << argv[0] << " program-path [arguments...]\n\n";
|
||||
std::cerr << "Environment variables:\n"
|
||||
"\tDYLD_DEBUG=1 - enable debug info (lots of output)\n"
|
||||
"\tDYLD_IGN_MISSING_SYMS=1 - replace missing symbol references with a stub function\n"
|
||||
"\tDYLD_SYSROOT=<path> - set the base for library path resolution (overrides autodetection)\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -35,25 +45,30 @@ int main(int argc, char** argv, char** envp)
|
||||
//initDlfcn();
|
||||
|
||||
g_mainBinary = MachO::readFile(argv[1], ARCH_NAME);
|
||||
#ifdef __x86_64__
|
||||
if (!g_mainBinary->is64())
|
||||
{
|
||||
std::cerr << argv[1] << ": Cannot execute binary file.\nThis version of Darwin dyld cannot run binaries for x86.\n";
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#else
|
||||
if (g_mainBinary->is64())
|
||||
{
|
||||
td::cerr << argv[1] << ": Cannot execute binary file.\nThis version of Darwin dyld cannot run binaries for x86-64.\n";
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
if (!g_mainBinary)
|
||||
throw std::runtime_error("Cannot open binary file");
|
||||
#ifdef __x86_64__
|
||||
if (!g_mainBinary->is64())
|
||||
{
|
||||
std::cerr << argv[1] << ": Cannot execute binary file.\nThis version of Darwin dyld cannot run binaries for x86.\n";
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#else
|
||||
if (g_mainBinary->is64())
|
||||
{
|
||||
std::cerr << argv[1] << ": Cannot execute binary file.\nThis version of Darwin dyld cannot run binaries for x86-64.\n";
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_loader = new MachOLoader;
|
||||
g_argv = argv+1;
|
||||
g_argc = argc-1;
|
||||
|
||||
autoSysrootSearch();
|
||||
|
||||
g_loader->run(*g_mainBinary, argc-1, argv+1, envp);
|
||||
|
||||
delete g_loader;
|
||||
@ -77,4 +92,27 @@ extern "C" const char* dyld_getLoaderPath()
|
||||
return g_loader_path;
|
||||
}
|
||||
|
||||
void autoSysrootSearch()
|
||||
{
|
||||
if (const char* s = getenv("DYLD_SYSROOT"))
|
||||
{
|
||||
strncpy(g_sysroot, s, PATH_MAX-1);
|
||||
g_sysroot[PATH_MAX-1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = g_darwin_executable_path;
|
||||
size_t pos = path.rfind("/usr/");
|
||||
|
||||
LOG << "Looking for SYSROOT signs in " << g_darwin_executable_path << std::endl;
|
||||
|
||||
if (pos != std::string::npos && pos > 0)
|
||||
{
|
||||
std::string sysroot = path.substr(0, pos);
|
||||
LOG << "SYSROOT detected to be " << sysroot << std::endl;
|
||||
strncpy(g_sysroot, sysroot.c_str(), PATH_MAX-1);
|
||||
g_sysroot[PATH_MAX-1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,470 +0,0 @@
|
||||
// Copyright 2011 Shinichiro Hamaji. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY Shinichiro Hamaji ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Shinichiro Hamaji OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
// SUCH DAMAGE.
|
||||
|
||||
// A Mach-O loader for linux.
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <execinfo.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <time.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <tr1/unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "env_flags.h"
|
||||
#include "FatMachO.h"
|
||||
#include "log.h"
|
||||
#include "MachO.h"
|
||||
#include "FileMap.h"
|
||||
#include "arch.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace std::tr1;
|
||||
|
||||
DEFINE_bool(TRACE_FUNCTIONS, false, "Show calling functions");
|
||||
DEFINE_bool(PRINT_TIME, false, "Print time spent in this loader");
|
||||
|
||||
class MachO;
|
||||
|
||||
static map<string, string> g_rename;
|
||||
static vector<string> g_bound_names;
|
||||
static set<string> g_no_trampoline;
|
||||
|
||||
static FileMap g_file_map;
|
||||
|
||||
static char* g_darwin_executable_path;
|
||||
|
||||
static Timer g_timer;
|
||||
|
||||
class MachOLoader;
|
||||
static MachOLoader* g_loader;
|
||||
|
||||
/*
|
||||
static void initRename() {
|
||||
#define RENAME(src, dst) g_rename.insert(make_pair(#src, #dst));
|
||||
#define WRAP(src) RENAME(src, __darwin_ ## src)
|
||||
#include "rename.tab"
|
||||
#undef RENAME
|
||||
#undef WRAP
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class MachOLoader {
|
||||
#ifdef __x86_64__
|
||||
typedef uint64_t intptr;
|
||||
typedef segment_command_64 Segment;
|
||||
|
||||
static const vector<Segment*>& getSegments(const MachO& mach) {
|
||||
return mach.segments64();
|
||||
}
|
||||
#else
|
||||
typedef uint32_t intptr;
|
||||
typedef segment_command Segment;
|
||||
|
||||
static const vector<Segment*>& getSegments(const MachO& mach) {
|
||||
return mach.segments();
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
MachOLoader()
|
||||
: last_addr_(0) {
|
||||
// TODO: this is very wrong
|
||||
/*
|
||||
dylib_to_so_.insert(make_pair(
|
||||
"/System/Library/Frameworks/CoreFoundation.framework"
|
||||
"/Versions/A/CoreFoundation",
|
||||
"libCoreFoundation.so"));
|
||||
dylib_to_so_.insert(make_pair(
|
||||
"/usr/lib/libncurses.5.4.dylib",
|
||||
"libncurses.so"));
|
||||
|
||||
symbol_to_so_.insert(make_pair("uuid_clear", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_compare", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_copy", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_generate", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_generate_random", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_generate_time", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_is_null", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_pack", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_parse", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_unpack", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_unparse", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_unparse_lower", "libuuid.so"));
|
||||
symbol_to_so_.insert(make_pair("uuid_unparse_upper", "libuuid.so"));
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void run(MachO& mach, int argc, char** argv, char** envp) {
|
||||
// I don't understand what it is.
|
||||
char* apple[2];
|
||||
apple[0] = argv[0];
|
||||
apple[1] = NULL;
|
||||
|
||||
load(mach);
|
||||
setupDyldData(mach);
|
||||
|
||||
g_file_map.addWatchDog(last_addr_ + 1);
|
||||
|
||||
char* trampoline_start_addr =
|
||||
(char*)(((uintptr_t)&trampoline_[0]) & ~0xfff);
|
||||
uint64_t trampoline_size =
|
||||
alignMem(&trampoline_[0] + trampoline_.size() - trampoline_start_addr,
|
||||
0x1000);
|
||||
mprotect(trampoline_start_addr, trampoline_size,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
g_timer.print(mach.filename().c_str());
|
||||
|
||||
mach.close();
|
||||
|
||||
runInitFuncs(argc, argv, envp, apple);
|
||||
|
||||
LOG << "booting from " << (void*)mach.entry() << "..." << endl;
|
||||
fflush(stdout);
|
||||
CHECK(argc > 0);
|
||||
boot(mach.entry(), argc, argv, envp);
|
||||
/*
|
||||
int (*fp)(int, char**, char**) =
|
||||
(int(*)(int, char**, char**))mach.entry();
|
||||
int ret = fp(argc, argv, envp);
|
||||
exit(ret);
|
||||
*/
|
||||
}
|
||||
|
||||
private:
|
||||
void boot(uint64_t entry, int argc, char** argv, char** envp);
|
||||
|
||||
void pushTrampolineCode(unsigned int c) {
|
||||
while (c) {
|
||||
trampoline_.push_back(c & 255);
|
||||
c = c >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void pushTrampolineCode64(unsigned long long c) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
trampoline_.push_back(c & 255);
|
||||
c = c >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void pushTrampolineCode32(unsigned int c) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
trampoline_.push_back(c & 255);
|
||||
c = c >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
string trampoline_;
|
||||
intptr last_addr_;
|
||||
vector<uint64_t> init_funcs_;
|
||||
Exports exports_;
|
||||
vector<pair<string, char*> > seen_weak_binds_;
|
||||
map<string, string> dylib_to_so_;
|
||||
map<string, string> symbol_to_so_;
|
||||
set<string> loaded_dylibs_;
|
||||
};
|
||||
|
||||
void MachOLoader::boot(
|
||||
uint64_t entry, int argc, char** argv, char** envp) {
|
||||
#ifdef __x86_64__
|
||||
// 0x08: argc
|
||||
// 0x10: argv[0]
|
||||
// 0x18: argv[1]
|
||||
// ...: argv[n]
|
||||
// 0
|
||||
// envp[0]
|
||||
// envp[1]
|
||||
// envp[n]
|
||||
|
||||
// TODO: add 'apple'!
|
||||
|
||||
__asm__ volatile(" mov %1, %%rax;\n"
|
||||
" mov %2, %%rdx;\n"
|
||||
" push $0;\n"
|
||||
// TODO(hamaji): envp
|
||||
" push $0;\n"
|
||||
".loop64:\n"
|
||||
" sub $8, %%rdx;\n"
|
||||
" push (%%rdx);\n"
|
||||
" dec %%eax;\n"
|
||||
" jnz .loop64;\n"
|
||||
" mov %1, %%eax;\n"
|
||||
" push %%rax;\n"
|
||||
" jmp *%0;\n"
|
||||
::"r"(entry), "r"(argc), "r"(argv + argc), "r"(envp)
|
||||
:"%rax", "%rdx");
|
||||
//fprintf(stderr, "done!\n");
|
||||
#else
|
||||
__asm__ volatile(" mov %1, %%eax;\n"
|
||||
" mov %2, %%edx;\n"
|
||||
" push $0;\n"
|
||||
".loop32:\n"
|
||||
" sub $4, %%edx;\n"
|
||||
" push (%%edx);\n"
|
||||
" dec %%eax;\n"
|
||||
" jnz .loop32;\n"
|
||||
" mov %1, %%eax;\n"
|
||||
" push %%eax;\n"
|
||||
" jmp *%0;\n"
|
||||
// TODO(hamaji): Fix parameters
|
||||
::"r"(entry), "r"(argc), "r"(argv + argc), "g"(envp)
|
||||
:"%eax", "%edx");
|
||||
#endif
|
||||
}
|
||||
|
||||
void runMachO(MachO& mach, int argc, char** argv, char** envp) {
|
||||
MachOLoader loader;
|
||||
g_loader = &loader;
|
||||
loader.run(mach, argc, argv, envp);
|
||||
g_loader = NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int getBacktrace(void** trace, int max_depth) {
|
||||
typedef struct frame {
|
||||
struct frame *bp;
|
||||
void *ret;
|
||||
} frame;
|
||||
|
||||
int depth;
|
||||
frame* bp = (frame*)__builtin_frame_address(0);
|
||||
for (depth = 0; bp && depth < max_depth; depth++) {
|
||||
trace[depth] = bp->ret;
|
||||
bp = bp->bp;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
const char* dumpSymbol(void* p) {
|
||||
return g_file_map.dumpSymbol(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* signal handler for fatal errors */
|
||||
static void handleSignal(int signum, siginfo_t* siginfo, void* vuc) {
|
||||
ucontext_t *uc = (ucontext_t*)vuc;
|
||||
void* pc = (void*)uc->uc_mcontext.gregs[
|
||||
#ifdef __x86_64__
|
||||
REG_RIP
|
||||
#else
|
||||
REG_EIP
|
||||
#endif
|
||||
];
|
||||
|
||||
fprintf(stderr, "%s(%d) %d (@%p) PC: %p\n\n",
|
||||
strsignal(signum), signum, siginfo->si_code, siginfo->si_addr, pc);
|
||||
|
||||
void* trace[100];
|
||||
int len = backtrace(trace, 99);
|
||||
//int len = getBacktrace(trace, 99);
|
||||
char** syms = backtrace_symbols(trace, len);
|
||||
for (int i = len - 1; i > 0; i--) {
|
||||
if (syms[i] && syms[i][0] != '[') {
|
||||
fprintf(stderr, "%s\n", syms[i]);
|
||||
} else {
|
||||
const char* s = dumpSymbol(trace[i]);
|
||||
if (s) {
|
||||
fprintf(stderr, "%s\n", s);
|
||||
} else {
|
||||
fprintf(stderr, "%p\n", trace[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate a stack backtrace when a CPU exception occurs. */
|
||||
static void initSignalHandler() {
|
||||
struct sigaction sigact;
|
||||
sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
|
||||
sigact.sa_sigaction = handleSignal;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigaction(SIGFPE, &sigact, NULL);
|
||||
sigaction(SIGILL, &sigact, NULL);
|
||||
sigaction(SIGSEGV, &sigact, NULL);
|
||||
sigaction(SIGBUS, &sigact, NULL);
|
||||
sigaction(SIGABRT, &sigact, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
static bool loadLibMac(const char* mypath) {
|
||||
if (dlopen("libmac.so", RTLD_LAZY | RTLD_GLOBAL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char buf[PATH_MAX + 100];
|
||||
strcpy(buf, mypath);
|
||||
char* p = strrchr(buf, '/');
|
||||
if (!p) {
|
||||
fprintf(stderr, "Weird loader path: %s\n", mypath);
|
||||
exit(1);
|
||||
}
|
||||
strcpy(p, "/libmac.so");
|
||||
|
||||
if (dlopen(buf, RTLD_LAZY | RTLD_GLOBAL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
sprintf(p, "/libmac%d.so", BITS);
|
||||
if (dlopen(buf, RTLD_LAZY | RTLD_GLOBAL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static void initLibMac() {
|
||||
char mypath[PATH_MAX + 1];
|
||||
ssize_t l = readlink("/proc/self/exe", mypath, PATH_MAX);
|
||||
if (l < 0) {
|
||||
err(1, "readlink for /proc/self/exe");
|
||||
}
|
||||
mypath[l] = '\0';
|
||||
|
||||
if (!loadLibMac(mypath)) {
|
||||
fprintf(stderr, "libmac not found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int* LIBMAC_LOG = (int*)dlsym(RTLD_DEFAULT, "LIBMAC_LOG");
|
||||
if (LIBMAC_LOG) {
|
||||
*LIBMAC_LOG = FLAGS_LOG;
|
||||
}
|
||||
|
||||
char* loader_path = (char*)dlsym(RTLD_DEFAULT, "__loader_path");
|
||||
if (!loader_path) {
|
||||
fprintf(stderr, "wrong libmac: __loader_path not found\n");
|
||||
exit(1);
|
||||
}
|
||||
strcpy(loader_path, mypath);
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: OMG
|
||||
static string ld_mac_dlerror_buf;
|
||||
static bool ld_mac_dlerror_is_set;
|
||||
|
||||
// TODO: broken - should support multiple loads and native libs
|
||||
void* __darwin_dlopen(const char* filename, int flag) {
|
||||
LOG << "ld_mac_dlopen: " << filename << " " << flag << endl;
|
||||
|
||||
// TODO: should return main executable on filename == NULL
|
||||
Timer timer;
|
||||
timer.start();
|
||||
|
||||
// TODO(hamaji): Handle failures.
|
||||
auto_ptr<MachO> dylib_mach(loadDylib(filename));
|
||||
|
||||
MachOLoader* loader = g_loader;
|
||||
CHECK(loader);
|
||||
Exports* exports = new Exports();
|
||||
loader->load(*dylib_mach, exports);
|
||||
|
||||
timer.print(filename);
|
||||
|
||||
loader->runInitFuncs(-1, NULL, NULL, NULL);
|
||||
return exports;
|
||||
}
|
||||
|
||||
// TODO: broken - should decrease the reference count
|
||||
static int __darwin_dlclose(void* handle) {
|
||||
LOG << "ld_mac_dlclose" << endl;
|
||||
|
||||
delete (Exports*)handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* __darwin_dlerror(void) {
|
||||
LOG << "ld_mac_dlerror" << endl;
|
||||
|
||||
if (!ld_mac_dlerror_is_set)
|
||||
return NULL;
|
||||
ld_mac_dlerror_is_set = false;
|
||||
return ld_mac_dlerror_buf.c_str();
|
||||
}
|
||||
|
||||
static void* __darwin_dlsym(void* handle, const char* symbol) {
|
||||
LOG << "ld_mac_dlsym: " << symbol << endl;
|
||||
|
||||
// TODO: support RTLD_DEFAULT
|
||||
|
||||
Exports* exports = (Exports*)handle;
|
||||
Exports::const_iterator found = exports->find(string("_") + symbol);
|
||||
if (found == exports->end()) {
|
||||
ld_mac_dlerror_is_set = true;
|
||||
ld_mac_dlerror_buf = string("undefined symbol: ") + symbol;
|
||||
return NULL;
|
||||
}
|
||||
return (void*)found->second.addr;
|
||||
}
|
||||
|
||||
/*
|
||||
void initDlfcn() {
|
||||
#define SET_DLFCN_FUNC(f) \
|
||||
do { \
|
||||
void** p = (void**)dlsym(RTLD_DEFAULT, "ld_mac_" #f); \
|
||||
*p = (void*)&ld_mac_ ## f; \
|
||||
} while (0)
|
||||
|
||||
SET_DLFCN_FUNC(dlopen);
|
||||
SET_DLFCN_FUNC(dlclose);
|
||||
SET_DLFCN_FUNC(dlerror);
|
||||
SET_DLFCN_FUNC(dlsym);
|
||||
}
|
||||
*/
|
127
src/dyld/ld.cpp
127
src/dyld/ld.cpp
@ -15,10 +15,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#include <regex.h>
|
||||
#include <cassert>
|
||||
|
||||
static Darling::Mutex g_ldMutex;
|
||||
static std::map<std::string, LoadedLibrary*> g_ldLibraries;
|
||||
static __thread char g_ldError[256] = "";
|
||||
static regex_t g_reAutoMappable;
|
||||
static LoadedLibrary g_dummyLibrary;
|
||||
|
||||
extern char g_darwin_executable_path[PATH_MAX];
|
||||
|
||||
@ -27,17 +31,33 @@ static const char* g_searchPath[] = {
|
||||
LIB_PATH, "/usr/lib", "/usr/local/lib"
|
||||
};
|
||||
|
||||
static const char* g_suffixes[] = { "$DARWIN_EXTSN", "$UNIX2003", "$NOCANCEL" };
|
||||
|
||||
static void* attemptDlopen(const char* filename, int flag);
|
||||
static int translateFlags(int flags);
|
||||
__attribute__((constructor)) static void initLD();
|
||||
|
||||
extern MachOLoader* g_loader;
|
||||
extern char g_darwin_executable_path[PATH_MAX];
|
||||
extern char g_sysroot[PATH_MAX];
|
||||
extern int g_argc;
|
||||
extern char** g_argv;
|
||||
extern FileMap g_file_map;
|
||||
|
||||
#define RET_IF(x) { if (void* p = x) return p; }
|
||||
|
||||
static void initLD()
|
||||
{
|
||||
int rv = regcomp(&g_reAutoMappable, "/(lib[[:alnum:]\\-]+)\\.([[:digit:]]+)(\\.[[:digit:]]+)?\\.dylib", REG_EXTENDED);
|
||||
assert(rv == 0);
|
||||
|
||||
g_dummyLibrary.name = "/dev/null";
|
||||
g_dummyLibrary.refCount = 1;
|
||||
g_dummyLibrary.type = LoadedLibraryDummy;
|
||||
g_dummyLibrary.nativeRef = 0;
|
||||
g_dummyLibrary.exports = 0;
|
||||
}
|
||||
|
||||
void* __darwin_dlopen(const char* filename, int flag)
|
||||
{
|
||||
TRACE2(filename, flag);
|
||||
@ -58,6 +78,18 @@ void* __darwin_dlopen(const char* filename, int flag)
|
||||
start_search:
|
||||
if (*filename == '/')
|
||||
{
|
||||
if (g_sysroot[0])
|
||||
{
|
||||
path = g_sysroot + std::string(filename) + ".so";
|
||||
LOG << "Trying " << path << std::endl;
|
||||
if (::access(path.c_str(), R_OK) == 0)
|
||||
RET_IF( attemptDlopen(path.c_str(), flag) );
|
||||
|
||||
path = std::string(g_sysroot) + filename;
|
||||
if (::access(path.c_str(), R_OK) == 0)
|
||||
RET_IF( attemptDlopen(path.c_str(), flag) );
|
||||
}
|
||||
|
||||
path = std::string(filename) + ".so";
|
||||
LOG << "Trying " << path << std::endl;
|
||||
if (::access(path.c_str(), R_OK) == 0)
|
||||
@ -74,6 +106,34 @@ start_search:
|
||||
if (::access(path.c_str(), R_OK) == 0)
|
||||
RET_IF( attemptDlopen(path.c_str(), flag) );
|
||||
|
||||
regmatch_t matches[3];
|
||||
if (regexec(&g_reAutoMappable, filename, 3, matches, 0) == 0)
|
||||
{
|
||||
path = std::string(filename, matches[0].rm_so+1);
|
||||
path += std::string(filename + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
|
||||
path += ".so.";
|
||||
path += std::string(filename + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
|
||||
|
||||
if (::access(path.c_str(), R_OK) == 0)
|
||||
{
|
||||
LOG << "Warning: Automatically mapping " << filename << " to " << path << std::endl;
|
||||
RET_IF( attemptDlopen(path.c_str(), flag) );
|
||||
}
|
||||
|
||||
//path = std::string(filename, matches[0].rm_so+1);
|
||||
path = std::string(filename + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
|
||||
path += ".so.";
|
||||
path += std::string(filename + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
|
||||
|
||||
LOG << path << std::endl;
|
||||
|
||||
//if (::access(path.c_str(), R_OK) == 0)
|
||||
//{
|
||||
LOG << "Warning: Trying to remap " << filename << " to " << path << std::endl;
|
||||
RET_IF( attemptDlopen(path.c_str(), flag) );
|
||||
//}
|
||||
}
|
||||
|
||||
if (strcmp(INSTALL_PREFIX, "/usr") != 0)
|
||||
{
|
||||
// We need to change the prefix in filename if present
|
||||
@ -123,7 +183,8 @@ start_search:
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(g_ldError, "File not found");
|
||||
if (!g_ldError[0])
|
||||
snprintf(g_ldError, sizeof(g_ldError)-1, "File not found: %s", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -148,7 +209,7 @@ static int translateFlags(int flag)
|
||||
static bool isSymlink(const char* path)
|
||||
{
|
||||
struct stat st;
|
||||
if (::stat(path, &st) == -1)
|
||||
if (::lstat(path, &st) == -1)
|
||||
return false;
|
||||
return S_ISLNK(st.st_mode);
|
||||
}
|
||||
@ -159,14 +220,26 @@ void* attemptDlopen(const char* filename, int flag)
|
||||
|
||||
TRACE2(filename,flag);
|
||||
|
||||
strcpy(name, filename);
|
||||
|
||||
// Resolve symlinks so that we don't load the same library multiple times
|
||||
if (isSymlink(filename) && ::readlink(filename, name, sizeof name) == -1)
|
||||
if (isSymlink(filename))
|
||||
{
|
||||
LOG << "Invalid symlink found: " << filename << std::endl;
|
||||
return 0;
|
||||
ssize_t len = ::readlink(filename, name, sizeof name);
|
||||
if (len == -1)
|
||||
{
|
||||
LOG << "Invalid symlink found: " << filename << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
name[len] = 0;
|
||||
}
|
||||
|
||||
if (strcmp(name, "/dev/null") == 0)
|
||||
{
|
||||
// We return a dummy
|
||||
return &g_dummyLibrary;
|
||||
}
|
||||
else
|
||||
strcpy(name, filename);
|
||||
|
||||
std::map<std::string,LoadedLibrary*>::iterator it = g_ldLibraries.find(name);
|
||||
if (it != g_ldLibraries.end())
|
||||
@ -191,9 +264,11 @@ void* attemptDlopen(const char* filename, int flag)
|
||||
LOG << "Loading a native library " << name << std::endl;
|
||||
// We're loading a native library
|
||||
// TODO: flags
|
||||
void* d = ::dlopen(name, RTLD_NOW);
|
||||
void* d = ::dlopen(name, RTLD_NOW|RTLD_GLOBAL);
|
||||
if (d != 0)
|
||||
{
|
||||
LOG << "Native library loaded\n";
|
||||
|
||||
LoadedLibrary* lib = new LoadedLibrary;
|
||||
lib->name = name;
|
||||
lib->refCount = 1;
|
||||
@ -206,13 +281,20 @@ void* attemptDlopen(const char* filename, int flag)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG << "Library failed to load: " << ::dlerror() << std::endl;
|
||||
strcpy(g_ldError, ::dlerror());
|
||||
LOG << "Native library failed to load\n";
|
||||
|
||||
const char* err;
|
||||
if ((err = ::dlerror()) && !g_ldError[0]) // we don't overwrite previous errors
|
||||
{
|
||||
LOG << "Library failed to load: " << err << std::endl;
|
||||
strcpy(g_ldError, err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG << "Loading a Mach-O library\n";
|
||||
// We're loading a Mach-O library
|
||||
try
|
||||
{
|
||||
@ -299,6 +381,22 @@ const char* __darwin_dlerror(void)
|
||||
return g_ldError[0] ? g_ldError : 0;
|
||||
}
|
||||
|
||||
static const char* translateSymbol(const char* symbol)
|
||||
{
|
||||
std::string s = symbol;
|
||||
static char symbuffer[255];
|
||||
|
||||
for (int i = 0; i < sizeof(g_suffixes) / sizeof(g_suffixes[0]); i++)
|
||||
{
|
||||
size_t pos = s.find(g_suffixes[i]);
|
||||
if (pos != std::string::npos)
|
||||
s.erase(pos, strlen(g_suffixes[i]));
|
||||
}
|
||||
|
||||
strcpy(symbuffer, s.c_str());
|
||||
return symbuffer;
|
||||
}
|
||||
|
||||
void* __darwin_dlsym(void* handle, const char* symbol)
|
||||
{
|
||||
TRACE2(handle, symbol);
|
||||
@ -306,6 +404,8 @@ void* __darwin_dlsym(void* handle, const char* symbol)
|
||||
Darling::MutexLock l(g_ldMutex);
|
||||
g_ldError[0] = 0;
|
||||
|
||||
symbol = translateSymbol(symbol);
|
||||
|
||||
if (handle == DARWIN_RTLD_NEXT || handle == DARWIN_RTLD_SELF || handle == DARWIN_RTLD_MAIN_ONLY || !handle)
|
||||
{
|
||||
LOG << "Cannot yet handle certain DARWIN_RTLD_* search strategies, falling back to RTLD_DEFAULT\n";
|
||||
@ -317,7 +417,7 @@ handling:
|
||||
{
|
||||
// First try native with the __darwin prefix
|
||||
void* sym;
|
||||
char* buf = reinterpret_cast<char*>(malloc(strlen(symbol+20)));
|
||||
char* buf = reinterpret_cast<char*>(malloc(strlen(symbol)+20));
|
||||
strcpy(buf, "__darwin_");
|
||||
strcat(buf, symbol);
|
||||
|
||||
@ -358,6 +458,11 @@ handling:
|
||||
strcpy(g_ldError, ::dlerror());
|
||||
return rv;
|
||||
}
|
||||
else if (lib->type == LoadedLibraryDummy)
|
||||
{
|
||||
snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol);
|
||||
return 0;
|
||||
}
|
||||
else if (!lib->exports)
|
||||
{
|
||||
// TODO: this isn't 100% correct
|
||||
|
@ -28,7 +28,7 @@ int __darwin_dladdr(void *addr, Dl_info *info);
|
||||
|
||||
}
|
||||
|
||||
enum LoadedLibraryType { LoadedLibraryDylib, LoadedLibraryNative };
|
||||
enum LoadedLibraryType { LoadedLibraryDylib, LoadedLibraryNative, LoadedLibraryDummy };
|
||||
|
||||
typedef std::unordered_map<std::string, MachO::Export> Exports;
|
||||
|
||||
|
@ -1,155 +0,0 @@
|
||||
// Copyright 2011 Shinichiro Hamaji. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials
|
||||
// provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY Shinichiro Hamaji ``AS IS'' AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Shinichiro Hamaji OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
// SUCH DAMAGE.
|
||||
|
||||
// A translation table from Mac symbols to Linux's.
|
||||
|
||||
RENAME(__stderrp, __darwin_stderr)
|
||||
RENAME(__stdoutp, __darwin_stdout)
|
||||
RENAME(__stdinp, __darwin_stdin)
|
||||
WRAP(stderr)
|
||||
WRAP(stdout)
|
||||
WRAP(stdin)
|
||||
|
||||
WRAP(fopen)
|
||||
WRAP(fdopen)
|
||||
WRAP(freopen)
|
||||
WRAP(fclose)
|
||||
WRAP(fread)
|
||||
WRAP(fwrite)
|
||||
WRAP(fseek)
|
||||
WRAP(ftell)
|
||||
WRAP(rewind)
|
||||
WRAP(getc)
|
||||
WRAP(fgetc)
|
||||
WRAP(ungetc)
|
||||
WRAP(fgets)
|
||||
WRAP(putc)
|
||||
WRAP(fputc)
|
||||
WRAP(fputs)
|
||||
WRAP(fscanf)
|
||||
WRAP(vfscanf)
|
||||
WRAP(fprintf)
|
||||
WRAP(vfprintf)
|
||||
WRAP(fflush)
|
||||
WRAP(setbuf)
|
||||
WRAP(setbuffer)
|
||||
WRAP(ferror)
|
||||
RENAME(_ferror, __darwin_ferror)
|
||||
WRAP(fileno)
|
||||
WRAP(tmpfile)
|
||||
|
||||
RENAME(__srget, __darwin_fgetc)
|
||||
RENAME(__swbuf, __darwin_fputc)
|
||||
|
||||
RENAME(__toupper, toupper)
|
||||
RENAME(__tolower, tolower)
|
||||
|
||||
RENAME(opendir$INODE64, opendir)
|
||||
RENAME(readdir$INODE64, __darwin_readdir64)
|
||||
WRAP(readdir)
|
||||
|
||||
WRAP(stat)
|
||||
WRAP(fstat)
|
||||
WRAP(lstat)
|
||||
RENAME(stat$INODE64, __darwin_stat64)
|
||||
RENAME(fstat$INODE64, __darwin_fstat64)
|
||||
RENAME(lstat$INODE64, __darwin_lstat64)
|
||||
|
||||
WRAP(open)
|
||||
|
||||
WRAP(mmap)
|
||||
WRAP(sysctl)
|
||||
|
||||
RENAME(realpath$DARWIN_EXTSN, realpath)
|
||||
|
||||
WRAP(execv)
|
||||
WRAP(execvp)
|
||||
WRAP(execl)
|
||||
WRAP(execlp)
|
||||
WRAP(execve)
|
||||
WRAP(execle)
|
||||
WRAP(posix_spawn)
|
||||
WRAP(posix_spawnp)
|
||||
|
||||
WRAP(posix_spawn_file_actions_init)
|
||||
WRAP(posix_spawn_file_actions_destroy)
|
||||
WRAP(posix_spawn_file_actions_addopen)
|
||||
WRAP(posix_spawn_file_actions_addclose)
|
||||
WRAP(posix_spawn_file_actions_adddup2)
|
||||
|
||||
RENAME(CC_MD5_Init, MD5_Init)
|
||||
RENAME(CC_MD5_Update, MD5_Update)
|
||||
RENAME(CC_MD5_Final, MD5_Final)
|
||||
RENAME(CC_MD5, MD5)
|
||||
|
||||
WRAP(__cxa_throw)
|
||||
|
||||
RENAME(atexit, __cxa_atexit)
|
||||
|
||||
WRAP(signal)
|
||||
WRAP(sigaction)
|
||||
WRAP(sigaltstack)
|
||||
|
||||
#ifdef __x86_64__
|
||||
RENAME(__ashldi3, __ashlti3)
|
||||
RENAME(__ashrdi3, __ashrti3)
|
||||
RENAME(__cmpdi2, __cmpti2)
|
||||
RENAME(__divdi3, __divti3)
|
||||
RENAME(__fixdfdi, __fixdfti)
|
||||
RENAME(__fixsfdi, __fixsfti)
|
||||
RENAME(__floatdidf, __floattidf)
|
||||
RENAME(__floatdisf, __floattisf)
|
||||
RENAME(__lshrdi3, __lshrti3)
|
||||
RENAME(__moddi3, __modti3)
|
||||
RENAME(__udivdi3, __udivti3)
|
||||
RENAME(__umoddi3, __umodti3)
|
||||
#endif
|
||||
|
||||
// TODO(hamaji): *attr_gettype and *attr_getpshared
|
||||
WRAP(pthread_mutexattr_settype)
|
||||
WRAP(pthread_mutexattr_setpshared)
|
||||
WRAP(pthread_rwlockattr_setpshared)
|
||||
|
||||
WRAP(dlopen)
|
||||
WRAP(dlclose)
|
||||
WRAP(dlerror)
|
||||
WRAP(dlsym)
|
||||
// TODO(hamaji): dladdr?
|
||||
|
||||
RENAME(_ZNSt12__basic_fileIcE8sys_openEP7__sFILESt13_Ios_Openmode,
|
||||
_ZNSt12__basic_fileIcE8sys_openEP8_IO_FILESt13_Ios_Openmode)
|
||||
|
||||
WRAP(uname)
|
||||
|
||||
// TODO(hamaji): Not sure if this is right...
|
||||
RENAME(select$1050, select)
|
||||
|
||||
WRAP(qsort_r)
|
||||
|
||||
WRAP(newlocale)
|
||||
|
||||
WRAP(compat_mode)
|
@ -51,6 +51,7 @@ set(libc_SRCS
|
||||
libc/stdio.cpp
|
||||
libc/fopsmisc.cpp
|
||||
libc/aio.cpp
|
||||
libc/mount.cpp
|
||||
common/path.cpp
|
||||
)
|
||||
|
||||
@ -60,6 +61,7 @@ set(bsdkern_SRCS
|
||||
kernel-bsd/io.cpp
|
||||
kernel-bsd/wait.cpp
|
||||
kernel-bsd/sockets.cpp
|
||||
kernel-bsd/fs.cpp
|
||||
)
|
||||
|
||||
set(machkern_SRCS
|
||||
@ -71,9 +73,9 @@ set(machkern_SRCS
|
||||
kernel-mach/vm.cpp
|
||||
)
|
||||
|
||||
add_library(System.dylib SHARED ${libc_SRCS} ${bsdkern_SRCS} ${machkern_SRCS})
|
||||
add_library(System.B.dylib SHARED ${libc_SRCS} ${bsdkern_SRCS} ${machkern_SRCS})
|
||||
# -luuid to make uuid_ functions available for Darwin apps
|
||||
target_link_libraries(System.dylib -ldl -lpthread -luuid -lmach-o -l:libobjc.so.4 -lrt -lssl)
|
||||
target_link_libraries(System.B.dylib -ldl -lpthread -luuid -lmach-o -l:libobjc.so.4 -lrt -lssl)
|
||||
|
||||
install(TARGETS System.dylib DESTINATION lib)
|
||||
install(TARGETS System.B.dylib DESTINATION lib)
|
||||
|
||||
|
161
src/libSystem/kernel-bsd/fs.cpp
Normal file
161
src/libSystem/kernel-bsd/fs.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
#include "config.h"
|
||||
#include "fs.h"
|
||||
#include <cstring>
|
||||
#include "common/path.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/darwin_errno_codes.h"
|
||||
#include <mntent.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <unistd.h>
|
||||
#include "log.h"
|
||||
|
||||
template<typename Out> void StatfsLinuxToDarwinGen(const char* path, const struct statvfs* in, Out* out)
|
||||
{
|
||||
out->f_bsize = in->f_bsize;
|
||||
out->f_blocks = out->f_iosize = in->f_blocks;
|
||||
out->f_bfree = in->f_bfree;
|
||||
out->f_bavail = in->f_bavail;
|
||||
out->f_files = in->f_files;
|
||||
out->f_ffree = in->f_ffree;
|
||||
out->f_fsid.val[0] = in->f_fsid;
|
||||
|
||||
if (in->f_flag & ST_RDONLY)
|
||||
out->f_flags |= DARWIN_MNT_RDONLY;
|
||||
if (in->f_flag & ST_NOSUID)
|
||||
out->f_flags |= DARWIN_MNT_NOSUID;
|
||||
|
||||
struct mntent* ent = findMountForPath(path);
|
||||
if (ent)
|
||||
{
|
||||
strncpy(out->f_mntfromname, ent->mnt_fsname, sizeof(out->f_mntfromname)-1); // we assume zeroed out, no need to set the last char to NUL
|
||||
strncpy(out->f_mntonname, ent->mnt_dir, sizeof(out->f_mntonname)-1);
|
||||
strncpy(out->f_fstypename, ent->mnt_fsname, sizeof(out->f_fstypename)-1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> int __darwin_statfsGen(const char* path, T* buf)
|
||||
{
|
||||
struct statvfs st;
|
||||
int rv;
|
||||
|
||||
::memset(buf, 0, sizeof(*buf));
|
||||
|
||||
rv = statvfs(path, &st);
|
||||
if (rv == -1)
|
||||
errnoOut();
|
||||
else
|
||||
StatfsLinuxToDarwinGen(path, &st, buf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int __darwin_statfs(const char* path, struct __darwin_statfs* buf)
|
||||
{
|
||||
return __darwin_statfsGen(translatePathCI(path), buf);
|
||||
}
|
||||
|
||||
int __darwin_statfs64(const char* path, struct __darwin_statfs64* buf)
|
||||
{
|
||||
return __darwin_statfsGen(translatePathCI(path), buf);
|
||||
}
|
||||
|
||||
template <typename T> int __darwin_fstatfsGen(int fd, T* out)
|
||||
{
|
||||
char buf[PATH_MAX], buf2[PATH_MAX];
|
||||
sprintf(buf, "/proc/%d/fd/%d", getpid(), fd);
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
if (::readlink(buf, buf2, sizeof buf2) == -1)
|
||||
{
|
||||
errnoOut();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __darwin_statfsGen(buf2, out);
|
||||
}
|
||||
|
||||
int __darwin_fstatfs(int fd, struct __darwin_statfs* buf)
|
||||
{
|
||||
return __darwin_fstatfsGen(fd, buf);
|
||||
}
|
||||
|
||||
int __darwin_fstatfs64(int fd, struct __darwin_statfs64* buf)
|
||||
{
|
||||
return __darwin_fstatfsGen(fd, buf);
|
||||
}
|
||||
|
||||
template<typename Stat> int __darwin_getfsstatGen(Stat* buf, int bufsize, int flags)
|
||||
{
|
||||
FILE* f = setmntent("/proc/mounts", "r");
|
||||
struct mntent *ent;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
LOG << "Cannot access /proc/mounts!\n";
|
||||
errno = DARWIN_ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
while ( (ent = getmntent(f)) != 0 && ((count+1)*sizeof(*buf) < bufsize || !buf) )
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
int rv = __darwin_statfsGen(ent->mnt_dir, buf+count);
|
||||
if (rv == -1)
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
endmntent(f);
|
||||
return count;
|
||||
}
|
||||
|
||||
int __darwin_getfsstat(struct __darwin_statfs* buf, int bufsize, int flags)
|
||||
{
|
||||
return __darwin_getfsstatGen(buf, bufsize, flags);
|
||||
}
|
||||
|
||||
int __darwin_getfsstat64(struct __darwin_statfs* buf, int bufsize, int flags)
|
||||
{
|
||||
return __darwin_getfsstatGen(buf, bufsize, flags);
|
||||
}
|
||||
|
||||
void StatfsLinuxToDarwin(const char* path, const struct statvfs* in, struct __darwin_statfs* out)
|
||||
{
|
||||
StatfsLinuxToDarwinGen(path, in, out);
|
||||
}
|
||||
|
||||
void StatfsLinuxToDarwin(const char* path, const struct statvfs* in, struct __darwin_statfs64* out)
|
||||
{
|
||||
StatfsLinuxToDarwinGen(path, in, out);
|
||||
}
|
||||
|
||||
struct mntent* findMountForPath(const char* path)
|
||||
{
|
||||
FILE* f = setmntent("/proc/mounts", "r");
|
||||
struct mntent *ent, *rv = 0;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
LOG << "Cannot access /proc/mounts!\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((ent = getmntent(f)))
|
||||
{
|
||||
if (strncmp(ent->mnt_dir, path, strlen(ent->mnt_dir)) == 0)
|
||||
{
|
||||
rv = ent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
endmntent(f);
|
||||
return rv;
|
||||
}
|
86
src/libSystem/kernel-bsd/fs.h
Normal file
86
src/libSystem/kernel-bsd/fs.h
Normal file
@ -0,0 +1,86 @@
|
||||
#ifndef BSD_FS_H
|
||||
#define BSD_FS_H
|
||||
#include <stdint.h>
|
||||
#include "common/path.h"
|
||||
|
||||
#define MFSNAMELEN 15
|
||||
#define MFSTYPENAMELEN 16
|
||||
#define MNAMELEN 90
|
||||
|
||||
#define DARWIN_MNT_RDONLY 0x1
|
||||
#define DARWIN_MNT_SYNCHRONOUS 0x2
|
||||
#define DARWIN_MNT_NOEXEC 0x4
|
||||
#define DARWIN_MNT_NOSUID 0x8
|
||||
#define DARWIN_MNT_NODEV 0x10
|
||||
#define DARWIN_MNT_UNION 0x20
|
||||
#define DARWIN_MNT_ASYNC 0x40
|
||||
#define DARWIN_MNT_CPROTECT 0x80
|
||||
|
||||
|
||||
typedef struct { int32_t val[2]; } darwin_fsid_t;
|
||||
|
||||
struct __darwin_statfs64
|
||||
{
|
||||
uint32_t f_bsize;
|
||||
int32_t f_iosize;
|
||||
uint64_t f_blocks;
|
||||
uint64_t f_bfree;
|
||||
uint64_t f_bavail;
|
||||
uint64_t f_files;
|
||||
uint64_t f_ffree;
|
||||
darwin_fsid_t f_fsid;
|
||||
uint32_t f_owner;
|
||||
uint32_t f_type;
|
||||
uint32_t f_flags;
|
||||
uint32_t f_fssubtype;
|
||||
char f_fstypename[MFSTYPENAMELEN];
|
||||
char f_mntonname[DARWIN_MAXPATHLEN];
|
||||
char f_mntfromname[DARWIN_MAXPATHLEN];
|
||||
uint32_t f_reserved[8];
|
||||
};
|
||||
|
||||
struct __darwin_statfs
|
||||
{
|
||||
short f_otype;
|
||||
short f_oflags;
|
||||
long f_bsize;
|
||||
long f_iosize;
|
||||
long f_blocks;
|
||||
long f_bfree;
|
||||
long f_bavail;
|
||||
long f_files;
|
||||
long f_ffree;
|
||||
darwin_fsid_t f_fsid;
|
||||
uint32_t f_owner;
|
||||
short f_reserved1;
|
||||
short f_type;
|
||||
long f_flags;
|
||||
long f_reserved2[2];
|
||||
char f_fstypename[MFSNAMELEN];
|
||||
char f_mntonname[MNAMELEN];
|
||||
char f_mntfromname[MNAMELEN];
|
||||
char f_reserved3;
|
||||
long f_reserved4[4];
|
||||
};
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
int __darwin_statfs(const char* path, struct __darwin_statfs* buf);
|
||||
int __darwin_statfs64(const char* path, struct __darwin_statfs64* buf) asm("__darwin_statfs$INODE64");
|
||||
int __darwin_fstatfs(int fd, struct __darwin_statfs* buf);
|
||||
int __darwin_fstatfs64(int fd, struct __darwin_statfs64* buf) asm("__darwin_fstatfs$INODE64");
|
||||
int __darwin_getfsstat(struct __darwin_statfs* buf, int bufsize, int flags);
|
||||
int __darwin_getfsstat64(struct __darwin_statfs64* buf, int bufsize, int flags) asm("__darwin_getfsstat$INODE64");
|
||||
|
||||
}
|
||||
|
||||
// out assumed to have been zeroed out
|
||||
void StatfsLinuxToDarwin(const char* path, const struct statvfs* in, struct __darwin_statfs* out);
|
||||
void StatfsLinuxToDarwin(const char* path, const struct statvfs* in, struct __darwin_statfs64* out);
|
||||
|
||||
struct mntent;
|
||||
struct mntent* findMountForPath(const char* path);
|
||||
|
||||
#endif
|
@ -1,3 +1,4 @@
|
||||
#include "config.h"
|
||||
#include "wait.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/darwin_errno_codes.h"
|
||||
|
@ -120,8 +120,73 @@ extern __darwin_opendir
|
||||
__darwin_opendir$INODE64:
|
||||
jmp __darwin_opendir WRT ..plt
|
||||
|
||||
global __darwin_rewinddir$INODE64
|
||||
extern __darwin_rewinddir
|
||||
__darwin_rewinddir$INODE64:
|
||||
jmp __darwin_rewinddir WRT ..plt
|
||||
|
||||
global __darwin_telldir$INODE64
|
||||
extern telldir
|
||||
__darwin_telldir$INODE64:
|
||||
jmp telldir WRT ..plt
|
||||
|
||||
global __darwin_curl_mfprintf
|
||||
extern __darwin_fprintf
|
||||
__darwin_curl_mfprintf:
|
||||
jmp __darwin_fprintf WRT ..plt
|
||||
|
||||
global __darwin_curl_mvfprintf
|
||||
extern __darwin_vfprintf
|
||||
__darwin_curl_mvfprintf:
|
||||
jmp __darwin_vfprintf WRT ..plt
|
||||
|
||||
global realpath$DARWIN_EXTSN
|
||||
extern __darwin_realpath
|
||||
realpath$DARWIN_EXTSN:
|
||||
jmp __darwin_realpath WRT ..plt
|
||||
|
||||
global libintl_gettext
|
||||
extern gettext
|
||||
libintl_gettext:
|
||||
jmp gettext WRT ..plt
|
||||
|
||||
global libintl_dgettext
|
||||
extern dgettext
|
||||
libintl_dgettext:
|
||||
jmp dgettext WRT ..plt
|
||||
|
||||
global libintl_ngettext
|
||||
extern ngettext
|
||||
libintl_ngettext:
|
||||
jmp ngettext WRT ..plt
|
||||
|
||||
global libintl_dngettext
|
||||
extern dngettext
|
||||
libintl_dngettext:
|
||||
jmp dngettext WRT ..plt
|
||||
|
||||
global libintl_dcngettext
|
||||
extern dcngettext
|
||||
libintl_dcngettext:
|
||||
jmp dcngettext WRT ..plt
|
||||
|
||||
global libintl_textdomain
|
||||
extern textdomain
|
||||
libintl_textdomain:
|
||||
jmp textdomain WRT ..plt
|
||||
|
||||
global libintl_bindtextdomain
|
||||
extern bindtextdomain
|
||||
libintl_bindtextdomain:
|
||||
jmp bindtextdomain WRT ..plt
|
||||
|
||||
global libintl_bind_textdomain
|
||||
extern bind_textdomain_codeset
|
||||
libintl_bind_textdomain:
|
||||
jmp bind_textdomain_codeset WRT ..plt
|
||||
|
||||
global libintl_setlocale
|
||||
extern setlocale
|
||||
libintl_setlocale:
|
||||
jmp setlocale WRT ..plt
|
||||
|
||||
|
@ -24,4 +24,22 @@ __darwin_err;__darwin__err
|
||||
|
||||
;;; dir.cpp
|
||||
__darwin_opendir$INODE64;__darwin_opendir
|
||||
__darwin_rewinddir$INODE64;__darwin_rewinddir
|
||||
__darwin_telldir$INODE64;telldir
|
||||
|
||||
__darwin_curl_mfprintf;__darwin_fprintf
|
||||
__darwin_curl_mvfprintf;__darwin_vfprintf
|
||||
|
||||
realpath$DARWIN_EXTSN;__darwin_realpath
|
||||
|
||||
libintl_gettext;gettext
|
||||
libintl_dgettext;dgettext
|
||||
libintl_ngettext;ngettext
|
||||
libintl_dngettext;dngettext
|
||||
libintl_dcngettext;dcngettext
|
||||
libintl_textdomain;textdomain
|
||||
libintl_bindtextdomain;bindtextdomain
|
||||
libintl_bind_textdomain;bind_textdomain_codeset
|
||||
libintl_setlocale;setlocale
|
||||
|
||||
|
||||
|
@ -17,6 +17,9 @@ char *__darwin_realpath(const char *path, char *resolved_path)
|
||||
|
||||
path = translatePathCI(path);
|
||||
|
||||
if (!resolved_path) // DARWIN_EXTSN
|
||||
resolved_path = static_cast<char*>(malloc(DARWIN_MAXPATHLEN));
|
||||
|
||||
char* rv = realpath(path, resolved_path);
|
||||
if (!rv)
|
||||
errnoOut();
|
||||
|
52
src/libSystem/libc/mount.cpp
Normal file
52
src/libSystem/libc/mount.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "mount.h"
|
||||
#include <mntent.h>
|
||||
#include "libc/darwin_errno_codes.h"
|
||||
#include <errno.h>
|
||||
|
||||
template<typename Statfs, typename Fsstatfun> int __darwin_getmntinfoGen(Fsstatfun f, Statfs** mntbufp, int flags)
|
||||
{
|
||||
static __thread Statfs* lastMntbufp = 0;
|
||||
|
||||
*mntbufp = 0;
|
||||
|
||||
if (lastMntbufp)
|
||||
{
|
||||
delete [] lastMntbufp;
|
||||
lastMntbufp = 0;
|
||||
}
|
||||
|
||||
int count = f(0, 0, 0);
|
||||
|
||||
if (count < 0)
|
||||
return -1;
|
||||
|
||||
lastMntbufp = new Statfs[count];
|
||||
if (!lastMntbufp)
|
||||
{
|
||||
errno = DARWIN_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
count = f(lastMntbufp, count*sizeof(Statfs), 0);
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
delete [] lastMntbufp;
|
||||
lastMntbufp = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mntbufp = lastMntbufp;
|
||||
return count;
|
||||
}
|
||||
|
||||
int __darwin_getmntinfo(struct __darwin_statfs** mntbufp, int flags)
|
||||
{
|
||||
return __darwin_getmntinfoGen(__darwin_getfsstat, mntbufp, flags);
|
||||
}
|
||||
|
||||
int __darwin_getmntinfo64(struct __darwin_statfs64** mntbufp, int flags)
|
||||
{
|
||||
return __darwin_getmntinfoGen(__darwin_getfsstat64, mntbufp, flags);
|
||||
}
|
||||
|
13
src/libSystem/libc/mount.h
Normal file
13
src/libSystem/libc/mount.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef LIBC_MOUNT_H
|
||||
#define LIBC_MOUNT_H
|
||||
#include "kernel-bsd/fs.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
int __darwin_getmntinfo(struct __darwin_statfs** mntbufp, int flags);
|
||||
int __darwin_getmntinfo64(struct __darwin_statfs64** mntbufp, int flags) asm("__darwin_getmntinfo$INODE64");
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,3 +1,4 @@
|
||||
#include "config.h"
|
||||
#include "stdio.h"
|
||||
#include "errno.h"
|
||||
#include "common/path.h"
|
||||
@ -7,11 +8,19 @@
|
||||
#include <cstdlib>
|
||||
#include <errno.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "log.h"
|
||||
|
||||
extern "C" __darwin_FILE* __stdinp = 0;
|
||||
extern "C" __darwin_FILE* __stdoutp = 0;
|
||||
extern "C" __darwin_FILE* __stderrp = 0;
|
||||
//extern "C"
|
||||
//{
|
||||
__darwin_FILE* __stdinp asm("__stdinp") = 0;
|
||||
__darwin_FILE* __stdoutp asm("__stdoutp") = 0;
|
||||
__darwin_FILE* __stderrp asm("__stderrp") = 0;
|
||||
//}
|
||||
|
||||
static __darwin_FILE* InitDarwinFILE(FILE* linux_fp)
|
||||
{
|
||||
@ -39,7 +48,30 @@ template<typename RetVal, typename Func, typename... Params> RetVal AutoFileErrn
|
||||
|
||||
__darwin_FILE* __darwin_fopen(const char* path, const char* mode)
|
||||
{
|
||||
return InitDarwinFILE(fopen(translatePathCI(path), mode));
|
||||
path = translatePathCI(path);
|
||||
|
||||
if (!strchr(mode, 'x'))
|
||||
return InitDarwinFILE(fopen(path, mode));
|
||||
else // DARWIN_EXTSN
|
||||
{
|
||||
std::string m = mode;
|
||||
size_t pos = m.find('x');
|
||||
m.erase(pos, 1);
|
||||
|
||||
int flags = O_CREAT | O_EXCL;
|
||||
if (m.find('a') != std::string::npos)
|
||||
flags |= O_APPEND;
|
||||
if (m.find('+') != std::string::npos)
|
||||
flags |= O_RDWR;
|
||||
else
|
||||
flags |= O_WRONLY;
|
||||
|
||||
int fd = ::open(path, flags, 0666);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
else
|
||||
return __darwin_fdopen(fd, m.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
__darwin_FILE* __darwin_fdopen(int fd, const char* mode)
|
||||
@ -296,9 +328,9 @@ wint_t __darwin_ungetwc(wint_t wc, __darwin_FILE *stream)
|
||||
|
||||
__attribute__((constructor)) static void initStdio()
|
||||
{
|
||||
__stderrp = InitDarwinFILE(stdin);
|
||||
__stderrp = InitDarwinFILE(stderr);
|
||||
__stdoutp = InitDarwinFILE(stdout);
|
||||
__stdinp = InitDarwinFILE(stderr);
|
||||
__stdinp = InitDarwinFILE(stdin);
|
||||
}
|
||||
|
||||
int __darwin_remove(const char* path)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "string.h"
|
||||
#include <cstdlib>
|
||||
#include <ctype.h>
|
||||
|
||||
size_t strlcpy(char* dst, const char* src, size_t size)
|
||||
{
|
||||
@ -40,3 +41,14 @@ int __mb_cur_max()
|
||||
{
|
||||
return MB_CUR_MAX;
|
||||
}
|
||||
|
||||
int __toupper(int c)
|
||||
{
|
||||
return toupper(c);
|
||||
}
|
||||
|
||||
int __tolower(int c)
|
||||
{
|
||||
return tolower(c);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,9 @@ void memset_pattern8(char* b, const char* pattern4, size_t len);
|
||||
void memset_pattern16(char* b, const char* pattern4, size_t len);
|
||||
|
||||
int __mb_cur_max();
|
||||
int __toupper(int c);
|
||||
int __tolower(int c);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#define N_WEAK_DEF 0x0080
|
||||
#define FLAGS_READ_SYMTAB 1
|
||||
@ -235,7 +236,7 @@ MachOImpl::MachOImpl(const char* filename, int fd, size_t offset, size_t len, bo
|
||||
m_fd = fd;
|
||||
m_offset = offset;
|
||||
m_text_offset = 0;
|
||||
m_main = 0;
|
||||
m_main = m_entry = 0;
|
||||
|
||||
if (!m_mapped_size)
|
||||
m_mapped_size = ::lseek(m_fd, 0, SEEK_END);
|
||||
@ -245,15 +246,14 @@ MachOImpl::MachOImpl(const char* filename, int fd, size_t offset, size_t len, bo
|
||||
char* bin = m_mapped = reinterpret_cast<char*>(
|
||||
::mmap(NULL, m_mapped_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, m_fd, offset)
|
||||
);
|
||||
|
||||
if (bin == MAP_FAILED)
|
||||
throw std::runtime_error("Cannot mmap Mach-O file");
|
||||
|
||||
m_base = bin;
|
||||
|
||||
mach_header* header = reinterpret_cast<mach_header*>(bin);
|
||||
|
||||
LOGF("magic=%x cpu=%d cpusub=%d file=%d ncmds=%d sizecmd=%d flags=%x\n",
|
||||
header->magic, header->cputype, header->cpusubtype,
|
||||
header->filetype, header->ncmds, header->sizeofcmds,
|
||||
header->flags);
|
||||
|
||||
m_is64 = false;
|
||||
if (header->magic == MH_MAGIC_64)
|
||||
m_is64 = true;
|
||||
@ -262,6 +262,12 @@ MachOImpl::MachOImpl(const char* filename, int fd, size_t offset, size_t len, bo
|
||||
fprintf(stderr, "Not mach-o: %s\n", filename);
|
||||
exit(1); // TODO: throw instead
|
||||
}
|
||||
|
||||
LOGF("magic=%x cpu=%d cpusub=%d file=%d ncmds=%d sizecmd=%d flags=%x\n",
|
||||
header->magic, header->cputype, header->cpusubtype,
|
||||
header->filetype, header->ncmds, header->sizeofcmds,
|
||||
header->flags);
|
||||
|
||||
m_ptrsize = m_is64 ? 8 : 4;
|
||||
|
||||
if ((header->cputype & 0x00ffffff) != CPU_TYPE_X86)
|
||||
|
@ -27,4 +27,13 @@
|
||||
|
||||
#include "env_flags.h"
|
||||
|
||||
DEFINE_bool(LOG, false, "Output bunch of logs");
|
||||
// DEFINE_bool(LOG, false, "Output bunch of logs");
|
||||
extern "C" bool g_loggingEnabled = false;
|
||||
|
||||
__attribute__((constructor)) static void initLogging()
|
||||
{
|
||||
const char* v = getenv("DYLD_DEBUG");
|
||||
if (v && atoi(v))
|
||||
g_loggingEnabled = true;
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,15 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
//#include "env_flags.h"
|
||||
|
||||
//DECLARE_bool(LOG);
|
||||
#define FLAGS_LOG 1
|
||||
extern bool g_loggingEnabled;
|
||||
#define FLAGS_LOG g_loggingEnabled
|
||||
|
||||
#ifdef NOLOG
|
||||
# define LOG if (0) std::cout
|
||||
|
@ -11,7 +11,10 @@ class Mutex
|
||||
public:
|
||||
Mutex()
|
||||
{
|
||||
pthread_mutex_init(&m_mutex, 0);
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&m_mutex, &attr);
|
||||
}
|
||||
~Mutex()
|
||||
{
|
||||
|
@ -2,31 +2,29 @@
|
||||
#include <stdarg.h>
|
||||
#include <iostream>
|
||||
|
||||
bool g_enableTrace = false;
|
||||
|
||||
TraceHelper::TraceHelper(const char* funcName)
|
||||
{
|
||||
std::cerr << "TRACE(): " << funcName << "";
|
||||
if (g_loggingEnabled)
|
||||
std::cerr << "TRACE(): " << funcName << "";
|
||||
}
|
||||
TraceHelper::~TraceHelper()
|
||||
{
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
void enableTrace(bool enable)
|
||||
{
|
||||
g_enableTrace = enable;
|
||||
if (g_loggingEnabled)
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
template<> void logPrint<std::string>(std::string value)
|
||||
{
|
||||
std::cerr << '\"' << value << '\"';
|
||||
if (g_loggingEnabled)
|
||||
std::cerr << '\"' << value << '\"';
|
||||
}
|
||||
template<> void logPrint<const char*>(const char* value)
|
||||
{
|
||||
std::cerr << '\"' << value << '\"';
|
||||
if (g_loggingEnabled)
|
||||
std::cerr << '\"' << value << '\"';
|
||||
}
|
||||
template<> void logPrint<ArgName>(ArgName value)
|
||||
{
|
||||
std::cerr << value.name;
|
||||
if (g_loggingEnabled)
|
||||
std::cerr << value.name;
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
#ifndef DARLING_TRACE_H
|
||||
#define DARLING_TRACE_H
|
||||
#include <iostream>
|
||||
#include "log.h"
|
||||
|
||||
extern bool g_enableTrace;
|
||||
void logTrace(const char* funcName, ...);
|
||||
void enableTrace(bool enable);
|
||||
|
||||
struct ArgName
|
||||
{
|
||||
@ -14,7 +13,8 @@ struct ArgName
|
||||
|
||||
template<typename T> void logPrint(T value)
|
||||
{
|
||||
std::cerr << value;
|
||||
if (g_loggingEnabled)
|
||||
std::cerr << value;
|
||||
}
|
||||
template<> void logPrint<const char*>(const char* value);
|
||||
template<> void logPrint<std::string>(std::string value);
|
||||
|
Loading…
Reference in New Issue
Block a user