From 67847892c023174a0f4771a473196e85945b73c7 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 30 Jul 2019 16:02:49 +0200 Subject: Remove android and OSX files --- OSX/enable_gc.c | 368 -------------------------------------------------------- 1 file changed, 368 deletions(-) delete mode 100644 OSX/enable_gc.c (limited to 'OSX/enable_gc.c') diff --git a/OSX/enable_gc.c b/OSX/enable_gc.c deleted file mode 100644 index 699c9a6..0000000 --- a/OSX/enable_gc.c +++ /dev/null @@ -1,368 +0,0 @@ -/* enable_gc.c, Copyright (c) 2014 Dave Odell - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * The problem: - * - * - OSX 10.5 and earlier require .saver bundles to not use GC. - * - OSX 10.6 and 10.7 require .saver bundles to use GC. - * - OSX 10.8 and later require .saver bundles to not use GC. - * - * So the way to build a portable .saver is to build it with "GC optional", - * via "-fobjc-gc" on the x86-64 architecture. - * - * But XCode 5.0.2 was the last version of XCode to support building - * executables that support GC, even optionally. So there's no way to make - * the XCode that ships with OSX 10.9 create a .saver bundle that will work - * on OSX 10.6 and 10.7. Though it will work on 10.5! - * - * The fix: after compiling, hand-hack the generated binary to tag the - * x86-64 arch with the OBJC_IMAGE_SUPPORTS_GC flag. - * - * Specifically, OR the __DATA,__objc_imageinfo section with - * "00 00 00 00 02 00 00 00"; normally this section is all zeros. - * The __objc_imageinfo section corresponds to struct objc_image_info in: - * http://www.opensource.apple.com/source/objc4/objc4-551.1/runtime/objc-private.h - * You can use "otool -o Interference.saver/Contents/MacOS/Interference" - * or "otool -s __DATA __objc_imageinfo Interference" to look at the - * section. - * - * This means that the binary is marked as supporting GC, but there - * are no actual GC-supporting write barriers compiled in! So does it - * actually ever GC? Yes, apparently it does. Apparently what's - * going on is that incremental-GCs are doing nothing, but full-GCs - * still collect ObjC objects properly. - * - * Mad Science! - * - * In the xscreensaver build process, the "enable_gc" target is a - * dependency of "libjwxyz" (so that it gets built first) and is - * invoked by "update-info-plist.pl" (so that it gets run on every - * saver). - * - * - * UPDATE, 2-Jun-2014: - * - * Actually, this seems not to be working. We're seeing intermittent - * crashes in malloc/calloc/free on 10.6 64 bit. When compiled with - * legit -fobjc-gc, those crashes don't occur. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BOUNDS_CHECK(ptr, end) \ - ((const void *)((ptr) + 1) <= (const void *)(end)) - -#define BOUNDS_CHECK_PRINT(ptr, end) \ - (BOUNDS_CHECK(ptr, end) ? 1 : (_got_eof(), 0)) - -/* - This part is lifted from objc-private.h, because it's not present on - most OS X systems. - http://www.opensource.apple.com/source/objc4/objc4-551.1/runtime/objc-private.h - */ - -typedef struct { - uint32_t version; // currently 0 - uint32_t flags; -} objc_image_info; - -// masks for objc_image_info.flags -#define OBJC_IMAGE_IS_REPLACEMENT (1<<0) -#define OBJC_IMAGE_SUPPORTS_GC (1<<1) -#define OBJC_IMAGE_REQUIRES_GC (1<<2) -#define OBJC_IMAGE_OPTIMIZED_BY_DYLD (1<<3) -#define OBJC_IMAGE_SUPPORTS_COMPACTION (1<<4) // might be re-assignable - -/* End objc-private.h excerpt. */ - -static void -_got_eof() -{ - fputs("Error: Unexpected EOF\n", stderr); -} - -/* This will probably only ever run on OS X, so CoreFoundation is used here. */ - -static inline uint32_t -_be_u32(uint32_t x) /* Big Endian _ Unsigned int 32-bit */ -{ - return (uint32_t)CFSwapInt32BigToHost(x); -} - -static inline uint32_t -_le_u32(uint32_t x) /* Little Endian _ Unsigned int 32-bit */ -{ - return (uint32_t)CFSwapInt32LittleToHost(x); -} - -static inline uint32_t -_le_u64(uint64_t x) /* Little Endian _ Unsigned int 64-bit */ -{ - return (uint32_t)CFSwapInt64LittleToHost(x); -} - -static int -_handle_x86_64(void *exec, void *exec_end) -{ - const uint32_t *magic = exec; - - if(!BOUNDS_CHECK_PRINT(magic, exec_end)) - return EXIT_FAILURE; - - if(*magic != _le_u32(MH_MAGIC_64)) - { - fputs("Error: Unknown magic number on Mach header.\n", stderr); - return EXIT_FAILURE; - } - - /* Mach headers can be little-endian or big-endian. */ - - const struct mach_header_64 *hdr = (const struct mach_header_64 *)magic; - if(!BOUNDS_CHECK_PRINT(hdr, exec_end)) - return EXIT_FAILURE; - - if(hdr->cputype != _le_u32(CPU_TYPE_X86_64)) - { - fputs("Error: Unexpected CPU type on Mach header.\n", stderr); - return EXIT_FAILURE; - } - - /* I may have missed a few _le_u32 calls, so watch out on PowerPC (heh). */ - - if((const uint8_t *)hdr + _le_u32(hdr->sizeofcmds) > - (const uint8_t *)exec_end) - { - _got_eof(); - return EXIT_FAILURE; - } - - const struct load_command *load_cmd = (const struct load_command *)(hdr + 1); - const void *cmds_end = (const uint8_t *)load_cmd + hdr->sizeofcmds; - - for(unsigned i = 0; i != _le_u32(hdr->ncmds); ++i) - { - if(!BOUNDS_CHECK_PRINT(load_cmd, cmds_end)) - return EXIT_FAILURE; - - const struct load_command *next_load_cmd = - (const struct load_command *)((const uint8_t *)load_cmd + - _le_u32(load_cmd->cmdsize)); - - if(load_cmd->cmd == _le_u32(LC_SEGMENT_64)) - { - const struct segment_command_64 *seg_cmd = - (const struct segment_command_64 *)load_cmd; - if(!BOUNDS_CHECK_PRINT(seg_cmd, cmds_end)) - return EXIT_FAILURE; - - if(!strcmp(seg_cmd->segname, "__DATA")) - { - const struct section_64 *sect = - (const struct section_64 *)(seg_cmd + 1); - for(unsigned j = 0; j != _le_u32(seg_cmd->nsects); ++j) - { - if(!BOUNDS_CHECK_PRINT(§[j], next_load_cmd)) - return EXIT_FAILURE; - - if(strcmp(sect[j].segname, "__DATA")) - fprintf(stderr, - "Warning: segment name mismatch in __DATA,%.16s\n", - sect[j].sectname); - - if(!memcmp(sect[j].sectname, "__objc_imageinfo", 16)) - { /* No null-terminator here. */ - if(_le_u64(sect[j].size) < sizeof(objc_image_info)) - { - fputs("__DATA,__objc_imageinfo too small.\n", - stderr); - return EXIT_FAILURE; - } - - /* - Not checked: - - Overlapping segments. - - Segments overlapping the load commands. - */ - - objc_image_info *img_info = (objc_image_info *) - ((uint8_t *)exec + _le_u64(sect[j].offset)); - - if(!BOUNDS_CHECK_PRINT(img_info, exec_end)) - return EXIT_FAILURE; - - if(img_info->version != 0) - { - fprintf( - stderr, - "Error: Unexpected version for " - "__DATA,__objc_imageinfo section. " - "Expected 0, got %d\n", - _le_u32(img_info->version)); - return EXIT_FAILURE; - } - - if(img_info->flags & - _le_u32(OBJC_IMAGE_REQUIRES_GC | - OBJC_IMAGE_SUPPORTS_GC)) - { - fputs("Warning: Image already supports GC.\n", - stderr); - return EXIT_SUCCESS; - } - - /* Finally, do the work. */ - img_info->flags |= _le_u32(OBJC_IMAGE_SUPPORTS_GC); - return EXIT_SUCCESS; - } - } - } - } - - load_cmd = next_load_cmd; - } - - if((const void *)load_cmd > cmds_end) - { - _got_eof(); - return EXIT_FAILURE; - } - - assert(load_cmd == cmds_end); - - fputs("Error: __DATA,__objc_imageinfo not found.\n", stderr); - return EXIT_FAILURE; -} - -int -main(int argc, const char **argv) -{ - if(argc != 2) - { - fprintf(stderr, "Usage: %s executable\n", argv[0]); - return EXIT_FAILURE; - } - - const char *exec_path = argv[1]; - - int fd = open(exec_path, O_RDWR | O_EXLOCK); - - if(fd < 0) - { - perror(exec_path); - return EXIT_FAILURE; - } - - int result = EXIT_FAILURE; - - struct stat exec_stat; - if(fstat(fd, &exec_stat) < 0) - { - perror("fstat"); - exit (1); - } - else - { - if(!(exec_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - { - fprintf(stderr, "Warning: %s is not executable.\n", exec_path); - exit (1); - } - - assert(exec_stat.st_size >= 0); - - /* - TODO (technically): mmap(2) can throw signals if somebody unplugs - the file system. In such situations, a signal handler - should be used to ensure sensible recovery. - */ - - void *exec = NULL; - - if(exec_stat.st_size) - { - exec = mmap(NULL, exec_stat.st_size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if(!exec) - perror("mmap"); - } - - if(exec || !exec_stat.st_size) - { - const void *exec_end = (const char *)exec + exec_stat.st_size; - - const uint32_t *magic = exec; - - if(BOUNDS_CHECK_PRINT(magic, exec_end)) - { - if(*magic == _be_u32(FAT_MAGIC)) - { - struct fat_header *hdr = (struct fat_header *)magic; - if(BOUNDS_CHECK_PRINT(hdr, exec_end)) - { - uint32_t nfat_arch = _be_u32(hdr->nfat_arch); - const struct fat_arch *arch = - (const struct fat_arch *)(hdr + 1); - - unsigned i = 0; - for(;;) - { - if(i == nfat_arch) - { - /* This could be done for other architectures. */ - fputs("Error: x86_64 architecture not found.\n", - stderr); - exit (1); - break; - } - - if(!BOUNDS_CHECK_PRINT(&arch[i], exec_end)) - break; - - if(arch[i].cputype == _be_u32(CPU_TYPE_X86_64)) - { - uint8_t *obj_begin = - (uint8_t *)exec + _be_u32(arch[i].offset); - result = _handle_x86_64(obj_begin, - obj_begin + - _be_u32(arch[i].size)); - break; - } - - ++i; - } - } - } - else - { - fprintf(stderr, - "Error: %s is not a recognized Mach binary format.\n", - exec_path); - exit (1); - } - } - - munmap(exec, exec_stat.st_size); - } - } - - close(fd); - - return result; -} -- cgit v1.2.3-55-g7522