From 3c8b0a1064c642672abee0f5cb5548a1e2916b2a Mon Sep 17 00:00:00 2001 From: Mohamed Mediouni <24752637+woachk@users.noreply.github.com> Date: Thu, 25 Oct 2018 21:03:38 +0200 Subject: [PATCH 1/2] Fix 32-bit builds --- ld-mac.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ld-mac.cc b/ld-mac.cc index 83d2592..ed48215 100644 --- a/ld-mac.cc +++ b/ld-mac.cc @@ -841,7 +841,7 @@ void MachOLoader::boot( " push %%eax;\n" " jmp *%0;\n" // TODO(hamaji): Fix parameters - ::"r"(entry), "r"(argc), "r"(argv + argc), "g"(envp) + ::"r"((uint32_t)entry), "r"(argc), "r"(argv + argc), "g"(envp) :"%eax", "%edx"); #endif } From 0a5678f1f991b1ab06dba76cf8c840773b71c582 Mon Sep 17 00:00:00 2001 From: WHR Date: Tue, 29 Nov 2022 11:31:51 +0800 Subject: [PATCH 2/2] Port to FreeBSD --- Makefile | 9 +- include/_types.h | 8 ++ include/{runetype.h => mac-runetype.h} | 26 ++--- ld-mac.cc | 22 +++- libmac/mac.c | 138 ++++++++++++++++++------- libmac/runetable.c | 2 +- macho2elf.cc | 6 +- 7 files changed, 152 insertions(+), 59 deletions(-) rename include/{runetype.h => mac-runetype.h} (90%) diff --git a/Makefile b/Makefile index 95cc0e0..8043309 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,14 @@ VERSION=0.4 BITS=64 GCC_EXTRA_FLAGS=-m$(BITS) -GCCFLAGS+=-g -Iinclude -Wall -MMD -fno-omit-frame-pointer -O $(GCC_EXTRA_FLAGS) +GCCFLAGS+=-g -Iinclude -Wall -MMD -fno-omit-frame-pointer -O1 $(GCC_EXTRA_FLAGS) ifeq ($(USE_LIBCXX), 1) GCCFLAGS+=-stdlib=libc++ -DUSE_LIBCXX CXX_LDFLAGS+=-lc++ -lsupc++ CC=clang CXX=clang++ endif -CXXFLAGS=$(GCCFLAGS) -W -Werror --std=c++11 +CXXFLAGS=$(GCCFLAGS) -Wextra -Werror --std=c++11 CFLAGS=$(GCCFLAGS) -fPIC EXES=libmac.so extract macho2elf ld-mac @@ -30,6 +30,7 @@ MAC_CC=PATH=$(MAC_BIN_DIR) ./ld-mac $(MAC_BIN_DIR)/gcc --sysroot=$(MAC_TOOL_DIR) MAC_CXX=PATH=$(MAC_BIN_DIR) ./ld-mac $(MAC_BIN_DIR)/g++ --sysroot=$(MAC_TOOL_DIR) MAC_OTOOL=./ld-mac $(MAC_BIN_DIR)/otool MAC_TARGETS=ld-mac $(MACBINS) $(MACTXTS) +DL_LIBS=-ldl else MAC_CC=$(CC) MAC_CXX=$(CXX) @@ -79,13 +80,13 @@ $(MACTXTS): %.txt: %.bin # touch $@ extract: extract.o fat.o - $(CXX) $^ -o $@ -g -I. -W -Wall $(GCC_EXTRA_FLAGS) $(CXX_LDFLAGS) + $(CXX) $^ -o $@ -g -I. -Wall $(GCC_EXTRA_FLAGS) $(CXX_LDFLAGS) macho2elf: macho2elf.o mach-o.o fat.o log.o $(CXX) $^ -o $@ -g $(GCC_EXTRA_FLAGS) $(CXX_LDFLAGS) ld-mac: ld-mac.o mach-o.o fat.o log.o - $(CXX) -v $^ -o $@ -g -ldl -lpthread $(GCC_EXTRA_FLAGS) $(CXX_LDFLAGS) + $(CXX) -v $^ -g $(GCC_EXTRA_FLAGS) $(CXX_LDFLAGS) -o $@ $(DL_LIBS) -lpthread $(LIBS) # TODO(hamaji): autotoolize? libmac.so: libmac/mac.o libmac/strmode.c diff --git a/include/_types.h b/include/_types.h index 16ce25b..cf91853 100644 --- a/include/_types.h +++ b/include/_types.h @@ -28,14 +28,22 @@ //#include #if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 +#ifndef __strfmonlike #define __strfmonlike(fmtarg, firstvararg) \ __attribute__((__format__ (__strfmon__, fmtarg, firstvararg))) +#endif +#ifndef __strftimelike #define __strftimelike(fmtarg) \ __attribute__((__format__ (__strftime__, fmtarg, 0))) +#endif #else +#ifndef __strfmonlike #define __strfmonlike(fmtarg, firstvararg) +#endif +#ifndef __strftimelike #define __strftimelike(fmtarg) #endif +#endif typedef int __darwin_nl_item; typedef int __darwin_wctrans_t; diff --git a/include/runetype.h b/include/mac-runetype.h similarity index 90% rename from include/runetype.h rename to include/mac-runetype.h index 9458b04..c494f04 100644 --- a/include/runetype.h +++ b/include/mac-runetype.h @@ -36,8 +36,8 @@ * @(#)runetype.h 8.1 (Berkeley) 6/2/93 */ -#ifndef _RUNETYPE_H_ -#define _RUNETYPE_H_ +#ifndef _MAC_RUNETYPE_H_ +#define _MAC_RUNETYPE_H_ #include <_types.h> #include @@ -45,7 +45,7 @@ typedef wchar_t __darwin_rune_t; typedef size_t __darwin_size_t; -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) +#if 0 && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) #ifndef _SIZE_T #define _SIZE_T @@ -87,12 +87,12 @@ typedef struct { __darwin_rune_t __max; /* Last rune (inclusive) of the range */ __darwin_rune_t __map; /* What first maps to in maps */ uint32_t *__types; /* Array of types in range */ -} _RuneEntry; +} _MacRuneEntry; typedef struct { int __nranges; /* Number of ranges stored */ - _RuneEntry *__ranges; /* Pointer to the ranges */ -} _RuneRange; + _MacRuneEntry *__ranges; /* Pointer to the ranges */ +} _MacRuneRange; typedef struct { char __name[14]; /* CHARCLASS_NAME_MAX = 14 */ @@ -116,9 +116,9 @@ typedef struct { * Their data is actually contiguous with this structure so as to make * it easier to read/write from/to disk. */ - _RuneRange __runetype_ext; - _RuneRange __maplower_ext; - _RuneRange __mapupper_ext; + _MacRuneRange __runetype_ext; + _MacRuneRange __maplower_ext; + _MacRuneRange __mapupper_ext; void *__variable; /* Data which depends on the encoding */ int __variable_len; /* how long that data is */ @@ -128,13 +128,13 @@ typedef struct { */ int __ncharclasses; _RuneCharClass *__charclasses; -} _RuneLocale; +} _MacRuneLocale; #define _RUNE_MAGIC_A "RuneMagA" /* Indicates version A of RuneLocale */ __BEGIN_DECLS -extern _RuneLocale _DefaultRuneLocale; -extern _RuneLocale *_CurrentRuneLocale; +extern _MacRuneLocale _MacDefaultRuneLocale; +extern _MacRuneLocale *_MacCurrentRuneLocale; __END_DECLS -#endif /* !_RUNETYPE_H_ */ +#endif /* !_MAC_RUNETYPE_H_ */ diff --git a/ld-mac.cc b/ld-mac.cc index ed48215..9d78b28 100644 --- a/ld-mac.cc +++ b/ld-mac.cc @@ -27,6 +27,7 @@ // A Mach-O loader for linux. +#include #include #include #include @@ -43,6 +44,9 @@ #include #include #include +#ifdef BSD +#include +#endif #include #include @@ -444,7 +448,7 @@ class MachOLoader { void* mapped = mmap((void*)(vmaddr + filesize), vmsize - filesize, prot, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, - 0, 0); + -1, 0); if (mapped == MAP_FAILED) { err(1, "%s mmap(anon) failed", mach.filename().c_str()); } @@ -879,6 +883,7 @@ extern "C" { /* signal handler for fatal errors */ static void handleSignal(int signum, siginfo_t* siginfo, void* vuc) { ucontext_t *uc = (ucontext_t*)vuc; +#ifdef __linux__ void* pc = (void*)uc->uc_mcontext.gregs[ #ifdef __x86_64__ REG_RIP @@ -886,6 +891,13 @@ static void handleSignal(int signum, siginfo_t* siginfo, void* vuc) { REG_EIP #endif ]; +#else +#ifdef __x86_64__ + void *pc = (void *)uc->uc_mcontext.mc_rip; +#else + void *pc = (void *)uc->uc_mcontext.mc_eip; +#endif +#endif fprintf(stderr, "%s(%d) %d (@%p) PC: %p\n\n", strsignal(signum), signum, siginfo->si_code, siginfo->si_addr, pc); @@ -949,11 +961,19 @@ static bool loadLibMac(const char* mypath) { static void initLibMac() { char mypath[PATH_MAX + 1]; +#ifdef __linux__ ssize_t l = readlink("/proc/self/exe", mypath, PATH_MAX); if (l < 0) { err(1, "readlink for /proc/self/exe"); } mypath[l] = '\0'; +#else + size_t len = sizeof mypath; + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + if(sysctl(mib, 4, mypath, &len, NULL, 0) < 0) { + err(1, "sysctl for kern.proc.pathname"); + } +#endif if (!loadLibMac(mypath)) { fprintf(stderr, "libmac not found\n"); diff --git a/libmac/mac.c b/libmac/mac.c index 78eb18a..3879115 100644 --- a/libmac/mac.c +++ b/libmac/mac.c @@ -28,7 +28,11 @@ // Emulation for functions in Mac. #define _GNU_SOURCE +#define _DONT_USE_CTYPE_INLINE_ /* Prevent ctype functions conflict */ +#define __mb_cur_max __host_mb_cur_max + +#include #include #include #include @@ -44,12 +48,22 @@ #include #include #include +#ifdef __GLIBC__ #include +#else +#include +#endif #include #include +#ifdef __GLIBC__ +#define HAVE_STAT64 +#define HAVE_STATFS64 +#define HAVE_FSEEKO64 +#endif + #include -#include +#include #include #ifdef NOLOG @@ -62,7 +76,7 @@ int LIBMAC_LOG; typedef __darwin_rune_t rune_t; typedef int __darwin_ct_rune_t; /* ct_rune_t */ -#define _INVALID_RUNE _DefaultRuneLocale.__invalid_rune +#define _INVALID_RUNE _MacDefaultRuneLocale.__invalid_rune #include "errno.c" #include "none.c" @@ -70,6 +84,8 @@ typedef int __darwin_ct_rune_t; /* ct_rune_t */ #include "runetable.c" #include "stack_protector-obsd.c" +#undef __mb_cur_max + struct __darwin_timespec { time_t tv_sec; long tv_nsec; @@ -127,6 +143,12 @@ struct __darwin_stat { __int64_t st_qspare[2]; }; +#ifndef HAVE_STAT64 +#define stat64 stat +#define lstat64 lstat +#define fstat64 fstat +#endif + static void __translate_stat64(struct stat64* linux_buf, struct __darwin_stat64* mac) { // TODO(hamaji): this memset seems to cause overflow... why? @@ -146,23 +168,23 @@ static void __translate_stat64(struct stat64* linux_buf, mac->st_ctimespec.tv_sec = linux_buf->st_ctime; } -static void __translate_stat(struct stat64* linux_buf, +static void __translate_stat(struct stat* host_buf, struct __darwin_stat* mac) { // TODO(hamaji): this memset seems to cause overflow... why? //memset(mac, 0, sizeof(*mac)); - mac->st_dev = linux_buf->st_dev; - mac->st_mode = linux_buf->st_mode; - mac->st_nlink = linux_buf->st_nlink; - mac->st_ino = linux_buf->st_ino; - mac->st_uid = linux_buf->st_uid; - mac->st_gid = linux_buf->st_gid; - mac->st_rdev = linux_buf->st_rdev; - mac->st_size = linux_buf->st_size; - mac->st_blksize = linux_buf->st_blksize; - mac->st_blocks = linux_buf->st_blocks; - mac->st_atimespec.tv_sec = linux_buf->st_atime; - mac->st_mtimespec.tv_sec = linux_buf->st_mtime; - mac->st_ctimespec.tv_sec = linux_buf->st_ctime; + mac->st_dev = host_buf->st_dev; + mac->st_mode = host_buf->st_mode; + mac->st_nlink = host_buf->st_nlink; + mac->st_ino = host_buf->st_ino; + mac->st_uid = host_buf->st_uid; + mac->st_gid = host_buf->st_gid; + mac->st_rdev = host_buf->st_rdev; + mac->st_size = host_buf->st_size; + mac->st_blksize = host_buf->st_blksize; + mac->st_blocks = host_buf->st_blocks; + mac->st_atimespec.tv_sec = host_buf->st_atime; + mac->st_mtimespec.tv_sec = host_buf->st_mtime; + mac->st_ctimespec.tv_sec = host_buf->st_ctime; } static const char kSysname[] = "Darwin"; @@ -198,26 +220,26 @@ int __darwin_lstat64(const char* path, struct __darwin_stat64* mac) { int __darwin_stat(const char* path, struct __darwin_stat* mac) { LOGF("stat: path=%s buf=%p\n", path, mac); - struct stat64 linux_buf; - int ret = stat64(path, &linux_buf); - __translate_stat(&linux_buf, mac); + struct stat host_buf; + int ret = stat(path, &host_buf); + __translate_stat(&host_buf, mac); return ret; } int __darwin_fstat(int fd, struct __darwin_stat* mac) { LOGF("fstat: fd=%d buf=%p\n", fd, mac); LOGF("fstat: size_offset=%d\n", (int)((char*)&mac->st_size - (char*)mac)); - struct stat64 linux_buf; - int ret = fstat64(fd, &linux_buf); - __translate_stat(&linux_buf, mac); + struct stat host_buf; + int ret = fstat(fd, &host_buf); + __translate_stat(&host_buf, mac); return ret; } int __darwin_lstat(const char* path, struct __darwin_stat* mac) { LOGF("lstat: path=%s buf=%p\n", path, mac); - struct stat64 linux_buf; - int ret = lstat64(path, &linux_buf); - __translate_stat(&linux_buf, mac); + struct stat host_buf; + int ret = lstat(path, &host_buf); + __translate_stat(&host_buf, mac); return ret; } @@ -299,6 +321,11 @@ struct __darwin_statfs64 { uint32_t f_reserved[8]; }; +#ifndef HAVE_STATFS64 +#define statfs64 statfs +#define fstatfs64 fstatfs +#endif + static void __translate_statfs64(struct statfs64* linux_buf, struct __darwin_statfs64* mac) { memset(mac, 0, sizeof(*mac)); @@ -335,7 +362,7 @@ int __darwin_fstatfs64(int fd, struct __darwin_statfs64* mac) { } int __maskrune(__darwin_ct_rune_t _c, unsigned long _f) { - return _DefaultRuneLocale.__runetype[_c & 0xff] & _f; + return _MacDefaultRuneLocale.__runetype[_c & 0xff] & _f; } int __maskrune_l(__darwin_ct_rune_t _c, unsigned long _f, void* l) { @@ -468,7 +495,7 @@ int vm_deallocate() { void *__darwin_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { LOGF("mmap: addr=%p length=%lu prot=%d flags=%d fd=%d offset=%lu\n", - addr, (unsigned long)length, prot, flags, fd, offset); + addr, (unsigned long)length, prot, flags, fd, (unsigned long int)offset); // MAP_ANON is 0x1000 on darwin but 0x20 on linux. // @@ -698,6 +725,10 @@ int __darwin_fseeko(__darwin_FILE* fp, uint64_t offset, int whence) { return fseeko(fp->linux_fp, offset, whence); } +#ifndef HAVE_FSEEKO64 +#define fseeko64 fseeko +#endif + int __darwin_fseeko64(__darwin_FILE* fp, uint64_t offset, int whence) { LOGF("fseeko64: %p %" PRIu64 " %d\n", fp, offset, whence); return fseeko64(fp->linux_fp, offset, whence); @@ -821,8 +852,8 @@ int _NSGetExecutablePath(char* buf, unsigned int* size) { int __darwin_open(const char* path, int flags, mode_t mode) { LOGF("open path=%s flags=%d\n", path, flags); - int linux_flags = 0; - linux_flags |= flags & O_ACCMODE; + int host_flags = 0; + host_flags |= flags & O_ACCMODE; // O_SHLOCK if (flags & 0x10) { fprintf(stderr, "Unsupported open flag=%d\n", flags); @@ -833,25 +864,27 @@ int __darwin_open(const char* path, int flags, mode_t mode) { fprintf(stderr, "Unsupported open flag=%d\n", flags); abort(); } - if (flags & 0x40) linux_flags |= O_ASYNC; - if (flags & 0x80) linux_flags |= O_SYNC; - if (flags & 0x100) linux_flags |= O_NOFOLLOW; - if (flags & 0x200) linux_flags |= O_CREAT; - if (flags & 0x400) linux_flags |= O_TRUNC; - if (flags & 0x800) linux_flags |= O_EXCL; + if (flags & 0x40) host_flags |= O_ASYNC; + if (flags & 0x80) host_flags |= O_SYNC; + if (flags & 0x100) host_flags |= O_NOFOLLOW; + if (flags & 0x200) host_flags |= O_CREAT; + if (flags & 0x400) host_flags |= O_TRUNC; + if (flags & 0x800) host_flags |= O_EXCL; // O_EVTONLY if (flags & 0x8000) { fprintf(stderr, "Unsupported open flag=%d\n", flags); abort(); } - if (flags & 0x20000) linux_flags |= O_NOCTTY; - if (flags & 0x100000) linux_flags |= O_DIRECTORY; + if (flags & 0x20000) host_flags |= O_NOCTTY; + if (flags & 0x100000) host_flags |= O_DIRECTORY; // O_SYMLINK if (flags & 0x200000) { fprintf(stderr, "Unsupported open flag=%d\n", flags); abort(); } - if (flags & 0x400000) linux_flags |= O_DSYNC; +#ifdef O_DSYNC + if (flags & 0x400000) host_flags |= O_DSYNC; +#endif // O_POPUP if (flags & 0x80000000) { fprintf(stderr, "Unsupported open flag=%d\n", flags); @@ -863,7 +896,7 @@ int __darwin_open(const char* path, int flags, mode_t mode) { abort(); } - return open(path, linux_flags, mode); + return open(path, host_flags, mode); } static char** add_loader_to_argv(char* argv[]) { @@ -1290,6 +1323,9 @@ int task_set_exception_ports() { } char*** _NSGetEnviron() { +#ifndef __GLIBC__ + extern char **environ; +#endif return &environ; } @@ -1299,13 +1335,25 @@ char*** _NSGetEnviron() { int __darwin_pthread_mutexattr_settype(pthread_mutexattr_t* attr, int kind) { switch (kind) { case __DARWIN_PTHREAD_MUTEX_NORMAL: +#ifdef __GLIBC__ kind = PTHREAD_MUTEX_FAST_NP; +#else + kind = PTHREAD_MUTEX_NORMAL; +#endif break; case __DARWIN_PTHREAD_MUTEX_ERRORCHECK: +#ifdef __GLIBC__ kind = PTHREAD_MUTEX_ERRORCHECK_NP; +#else + kind = PTHREAD_MUTEX_ERRORCHECK; +#endif break; case __DARWIN_PTHREAD_MUTEX_RECURSIVE: +#ifdef __GLIBC__ kind = PTHREAD_MUTEX_RECURSIVE_NP; +#else + kind = PTHREAD_MUTEX_RECURSIVE; +#endif break; default: fprintf(stderr, "Unknown pthread_mutexattr_settype kind: %d\n", kind); @@ -1406,7 +1454,11 @@ typedef struct { void* thunk; } __darwin_qsort_r_context; +#ifdef __GLIBC__ int __darwin_qsort_r_helper(const void* a, const void* b, void* data) { +#else +int __darwin_qsort_r_helper(void *data, const void* a, const void* b) { +#endif __darwin_qsort_r_context* ctx = (__darwin_qsort_r_context*)data; return ctx->compar(ctx->thunk, a, b); } @@ -1417,7 +1469,11 @@ void __darwin_qsort_r(void* base, size_t nel, size_t width, void* thunk, __darwin_qsort_r_context ctx; ctx.compar = compar; ctx.thunk = thunk; +#ifdef __GLIBC__ qsort_r(base, nel, width, &__darwin_qsort_r_helper, &ctx); +#else + qsort_r(base, nel, width, &ctx, &__darwin_qsort_r_helper); +#endif } // uuid_t is unsigned char[16] both on Linux and Mac. @@ -1518,6 +1574,10 @@ struct __darwin_pthread_mutex_t { char opaque[__DARWIN_PTHREAD_MUTEX_SIZE]; }; +#if !defined __GLIBC__ && !defined __linux__ && !defined PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_MUTEX_INITIALIZER +#endif + int __darwin_pthread_mutex_lock(struct __darwin_pthread_mutex_t *mutex) { // convert pthread_mutex_t initialized by Mac's PTHREAD_MUTEX_INITIALIZER to // that of Linux. diff --git a/libmac/runetable.c b/libmac/runetable.c index 432cae2..b21df6d 100644 --- a/libmac/runetable.c +++ b/libmac/runetable.c @@ -55,7 +55,7 @@ * SUCH DAMAGE. */ -_RuneLocale _DefaultRuneLocale = { +_MacRuneLocale _MacDefaultRuneLocale = { _RUNE_MAGIC_A, "none", _none_sgetrune, diff --git a/macho2elf.cc b/macho2elf.cc index 38991be..e0760ef 100644 --- a/macho2elf.cc +++ b/macho2elf.cc @@ -43,6 +43,10 @@ #include "mach-o.h" +#ifndef R_X86_64_JUMP_SLOT +#define R_X86_64_JUMP_SLOT 7 +#endif + using namespace std; static map g_rename; @@ -323,7 +327,7 @@ class ELFBuilder { name = found->second.c_str(); } - int sym_index = putELFSym(symtab, bind->vmaddr, 0, + uint64_t sym_index = putELFSym(symtab, bind->vmaddr, 0, ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), 0, 0, name);