Created
July 30, 2023 17:51
-
-
Save chrstphrchvz/1877aae844c52d977c5cf73716fbf955 to your computer and use it in GitHub Desktop.
XEqualRegion() for Tk Aqua using __HIShapeEqual() using FindSymbol() hack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FindSymbol() approach stolen from https://stackoverflow.com/a/21855885/4896937 | |
// Adapted from: | |
// https://github.com/0xced/iOS-Artwork-Extractor/blob/master/Classes/FindSymbol.c | |
// Adapted from MoreAddrToSym / GetFunctionName() | |
// http://www.opensource.apple.com/source/openmpi/openmpi-8/openmpi/opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreAddrToSym.c | |
#include <mach-o/dyld.h> | |
#include <mach-o/nlist.h> | |
static void *FindSymbol(const struct mach_header *img, const char *symbol) | |
{ | |
if ((img == NULL) || (symbol == NULL)) | |
return NULL; | |
// only 64bit supported | |
#if defined (__LP64__) | |
if(img->magic != MH_MAGIC_64) | |
// we currently only support Intel 64bit | |
return NULL; | |
struct mach_header_64 *image = (struct mach_header_64*) img; | |
struct segment_command_64 *seg_linkedit = NULL; | |
struct segment_command_64 *seg_text = NULL; | |
struct symtab_command *symtab = NULL; | |
unsigned int index; | |
struct load_command *cmd = (struct load_command*)(image + 1); | |
for (index = 0; index < image->ncmds; index += 1, cmd = (struct load_command*)((char*)cmd + cmd->cmdsize)) | |
{ | |
switch(cmd->cmd) | |
{ | |
case LC_SEGMENT_64: { | |
struct segment_command_64* segcmd = (struct segment_command_64*)cmd; | |
if (!strcmp(segcmd->segname, SEG_TEXT)) | |
seg_text = segcmd; | |
else if (!strcmp(segcmd->segname, SEG_LINKEDIT)) | |
seg_linkedit = segcmd; | |
break; | |
} | |
case LC_SYMTAB: | |
symtab = (struct symtab_command*)cmd; | |
break; | |
default: | |
break; | |
} | |
} | |
if ((seg_text == NULL) || (seg_linkedit == NULL) || (symtab == NULL)) | |
return NULL; | |
unsigned long vm_slide = (unsigned long)image - (unsigned long)seg_text->vmaddr; | |
unsigned long file_slide = ((unsigned long)seg_linkedit->vmaddr - (unsigned long)seg_text->vmaddr) - seg_linkedit->fileoff; | |
struct nlist_64 *symbase = (struct nlist_64*)((unsigned long)image + (symtab->symoff + file_slide)); | |
char *strings = (char*)((unsigned long)image + (symtab->stroff + file_slide)); | |
struct nlist_64 *sym; | |
for (index = 0, sym = symbase; index < symtab->nsyms; index += 1, sym += 1) | |
{ | |
if (sym->n_un.n_strx != 0 && !strcmp(symbol, strings + sym->n_un.n_strx)) | |
{ | |
unsigned long address = vm_slide + sym->n_value; | |
if (sym->n_desc & N_ARM_THUMB_DEF) | |
return (void*)(address | 1); | |
else | |
return (void*)(address); | |
} | |
} | |
#endif | |
return NULL; | |
} | |
typedef Boolean (*HIShapeEqualFunc)(void const *inShape1, void const *inShape2); | |
Bool | |
XEqualRegion( | |
void *srca, | |
void *srcb) | |
{ | |
static HIShapeEqualFunc HIShapeEqual = NULL; | |
if (HIShapeEqual == NULL) { | |
const struct mach_header* img = NSAddImage( | |
"/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices", | |
NSADDIMAGE_OPTION_NONE); | |
const char *mangled_name ="__ZL14__HIShapeEqualPKvS0_"; // Boolean __attribute__((overloadable)) __HIShapeEqual(void const*, void const*) | |
HIShapeEqual = (HIShapeEqualFunc) FindSymbol(img, mangled_name); | |
} | |
return HIShapeEqual(srca, srcb); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment