From 45a369fdf968fdf376a4d3a6c130cb503777d68b Mon Sep 17 00:00:00 2001 From: Lubos Dolezel Date: Wed, 15 Aug 2012 12:17:58 +0200 Subject: [PATCH] Loads of work on dyld and BSD functions --- .gdbinit | 2 +- CMakeLists.txt | 2 +- src/dyld/MachOLoader.cpp | 28 +- src/dyld/dyld.cpp | 68 ++++- src/dyld/ld-mac.cc | 470 ------------------------------ src/dyld/ld.cpp | 127 +++++++- src/dyld/ld.h | 2 +- src/dyld/rename.tab | 155 ---------- src/libSystem/CMakeLists.txt | 8 +- src/libSystem/kernel-bsd/fs.cpp | 161 ++++++++++ src/libSystem/kernel-bsd/fs.h | 86 ++++++ src/libSystem/kernel-bsd/wait.cpp | 1 + src/libSystem/libc/directmap.asm | 65 +++++ src/libSystem/libc/directmap.lst | 18 ++ src/libSystem/libc/fopsmisc.cpp | 3 + src/libSystem/libc/mount.cpp | 52 ++++ src/libSystem/libc/mount.h | 13 + src/libSystem/libc/stdio.cpp | 44 ++- src/libSystem/libc/string.cpp | 12 + src/libSystem/libc/string.h | 3 + src/libmach-o/MachOImpl.cpp | 18 +- src/util/log.cc | 11 +- src/util/log.h | 7 +- src/util/mutex.h | 5 +- src/util/trace.cpp | 22 +- src/util/trace.h | 6 +- 26 files changed, 695 insertions(+), 694 deletions(-) delete mode 100644 src/dyld/ld-mac.cc delete mode 100644 src/dyld/rename.tab create mode 100644 src/libSystem/kernel-bsd/fs.cpp create mode 100644 src/libSystem/kernel-bsd/fs.h create mode 100644 src/libSystem/libc/mount.cpp create mode 100644 src/libSystem/libc/mount.h diff --git a/.gdbinit b/.gdbinit index beb4dc6cd..a717a5162 100644 --- a/.gdbinit +++ b/.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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 293568c3f..3c1267d56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/dyld/MachOLoader.cpp b/src/dyld/MachOLoader.cpp index 5c9fdc99d..9adb4b5e1 100644 --- a/src/dyld/MachOLoader.cpp +++ b/src/dyld/MachOLoader.cpp @@ -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(__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(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 << ": " diff --git a/src/dyld/dyld.cpp b/src/dyld/dyld.cpp index 9b68f9ee3..2efed83ff 100644 --- a/src/dyld/dyld.cpp +++ b/src/dyld/dyld.cpp @@ -1,25 +1,35 @@ #include "MachO.h" #include "MachOLoader.h" #include "arch.h" +#include "log.h" #include #include #include #include #include +#include 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= - 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; + } + } +} diff --git a/src/dyld/ld-mac.cc b/src/dyld/ld-mac.cc deleted file mode 100644 index 67e1ccea9..000000000 --- a/src/dyld/ld-mac.cc +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#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 g_rename; -static vector g_bound_names; -static set 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& getSegments(const MachO& mach) { - return mach.segments64(); - } -#else - typedef uint32_t intptr; - typedef segment_command Segment; - - static const vector& 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 init_funcs_; - Exports exports_; - vector > seen_weak_binds_; - map dylib_to_so_; - map symbol_to_so_; - set 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 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); -} -*/ diff --git a/src/dyld/ld.cpp b/src/dyld/ld.cpp index dc246a361..352f88fad 100644 --- a/src/dyld/ld.cpp +++ b/src/dyld/ld.cpp @@ -15,10 +15,14 @@ #include #include #include +#include +#include static Darling::Mutex g_ldMutex; static std::map 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::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(malloc(strlen(symbol+20))); + char* buf = reinterpret_cast(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 diff --git a/src/dyld/ld.h b/src/dyld/ld.h index 276dbd0c3..2378cdf40 100644 --- a/src/dyld/ld.h +++ b/src/dyld/ld.h @@ -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 Exports; diff --git a/src/dyld/rename.tab b/src/dyld/rename.tab deleted file mode 100644 index 670af8174..000000000 --- a/src/dyld/rename.tab +++ /dev/null @@ -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) diff --git a/src/libSystem/CMakeLists.txt b/src/libSystem/CMakeLists.txt index 91f0b6284..0b522faac 100644 --- a/src/libSystem/CMakeLists.txt +++ b/src/libSystem/CMakeLists.txt @@ -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) diff --git a/src/libSystem/kernel-bsd/fs.cpp b/src/libSystem/kernel-bsd/fs.cpp new file mode 100644 index 000000000..22b5d8593 --- /dev/null +++ b/src/libSystem/kernel-bsd/fs.cpp @@ -0,0 +1,161 @@ +#include "config.h" +#include "fs.h" +#include +#include "common/path.h" +#include "libc/errno.h" +#include "libc/darwin_errno_codes.h" +#include +#include +#include +#include +#include +#include +#include "log.h" + +template 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 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 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 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; +} diff --git a/src/libSystem/kernel-bsd/fs.h b/src/libSystem/kernel-bsd/fs.h new file mode 100644 index 000000000..f67c60461 --- /dev/null +++ b/src/libSystem/kernel-bsd/fs.h @@ -0,0 +1,86 @@ +#ifndef BSD_FS_H +#define BSD_FS_H +#include +#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 diff --git a/src/libSystem/kernel-bsd/wait.cpp b/src/libSystem/kernel-bsd/wait.cpp index 928c7f311..9e409bdd9 100644 --- a/src/libSystem/kernel-bsd/wait.cpp +++ b/src/libSystem/kernel-bsd/wait.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include "wait.h" #include "libc/errno.h" #include "libc/darwin_errno_codes.h" diff --git a/src/libSystem/libc/directmap.asm b/src/libSystem/libc/directmap.asm index 04e202aab..3a9c9b93a 100644 --- a/src/libSystem/libc/directmap.asm +++ b/src/libSystem/libc/directmap.asm @@ -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 + diff --git a/src/libSystem/libc/directmap.lst b/src/libSystem/libc/directmap.lst index b9cc278f3..486d02934 100644 --- a/src/libSystem/libc/directmap.lst +++ b/src/libSystem/libc/directmap.lst @@ -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 + + diff --git a/src/libSystem/libc/fopsmisc.cpp b/src/libSystem/libc/fopsmisc.cpp index f4ecf5eaa..8db263ce3 100644 --- a/src/libSystem/libc/fopsmisc.cpp +++ b/src/libSystem/libc/fopsmisc.cpp @@ -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(malloc(DARWIN_MAXPATHLEN)); + char* rv = realpath(path, resolved_path); if (!rv) errnoOut(); diff --git a/src/libSystem/libc/mount.cpp b/src/libSystem/libc/mount.cpp new file mode 100644 index 000000000..8a4212e19 --- /dev/null +++ b/src/libSystem/libc/mount.cpp @@ -0,0 +1,52 @@ +#include "mount.h" +#include +#include "libc/darwin_errno_codes.h" +#include + +template 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); +} + diff --git a/src/libSystem/libc/mount.h b/src/libSystem/libc/mount.h new file mode 100644 index 000000000..5327fefec --- /dev/null +++ b/src/libSystem/libc/mount.h @@ -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 diff --git a/src/libSystem/libc/stdio.cpp b/src/libSystem/libc/stdio.cpp index 5f69b8cf2..443f76261 100644 --- a/src/libSystem/libc/stdio.cpp +++ b/src/libSystem/libc/stdio.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include "stdio.h" #include "errno.h" #include "common/path.h" @@ -7,11 +8,19 @@ #include #include #include +#include +#include +#include +#include +#include #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 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) diff --git a/src/libSystem/libc/string.cpp b/src/libSystem/libc/string.cpp index 9c4521e8a..5f9c9b630 100644 --- a/src/libSystem/libc/string.cpp +++ b/src/libSystem/libc/string.cpp @@ -1,5 +1,6 @@ #include "string.h" #include +#include 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); +} + diff --git a/src/libSystem/libc/string.h b/src/libSystem/libc/string.h index 763670456..76f0bf081 100644 --- a/src/libSystem/libc/string.h +++ b/src/libSystem/libc/string.h @@ -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); + } diff --git a/src/libmach-o/MachOImpl.cpp b/src/libmach-o/MachOImpl.cpp index f0ae94f86..cf25ad741 100644 --- a/src/libmach-o/MachOImpl.cpp +++ b/src/libmach-o/MachOImpl.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #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( ::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(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) diff --git a/src/util/log.cc b/src/util/log.cc index 43d38c053..8cb1ec2e9 100644 --- a/src/util/log.cc +++ b/src/util/log.cc @@ -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; +} + diff --git a/src/util/log.h b/src/util/log.h index 93cf11e76..dbfdb44a6 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -31,10 +31,15 @@ #include #include +#ifdef __cplusplus +# include +#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 diff --git a/src/util/mutex.h b/src/util/mutex.h index ca13e8624..c0a4faad5 100644 --- a/src/util/mutex.h +++ b/src/util/mutex.h @@ -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() { diff --git a/src/util/trace.cpp b/src/util/trace.cpp index 682aa8649..1a8686e7d 100644 --- a/src/util/trace.cpp +++ b/src/util/trace.cpp @@ -2,31 +2,29 @@ #include #include -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 value) { - std::cerr << '\"' << value << '\"'; + if (g_loggingEnabled) + std::cerr << '\"' << value << '\"'; } template<> void logPrint(const char* value) { - std::cerr << '\"' << value << '\"'; + if (g_loggingEnabled) + std::cerr << '\"' << value << '\"'; } template<> void logPrint(ArgName value) { - std::cerr << value.name; + if (g_loggingEnabled) + std::cerr << value.name; } diff --git a/src/util/trace.h b/src/util/trace.h index 5b0ce2a39..d8fb9702d 100644 --- a/src/util/trace.h +++ b/src/util/trace.h @@ -1,10 +1,9 @@ #ifndef DARLING_TRACE_H #define DARLING_TRACE_H #include +#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 void logPrint(T value) { - std::cerr << value; + if (g_loggingEnabled) + std::cerr << value; } template<> void logPrint(const char* value); template<> void logPrint(std::string value);