this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Work on loading 32-bit apps in 64-bit Linux processes

+507 -183
+1
src/duct/src/CMakeLists.txt
··· 28 28 set(CMAKE_AR "${CMAKE_BINARY_DIR}/src/external/cctools-port/cctools/ar/x86_64-apple-darwin11-ar") 29 29 set(CMAKE_RANLIB "${CMAKE_BINARY_DIR}/src/external/cctools-port/cctools/misc/ranlib") 30 30 add_library(system_duct_static STATIC ${duct_sources}) 31 + make_fat(system_duct_static) 31 32 add_dependencies(system_duct_static ranlib x86_64-apple-darwin11-ar) 32 33 33 34 install(TARGETS system_duct DESTINATION libexec/darling/usr/lib/system)
+2 -2
src/dyld-apple/CMakeLists.txt
··· 80 80 81 81 use_ld64(system_loader) 82 82 set_target_properties(system_loader PROPERTIES OUTPUT_NAME "dyld") 83 - set_property(TARGET system_loader APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-dylinker -Wl,-dead_strip -nostdlib -Wl,-e,__dyld_start") 83 + set_property(TARGET system_loader APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-dylinker -Wl,-dead_strip -nostdlib -Wl,-e,__dyld_start -Wl,-image_base,0x1fe00000") 84 84 target_link_libraries(system_loader libc_static system_blocks_static 85 85 libc_static32 libc_static64 86 86 unwind_static system_kernel_static system_m_static cxxabi_static 87 87 keymgr_static compiler_rt_static32 compiler_rt_static64 system_duct_static 88 88 platform_static32 platform_static64 pthread_static macho_static) 89 89 90 - #make_fat(system_dyld) 90 + make_fat(system_loader) 91 91 92 92 install(TARGETS system_dyld DESTINATION libexec/darling/usr/lib/system) 93 93 install(TARGETS system_loader DESTINATION libexec/darling/usr/lib)
+1
src/dyld/CMakeLists.txt
··· 10 10 enable_language(C ASM) 11 11 12 12 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -ggdb") 13 + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Ttext-segment,0x400000 -Wl,-Tbss,0x410000 -Wl,-Tdata,0x420000") 13 14 add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" -D_GNU_SOURCE -DMLDR_BUILD) 14 15 15 16 add_executable(darling darling.c)
+8
src/dyld/commpage.h
··· 3 3 #include <stdbool.h> 4 4 #include <stdint.h> 5 5 6 + #ifdef __cplusplus 7 + extern "C" { 8 + #endif 9 + 6 10 void commpage_setup(bool _64bit); 7 11 8 12 union cpu_flags1 { ··· 141 145 }; 142 146 uint32_t reg; 143 147 }; 148 + 149 + #ifdef __cplusplus 150 + } 151 + #endif 144 152 145 153 #endif 146 154
+9 -1
src/dyld/gdb.h
··· 1 1 /* 2 2 This file is part of Darling. 3 3 4 - Copyright (C) 2016 Lubos Dolezel 4 + Copyright (C) 2017 Lubos Dolezel 5 5 6 6 Darling is free software: you can redistribute it and/or modify 7 7 it under the terms of the GNU General Public License as published by ··· 22 22 #include <mach-o/dyld_images.h> 23 23 #include <stdint.h> 24 24 25 + #ifdef __cplusplus 26 + extern "C" { 27 + #endif 28 + 25 29 void setup_gdb_notifications(uint64_t slide, uint64_t addr); 30 + 31 + #ifdef __cplusplus 32 + } 33 + #endif 26 34 27 35 #endif 28 36
+231
src/dyld/loader.c
··· 1 + 2 + // Definitions: 3 + // FUNCTION_NAME (load32/load64) 4 + // SEGMENT_STRUCT (segment_command/SEGMENT_STRUCT) 5 + // SEGMENT_COMMAND (LC_SEGMENT/SEGMENT_COMMAND) 6 + // MACH_HEADER_STRUCT (mach_header/MACH_HEADER_STRUCT) 7 + // SECTION_STRUCT (section/SECTION_STRUCT) 8 + 9 + #if defined(GEN_64BIT) 10 + # define FUNCTION_NAME load64 11 + # define SEGMENT_STRUCT segment_command_64 12 + # define SEGMENT_COMMAND LC_SEGMENT_64 13 + # define MACH_HEADER_STRUCT mach_header_64 14 + # define SECTION_STRUCT section_64 15 + # define MAP_EXTRA 0 16 + #elif defined(GEN_32BIT) 17 + # define FUNCTION_NAME load32 18 + # define SEGMENT_STRUCT segment_command 19 + # define SEGMENT_COMMAND LC_SEGMENT 20 + # define MACH_HEADER_STRUCT mach_header 21 + # define SECTION_STRUCT section 22 + # define MAP_EXTRA MAP_32BIT 23 + #else 24 + # error See above 25 + #endif 26 + 27 + void FUNCTION_NAME(int fd, uint64_t* entryPoint_out, uint64_t* mh_out) 28 + { 29 + struct MACH_HEADER_STRUCT header; 30 + uint8_t* cmds; 31 + uint64_t entryPoint = 0, entryPointDylinker = 0; 32 + struct MACH_HEADER_STRUCT* mappedHeader = NULL; 33 + uint64_t slide = 0; 34 + uint64_t mmapSize = 0; 35 + bool pie = false; 36 + uint32_t fat_offset; 37 + 38 + fat_offset = lseek(fd, 0, SEEK_CUR); 39 + 40 + if (read(fd, &header, sizeof(header)) != sizeof(header)) 41 + { 42 + fprintf(stderr, "Cannot read the mach header.\n"); 43 + exit(1); 44 + } 45 + 46 + cmds = (uint8_t*) malloc(header.sizeofcmds); 47 + if (!cmds) 48 + { 49 + fprintf(stderr, "Cannot allocate %u bytes for loader commands.\n", header.sizeofcmds); 50 + exit(1); 51 + } 52 + 53 + if (read(fd, cmds, header.sizeofcmds) != header.sizeofcmds) 54 + { 55 + fprintf(stderr, "Cannot read loader commands.\n"); 56 + exit(1); 57 + } 58 + 59 + if ((header.filetype == MH_EXECUTE && header.flags & MH_PIE) || header.filetype == MH_DYLINKER) 60 + { 61 + uint64_t base = -1; 62 + 63 + // Go through all SEGMENT_COMMAND commands to get the total continuous range required. 64 + for (uint32_t i = 0, p = 0; i < header.ncmds; i++) 65 + { 66 + struct SEGMENT_STRUCT* seg = (struct SEGMENT_STRUCT*) &cmds[p]; 67 + 68 + // Load commands are always sorted, so this will get us the maximum address. 69 + if (seg->cmd == SEGMENT_COMMAND) 70 + { 71 + if (base == -1) 72 + { 73 + base = seg->vmaddr; 74 + if (base != 0 && header.filetype == MH_DYLINKER) 75 + goto no_slide; 76 + } 77 + mmapSize = seg->vmaddr + seg->vmsize - base; 78 + } 79 + 80 + p += seg->cmdsize; 81 + } 82 + 83 + slide = (uint64_t) mmap((void*) base, mmapSize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_EXTRA, -1, 0); 84 + if (slide == (uint64_t)MAP_FAILED) 85 + { 86 + fprintf(stderr, "Cannot mmap anonymous memory range: %s", strerror(errno)); 87 + exit(1); 88 + } 89 + 90 + pie = true; 91 + } 92 + no_slide: 93 + 94 + for (uint32_t i = 0, p = 0; i < header.ncmds; i++) 95 + { 96 + struct load_command* lc; 97 + 98 + lc = (struct load_command*) &cmds[p]; 99 + 100 + switch (lc->cmd) 101 + { 102 + case SEGMENT_COMMAND: 103 + { 104 + struct SEGMENT_STRUCT* seg = (struct SEGMENT_STRUCT*) lc; 105 + void* rv; 106 + 107 + if (memcmp(SEG_PAGEZERO, seg->segname, sizeof(SEG_PAGEZERO)) == 0) 108 + { 109 + // Let's skip pagezero and map a single page at address 0 elsewhere. 110 + p += lc->cmdsize; 111 + continue; 112 + } 113 + 114 + if (seg->filesize < seg->vmsize) 115 + { 116 + if (slide != 0) 117 + { 118 + // Some segments' filesize != vmsize, thus this mprotect(). 119 + if (mprotect((void*) (seg->vmaddr + slide), seg->vmsize, native_prot(seg->maxprot)) != 0) 120 + { 121 + fprintf(stderr, "Cannot mprotect for segment %s: %s\n", seg->segname, strerror(errno)); 122 + exit(1); 123 + } 124 + } 125 + else 126 + { 127 + size_t size = seg->vmsize - seg->filesize; 128 + rv = mmap((void*) PAGE_ALIGN(seg->vmaddr + seg->vmsize - size), PAGE_ROUNDUP(size), native_prot(seg->maxprot), 129 + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 130 + } 131 + } 132 + 133 + if (seg->filesize > 0) 134 + { 135 + rv = mmap((void*) (seg->vmaddr + slide), seg->filesize, native_prot(seg->maxprot), 136 + MAP_FIXED | MAP_PRIVATE, fd, seg->fileoff + fat_offset); 137 + if (rv == (void*)MAP_FAILED) 138 + { 139 + fprintf(stderr, "Cannot mmap segment %s at %p: %s\n", seg->segname, (void*)(uintptr_t)seg->vmaddr, strerror(errno)); 140 + exit(1); 141 + } 142 + 143 + if (seg->fileoff == 0) 144 + mappedHeader = (struct MACH_HEADER_STRUCT*) (seg->vmaddr + slide); 145 + } 146 + 147 + if (strcmp(SEG_DATA, seg->segname) == 0) 148 + { 149 + // Look for section named __all_image_info for GDB integration 150 + struct SECTION_STRUCT* sect = (struct SECTION_STRUCT*) (seg+1); 151 + struct SECTION_STRUCT* end = (struct SECTION_STRUCT*) (&cmds[p + lc->cmdsize]); 152 + 153 + while (sect < end) 154 + { 155 + if (strncmp(sect->sectname, "__all_image_info", 16) == 0) 156 + { 157 + #ifdef GEN_64BIT 158 + setup_gdb_notifications(slide, sect->addr); 159 + #endif 160 + break; 161 + } 162 + sect++; 163 + } 164 + } 165 + break; 166 + } 167 + case LC_UNIXTHREAD: 168 + { 169 + #ifdef GEN_64BIT 170 + entryPoint = ((uint64_t*) lc)[18]; 171 + #endif 172 + #ifdef GEN_32BIT 173 + entryPoint = ((uint32_t*) lc)[14]; 174 + #endif 175 + entryPoint += slide; 176 + break; 177 + } 178 + case LC_LOAD_DYLINKER: 179 + { 180 + struct dylinker_command* dy = (struct dylinker_command*) lc; 181 + char path[4096]; 182 + size_t length = dy->cmdsize - dy->name.offset; 183 + 184 + if (length > sizeof(path)-1) 185 + { 186 + fprintf(stderr, "Dynamic linker name too long: %lu\n", length); 187 + exit(1); 188 + } 189 + 190 + memcpy(path, ((char*) dy) + dy->name.offset, length); 191 + path[length] = '\0'; 192 + 193 + apply_root_path(path); 194 + 195 + #ifdef GEN_64BIT 196 + load(path, &entryPointDylinker, NULL, CPU_TYPE_X86_64); 197 + #endif 198 + #ifdef GEN_32BIT 199 + load(path, &entryPointDylinker, NULL, CPU_TYPE_X86); 200 + #endif 201 + 202 + break; 203 + } 204 + case LC_MAIN: 205 + { 206 + struct entry_point_command* ee = (struct entry_point_command*) lc; 207 + if (ee->stacksize > stack_size) 208 + stack_size = ee->stacksize; 209 + break; 210 + } 211 + } 212 + 213 + p += lc->cmdsize; 214 + } 215 + 216 + free(cmds); 217 + 218 + if (entryPoint_out != NULL) 219 + *entryPoint_out = entryPointDylinker ? entryPointDylinker : entryPoint; 220 + if (mh_out != NULL) 221 + *mh_out = (uint64_t) mappedHeader; 222 + } 223 + 224 + 225 + #undef FUNCTION_NAME 226 + #undef SEGMENT_STRUCT 227 + #undef SEGMENT_COMMAND 228 + #undef MACH_HEADER_STRUCT 229 + #undef SECTION_STRUCT 230 + #undef MAP_EXTRA 231 +
+206 -168
src/dyld/mldr.c
··· 31 31 #include <mach-o/loader.h> 32 32 #include <mach-o/fat.h> 33 33 #include <dlfcn.h> 34 + #include <endian.h> 34 35 #include "elfcalls.h" 35 36 #include "threads.h" 36 37 #include "gdb.h" ··· 41 42 #endif 42 43 #define PAGE_ALIGN(x) (x & ~(PAGE_SIZE-1)) 43 44 #define PAGE_ROUNDUP(x) (((((x)-1) / PAGE_SIZE)+1) * PAGE_SIZE) 45 + 46 + #define CPU_ARCH_ABI64 0x01000000 47 + #define CPU_TYPE_ANY ((cpu_type_t) -1) 48 + #define CPU_TYPE_X86 ((cpu_type_t) 7) 49 + #define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64) 44 50 45 51 static const char* dyld_path = INSTALL_PREFIX "/libexec/usr/lib/dyld"; 46 52 ··· 51 57 // Additionally, mldr providers access to native platforms libdl.so APIs (ELF loader). 52 58 53 59 static void load64(int fd, uint64_t* entryPoint_out, uint64_t* mh_out); 54 - static void load(const char* path, uint64_t* entryPoint_out, uint64_t* mh_out); 60 + static void load32(int fd, uint64_t* entryPoint_out, uint64_t* mh_out); 61 + static void load(const char* path, uint64_t* entryPoint_out, uint64_t* mh_out, cpu_type_t cpu); 55 62 static int native_prot(int prot); 56 63 static void apply_root_path(char* path); 57 64 static char* elfcalls_make(void); 58 65 static char* apple0_make(const char* filepath); 66 + static void* setup_stack32(void* stack, int argc, const char** argv, const char** envp, const char** apple, uint64_t mh); 67 + 68 + static bool mode_32in64 = false; 69 + static uint32_t stack_size = 0; 59 70 60 71 int main(int argc, char** argv, char** envp) 61 72 { ··· 93 104 memset(p, 0, envp[0]-p); 94 105 argv[--argc] = NULL; 95 106 96 - load(filename, &entryPoint, &mh); 107 + load(filename, &entryPoint, &mh, CPU_TYPE_ANY); 97 108 98 109 #ifdef __x86_64__ 99 110 # define GETSP(ptr) __asm__ volatile("movq %%rsp, %0" : "=r"(ptr) ::) 100 111 # define JUMPX(pushCount, addr) __asm__ volatile("sub %1, %%rsp; jmpq *%0" :: "m"(addr), "r"(pushCount * sizeof(void*)) :) 112 + 113 + // Jump to a 32-bit address through segment number 0x23 (32-bit). The 64-bit segment is 0x33. 114 + // Set DS to 0x2B. 115 + # define JUMPSP(sp, addr) __asm__ volatile("movq %1, %%rsp;" \ 116 + "subq $12, %%rsp;" \ 117 + /*"movq %0, %%rax;"*/ \ 118 + "movl %0, 8(%%rsp);" \ 119 + "movl $0x23, 4(%%rsp);" \ 120 + "leaq 1f, %%rax;" \ 121 + "movl %%eax, (%%rsp);" \ 122 + "lret;" \ 123 + ".code32;\n" \ 124 + "1: push $0x2b;" \ 125 + "pop %%ds;" \ 126 + "ret;" \ 127 + :: "r"((uint32_t)addr), "r"(sp) : "rax") 101 128 #elif defined(__i386__) 102 129 # define GETSP(ptr) __asm__ volatile("movl %%esp, %0" : "=m"(ptr) ::) 103 130 # define JUMPX(pushCount, addr) __asm__ volatile("sub %1, %%esp; jmp *%0" :: "m"(addr), "r"(pushCount * sizeof(void*)) :) ··· 112 139 apple[1] = elfcalls_make(); 113 140 apple[2] = NULL; 114 141 115 - GETSP(sp); 116 - sp--; 142 + if (!mode_32in64) 143 + { 144 + GETSP(sp); 145 + sp--; 146 + 147 + for (int i = sizeof(apple)/sizeof(apple[0])-1; i >= 0; i--) 148 + *(sp-(pushCount++)) = (void*) apple[i]; 149 + 150 + *(sp-(pushCount++)) = NULL; 151 + for (int i = 0; environ[i] != NULL; i++) 152 + *(sp-(pushCount++)) = environ[i]; 153 + 154 + *(sp-(pushCount++)) = NULL; 155 + for (int i = argc-1; i >= 0; i--) 156 + *(sp-(pushCount++)) = (void*) argv[i]; 157 + 158 + *(sp-(pushCount++)) = (void*) (uintptr_t)(argc); 159 + *(sp-(pushCount++)) = (void*) mh; 160 + 161 + JUMPX(pushCount, entryPoint); 162 + } 163 + else 164 + { 165 + uint32_t size = stack_size ? stack_size : 8*1024*1024; 166 + size &= ~3u; 167 + 168 + sp = mmap(NULL, size, 169 + PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_32BIT | MAP_ANONYMOUS, 170 + -1, 0); 171 + // stack guard page 172 + mprotect(sp, PAGE_SIZE, PROT_NONE); 173 + 174 + // move to the top of the stack 175 + sp += size/sizeof(void*) - 1; 176 + 177 + JUMPSP(setup_stack32(sp, argc, (const char**) argv, (const char**) envp, apple, mh), entryPoint); 178 + } 179 + 180 + 181 + __builtin_unreachable(); 182 + } 183 + 184 + static char* copystring(void* stack, const char* str) 185 + { 186 + size_t len = strlen(str); 187 + char* pos = (char*) stack; 188 + 189 + pos -= len+1; 190 + strcpy(pos, str); 191 + 192 + return pos; 193 + } 194 + 195 + static size_t arraylen(const char** str) 196 + { 197 + size_t len = 0; 198 + while (str[len] != NULL) 199 + len++; 200 + return len; 201 + } 202 + 203 + void* setup_stack32(void* stack, int argc, const char** argv_in, const char** envp_in, const char** apple_in, uint64_t mh) 204 + { 205 + char **argv_new, **envp_new, **apple_new; 206 + size_t size, apple_size; 207 + uint32_t* stack_pointers; 208 + 209 + argv_new = (char**) __builtin_alloca((arraylen(argv_in) + 1) * sizeof(char*)); 210 + for (int i = argc-1; i >= 0; i--) 211 + stack = argv_new[i] = copystring(stack, argv_in[i]); 212 + argv_new[argc] = NULL; 213 + 214 + size = arraylen(envp_in); 215 + envp_new = (char**) __builtin_alloca((size + 1) * sizeof(char*)); 216 + for (int i = size-1; i >= 0; i--) 217 + stack = envp_new[i] = copystring(stack, envp_in[i]); 218 + envp_new[size] = NULL; 219 + 220 + apple_size = arraylen(apple_in); 221 + apple_new = (char**) __builtin_alloca((apple_size + 1) * sizeof(char*)); 222 + for (int i = apple_size-1; i >= 0; i--) 223 + stack = apple_new[i] = copystring(stack, apple_in[i]); 224 + 225 + stack_pointers = (uint32_t*) stack; 226 + stack_pointers--; 117 227 118 - for (int i = sizeof(apple)/sizeof(apple[0])-1; i >= 0; i--) 119 - *(sp-(pushCount++)) = (void*) apple[i]; 228 + *stack_pointers-- = 0; 229 + for (int i = apple_size-1; i >= 0; i--) 230 + *stack_pointers-- = (uint32_t) apple_new[i]; 120 231 121 - *(sp-(pushCount++)) = NULL; 122 - for (int i = 0; environ[i] != NULL; i++) 123 - *(sp-(pushCount++)) = environ[i]; 232 + *stack_pointers-- = 0; 233 + for (int i = 0; envp_new[i] != NULL; i++) 234 + *stack_pointers-- = (uint32_t) envp_new[i]; 124 235 125 - *(sp-(pushCount++)) = NULL; 236 + *stack_pointers-- = 0; 126 237 for (int i = argc-1; i >= 0; i--) 127 - *(sp-(pushCount++)) = (void*) argv[i]; 238 + *stack_pointers-- = (uint32_t) argv_new[i]; 128 239 129 - *(sp-(pushCount++)) = (void*) (uintptr_t)(argc); 130 - *(sp-(pushCount++)) = (void*) mh; 131 - JUMPX(pushCount, entryPoint); 240 + *stack_pointers-- = argc; 241 + *stack_pointers = (uint32_t) mh; 132 242 133 - __builtin_unreachable(); 243 + return stack_pointers; 134 244 } 135 245 136 - void load(const char* path, uint64_t* entryPoint_out, uint64_t* mh_out) 246 + void load(const char* path, uint64_t* entryPoint_out, uint64_t* mh_out, cpu_type_t cpu_desired) 137 247 { 138 248 int fd; 139 249 uint32_t magic; ··· 165 275 lseek(fd, 0, SEEK_SET); 166 276 load64(fd, entryPoint_out, mh_out); 167 277 } 168 - else if (magic == FAT_MAGIC || magic == FAT_CIGAM) 169 - { 170 - if (mh_out) 171 - commpage_setup(false); 172 - } 173 - else 174 - { 175 - fprintf(stderr, "Unknown file format: %s.\n", path); 176 - exit(1); 177 - } 178 - 179 - close(fd); 180 - } 181 - 182 - void load64(int fd, uint64_t* entryPoint_out, uint64_t* mh_out) 183 - { 184 - struct mach_header_64 header; 185 - uint8_t* cmds; 186 - uint64_t entryPoint = 0, entryPointDylinker = 0; 187 - struct mach_header_64* mappedHeader = NULL; 188 - uint64_t slide = 0; 189 - uint64_t mmapSize = 0; 190 - bool pie = false; 191 - 192 - if (read(fd, &header, sizeof(header)) != sizeof(header)) 278 + else if (magic == MH_MAGIC || magic == MH_CIGAM) 193 279 { 194 - fprintf(stderr, "Cannot read the dyld header.\n"); 195 - exit(1); 196 - } 280 + //if (mh_out) 281 + // commpage_setup(false); 197 282 198 - cmds = (uint8_t*) malloc(header.sizeofcmds); 199 - if (!cmds) 200 - { 201 - fprintf(stderr, "Cannot allocate %u bytes for loader commands.\n", header.sizeofcmds); 202 - exit(1); 203 - } 204 - 205 - if (read(fd, cmds, header.sizeofcmds) != header.sizeofcmds) 206 - { 207 - fprintf(stderr, "Cannot read loader commands.\n"); 208 - exit(1); 283 + mode_32in64 = true; 284 + lseek(fd, 0, SEEK_SET); 285 + load32(fd, entryPoint_out, mh_out); 209 286 } 210 - 211 - if ((header.filetype == MH_EXECUTE && header.flags & MH_PIE) || header.filetype == MH_DYLINKER) 287 + else if (magic == FAT_MAGIC || magic == FAT_CIGAM) 212 288 { 213 - // Go through all LC_SEGMENT_64 commands to get the total continuous range required. 214 - for (uint32_t i = 0, p = 0; i < header.ncmds; i++) 215 - { 216 - struct segment_command_64* seg = (struct segment_command_64*) &cmds[p]; 217 - 218 - // Load commands are always sorted, so this will get us the maximum address. 219 - if (seg->cmd == LC_SEGMENT_64) 220 - mmapSize = seg->vmaddr + seg->vmsize; 289 + struct fat_header fhdr; 290 + struct fat_arch best_arch; 291 + const bool swap = magic == FAT_CIGAM; 221 292 222 - p += seg->cmdsize; 223 - } 293 + best_arch.cputype = CPU_TYPE_ANY; 224 294 225 - slide = (uint64_t) mmap(NULL, mmapSize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 226 - if (slide == (uint64_t)MAP_FAILED) 295 + if (read(fd, &fhdr.nfat_arch, sizeof(fhdr.nfat_arch)) != sizeof(fhdr.nfat_arch)) 227 296 { 228 - fprintf(stderr, "Cannot mmap anonymous memory range: %s", strerror(errno)); 297 + fprintf(stderr, "Cannot read the file header of %s.\n", path); 229 298 exit(1); 230 299 } 231 300 232 - pie = true; 233 - } 301 + #define SWAP32(x) x = __bswap_32(x) 234 302 235 - for (uint32_t i = 0, p = 0; i < header.ncmds; i++) 236 - { 237 - struct load_command* lc; 303 + if (swap) 304 + SWAP32(fhdr.nfat_arch); 238 305 239 - lc = (struct load_command*) &cmds[p]; 306 + for (uint32_t i = 0; i < fhdr.nfat_arch; i++) 307 + { 308 + struct fat_arch arch; 240 309 241 - switch (lc->cmd) 242 - { 243 - case LC_SEGMENT_64: 310 + if (read(fd, &arch, sizeof(arch)) != sizeof(arch)) 244 311 { 245 - struct segment_command_64* seg = (struct segment_command_64*) lc; 246 - void* rv; 312 + fprintf(stderr, "Cannot read fat_arch header of %s.\n", path); 313 + exit(1); 314 + } 247 315 248 - if (memcmp(SEG_PAGEZERO, seg->segname, sizeof(SEG_PAGEZERO)) == 0) 249 - { 250 - // Let's skip pagezero and map a single page at address 0 elsewhere. 251 - p += lc->cmdsize; 252 - continue; 253 - } 316 + if (swap) 317 + { 318 + SWAP32(arch.cputype); 319 + SWAP32(arch.cpusubtype); 320 + SWAP32(arch.offset); 321 + SWAP32(arch.size); 322 + SWAP32(arch.align); 323 + } 254 324 255 - if (seg->filesize < seg->vmsize) 325 + if (cpu_desired == CPU_TYPE_ANY) 326 + { 327 + // Find the best arch 328 + #ifdef __x86_64__ 329 + // Hope for x86-64, but also accept i386 330 + // TODO: x86_64h (Haswell) 331 + if (arch.cputype == CPU_TYPE_X86_64) 256 332 { 257 - if (slide != 0) 258 - { 259 - // Some segments' filesize != vmsize, thus this mprotect(). 260 - if (mprotect((void*) (seg->vmaddr + slide), seg->vmsize, native_prot(seg->maxprot)) != 0) 261 - { 262 - fprintf(stderr, "Cannot mprotect for segment %s: %s\n", seg->segname, strerror(errno)); 263 - exit(1); 264 - } 265 - } 266 - else 267 - { 268 - size_t size = seg->vmsize - seg->filesize; 269 - rv = mmap((void*) PAGE_ALIGN(seg->vmaddr + seg->vmsize - size), PAGE_ROUNDUP(size), native_prot(seg->maxprot), 270 - MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 271 - } 333 + memcpy(&best_arch, &arch, sizeof(arch)); 334 + break; 272 335 } 273 - 274 - if (seg->filesize > 0) 275 - { 276 - rv = mmap((void*) (seg->vmaddr + slide), seg->filesize, native_prot(seg->maxprot), 277 - MAP_FIXED | MAP_PRIVATE, fd, seg->fileoff); 278 - if (rv == (void*)MAP_FAILED) 279 - { 280 - fprintf(stderr, "Cannot mmap segment %s at %p: %s\n", seg->segname, (void*)seg->vmaddr, strerror(errno)); 281 - exit(1); 282 - } 283 - 284 - if (seg->fileoff == 0) 285 - mappedHeader = (struct mach_header_64*) (seg->vmaddr + slide); 286 - } 287 - 288 - if (strcmp(SEG_DATA, seg->segname) == 0) 289 - { 290 - // Look for section named __all_image_info for GDB integration 291 - struct section_64* sect = (struct section_64*) (seg+1); 292 - struct section_64* end = (struct section_64*) (&cmds[p + lc->cmdsize]); 293 - 294 - while (sect < end) 295 - { 296 - if (strncmp(sect->sectname, "__all_image_info", 16) == 0) 297 - { 298 - setup_gdb_notifications(slide, sect->addr); 299 - break; 300 - } 301 - sect++; 302 - } 303 - } 304 - break; 336 + else if (arch.cputype == CPU_TYPE_X86) 337 + memcpy(&best_arch, &arch, sizeof(arch)); 338 + #endif 305 339 } 306 - case LC_UNIXTHREAD: 340 + else if (arch.cputype == cpu_desired) 307 341 { 308 - entryPoint = ((uint64_t*) lc)[18]; 309 - entryPoint += slide; 342 + memcpy(&best_arch, &arch, sizeof(arch)); 310 343 break; 311 344 } 312 - case LC_LOAD_DYLINKER: 313 - { 314 - struct dylinker_command* dy = (struct dylinker_command*) lc; 315 - char path[4096]; 316 - size_t length = dy->cmdsize - dy->name.offset; 345 + } 317 346 318 - if (length > sizeof(path)-1) 319 - { 320 - fprintf(stderr, "Dynamic linker name too long: %lu\n", length); 321 - exit(1); 322 - } 323 - 324 - memcpy(path, ((char*) dy) + dy->name.offset, length); 325 - path[length] = '\0'; 326 - 327 - apply_root_path(path); 347 + if (best_arch.cputype == CPU_TYPE_ANY) 348 + { 349 + fprintf(stderr, "No supported architecture found in fat %s.\n", path); 350 + exit(1); 351 + } 352 + if (lseek(fd, best_arch.offset, SEEK_SET) == -1) 353 + { 354 + fprintf(stderr, "Cannot seek to selected arch in fat %s.\n", path); 355 + exit(1); 356 + } 328 357 329 - load(path, &entryPointDylinker, NULL); 358 + 359 + if (mh_out) 360 + commpage_setup(best_arch.cputype & CPU_ARCH_ABI64); 330 361 331 - break; 332 - } 362 + if (best_arch.cputype & CPU_ARCH_ABI64) 363 + load64(fd, entryPoint_out, mh_out); 364 + else 365 + { 366 + mode_32in64 = true; 367 + load32(fd, entryPoint_out, mh_out); 333 368 } 334 - 335 - p += lc->cmdsize; 369 + } 370 + else 371 + { 372 + fprintf(stderr, "Unknown file format: %s.\n", path); 373 + exit(1); 336 374 } 337 375 338 - free(cmds); 339 - 340 - if (entryPoint_out != NULL) 341 - *entryPoint_out = entryPointDylinker ? entryPointDylinker : entryPoint; 342 - if (mh_out != NULL) 343 - *mh_out = (uint64_t) mappedHeader; 376 + close(fd); 344 377 } 378 + 379 + #define GEN_64BIT 380 + #include "loader.c" 381 + #undef GEN_64BIT 382 + 383 + #define GEN_32BIT 384 + #include "loader.c" 385 + #undef GEN_32BIT 345 386 346 387 int native_prot(int prot) 347 388 { ··· 421 462 422 463 char* apple0_make(const char* filepath) 423 464 { 424 - const char prefix[] = "executable_path="; 425 - char* apple0; 465 + static char apple0[4096] = "executable_path="; 426 466 427 - apple0 = (char*) malloc(strlen(filepath) + sizeof(prefix)); 428 - strcpy(apple0, prefix); 429 467 strcat(apple0, filepath); 430 468 431 469 return apple0;
+27
src/kernel/emulation/linux/linux-syscall.S
··· 13 13 14 14 #elif defined(__i386__) 15 15 16 + // With 32in64, we cannot use sysenter, because our process doesn't have a 32-bit VDSO mapped 17 + // and sysenter needs that for returning to user space. 18 + 19 + // eax, ecx and edx are caller saved, the rest is calee saved 20 + push %ebx 21 + push %esi 22 + push %edi 23 + push %ebp 24 + 25 + mov 20(%esp), %ebx 26 + mov 24(%esp), %ecx 27 + mov 28(%esp), %edx 28 + mov 32(%esp), %esi 29 + mov 36(%esp), %edi 30 + mov 40(%esp), %ebp 31 + mov 44(%esp), %eax 32 + 33 + int $0x80 34 + 35 + pop %ebp 36 + pop %edi 37 + pop %esi 38 + pop %ebx 39 + ret 40 + 41 + #elif 0 //defined(__i386__) 42 + 16 43 push %ebp 17 44 push %ebx 18 45 push %esi
+4 -4
src/kernel/emulation/linux/machdep/machdep-table.S
··· 30 30 movl %ecx, -24+off(%esp) 31 31 32 32 __darling_machdep_syscall: 33 - calll .L0$pb 34 - .L0$pb: 33 + calll 1f 34 + 1: 35 35 popl %ecx 36 - .Ltmp0: 37 - movl L___machdep_syscall_table$non_lazy_ptr-.L0$pb(%ecx), %ecx 36 + 2: 37 + movl L___machdep_syscall_table$non_lazy_ptr-1b(%ecx), %ecx 38 38 andl $0xffff, %eax // Because there is some extra stuff in upper bytes we don't need 39 39 movl (%ecx,%eax,4), %eax 40 40 test %eax, %eax
+1 -1
src/kernel/emulation/linux/machdep/tls.c
··· 37 37 LINUX_SYSCALL(__NR_set_thread_area, &desc); 38 38 39 39 entry_number = desc.entry_number; 40 - __asm__ ("movl %0, %%fs" :: "r" (desc.entry_number*8 + 3)); 40 + __asm__ ("movl %0, %%gs" :: "r" (desc.entry_number*8 + 3)); 41 41 #endif 42 42 } 43 43
+1
src/kernel/emulation/linux/mman/duct_mman.h
··· 44 44 #define LINUX_MAP_NONBLOCK 0x10000 45 45 #define LINUX_MAP_STACK 0x20000 46 46 #define LINUX_MAP_HUGETLB 0x40000 47 + #define LINUX_MAP_32BIT 0x40 47 48 #define LINUX_MCL_CURRENT 1 48 49 #define LINUX_MCL_FUTURE 2 49 50
+3
src/kernel/emulation/linux/mman/mman.c
··· 40 40 // linux_flags |= LINUX_MAP_STACK; 41 41 42 42 #ifdef __NR_mmap2 43 + #ifdef __i386__ 44 + linux_flags |= LINUX_MAP_32BIT; 45 + #endif 43 46 ret = (void*) LINUX_SYSCALL6(__NR_mmap2, start, len, linux_prot, linux_flags, fd, pos / 4096); 44 47 #else 45 48 ret = (void*) LINUX_SYSCALL6(__NR_mmap, start, len, linux_prot, linux_flags, fd, pos);
+4 -4
src/kernel/emulation/linux/syscalls-table.S
··· 29 29 movl %ecx, -24+off(%esp) 30 30 31 31 __darling_bsd_syscall: 32 - calll .L0$pb 33 - .L0$pb: 32 + calll 1f 33 + 1: 34 34 popl %ecx 35 - .Ltmp0: 36 - movl L___bsd_syscall_table$non_lazy_ptr-.L0$pb(%ecx), %ecx 35 + 2: 36 + movl L___bsd_syscall_table$non_lazy_ptr-1b(%ecx), %ecx 37 37 andl $0xffff, %eax // Because there is some extra stuff in upper bytes we don't need 38 38 movl (%ecx,%eax,4), %eax 39 39 test %eax, %eax
+1 -1
src/kernel/libsyscall/bsdsyscalls/___syscall.S
··· 37 37 pushl %ecx 38 38 UNIX_SYSCALL_TRAP 39 39 movl (%esp),%edx // add one element to stack so 40 - pushl %ecx // caller "pop" will work 40 + pushl %edx // caller "pop" will work 41 41 jnb 2f 42 42 BRANCH_EXTERN(tramp_cerror) 43 43 2:
+2 -2
src/kernel/libsyscall/os/tsd.h
··· 66 66 { 67 67 void *ret; 68 68 #if defined(__i386__) 69 - __asm__("mov %%fs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *)))); 69 + __asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *)))); 70 70 #else 71 71 __asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void **)(slot * sizeof(void *)))); 72 72 #endif ··· 78 78 _os_tsd_set_direct(unsigned long slot, void *val) 79 79 { 80 80 #if defined(__i386__) && defined(__PIC__) 81 - __asm__("movl %1, %%fs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val)); 81 + __asm__("movl %1, %%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "rn" (val)); 82 82 #elif defined(__i386__) && !defined(__PIC__) 83 83 __asm__("movl %1, %%gs:%0" : "=m" (*(void **)(slot * sizeof(void *))) : "ri" (val)); 84 84 #else
+1
src/keymgr/CMakeLists.txt
··· 35 35 set(CMAKE_AR "${CMAKE_BINARY_DIR}/src/external/cctools-port/cctools/ar/x86_64-apple-darwin11-ar") 36 36 set(CMAKE_RANLIB "${CMAKE_BINARY_DIR}/src/external/cctools-port/cctools/misc/ranlib") 37 37 add_library(keymgr_static STATIC ${keymgr_sources}) 38 + make_fat(keymgr_static) 38 39 add_dependencies(keymgr_static ranlib x86_64-apple-darwin11-ar) 39 40 40 41 install(TARGETS keymgr DESTINATION libexec/darling/usr/lib/system)
+5
src/libc/CMakeLists.txt
··· 121 121 libc-net 122 122 libc-net_cancelable 123 123 libc-locale 124 + libc-gen_dyld 125 + libc-stdlib_dyld 126 + libc-string_dyld 127 + libc-sys_dyld 128 + libc-gdtoa_dyld 124 129 ) 125 130 # APPEND_STRING PROPERTY COMPILE_FLAGS 126 131 # " -arch x86_64 -arch i386"